]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Auto-complete for `show bgp <afi> <safi> community-list`
[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"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
718e3744 105/* Extern from bgp_dump.c */
dde72586
SH
106extern const char *bgp_origin_str[];
107extern const char *bgp_origin_long_str[];
3742de8d 108
b7d08f5a 109/* PMSI strings. */
110#define PMSI_TNLTYPE_STR_NO_INFO "No info"
111#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
112static const struct message bgp_pmsi_tnltype_str[] = {
113 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
114 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
115 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
116 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
117 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
118 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
119 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
120 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 121 {0}
122};
b7d08f5a 123
9df8b37c 124#define VRFID_NONE_STR "-"
46aeabed 125#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 126
4a11bf2c 127DEFINE_HOOK(bgp_process,
9bcb3eef
DS
128 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
129 struct peer *peer, bool withdraw),
8451921b 130 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 131
4056a5f6
RZ
132/** Test if path is suppressed. */
133static bool bgp_path_suppressed(struct bgp_path_info *pi)
134{
135 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
136 return false;
137
138 return listcount(pi->extra->aggr_suppressors) > 0;
139}
4a11bf2c 140
9bcb3eef 141struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 142 safi_t safi, const struct prefix *p,
d62a17ae 143 struct prefix_rd *prd)
144{
9bcb3eef
DS
145 struct bgp_dest *dest;
146 struct bgp_dest *pdest = NULL;
d62a17ae 147
148 assert(table);
d62a17ae 149
150 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
151 || (safi == SAFI_EVPN)) {
9bcb3eef 152 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 153
9bcb3eef
DS
154 if (!bgp_dest_has_bgp_path_info_data(pdest))
155 bgp_dest_set_bgp_table_info(
156 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 157 else
9bcb3eef
DS
158 bgp_dest_unlock_node(pdest);
159 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 160 }
718e3744 161
9bcb3eef 162 dest = bgp_node_get(table, p);
718e3744 163
d62a17ae 164 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
165 || (safi == SAFI_EVPN))
9bcb3eef 166 dest->pdest = pdest;
718e3744 167
9bcb3eef 168 return dest;
718e3744 169}
6b0655a2 170
9bcb3eef 171struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 172 safi_t safi, const struct prefix *p,
d62a17ae 173 struct prefix_rd *prd)
128ea8ab 174{
9bcb3eef
DS
175 struct bgp_dest *dest;
176 struct bgp_dest *pdest = NULL;
128ea8ab 177
d62a17ae 178 if (!table)
179 return NULL;
128ea8ab 180
d62a17ae 181 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
182 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
183 pdest = bgp_node_lookup(table, (struct prefix *)prd);
184 if (!pdest)
d62a17ae 185 return NULL;
128ea8ab 186
9bcb3eef
DS
187 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
188 bgp_dest_unlock_node(pdest);
d62a17ae 189 return NULL;
190 }
128ea8ab 191
9bcb3eef 192 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 193 }
128ea8ab 194
9bcb3eef 195 dest = bgp_node_lookup(table, p);
128ea8ab 196
9bcb3eef 197 return dest;
128ea8ab 198}
199
18ee8310
DS
200/* Allocate bgp_path_info_extra */
201static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 202{
4b7e6066
DS
203 struct bgp_path_info_extra *new;
204 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
205 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
206 new->label[0] = MPLS_INVALID_LABEL;
207 new->num_labels = 0;
3e3708cb
PG
208 new->bgp_fs_pbr = NULL;
209 new->bgp_fs_iprule = NULL;
d62a17ae 210 return new;
fb982c25
PJ
211}
212
a2e219fe 213void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 214{
4b7e6066 215 struct bgp_path_info_extra *e;
d62a17ae 216
c93a3b77
DS
217 if (!extra || !*extra)
218 return;
d62a17ae 219
c93a3b77 220 e = *extra;
4538f895 221 if (e->damp_info)
b4f7f45b
IR
222 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
223 e->damp_info->safi);
4538f895 224
c93a3b77
DS
225 e->damp_info = NULL;
226 if (e->parent) {
40381db7 227 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 228
40381db7 229 if (bpi->net) {
0e70e6c8
DL
230 /* FIXME: since multiple e may have the same e->parent
231 * and e->parent->net is holding a refcount for each
232 * of them, we need to do some fudging here.
233 *
40381db7
DS
234 * WARNING: if bpi->net->lock drops to 0, bpi may be
235 * freed as well (because bpi->net was holding the
236 * last reference to bpi) => write after free!
0e70e6c8
DL
237 */
238 unsigned refcount;
239
40381db7 240 bpi = bgp_path_info_lock(bpi);
c10e14e9 241 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 242 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 243 if (!refcount)
40381db7
DS
244 bpi->net = NULL;
245 bgp_path_info_unlock(bpi);
0e70e6c8 246 }
18ee8310 247 bgp_path_info_unlock(e->parent);
c93a3b77 248 e->parent = NULL;
d62a17ae 249 }
c93a3b77
DS
250
251 if (e->bgp_orig)
252 bgp_unlock(e->bgp_orig);
c26edcda 253
ff3bf9a4
DS
254 if (e->aggr_suppressors)
255 list_delete(&e->aggr_suppressors);
256
60605cbc
AK
257 if (e->mh_info)
258 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 259
ce3c0614
PG
260 if ((*extra)->bgp_fs_iprule)
261 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 262 if ((*extra)->bgp_fs_pbr)
6a154c88 263 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 264 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
265}
266
18ee8310
DS
267/* Get bgp_path_info extra information for the given bgp_path_info, lazy
268 * allocated if required.
fb982c25 269 */
40381db7 270struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 271{
40381db7
DS
272 if (!pi->extra)
273 pi->extra = bgp_path_info_extra_new();
274 return pi->extra;
fb982c25
PJ
275}
276
718e3744 277/* Free bgp route information. */
9b6d8fcf 278static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 279{
05864da7 280 bgp_attr_unintern(&path->attr);
fb018d25 281
9b6d8fcf
DS
282 bgp_unlink_nexthop(path);
283 bgp_path_info_extra_free(&path->extra);
284 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
285 if (path->net)
286 bgp_addpath_free_info_data(&path->tx_addpath,
287 &path->net->tx_addpath);
718e3744 288
9b6d8fcf 289 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 290
9b6d8fcf 291 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 292}
293
9b6d8fcf 294struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 295{
9b6d8fcf
DS
296 path->lock++;
297 return path;
200df115 298}
299
9b6d8fcf 300struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 301{
9b6d8fcf
DS
302 assert(path && path->lock > 0);
303 path->lock--;
d62a17ae 304
9b6d8fcf 305 if (path->lock == 0) {
200df115 306#if 0
307 zlog_debug ("%s: unlocked and freeing", __func__);
308 zlog_backtrace (LOG_DEBUG);
309#endif
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
314#if 0
9b6d8fcf 315 if (path->lock == 1)
200df115 316 {
317 zlog_debug ("%s: unlocked to 1", __func__);
318 zlog_backtrace (LOG_DEBUG);
319 }
320#endif
d62a17ae 321
9b6d8fcf 322 return path;
200df115 323}
324
f009ff26 325/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 326static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 327{
328 struct peer *peer;
329 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 330 bool set_flag = false;
f009ff26 331 struct bgp *bgp = NULL;
332 struct bgp_table *table = NULL;
333 afi_t afi = 0;
334 safi_t safi = 0;
f009ff26 335
336 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
337 * then the route selection is deferred
338 */
9bcb3eef 339 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 340 return 0;
341
9bcb3eef 342 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 343 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 344 zlog_debug(
56ca3b5b
DL
345 "Route %pBD is in workqueue and being processed, not deferred.",
346 dest);
b54892e0 347
5f9c1aa2 348 return 0;
349 }
350
9bcb3eef 351 table = bgp_dest_table(dest);
f009ff26 352 if (table) {
353 bgp = table->bgp;
354 afi = table->afi;
355 safi = table->safi;
356 }
357
9bcb3eef 358 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 359 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
360 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
361 continue;
362
363 /* Route selection is deferred if there is a stale path which
364 * which indicates peer is in restart mode
365 */
36235319
QY
366 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
367 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 368 set_flag = true;
f009ff26 369 } else {
370 /* If the peer is graceful restart capable and peer is
371 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
372 */
373 peer = old_pi->peer;
36235319
QY
374 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
375 && BGP_PEER_RESTARTING_MODE(peer)
376 && (old_pi
377 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 378 set_flag = true;
f009ff26 379 }
380 }
381 if (set_flag)
382 break;
383 }
384
385 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
386 * is active
387 */
2ba1fe69 388 if (set_flag && table) {
f009ff26 389 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
390 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
391 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 392 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 393 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
394 zlog_debug("DEFER route %pBD, dest %p", dest,
395 dest);
f009ff26 396 return 0;
397 }
398 }
399 return -1;
400}
401
9bcb3eef 402void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 403{
4b7e6066 404 struct bgp_path_info *top;
718e3744 405
9bcb3eef 406 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 407
6f94b685 408 pi->next = top;
40381db7 409 pi->prev = NULL;
d62a17ae 410 if (top)
40381db7 411 top->prev = pi;
9bcb3eef 412 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 413
40381db7 414 bgp_path_info_lock(pi);
9bcb3eef 415 bgp_dest_lock_node(dest);
40381db7 416 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 417 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 418 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 419}
420
d62a17ae 421/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 422 completion callback *only* */
9bcb3eef 423void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 424{
40381db7
DS
425 if (pi->next)
426 pi->next->prev = pi->prev;
427 if (pi->prev)
428 pi->prev->next = pi->next;
d62a17ae 429 else
9bcb3eef 430 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 431
40381db7
DS
432 bgp_path_info_mpath_dequeue(pi);
433 bgp_path_info_unlock(pi);
7fd28dd2 434 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 435 bgp_dest_unlock_node(dest);
718e3744 436}
437
9bcb3eef 438void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 439{
9bcb3eef 440 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 441 /* set of previous already took care of pcount */
40381db7 442 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 443}
444
18ee8310 445/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
446 called when a route is deleted and then quickly re-added before the
447 deletion has been processed */
9bcb3eef 448void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 449{
9bcb3eef 450 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 451 /* unset of previous already took care of pcount */
40381db7 452 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
453}
454
d62a17ae 455/* Adjust pcount as required */
9bcb3eef 456static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 457{
d62a17ae 458 struct bgp_table *table;
67174041 459
9bcb3eef 460 assert(dest && bgp_dest_table(dest));
40381db7 461 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 462
9bcb3eef 463 table = bgp_dest_table(dest);
67174041 464
40381db7 465 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 466 return;
467
40381db7
DS
468 if (!BGP_PATH_COUNTABLE(pi)
469 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 470
40381db7 471 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 472
473 /* slight hack, but more robust against errors. */
40381db7
DS
474 if (pi->peer->pcount[table->afi][table->safi])
475 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 476 else
450971aa 477 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 478 "Asked to decrement 0 prefix count for peer");
40381db7
DS
479 } else if (BGP_PATH_COUNTABLE(pi)
480 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
481 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
482 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 483 }
1a392d46
PJ
484}
485
40381db7
DS
486static int bgp_label_index_differs(struct bgp_path_info *pi1,
487 struct bgp_path_info *pi2)
28d58fd7 488{
40381db7 489 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 490}
1a392d46 491
18ee8310 492/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
493 * This is here primarily to keep prefix-count in check.
494 */
9bcb3eef 495void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 496 uint32_t flag)
1a392d46 497{
40381db7 498 SET_FLAG(pi->flags, flag);
d62a17ae 499
500 /* early bath if we know it's not a flag that changes countability state
501 */
502 if (!CHECK_FLAG(flag,
1defdda8 503 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 504 return;
505
9bcb3eef 506 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
507}
508
9bcb3eef 509void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 510 uint32_t flag)
1a392d46 511{
40381db7 512 UNSET_FLAG(pi->flags, flag);
d62a17ae 513
514 /* early bath if we know it's not a flag that changes countability state
515 */
516 if (!CHECK_FLAG(flag,
1defdda8 517 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 518 return;
519
9bcb3eef 520 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
521}
522
718e3744 523/* Get MED value. If MED value is missing and "bgp bestpath
524 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 525static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 526{
527 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
528 return attr->med;
529 else {
892fedb6 530 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 531 return BGP_MED_MAX;
532 else
533 return 0;
534 }
718e3744 535}
536
7533cad7
QY
537void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
538 size_t buf_len)
2ec1e66f 539{
40381db7 540 if (pi->addpath_rx_id)
7533cad7
QY
541 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
542 pi->peer->host, pi->addpath_rx_id);
d62a17ae 543 else
7533cad7 544 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 545}
9fbdd100 546
d62a17ae 547/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
548 */
18ee8310
DS
549static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
550 struct bgp_path_info *exist, int *paths_eq,
551 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
552 char *pfx_buf, afi_t afi, safi_t safi,
553 enum bgp_path_selection_reason *reason)
d62a17ae 554{
5df26422 555 const struct prefix *new_p;
d62a17ae 556 struct attr *newattr, *existattr;
557 bgp_peer_sort_t new_sort;
558 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
559 uint32_t new_pref;
560 uint32_t exist_pref;
561 uint32_t new_med;
562 uint32_t exist_med;
563 uint32_t new_weight;
564 uint32_t exist_weight;
d62a17ae 565 uint32_t newm, existm;
566 struct in_addr new_id;
567 struct in_addr exist_id;
568 int new_cluster;
569 int exist_cluster;
570 int internal_as_route;
571 int confed_as_route;
04d14c8b 572 int ret = 0;
ee88563a
JM
573 int igp_metric_ret = 0;
574 int peer_sort_ret = -1;
d62a17ae 575 char new_buf[PATH_ADDPATH_STR_BUFFER];
576 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
577 uint32_t new_mm_seq;
578 uint32_t exist_mm_seq;
6d8c603a 579 int nh_cmp;
d071f237
AK
580 esi_t *exist_esi;
581 esi_t *new_esi;
582 bool same_esi;
583 bool old_proxy;
584 bool new_proxy;
33c6e933 585 bool new_origin, exist_origin;
d62a17ae 586
587 *paths_eq = 0;
588
589 /* 0. Null check. */
590 if (new == NULL) {
fdf81fa0 591 *reason = bgp_path_selection_none;
d62a17ae 592 if (debug)
593 zlog_debug("%s: new is NULL", pfx_buf);
594 return 0;
595 }
2ec1e66f 596
d62a17ae 597 if (debug)
7533cad7
QY
598 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
599 sizeof(new_buf));
718e3744 600
d62a17ae 601 if (exist == NULL) {
fdf81fa0 602 *reason = bgp_path_selection_first;
d62a17ae 603 if (debug)
604 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
605 new_buf);
606 return 1;
607 }
2ec1e66f 608
d62a17ae 609 if (debug) {
7533cad7
QY
610 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
611 sizeof(exist_buf));
d62a17ae 612 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
613 pfx_buf, new_buf, new->flags, exist_buf,
614 exist->flags);
615 }
8ff56318 616
d62a17ae 617 newattr = new->attr;
618 existattr = exist->attr;
619
5df26422
NS
620 new_p = bgp_dest_get_prefix(new->net);
621
d62a17ae 622 /* For EVPN routes, we cannot just go by local vs remote, we have to
623 * look at the MAC mobility sequence number, if present.
624 */
5df26422
NS
625 if ((safi == SAFI_EVPN)
626 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 627 /* This is an error condition described in RFC 7432 Section
628 * 15.2. The RFC
629 * states that in this scenario "the PE MUST alert the operator"
630 * but it
631 * does not state what other action to take. In order to provide
632 * some
633 * consistency in this scenario we are going to prefer the path
634 * with the
635 * sticky flag.
636 */
637 if (newattr->sticky != existattr->sticky) {
638 if (!debug) {
5df26422
NS
639 prefix2str(new_p, pfx_buf,
640 sizeof(*pfx_buf)
641 * PREFIX2STR_BUFFER);
18ee8310 642 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
643 new, new_buf, sizeof(new_buf));
644 bgp_path_info_path_with_addpath_rx_str(
645 exist, exist_buf, sizeof(exist_buf));
d62a17ae 646 }
647
648 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 649 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
650 if (debug)
651 zlog_debug(
652 "%s: %s wins over %s due to sticky MAC flag",
653 pfx_buf, new_buf, exist_buf);
d62a17ae 654 return 1;
655 }
656
657 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 658 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
659 if (debug)
660 zlog_debug(
661 "%s: %s loses to %s due to sticky MAC flag",
662 pfx_buf, new_buf, exist_buf);
d62a17ae 663 return 0;
664 }
665 }
128ea8ab 666
d071f237
AK
667 new_esi = bgp_evpn_attr_get_esi(newattr);
668 exist_esi = bgp_evpn_attr_get_esi(existattr);
669 if (bgp_evpn_is_esi_valid(new_esi) &&
670 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
671 same_esi = true;
672 } else {
673 same_esi = false;
674 }
675
676 /* If both paths have the same non-zero ES and
677 * one path is local it wins.
678 * PS: Note the local path wins even if the remote
679 * has the higher MM seq. The local path's
680 * MM seq will be fixed up to match the highest
681 * rem seq, subsequently.
682 */
683 if (same_esi) {
684 char esi_buf[ESI_STR_LEN];
685
686 if (bgp_evpn_is_path_local(bgp, new)) {
687 *reason = bgp_path_selection_evpn_local_path;
688 if (debug)
689 zlog_debug(
690 "%s: %s wins over %s as ES %s is same and local",
691 pfx_buf, new_buf, exist_buf,
692 esi_to_str(new_esi, esi_buf,
693 sizeof(esi_buf)));
694 return 1;
695 }
696 if (bgp_evpn_is_path_local(bgp, exist)) {
697 *reason = bgp_path_selection_evpn_local_path;
698 if (debug)
699 zlog_debug(
700 "%s: %s loses to %s as ES %s is same and local",
701 pfx_buf, new_buf, exist_buf,
702 esi_to_str(new_esi, esi_buf,
703 sizeof(esi_buf)));
704 return 0;
705 }
706 }
707
d62a17ae 708 new_mm_seq = mac_mobility_seqnum(newattr);
709 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 710
d62a17ae 711 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 712 *reason = bgp_path_selection_evpn_seq;
d62a17ae 713 if (debug)
714 zlog_debug(
715 "%s: %s wins over %s due to MM seq %u > %u",
716 pfx_buf, new_buf, exist_buf, new_mm_seq,
717 exist_mm_seq);
718 return 1;
719 }
8ff56318 720
d62a17ae 721 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 722 *reason = bgp_path_selection_evpn_seq;
d62a17ae 723 if (debug)
724 zlog_debug(
725 "%s: %s loses to %s due to MM seq %u < %u",
726 pfx_buf, new_buf, exist_buf, new_mm_seq,
727 exist_mm_seq);
728 return 0;
729 }
6d8c603a 730
d071f237
AK
731 /* if the sequence numbers and ESI are the same and one path
732 * is non-proxy it wins (over proxy)
733 */
734 new_proxy = bgp_evpn_attr_is_proxy(newattr);
735 old_proxy = bgp_evpn_attr_is_proxy(existattr);
736 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
737 old_proxy != new_proxy) {
738 if (!new_proxy) {
739 *reason = bgp_path_selection_evpn_non_proxy;
740 if (debug)
741 zlog_debug(
742 "%s: %s wins over %s, same seq/es and non-proxy",
743 pfx_buf, new_buf, exist_buf);
744 return 1;
745 }
746
747 *reason = bgp_path_selection_evpn_non_proxy;
748 if (debug)
749 zlog_debug(
750 "%s: %s loses to %s, same seq/es and non-proxy",
751 pfx_buf, new_buf, exist_buf);
752 return 0;
753 }
754
6d8c603a
AK
755 /*
756 * if sequence numbers are the same path with the lowest IP
757 * wins
758 */
759 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
760 if (nh_cmp < 0) {
fdf81fa0 761 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
762 if (debug)
763 zlog_debug(
23d0a753 764 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 765 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 766 &new->attr->nexthop);
6d8c603a
AK
767 return 1;
768 }
769 if (nh_cmp > 0) {
fdf81fa0 770 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
771 if (debug)
772 zlog_debug(
23d0a753 773 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 774 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 775 &new->attr->nexthop);
6d8c603a
AK
776 return 0;
777 }
d62a17ae 778 }
9fbdd100 779
d62a17ae 780 /* 1. Weight check. */
d62a17ae 781 new_weight = newattr->weight;
782 exist_weight = existattr->weight;
8ff56318 783
d62a17ae 784 if (new_weight > exist_weight) {
fdf81fa0 785 *reason = bgp_path_selection_weight;
d62a17ae 786 if (debug)
787 zlog_debug("%s: %s wins over %s due to weight %d > %d",
788 pfx_buf, new_buf, exist_buf, new_weight,
789 exist_weight);
790 return 1;
791 }
718e3744 792
d62a17ae 793 if (new_weight < exist_weight) {
fdf81fa0 794 *reason = bgp_path_selection_weight;
d62a17ae 795 if (debug)
796 zlog_debug("%s: %s loses to %s due to weight %d < %d",
797 pfx_buf, new_buf, exist_buf, new_weight,
798 exist_weight);
799 return 0;
800 }
9fbdd100 801
d62a17ae 802 /* 2. Local preference check. */
803 new_pref = exist_pref = bgp->default_local_pref;
804
805 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
806 new_pref = newattr->local_pref;
807 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
808 exist_pref = existattr->local_pref;
809
810 if (new_pref > exist_pref) {
fdf81fa0 811 *reason = bgp_path_selection_local_pref;
d62a17ae 812 if (debug)
813 zlog_debug(
814 "%s: %s wins over %s due to localpref %d > %d",
815 pfx_buf, new_buf, exist_buf, new_pref,
816 exist_pref);
817 return 1;
818 }
718e3744 819
d62a17ae 820 if (new_pref < exist_pref) {
fdf81fa0 821 *reason = bgp_path_selection_local_pref;
d62a17ae 822 if (debug)
823 zlog_debug(
824 "%s: %s loses to %s due to localpref %d < %d",
825 pfx_buf, new_buf, exist_buf, new_pref,
826 exist_pref);
827 return 0;
828 }
9fbdd100 829
d62a17ae 830 /* 3. Local route check. We prefer:
831 * - BGP_ROUTE_STATIC
832 * - BGP_ROUTE_AGGREGATE
833 * - BGP_ROUTE_REDISTRIBUTE
834 */
33c6e933
DS
835 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
836 new->sub_type == BGP_ROUTE_IMPORTED);
837 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
838 exist->sub_type == BGP_ROUTE_IMPORTED);
839
840 if (new_origin && !exist_origin) {
fdf81fa0 841 *reason = bgp_path_selection_local_route;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to preferred BGP_ROUTE type",
845 pfx_buf, new_buf, exist_buf);
846 return 1;
847 }
718e3744 848
33c6e933 849 if (!new_origin && exist_origin) {
fdf81fa0 850 *reason = bgp_path_selection_local_route;
d62a17ae 851 if (debug)
852 zlog_debug(
853 "%s: %s loses to %s due to preferred BGP_ROUTE type",
854 pfx_buf, new_buf, exist_buf);
855 return 0;
6811845b 856 }
718e3744 857
d62a17ae 858 /* 4. AS path length check. */
892fedb6 859 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 860 int exist_hops = aspath_count_hops(existattr->aspath);
861 int exist_confeds = aspath_count_confeds(existattr->aspath);
862
892fedb6 863 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 864 int aspath_hops;
865
866 aspath_hops = aspath_count_hops(newattr->aspath);
867 aspath_hops += aspath_count_confeds(newattr->aspath);
868
869 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 870 *reason = bgp_path_selection_confed_as_path;
d62a17ae 871 if (debug)
872 zlog_debug(
873 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
874 pfx_buf, new_buf, exist_buf,
875 aspath_hops,
876 (exist_hops + exist_confeds));
877 return 1;
878 }
879
880 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 881 *reason = bgp_path_selection_confed_as_path;
d62a17ae 882 if (debug)
883 zlog_debug(
884 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
885 pfx_buf, new_buf, exist_buf,
886 aspath_hops,
887 (exist_hops + exist_confeds));
888 return 0;
889 }
890 } else {
891 int newhops = aspath_count_hops(newattr->aspath);
892
893 if (newhops < exist_hops) {
fdf81fa0 894 *reason = bgp_path_selection_as_path;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s wins over %s due to aspath hopcount %d < %d",
898 pfx_buf, new_buf, exist_buf,
899 newhops, exist_hops);
900 return 1;
901 }
902
903 if (newhops > exist_hops) {
fdf81fa0 904 *reason = bgp_path_selection_as_path;
d62a17ae 905 if (debug)
906 zlog_debug(
907 "%s: %s loses to %s due to aspath hopcount %d > %d",
908 pfx_buf, new_buf, exist_buf,
909 newhops, exist_hops);
910 return 0;
911 }
912 }
913 }
9fbdd100 914
d62a17ae 915 /* 5. Origin check. */
916 if (newattr->origin < existattr->origin) {
fdf81fa0 917 *reason = bgp_path_selection_origin;
d62a17ae 918 if (debug)
919 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
920 pfx_buf, new_buf, exist_buf,
921 bgp_origin_long_str[newattr->origin],
922 bgp_origin_long_str[existattr->origin]);
923 return 1;
924 }
718e3744 925
d62a17ae 926 if (newattr->origin > existattr->origin) {
fdf81fa0 927 *reason = bgp_path_selection_origin;
d62a17ae 928 if (debug)
929 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
930 pfx_buf, new_buf, exist_buf,
931 bgp_origin_long_str[newattr->origin],
932 bgp_origin_long_str[existattr->origin]);
933 return 0;
934 }
718e3744 935
d62a17ae 936 /* 6. MED check. */
937 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
938 && aspath_count_hops(existattr->aspath) == 0);
939 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
940 && aspath_count_confeds(existattr->aspath) > 0
941 && aspath_count_hops(newattr->aspath) == 0
942 && aspath_count_hops(existattr->aspath) == 0);
943
892fedb6
DA
944 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
945 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 946 || aspath_cmp_left(newattr->aspath, existattr->aspath)
947 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
948 || internal_as_route) {
949 new_med = bgp_med_value(new->attr, bgp);
950 exist_med = bgp_med_value(exist->attr, bgp);
951
952 if (new_med < exist_med) {
fdf81fa0 953 *reason = bgp_path_selection_med;
d62a17ae 954 if (debug)
955 zlog_debug(
956 "%s: %s wins over %s due to MED %d < %d",
957 pfx_buf, new_buf, exist_buf, new_med,
958 exist_med);
959 return 1;
960 }
8ff56318 961
d62a17ae 962 if (new_med > exist_med) {
fdf81fa0 963 *reason = bgp_path_selection_med;
d62a17ae 964 if (debug)
965 zlog_debug(
966 "%s: %s loses to %s due to MED %d > %d",
967 pfx_buf, new_buf, exist_buf, new_med,
968 exist_med);
969 return 0;
970 }
971 }
9fbdd100 972
d62a17ae 973 /* 7. Peer type check. */
974 new_sort = new->peer->sort;
975 exist_sort = exist->peer->sort;
976
977 if (new_sort == BGP_PEER_EBGP
978 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 979 *reason = bgp_path_selection_peer;
d62a17ae 980 if (debug)
981 zlog_debug(
982 "%s: %s wins over %s due to eBGP peer > iBGP peer",
983 pfx_buf, new_buf, exist_buf);
ee88563a
JM
984 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
985 return 1;
986 peer_sort_ret = 1;
d62a17ae 987 }
718e3744 988
d62a17ae 989 if (exist_sort == BGP_PEER_EBGP
990 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 991 *reason = bgp_path_selection_peer;
d62a17ae 992 if (debug)
993 zlog_debug(
994 "%s: %s loses to %s due to iBGP peer < eBGP peer",
995 pfx_buf, new_buf, exist_buf);
ee88563a
JM
996 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
997 return 0;
998 peer_sort_ret = 0;
d62a17ae 999 }
8ff56318 1000
d62a17ae 1001 /* 8. IGP metric check. */
1002 newm = existm = 0;
8ff56318 1003
d62a17ae 1004 if (new->extra)
1005 newm = new->extra->igpmetric;
1006 if (exist->extra)
1007 existm = exist->extra->igpmetric;
9fbdd100 1008
d62a17ae 1009 if (newm < existm) {
ee88563a 1010 if (debug && peer_sort_ret < 0)
d62a17ae 1011 zlog_debug(
d588b995 1012 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1013 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1014 igp_metric_ret = 1;
d62a17ae 1015 }
718e3744 1016
d62a17ae 1017 if (newm > existm) {
ee88563a 1018 if (debug && peer_sort_ret < 0)
d62a17ae 1019 zlog_debug(
d588b995 1020 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1021 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1022 igp_metric_ret = 0;
5e242b0d 1023 }
5e242b0d 1024
d62a17ae 1025 /* 9. Same IGP metric. Compare the cluster list length as
1026 representative of IGP hops metric. Rewrite the metric value
1027 pair (newm, existm) with the cluster list length. Prefer the
1028 path with smaller cluster list length. */
1029 if (newm == existm) {
bf0d28dc
DS
1030 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1031 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1032 && (mpath_cfg == NULL
1033 || CHECK_FLAG(
1034 mpath_cfg->ibgp_flags,
1035 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1036 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1037 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1038
1039 if (newm < existm) {
ee88563a 1040 if (debug && peer_sort_ret < 0)
d62a17ae 1041 zlog_debug(
d588b995 1042 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1043 pfx_buf, new_buf, exist_buf,
1044 newm, existm);
ee88563a 1045 igp_metric_ret = 1;
d62a17ae 1046 }
1047
1048 if (newm > existm) {
ee88563a 1049 if (debug && peer_sort_ret < 0)
d62a17ae 1050 zlog_debug(
d588b995 1051 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1052 pfx_buf, new_buf, exist_buf,
1053 newm, existm);
ee88563a 1054 igp_metric_ret = 0;
d62a17ae 1055 }
1056 }
1057 }
31a4638f 1058
d62a17ae 1059 /* 10. confed-external vs. confed-internal */
1060 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1061 if (new_sort == BGP_PEER_CONFED
1062 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1063 *reason = bgp_path_selection_confed;
d62a17ae 1064 if (debug)
1065 zlog_debug(
1066 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1067 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1068 if (!CHECK_FLAG(bgp->flags,
1069 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1070 return 1;
1071 peer_sort_ret = 1;
d62a17ae 1072 }
718e3744 1073
d62a17ae 1074 if (exist_sort == BGP_PEER_CONFED
1075 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1076 *reason = bgp_path_selection_confed;
d62a17ae 1077 if (debug)
1078 zlog_debug(
1079 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1080 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1081 if (!CHECK_FLAG(bgp->flags,
1082 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1083 return 0;
1084 peer_sort_ret = 0;
d62a17ae 1085 }
1086 }
718e3744 1087
d62a17ae 1088 /* 11. Maximum path check. */
1089 if (newm == existm) {
1090 /* If one path has a label but the other does not, do not treat
1091 * them as equals for multipath
1092 */
a4d82a8a 1093 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1094 != (exist->extra
b57ba6d2 1095 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1096 if (debug)
1097 zlog_debug(
1098 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1099 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1100 } else if (CHECK_FLAG(bgp->flags,
1101 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1102
1103 /*
1104 * For the two paths, all comparison steps till IGP
1105 * metric
1106 * have succeeded - including AS_PATH hop count. Since
1107 * 'bgp
1108 * bestpath as-path multipath-relax' knob is on, we
1109 * don't need
1110 * an exact match of AS_PATH. Thus, mark the paths are
1111 * equal.
1112 * That will trigger both these paths to get into the
1113 * multipath
1114 * array.
1115 */
1116 *paths_eq = 1;
1117
1118 if (debug)
1119 zlog_debug(
1120 "%s: %s and %s are equal via multipath-relax",
1121 pfx_buf, new_buf, exist_buf);
1122 } else if (new->peer->sort == BGP_PEER_IBGP) {
1123 if (aspath_cmp(new->attr->aspath,
1124 exist->attr->aspath)) {
1125 *paths_eq = 1;
1126
1127 if (debug)
1128 zlog_debug(
1129 "%s: %s and %s are equal via matching aspaths",
1130 pfx_buf, new_buf, exist_buf);
1131 }
1132 } else if (new->peer->as == exist->peer->as) {
1133 *paths_eq = 1;
1134
1135 if (debug)
1136 zlog_debug(
1137 "%s: %s and %s are equal via same remote-as",
1138 pfx_buf, new_buf, exist_buf);
1139 }
1140 } else {
1141 /*
1142 * TODO: If unequal cost ibgp multipath is enabled we can
1143 * mark the paths as equal here instead of returning
1144 */
ee88563a
JM
1145
1146 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1147 * if either step 7 or 10 (peer type checks) yielded a winner,
1148 * that result was returned immediately. Returning from step 10
1149 * ignored the return value computed in steps 8 and 9 (IGP
1150 * metric checks). In order to preserve that behavior, if
1151 * peer_sort_ret is set, return that rather than igp_metric_ret.
1152 */
1153 ret = peer_sort_ret;
1154 if (peer_sort_ret < 0) {
1155 ret = igp_metric_ret;
1156 if (debug) {
1157 if (ret == 1)
1158 zlog_debug(
1159 "%s: %s wins over %s after IGP metric comparison",
1160 pfx_buf, new_buf, exist_buf);
1161 else
1162 zlog_debug(
1163 "%s: %s loses to %s after IGP metric comparison",
1164 pfx_buf, new_buf, exist_buf);
1165 }
1166 *reason = bgp_path_selection_igp_metric;
d62a17ae 1167 }
1168 return ret;
1169 }
718e3744 1170
ee88563a
JM
1171 /*
1172 * At this point, the decision whether to set *paths_eq = 1 has been
1173 * completed. If we deferred returning because of bestpath peer-type
1174 * relax configuration, return now.
1175 */
1176 if (peer_sort_ret >= 0)
1177 return peer_sort_ret;
1178
d62a17ae 1179 /* 12. If both paths are external, prefer the path that was received
1180 first (the oldest one). This step minimizes route-flap, since a
1181 newer path won't displace an older one, even if it was the
1182 preferred route based on the additional decision criteria below. */
892fedb6 1183 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1184 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1185 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1186 *reason = bgp_path_selection_older;
d62a17ae 1187 if (debug)
1188 zlog_debug(
1189 "%s: %s wins over %s due to oldest external",
1190 pfx_buf, new_buf, exist_buf);
1191 return 1;
1192 }
9fbdd100 1193
1defdda8 1194 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1195 *reason = bgp_path_selection_older;
d62a17ae 1196 if (debug)
1197 zlog_debug(
1198 "%s: %s loses to %s due to oldest external",
1199 pfx_buf, new_buf, exist_buf);
1200 return 0;
1201 }
1202 }
718e3744 1203
d62a17ae 1204 /* 13. Router-ID comparision. */
1205 /* If one of the paths is "stale", the corresponding peer router-id will
1206 * be 0 and would always win over the other path. If originator id is
1207 * used for the comparision, it will decide which path is better.
1208 */
1209 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1210 new_id.s_addr = newattr->originator_id.s_addr;
1211 else
1212 new_id.s_addr = new->peer->remote_id.s_addr;
1213 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1214 exist_id.s_addr = existattr->originator_id.s_addr;
1215 else
1216 exist_id.s_addr = exist->peer->remote_id.s_addr;
1217
1218 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1219 *reason = bgp_path_selection_router_id;
d62a17ae 1220 if (debug)
1221 zlog_debug(
1222 "%s: %s wins over %s due to Router-ID comparison",
1223 pfx_buf, new_buf, exist_buf);
1224 return 1;
1225 }
718e3744 1226
d62a17ae 1227 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1228 *reason = bgp_path_selection_router_id;
d62a17ae 1229 if (debug)
1230 zlog_debug(
1231 "%s: %s loses to %s due to Router-ID comparison",
1232 pfx_buf, new_buf, exist_buf);
1233 return 0;
1234 }
9fbdd100 1235
d62a17ae 1236 /* 14. Cluster length comparision. */
1237 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1238 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1239
1240 if (new_cluster < exist_cluster) {
fdf81fa0 1241 *reason = bgp_path_selection_cluster_length;
d62a17ae 1242 if (debug)
1243 zlog_debug(
1244 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1245 pfx_buf, new_buf, exist_buf, new_cluster,
1246 exist_cluster);
1247 return 1;
1248 }
718e3744 1249
d62a17ae 1250 if (new_cluster > exist_cluster) {
fdf81fa0 1251 *reason = bgp_path_selection_cluster_length;
d62a17ae 1252 if (debug)
1253 zlog_debug(
1254 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1255 pfx_buf, new_buf, exist_buf, new_cluster,
1256 exist_cluster);
1257 return 0;
1258 }
9fbdd100 1259
d62a17ae 1260 /* 15. Neighbor address comparision. */
1261 /* Do this only if neither path is "stale" as stale paths do not have
1262 * valid peer information (as the connection may or may not be up).
1263 */
1defdda8 1264 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1265 *reason = bgp_path_selection_stale;
d62a17ae 1266 if (debug)
1267 zlog_debug(
1268 "%s: %s wins over %s due to latter path being STALE",
1269 pfx_buf, new_buf, exist_buf);
1270 return 1;
1271 }
0de5153c 1272
1defdda8 1273 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1274 *reason = bgp_path_selection_stale;
d62a17ae 1275 if (debug)
1276 zlog_debug(
1277 "%s: %s loses to %s due to former path being STALE",
1278 pfx_buf, new_buf, exist_buf);
1279 return 0;
1280 }
718e3744 1281
d62a17ae 1282 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1283 if (new->peer->su_remote == NULL) {
1284 *reason = bgp_path_selection_local_configured;
d62a17ae 1285 return 0;
fdf81fa0
DS
1286 }
1287 if (exist->peer->su_remote == NULL) {
1288 *reason = bgp_path_selection_local_configured;
d62a17ae 1289 return 1;
fdf81fa0 1290 }
9fbdd100 1291
d62a17ae 1292 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1293
1294 if (ret == 1) {
fdf81fa0 1295 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1296 if (debug)
1297 zlog_debug(
1298 "%s: %s loses to %s due to Neighor IP comparison",
1299 pfx_buf, new_buf, exist_buf);
1300 return 0;
1301 }
1302
1303 if (ret == -1) {
fdf81fa0 1304 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1305 if (debug)
1306 zlog_debug(
1307 "%s: %s wins over %s due to Neighor IP comparison",
1308 pfx_buf, new_buf, exist_buf);
1309 return 1;
1310 }
9fbdd100 1311
fdf81fa0 1312 *reason = bgp_path_selection_default;
d62a17ae 1313 if (debug)
1314 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1315 pfx_buf, new_buf, exist_buf);
718e3744 1316
d62a17ae 1317 return 1;
718e3744 1318}
1319
d071f237
AK
1320
1321int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1322 struct bgp_path_info *exist, int *paths_eq)
1323{
1324 enum bgp_path_selection_reason reason;
1325 char pfx_buf[PREFIX2STR_BUFFER];
1326
1327 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1328 AFI_L2VPN, SAFI_EVPN, &reason);
1329}
1330
65efcfce
LB
1331/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1332 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1333 * multipath is enabled
65efcfce 1334 * This version is compatible with */
18ee8310
DS
1335int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1336 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1337 afi_t afi, safi_t safi,
1338 enum bgp_path_selection_reason *reason)
d62a17ae 1339{
1340 int paths_eq;
1341 int ret;
18ee8310 1342 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1343 afi, safi, reason);
d62a17ae 1344
1345 if (paths_eq)
1346 ret = 0;
1347 else {
1348 if (ret == 1)
1349 ret = -1;
1350 else
1351 ret = 1;
1352 }
1353 return ret;
65efcfce
LB
1354}
1355
5a1ae2c2
DS
1356static enum filter_type bgp_input_filter(struct peer *peer,
1357 const struct prefix *p,
d62a17ae 1358 struct attr *attr, afi_t afi,
1359 safi_t safi)
718e3744 1360{
d62a17ae 1361 struct bgp_filter *filter;
6401252f 1362 enum filter_type ret = FILTER_PERMIT;
718e3744 1363
d62a17ae 1364 filter = &peer->filter[afi][safi];
718e3744 1365
d62a17ae 1366#define FILTER_EXIST_WARN(F, f, filter) \
1367 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1368 zlog_debug("%s: Could not find configured input %s-list %s!", \
1369 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1370
1371 if (DISTRIBUTE_IN_NAME(filter)) {
1372 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1373
6401252f
QY
1374 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1375 == FILTER_DENY) {
1376 ret = FILTER_DENY;
1377 goto done;
1378 }
d62a17ae 1379 }
1380
1381 if (PREFIX_LIST_IN_NAME(filter)) {
1382 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1383
6401252f
QY
1384 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1385 == PREFIX_DENY) {
1386 ret = FILTER_DENY;
1387 goto done;
1388 }
d62a17ae 1389 }
1390
1391 if (FILTER_LIST_IN_NAME(filter)) {
1392 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1393
1394 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1395 == AS_FILTER_DENY) {
1396 ret = FILTER_DENY;
1397 goto done;
1398 }
d62a17ae 1399 }
1400
6401252f 1401done:
c7bb4f00 1402 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1403 char pfxprint[PREFIX2STR_BUFFER];
1404
1405 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1406 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1407 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1408 }
1409
1410 return ret;
650f76c2 1411#undef FILTER_EXIST_WARN
718e3744 1412}
1413
b8685f9b
DS
1414static enum filter_type bgp_output_filter(struct peer *peer,
1415 const struct prefix *p,
d62a17ae 1416 struct attr *attr, afi_t afi,
1417 safi_t safi)
718e3744 1418{
d62a17ae 1419 struct bgp_filter *filter;
6401252f 1420 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1421
1422 filter = &peer->filter[afi][safi];
1423
1424#define FILTER_EXIST_WARN(F, f, filter) \
1425 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1426 zlog_debug("%s: Could not find configured output %s-list %s!", \
1427 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1428
d62a17ae 1429 if (DISTRIBUTE_OUT_NAME(filter)) {
1430 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1431
6401252f
QY
1432 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1433 == FILTER_DENY) {
1434 ret = FILTER_DENY;
1435 goto done;
1436 }
d62a17ae 1437 }
1438
1439 if (PREFIX_LIST_OUT_NAME(filter)) {
1440 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1441
d62a17ae 1442 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1443 == PREFIX_DENY) {
1444 ret = FILTER_DENY;
1445 goto done;
1446 }
d62a17ae 1447 }
718e3744 1448
d62a17ae 1449 if (FILTER_LIST_OUT_NAME(filter)) {
1450 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1451
d62a17ae 1452 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1453 == AS_FILTER_DENY) {
1454 ret = FILTER_DENY;
1455 goto done;
1456 }
1457 }
1458
c7bb4f00 1459 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1460 char pfxprint[PREFIX2STR_BUFFER];
1461
1462 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1463 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1464 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1465 }
718e3744 1466
6401252f
QY
1467done:
1468 return ret;
650f76c2 1469#undef FILTER_EXIST_WARN
718e3744 1470}
1471
1472/* If community attribute includes no_export then return 1. */
3dc339cd 1473static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1474{
1475 if (attr->community) {
1476 /* NO_ADVERTISE check. */
1477 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1478 return true;
d62a17ae 1479
1480 /* NO_EXPORT check. */
1481 if (peer->sort == BGP_PEER_EBGP
1482 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1483 return true;
d62a17ae 1484
1485 /* NO_EXPORT_SUBCONFED check. */
1486 if (peer->sort == BGP_PEER_EBGP
1487 || peer->sort == BGP_PEER_CONFED)
1488 if (community_include(attr->community,
1489 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1490 return true;
d62a17ae 1491 }
3dc339cd 1492 return false;
718e3744 1493}
1494
1495/* Route reflection loop check. */
3dc339cd 1496static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1497{
d62a17ae 1498 struct in_addr cluster_id;
779fee93 1499 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1500
779fee93 1501 if (cluster) {
d62a17ae 1502 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1503 cluster_id = peer->bgp->cluster_id;
1504 else
1505 cluster_id = peer->bgp->router_id;
1506
779fee93 1507 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1508 return true;
d62a17ae 1509 }
3dc339cd 1510 return false;
718e3744 1511}
6b0655a2 1512
5a1ae2c2 1513static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1514 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1515 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1516 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1517{
d62a17ae 1518 struct bgp_filter *filter;
82b692c0
LK
1519 struct bgp_path_info rmap_path = { 0 };
1520 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1521 route_map_result_t ret;
1522 struct route_map *rmap = NULL;
718e3744 1523
d62a17ae 1524 filter = &peer->filter[afi][safi];
718e3744 1525
d62a17ae 1526 /* Apply default weight value. */
1527 if (peer->weight[afi][safi])
1528 attr->weight = peer->weight[afi][safi];
718e3744 1529
d62a17ae 1530 if (rmap_name) {
1531 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1532
d62a17ae 1533 if (rmap == NULL)
1534 return RMAP_DENY;
1535 } else {
1536 if (ROUTE_MAP_IN_NAME(filter)) {
1537 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1538
d62a17ae 1539 if (rmap == NULL)
1540 return RMAP_DENY;
1541 }
1542 }
0b16f239 1543
d62a17ae 1544 /* Route map apply. */
1545 if (rmap) {
40381db7 1546 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1547 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1548 rmap_path.peer = peer;
1549 rmap_path.attr = attr;
82b692c0 1550 rmap_path.extra = &extra;
9bcb3eef 1551 rmap_path.net = dest;
196c6b09 1552
82b692c0
LK
1553 extra.num_labels = num_labels;
1554 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1555 memcpy(extra.label, label,
1556 num_labels * sizeof(mpls_label_t));
718e3744 1557
d62a17ae 1558 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1559
d62a17ae 1560 /* Apply BGP route map to the attribute. */
1782514f 1561 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1562
d62a17ae 1563 peer->rmap_type = 0;
0b16f239 1564
1f2263be 1565 if (ret == RMAP_DENYMATCH)
d62a17ae 1566 return RMAP_DENY;
0b16f239 1567 }
d62a17ae 1568 return RMAP_PERMIT;
0b16f239
DS
1569}
1570
5f040085 1571static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1572 struct attr *attr, afi_t afi, safi_t safi,
1573 const char *rmap_name)
0b16f239 1574{
40381db7 1575 struct bgp_path_info rmap_path;
d62a17ae 1576 route_map_result_t ret;
1577 struct route_map *rmap = NULL;
d7c0a89a 1578 uint8_t rmap_type;
0b16f239 1579
b787157a
DS
1580 /*
1581 * So if we get to this point and have no rmap_name
1582 * we want to just show the output as it currently
1583 * exists.
1584 */
1585 if (!rmap_name)
1586 return RMAP_PERMIT;
0b16f239 1587
d62a17ae 1588 /* Apply default weight value. */
1589 if (peer->weight[afi][safi])
1590 attr->weight = peer->weight[afi][safi];
0b16f239 1591
b787157a 1592 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1593
b787157a
DS
1594 /*
1595 * If we have a route map name and we do not find
1596 * the routemap that means we have an implicit
1597 * deny.
1598 */
1599 if (rmap == NULL)
1600 return RMAP_DENY;
0b16f239 1601
40381db7 1602 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1603 /* Route map apply. */
b787157a 1604 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1605 rmap_path.peer = peer;
1606 rmap_path.attr = attr;
0b16f239 1607
0f672529 1608 rmap_type = peer->rmap_type;
b787157a 1609 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1610
b787157a 1611 /* Apply BGP route map to the attribute. */
1782514f 1612 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1613
0f672529 1614 peer->rmap_type = rmap_type;
b787157a
DS
1615
1616 if (ret == RMAP_DENYMATCH)
1617 /*
1618 * caller has multiple error paths with bgp_attr_flush()
1619 */
1620 return RMAP_DENY;
ac41b2a2 1621
d62a17ae 1622 return RMAP_PERMIT;
718e3744 1623}
6b0655a2 1624
5000f21c 1625/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1626static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1627 struct peer *peer, struct attr *attr)
1628{
1629 if (peer->sort == BGP_PEER_EBGP
1630 && (peer_af_flag_check(peer, afi, safi,
1631 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1632 || peer_af_flag_check(peer, afi, safi,
1633 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1634 || peer_af_flag_check(peer, afi, safi,
1635 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1636 || peer_af_flag_check(peer, afi, safi,
1637 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1638 // Take action on the entire aspath
1639 if (peer_af_flag_check(peer, afi, safi,
1640 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1641 || peer_af_flag_check(peer, afi, safi,
1642 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1643 if (peer_af_flag_check(
1644 peer, afi, safi,
1645 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1646 attr->aspath = aspath_replace_private_asns(
bf26b80e 1647 attr->aspath, bgp->as, peer->as);
d62a17ae 1648
1649 // The entire aspath consists of private ASNs so create
1650 // an empty aspath
1651 else if (aspath_private_as_check(attr->aspath))
1652 attr->aspath = aspath_empty_get();
1653
1654 // There are some public and some private ASNs, remove
1655 // the private ASNs
1656 else
1657 attr->aspath = aspath_remove_private_asns(
bf26b80e 1658 attr->aspath, peer->as);
d62a17ae 1659 }
1660
1661 // 'all' was not specified so the entire aspath must be private
1662 // ASNs
1663 // for us to do anything
1664 else if (aspath_private_as_check(attr->aspath)) {
1665 if (peer_af_flag_check(
1666 peer, afi, safi,
1667 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1668 attr->aspath = aspath_replace_private_asns(
bf26b80e 1669 attr->aspath, bgp->as, peer->as);
d62a17ae 1670 else
1671 attr->aspath = aspath_empty_get();
1672 }
1673 }
5000f21c
DS
1674}
1675
c7122e14 1676/* If this is an EBGP peer with as-override */
d62a17ae 1677static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1678 struct peer *peer, struct attr *attr)
1679{
1680 if (peer->sort == BGP_PEER_EBGP
1681 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1682 if (aspath_single_asn_check(attr->aspath, peer->as))
1683 attr->aspath = aspath_replace_specific_asn(
1684 attr->aspath, peer->as, bgp->as);
1685 }
1686}
1687
7f323236
DW
1688void bgp_attr_add_gshut_community(struct attr *attr)
1689{
1690 struct community *old;
1691 struct community *new;
1692 struct community *merge;
1693 struct community *gshut;
1694
1695 old = attr->community;
1696 gshut = community_str2com("graceful-shutdown");
1697
990f4f91 1698 assert(gshut);
1699
7f323236
DW
1700 if (old) {
1701 merge = community_merge(community_dup(old), gshut);
1702
a4d82a8a 1703 if (old->refcnt == 0)
3c1f53de 1704 community_free(&old);
7f323236
DW
1705
1706 new = community_uniq_sort(merge);
3c1f53de 1707 community_free(&merge);
7f323236
DW
1708 } else {
1709 new = community_dup(gshut);
1710 }
1711
3c1f53de 1712 community_free(&gshut);
7f323236
DW
1713 attr->community = new;
1714 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1715
1716 /* When we add the graceful-shutdown community we must also
1717 * lower the local-preference */
1718 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1719 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1720}
1721
1722
e73c112e
MK
1723/* Notify BGP Conditional advertisement scanner process. */
1724void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1725{
1726 struct peer *temp_peer;
1727 struct peer *peer = SUBGRP_PEER(subgrp);
1728 struct listnode *temp_node, *temp_nnode = NULL;
1729 afi_t afi = SUBGRP_AFI(subgrp);
1730 safi_t safi = SUBGRP_SAFI(subgrp);
1731 struct bgp *bgp = SUBGRP_INST(subgrp);
1732 struct bgp_filter *filter = &peer->filter[afi][safi];
1733
1734 if (!ADVERTISE_MAP_NAME(filter))
1735 return;
1736
1737 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1738 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1739 continue;
1740
1741 if (peer != temp_peer)
1742 continue;
1743
1744 temp_peer->advmap_table_change = true;
1745 break;
1746 }
1747}
1748
1749
f2ee6d5c 1750void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1751{
960035b2 1752 if (family == AF_INET) {
975a328e
DA
1753 attr->nexthop.s_addr = INADDR_ANY;
1754 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1755 }
d62a17ae 1756 if (family == AF_INET6)
1757 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1758 if (family == AF_EVPN)
1759 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1760}
1761
9bcb3eef 1762bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1763 struct update_subgroup *subgrp,
7f7940e6
MK
1764 const struct prefix *p, struct attr *attr,
1765 bool skip_rmap_check)
d62a17ae 1766{
1767 struct bgp_filter *filter;
1768 struct peer *from;
1769 struct peer *peer;
1770 struct peer *onlypeer;
1771 struct bgp *bgp;
40381db7 1772 struct attr *piattr;
b68885f9 1773 route_map_result_t ret;
d62a17ae 1774 int transparent;
1775 int reflect;
1776 afi_t afi;
1777 safi_t safi;
1778 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1779 bool nh_reset = false;
1780 uint64_t cum_bw;
d62a17ae 1781
1782 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1783 return false;
d62a17ae 1784
1785 afi = SUBGRP_AFI(subgrp);
1786 safi = SUBGRP_SAFI(subgrp);
1787 peer = SUBGRP_PEER(subgrp);
1788 onlypeer = NULL;
1789 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1790 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1791
40381db7 1792 from = pi->peer;
d62a17ae 1793 filter = &peer->filter[afi][safi];
1794 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1795 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1796 : pi->attr;
3f9c7369 1797
49e5a4a0 1798#ifdef ENABLE_BGP_VNC
d62a17ae 1799 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1800 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1801 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1802
1803 /*
1804 * direct and direct_ext type routes originate internally even
1805 * though they can have peer pointers that reference other
1806 * systems
1807 */
8228a9a7
DS
1808 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1809 __func__, p);
d62a17ae 1810 samepeer_safe = 1;
1811 }
65efcfce
LB
1812#endif
1813
ddb5b488
PZ
1814 if (((afi == AFI_IP) || (afi == AFI_IP6))
1815 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1816 && (pi->type == ZEBRA_ROUTE_BGP)
1817 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1818
1819 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1820
1821 samepeer_safe = 1;
1822 }
1823
d62a17ae 1824 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1825 * pi is valid */
1826 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1827 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1828 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1829 return false;
d62a17ae 1830 }
adbac85e 1831
d62a17ae 1832 /* If this is not the bestpath then check to see if there is an enabled
1833 * addpath
1834 * feature that requires us to advertise it */
40381db7 1835 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1836 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1837 return false;
d62a17ae 1838 }
1839 }
06370dac 1840
d62a17ae 1841 /* Aggregate-address suppress check. */
4056a5f6
RZ
1842 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1843 return false;
3f9c7369 1844
13b7e7f0
DS
1845 /*
1846 * If we are doing VRF 2 VRF leaking via the import
1847 * statement, we want to prevent the route going
1848 * off box as that the RT and RD created are localy
1849 * significant and globaly useless.
1850 */
40381db7
DS
1851 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1852 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1853 return false;
13b7e7f0 1854
d62a17ae 1855 /* If it's labeled safi, make sure the route has a valid label. */
1856 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1857 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1858 if (!bgp_is_valid_label(&label)) {
1859 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1860 zlog_debug("u%" PRIu64 ":s%" PRIu64
1861 " %pFX is filtered - no label (%p)",
d62a17ae 1862 subgrp->update_group->id, subgrp->id,
8228a9a7 1863 p, &label);
3dc339cd 1864 return false;
d62a17ae 1865 }
1866 }
cd1964ff 1867
d62a17ae 1868 /* Do not send back route to sender. */
1869 if (onlypeer && from == onlypeer) {
3dc339cd 1870 return false;
d62a17ae 1871 }
3f9c7369 1872
d62a17ae 1873 /* Do not send the default route in the BGP table if the neighbor is
1874 * configured for default-originate */
1875 if (CHECK_FLAG(peer->af_flags[afi][safi],
1876 PEER_FLAG_DEFAULT_ORIGINATE)) {
1877 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1878 return false;
d62a17ae 1879 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1880 return false;
d62a17ae 1881 }
4125bb67 1882
d62a17ae 1883 /* Transparency check. */
1884 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1885 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1886 transparent = 1;
1887 else
1888 transparent = 0;
1889
1890 /* If community is not disabled check the no-export and local. */
40381db7 1891 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1892 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1893 zlog_debug("%s: community filter check fail for %pFX",
1894 __func__, p);
3dc339cd 1895 return false;
d62a17ae 1896 }
3f9c7369 1897
d62a17ae 1898 /* If the attribute has originator-id and it is same as remote
1899 peer's id. */
40381db7
DS
1900 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1901 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1902 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1903 zlog_debug(
8228a9a7
DS
1904 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1905 onlypeer->host, p);
3dc339cd 1906 return false;
d62a17ae 1907 }
3f9c7369 1908
d62a17ae 1909 /* ORF prefix-list filter check */
1910 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1911 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1912 || CHECK_FLAG(peer->af_cap[afi][safi],
1913 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1914 if (peer->orf_plist[afi][safi]) {
1915 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1916 == PREFIX_DENY) {
1917 if (bgp_debug_update(NULL, p,
1918 subgrp->update_group, 0))
1919 zlog_debug(
8228a9a7
DS
1920 "%s [Update:SEND] %pFX is filtered via ORF",
1921 peer->host, p);
3dc339cd 1922 return false;
d62a17ae 1923 }
1924 }
1925
1926 /* Output filter check. */
40381db7 1927 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1928 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1929 zlog_debug("%s [Update:SEND] %pFX is filtered",
1930 peer->host, p);
3dc339cd 1931 return false;
d62a17ae 1932 }
3f9c7369 1933
d62a17ae 1934 /* AS path loop check. */
2b31007c
RZ
1935 if (onlypeer && onlypeer->as_path_loop_detection
1936 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1937 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1938 zlog_debug(
3efd0893 1939 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1940 onlypeer->host, onlypeer->as);
3dc339cd 1941 return false;
d62a17ae 1942 }
3f9c7369 1943
d62a17ae 1944 /* If we're a CONFED we need to loop check the CONFED ID too */
1945 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1946 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1947 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1948 zlog_debug(
3efd0893 1949 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1950 peer->host, bgp->confed_id);
3dc339cd 1951 return false;
d62a17ae 1952 }
3f9c7369 1953 }
3f9c7369 1954
d62a17ae 1955 /* Route-Reflect check. */
1956 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1957 reflect = 1;
1958 else
1959 reflect = 0;
1960
1961 /* IBGP reflection check. */
1962 if (reflect && !samepeer_safe) {
1963 /* A route from a Client peer. */
1964 if (CHECK_FLAG(from->af_flags[afi][safi],
1965 PEER_FLAG_REFLECTOR_CLIENT)) {
1966 /* Reflect to all the Non-Client peers and also to the
1967 Client peers other than the originator. Originator
1968 check
1969 is already done. So there is noting to do. */
1970 /* no bgp client-to-client reflection check. */
892fedb6
DA
1971 if (CHECK_FLAG(bgp->flags,
1972 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1973 if (CHECK_FLAG(peer->af_flags[afi][safi],
1974 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1975 return false;
d62a17ae 1976 } else {
1977 /* A route from a Non-client peer. Reflect to all other
1978 clients. */
1979 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1980 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1981 return false;
d62a17ae 1982 }
1983 }
3f9c7369 1984
d62a17ae 1985 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1986 *attr = *piattr;
d62a17ae 1987
1988 /* If local-preference is not set. */
1989 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1990 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1991 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1992 attr->local_pref = bgp->default_local_pref;
3f9c7369 1993 }
3f9c7369 1994
d62a17ae 1995 /* If originator-id is not set and the route is to be reflected,
1996 set the originator id */
1997 if (reflect
1998 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1999 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2000 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2001 }
3f9c7369 2002
d62a17ae 2003 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2004 */
2005 if (peer->sort == BGP_PEER_EBGP
2006 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2007 if (from != bgp->peer_self && !transparent
2008 && !CHECK_FLAG(peer->af_flags[afi][safi],
2009 PEER_FLAG_MED_UNCHANGED))
2010 attr->flag &=
2011 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2012 }
3f9c7369 2013
d62a17ae 2014 /* Since the nexthop attribute can vary per peer, it is not explicitly
2015 * set
2016 * in announce check, only certain flags and length (or number of
2017 * nexthops
2018 * -- for IPv6/MP_REACH) are set here in order to guide the update
2019 * formation
2020 * code in setting the nexthop(s) on a per peer basis in
2021 * reformat_peer().
2022 * Typically, the source nexthop in the attribute is preserved but in
2023 * the
2024 * scenarios where we know it will always be overwritten, we reset the
2025 * nexthop to "0" in an attempt to achieve better Update packing. An
2026 * example of this is when a prefix from each of 2 IBGP peers needs to
2027 * be
2028 * announced to an EBGP peer (and they have the same attributes barring
2029 * their nexthop).
2030 */
2031 if (reflect)
2032 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2033
2034#define NEXTHOP_IS_V6 \
2035 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2036 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2037 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2038 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2039
2040 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2041 * if
2042 * the peer (group) is configured to receive link-local nexthop
2043 * unchanged
c728d027
DA
2044 * and it is available in the prefix OR we're not reflecting the route,
2045 * link-local nexthop address is valid and
d62a17ae 2046 * the peer (group) to whom we're going to announce is on a shared
2047 * network
2048 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2049 * By checking if nexthop LL address is valid we are sure that
2050 * we do not announce LL address as `::`.
d62a17ae 2051 */
2052 if (NEXTHOP_IS_V6) {
2053 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2054 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2055 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2056 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2057 || (!reflect
2058 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2059 && peer->shared_network
d62a17ae 2060 && (from == bgp->peer_self
2061 || peer->sort == BGP_PEER_EBGP))) {
2062 attr->mp_nexthop_len =
2063 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2064 }
3f9c7369 2065
d62a17ae 2066 /* Clear off link-local nexthop in source, whenever it is not
2067 * needed to
2068 * ensure more prefixes share the same attribute for
2069 * announcement.
2070 */
2071 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2072 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2073 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2074 }
3f9c7369 2075
d62a17ae 2076 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2077 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2078
2079 /* Route map & unsuppress-map apply. */
7f7940e6 2080 if (!skip_rmap_check
e73c112e 2081 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2082 struct bgp_path_info rmap_path = {0};
2083 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2084 struct attr dummy_attr = {0};
d62a17ae 2085
e34291b8 2086 /* Fill temp path_info */
9bcb3eef
DS
2087 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2088 pi, peer, attr);
16f7ce2b 2089
d62a17ae 2090 /* don't confuse inbound and outbound setting */
2091 RESET_FLAG(attr->rmap_change_flags);
2092
2093 /*
2094 * The route reflector is not allowed to modify the attributes
2095 * of the reflected IBGP routes unless explicitly allowed.
2096 */
2097 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2098 && !CHECK_FLAG(bgp->flags,
2099 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2100 dummy_attr = *attr;
40381db7 2101 rmap_path.attr = &dummy_attr;
d62a17ae 2102 }
3f9c7369 2103
d62a17ae 2104 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2105
4056a5f6 2106 if (bgp_path_suppressed(pi))
d62a17ae 2107 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2108 &rmap_path);
d62a17ae 2109 else
2110 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2111 &rmap_path);
d62a17ae 2112
2113 peer->rmap_type = 0;
2114
2115 if (ret == RMAP_DENYMATCH) {
778048bf 2116 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2117 zlog_debug(
2118 "%s [Update:SEND] %pFX is filtered by route-map",
2119 peer->host, p);
778048bf 2120
d62a17ae 2121 bgp_attr_flush(attr);
3dc339cd 2122 return false;
d62a17ae 2123 }
3f9c7369 2124 }
3f9c7369 2125
9dac9fc8
DA
2126 /* RFC 8212 to prevent route leaks.
2127 * This specification intends to improve this situation by requiring the
2128 * explicit configuration of both BGP Import and Export Policies for any
2129 * External BGP (EBGP) session such as customers, peers, or
2130 * confederation boundaries for all enabled address families. Through
2131 * codification of the aforementioned requirement, operators will
2132 * benefit from consistent behavior across different BGP
2133 * implementations.
2134 */
1d3fdccf 2135 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2136 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2137 return false;
9dac9fc8 2138
fb29348a
DA
2139 /* draft-ietf-idr-deprecate-as-set-confed-set
2140 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2141 * Eventually, This document (if approved) updates RFC 4271
2142 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2143 * and obsoletes RFC 6472.
2144 */
7f972cd8 2145 if (peer->bgp->reject_as_sets)
fb29348a 2146 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2147 return false;
fb29348a 2148
33d022bc
DA
2149 /* Codification of AS 0 Processing */
2150 if (aspath_check_as_zero(attr->aspath))
e2369003 2151 return false;
33d022bc 2152
637e5ba4 2153 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2154 if (peer->sort == BGP_PEER_IBGP
2155 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2156 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2157 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2158 } else {
2159 bgp_attr_add_gshut_community(attr);
2160 }
2161 }
2162
d62a17ae 2163 /* After route-map has been applied, we check to see if the nexthop to
2164 * be carried in the attribute (that is used for the announcement) can
2165 * be cleared off or not. We do this in all cases where we would be
2166 * setting the nexthop to "ourselves". For IPv6, we only need to
2167 * consider
2168 * the global nexthop here; the link-local nexthop would have been
2169 * cleared
2170 * already, and if not, it is required by the update formation code.
2171 * Also see earlier comments in this function.
2172 */
2173 /*
2174 * If route-map has performed some operation on the nexthop or the peer
2175 * configuration says to pass it unchanged, we cannot reset the nexthop
2176 * here, so only attempt to do it if these aren't true. Note that the
2177 * route-map handler itself might have cleared the nexthop, if for
2178 * example,
2179 * it is configured as 'peer-address'.
2180 */
2181 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2182 piattr->rmap_change_flags)
d62a17ae 2183 && !transparent
2184 && !CHECK_FLAG(peer->af_flags[afi][safi],
2185 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2186 /* We can reset the nexthop, if setting (or forcing) it to
2187 * 'self' */
2188 if (CHECK_FLAG(peer->af_flags[afi][safi],
2189 PEER_FLAG_NEXTHOP_SELF)
2190 || CHECK_FLAG(peer->af_flags[afi][safi],
2191 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2192 if (!reflect
2193 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2194 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2195 subgroup_announce_reset_nhop(
2196 (peer_cap_enhe(peer, afi, safi)
2197 ? AF_INET6
2198 : p->family),
2199 attr);
7b651a32 2200 nh_reset = true;
2201 }
d62a17ae 2202 } else if (peer->sort == BGP_PEER_EBGP) {
2203 /* Can also reset the nexthop if announcing to EBGP, but
2204 * only if
2205 * no peer in the subgroup is on a shared subnet.
2206 * Note: 3rd party nexthop currently implemented for
2207 * IPv4 only.
2208 */
737af885
BS
2209 if ((p->family == AF_INET) &&
2210 (!bgp_subgrp_multiaccess_check_v4(
2211 piattr->nexthop,
7b651a32 2212 subgrp, from))) {
d62a17ae 2213 subgroup_announce_reset_nhop(
2214 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2215 ? AF_INET6
2216 : p->family),
737af885 2217 attr);
7b651a32 2218 nh_reset = true;
2219 }
737af885
BS
2220
2221 if ((p->family == AF_INET6) &&
2222 (!bgp_subgrp_multiaccess_check_v6(
2223 piattr->mp_nexthop_global,
7b651a32 2224 subgrp, from))) {
737af885
BS
2225 subgroup_announce_reset_nhop(
2226 (peer_cap_enhe(peer, afi, safi)
2227 ? AF_INET6
2228 : p->family),
2229 attr);
7b651a32 2230 nh_reset = true;
2231 }
737af885
BS
2232
2233
2234
40381db7 2235 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2236 /*
2237 * This flag is used for leaked vpn-vrf routes
2238 */
2239 int family = p->family;
2240
2241 if (peer_cap_enhe(peer, afi, safi))
2242 family = AF_INET6;
2243
2244 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2245 zlog_debug(
1defdda8 2246 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2247 __func__, family2str(family));
2248 subgroup_announce_reset_nhop(family, attr);
7b651a32 2249 nh_reset = true;
d62a17ae 2250 }
63696f1d 2251 }
960035b2 2252
63696f1d 2253 /* If IPv6/MP and nexthop does not have any override and happens
2254 * to
2255 * be a link-local address, reset it so that we don't pass along
2256 * the
2257 * source's link-local IPv6 address to recipients who may not be
2258 * on
2259 * the same interface.
2260 */
2261 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2262 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2263 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2264 nh_reset = true;
2265 }
d62a17ae 2266 }
3f9c7369 2267
7b651a32 2268 /*
2269 * When the next hop is set to ourselves, if all multipaths have
2270 * link-bandwidth announce the cumulative bandwidth as that makes
2271 * the most sense. However, don't modify if the link-bandwidth has
2272 * been explicitly set by user policy.
2273 */
2274 if (nh_reset &&
f7e1c681 2275 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2276 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2277 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2278 attr->ecommunity = ecommunity_replace_linkbw(
2279 bgp->as, attr->ecommunity, cum_bw);
2280
3dc339cd 2281 return true;
3f9c7369
DS
2282}
2283
f009ff26 2284static int bgp_route_select_timer_expire(struct thread *thread)
2285{
2286 struct afi_safi_info *info;
2287 afi_t afi;
2288 safi_t safi;
2289 struct bgp *bgp;
2290
2291 info = THREAD_ARG(thread);
2292 afi = info->afi;
2293 safi = info->safi;
2294 bgp = info->bgp;
2295
2296 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2297 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2298 safi);
f009ff26 2299
2300 bgp->gr_info[afi][safi].t_route_select = NULL;
2301
2302 XFREE(MTYPE_TMP, info);
2303
2304 /* Best path selection */
2305 return bgp_best_path_select_defer(bgp, afi, safi);
2306}
2307
9bcb3eef 2308void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2309 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2310 struct bgp_path_info_pair *result, afi_t afi,
2311 safi_t safi)
2312{
2313 struct bgp_path_info *new_select;
2314 struct bgp_path_info *old_select;
40381db7
DS
2315 struct bgp_path_info *pi;
2316 struct bgp_path_info *pi1;
2317 struct bgp_path_info *pi2;
2318 struct bgp_path_info *nextpi = NULL;
d62a17ae 2319 int paths_eq, do_mpath, debug;
2320 struct list mp_list;
2321 char pfx_buf[PREFIX2STR_BUFFER];
2322 char path_buf[PATH_ADDPATH_STR_BUFFER];
2323
2324 bgp_mp_list_init(&mp_list);
2325 do_mpath =
2326 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2327
9bcb3eef 2328 debug = bgp_debug_bestpath(dest);
d62a17ae 2329
2330 if (debug)
9bcb3eef 2331 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2332
9bcb3eef 2333 dest->reason = bgp_path_selection_none;
d62a17ae 2334 /* bgp deterministic-med */
2335 new_select = NULL;
892fedb6 2336 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2337
1defdda8 2338 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2339 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2340 pi1 = pi1->next)
9bcb3eef 2341 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2342 BGP_PATH_DMED_SELECTED);
d62a17ae 2343
9bcb3eef 2344 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2345 pi1 = pi1->next) {
40381db7 2346 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2347 continue;
40381db7 2348 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2349 continue;
ea8b2282 2350 if (pi1->peer != bgp->peer_self)
feb17238 2351 if (!peer_established(pi1->peer))
d62a17ae 2352 continue;
2353
40381db7
DS
2354 new_select = pi1;
2355 if (pi1->next) {
2356 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2357 if (CHECK_FLAG(pi2->flags,
1defdda8 2358 BGP_PATH_DMED_CHECK))
d62a17ae 2359 continue;
40381db7 2360 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2361 continue;
ea8b2282 2362 if (pi2->peer != bgp->peer_self
d62a17ae 2363 && !CHECK_FLAG(
ea8b2282
DS
2364 pi2->peer->sflags,
2365 PEER_STATUS_NSF_WAIT))
40381db7 2366 if (pi2->peer->status
d62a17ae 2367 != Established)
2368 continue;
2369
121e245d
DS
2370 if (!aspath_cmp_left(pi1->attr->aspath,
2371 pi2->attr->aspath)
2372 && !aspath_cmp_left_confed(
40381db7 2373 pi1->attr->aspath,
121e245d
DS
2374 pi2->attr->aspath))
2375 continue;
d62a17ae 2376
121e245d
DS
2377 if (bgp_path_info_cmp(
2378 bgp, pi2, new_select,
2379 &paths_eq, mpath_cfg, debug,
fdf81fa0 2380 pfx_buf, afi, safi,
9bcb3eef 2381 &dest->reason)) {
121e245d 2382 bgp_path_info_unset_flag(
9bcb3eef 2383 dest, new_select,
121e245d
DS
2384 BGP_PATH_DMED_SELECTED);
2385 new_select = pi2;
d62a17ae 2386 }
121e245d
DS
2387
2388 bgp_path_info_set_flag(
9bcb3eef 2389 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2390 }
2391 }
9bcb3eef 2392 bgp_path_info_set_flag(dest, new_select,
18ee8310 2393 BGP_PATH_DMED_CHECK);
9bcb3eef 2394 bgp_path_info_set_flag(dest, new_select,
18ee8310 2395 BGP_PATH_DMED_SELECTED);
d62a17ae 2396
2397 if (debug) {
18ee8310 2398 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2399 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2400 zlog_debug(
2401 "%pBD: %s is the bestpath from AS %u",
2402 dest, path_buf,
2403 aspath_get_first_as(
2404 new_select->attr->aspath));
d62a17ae 2405 }
2406 }
2407 }
96450faf 2408
d62a17ae 2409 /* Check old selected route and new selected route. */
2410 old_select = NULL;
2411 new_select = NULL;
9bcb3eef 2412 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2413 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2414 enum bgp_path_selection_reason reason;
2415
40381db7
DS
2416 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2417 old_select = pi;
d62a17ae 2418
40381db7 2419 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2420 /* reap REMOVED routes, if needs be
2421 * selected route must stay for a while longer though
2422 */
40381db7
DS
2423 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2424 && (pi != old_select))
9bcb3eef 2425 bgp_path_info_reap(dest, pi);
d62a17ae 2426
ddb5b488 2427 if (debug)
40381db7
DS
2428 zlog_debug("%s: pi %p in holddown", __func__,
2429 pi);
ddb5b488 2430
d62a17ae 2431 continue;
2432 }
96450faf 2433
40381db7
DS
2434 if (pi->peer && pi->peer != bgp->peer_self
2435 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2436 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2437
2438 if (debug)
2439 zlog_debug(
40381db7
DS
2440 "%s: pi %p non self peer %s not estab state",
2441 __func__, pi, pi->peer->host);
ddb5b488 2442
d62a17ae 2443 continue;
ddb5b488 2444 }
9fbdd100 2445
892fedb6 2446 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2447 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2448 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2449 if (debug)
40381db7 2450 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2451 continue;
2452 }
9fbdd100 2453
9bcb3eef 2454 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2455
9bcb3eef 2456 reason = dest->reason;
40381db7 2457 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2458 debug, pfx_buf, afi, safi,
2459 &dest->reason)) {
19ea4cec
DS
2460 if (new_select == NULL &&
2461 reason != bgp_path_selection_none)
9bcb3eef 2462 dest->reason = reason;
40381db7 2463 new_select = pi;
d62a17ae 2464 }
2465 }
718e3744 2466
d62a17ae 2467 /* Now that we know which path is the bestpath see if any of the other
2468 * paths
2469 * qualify as multipaths
2470 */
2471 if (debug) {
2472 if (new_select)
7533cad7
QY
2473 bgp_path_info_path_with_addpath_rx_str(
2474 new_select, path_buf, sizeof(path_buf));
d62a17ae 2475 else
772270f3 2476 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2477 zlog_debug(
8228a9a7
DS
2478 "%pBD: After path selection, newbest is %s oldbest was %s",
2479 dest, path_buf,
d62a17ae 2480 old_select ? old_select->peer->host : "NONE");
96450faf 2481 }
9fbdd100 2482
d62a17ae 2483 if (do_mpath && new_select) {
9bcb3eef 2484 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2485 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2486
2487 if (debug)
18ee8310 2488 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2489 pi, path_buf, sizeof(path_buf));
d62a17ae 2490
40381db7 2491 if (pi == new_select) {
d62a17ae 2492 if (debug)
2493 zlog_debug(
8228a9a7
DS
2494 "%pBD: %s is the bestpath, add to the multipath list",
2495 dest, path_buf);
40381db7 2496 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2497 continue;
2498 }
2499
40381db7 2500 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2501 continue;
2502
40381db7
DS
2503 if (pi->peer && pi->peer != bgp->peer_self
2504 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2505 PEER_STATUS_NSF_WAIT))
feb17238 2506 if (!peer_established(pi->peer))
d62a17ae 2507 continue;
2508
40381db7 2509 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2510 if (debug)
2511 zlog_debug(
8228a9a7
DS
2512 "%pBD: %s has the same nexthop as the bestpath, skip it",
2513 dest, path_buf);
d62a17ae 2514 continue;
2515 }
2516
40381db7 2517 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2518 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2519 &dest->reason);
d62a17ae 2520
2521 if (paths_eq) {
2522 if (debug)
2523 zlog_debug(
8228a9a7
DS
2524 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2525 dest, path_buf);
40381db7 2526 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2527 }
2528 }
2529 }
fee0f4c6 2530
9bcb3eef 2531 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2532 mpath_cfg);
2533 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2534 bgp_mp_list_clear(&mp_list);
96450faf 2535
9bcb3eef 2536 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2537
d62a17ae 2538 result->old = old_select;
2539 result->new = new_select;
96450faf 2540
d62a17ae 2541 return;
fee0f4c6 2542}
2543
3f9c7369
DS
2544/*
2545 * A new route/change in bestpath of an existing route. Evaluate the path
2546 * for advertisement to the subgroup.
2547 */
3dc339cd
DA
2548void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2549 struct bgp_path_info *selected,
9bcb3eef 2550 struct bgp_dest *dest,
3dc339cd 2551 uint32_t addpath_tx_id)
d62a17ae 2552{
b54892e0 2553 const struct prefix *p;
d62a17ae 2554 struct peer *onlypeer;
2555 struct attr attr;
2556 afi_t afi;
2557 safi_t safi;
a77e2f4b
S
2558 struct bgp *bgp;
2559 bool advertise;
adbac85e 2560
9bcb3eef 2561 p = bgp_dest_get_prefix(dest);
d62a17ae 2562 afi = SUBGRP_AFI(subgrp);
2563 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2564 bgp = SUBGRP_INST(subgrp);
d62a17ae 2565 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2566 : NULL);
2567
2dbe669b
DA
2568 if (BGP_DEBUG(update, UPDATE_OUT))
2569 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2570
d62a17ae 2571 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2572 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2573 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2574 return;
d62a17ae 2575
2576 memset(&attr, 0, sizeof(struct attr));
2577 /* It's initialized in bgp_announce_check() */
2578
a77e2f4b
S
2579 /* Announcement to the subgroup. If the route is filtered withdraw it.
2580 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2581 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2582 * route
d62a17ae 2583 */
a77e2f4b
S
2584 advertise = bgp_check_advertise(bgp, dest);
2585
d62a17ae 2586 if (selected) {
7f7940e6 2587 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2588 false)) {
2589 /* Route is selected, if the route is already installed
2590 * in FIB, then it is advertised
2591 */
2592 if (advertise)
2593 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2594 selected);
2595 } else
9bcb3eef 2596 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2597 addpath_tx_id);
d62a17ae 2598 }
2599
2600 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2601 else {
9bcb3eef 2602 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2603 }
200df115 2604}
fee0f4c6 2605
3064bf43 2606/*
e1072051 2607 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2608 * This is called at the end of route processing.
3064bf43 2609 */
9bcb3eef 2610void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2611{
40381db7 2612 struct bgp_path_info *pi;
3064bf43 2613
9bcb3eef 2614 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2615 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2616 continue;
40381db7
DS
2617 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2618 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2619 }
3064bf43 2620}
2621
2622/*
2623 * Has the route changed from the RIB's perspective? This is invoked only
2624 * if the route selection returns the same best route as earlier - to
2625 * determine if we need to update zebra or not.
2626 */
9bcb3eef 2627bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2628{
4b7e6066 2629 struct bgp_path_info *mpinfo;
d62a17ae 2630
2bb9eff4
DS
2631 /* If this is multipath, check all selected paths for any nexthop
2632 * change or attribute change. Some attribute changes (e.g., community)
2633 * aren't of relevance to the RIB, but we'll update zebra to ensure
2634 * we handle the case of BGP nexthop change. This is the behavior
2635 * when the best path has an attribute change anyway.
d62a17ae 2636 */
1defdda8 2637 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2638 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2639 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2640 return true;
d62a17ae 2641
2bb9eff4
DS
2642 /*
2643 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2644 */
18ee8310
DS
2645 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2646 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2647 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2648 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2649 return true;
d62a17ae 2650 }
3064bf43 2651
d62a17ae 2652 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2653 return false;
3064bf43 2654}
2655
d62a17ae 2656struct bgp_process_queue {
2657 struct bgp *bgp;
9bcb3eef 2658 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2659#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2660 unsigned int flags;
2661 unsigned int queued;
200df115 2662};
2663
3b0c17e1 2664static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2665 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2666 struct bgp_path_info *new_select,
2667 struct bgp_path_info *old_select)
2668{
9bcb3eef 2669 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2670
2671 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2672 return;
2673
2674 if (advertise_type5_routes(bgp, afi) && new_select
2675 && is_route_injectable_into_evpn(new_select)) {
2676
2677 /* apply the route-map */
2678 if (bgp->adv_cmd_rmap[afi][safi].map) {
2679 route_map_result_t ret;
2680 struct bgp_path_info rmap_path;
2681 struct bgp_path_info_extra rmap_path_extra;
2682 struct attr dummy_attr;
2683
2684 dummy_attr = *new_select->attr;
2685
2686 /* Fill temp path_info */
9bcb3eef 2687 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2688 new_select, new_select->peer,
2689 &dummy_attr);
2690
2691 RESET_FLAG(dummy_attr.rmap_change_flags);
2692
2693 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2694 p, &rmap_path);
3b0c17e1 2695
2696 if (ret == RMAP_DENYMATCH) {
2697 bgp_attr_flush(&dummy_attr);
2698 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2699 safi);
2700 } else
2701 bgp_evpn_advertise_type5_route(
2702 bgp, p, &dummy_attr, afi, safi);
2703 } else {
2704 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2705 afi, safi);
2706 }
2707 } else if (advertise_type5_routes(bgp, afi) && old_select
2708 && is_route_injectable_into_evpn(old_select))
2709 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2710}
2711
3103e8d2
DS
2712/*
2713 * old_select = The old best path
2714 * new_select = the new best path
2715 *
2716 * if (!old_select && new_select)
2717 * We are sending new information on.
2718 *
2719 * if (old_select && new_select) {
2720 * if (new_select != old_select)
2721 * We have a new best path send a change
2722 * else
2723 * We've received a update with new attributes that needs
2724 * to be passed on.
2725 * }
2726 *
2727 * if (old_select && !new_select)
2728 * We have no eligible route that we can announce or the rn
2729 * is being removed.
2730 */
9bcb3eef 2731static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2732 afi_t afi, safi_t safi)
d62a17ae 2733{
4b7e6066
DS
2734 struct bgp_path_info *new_select;
2735 struct bgp_path_info *old_select;
2736 struct bgp_path_info_pair old_and_new;
ddb5b488 2737 int debug = 0;
d62a17ae 2738
892fedb6 2739 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2740 if (dest)
2741 debug = bgp_debug_bestpath(dest);
b54892e0 2742 if (debug)
f4c713ae 2743 zlog_debug(
56ca3b5b 2744 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2745 __func__, dest);
f4c713ae
LB
2746 return;
2747 }
d62a17ae 2748 /* Is it end of initial update? (after startup) */
9bcb3eef 2749 if (!dest) {
d62a17ae 2750 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2751 sizeof(bgp->update_delay_zebra_resume_time));
2752
2753 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2754 FOREACH_AFI_SAFI (afi, safi) {
2755 if (bgp_fibupd_safi(safi))
2756 bgp_zebra_announce_table(bgp, afi, safi);
2757 }
d62a17ae 2758 bgp->main_peers_update_hold = 0;
2759
2760 bgp_start_routeadv(bgp);
aac24838 2761 return;
d62a17ae 2762 }
cb1faec9 2763
9bcb3eef 2764 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2765
9bcb3eef 2766 debug = bgp_debug_bestpath(dest);
b54892e0 2767 if (debug)
56ca3b5b 2768 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2769 afi2str(afi), safi2str(safi));
ddb5b488 2770
f009ff26 2771 /* The best path calculation for the route is deferred if
2772 * BGP_NODE_SELECT_DEFER is set
2773 */
9bcb3eef 2774 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2775 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2776 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2777 return;
2778 }
2779
d62a17ae 2780 /* Best path selection. */
9bcb3eef 2781 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2782 afi, safi);
2783 old_select = old_and_new.old;
2784 new_select = old_and_new.new;
2785
2786 /* Do we need to allocate or free labels?
2787 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2788 * necessary to do this upon changes to best path. Exceptions:
2789 * - label index has changed -> recalculate resulting label
2790 * - path_info sub_type changed -> switch to/from implicit-null
2791 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2792 */
318cac96 2793 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2794 if (new_select) {
2795 if (!old_select
2796 || bgp_label_index_differs(new_select, old_select)
57592a53 2797 || new_select->sub_type != old_select->sub_type
9bcb3eef 2798 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2799 /* Enforced penultimate hop popping:
2800 * implicit-null for local routes, aggregate
2801 * and redistributed routes
2802 */
d62a17ae 2803 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2804 || new_select->sub_type
2805 == BGP_ROUTE_AGGREGATE
2806 || new_select->sub_type
2807 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2808 if (CHECK_FLAG(
9bcb3eef 2809 dest->flags,
992dd67e
PR
2810 BGP_NODE_REGISTERED_FOR_LABEL)
2811 || CHECK_FLAG(
2812 dest->flags,
2813 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2814 bgp_unregister_for_label(dest);
70e98a7f 2815 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2816 &dest->local_label);
2817 bgp_set_valid_label(&dest->local_label);
d62a17ae 2818 } else
9bcb3eef
DS
2819 bgp_register_for_label(dest,
2820 new_select);
d62a17ae 2821 }
9bcb3eef 2822 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2823 BGP_NODE_REGISTERED_FOR_LABEL)
2824 || CHECK_FLAG(dest->flags,
2825 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2826 bgp_unregister_for_label(dest);
318cac96 2827 }
992dd67e
PR
2828 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2829 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2830 bgp_unregister_for_label(dest);
d62a17ae 2831 }
cd1964ff 2832
b54892e0 2833 if (debug)
ddb5b488 2834 zlog_debug(
56ca3b5b 2835 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2836 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2837 old_select, new_select);
ddb5b488 2838
d62a17ae 2839 /* If best route remains the same and this is not due to user-initiated
2840 * clear, see exactly what needs to be done.
2841 */
d62a17ae 2842 if (old_select && old_select == new_select
9bcb3eef 2843 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2844 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2845 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2846 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2847#ifdef ENABLE_BGP_VNC
d62a17ae 2848 vnc_import_bgp_add_route(bgp, p, old_select);
2849 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2850#endif
bb744275 2851 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2852 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2853
2854 if (new_select->type == ZEBRA_ROUTE_BGP
2855 && (new_select->sub_type == BGP_ROUTE_NORMAL
2856 || new_select->sub_type
2857 == BGP_ROUTE_IMPORTED))
2858
9bcb3eef 2859 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2860 bgp, afi, safi);
2861 }
d62a17ae 2862 }
d62a17ae 2863
2864 /* If there is a change of interest to peers, reannounce the
2865 * route. */
1defdda8 2866 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2867 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2868 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2869 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2870
2871 /* unicast routes must also be annouced to
2872 * labeled-unicast update-groups */
2873 if (safi == SAFI_UNICAST)
2874 group_announce_route(bgp, afi,
9bcb3eef 2875 SAFI_LABELED_UNICAST, dest,
d62a17ae 2876 new_select);
2877
1defdda8 2878 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2879 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2880 }
fee0f4c6 2881
3b0c17e1 2882 /* advertise/withdraw type-5 routes */
2883 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2884 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2885 bgp_process_evpn_route_injection(
9bcb3eef 2886 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2887
b1875e65 2888 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2889 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2890 bgp_zebra_clear_route_change_flags(dest);
2891 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2892 return;
d62a17ae 2893 }
8ad7271d 2894
d62a17ae 2895 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2896 */
9bcb3eef 2897 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2898
2899 /* bestpath has changed; bump version */
2900 if (old_select || new_select) {
9bcb3eef 2901 bgp_bump_version(dest);
d62a17ae 2902
2903 if (!bgp->t_rmap_def_originate_eval) {
2904 bgp_lock(bgp);
2905 thread_add_timer(
2906 bm->master,
2907 update_group_refresh_default_originate_route_map,
2908 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2909 &bgp->t_rmap_def_originate_eval);
2910 }
2911 }
3f9c7369 2912
d62a17ae 2913 if (old_select)
9bcb3eef 2914 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2915 if (new_select) {
ddb5b488
PZ
2916 if (debug)
2917 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2918 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2919 bgp_path_info_unset_flag(dest, new_select,
2920 BGP_PATH_ATTR_CHANGED);
1defdda8 2921 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2922 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2923 }
338b3424 2924
49e5a4a0 2925#ifdef ENABLE_BGP_VNC
d62a17ae 2926 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2927 if (old_select != new_select) {
2928 if (old_select) {
2929 vnc_import_bgp_exterior_del_route(bgp, p,
2930 old_select);
2931 vnc_import_bgp_del_route(bgp, p, old_select);
2932 }
2933 if (new_select) {
2934 vnc_import_bgp_exterior_add_route(bgp, p,
2935 new_select);
2936 vnc_import_bgp_add_route(bgp, p, new_select);
2937 }
2938 }
2939 }
65efcfce
LB
2940#endif
2941
9bcb3eef 2942 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2943
2944 /* unicast routes must also be annouced to labeled-unicast update-groups
2945 */
2946 if (safi == SAFI_UNICAST)
9bcb3eef 2947 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2948 new_select);
2949
2950 /* FIB update. */
2951 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2952 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2953 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2954 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2955 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2956 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2957
2958 /* if this is an evpn imported type-5 prefix,
2959 * we need to withdraw the route first to clear
2960 * the nh neigh and the RMAC entry.
2961 */
2962 if (old_select &&
2963 is_route_parent_evpn(old_select))
2964 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2965
9bcb3eef 2966 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2967 } else {
d62a17ae 2968 /* Withdraw the route from the kernel. */
2969 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2970 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2971 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2972 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2973
568e10ca 2974 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2975 }
718e3744 2976 }
3064bf43 2977
9bcb3eef 2978 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2979 old_select);
5424b7ba 2980
d62a17ae 2981 /* Clear any route change flags. */
9bcb3eef 2982 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2983
18ee8310 2984 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2985 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2986 bgp_path_info_reap(dest, old_select);
d62a17ae 2987
9bcb3eef 2988 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2989 return;
718e3744 2990}
2991
f009ff26 2992/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2993int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2994{
9bcb3eef 2995 struct bgp_dest *dest;
f009ff26 2996 int cnt = 0;
2997 struct afi_safi_info *thread_info;
f009ff26 2998
56c226e7
DS
2999 if (bgp->gr_info[afi][safi].t_route_select) {
3000 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3001
3002 thread_info = THREAD_ARG(t);
3003 XFREE(MTYPE_TMP, thread_info);
f009ff26 3004 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3005 }
f009ff26 3006
3007 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3008 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3009 get_afi_safi_str(afi, safi, false),
26742171 3010 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3011 }
3012
3013 /* Process the route list */
6338d242
DS
3014 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3015 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3016 dest = bgp_route_next(dest)) {
3017 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3018 continue;
3019
3020 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3021 bgp->gr_info[afi][safi].gr_deferred--;
3022 bgp_process_main_one(bgp, dest, afi, safi);
3023 cnt++;
3024 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3025 bgp_dest_unlock_node(dest);
3026 break;
f009ff26 3027 }
f009ff26 3028 }
3029
9e3b51a7 3030 /* Send EOR message when all routes are processed */
6338d242 3031 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3032 bgp_send_delayed_eor(bgp);
8c48b3b6 3033 /* Send route processing complete message to RIB */
3034 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3035 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3036 return 0;
9e3b51a7 3037 }
f009ff26 3038
3039 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3040
3041 thread_info->afi = afi;
3042 thread_info->safi = safi;
3043 thread_info->bgp = bgp;
3044
3045 /* If there are more routes to be processed, start the
3046 * selection timer
3047 */
3048 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3049 BGP_ROUTE_SELECT_DELAY,
3050 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3051 return 0;
3052}
3053
aac24838 3054static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3055{
aac24838
JB
3056 struct bgp_process_queue *pqnode = data;
3057 struct bgp *bgp = pqnode->bgp;
d62a17ae 3058 struct bgp_table *table;
9bcb3eef 3059 struct bgp_dest *dest;
aac24838
JB
3060
3061 /* eoiu marker */
3062 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3063 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3064 /* should always have dedicated wq call */
3065 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3066 return WQ_SUCCESS;
3067 }
3068
ac021f40 3069 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3070 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3071 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3072 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3073 table = bgp_dest_table(dest);
3074 /* note, new DESTs may be added as part of processing */
3075 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3076
9bcb3eef 3077 bgp_dest_unlock_node(dest);
d62a17ae 3078 bgp_table_unlock(table);
3079 }
aac24838
JB
3080
3081 return WQ_SUCCESS;
3082}
3083
3084static void bgp_processq_del(struct work_queue *wq, void *data)
3085{
3086 struct bgp_process_queue *pqnode = data;
3087
3088 bgp_unlock(pqnode->bgp);
3089
3090 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3091}
3092
b6c386bb 3093void bgp_process_queue_init(struct bgp *bgp)
200df115 3094{
b6c386bb
DS
3095 if (!bgp->process_queue) {
3096 char name[BUFSIZ];
3097
3098 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3099 bgp->process_queue = work_queue_new(bm->master, name);
3100 }
3101
3102 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3103 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3104 bgp->process_queue->spec.max_retries = 0;
3105 bgp->process_queue->spec.hold = 50;
d62a17ae 3106 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3107 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3108}
3109
cfe8d15a 3110static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3111{
3112 struct bgp_process_queue *pqnode;
3113
a4d82a8a
PZ
3114 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3115 sizeof(struct bgp_process_queue));
aac24838
JB
3116
3117 /* unlocked in bgp_processq_del */
3118 pqnode->bgp = bgp_lock(bgp);
3119 STAILQ_INIT(&pqnode->pqueue);
3120
aac24838
JB
3121 return pqnode;
3122}
3123
9bcb3eef 3124void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3125{
aac24838 3126#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3127 struct work_queue *wq = bgp->process_queue;
d62a17ae 3128 struct bgp_process_queue *pqnode;
cfe8d15a 3129 int pqnode_reuse = 0;
495f0b13 3130
d62a17ae 3131 /* already scheduled for processing? */
9bcb3eef 3132 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3133 return;
2e02b9b2 3134
f009ff26 3135 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3136 * the workqueue
3137 */
9bcb3eef 3138 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3139 if (BGP_DEBUG(update, UPDATE_OUT))
3140 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3141 dest);
f009ff26 3142 return;
3143 }
3144
46aeabed
LS
3145 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3146 if (BGP_DEBUG(update, UPDATE_OUT))
3147 zlog_debug(
3148 "Soft reconfigure table in progress for route %p",
3149 dest);
3150 return;
3151 }
3152
aac24838 3153 if (wq == NULL)
d62a17ae 3154 return;
3155
aac24838 3156 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3157 limit only if is from the same BGP view and it's not an EOIU marker
3158 */
aac24838
JB
3159 if (work_queue_item_count(wq)) {
3160 struct work_queue_item *item = work_queue_last_item(wq);
3161 pqnode = item->data;
228da428 3162
a4d82a8a
PZ
3163 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3164 || pqnode->bgp != bgp
3165 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3166 pqnode = bgp_processq_alloc(bgp);
3167 else
3168 pqnode_reuse = 1;
aac24838 3169 } else
cfe8d15a 3170 pqnode = bgp_processq_alloc(bgp);
aac24838 3171 /* all unlocked in bgp_process_wq */
9bcb3eef 3172 bgp_table_lock(bgp_dest_table(dest));
aac24838 3173
9bcb3eef
DS
3174 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3175 bgp_dest_lock_node(dest);
aac24838 3176
60466a63 3177 /* can't be enqueued twice */
9bcb3eef
DS
3178 assert(STAILQ_NEXT(dest, pq) == NULL);
3179 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3180 pqnode->queued++;
3181
cfe8d15a
LB
3182 if (!pqnode_reuse)
3183 work_queue_add(wq, pqnode);
3184
d62a17ae 3185 return;
fee0f4c6 3186}
0a486e5f 3187
d62a17ae 3188void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3189{
d62a17ae 3190 struct bgp_process_queue *pqnode;
cb1faec9 3191
b6c386bb 3192 if (bgp->process_queue == NULL)
d62a17ae 3193 return;
2e02b9b2 3194
cfe8d15a 3195 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3196
aac24838 3197 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3198 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3199}
3200
d62a17ae 3201static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3202{
d62a17ae 3203 struct peer *peer;
0a486e5f 3204
d62a17ae 3205 peer = THREAD_ARG(thread);
3206 peer->t_pmax_restart = NULL;
0a486e5f 3207
d62a17ae 3208 if (bgp_debug_neighbor_events(peer))
3209 zlog_debug(
3210 "%s Maximum-prefix restart timer expired, restore peering",
3211 peer->host);
0a486e5f 3212
a9bafa95 3213 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3214 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3215
d62a17ae 3216 return 0;
0a486e5f 3217}
3218
9cbd06e0
DA
3219static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3220 safi_t safi)
3221{
3222 uint32_t count = 0;
f41b0459 3223 bool filtered = false;
9cbd06e0
DA
3224 struct bgp_dest *dest;
3225 struct bgp_adj_in *ain;
40bb2ccf 3226 struct attr attr = {};
9cbd06e0
DA
3227 struct bgp_table *table = peer->bgp->rib[afi][safi];
3228
3229 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3230 for (ain = dest->adj_in; ain; ain = ain->next) {
3231 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3232
3233 attr = *ain->attr;
9cbd06e0
DA
3234
3235 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3236 == FILTER_DENY)
f41b0459
DA
3237 filtered = true;
3238
3239 if (bgp_input_modifier(
3240 peer, rn_p, &attr, afi, safi,
3241 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3242 NULL, 0, NULL)
3243 == RMAP_DENY)
3244 filtered = true;
3245
3246 if (filtered)
9cbd06e0 3247 count++;
f41b0459
DA
3248
3249 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3250 }
3251 }
3252
3253 return count;
3254}
3255
3dc339cd
DA
3256bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3257 int always)
718e3744 3258{
d62a17ae 3259 iana_afi_t pkt_afi;
5c525538 3260 iana_safi_t pkt_safi;
9cbd06e0
DA
3261 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3262 PEER_FLAG_MAX_PREFIX_FORCE))
3263 ? bgp_filtered_routes_count(peer, afi, safi)
3264 + peer->pcount[afi][safi]
3265 : peer->pcount[afi][safi];
9cabb64b 3266
d62a17ae 3267 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3268 return false;
e0701b79 3269
9cbd06e0 3270 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3271 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3272 PEER_STATUS_PREFIX_LIMIT)
3273 && !always)
3dc339cd 3274 return false;
e0701b79 3275
d62a17ae 3276 zlog_info(
6cde4b45 3277 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3278 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3279 peer->pmax[afi][safi]);
d62a17ae 3280 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3281
3282 if (CHECK_FLAG(peer->af_flags[afi][safi],
3283 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3284 return false;
d62a17ae 3285
3286 /* Convert AFI, SAFI to values for packet. */
3287 pkt_afi = afi_int2iana(afi);
3288 pkt_safi = safi_int2iana(safi);
3289 {
d7c0a89a 3290 uint8_t ndata[7];
d62a17ae 3291
3292 ndata[0] = (pkt_afi >> 8);
3293 ndata[1] = pkt_afi;
3294 ndata[2] = pkt_safi;
3295 ndata[3] = (peer->pmax[afi][safi] >> 24);
3296 ndata[4] = (peer->pmax[afi][safi] >> 16);
3297 ndata[5] = (peer->pmax[afi][safi] >> 8);
3298 ndata[6] = (peer->pmax[afi][safi]);
3299
3300 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3301 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3302 BGP_NOTIFY_CEASE_MAX_PREFIX,
3303 ndata, 7);
3304 }
3305
3306 /* Dynamic peers will just close their connection. */
3307 if (peer_dynamic_neighbor(peer))
3dc339cd 3308 return true;
d62a17ae 3309
3310 /* restart timer start */
3311 if (peer->pmax_restart[afi][safi]) {
3312 peer->v_pmax_restart =
3313 peer->pmax_restart[afi][safi] * 60;
3314
3315 if (bgp_debug_neighbor_events(peer))
3316 zlog_debug(
3317 "%s Maximum-prefix restart timer started for %d secs",
3318 peer->host, peer->v_pmax_restart);
3319
3320 BGP_TIMER_ON(peer->t_pmax_restart,
3321 bgp_maximum_prefix_restart_timer,
3322 peer->v_pmax_restart);
3323 }
3324
3dc339cd 3325 return true;
d62a17ae 3326 } else
3327 UNSET_FLAG(peer->af_sflags[afi][safi],
3328 PEER_STATUS_PREFIX_LIMIT);
3329
b1823b69
DS
3330 if (pcount
3331 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3332 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3333 PEER_STATUS_PREFIX_THRESHOLD)
3334 && !always)
3dc339cd 3335 return false;
d62a17ae 3336
3337 zlog_info(
6cde4b45 3338 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3339 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3340 peer->pmax[afi][safi]);
d62a17ae 3341 SET_FLAG(peer->af_sflags[afi][safi],
3342 PEER_STATUS_PREFIX_THRESHOLD);
3343 } else
3344 UNSET_FLAG(peer->af_sflags[afi][safi],
3345 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3346 return false;
718e3744 3347}
3348
b40d939b 3349/* Unconditionally remove the route from the RIB, without taking
3350 * damping into consideration (eg, because the session went down)
3351 */
9bcb3eef 3352void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3353 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3354{
f009ff26 3355
3356 struct bgp *bgp = NULL;
3357 bool delete_route = false;
3358
9bcb3eef
DS
3359 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3360 safi);
d62a17ae 3361
f009ff26 3362 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3363 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3364
f009ff26 3365 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3366 * flag
3367 */
3368 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3369 delete_route = true;
9bcb3eef 3370 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3371 delete_route = true;
f009ff26 3372 if (delete_route) {
9bcb3eef
DS
3373 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3374 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3375 bgp = pi->peer->bgp;
26742171 3376 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3377 }
3378 }
3379 }
4a11bf2c 3380
9bcb3eef
DS
3381 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3382 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3383}
3384
9bcb3eef 3385static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3386 struct peer *peer, afi_t afi, safi_t safi,
3387 struct prefix_rd *prd)
3388{
9bcb3eef 3389 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3390
d62a17ae 3391 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3392 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3393 */
b4f7f45b
IR
3394 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3395 && peer->sort == BGP_PEER_EBGP)
3396 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3397 == BGP_DAMP_SUPPRESSED) {
3398 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3399 safi);
3400 return;
d62a17ae 3401 }
3402
49e5a4a0 3403#ifdef ENABLE_BGP_VNC
d62a17ae 3404 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3405 struct bgp_dest *pdest = NULL;
d62a17ae 3406 struct bgp_table *table = NULL;
3407
9bcb3eef
DS
3408 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3409 (struct prefix *)prd);
3410 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3411 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3412
3413 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3414 peer->bgp, prd, table, p, pi);
d62a17ae 3415 }
9bcb3eef 3416 bgp_dest_unlock_node(pdest);
d62a17ae 3417 }
3418 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3419 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3420
b54892e0
DS
3421 vnc_import_bgp_del_route(peer->bgp, p, pi);
3422 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3423 }
65efcfce 3424 }
d62a17ae 3425#endif
128ea8ab 3426
d62a17ae 3427 /* If this is an EVPN route, process for un-import. */
3428 if (safi == SAFI_EVPN)
b54892e0 3429 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3430
9bcb3eef 3431 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3432}
3433
4b7e6066
DS
3434struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3435 struct peer *peer, struct attr *attr,
9bcb3eef 3436 struct bgp_dest *dest)
fb018d25 3437{
4b7e6066 3438 struct bgp_path_info *new;
fb018d25 3439
d62a17ae 3440 /* Make new BGP info. */
4b7e6066 3441 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3442 new->type = type;
3443 new->instance = instance;
3444 new->sub_type = sub_type;
3445 new->peer = peer;
3446 new->attr = attr;
3447 new->uptime = bgp_clock();
9bcb3eef 3448 new->net = dest;
d62a17ae 3449 return new;
fb018d25
DS
3450}
3451
40381db7 3452static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3453 union gw_addr *gw_ip)
3454{
6c924775
DS
3455 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3456 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3457 union {
0a50c248 3458 esi_t esi;
11ebf4ed
DS
3459 union gw_addr ip;
3460 } temp;
d62a17ae 3461
3462 if (afi != AFI_L2VPN)
3463 return true;
11ebf4ed 3464
6c924775 3465 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3466
3467 if (gw_ip == NULL) {
3468 memset(&temp, 0, sizeof(temp));
40381db7 3469 path_gw_ip_remote = &temp.ip;
11ebf4ed 3470 } else
40381db7 3471 path_gw_ip_remote = gw_ip;
11ebf4ed 3472
6c924775 3473 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3474}
3475
c265ee22 3476/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3477bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3478 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3479 struct bgp_dest *dest)
d62a17ae 3480{
2dbe3fa9 3481 bool ret = false;
b099a5c8
DA
3482 bool is_bgp_static_route =
3483 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3484 : false;
d62a17ae 3485
e8442016
DS
3486 /*
3487 * Only validated for unicast and multicast currently.
3488 * Also valid for EVPN where the nexthop is an IP address.
3489 * If we are a bgp static route being checked then there is
3490 * no need to check to see if the nexthop is martian as
3491 * that it should be ok.
3492 */
3493 if (is_bgp_static_route ||
3494 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3495 return false;
d62a17ae 3496
3497 /* If NEXT_HOP is present, validate it. */
3498 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3499 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3500 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3501 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3502 return true;
d62a17ae 3503 }
c265ee22 3504
d62a17ae 3505 /* If MP_NEXTHOP is present, validate it. */
3506 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3507 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3508 * it is not an IPv6 link-local address.
0355b41d
DA
3509 *
3510 * If we receive an UPDATE with nexthop length set to 32 bytes
3511 * we shouldn't discard an UPDATE if it's set to (::).
3512 * The link-local (2st) is validated along the code path later.
d62a17ae 3513 */
3514 if (attr->mp_nexthop_len) {
3515 switch (attr->mp_nexthop_len) {
3516 case BGP_ATTR_NHLEN_IPV4:
3517 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3518 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3519 || IPV4_CLASS_DE(
3520 ntohl(attr->mp_nexthop_global_in.s_addr))
3521 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3522 dest));
d62a17ae 3523 break;
3524
3525 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3526 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3527 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3528 &attr->mp_nexthop_global)
d62a17ae 3529 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3530 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3531 &attr->mp_nexthop_global)
3532 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3533 dest));
d62a17ae 3534 break;
0355b41d
DA
3535 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3536 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3537 || IN6_IS_ADDR_MULTICAST(
3538 &attr->mp_nexthop_global)
3539 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3540 dest));
0355b41d 3541 break;
d62a17ae 3542
3543 default:
3dc339cd 3544 ret = true;
d62a17ae 3545 break;
3546 }
3547 }
c265ee22 3548
d62a17ae 3549 return ret;
3550}
3551
aade37d7 3552static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3553{
3554 struct community *old;
3555 struct community *new;
3556 struct community *merge;
aade37d7 3557 struct community *no_export;
2721dd61
DA
3558
3559 old = attr->community;
aade37d7 3560 no_export = community_str2com("no-export");
2721dd61 3561
b4efa101
DA
3562 assert(no_export);
3563
2721dd61 3564 if (old) {
aade37d7 3565 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3566
3567 if (!old->refcnt)
3568 community_free(&old);
3569
3570 new = community_uniq_sort(merge);
3571 community_free(&merge);
3572 } else {
aade37d7 3573 new = community_dup(no_export);
2721dd61
DA
3574 }
3575
aade37d7 3576 community_free(&no_export);
2721dd61
DA
3577
3578 attr->community = new;
3579 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3580}
3581
5a1ae2c2 3582int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3583 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3584 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3585 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3586 struct bgp_route_evpn *evpn)
d62a17ae 3587{
3588 int ret;
3589 int aspath_loop_count = 0;
9bcb3eef 3590 struct bgp_dest *dest;
d62a17ae 3591 struct bgp *bgp;
3592 struct attr new_attr;
3593 struct attr *attr_new;
40381db7 3594 struct bgp_path_info *pi;
4b7e6066
DS
3595 struct bgp_path_info *new;
3596 struct bgp_path_info_extra *extra;
d62a17ae 3597 const char *reason;
3598 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3599 int connected = 0;
3600 int do_loop_check = 1;
3601 int has_valid_label = 0;
7c312383 3602 afi_t nh_afi;
949b0f24 3603 uint8_t pi_type = 0;
3604 uint8_t pi_sub_type = 0;
9146341f 3605 bool force_evpn_import = false;
949b0f24 3606
c7bb4f00 3607 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3608 char pfxprint[PREFIX2STR_BUFFER];
3609
3610 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3611 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3612 afi, safi, attr);
6401252f
QY
3613 }
3614
49e5a4a0 3615#ifdef ENABLE_BGP_VNC
d62a17ae 3616 int vnc_implicit_withdraw = 0;
65efcfce 3617#endif
d62a17ae 3618 int same_attr = 0;
718e3744 3619
d62a17ae 3620 memset(&new_attr, 0, sizeof(struct attr));
3621 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3622 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3623
d62a17ae 3624 bgp = peer->bgp;
9bcb3eef 3625 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3626 /* TODO: Check to see if we can get rid of "is_valid_label" */
3627 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3628 has_valid_label = (num_labels > 0) ? 1 : 0;
3629 else
3630 has_valid_label = bgp_is_valid_label(label);
718e3744 3631
28f66de2
MS
3632 if (has_valid_label)
3633 assert(label != NULL);
3634
66ff6089
AD
3635 /* Update overlay index of the attribute */
3636 if (afi == AFI_L2VPN && evpn)
3637 memcpy(&attr->evpn_overlay, evpn,
3638 sizeof(struct bgp_route_evpn));
3639
d62a17ae 3640 /* When peer's soft reconfiguration enabled. Record input packet in
3641 Adj-RIBs-In. */
3642 if (!soft_reconfig
3643 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3644 && peer != bgp->peer_self)
9bcb3eef 3645 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3646
3647 /* Check previously received route. */
9bcb3eef 3648 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3649 if (pi->peer == peer && pi->type == type
3650 && pi->sub_type == sub_type
3651 && pi->addpath_rx_id == addpath_id)
d62a17ae 3652 break;
3653
3654 /* AS path local-as loop check. */
3655 if (peer->change_local_as) {
c4368918
DW
3656 if (peer->allowas_in[afi][safi])
3657 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3658 else if (!CHECK_FLAG(peer->flags,
3659 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3660 aspath_loop_count = 1;
3661
3662 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3663 > aspath_loop_count) {
b4d46cc9 3664 peer->stat_pfx_aspath_loop++;
692174a1 3665 reason = "as-path contains our own AS;";
d62a17ae 3666 goto filtered;
3667 }
718e3744 3668 }
718e3744 3669
d62a17ae 3670 /* If the peer is configured for "allowas-in origin" and the last ASN in
3671 * the
3672 * as-path is our ASN then we do not need to call aspath_loop_check
3673 */
3674 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3675 if (aspath_get_last_as(attr->aspath) == bgp->as)
3676 do_loop_check = 0;
3677
3678 /* AS path loop check. */
3679 if (do_loop_check) {
3680 if (aspath_loop_check(attr->aspath, bgp->as)
3681 > peer->allowas_in[afi][safi]
3682 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3683 && aspath_loop_check(attr->aspath, bgp->confed_id)
3684 > peer->allowas_in[afi][safi])) {
b4d46cc9 3685 peer->stat_pfx_aspath_loop++;
d62a17ae 3686 reason = "as-path contains our own AS;";
3687 goto filtered;
3688 }
3689 }
aac9ef6c 3690
d62a17ae 3691 /* Route reflector originator ID check. */
3692 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3693 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3694 peer->stat_pfx_originator_loop++;
d62a17ae 3695 reason = "originator is us;";
3696 goto filtered;
3697 }
718e3744 3698
d62a17ae 3699 /* Route reflector cluster ID check. */
3700 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3701 peer->stat_pfx_cluster_loop++;
d62a17ae 3702 reason = "reflected from the same cluster;";
3703 goto filtered;
3704 }
718e3744 3705
d62a17ae 3706 /* Apply incoming filter. */
3707 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3708 peer->stat_pfx_filter++;
d62a17ae 3709 reason = "filter;";
3710 goto filtered;
3711 }
718e3744 3712
a8b72dc6
DA
3713 /* RFC 8212 to prevent route leaks.
3714 * This specification intends to improve this situation by requiring the
3715 * explicit configuration of both BGP Import and Export Policies for any
3716 * External BGP (EBGP) session such as customers, peers, or
3717 * confederation boundaries for all enabled address families. Through
3718 * codification of the aforementioned requirement, operators will
3719 * benefit from consistent behavior across different BGP
3720 * implementations.
3721 */
1d3fdccf 3722 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3723 if (!bgp_inbound_policy_exists(peer,
3724 &peer->filter[afi][safi])) {
3725 reason = "inbound policy missing";
3726 goto filtered;
3727 }
3728
fb29348a
DA
3729 /* draft-ietf-idr-deprecate-as-set-confed-set
3730 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3731 * Eventually, This document (if approved) updates RFC 4271
3732 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3733 * and obsoletes RFC 6472.
3734 */
7f972cd8 3735 if (peer->bgp->reject_as_sets)
fb29348a
DA
3736 if (aspath_check_as_sets(attr->aspath)) {
3737 reason =
3738 "as-path contains AS_SET or AS_CONFED_SET type;";
3739 goto filtered;
3740 }
3741
6f4f49b2 3742 new_attr = *attr;
d62a17ae 3743
3744 /* Apply incoming route-map.
3745 * NB: new_attr may now contain newly allocated values from route-map
3746 * "set"
3747 * commands, so we need bgp_attr_flush in the error paths, until we
3748 * intern
3749 * the attr (which takes over the memory references) */
9bcb3eef
DS
3750 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3751 num_labels, dest)
3752 == RMAP_DENY) {
b4d46cc9 3753 peer->stat_pfx_filter++;
d62a17ae 3754 reason = "route-map;";
3755 bgp_attr_flush(&new_attr);
3756 goto filtered;
3757 }
718e3744 3758
05864da7 3759 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3760 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3761 /* remove from RIB previous entry */
3762 bgp_zebra_withdraw(p, pi, bgp, safi);
3763 }
3764
7f323236
DW
3765 if (peer->sort == BGP_PEER_EBGP) {
3766
2721dd61
DA
3767 /* rfc7999:
3768 * A BGP speaker receiving an announcement tagged with the
3769 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3770 * NO_EXPORT community as defined in RFC1997, or a
3771 * similar community, to prevent propagation of the
3772 * prefix outside the local AS. The community to prevent
3773 * propagation SHOULD be chosen according to the operator's
3774 * routing policy.
3775 */
3776 if (new_attr.community
3777 && community_include(new_attr.community,
3778 COMMUNITY_BLACKHOLE))
aade37d7 3779 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3780
a4d82a8a
PZ
3781 /* If we receive the graceful-shutdown community from an eBGP
3782 * peer we must lower local-preference */
3783 if (new_attr.community
3784 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3785 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3786 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3787
a4d82a8a
PZ
3788 /* If graceful-shutdown is configured then add the GSHUT
3789 * community to all paths received from eBGP peers */
637e5ba4 3790 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3791 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3792 }
3793
949b0f24 3794 if (pi) {
3795 pi_type = pi->type;
3796 pi_sub_type = pi->sub_type;
3797 }
3798
d62a17ae 3799 /* next hop check. */
a4d82a8a 3800 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3801 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3802 &new_attr, dest)) {
b4d46cc9 3803 peer->stat_pfx_nh_invalid++;
d62a17ae 3804 reason = "martian or self next-hop;";
3805 bgp_attr_flush(&new_attr);
3806 goto filtered;
3807 }
718e3744 3808
5c14a191 3809 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3810 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3811 reason = "self mac;";
3812 goto filtered;
3813 }
3814
a1b773e2
DS
3815 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3816 * condition :
3817 * Suppress fib is enabled
3818 * BGP_OPT_NO_FIB is not enabled
3819 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3820 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3821 */
3822 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3823 && (sub_type == BGP_ROUTE_NORMAL)
3824 && (!bgp_option_check(BGP_OPT_NO_FIB))
3825 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3826 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3827
d62a17ae 3828 attr_new = bgp_attr_intern(&new_attr);
3829
9cbd06e0
DA
3830 /* If maximum prefix count is configured and current prefix
3831 * count exeed it.
3832 */
3833 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3834 return -1;
3835
d62a17ae 3836 /* If the update is implicit withdraw. */
40381db7
DS
3837 if (pi) {
3838 pi->uptime = bgp_clock();
3839 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3840
9bcb3eef 3841 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3842
d62a17ae 3843 /* Same attribute comes in. */
40381db7 3844 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3845 && same_attr
d62a17ae 3846 && (!has_valid_label
40381db7 3847 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3848 num_labels * sizeof(mpls_label_t))
66ff6089 3849 == 0)) {
b4f7f45b
IR
3850 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3851 BGP_CONFIG_DAMPENING)
d62a17ae 3852 && peer->sort == BGP_PEER_EBGP
40381db7 3853 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3854 if (bgp_debug_update(peer, p, NULL, 1)) {
3855 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3856 afi, safi, prd, p, label,
3857 num_labels, addpath_id ? 1 : 0,
66ff6089 3858 addpath_id, evpn, pfx_buf,
a4d82a8a 3859 sizeof(pfx_buf));
d62a17ae 3860 zlog_debug("%s rcvd %s", peer->host,
3861 pfx_buf);
3862 }
3863
9bcb3eef 3864 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3865 != BGP_DAMP_SUPPRESSED) {
40381db7 3866 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3867 safi);
9bcb3eef 3868 bgp_process(bgp, dest, afi, safi);
d62a17ae 3869 }
3870 } else /* Duplicate - odd */
3871 {
3872 if (bgp_debug_update(peer, p, NULL, 1)) {
3873 if (!peer->rcvd_attr_printed) {
3874 zlog_debug(
3875 "%s rcvd UPDATE w/ attr: %s",
3876 peer->host,
3877 peer->rcvd_attr_str);
3878 peer->rcvd_attr_printed = 1;
3879 }
3880
3881 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3882 afi, safi, prd, p, label,
3883 num_labels, addpath_id ? 1 : 0,
66ff6089 3884 addpath_id, evpn, pfx_buf,
a4d82a8a 3885 sizeof(pfx_buf));
d62a17ae 3886 zlog_debug(
3887 "%s rcvd %s...duplicate ignored",
3888 peer->host, pfx_buf);
3889 }
3890
3891 /* graceful restart STALE flag unset. */
40381db7 3892 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3893 bgp_path_info_unset_flag(
9bcb3eef
DS
3894 dest, pi, BGP_PATH_STALE);
3895 bgp_dest_set_defer_flag(dest, false);
3896 bgp_process(bgp, dest, afi, safi);
d62a17ae 3897 }
3898 }
3899
9bcb3eef 3900 bgp_dest_unlock_node(dest);
d62a17ae 3901 bgp_attr_unintern(&attr_new);
3902
3903 return 0;
3904 }
718e3744 3905
d62a17ae 3906 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3907 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3908 if (bgp_debug_update(peer, p, NULL, 1)) {
3909 bgp_debug_rdpfxpath2str(
a4d82a8a 3910 afi, safi, prd, p, label, num_labels,
66ff6089 3911 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 3912 pfx_buf, sizeof(pfx_buf));
d62a17ae 3913 zlog_debug(
3914 "%s rcvd %s, flapped quicker than processing",
3915 peer->host, pfx_buf);
3916 }
3917
9bcb3eef 3918 bgp_path_info_restore(dest, pi);
9146341f 3919
3920 /*
3921 * If the BGP_PATH_REMOVED flag is set, then EVPN
3922 * routes would have been unimported already when a
3923 * prior BGP withdraw processing happened. Such routes
3924 * need to be imported again, so flag accordingly.
3925 */
3926 force_evpn_import = true;
d62a17ae 3927 }
718e3744 3928
d62a17ae 3929 /* Received Logging. */
3930 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3931 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3932 num_labels, addpath_id ? 1 : 0,
66ff6089 3933 addpath_id, evpn, pfx_buf,
a4d82a8a 3934 sizeof(pfx_buf));
d62a17ae 3935 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3936 }
718e3744 3937
d62a17ae 3938 /* graceful restart STALE flag unset. */
f009ff26 3939 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3940 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3941 bgp_dest_set_defer_flag(dest, false);
f009ff26 3942 }
d62a17ae 3943
3944 /* The attribute is changed. */
9bcb3eef 3945 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3946
3947 /* implicit withdraw, decrement aggregate and pcount here.
3948 * only if update is accepted, they'll increment below.
3949 */
40381db7 3950 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3951
3952 /* Update bgp route dampening information. */
b4f7f45b 3953 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 3954 && peer->sort == BGP_PEER_EBGP) {
3955 /* This is implicit withdraw so we should update
b4f7f45b
IR
3956 dampening
3957 information. */
40381db7 3958 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3959 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3960 }
49e5a4a0 3961#ifdef ENABLE_BGP_VNC
d62a17ae 3962 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3963 struct bgp_dest *pdest = NULL;
d62a17ae 3964 struct bgp_table *table = NULL;
3965
9bcb3eef
DS
3966 pdest = bgp_node_get(bgp->rib[afi][safi],
3967 (struct prefix *)prd);
3968 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3969 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3970
3971 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3972 bgp, prd, table, p, pi);
d62a17ae 3973 }
9bcb3eef 3974 bgp_dest_unlock_node(pdest);
d62a17ae 3975 }
3976 if ((afi == AFI_IP || afi == AFI_IP6)
3977 && (safi == SAFI_UNICAST)) {
40381db7 3978 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3979 /*
3980 * Implicit withdraw case.
3981 */
3982 ++vnc_implicit_withdraw;
40381db7
DS
3983 vnc_import_bgp_del_route(bgp, p, pi);
3984 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3985 }
3986 }
65efcfce 3987#endif
128ea8ab 3988
d62a17ae 3989 /* Special handling for EVPN update of an existing route. If the
3990 * extended community attribute has changed, we need to
3991 * un-import
3992 * the route using its existing extended community. It will be
3993 * subsequently processed for import with the new extended
3994 * community.
3995 */
6f8c9c11
PR
3996 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3997 && !same_attr) {
40381db7 3998 if ((pi->attr->flag
d62a17ae 3999 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4000 && (attr_new->flag
4001 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4002 int cmp;
4003
40381db7 4004 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4005 attr_new->ecommunity);
4006 if (!cmp) {
4007 if (bgp_debug_update(peer, p, NULL, 1))
4008 zlog_debug(
4009 "Change in EXT-COMM, existing %s new %s",
4010 ecommunity_str(
40381db7 4011 pi->attr->ecommunity),
d62a17ae 4012 ecommunity_str(
4013 attr_new->ecommunity));
6f8c9c11
PR
4014 if (safi == SAFI_EVPN)
4015 bgp_evpn_unimport_route(
4016 bgp, afi, safi, p, pi);
4017 else /* SAFI_MPLS_VPN */
4018 vpn_leak_to_vrf_withdraw(bgp,
4019 pi);
d62a17ae 4020 }
4021 }
4022 }
718e3744 4023
d62a17ae 4024 /* Update to new attribute. */
40381db7
DS
4025 bgp_attr_unintern(&pi->attr);
4026 pi->attr = attr_new;
d62a17ae 4027
4028 /* Update MPLS label */
4029 if (has_valid_label) {
40381db7 4030 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4031 if (extra->label != label) {
4032 memcpy(&extra->label, label,
dbd587da 4033 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4034 extra->num_labels = num_labels;
4035 }
b57ba6d2
MK
4036 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4037 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4038 }
718e3744 4039
e496b420
HS
4040 /* Update SRv6 SID */
4041 if (attr->srv6_l3vpn) {
4042 extra = bgp_path_info_extra_get(pi);
4043 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4044 sid_copy(&extra->sid[0],
4045 &attr->srv6_l3vpn->sid);
4046 extra->num_sids = 1;
4047 }
4048 } else if (attr->srv6_vpn) {
4049 extra = bgp_path_info_extra_get(pi);
4050 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4051 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4052 extra->num_sids = 1;
4053 }
4054 }
4055
49e5a4a0 4056#ifdef ENABLE_BGP_VNC
d62a17ae 4057 if ((afi == AFI_IP || afi == AFI_IP6)
4058 && (safi == SAFI_UNICAST)) {
4059 if (vnc_implicit_withdraw) {
4060 /*
4061 * Add back the route with its new attributes
4062 * (e.g., nexthop).
4063 * The route is still selected, until the route
4064 * selection
4065 * queued by bgp_process actually runs. We have
4066 * to make this
4067 * update to the VNC side immediately to avoid
4068 * racing against
4069 * configuration changes (e.g., route-map
4070 * changes) which
4071 * trigger re-importation of the entire RIB.
4072 */
40381db7
DS
4073 vnc_import_bgp_add_route(bgp, p, pi);
4074 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4075 }
4076 }
65efcfce
LB
4077#endif
4078
d62a17ae 4079 /* Update bgp route dampening information. */
b4f7f45b 4080 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4081 && peer->sort == BGP_PEER_EBGP) {
4082 /* Now we do normal update dampening. */
9bcb3eef 4083 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4084 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4085 bgp_dest_unlock_node(dest);
d62a17ae 4086 return 0;
4087 }
4088 }
128ea8ab 4089
d62a17ae 4090 /* Nexthop reachability check - for unicast and
4091 * labeled-unicast.. */
7c312383
AD
4092 if (((afi == AFI_IP || afi == AFI_IP6)
4093 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4094 || (safi == SAFI_EVPN &&
4095 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4096 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4097 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4098 && !CHECK_FLAG(peer->flags,
4099 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4100 && !CHECK_FLAG(bgp->flags,
4101 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4102 connected = 1;
4103 else
4104 connected = 0;
4105
960035b2
PZ
4106 struct bgp *bgp_nexthop = bgp;
4107
40381db7
DS
4108 if (pi->extra && pi->extra->bgp_orig)
4109 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4110
7c312383
AD
4111 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4112
4113 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4114 safi, pi, NULL, connected,
4115 p)
a4d82a8a 4116 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4117 bgp_path_info_set_flag(dest, pi,
4118 BGP_PATH_VALID);
d62a17ae 4119 else {
4120 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4121 zlog_debug("%s(%pI4): NH unresolved",
4122 __func__,
4123 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4124 }
9bcb3eef 4125 bgp_path_info_unset_flag(dest, pi,
18ee8310 4126 BGP_PATH_VALID);
d62a17ae 4127 }
4128 } else
9bcb3eef 4129 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4130
49e5a4a0 4131#ifdef ENABLE_BGP_VNC
d62a17ae 4132 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4133 struct bgp_dest *pdest = NULL;
d62a17ae 4134 struct bgp_table *table = NULL;
4135
9bcb3eef
DS
4136 pdest = bgp_node_get(bgp->rib[afi][safi],
4137 (struct prefix *)prd);
4138 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4139 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4140
4141 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4142 bgp, prd, table, p, pi);
d62a17ae 4143 }
9bcb3eef 4144 bgp_dest_unlock_node(pdest);
d62a17ae 4145 }
4146#endif
718e3744 4147
d62a17ae 4148 /* If this is an EVPN route and some attribute has changed,
9146341f 4149 * or we are explicitly told to perform a route import, process
d62a17ae 4150 * route for import. If the extended community has changed, we
4151 * would
4152 * have done the un-import earlier and the import would result
4153 * in the
4154 * route getting injected into appropriate L2 VNIs. If it is
4155 * just
4156 * some other attribute change, the import will result in
4157 * updating
4158 * the attributes for the route in the VNI(s).
4159 */
9146341f 4160 if (safi == SAFI_EVPN &&
4161 (!same_attr || force_evpn_import) &&
7c312383 4162 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4163 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4164
4165 /* Process change. */
40381db7 4166 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4167
9bcb3eef
DS
4168 bgp_process(bgp, dest, afi, safi);
4169 bgp_dest_unlock_node(dest);
558d1fec 4170
ddb5b488
PZ
4171 if (SAFI_UNICAST == safi
4172 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4173 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4174
40381db7 4175 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4176 }
4177 if ((SAFI_MPLS_VPN == safi)
4178 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4179
40381db7 4180 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4181 }
4182
49e5a4a0 4183#ifdef ENABLE_BGP_VNC
d62a17ae 4184 if (SAFI_MPLS_VPN == safi) {
4185 mpls_label_t label_decoded = decode_label(label);
28070ee3 4186
d62a17ae 4187 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4188 type, sub_type, &label_decoded);
4189 }
4190 if (SAFI_ENCAP == safi) {
4191 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4192 type, sub_type, NULL);
4193 }
28070ee3
PZ
4194#endif
4195
d62a17ae 4196 return 0;
4197 } // End of implicit withdraw
718e3744 4198
d62a17ae 4199 /* Received Logging. */
4200 if (bgp_debug_update(peer, p, NULL, 1)) {
4201 if (!peer->rcvd_attr_printed) {
4202 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4203 peer->rcvd_attr_str);
4204 peer->rcvd_attr_printed = 1;
4205 }
718e3744 4206
a4d82a8a 4207 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4208 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4209 pfx_buf, sizeof(pfx_buf));
d62a17ae 4210 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4211 }
718e3744 4212
d62a17ae 4213 /* Make new BGP info. */
9bcb3eef 4214 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4215
d62a17ae 4216 /* Update MPLS label */
4217 if (has_valid_label) {
18ee8310 4218 extra = bgp_path_info_extra_get(new);
8ba71050 4219 if (extra->label != label) {
dbd587da
QY
4220 memcpy(&extra->label, label,
4221 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4222 extra->num_labels = num_labels;
4223 }
b57ba6d2
MK
4224 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4225 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4226 }
718e3744 4227
e496b420
HS
4228 /* Update SRv6 SID */
4229 if (safi == SAFI_MPLS_VPN) {
4230 extra = bgp_path_info_extra_get(new);
4231 if (attr->srv6_l3vpn) {
4232 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4233 extra->num_sids = 1;
4234 } else if (attr->srv6_vpn) {
4235 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4236 extra->num_sids = 1;
4237 }
4238 }
4239
d62a17ae 4240 /* Nexthop reachability check. */
7c312383
AD
4241 if (((afi == AFI_IP || afi == AFI_IP6)
4242 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4243 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4244 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4245 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4246 && !CHECK_FLAG(peer->flags,
4247 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4248 && !CHECK_FLAG(bgp->flags,
4249 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4250 connected = 1;
4251 else
4252 connected = 0;
4253
7c312383
AD
4254 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4255
4053e952 4256 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4257 connected, p)
a4d82a8a 4258 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4259 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4260 else {
4261 if (BGP_DEBUG(nht, NHT)) {
4262 char buf1[INET6_ADDRSTRLEN];
4263 inet_ntop(AF_INET,
4264 (const void *)&attr_new->nexthop,
4265 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4266 zlog_debug("%s(%s): NH unresolved", __func__,
4267 buf1);
d62a17ae 4268 }
9bcb3eef 4269 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4270 }
4271 } else
9bcb3eef 4272 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4273
d62a17ae 4274 /* Addpath ID */
4275 new->addpath_rx_id = addpath_id;
4276
4277 /* Increment prefix */
4278 bgp_aggregate_increment(bgp, p, new, afi, safi);
4279
4280 /* Register new BGP information. */
9bcb3eef 4281 bgp_path_info_add(dest, new);
d62a17ae 4282
4283 /* route_node_get lock */
9bcb3eef 4284 bgp_dest_unlock_node(dest);
558d1fec 4285
49e5a4a0 4286#ifdef ENABLE_BGP_VNC
d62a17ae 4287 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4288 struct bgp_dest *pdest = NULL;
d62a17ae 4289 struct bgp_table *table = NULL;
4290
9bcb3eef
DS
4291 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4292 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4293 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4294
4295 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4296 bgp, prd, table, p, new);
4297 }
9bcb3eef 4298 bgp_dest_unlock_node(pdest);
d62a17ae 4299 }
65efcfce
LB
4300#endif
4301
d62a17ae 4302 /* If this is an EVPN route, process for import. */
7c312383 4303 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4304 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4305
9bcb3eef 4306 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4307
d62a17ae 4308 /* Process change. */
9bcb3eef 4309 bgp_process(bgp, dest, afi, safi);
718e3744 4310
ddb5b488
PZ
4311 if (SAFI_UNICAST == safi
4312 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4313 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4314 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4315 }
4316 if ((SAFI_MPLS_VPN == safi)
4317 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4318
4319 vpn_leak_to_vrf_update(bgp, new);
4320 }
49e5a4a0 4321#ifdef ENABLE_BGP_VNC
d62a17ae 4322 if (SAFI_MPLS_VPN == safi) {
4323 mpls_label_t label_decoded = decode_label(label);
28070ee3 4324
d62a17ae 4325 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4326 sub_type, &label_decoded);
4327 }
4328 if (SAFI_ENCAP == safi) {
4329 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4330 sub_type, NULL);
4331 }
28070ee3
PZ
4332#endif
4333
d62a17ae 4334 return 0;
718e3744 4335
d62a17ae 4336/* This BGP update is filtered. Log the reason then update BGP
4337 entry. */
4338filtered:
9bcb3eef 4339 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4340
d62a17ae 4341 if (bgp_debug_update(peer, p, NULL, 1)) {
4342 if (!peer->rcvd_attr_printed) {
4343 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4344 peer->rcvd_attr_str);
4345 peer->rcvd_attr_printed = 1;
4346 }
718e3744 4347
a4d82a8a 4348 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4349 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4350 pfx_buf, sizeof(pfx_buf));
d62a17ae 4351 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4352 peer->host, pfx_buf, reason);
4353 }
128ea8ab 4354
40381db7 4355 if (pi) {
d62a17ae 4356 /* If this is an EVPN route, un-import it as it is now filtered.
4357 */
4358 if (safi == SAFI_EVPN)
40381db7 4359 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4360
ddb5b488
PZ
4361 if (SAFI_UNICAST == safi
4362 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4363 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4364
40381db7 4365 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4366 }
4367 if ((SAFI_MPLS_VPN == safi)
4368 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4369
40381db7 4370 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4371 }
4372
9bcb3eef 4373 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4374 }
4375
9bcb3eef 4376 bgp_dest_unlock_node(dest);
558d1fec 4377
49e5a4a0 4378#ifdef ENABLE_BGP_VNC
d62a17ae 4379 /*
4380 * Filtered update is treated as an implicit withdrawal (see
4381 * bgp_rib_remove()
4382 * a few lines above)
4383 */
4384 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4385 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4386 0);
4387 }
97736e32
PZ
4388#endif
4389
d62a17ae 4390 return 0;
718e3744 4391}
4392
26a3ffd6 4393int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4394 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4395 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4396 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4397{
d62a17ae 4398 struct bgp *bgp;
4399 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4400 struct bgp_dest *dest;
40381db7 4401 struct bgp_path_info *pi;
718e3744 4402
49e5a4a0 4403#ifdef ENABLE_BGP_VNC
d62a17ae 4404 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4405 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4406 0);
4407 }
28070ee3
PZ
4408#endif
4409
d62a17ae 4410 bgp = peer->bgp;
4411
4412 /* Lookup node. */
9bcb3eef 4413 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4414
4415 /* If peer is soft reconfiguration enabled. Record input packet for
4416 * further calculation.
4417 *
4418 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4419 * routes that are filtered. This tanks out Quagga RS pretty badly due
4420 * to
4421 * the iteration over all RS clients.
4422 * Since we need to remove the entry from adj_in anyway, do that first
4423 * and
4424 * if there was no entry, we don't need to do anything more.
4425 */
4426 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4427 && peer != bgp->peer_self)
9bcb3eef 4428 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4429 peer->stat_pfx_dup_withdraw++;
4430
d62a17ae 4431 if (bgp_debug_update(peer, p, NULL, 1)) {
4432 bgp_debug_rdpfxpath2str(
a4d82a8a 4433 afi, safi, prd, p, label, num_labels,
6c995628
AD
4434 addpath_id ? 1 : 0, addpath_id, NULL,
4435 pfx_buf, sizeof(pfx_buf));
d62a17ae 4436 zlog_debug(
4437 "%s withdrawing route %s not in adj-in",
4438 peer->host, pfx_buf);
4439 }
9bcb3eef 4440 bgp_dest_unlock_node(dest);
d62a17ae 4441 return 0;
4442 }
cd808e74 4443
d62a17ae 4444 /* Lookup withdrawn route. */
9bcb3eef 4445 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4446 if (pi->peer == peer && pi->type == type
4447 && pi->sub_type == sub_type
4448 && pi->addpath_rx_id == addpath_id)
d62a17ae 4449 break;
4450
4451 /* Logging. */
4452 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4453 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4454 addpath_id ? 1 : 0, addpath_id, NULL,
4455 pfx_buf, sizeof(pfx_buf));
d62a17ae 4456 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4457 pfx_buf);
4458 }
718e3744 4459
d62a17ae 4460 /* Withdraw specified route from routing table. */
40381db7 4461 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4462 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4463 if (SAFI_UNICAST == safi
4464 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4465 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4466 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4467 }
4468 if ((SAFI_MPLS_VPN == safi)
4469 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4470
40381db7 4471 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4472 }
4473 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4474 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4475 addpath_id ? 1 : 0, addpath_id, NULL,
4476 pfx_buf, sizeof(pfx_buf));
d62a17ae 4477 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4478 }
718e3744 4479
d62a17ae 4480 /* Unlock bgp_node_get() lock. */
9bcb3eef 4481 bgp_dest_unlock_node(dest);
d62a17ae 4482
4483 return 0;
718e3744 4484}
6b0655a2 4485
d62a17ae 4486void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4487 int withdraw)
718e3744 4488{
d62a17ae 4489 struct update_subgroup *subgrp;
4490 subgrp = peer_subgroup(peer, afi, safi);
4491 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4492}
6182d65b 4493
718e3744 4494
3f9c7369
DS
4495/*
4496 * bgp_stop_announce_route_timer
4497 */
d62a17ae 4498void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4499{
d62a17ae 4500 if (!paf->t_announce_route)
4501 return;
4502
50478845 4503 thread_cancel(&paf->t_announce_route);
718e3744 4504}
6b0655a2 4505
3f9c7369
DS
4506/*
4507 * bgp_announce_route_timer_expired
4508 *
4509 * Callback that is invoked when the route announcement timer for a
4510 * peer_af expires.
4511 */
d62a17ae 4512static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4513{
d62a17ae 4514 struct peer_af *paf;
4515 struct peer *peer;
558d1fec 4516
d62a17ae 4517 paf = THREAD_ARG(t);
4518 peer = paf->peer;
718e3744 4519
feb17238 4520 if (!peer_established(peer))
d62a17ae 4521 return 0;
3f9c7369 4522
d62a17ae 4523 if (!peer->afc_nego[paf->afi][paf->safi])
4524 return 0;
3f9c7369 4525
d62a17ae 4526 peer_af_announce_route(paf, 1);
c5aec50b
MK
4527
4528 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4529 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4530
d62a17ae 4531 return 0;
718e3744 4532}
4533
3f9c7369
DS
4534/*
4535 * bgp_announce_route
4536 *
4537 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4538 */
d62a17ae 4539void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4540{
4541 struct peer_af *paf;
4542 struct update_subgroup *subgrp;
4543
4544 paf = peer_af_find(peer, afi, safi);
4545 if (!paf)
4546 return;
4547 subgrp = PAF_SUBGRP(paf);
4548
4549 /*
4550 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4551 * or a refresh has already been triggered.
4552 */
4553 if (!subgrp || paf->t_announce_route)
4554 return;
4555
4556 /*
4557 * Start a timer to stagger/delay the announce. This serves
4558 * two purposes - announcement can potentially be combined for
4559 * multiple peers and the announcement doesn't happen in the
4560 * vty context.
4561 */
4562 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4563 (subgrp->peer_count == 1)
4564 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4565 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4566 &paf->t_announce_route);
3f9c7369
DS
4567}
4568
4569/*
4570 * Announce routes from all AF tables to a peer.
4571 *
4572 * This should ONLY be called when there is a need to refresh the
4573 * routes to the peer based on a policy change for this peer alone
4574 * or a route refresh request received from the peer.
4575 * The operation will result in splitting the peer from its existing
4576 * subgroups and putting it in new subgroups.
4577 */
d62a17ae 4578void bgp_announce_route_all(struct peer *peer)
718e3744 4579{
d62a17ae 4580 afi_t afi;
4581 safi_t safi;
4582
05c7a1cc
QY
4583 FOREACH_AFI_SAFI (afi, safi)
4584 bgp_announce_route(peer, afi, safi);
718e3744 4585}
6b0655a2 4586
46aeabed
LS
4587/* Flag or unflag bgp_dest to determine whether it should be treated by
4588 * bgp_soft_reconfig_table_task.
4589 * Flag if flag is true. Unflag if flag is false.
4590 */
4591static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4592{
4593 struct bgp_dest *dest;
4594 struct bgp_adj_in *ain;
4595
4596 if (!table)
4597 return;
4598
4599 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4600 for (ain = dest->adj_in; ain; ain = ain->next) {
4601 if (ain->peer != NULL)
4602 break;
4603 }
4604 if (flag && ain != NULL && ain->peer != NULL)
4605 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4606 else
4607 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4608 }
4609}
4610
4611static int bgp_soft_reconfig_table_update(struct peer *peer,
4612 struct bgp_dest *dest,
4613 struct bgp_adj_in *ain, afi_t afi,
4614 safi_t safi, struct prefix_rd *prd)
4615{
4616 struct bgp_path_info *pi;
4617 uint32_t num_labels = 0;
4618 mpls_label_t *label_pnt = NULL;
4619 struct bgp_route_evpn evpn;
4620
4621 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4622 if (pi->peer == peer)
4623 break;
4624
4625 if (pi && pi->extra)
4626 num_labels = pi->extra->num_labels;
4627 if (num_labels)
4628 label_pnt = &pi->extra->label[0];
4629 if (pi)
4630 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4631 sizeof(evpn));
4632 else
4633 memset(&evpn, 0, sizeof(evpn));
4634
4635 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4636 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4637 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4638 &evpn);
4639}
4640
d62a17ae 4641static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4642 struct bgp_table *table,
4643 struct prefix_rd *prd)
718e3744 4644{
d62a17ae 4645 int ret;
9bcb3eef 4646 struct bgp_dest *dest;
d62a17ae 4647 struct bgp_adj_in *ain;
718e3744 4648
d62a17ae 4649 if (!table)
4650 table = peer->bgp->rib[afi][safi];
718e3744 4651
9bcb3eef
DS
4652 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4653 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4654 if (ain->peer != peer)
4655 continue;
8692c506 4656
46aeabed
LS
4657 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4658 afi, safi, prd);
ea47320b
DL
4659
4660 if (ret < 0) {
9bcb3eef 4661 bgp_dest_unlock_node(dest);
ea47320b 4662 return;
d62a17ae 4663 }
4664 }
718e3744 4665}
4666
46aeabed
LS
4667/* Do soft reconfig table per bgp table.
4668 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4669 * when BGP_NODE_SOFT_RECONFIG is set,
4670 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4671 * Schedule a new thread to continue the job.
4672 * Without splitting the full job into several part,
4673 * vtysh waits for the job to finish before responding to a BGP command
4674 */
4675static int bgp_soft_reconfig_table_task(struct thread *thread)
4676{
4677 uint32_t iter, max_iter;
4678 int ret;
4679 struct bgp_dest *dest;
4680 struct bgp_adj_in *ain;
4681 struct peer *peer;
4682 struct bgp_table *table;
4683 struct prefix_rd *prd;
4684 struct listnode *node, *nnode;
4685
4686 table = THREAD_ARG(thread);
4687 prd = NULL;
4688
4689 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4690 if (table->soft_reconfig_init) {
4691 /* first call of the function with a new srta structure.
4692 * Don't do any treatment this time on nodes
4693 * in order vtysh to respond quickly
4694 */
4695 max_iter = 0;
4696 }
4697
4698 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4699 dest = bgp_route_next(dest)) {
4700 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4701 continue;
4702
4703 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4704
4705 for (ain = dest->adj_in; ain; ain = ain->next) {
4706 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4707 nnode, peer)) {
4708 if (ain->peer != peer)
4709 continue;
4710
4711 ret = bgp_soft_reconfig_table_update(
4712 peer, dest, ain, table->afi,
4713 table->safi, prd);
4714 iter++;
4715
4716 if (ret < 0) {
4717 bgp_dest_unlock_node(dest);
4718 listnode_delete(
4719 table->soft_reconfig_peers,
4720 peer);
4721 bgp_announce_route(peer, table->afi,
4722 table->safi);
4723 if (list_isempty(
4724 table->soft_reconfig_peers)) {
4725 list_delete(
4726 &table->soft_reconfig_peers);
4727 bgp_soft_reconfig_table_flag(
4728 table, false);
4729 return 0;
4730 }
4731 }
4732 }
4733 }
4734 }
4735
4736 /* we're either starting the initial iteration,
4737 * or we're going to continue an ongoing iteration
4738 */
4739 if (dest || table->soft_reconfig_init) {
4740 table->soft_reconfig_init = false;
4741 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4742 table, 0, &table->soft_reconfig_thread);
4743 return 0;
4744 }
4745 /* we're done, clean up the background iteration context info and
4746 schedule route annoucement
4747 */
4748 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4749 listnode_delete(table->soft_reconfig_peers, peer);
4750 bgp_announce_route(peer, table->afi, table->safi);
4751 }
4752
4753 list_delete(&table->soft_reconfig_peers);
4754
4755 return 0;
4756}
4757
4758
4759/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4760 * and peer.
4761 * - bgp cannot be NULL
4762 * - if table and peer are NULL, cancel all threads within the bgp instance
4763 * - if table is NULL and peer is not,
4764 * remove peer in all threads within the bgp instance
4765 * - if peer is NULL, cancel all threads matching table within the bgp instance
4766 */
4767void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4768 const struct bgp_table *table,
4769 const struct peer *peer)
4770{
4771 struct peer *npeer;
4772 struct listnode *node, *nnode;
4773 int afi, safi;
4774 struct bgp_table *ntable;
4775
4776 if (!bgp)
4777 return;
4778
4779 FOREACH_AFI_SAFI (afi, safi) {
4780 ntable = bgp->rib[afi][safi];
4781 if (!ntable)
4782 continue;
4783 if (table && table != ntable)
4784 continue;
4785
4786 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4787 npeer)) {
4788 if (peer && peer != npeer)
4789 continue;
4790 listnode_delete(ntable->soft_reconfig_peers, npeer);
4791 }
4792
4793 if (!ntable->soft_reconfig_peers
4794 || !list_isempty(ntable->soft_reconfig_peers))
4795 continue;
4796
4797 list_delete(&ntable->soft_reconfig_peers);
4798 bgp_soft_reconfig_table_flag(ntable, false);
4799 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4800 }
4801}
4802
d62a17ae 4803void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4804{
9bcb3eef 4805 struct bgp_dest *dest;
d62a17ae 4806 struct bgp_table *table;
46aeabed
LS
4807 struct listnode *node, *nnode;
4808 struct peer *npeer;
4809 struct peer_af *paf;
718e3744 4810
feb17238 4811 if (!peer_established(peer))
d62a17ae 4812 return;
718e3744 4813
d62a17ae 4814 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
4815 && (safi != SAFI_EVPN)) {
4816 table = peer->bgp->rib[afi][safi];
4817 if (!table)
4818 return;
4819
4820 table->soft_reconfig_init = true;
4821
4822 if (!table->soft_reconfig_peers)
4823 table->soft_reconfig_peers = list_new();
4824 npeer = NULL;
4825 /* add peer to the table soft_reconfig_peers if not already
4826 * there
4827 */
4828 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
4829 npeer)) {
4830 if (peer == npeer)
4831 break;
4832 }
4833 if (peer != npeer)
4834 listnode_add(table->soft_reconfig_peers, peer);
4835
4836 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4837 * on table would start back at the beginning.
4838 */
4839 bgp_soft_reconfig_table_flag(table, true);
4840
4841 if (!table->soft_reconfig_thread)
4842 thread_add_event(bm->master,
4843 bgp_soft_reconfig_table_task, table, 0,
4844 &table->soft_reconfig_thread);
4845 /* Cancel bgp_announce_route_timer_expired threads.
4846 * bgp_announce_route_timer_expired threads have been scheduled
4847 * to announce routes as soon as the soft_reconfigure process
4848 * finishes.
4849 * In this case, soft_reconfigure is also scheduled by using
4850 * a thread but is planned after the
4851 * bgp_announce_route_timer_expired threads. It means that,
4852 * without cancelling the threads, the route announcement task
4853 * would run before the soft reconfiguration one. That would
4854 * useless and would block vtysh during several seconds. Route
4855 * announcements are rescheduled as soon as the soft_reconfigure
4856 * process finishes.
4857 */
4858 paf = peer_af_find(peer, afi, safi);
4859 if (paf)
4860 bgp_stop_announce_route_timer(paf);
4861 } else
9bcb3eef
DS
4862 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4863 dest = bgp_route_next(dest)) {
4864 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4865
b54892e0
DS
4866 if (table == NULL)
4867 continue;
8692c506 4868
9bcb3eef 4869 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4870 struct prefix_rd prd;
4871
4872 prd.family = AF_UNSPEC;
4873 prd.prefixlen = 64;
4874 memcpy(&prd.val, p->u.val, 8);
4875
4876 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4877 }
718e3744 4878}
6b0655a2 4879
228da428 4880
d62a17ae 4881struct bgp_clear_node_queue {
9bcb3eef 4882 struct bgp_dest *dest;
228da428
CC
4883};
4884
d62a17ae 4885static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4886{
d62a17ae 4887 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4888 struct bgp_dest *dest = cnq->dest;
d62a17ae 4889 struct peer *peer = wq->spec.data;
40381db7 4890 struct bgp_path_info *pi;
3103e8d2 4891 struct bgp *bgp;
9bcb3eef
DS
4892 afi_t afi = bgp_dest_table(dest)->afi;
4893 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4894
9bcb3eef 4895 assert(dest && peer);
3103e8d2 4896 bgp = peer->bgp;
d62a17ae 4897
4898 /* It is possible that we have multiple paths for a prefix from a peer
4899 * if that peer is using AddPath.
4900 */
9bcb3eef 4901 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4902 if (pi->peer != peer)
ea47320b
DL
4903 continue;
4904
4905 /* graceful restart STALE flag set. */
9af52ccf
DA
4906 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4907 && peer->nsf[afi][safi])
4908 || CHECK_FLAG(peer->af_sflags[afi][safi],
4909 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4910 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4911 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4912 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4913 else {
4914 /* If this is an EVPN route, process for
4915 * un-import. */
4916 if (safi == SAFI_EVPN)
9bcb3eef
DS
4917 bgp_evpn_unimport_route(
4918 bgp, afi, safi,
4919 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4920 /* Handle withdraw for VRF route-leaking and L3VPN */
4921 if (SAFI_UNICAST == safi
4922 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4923 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4924 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4925 bgp, pi);
960035b2 4926 }
3103e8d2 4927 if (SAFI_MPLS_VPN == safi &&
960035b2 4928 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4929 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4930 }
3103e8d2 4931
9bcb3eef 4932 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4933 }
ea47320b 4934 }
d62a17ae 4935 return WQ_SUCCESS;
200df115 4936}
4937
d62a17ae 4938static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4939{
d62a17ae 4940 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4941 struct bgp_dest *dest = cnq->dest;
4942 struct bgp_table *table = bgp_dest_table(dest);
228da428 4943
9bcb3eef 4944 bgp_dest_unlock_node(dest);
d62a17ae 4945 bgp_table_unlock(table);
4946 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4947}
4948
d62a17ae 4949static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4950{
d62a17ae 4951 struct peer *peer = wq->spec.data;
64e580a7 4952
d62a17ae 4953 /* Tickle FSM to start moving again */
4954 BGP_EVENT_ADD(peer, Clearing_Completed);
4955
4956 peer_unlock(peer); /* bgp_clear_route */
200df115 4957}
718e3744 4958
d62a17ae 4959static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4960{
d62a17ae 4961 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4962
4963 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4964#undef CLEAR_QUEUE_NAME_LEN
4965
0ce1ca80 4966 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4967 peer->clear_node_queue->spec.hold = 10;
4968 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4969 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4970 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4971 peer->clear_node_queue->spec.max_retries = 0;
4972
4973 /* we only 'lock' this peer reference when the queue is actually active
4974 */
4975 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4976}
4977
d62a17ae 4978static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4979 struct bgp_table *table)
65ca75e0 4980{
9bcb3eef 4981 struct bgp_dest *dest;
b6c386bb 4982 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4983
d62a17ae 4984 if (!table)
4985 table = peer->bgp->rib[afi][safi];
dc83d712 4986
d62a17ae 4987 /* If still no table => afi/safi isn't configured at all or smth. */
4988 if (!table)
4989 return;
dc83d712 4990
9bcb3eef 4991 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4992 struct bgp_path_info *pi, *next;
d62a17ae 4993 struct bgp_adj_in *ain;
4994 struct bgp_adj_in *ain_next;
4995
4996 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4997 * queued for every clearing peer, regardless of whether it is
4998 * relevant to the peer at hand.
4999 *
5000 * Overview: There are 3 different indices which need to be
5001 * scrubbed, potentially, when a peer is removed:
5002 *
5003 * 1 peer's routes visible via the RIB (ie accepted routes)
5004 * 2 peer's routes visible by the (optional) peer's adj-in index
5005 * 3 other routes visible by the peer's adj-out index
5006 *
5007 * 3 there is no hurry in scrubbing, once the struct peer is
5008 * removed from bgp->peer, we could just GC such deleted peer's
5009 * adj-outs at our leisure.
5010 *
5011 * 1 and 2 must be 'scrubbed' in some way, at least made
5012 * invisible via RIB index before peer session is allowed to be
5013 * brought back up. So one needs to know when such a 'search' is
5014 * complete.
5015 *
5016 * Ideally:
5017 *
5018 * - there'd be a single global queue or a single RIB walker
5019 * - rather than tracking which route_nodes still need to be
5020 * examined on a peer basis, we'd track which peers still
5021 * aren't cleared
5022 *
5023 * Given that our per-peer prefix-counts now should be reliable,
5024 * this may actually be achievable. It doesn't seem to be a huge
5025 * problem at this time,
5026 *
5027 * It is possible that we have multiple paths for a prefix from
5028 * a peer
5029 * if that peer is using AddPath.
5030 */
9bcb3eef 5031 ain = dest->adj_in;
d62a17ae 5032 while (ain) {
5033 ain_next = ain->next;
5034
6a840fd9 5035 if (ain->peer == peer)
9bcb3eef 5036 bgp_adj_in_remove(dest, ain);
d62a17ae 5037
5038 ain = ain_next;
5039 }
5040
9bcb3eef 5041 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5042 next = pi->next;
5043 if (pi->peer != peer)
d62a17ae 5044 continue;
5045
5046 if (force)
9bcb3eef 5047 bgp_path_info_reap(dest, pi);
d62a17ae 5048 else {
5049 struct bgp_clear_node_queue *cnq;
5050
5051 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5052 bgp_table_lock(bgp_dest_table(dest));
5053 bgp_dest_lock_node(dest);
d62a17ae 5054 cnq = XCALLOC(
5055 MTYPE_BGP_CLEAR_NODE_QUEUE,
5056 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5057 cnq->dest = dest;
d62a17ae 5058 work_queue_add(peer->clear_node_queue, cnq);
5059 break;
5060 }
5061 }
5062 }
5063 return;
5064}
5065
5066void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5067{
9bcb3eef 5068 struct bgp_dest *dest;
d62a17ae 5069 struct bgp_table *table;
5070
5071 if (peer->clear_node_queue == NULL)
5072 bgp_clear_node_queue_init(peer);
5073
5074 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5075 * Idle until it receives a Clearing_Completed event. This protects
5076 * against peers which flap faster than we can we clear, which could
5077 * lead to:
5078 *
5079 * a) race with routes from the new session being installed before
5080 * clear_route_node visits the node (to delete the route of that
5081 * peer)
5082 * b) resource exhaustion, clear_route_node likely leads to an entry
5083 * on the process_main queue. Fast-flapping could cause that queue
5084 * to grow and grow.
5085 */
5086
5087 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5088 * the unlock will happen upon work-queue completion; other wise, the
5089 * unlock happens at the end of this function.
5090 */
5091 if (!peer->clear_node_queue->thread)
5092 peer_lock(peer);
5093
5094 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5095 bgp_clear_route_table(peer, afi, safi, NULL);
5096 else
9bcb3eef
DS
5097 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5098 dest = bgp_route_next(dest)) {
5099 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5100 if (!table)
5101 continue;
5102
5103 bgp_clear_route_table(peer, afi, safi, table);
5104 }
d62a17ae 5105
5106 /* unlock if no nodes got added to the clear-node-queue. */
5107 if (!peer->clear_node_queue->thread)
5108 peer_unlock(peer);
718e3744 5109}
d62a17ae 5110
5111void bgp_clear_route_all(struct peer *peer)
718e3744 5112{
d62a17ae 5113 afi_t afi;
5114 safi_t safi;
718e3744 5115
05c7a1cc
QY
5116 FOREACH_AFI_SAFI (afi, safi)
5117 bgp_clear_route(peer, afi, safi);
65efcfce 5118
49e5a4a0 5119#ifdef ENABLE_BGP_VNC
d62a17ae 5120 rfapiProcessPeerDown(peer);
65efcfce 5121#endif
718e3744 5122}
5123
d62a17ae 5124void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5125{
d62a17ae 5126 struct bgp_table *table;
9bcb3eef 5127 struct bgp_dest *dest;
d62a17ae 5128 struct bgp_adj_in *ain;
5129 struct bgp_adj_in *ain_next;
718e3744 5130
d62a17ae 5131 table = peer->bgp->rib[afi][safi];
718e3744 5132
d62a17ae 5133 /* It is possible that we have multiple paths for a prefix from a peer
5134 * if that peer is using AddPath.
5135 */
9bcb3eef
DS
5136 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5137 ain = dest->adj_in;
43143c8f 5138
d62a17ae 5139 while (ain) {
5140 ain_next = ain->next;
43143c8f 5141
6a840fd9 5142 if (ain->peer == peer)
9bcb3eef 5143 bgp_adj_in_remove(dest, ain);
43143c8f 5144
d62a17ae 5145 ain = ain_next;
5146 }
5147 }
718e3744 5148}
93406d87 5149
d62a17ae 5150void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5151{
9bcb3eef 5152 struct bgp_dest *dest;
40381db7 5153 struct bgp_path_info *pi;
d62a17ae 5154 struct bgp_table *table;
5155
9af52ccf 5156 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5157 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5158 dest = bgp_route_next(dest)) {
5159 struct bgp_dest *rm;
d62a17ae 5160
5161 /* look for neighbor in tables */
9bcb3eef 5162 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5163 if (!table)
ea47320b
DL
5164 continue;
5165
5166 for (rm = bgp_table_top(table); rm;
5167 rm = bgp_route_next(rm))
9bcb3eef 5168 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5169 pi = pi->next) {
40381db7 5170 if (pi->peer != peer)
ea47320b 5171 continue;
40381db7 5172 if (!CHECK_FLAG(pi->flags,
1defdda8 5173 BGP_PATH_STALE))
ea47320b
DL
5174 break;
5175
40381db7 5176 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5177 break;
5178 }
d62a17ae 5179 }
5180 } else {
9bcb3eef
DS
5181 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5182 dest = bgp_route_next(dest))
5183 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5184 pi = pi->next) {
40381db7 5185 if (pi->peer != peer)
ea47320b 5186 continue;
40381db7 5187 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5188 break;
9bcb3eef 5189 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5190 break;
5191 }
d62a17ae 5192 }
93406d87 5193}
6b0655a2 5194
9af52ccf
DA
5195void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5196{
5197 struct bgp_dest *dest, *ndest;
5198 struct bgp_path_info *pi;
5199 struct bgp_table *table;
5200
5201 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5202 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5203 dest = bgp_route_next(dest)) {
5204 table = bgp_dest_get_bgp_table_info(dest);
5205 if (!table)
5206 continue;
5207
5208 for (ndest = bgp_table_top(table); ndest;
5209 ndest = bgp_route_next(ndest)) {
5210 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5211 pi = pi->next) {
5212 if (pi->peer != peer)
5213 continue;
5214
5215 if ((CHECK_FLAG(
5216 peer->af_sflags[afi][safi],
5217 PEER_STATUS_ENHANCED_REFRESH))
5218 && !CHECK_FLAG(pi->flags,
5219 BGP_PATH_STALE)
5220 && !CHECK_FLAG(
5221 pi->flags,
5222 BGP_PATH_UNUSEABLE)) {
5223 if (bgp_debug_neighbor_events(
5224 peer))
5225 zlog_debug(
5226 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5227 peer->host,
5228 afi2str(afi),
5229 safi2str(safi),
5230 bgp_dest_get_prefix(
5231 ndest));
5232
5233 bgp_path_info_set_flag(
5234 ndest, pi,
5235 BGP_PATH_STALE);
5236 }
5237 }
5238 }
5239 }
5240 } else {
5241 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5242 dest = bgp_route_next(dest)) {
5243 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5244 pi = pi->next) {
5245 if (pi->peer != peer)
5246 continue;
5247
5248 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5249 PEER_STATUS_ENHANCED_REFRESH))
5250 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5251 && !CHECK_FLAG(pi->flags,
5252 BGP_PATH_UNUSEABLE)) {
5253 if (bgp_debug_neighbor_events(peer))
5254 zlog_debug(
5255 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5256 peer->host,
5257 afi2str(afi),
5258 safi2str(safi),
5259 bgp_dest_get_prefix(
5260 dest));
5261
5262 bgp_path_info_set_flag(dest, pi,
5263 BGP_PATH_STALE);
5264 }
5265 }
5266 }
5267 }
5268}
5269
3dc339cd 5270bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5271{
e0df4c04 5272 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5273 return true;
e0df4c04 5274
9dac9fc8
DA
5275 if (peer->sort == BGP_PEER_EBGP
5276 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5277 || FILTER_LIST_OUT_NAME(filter)
5278 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5279 return true;
5280 return false;
9dac9fc8
DA
5281}
5282
3dc339cd 5283bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5284{
e0df4c04 5285 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5286 return true;
e0df4c04 5287
9dac9fc8
DA
5288 if (peer->sort == BGP_PEER_EBGP
5289 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5290 || FILTER_LIST_IN_NAME(filter)
5291 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5292 return true;
5293 return false;
9dac9fc8
DA
5294}
5295
568e10ca 5296static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5297 safi_t safi)
bb86c601 5298{
9bcb3eef 5299 struct bgp_dest *dest;
40381db7 5300 struct bgp_path_info *pi;
4b7e6066 5301 struct bgp_path_info *next;
bb86c601 5302
9bcb3eef
DS
5303 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5304 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5305 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5306
40381db7 5307 next = pi->next;
1b7bb747
CS
5308
5309 /* Unimport EVPN routes from VRFs */
5310 if (safi == SAFI_EVPN)
5311 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5312 SAFI_EVPN, p, pi);
1b7bb747 5313
40381db7
DS
5314 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5315 && pi->type == ZEBRA_ROUTE_BGP
5316 && (pi->sub_type == BGP_ROUTE_NORMAL
5317 || pi->sub_type == BGP_ROUTE_AGGREGATE
5318 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5319
d62a17ae 5320 if (bgp_fibupd_safi(safi))
b54892e0 5321 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5322 }
9514b37d 5323
9bcb3eef 5324 bgp_path_info_reap(dest, pi);
d62a17ae 5325 }
bb86c601
LB
5326}
5327
718e3744 5328/* Delete all kernel routes. */
d62a17ae 5329void bgp_cleanup_routes(struct bgp *bgp)
5330{
5331 afi_t afi;
9bcb3eef 5332 struct bgp_dest *dest;
67009e22 5333 struct bgp_table *table;
d62a17ae 5334
5335 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5336 if (afi == AFI_L2VPN)
5337 continue;
568e10ca 5338 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5339 SAFI_UNICAST);
d62a17ae 5340 /*
5341 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5342 */
5343 if (afi != AFI_L2VPN) {
5344 safi_t safi;
5345 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5346 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5347 dest = bgp_route_next(dest)) {
5348 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5349 if (table != NULL) {
5350 bgp_cleanup_table(bgp, table, safi);
5351 bgp_table_finish(&table);
9bcb3eef
DS
5352 bgp_dest_set_bgp_table_info(dest, NULL);
5353 bgp_dest_unlock_node(dest);
d62a17ae 5354 }
5355 }
5356 safi = SAFI_ENCAP;
9bcb3eef
DS
5357 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5358 dest = bgp_route_next(dest)) {
5359 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5360 if (table != NULL) {
5361 bgp_cleanup_table(bgp, table, safi);
5362 bgp_table_finish(&table);
9bcb3eef
DS
5363 bgp_dest_set_bgp_table_info(dest, NULL);
5364 bgp_dest_unlock_node(dest);
d62a17ae 5365 }
5366 }
5367 }
5368 }
9bcb3eef
DS
5369 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5370 dest = bgp_route_next(dest)) {
5371 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5372 if (table != NULL) {
5373 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5374 bgp_table_finish(&table);
9bcb3eef
DS
5375 bgp_dest_set_bgp_table_info(dest, NULL);
5376 bgp_dest_unlock_node(dest);
d62a17ae 5377 }
bb86c601 5378 }
718e3744 5379}
5380
d62a17ae 5381void bgp_reset(void)
718e3744 5382{
d62a17ae 5383 vty_reset();
5384 bgp_zclient_reset();
5385 access_list_reset();
5386 prefix_list_reset();
718e3744 5387}
6b0655a2 5388
d62a17ae 5389static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5390{
d62a17ae 5391 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5392 && CHECK_FLAG(peer->af_cap[afi][safi],
5393 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5394}
5395
718e3744 5396/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5397 value. */
d62a17ae 5398int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5399 struct bgp_nlri *packet)
5400{
d7c0a89a
QY
5401 uint8_t *pnt;
5402 uint8_t *lim;
d62a17ae 5403 struct prefix p;
5404 int psize;
5405 int ret;
5406 afi_t afi;
5407 safi_t safi;
5408 int addpath_encoded;
d7c0a89a 5409 uint32_t addpath_id;
d62a17ae 5410
d62a17ae 5411 pnt = packet->nlri;
5412 lim = pnt + packet->length;
5413 afi = packet->afi;
5414 safi = packet->safi;
5415 addpath_id = 0;
5416 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5417
5418 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5419 syntactic validity. If the field is syntactically incorrect,
5420 then the Error Subcode is set to Invalid Network Field. */
5421 for (; pnt < lim; pnt += psize) {
5422 /* Clear prefix structure. */
5423 memset(&p, 0, sizeof(struct prefix));
5424
5425 if (addpath_encoded) {
5426
5427 /* When packet overflow occurs return immediately. */
761ed665 5428 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5429 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5430
a3a850a1 5431 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5432 addpath_id = ntohl(addpath_id);
d62a17ae 5433 pnt += BGP_ADDPATH_ID_LEN;
5434 }
718e3744 5435
d62a17ae 5436 /* Fetch prefix length. */
5437 p.prefixlen = *pnt++;
5438 /* afi/safi validity already verified by caller,
5439 * bgp_update_receive */
5440 p.family = afi2family(afi);
5441
5442 /* Prefix length check. */
5443 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5444 flog_err(
e50f7cfd 5445 EC_BGP_UPDATE_RCV,
14454c9f 5446 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5447 peer->host, p.prefixlen, packet->afi);
513386b5 5448 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5449 }
6b0655a2 5450
d62a17ae 5451 /* Packet size overflow check. */
5452 psize = PSIZE(p.prefixlen);
5453
5454 /* When packet overflow occur return immediately. */
5455 if (pnt + psize > lim) {
af4c2728 5456 flog_err(
e50f7cfd 5457 EC_BGP_UPDATE_RCV,
d62a17ae 5458 "%s [Error] Update packet error (prefix length %d overflows packet)",
5459 peer->host, p.prefixlen);
513386b5 5460 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5461 }
5462
5463 /* Defensive coding, double-check the psize fits in a struct
5464 * prefix */
5465 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5466 flog_err(
e50f7cfd 5467 EC_BGP_UPDATE_RCV,
d62a17ae 5468 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5469 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5470 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5471 }
5472
5473 /* Fetch prefix from NLRI packet. */
a85297a7 5474 memcpy(p.u.val, pnt, psize);
d62a17ae 5475
5476 /* Check address. */
5477 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5478 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5479 /* From RFC4271 Section 6.3:
5480 *
5481 * If a prefix in the NLRI field is semantically
5482 * incorrect
5483 * (e.g., an unexpected multicast IP address),
5484 * an error SHOULD
5485 * be logged locally, and the prefix SHOULD be
5486 * ignored.
a4d82a8a 5487 */
af4c2728 5488 flog_err(
e50f7cfd 5489 EC_BGP_UPDATE_RCV,
23d0a753
DA
5490 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5491 peer->host, &p.u.prefix4);
d62a17ae 5492 continue;
5493 }
5494 }
5495
5496 /* Check address. */
5497 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5498 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5499 flog_err(
e50f7cfd 5500 EC_BGP_UPDATE_RCV,
c0d72166
DS
5501 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5502 peer->host, &p.u.prefix6);
d62a17ae 5503
5504 continue;
5505 }
5506 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5507 flog_err(
e50f7cfd 5508 EC_BGP_UPDATE_RCV,
c0d72166
DS
5509 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5510 peer->host, &p.u.prefix6);
d62a17ae 5511
5512 continue;
5513 }
5514 }
5515
5516 /* Normal process. */
5517 if (attr)
5518 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5519 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5520 NULL, NULL, 0, 0, NULL);
d62a17ae 5521 else
5522 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5523 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5524 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5525 NULL);
d62a17ae 5526
513386b5
DA
5527 /* Do not send BGP notification twice when maximum-prefix count
5528 * overflow. */
5529 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5530 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5531
5532 /* Address family configuration mismatch. */
d62a17ae 5533 if (ret < 0)
513386b5 5534 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5535 }
5536
5537 /* Packet length consistency check. */
5538 if (pnt != lim) {
af4c2728 5539 flog_err(
e50f7cfd 5540 EC_BGP_UPDATE_RCV,
d62a17ae 5541 "%s [Error] Update packet error (prefix length mismatch with total length)",
5542 peer->host);
513386b5 5543 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5544 }
6b0655a2 5545
513386b5 5546 return BGP_NLRI_PARSE_OK;
718e3744 5547}
5548
d62a17ae 5549static struct bgp_static *bgp_static_new(void)
718e3744 5550{
d62a17ae 5551 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5552}
5553
d62a17ae 5554static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5555{
0a22ddfb 5556 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5557 route_map_counter_decrement(bgp_static->rmap.map);
5558
0a22ddfb 5559 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5560 XFREE(MTYPE_BGP_STATIC, bgp_static);
5561}
5562
5f040085 5563void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5564 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5565{
9bcb3eef 5566 struct bgp_dest *dest;
40381db7 5567 struct bgp_path_info *pi;
4b7e6066 5568 struct bgp_path_info *new;
40381db7 5569 struct bgp_path_info rmap_path;
d62a17ae 5570 struct attr attr;
5571 struct attr *attr_new;
b68885f9 5572 route_map_result_t ret;
49e5a4a0 5573#ifdef ENABLE_BGP_VNC
d62a17ae 5574 int vnc_implicit_withdraw = 0;
65efcfce 5575#endif
fee0f4c6 5576
d62a17ae 5577 assert(bgp_static);
dd8103a9 5578
9bcb3eef 5579 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5580
d62a17ae 5581 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5582
d62a17ae 5583 attr.nexthop = bgp_static->igpnexthop;
5584 attr.med = bgp_static->igpmetric;
5585 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5586
d62a17ae 5587 if (bgp_static->atomic)
5588 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5589
d62a17ae 5590 /* Store label index, if required. */
5591 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5592 attr.label_index = bgp_static->label_index;
5593 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5594 }
718e3744 5595
d62a17ae 5596 /* Apply route-map. */
5597 if (bgp_static->rmap.name) {
5598 struct attr attr_tmp = attr;
80ced710 5599
40381db7
DS
5600 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5601 rmap_path.peer = bgp->peer_self;
5602 rmap_path.attr = &attr_tmp;
fee0f4c6 5603
d62a17ae 5604 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5605
1782514f 5606 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5607
d62a17ae 5608 bgp->peer_self->rmap_type = 0;
718e3744 5609
d62a17ae 5610 if (ret == RMAP_DENYMATCH) {
5611 /* Free uninterned attribute. */
5612 bgp_attr_flush(&attr_tmp);
718e3744 5613
d62a17ae 5614 /* Unintern original. */
5615 aspath_unintern(&attr.aspath);
5616 bgp_static_withdraw(bgp, p, afi, safi);
5617 return;
5618 }
7f323236 5619
637e5ba4 5620 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5621 bgp_attr_add_gshut_community(&attr_tmp);
5622
d62a17ae 5623 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5624 } else {
5625
637e5ba4 5626 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5627 bgp_attr_add_gshut_community(&attr);
5628
d62a17ae 5629 attr_new = bgp_attr_intern(&attr);
7f323236 5630 }
718e3744 5631
9bcb3eef 5632 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5633 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5634 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5635 break;
5636
40381db7
DS
5637 if (pi) {
5638 if (attrhash_cmp(pi->attr, attr_new)
5639 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5640 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5641 bgp_dest_unlock_node(dest);
d62a17ae 5642 bgp_attr_unintern(&attr_new);
5643 aspath_unintern(&attr.aspath);
5644 return;
5645 } else {
5646 /* The attribute is changed. */
9bcb3eef 5647 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5648
5649 /* Rewrite BGP route information. */
40381db7 5650 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5651 bgp_path_info_restore(dest, pi);
d62a17ae 5652 else
40381db7 5653 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5654#ifdef ENABLE_BGP_VNC
d62a17ae 5655 if ((afi == AFI_IP || afi == AFI_IP6)
5656 && (safi == SAFI_UNICAST)) {
40381db7 5657 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5658 /*
5659 * Implicit withdraw case.
40381db7 5660 * We have to do this before pi is
d62a17ae 5661 * changed
5662 */
5663 ++vnc_implicit_withdraw;
40381db7 5664 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5665 vnc_import_bgp_exterior_del_route(
40381db7 5666 bgp, p, pi);
d62a17ae 5667 }
5668 }
65efcfce 5669#endif
40381db7
DS
5670 bgp_attr_unintern(&pi->attr);
5671 pi->attr = attr_new;
5672 pi->uptime = bgp_clock();
49e5a4a0 5673#ifdef ENABLE_BGP_VNC
d62a17ae 5674 if ((afi == AFI_IP || afi == AFI_IP6)
5675 && (safi == SAFI_UNICAST)) {
5676 if (vnc_implicit_withdraw) {
40381db7 5677 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5678 vnc_import_bgp_exterior_add_route(
40381db7 5679 bgp, p, pi);
d62a17ae 5680 }
5681 }
65efcfce 5682#endif
718e3744 5683
d62a17ae 5684 /* Nexthop reachability check. */
892fedb6 5685 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5686 && (safi == SAFI_UNICAST
5687 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5688
5689 struct bgp *bgp_nexthop = bgp;
5690
40381db7
DS
5691 if (pi->extra && pi->extra->bgp_orig)
5692 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5693
5694 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5695 afi, safi, pi, NULL,
654a5978 5696 0, p))
9bcb3eef 5697 bgp_path_info_set_flag(dest, pi,
18ee8310 5698 BGP_PATH_VALID);
d62a17ae 5699 else {
5700 if (BGP_DEBUG(nht, NHT)) {
5701 char buf1[INET6_ADDRSTRLEN];
5702 inet_ntop(p->family,
5703 &p->u.prefix, buf1,
5704 INET6_ADDRSTRLEN);
5705 zlog_debug(
5706 "%s(%s): Route not in table, not advertising",
15569c58 5707 __func__, buf1);
d62a17ae 5708 }
18ee8310 5709 bgp_path_info_unset_flag(
9bcb3eef 5710 dest, pi, BGP_PATH_VALID);
d62a17ae 5711 }
5712 } else {
5713 /* Delete the NHT structure if any, if we're
5714 * toggling between
5715 * enabling/disabling import check. We
5716 * deregister the route
5717 * from NHT to avoid overloading NHT and the
5718 * process interaction
5719 */
40381db7 5720 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5721 bgp_path_info_set_flag(dest, pi,
5722 BGP_PATH_VALID);
d62a17ae 5723 }
5724 /* Process change. */
40381db7 5725 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5726 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5727
5728 if (SAFI_UNICAST == safi
5729 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5730 || bgp->inst_type
5731 == BGP_INSTANCE_TYPE_DEFAULT)) {
5732 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5733 pi);
ddb5b488
PZ
5734 }
5735
9bcb3eef 5736 bgp_dest_unlock_node(dest);
d62a17ae 5737 aspath_unintern(&attr.aspath);
5738 return;
5739 }
718e3744 5740 }
718e3744 5741
d62a17ae 5742 /* Make new BGP info. */
5743 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5744 attr_new, dest);
d62a17ae 5745 /* Nexthop reachability check. */
892fedb6 5746 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5747 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5748 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5749 p))
9bcb3eef 5750 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5751 else {
5752 if (BGP_DEBUG(nht, NHT)) {
5753 char buf1[INET6_ADDRSTRLEN];
5754 inet_ntop(p->family, &p->u.prefix, buf1,
5755 INET6_ADDRSTRLEN);
5756 zlog_debug(
5757 "%s(%s): Route not in table, not advertising",
15569c58 5758 __func__, buf1);
d62a17ae 5759 }
9bcb3eef 5760 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5761 }
5762 } else {
5763 /* Delete the NHT structure if any, if we're toggling between
5764 * enabling/disabling import check. We deregister the route
5765 * from NHT to avoid overloading NHT and the process interaction
5766 */
5767 bgp_unlink_nexthop(new);
5768
9bcb3eef 5769 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5770 }
078430f6 5771
d62a17ae 5772 /* Aggregate address increment. */
5773 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5774
d62a17ae 5775 /* Register new BGP information. */
9bcb3eef 5776 bgp_path_info_add(dest, new);
718e3744 5777
d62a17ae 5778 /* route_node_get lock */
9bcb3eef 5779 bgp_dest_unlock_node(dest);
d62a17ae 5780
5781 /* Process change. */
9bcb3eef 5782 bgp_process(bgp, dest, afi, safi);
d62a17ae 5783
ddb5b488
PZ
5784 if (SAFI_UNICAST == safi
5785 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5786 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5787 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5788 }
5789
d62a17ae 5790 /* Unintern original. */
5791 aspath_unintern(&attr.aspath);
718e3744 5792}
5793
5f040085 5794void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5795 safi_t safi)
718e3744 5796{
9bcb3eef 5797 struct bgp_dest *dest;
40381db7 5798 struct bgp_path_info *pi;
718e3744 5799
9bcb3eef 5800 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5801
d62a17ae 5802 /* Check selected route and self inserted route. */
9bcb3eef 5803 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5804 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5805 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5806 break;
5807
5808 /* Withdraw static BGP route from routing table. */
40381db7 5809 if (pi) {
ddb5b488
PZ
5810 if (SAFI_UNICAST == safi
5811 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5812 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5813 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5814 }
40381db7
DS
5815 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5816 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5817 bgp_path_info_delete(dest, pi);
5818 bgp_process(bgp, dest, afi, safi);
d62a17ae 5819 }
718e3744 5820
d62a17ae 5821 /* Unlock bgp_node_lookup. */
9bcb3eef 5822 bgp_dest_unlock_node(dest);
718e3744 5823}
5824
137446f9
LB
5825/*
5826 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5827 */
5f040085 5828static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5829 afi_t afi, safi_t safi,
5830 struct prefix_rd *prd)
718e3744 5831{
9bcb3eef 5832 struct bgp_dest *dest;
40381db7 5833 struct bgp_path_info *pi;
718e3744 5834
9bcb3eef 5835 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5836
d62a17ae 5837 /* Check selected route and self inserted route. */
9bcb3eef 5838 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5839 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5840 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5841 break;
718e3744 5842
d62a17ae 5843 /* Withdraw static BGP route from routing table. */
40381db7 5844 if (pi) {
49e5a4a0 5845#ifdef ENABLE_BGP_VNC
d62a17ae 5846 rfapiProcessWithdraw(
40381db7 5847 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5848 1); /* Kill, since it is an administrative change */
65efcfce 5849#endif
ddb5b488
PZ
5850 if (SAFI_MPLS_VPN == safi
5851 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5852 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5853 }
40381db7 5854 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5855 bgp_path_info_delete(dest, pi);
5856 bgp_process(bgp, dest, afi, safi);
d62a17ae 5857 }
718e3744 5858
d62a17ae 5859 /* Unlock bgp_node_lookup. */
9bcb3eef 5860 bgp_dest_unlock_node(dest);
718e3744 5861}
5862
5f040085 5863static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5864 struct bgp_static *bgp_static, afi_t afi,
5865 safi_t safi)
137446f9 5866{
9bcb3eef 5867 struct bgp_dest *dest;
4b7e6066 5868 struct bgp_path_info *new;
d62a17ae 5869 struct attr *attr_new;
5870 struct attr attr = {0};
40381db7 5871 struct bgp_path_info *pi;
49e5a4a0 5872#ifdef ENABLE_BGP_VNC
d62a17ae 5873 mpls_label_t label = 0;
65efcfce 5874#endif
d7c0a89a 5875 uint32_t num_labels = 0;
d62a17ae 5876 union gw_addr add;
137446f9 5877
d62a17ae 5878 assert(bgp_static);
137446f9 5879
b57ba6d2
MK
5880 if (bgp_static->label != MPLS_INVALID_LABEL)
5881 num_labels = 1;
9bcb3eef
DS
5882 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5883 &bgp_static->prd);
137446f9 5884
d62a17ae 5885 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5886
d62a17ae 5887 attr.nexthop = bgp_static->igpnexthop;
5888 attr.med = bgp_static->igpmetric;
5889 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5890
d62a17ae 5891 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5892 || (safi == SAFI_ENCAP)) {
5893 if (afi == AFI_IP) {
5894 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5895 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5896 }
5897 }
5898 if (afi == AFI_L2VPN) {
5899 if (bgp_static->gatewayIp.family == AF_INET)
5900 add.ipv4.s_addr =
5901 bgp_static->gatewayIp.u.prefix4.s_addr;
5902 else if (bgp_static->gatewayIp.family == AF_INET6)
5903 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5904 sizeof(struct in6_addr));
0a50c248 5905 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5906 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5907 struct bgp_encap_type_vxlan bet;
5908 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5909 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5910 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5911 }
5912 if (bgp_static->router_mac) {
5913 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5914 }
5915 }
5916 /* Apply route-map. */
5917 if (bgp_static->rmap.name) {
5918 struct attr attr_tmp = attr;
40381db7 5919 struct bgp_path_info rmap_path;
b68885f9 5920 route_map_result_t ret;
137446f9 5921
40381db7
DS
5922 rmap_path.peer = bgp->peer_self;
5923 rmap_path.attr = &attr_tmp;
137446f9 5924
d62a17ae 5925 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5926
1782514f 5927 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5928
d62a17ae 5929 bgp->peer_self->rmap_type = 0;
137446f9 5930
d62a17ae 5931 if (ret == RMAP_DENYMATCH) {
5932 /* Free uninterned attribute. */
5933 bgp_attr_flush(&attr_tmp);
137446f9 5934
d62a17ae 5935 /* Unintern original. */
5936 aspath_unintern(&attr.aspath);
5937 bgp_static_withdraw_safi(bgp, p, afi, safi,
5938 &bgp_static->prd);
5939 return;
5940 }
137446f9 5941
d62a17ae 5942 attr_new = bgp_attr_intern(&attr_tmp);
5943 } else {
5944 attr_new = bgp_attr_intern(&attr);
5945 }
137446f9 5946
9bcb3eef 5947 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5948 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5949 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5950 break;
5951
40381db7 5952 if (pi) {
d62a17ae 5953 memset(&add, 0, sizeof(union gw_addr));
40381db7 5954 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5955 && overlay_index_equal(afi, pi, &add)
40381db7 5956 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5957 bgp_dest_unlock_node(dest);
d62a17ae 5958 bgp_attr_unintern(&attr_new);
5959 aspath_unintern(&attr.aspath);
5960 return;
5961 } else {
5962 /* The attribute is changed. */
9bcb3eef 5963 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5964
5965 /* Rewrite BGP route information. */
40381db7 5966 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5967 bgp_path_info_restore(dest, pi);
d62a17ae 5968 else
40381db7
DS
5969 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5970 bgp_attr_unintern(&pi->attr);
5971 pi->attr = attr_new;
5972 pi->uptime = bgp_clock();
49e5a4a0 5973#ifdef ENABLE_BGP_VNC
40381db7
DS
5974 if (pi->extra)
5975 label = decode_label(&pi->extra->label[0]);
65efcfce 5976#endif
137446f9 5977
d62a17ae 5978 /* Process change. */
40381db7 5979 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5980 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5981
5982 if (SAFI_MPLS_VPN == safi
5983 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5984 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5985 }
49e5a4a0 5986#ifdef ENABLE_BGP_VNC
40381db7
DS
5987 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5988 pi->attr, afi, safi, pi->type,
5989 pi->sub_type, &label);
65efcfce 5990#endif
9bcb3eef 5991 bgp_dest_unlock_node(dest);
d62a17ae 5992 aspath_unintern(&attr.aspath);
5993 return;
5994 }
5995 }
137446f9
LB
5996
5997
d62a17ae 5998 /* Make new BGP info. */
5999 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6000 attr_new, dest);
1defdda8 6001 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 6002 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
6003 if (num_labels) {
6004 new->extra->label[0] = bgp_static->label;
6005 new->extra->num_labels = num_labels;
6006 }
49e5a4a0 6007#ifdef ENABLE_BGP_VNC
d62a17ae 6008 label = decode_label(&bgp_static->label);
65efcfce 6009#endif
137446f9 6010
d62a17ae 6011 /* Aggregate address increment. */
6012 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6013
d62a17ae 6014 /* Register new BGP information. */
9bcb3eef 6015 bgp_path_info_add(dest, new);
d62a17ae 6016 /* route_node_get lock */
9bcb3eef 6017 bgp_dest_unlock_node(dest);
137446f9 6018
d62a17ae 6019 /* Process change. */
9bcb3eef 6020 bgp_process(bgp, dest, afi, safi);
137446f9 6021
ddb5b488
PZ
6022 if (SAFI_MPLS_VPN == safi
6023 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6024 vpn_leak_to_vrf_update(bgp, new);
6025 }
49e5a4a0 6026#ifdef ENABLE_BGP_VNC
d62a17ae 6027 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6028 safi, new->type, new->sub_type, &label);
65efcfce
LB
6029#endif
6030
d62a17ae 6031 /* Unintern original. */
6032 aspath_unintern(&attr.aspath);
137446f9
LB
6033}
6034
718e3744 6035/* Configure static BGP network. When user don't run zebra, static
6036 route should be installed as valid. */
585f1adc
IR
6037static int bgp_static_set(struct vty *vty, const char *negate,
6038 const char *ip_str, afi_t afi, safi_t safi,
6039 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6040{
585f1adc
IR
6041 VTY_DECLVAR_CONTEXT(bgp, bgp);
6042 int ret;
d62a17ae 6043 struct prefix p;
6044 struct bgp_static *bgp_static;
9bcb3eef 6045 struct bgp_dest *dest;
d7c0a89a 6046 uint8_t need_update = 0;
d62a17ae 6047
585f1adc
IR
6048 /* Convert IP prefix string to struct prefix. */
6049 ret = str2prefix(ip_str, &p);
6050 if (!ret) {
6051 vty_out(vty, "%% Malformed prefix\n");
6052 return CMD_WARNING_CONFIG_FAILED;
6053 }
6054 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6055 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6056 return CMD_WARNING_CONFIG_FAILED;
6057 }
6058
d62a17ae 6059 apply_mask(&p);
718e3744 6060
e2a86ad9 6061 if (negate) {
718e3744 6062
e2a86ad9 6063 /* Set BGP static route configuration. */
9bcb3eef 6064 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6065
9bcb3eef 6066 if (!dest) {
585f1adc
IR
6067 vty_out(vty, "%% Can't find static route specified\n");
6068 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6069 }
6070
9bcb3eef 6071 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6072
e2a86ad9
DS
6073 if ((label_index != BGP_INVALID_LABEL_INDEX)
6074 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6075 vty_out(vty,
6076 "%% label-index doesn't match static route\n");
70d9b134 6077 bgp_dest_unlock_node(dest);
585f1adc 6078 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6079 }
d62a17ae 6080
e2a86ad9
DS
6081 if ((rmap && bgp_static->rmap.name)
6082 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6083 vty_out(vty,
6084 "%% route-map name doesn't match static route\n");
70d9b134 6085 bgp_dest_unlock_node(dest);
585f1adc 6086 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6087 }
718e3744 6088
e2a86ad9
DS
6089 /* Update BGP RIB. */
6090 if (!bgp_static->backdoor)
6091 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6092
e2a86ad9
DS
6093 /* Clear configuration. */
6094 bgp_static_free(bgp_static);
9bcb3eef
DS
6095 bgp_dest_set_bgp_static_info(dest, NULL);
6096 bgp_dest_unlock_node(dest);
6097 bgp_dest_unlock_node(dest);
e2a86ad9 6098 } else {
718e3744 6099
e2a86ad9 6100 /* Set BGP static route configuration. */
9bcb3eef
DS
6101 dest = bgp_node_get(bgp->route[afi][safi], &p);
6102 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6103 if (bgp_static) {
e2a86ad9 6104 /* Configuration change. */
e2a86ad9
DS
6105 /* Label index cannot be changed. */
6106 if (bgp_static->label_index != label_index) {
585f1adc
IR
6107 vty_out(vty, "%% cannot change label-index\n");
6108 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6109 }
d62a17ae 6110
e2a86ad9 6111 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6112 if (bgp_static->valid
6113 && bgp_static->backdoor != backdoor)
e2a86ad9 6114 need_update = 1;
718e3744 6115
e2a86ad9 6116 bgp_static->backdoor = backdoor;
718e3744 6117
e2a86ad9 6118 if (rmap) {
0a22ddfb
QY
6119 XFREE(MTYPE_ROUTE_MAP_NAME,
6120 bgp_static->rmap.name);
b4897fa5 6121 route_map_counter_decrement(
6122 bgp_static->rmap.map);
e2a86ad9
DS
6123 bgp_static->rmap.name =
6124 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6125 bgp_static->rmap.map =
6126 route_map_lookup_by_name(rmap);
b4897fa5 6127 route_map_counter_increment(
6128 bgp_static->rmap.map);
e2a86ad9 6129 } else {
0a22ddfb
QY
6130 XFREE(MTYPE_ROUTE_MAP_NAME,
6131 bgp_static->rmap.name);
b4897fa5 6132 route_map_counter_decrement(
6133 bgp_static->rmap.map);
e2a86ad9
DS
6134 bgp_static->rmap.map = NULL;
6135 bgp_static->valid = 0;
6136 }
9bcb3eef 6137 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6138 } else {
6139 /* New configuration. */
6140 bgp_static = bgp_static_new();
6141 bgp_static->backdoor = backdoor;
6142 bgp_static->valid = 0;
6143 bgp_static->igpmetric = 0;
975a328e 6144 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6145 bgp_static->label_index = label_index;
718e3744 6146
e2a86ad9 6147 if (rmap) {
0a22ddfb
QY
6148 XFREE(MTYPE_ROUTE_MAP_NAME,
6149 bgp_static->rmap.name);
b4897fa5 6150 route_map_counter_decrement(
6151 bgp_static->rmap.map);
e2a86ad9
DS
6152 bgp_static->rmap.name =
6153 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6154 bgp_static->rmap.map =
6155 route_map_lookup_by_name(rmap);
b4897fa5 6156 route_map_counter_increment(
6157 bgp_static->rmap.map);
e2a86ad9 6158 }
9bcb3eef 6159 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6160 }
d62a17ae 6161
e2a86ad9
DS
6162 bgp_static->valid = 1;
6163 if (need_update)
6164 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6165
e2a86ad9
DS
6166 if (!bgp_static->backdoor)
6167 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6168 }
d62a17ae 6169
585f1adc 6170 return CMD_SUCCESS;
d62a17ae 6171}
6172
6173void bgp_static_add(struct bgp *bgp)
6174{
6175 afi_t afi;
6176 safi_t safi;
9bcb3eef
DS
6177 struct bgp_dest *dest;
6178 struct bgp_dest *rm;
d62a17ae 6179 struct bgp_table *table;
6180 struct bgp_static *bgp_static;
6181
47fc6261 6182 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6183 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6184 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6185 dest = bgp_route_next(dest)) {
6186 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6187 continue;
ea47320b 6188
05c7a1cc
QY
6189 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6190 || (safi == SAFI_EVPN)) {
9bcb3eef 6191 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6192
6193 for (rm = bgp_table_top(table); rm;
6194 rm = bgp_route_next(rm)) {
a78beeb5 6195 bgp_static =
9bcb3eef 6196 bgp_dest_get_bgp_static_info(
5a8ba9fc 6197 rm);
9bcb3eef
DS
6198 bgp_static_update_safi(
6199 bgp, bgp_dest_get_prefix(rm),
6200 bgp_static, afi, safi);
d62a17ae 6201 }
05c7a1cc 6202 } else {
5a8ba9fc 6203 bgp_static_update(
9bcb3eef
DS
6204 bgp, bgp_dest_get_prefix(dest),
6205 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6206 safi);
ea47320b 6207 }
05c7a1cc 6208 }
47fc6261 6209 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6210}
6211
718e3744 6212/* Called from bgp_delete(). Delete all static routes from the BGP
6213 instance. */
d62a17ae 6214void bgp_static_delete(struct bgp *bgp)
6215{
6216 afi_t afi;
6217 safi_t safi;
9bcb3eef
DS
6218 struct bgp_dest *dest;
6219 struct bgp_dest *rm;
d62a17ae 6220 struct bgp_table *table;
6221 struct bgp_static *bgp_static;
6222
05c7a1cc 6223 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6224 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6225 dest = bgp_route_next(dest)) {
6226 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6227 continue;
ea47320b 6228
05c7a1cc
QY
6229 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6230 || (safi == SAFI_EVPN)) {
9bcb3eef 6231 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6232
6233 for (rm = bgp_table_top(table); rm;
6234 rm = bgp_route_next(rm)) {
a78beeb5 6235 bgp_static =
9bcb3eef 6236 bgp_dest_get_bgp_static_info(
5a8ba9fc 6237 rm);
c7d14ba6
PG
6238 if (!bgp_static)
6239 continue;
6240
05c7a1cc 6241 bgp_static_withdraw_safi(
9bcb3eef 6242 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6243 AFI_IP, safi,
6244 (struct prefix_rd *)
9bcb3eef
DS
6245 bgp_dest_get_prefix(
6246 dest));
ea47320b 6247 bgp_static_free(bgp_static);
811c6797 6248 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6249 NULL);
811c6797 6250 bgp_dest_unlock_node(rm);
d62a17ae 6251 }
05c7a1cc 6252 } else {
9bcb3eef 6253 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6254 bgp_static_withdraw(bgp,
9bcb3eef 6255 bgp_dest_get_prefix(dest),
b54892e0 6256 afi, safi);
05c7a1cc 6257 bgp_static_free(bgp_static);
9bcb3eef
DS
6258 bgp_dest_set_bgp_static_info(dest, NULL);
6259 bgp_dest_unlock_node(dest);
ea47320b 6260 }
05c7a1cc 6261 }
d62a17ae 6262}
6263
6264void bgp_static_redo_import_check(struct bgp *bgp)
6265{
6266 afi_t afi;
6267 safi_t safi;
9bcb3eef
DS
6268 struct bgp_dest *dest;
6269 struct bgp_dest *rm;
d62a17ae 6270 struct bgp_table *table;
6271 struct bgp_static *bgp_static;
6272
6273 /* Use this flag to force reprocessing of the route */
892fedb6 6274 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6275 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6276 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6277 dest = bgp_route_next(dest)) {
6278 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6279 continue;
ea47320b 6280
05c7a1cc
QY
6281 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6282 || (safi == SAFI_EVPN)) {
9bcb3eef 6283 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6284
6285 for (rm = bgp_table_top(table); rm;
6286 rm = bgp_route_next(rm)) {
a78beeb5 6287 bgp_static =
9bcb3eef 6288 bgp_dest_get_bgp_static_info(
5a8ba9fc 6289 rm);
9bcb3eef
DS
6290 bgp_static_update_safi(
6291 bgp, bgp_dest_get_prefix(rm),
6292 bgp_static, afi, safi);
d62a17ae 6293 }
05c7a1cc 6294 } else {
9bcb3eef
DS
6295 bgp_static = bgp_dest_get_bgp_static_info(dest);
6296 bgp_static_update(bgp,
6297 bgp_dest_get_prefix(dest),
6298 bgp_static, afi, safi);
ea47320b 6299 }
05c7a1cc
QY
6300 }
6301 }
892fedb6 6302 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6303}
6304
6305static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6306 safi_t safi)
6307{
6308 struct bgp_table *table;
9bcb3eef 6309 struct bgp_dest *dest;
40381db7 6310 struct bgp_path_info *pi;
d62a17ae 6311
dfb6fd1d
NT
6312 /* Do not install the aggregate route if BGP is in the
6313 * process of termination.
6314 */
892fedb6
DA
6315 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6316 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6317 return;
6318
d62a17ae 6319 table = bgp->rib[afi][safi];
9bcb3eef
DS
6320 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6321 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6322 if (pi->peer == bgp->peer_self
6323 && ((pi->type == ZEBRA_ROUTE_BGP
6324 && pi->sub_type == BGP_ROUTE_STATIC)
6325 || (pi->type != ZEBRA_ROUTE_BGP
6326 && pi->sub_type
d62a17ae 6327 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6328 bgp_aggregate_decrement(
6329 bgp, bgp_dest_get_prefix(dest), pi, afi,
6330 safi);
40381db7 6331 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6332 bgp_path_info_delete(dest, pi);
6333 bgp_process(bgp, dest, afi, safi);
d62a17ae 6334 }
6335 }
6336 }
ad4cbda1 6337}
6338
6339/*
6340 * Purge all networks and redistributed routes from routing table.
6341 * Invoked upon the instance going down.
6342 */
d62a17ae 6343void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6344{
d62a17ae 6345 afi_t afi;
6346 safi_t safi;
ad4cbda1 6347
05c7a1cc
QY
6348 FOREACH_AFI_SAFI (afi, safi)
6349 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6350}
6351
137446f9
LB
6352/*
6353 * gpz 110624
6354 * Currently this is used to set static routes for VPN and ENCAP.
6355 * I think it can probably be factored with bgp_static_set.
6356 */
d62a17ae 6357int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6358 const char *ip_str, const char *rd_str,
6359 const char *label_str, const char *rmap_str,
6360 int evpn_type, const char *esi, const char *gwip,
6361 const char *ethtag, const char *routermac)
6362{
6363 VTY_DECLVAR_CONTEXT(bgp, bgp);
6364 int ret;
6365 struct prefix p;
6366 struct prefix_rd prd;
9bcb3eef
DS
6367 struct bgp_dest *pdest;
6368 struct bgp_dest *dest;
d62a17ae 6369 struct bgp_table *table;
6370 struct bgp_static *bgp_static;
6371 mpls_label_t label = MPLS_INVALID_LABEL;
6372 struct prefix gw_ip;
6373
6374 /* validate ip prefix */
6375 ret = str2prefix(ip_str, &p);
6376 if (!ret) {
6377 vty_out(vty, "%% Malformed prefix\n");
6378 return CMD_WARNING_CONFIG_FAILED;
6379 }
6380 apply_mask(&p);
6381 if ((afi == AFI_L2VPN)
6382 && (bgp_build_evpn_prefix(evpn_type,
6383 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6384 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6385 return CMD_WARNING_CONFIG_FAILED;
6386 }
718e3744 6387
d62a17ae 6388 ret = str2prefix_rd(rd_str, &prd);
6389 if (!ret) {
6390 vty_out(vty, "%% Malformed rd\n");
6391 return CMD_WARNING_CONFIG_FAILED;
6392 }
718e3744 6393
d62a17ae 6394 if (label_str) {
6395 unsigned long label_val;
6396 label_val = strtoul(label_str, NULL, 10);
6397 encode_label(label_val, &label);
6398 }
9bedbb1e 6399
d62a17ae 6400 if (safi == SAFI_EVPN) {
6401 if (esi && str2esi(esi, NULL) == 0) {
6402 vty_out(vty, "%% Malformed ESI\n");
6403 return CMD_WARNING_CONFIG_FAILED;
6404 }
6405 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6406 vty_out(vty, "%% Malformed Router MAC\n");
6407 return CMD_WARNING_CONFIG_FAILED;
6408 }
6409 if (gwip) {
6410 memset(&gw_ip, 0, sizeof(struct prefix));
6411 ret = str2prefix(gwip, &gw_ip);
6412 if (!ret) {
6413 vty_out(vty, "%% Malformed GatewayIp\n");
6414 return CMD_WARNING_CONFIG_FAILED;
6415 }
6416 if ((gw_ip.family == AF_INET
3714a385 6417 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6418 (struct prefix_evpn *)&p))
6419 || (gw_ip.family == AF_INET6
3714a385 6420 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6421 (struct prefix_evpn *)&p))) {
6422 vty_out(vty,
6423 "%% GatewayIp family differs with IP prefix\n");
6424 return CMD_WARNING_CONFIG_FAILED;
6425 }
6426 }
6427 }
9bcb3eef
DS
6428 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6429 if (!bgp_dest_has_bgp_path_info_data(pdest))
6430 bgp_dest_set_bgp_table_info(pdest,
67009e22 6431 bgp_table_init(bgp, afi, safi));
9bcb3eef 6432 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6433
9bcb3eef 6434 dest = bgp_node_get(table, &p);
d62a17ae 6435
9bcb3eef 6436 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6437 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6438 bgp_dest_unlock_node(dest);
d62a17ae 6439 } else {
6440 /* New configuration. */
6441 bgp_static = bgp_static_new();
6442 bgp_static->backdoor = 0;
6443 bgp_static->valid = 0;
6444 bgp_static->igpmetric = 0;
975a328e 6445 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6446 bgp_static->label = label;
6447 bgp_static->prd = prd;
6448
6449 if (rmap_str) {
0a22ddfb 6450 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6451 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6452 bgp_static->rmap.name =
6453 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6454 bgp_static->rmap.map =
6455 route_map_lookup_by_name(rmap_str);
b4897fa5 6456 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6457 }
718e3744 6458
d62a17ae 6459 if (safi == SAFI_EVPN) {
6460 if (esi) {
6461 bgp_static->eth_s_id =
6462 XCALLOC(MTYPE_ATTR,
0a50c248 6463 sizeof(esi_t));
d62a17ae 6464 str2esi(esi, bgp_static->eth_s_id);
6465 }
6466 if (routermac) {
6467 bgp_static->router_mac =
28328ea9 6468 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6469 (void)prefix_str2mac(routermac,
6470 bgp_static->router_mac);
d62a17ae 6471 }
6472 if (gwip)
6473 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6474 }
9bcb3eef 6475 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6476
d62a17ae 6477 bgp_static->valid = 1;
6478 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6479 }
718e3744 6480
d62a17ae 6481 return CMD_SUCCESS;
718e3744 6482}
6483
6484/* Configure static BGP network. */
d62a17ae 6485int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6486 const char *ip_str, const char *rd_str,
6487 const char *label_str, int evpn_type, const char *esi,
6488 const char *gwip, const char *ethtag)
6489{
6490 VTY_DECLVAR_CONTEXT(bgp, bgp);
6491 int ret;
6492 struct prefix p;
6493 struct prefix_rd prd;
9bcb3eef
DS
6494 struct bgp_dest *pdest;
6495 struct bgp_dest *dest;
d62a17ae 6496 struct bgp_table *table;
6497 struct bgp_static *bgp_static;
6498 mpls_label_t label = MPLS_INVALID_LABEL;
6499
6500 /* Convert IP prefix string to struct prefix. */
6501 ret = str2prefix(ip_str, &p);
6502 if (!ret) {
6503 vty_out(vty, "%% Malformed prefix\n");
6504 return CMD_WARNING_CONFIG_FAILED;
6505 }
6506 apply_mask(&p);
6507 if ((afi == AFI_L2VPN)
6508 && (bgp_build_evpn_prefix(evpn_type,
6509 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6510 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6511 return CMD_WARNING_CONFIG_FAILED;
6512 }
6513 ret = str2prefix_rd(rd_str, &prd);
6514 if (!ret) {
6515 vty_out(vty, "%% Malformed rd\n");
6516 return CMD_WARNING_CONFIG_FAILED;
6517 }
718e3744 6518
d62a17ae 6519 if (label_str) {
6520 unsigned long label_val;
6521 label_val = strtoul(label_str, NULL, 10);
6522 encode_label(label_val, &label);
6523 }
718e3744 6524
9bcb3eef
DS
6525 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6526 if (!bgp_dest_has_bgp_path_info_data(pdest))
6527 bgp_dest_set_bgp_table_info(pdest,
67009e22 6528 bgp_table_init(bgp, afi, safi));
d62a17ae 6529 else
9bcb3eef
DS
6530 bgp_dest_unlock_node(pdest);
6531 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6532
9bcb3eef 6533 dest = bgp_node_lookup(table, &p);
6b0655a2 6534
9bcb3eef 6535 if (dest) {
d62a17ae 6536 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6537
9bcb3eef 6538 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6539 bgp_static_free(bgp_static);
9bcb3eef
DS
6540 bgp_dest_set_bgp_static_info(dest, NULL);
6541 bgp_dest_unlock_node(dest);
6542 bgp_dest_unlock_node(dest);
d62a17ae 6543 } else
6544 vty_out(vty, "%% Can't find the route\n");
6545
6546 return CMD_SUCCESS;
6547}
6548
6549static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6550 const char *rmap_name)
6551{
6552 VTY_DECLVAR_CONTEXT(bgp, bgp);
6553 struct bgp_rmap *rmap;
6554
6555 rmap = &bgp->table_map[afi][safi];
6556 if (rmap_name) {
0a22ddfb 6557 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6558 route_map_counter_decrement(rmap->map);
d62a17ae 6559 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6560 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6561 route_map_counter_increment(rmap->map);
d62a17ae 6562 } else {
0a22ddfb 6563 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6564 route_map_counter_decrement(rmap->map);
d62a17ae 6565 rmap->map = NULL;
6566 }
73ac8160 6567
d62a17ae 6568 if (bgp_fibupd_safi(safi))
6569 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6570
d62a17ae 6571 return CMD_SUCCESS;
73ac8160
DS
6572}
6573
d62a17ae 6574static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6575 const char *rmap_name)
73ac8160 6576{
d62a17ae 6577 VTY_DECLVAR_CONTEXT(bgp, bgp);
6578 struct bgp_rmap *rmap;
73ac8160 6579
d62a17ae 6580 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6581 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6582 route_map_counter_decrement(rmap->map);
d62a17ae 6583 rmap->map = NULL;
73ac8160 6584
d62a17ae 6585 if (bgp_fibupd_safi(safi))
6586 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6587
d62a17ae 6588 return CMD_SUCCESS;
73ac8160
DS
6589}
6590
2b791107 6591void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6592 safi_t safi)
73ac8160 6593{
d62a17ae 6594 if (bgp->table_map[afi][safi].name) {
d62a17ae 6595 vty_out(vty, " table-map %s\n",
6596 bgp->table_map[afi][safi].name);
6597 }
73ac8160
DS
6598}
6599
73ac8160
DS
6600DEFUN (bgp_table_map,
6601 bgp_table_map_cmd,
6602 "table-map WORD",
6603 "BGP table to RIB route download filter\n"
6604 "Name of the route map\n")
6605{
d62a17ae 6606 int idx_word = 1;
6607 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6608 argv[idx_word]->arg);
73ac8160
DS
6609}
6610DEFUN (no_bgp_table_map,
6611 no_bgp_table_map_cmd,
6612 "no table-map WORD",
3a2d747c 6613 NO_STR
73ac8160
DS
6614 "BGP table to RIB route download filter\n"
6615 "Name of the route map\n")
6616{
d62a17ae 6617 int idx_word = 2;
6618 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6619 argv[idx_word]->arg);
73ac8160
DS
6620}
6621
585f1adc
IR
6622DEFPY(bgp_network,
6623 bgp_network_cmd,
6624 "[no] network \
6625 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6626 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6627 backdoor$backdoor}]",
6628 NO_STR
6629 "Specify a network to announce via BGP\n"
6630 "IPv4 prefix\n"
6631 "Network number\n"
6632 "Network mask\n"
6633 "Network mask\n"
6634 "Route-map to modify the attributes\n"
6635 "Name of the route map\n"
6636 "Label index to associate with the prefix\n"
6637 "Label index value\n"
6638 "Specify a BGP backdoor route\n")
6639{
6640 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6641
6642 if (address_str) {
6643 int ret;
718e3744 6644
e2a86ad9 6645 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6646 addr_prefix_str,
6647 sizeof(addr_prefix_str));
e2a86ad9
DS
6648 if (!ret) {
6649 vty_out(vty, "%% Inconsistent address and mask\n");
6650 return CMD_WARNING_CONFIG_FAILED;
6651 }
d62a17ae 6652 }
718e3744 6653
585f1adc
IR
6654 return bgp_static_set(
6655 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6656 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6657 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6658}
6659
585f1adc
IR
6660DEFPY(ipv6_bgp_network,
6661 ipv6_bgp_network_cmd,
6662 "[no] network X:X::X:X/M$prefix \
6663 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6664 NO_STR
6665 "Specify a network to announce via BGP\n"
6666 "IPv6 prefix\n"
6667 "Route-map to modify the attributes\n"
6668 "Name of the route map\n"
6669 "Label index to associate with the prefix\n"
6670 "Label index value\n")
37a87b8f 6671{
585f1adc
IR
6672 return bgp_static_set(
6673 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6674 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6675}
6676
d62a17ae 6677static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6678{
d62a17ae 6679 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6680}
6681
d62a17ae 6682static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6683{
365ab2e7
RZ
6684 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6685 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6686 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6687 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6688 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6689}
718e3744 6690
365ab2e7
RZ
6691/**
6692 * Helper function to avoid repeated code: prepare variables for a
6693 * `route_map_apply` call.
6694 *
6695 * \returns `true` on route map match, otherwise `false`.
6696 */
6697static bool aggr_suppress_map_test(struct bgp *bgp,
6698 struct bgp_aggregate *aggregate,
6699 struct bgp_path_info *pi)
6700{
6701 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6702 route_map_result_t rmr = RMAP_DENYMATCH;
6703 struct bgp_path_info rmap_path = {};
6704 struct attr attr = {};
6705
6706 /* No route map entries created, just don't match. */
6707 if (aggregate->suppress_map == NULL)
6708 return false;
6709
6710 /* Call route map matching and return result. */
6711 attr.aspath = aspath_empty();
6712 rmap_path.peer = bgp->peer_self;
6713 rmap_path.attr = &attr;
6714
6715 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6716 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6717 bgp->peer_self->rmap_type = 0;
6718
6719 bgp_attr_flush(&attr);
6720
6721 return rmr == RMAP_PERMITMATCH;
6722}
6723
4056a5f6
RZ
6724/** Test whether the aggregation has suppressed this path or not. */
6725static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6726 struct bgp_path_info *pi)
6727{
6728 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6729 return false;
6730
6731 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6732}
6733
6734/**
6735 * Suppress this path and keep the reference.
6736 *
6737 * \returns `true` if needs processing otherwise `false`.
6738 */
6739static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6740 struct bgp_path_info *pi)
6741{
6742 struct bgp_path_info_extra *pie;
6743
6744 /* Path is already suppressed by this aggregation. */
6745 if (aggr_suppress_exists(aggregate, pi))
6746 return false;
6747
6748 pie = bgp_path_info_extra_get(pi);
6749
6750 /* This is the first suppression, allocate memory and list it. */
6751 if (pie->aggr_suppressors == NULL)
6752 pie->aggr_suppressors = list_new();
6753
6754 listnode_add(pie->aggr_suppressors, aggregate);
6755
6756 /* Only mark for processing if suppressed. */
6757 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6758 if (BGP_DEBUG(update, UPDATE_OUT))
6759 zlog_debug("aggregate-address suppressing: %pFX",
6760 bgp_dest_get_prefix(pi->net));
6761
4056a5f6
RZ
6762 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6763 return true;
6764 }
6765
6766 return false;
6767}
6768
6769/**
6770 * Unsuppress this path and remove the reference.
6771 *
6772 * \returns `true` if needs processing otherwise `false`.
6773 */
6774static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6775 struct bgp_path_info *pi)
6776{
6777 /* Path wasn't suppressed. */
6778 if (!aggr_suppress_exists(aggregate, pi))
6779 return false;
6780
6781 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6782
6783 /* Unsuppress and free extra memory if last item. */
6784 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6785 if (BGP_DEBUG(update, UPDATE_OUT))
6786 zlog_debug("aggregate-address unsuppressing: %pFX",
6787 bgp_dest_get_prefix(pi->net));
6788
4056a5f6
RZ
6789 list_delete(&pi->extra->aggr_suppressors);
6790 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6791 return true;
6792 }
6793
6794 return false;
6795}
6796
3dc339cd
DA
6797static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6798 struct aspath *aspath,
6799 struct community *comm,
6800 struct ecommunity *ecomm,
6801 struct lcommunity *lcomm)
eaaf8adb
DS
6802{
6803 static struct aspath *ae = NULL;
6804
6805 if (!ae)
6806 ae = aspath_empty();
6807
40381db7 6808 if (!pi)
3dc339cd 6809 return false;
eaaf8adb 6810
40381db7 6811 if (origin != pi->attr->origin)
3dc339cd 6812 return false;
eaaf8adb 6813
40381db7 6814 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6815 return false;
29f7d023 6816
40381db7 6817 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6818 return false;
eaaf8adb 6819
3da2cc32 6820 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6821 return false;
eaaf8adb 6822
dd18c5a9 6823 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6824 return false;
dd18c5a9 6825
40381db7 6826 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6827 return false;
7ce8a8e0 6828
3dc339cd 6829 return true;
eaaf8adb
DS
6830}
6831
5f040085
DS
6832static void bgp_aggregate_install(
6833 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6834 uint8_t origin, struct aspath *aspath, struct community *community,
6835 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6836 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6837{
9bcb3eef 6838 struct bgp_dest *dest;
c701010e 6839 struct bgp_table *table;
6f94b685 6840 struct bgp_path_info *pi, *orig, *new;
20894f50 6841 struct attr *attr;
c701010e
DS
6842
6843 table = bgp->rib[afi][safi];
6844
9bcb3eef 6845 dest = bgp_node_get(table, p);
eaaf8adb 6846
9bcb3eef 6847 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6848 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6849 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6850 break;
6851
6aabb15d
RZ
6852 /*
6853 * If we have paths with different MEDs, then don't install
6854 * (or uninstall) the aggregate route.
6855 */
6856 if (aggregate->match_med && aggregate->med_mismatched)
6857 goto uninstall_aggregate_route;
6858
c701010e 6859 if (aggregate->count > 0) {
eaaf8adb
DS
6860 /*
6861 * If the aggregate information has not changed
6862 * no need to re-install it again.
6863 */
6f94b685 6864 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6865 ecommunity, lcommunity)) {
9bcb3eef 6866 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6867
6868 if (aspath)
6869 aspath_free(aspath);
6870 if (community)
3c1f53de 6871 community_free(&community);
3da2cc32
DS
6872 if (ecommunity)
6873 ecommunity_free(&ecommunity);
dd18c5a9
DS
6874 if (lcommunity)
6875 lcommunity_free(&lcommunity);
eaaf8adb
DS
6876
6877 return;
6878 }
6879
6880 /*
6881 * Mark the old as unusable
6882 */
40381db7 6883 if (pi)
9bcb3eef 6884 bgp_path_info_delete(dest, pi);
eaaf8adb 6885
20894f50
DA
6886 attr = bgp_attr_aggregate_intern(
6887 bgp, origin, aspath, community, ecommunity, lcommunity,
6888 aggregate, atomic_aggregate, p);
6889
6890 if (!attr) {
6891 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6892 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6893 zlog_debug("%s: %pFX null attribute", __func__,
6894 p);
20894f50
DA
6895 return;
6896 }
6897
3da2cc32 6898 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6899 bgp->peer_self, attr, dest);
20894f50 6900
1defdda8 6901 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6902
9bcb3eef
DS
6903 bgp_path_info_add(dest, new);
6904 bgp_process(bgp, dest, afi, safi);
c701010e 6905 } else {
6aabb15d 6906 uninstall_aggregate_route:
6f94b685 6907 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6908 if (pi->peer == bgp->peer_self
6909 && pi->type == ZEBRA_ROUTE_BGP
6910 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6911 break;
6912
6913 /* Withdraw static BGP route from routing table. */
40381db7 6914 if (pi) {
9bcb3eef
DS
6915 bgp_path_info_delete(dest, pi);
6916 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6917 }
6918 }
6919
9bcb3eef 6920 bgp_dest_unlock_node(dest);
c701010e
DS
6921}
6922
6aabb15d
RZ
6923/**
6924 * Check if the current path has different MED than other known paths.
6925 *
6926 * \returns `true` if the MED matched the others else `false`.
6927 */
6928static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6929 struct bgp *bgp, struct bgp_path_info *pi)
6930{
6931 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6932
6933 /* This is the first route being analyzed. */
6934 if (!aggregate->med_initialized) {
6935 aggregate->med_initialized = true;
6936 aggregate->med_mismatched = false;
6937 aggregate->med_matched_value = cur_med;
6938 } else {
6939 /* Check if routes with different MED showed up. */
6940 if (cur_med != aggregate->med_matched_value)
6941 aggregate->med_mismatched = true;
6942 }
6943
6944 return !aggregate->med_mismatched;
6945}
6946
6947/**
6948 * Initializes and tests all routes in the aggregate address path for MED
6949 * values.
6950 *
6951 * \returns `true` if all MEDs are the same otherwise `false`.
6952 */
6953static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6954 struct bgp *bgp, const struct prefix *p,
6955 afi_t afi, safi_t safi)
6956{
6957 struct bgp_table *table = bgp->rib[afi][safi];
6958 const struct prefix *dest_p;
6959 struct bgp_dest *dest, *top;
6960 struct bgp_path_info *pi;
6961 bool med_matched = true;
6962
6963 aggregate->med_initialized = false;
6964
6965 top = bgp_node_get(table, p);
6966 for (dest = bgp_node_get(table, p); dest;
6967 dest = bgp_route_next_until(dest, top)) {
6968 dest_p = bgp_dest_get_prefix(dest);
6969 if (dest_p->prefixlen <= p->prefixlen)
6970 continue;
6971
6972 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6973 if (BGP_PATH_HOLDDOWN(pi))
6974 continue;
6975 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6976 continue;
6977 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6978 med_matched = false;
6979 break;
6980 }
6981 }
6982 if (!med_matched)
6983 break;
6984 }
6985 bgp_dest_unlock_node(top);
6986
6987 return med_matched;
6988}
6989
6990/**
6991 * Toggles the route suppression status for this aggregate address
6992 * configuration.
6993 */
4056a5f6
RZ
6994void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6995 struct bgp *bgp, const struct prefix *p,
6996 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6997{
6998 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6999 const struct prefix *dest_p;
7000 struct bgp_dest *dest, *top;
7001 struct bgp_path_info *pi;
7002 bool toggle_suppression;
7003
7004 /* We've found a different MED we must revert any suppressed routes. */
7005 top = bgp_node_get(table, p);
7006 for (dest = bgp_node_get(table, p); dest;
7007 dest = bgp_route_next_until(dest, top)) {
7008 dest_p = bgp_dest_get_prefix(dest);
7009 if (dest_p->prefixlen <= p->prefixlen)
7010 continue;
7011
7012 toggle_suppression = false;
7013 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7014 if (BGP_PATH_HOLDDOWN(pi))
7015 continue;
7016 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7017 continue;
7018
6aabb15d
RZ
7019 /* We are toggling suppression back. */
7020 if (suppress) {
6aabb15d 7021 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7022 if (aggr_suppress_path(aggregate, pi))
7023 toggle_suppression = true;
6aabb15d
RZ
7024 continue;
7025 }
7026
6aabb15d 7027 /* Install route if there is no more suppression. */
4056a5f6 7028 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7029 toggle_suppression = true;
6aabb15d
RZ
7030 }
7031
7032 if (toggle_suppression)
7033 bgp_process(bgp, dest, afi, safi);
7034 }
7035 bgp_dest_unlock_node(top);
7036}
7037
7038/**
7039 * Aggregate address MED matching incremental test: this function is called
7040 * when the initial aggregation occurred and we are only testing a single
7041 * new path.
7042 *
7043 * In addition to testing and setting the MED validity it also installs back
7044 * suppressed routes (if summary is configured).
7045 *
7046 * Must not be called in `bgp_aggregate_route`.
7047 */
7048static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7049 struct bgp *bgp, const struct prefix *p,
7050 afi_t afi, safi_t safi,
7051 struct bgp_path_info *pi, bool is_adding)
7052{
7053 /* MED matching disabled. */
7054 if (!aggregate->match_med)
7055 return;
7056
7057 /* Aggregation with different MED, nothing to do. */
7058 if (aggregate->med_mismatched)
7059 return;
7060
7061 /*
7062 * Test the current entry:
7063 *
7064 * is_adding == true: if the new entry doesn't match then we must
7065 * install all suppressed routes.
7066 *
7067 * is_adding == false: if the entry being removed was the last
7068 * unmatching entry then we can suppress all routes.
7069 */
7070 if (!is_adding) {
7071 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7072 && aggregate->summary_only)
7073 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7074 safi, true);
7075 } else
7076 bgp_aggregate_med_match(aggregate, bgp, pi);
7077
7078 /* No mismatches, just quit. */
7079 if (!aggregate->med_mismatched)
7080 return;
7081
7082 /* Route summarization is disabled. */
7083 if (!aggregate->summary_only)
7084 return;
7085
7086 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7087}
7088
b5d58c32 7089/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7090void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7091 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7092{
7093 struct bgp_table *table;
9bcb3eef
DS
7094 struct bgp_dest *top;
7095 struct bgp_dest *dest;
d7c0a89a 7096 uint8_t origin;
d62a17ae 7097 struct aspath *aspath = NULL;
d62a17ae 7098 struct community *community = NULL;
3da2cc32 7099 struct ecommunity *ecommunity = NULL;
dd18c5a9 7100 struct lcommunity *lcommunity = NULL;
40381db7 7101 struct bgp_path_info *pi;
d62a17ae 7102 unsigned long match = 0;
d7c0a89a 7103 uint8_t atomic_aggregate = 0;
d62a17ae 7104
9f822fa2
S
7105 /* If the bgp instance is being deleted or self peer is deleted
7106 * then do not create aggregate route
7107 */
892fedb6
DA
7108 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7109 || (bgp->peer_self == NULL))
9f822fa2
S
7110 return;
7111
6aabb15d
RZ
7112 /* Initialize and test routes for MED difference. */
7113 if (aggregate->match_med)
7114 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7115
4056a5f6
RZ
7116 /*
7117 * Reset aggregate count: we might've been called from route map
7118 * update so in that case we must retest all more specific routes.
7119 *
7120 * \see `bgp_route_map_process_update`.
7121 */
7122 aggregate->count = 0;
7123 aggregate->incomplete_origin_count = 0;
7124 aggregate->incomplete_origin_count = 0;
7125 aggregate->egp_origin_count = 0;
7126
d62a17ae 7127 /* ORIGIN attribute: If at least one route among routes that are
7128 aggregated has ORIGIN with the value INCOMPLETE, then the
7129 aggregated route must have the ORIGIN attribute with the value
7130 INCOMPLETE. Otherwise, if at least one route among routes that
7131 are aggregated has ORIGIN with the value EGP, then the aggregated
7132 route must have the origin attribute with the value EGP. In all
7133 other case the value of the ORIGIN attribute of the aggregated
7134 route is INTERNAL. */
7135 origin = BGP_ORIGIN_IGP;
718e3744 7136
d62a17ae 7137 table = bgp->rib[afi][safi];
718e3744 7138
d62a17ae 7139 top = bgp_node_get(table, p);
9bcb3eef
DS
7140 for (dest = bgp_node_get(table, p); dest;
7141 dest = bgp_route_next_until(dest, top)) {
7142 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7143
9bcb3eef 7144 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7145 continue;
d62a17ae 7146
a77e2f4b
S
7147 /* If suppress fib is enabled and route not installed
7148 * in FIB, skip the route
7149 */
7150 if (!bgp_check_advertise(bgp, dest))
7151 continue;
7152
c2ff8b3e 7153 match = 0;
d62a17ae 7154
9bcb3eef 7155 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7156 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7157 continue;
718e3744 7158
40381db7 7159 if (pi->attr->flag
c2ff8b3e
DS
7160 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7161 atomic_aggregate = 1;
d62a17ae 7162
40381db7 7163 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7164 continue;
d62a17ae 7165
f273fef1
DS
7166 /*
7167 * summary-only aggregate route suppress
7168 * aggregated route announcements.
6aabb15d
RZ
7169 *
7170 * MED matching:
7171 * Don't create summaries if MED didn't match
7172 * otherwise neither the specific routes and the
7173 * aggregation will be announced.
f273fef1 7174 */
6aabb15d
RZ
7175 if (aggregate->summary_only
7176 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7177 if (aggr_suppress_path(aggregate, pi))
7178 match++;
d62a17ae 7179 }
c2ff8b3e 7180
365ab2e7
RZ
7181 /*
7182 * Suppress more specific routes that match the route
7183 * map results.
7184 *
7185 * MED matching:
7186 * Don't suppress routes if MED matching is enabled and
7187 * it mismatched otherwise we might end up with no
7188 * routes for this path.
7189 */
7190 if (aggregate->suppress_map_name
7191 && AGGREGATE_MED_VALID(aggregate)
7192 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7193 if (aggr_suppress_path(aggregate, pi))
7194 match++;
d62a17ae 7195 }
c2ff8b3e
DS
7196
7197 aggregate->count++;
7198
f273fef1
DS
7199 /*
7200 * If at least one route among routes that are
7201 * aggregated has ORIGIN with the value INCOMPLETE,
7202 * then the aggregated route MUST have the ORIGIN
7203 * attribute with the value INCOMPLETE. Otherwise, if
7204 * at least one route among routes that are aggregated
7205 * has ORIGIN with the value EGP, then the aggregated
7206 * route MUST have the ORIGIN attribute with the value
7207 * EGP.
7208 */
fc968841
NT
7209 switch (pi->attr->origin) {
7210 case BGP_ORIGIN_INCOMPLETE:
7211 aggregate->incomplete_origin_count++;
7212 break;
7213 case BGP_ORIGIN_EGP:
7214 aggregate->egp_origin_count++;
7215 break;
7216 default:
7217 /*Do nothing.
7218 */
7219 break;
7220 }
c2ff8b3e
DS
7221
7222 if (!aggregate->as_set)
7223 continue;
7224
f273fef1
DS
7225 /*
7226 * as-set aggregate route generate origin, as path,
7227 * and community aggregation.
7228 */
fc968841
NT
7229 /* Compute aggregate route's as-path.
7230 */
ef51a7d8 7231 bgp_compute_aggregate_aspath_hash(aggregate,
7232 pi->attr->aspath);
c2ff8b3e 7233
fc968841
NT
7234 /* Compute aggregate route's community.
7235 */
7236 if (pi->attr->community)
21fec674 7237 bgp_compute_aggregate_community_hash(
fc968841
NT
7238 aggregate,
7239 pi->attr->community);
dd18c5a9 7240
fc968841
NT
7241 /* Compute aggregate route's extended community.
7242 */
7243 if (pi->attr->ecommunity)
4edd83f9 7244 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7245 aggregate,
7246 pi->attr->ecommunity);
7247
7248 /* Compute aggregate route's large community.
7249 */
7250 if (pi->attr->lcommunity)
f1eb1f05 7251 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7252 aggregate,
7253 pi->attr->lcommunity);
d62a17ae 7254 }
c2ff8b3e 7255 if (match)
9bcb3eef 7256 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7257 }
21fec674 7258 if (aggregate->as_set) {
ef51a7d8 7259 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7260 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7261 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7262 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7263 }
7264
f1eb1f05 7265
9bcb3eef 7266 bgp_dest_unlock_node(top);
718e3744 7267
718e3744 7268
fc968841
NT
7269 if (aggregate->incomplete_origin_count > 0)
7270 origin = BGP_ORIGIN_INCOMPLETE;
7271 else if (aggregate->egp_origin_count > 0)
7272 origin = BGP_ORIGIN_EGP;
d62a17ae 7273
229757f1
DA
7274 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7275 origin = aggregate->origin;
7276
fc968841
NT
7277 if (aggregate->as_set) {
7278 if (aggregate->aspath)
7279 /* Retrieve aggregate route's as-path.
7280 */
7281 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7282
fc968841
NT
7283 if (aggregate->community)
7284 /* Retrieve aggregate route's community.
7285 */
7286 community = community_dup(aggregate->community);
3da2cc32 7287
fc968841
NT
7288 if (aggregate->ecommunity)
7289 /* Retrieve aggregate route's ecommunity.
7290 */
7291 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7292
fc968841
NT
7293 if (aggregate->lcommunity)
7294 /* Retrieve aggregate route's lcommunity.
7295 */
7296 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7297 }
718e3744 7298
c701010e 7299 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7300 ecommunity, lcommunity, atomic_aggregate,
7301 aggregate);
718e3744 7302}
7303
5f040085
DS
7304void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7305 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7306{
7307 struct bgp_table *table;
9bcb3eef
DS
7308 struct bgp_dest *top;
7309 struct bgp_dest *dest;
40381db7 7310 struct bgp_path_info *pi;
3b7db173
DS
7311 unsigned long match;
7312
7313 table = bgp->rib[afi][safi];
7314
7315 /* If routes exists below this node, generate aggregate routes. */
7316 top = bgp_node_get(table, p);
9bcb3eef
DS
7317 for (dest = bgp_node_get(table, p); dest;
7318 dest = bgp_route_next_until(dest, top)) {
7319 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7320
9bcb3eef 7321 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7322 continue;
7323 match = 0;
7324
9bcb3eef 7325 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7326 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7327 continue;
7328
40381db7 7329 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7330 continue;
7331
6aabb15d
RZ
7332 if (aggregate->summary_only && pi->extra
7333 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7334 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7335 match++;
3b7db173 7336 }
3b7db173 7337
365ab2e7
RZ
7338 if (aggregate->suppress_map_name
7339 && AGGREGATE_MED_VALID(aggregate)
7340 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7341 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7342 match++;
3b7db173 7343 }
365ab2e7 7344
3b7db173 7345 aggregate->count--;
fc968841
NT
7346
7347 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7348 aggregate->incomplete_origin_count--;
7349 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7350 aggregate->egp_origin_count--;
7351
7352 if (aggregate->as_set) {
7353 /* Remove as-path from aggregate.
7354 */
ef51a7d8 7355 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7356 aggregate,
7357 pi->attr->aspath);
7358
7359 if (pi->attr->community)
7360 /* Remove community from aggregate.
7361 */
21fec674 7362 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7363 aggregate,
7364 pi->attr->community);
7365
7366 if (pi->attr->ecommunity)
7367 /* Remove ecommunity from aggregate.
7368 */
4edd83f9 7369 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7370 aggregate,
7371 pi->attr->ecommunity);
7372
7373 if (pi->attr->lcommunity)
7374 /* Remove lcommunity from aggregate.
7375 */
f1eb1f05 7376 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7377 aggregate,
7378 pi->attr->lcommunity);
7379 }
3b7db173
DS
7380 }
7381
7382 /* If this node was suppressed, process the change. */
7383 if (match)
9bcb3eef 7384 bgp_process(bgp, dest, afi, safi);
3b7db173 7385 }
f1eb1f05 7386 if (aggregate->as_set) {
ef51a7d8 7387 aspath_free(aggregate->aspath);
7388 aggregate->aspath = NULL;
21fec674 7389 if (aggregate->community)
7390 community_free(&aggregate->community);
4edd83f9 7391 if (aggregate->ecommunity)
7392 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7393 if (aggregate->lcommunity)
7394 lcommunity_free(&aggregate->lcommunity);
7395 }
7396
9bcb3eef 7397 bgp_dest_unlock_node(top);
3b7db173 7398}
718e3744 7399
5f040085
DS
7400static void bgp_add_route_to_aggregate(struct bgp *bgp,
7401 const struct prefix *aggr_p,
fc968841
NT
7402 struct bgp_path_info *pinew, afi_t afi,
7403 safi_t safi,
7404 struct bgp_aggregate *aggregate)
7405{
7406 uint8_t origin;
7407 struct aspath *aspath = NULL;
7408 uint8_t atomic_aggregate = 0;
7409 struct community *community = NULL;
7410 struct ecommunity *ecommunity = NULL;
7411 struct lcommunity *lcommunity = NULL;
7412
a4559740 7413 /* If the bgp instance is being deleted or self peer is deleted
7414 * then do not create aggregate route
7415 */
7416 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7417 || (bgp->peer_self == NULL))
7418 return;
7419
fc968841
NT
7420 /* ORIGIN attribute: If at least one route among routes that are
7421 * aggregated has ORIGIN with the value INCOMPLETE, then the
7422 * aggregated route must have the ORIGIN attribute with the value
7423 * INCOMPLETE. Otherwise, if at least one route among routes that
7424 * are aggregated has ORIGIN with the value EGP, then the aggregated
7425 * route must have the origin attribute with the value EGP. In all
7426 * other case the value of the ORIGIN attribute of the aggregated
7427 * route is INTERNAL.
7428 */
7429 origin = BGP_ORIGIN_IGP;
7430
7431 aggregate->count++;
7432
6aabb15d
RZ
7433 /*
7434 * This must be called before `summary` check to avoid
7435 * "suppressing" twice.
7436 */
7437 if (aggregate->match_med)
7438 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7439 pinew, true);
7440
7441 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7442 aggr_suppress_path(aggregate, pinew);
fc968841 7443
365ab2e7
RZ
7444 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7445 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7446 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7447
7448 switch (pinew->attr->origin) {
7449 case BGP_ORIGIN_INCOMPLETE:
7450 aggregate->incomplete_origin_count++;
7451 break;
7452 case BGP_ORIGIN_EGP:
7453 aggregate->egp_origin_count++;
7454 break;
7455 default:
7456 /* Do nothing.
7457 */
7458 break;
7459 }
7460
7461 if (aggregate->incomplete_origin_count > 0)
7462 origin = BGP_ORIGIN_INCOMPLETE;
7463 else if (aggregate->egp_origin_count > 0)
7464 origin = BGP_ORIGIN_EGP;
7465
229757f1
DA
7466 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7467 origin = aggregate->origin;
7468
fc968841
NT
7469 if (aggregate->as_set) {
7470 /* Compute aggregate route's as-path.
7471 */
7472 bgp_compute_aggregate_aspath(aggregate,
7473 pinew->attr->aspath);
7474
7475 /* Compute aggregate route's community.
7476 */
7477 if (pinew->attr->community)
7478 bgp_compute_aggregate_community(
7479 aggregate,
7480 pinew->attr->community);
7481
7482 /* Compute aggregate route's extended community.
7483 */
7484 if (pinew->attr->ecommunity)
7485 bgp_compute_aggregate_ecommunity(
7486 aggregate,
7487 pinew->attr->ecommunity);
7488
7489 /* Compute aggregate route's large community.
7490 */
7491 if (pinew->attr->lcommunity)
7492 bgp_compute_aggregate_lcommunity(
7493 aggregate,
7494 pinew->attr->lcommunity);
7495
7496 /* Retrieve aggregate route's as-path.
7497 */
7498 if (aggregate->aspath)
7499 aspath = aspath_dup(aggregate->aspath);
7500
7501 /* Retrieve aggregate route's community.
7502 */
7503 if (aggregate->community)
7504 community = community_dup(aggregate->community);
7505
7506 /* Retrieve aggregate route's ecommunity.
7507 */
7508 if (aggregate->ecommunity)
7509 ecommunity = ecommunity_dup(aggregate->ecommunity);
7510
7511 /* Retrieve aggregate route's lcommunity.
7512 */
7513 if (aggregate->lcommunity)
7514 lcommunity = lcommunity_dup(aggregate->lcommunity);
7515 }
7516
7517 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7518 aspath, community, ecommunity,
7519 lcommunity, atomic_aggregate, aggregate);
7520}
7521
7522static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7523 safi_t safi,
7524 struct bgp_path_info *pi,
7525 struct bgp_aggregate *aggregate,
5f040085 7526 const struct prefix *aggr_p)
fc968841
NT
7527{
7528 uint8_t origin;
7529 struct aspath *aspath = NULL;
7530 uint8_t atomic_aggregate = 0;
7531 struct community *community = NULL;
7532 struct ecommunity *ecommunity = NULL;
7533 struct lcommunity *lcommunity = NULL;
7534 unsigned long match = 0;
7535
a4559740 7536 /* If the bgp instance is being deleted or self peer is deleted
7537 * then do not create aggregate route
7538 */
7539 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7540 || (bgp->peer_self == NULL))
7541 return;
7542
fc968841
NT
7543 if (BGP_PATH_HOLDDOWN(pi))
7544 return;
7545
7546 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7547 return;
7548
4056a5f6
RZ
7549 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7550 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7551 match++;
fc968841 7552
365ab2e7 7553 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7554 && aggr_suppress_map_test(bgp, aggregate, pi))
7555 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7556 match++;
fc968841 7557
6aabb15d 7558 /*
365ab2e7 7559 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7560 * "unsuppressing" twice.
7561 */
7562 if (aggregate->match_med)
7563 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7564 true);
7565
fc968841
NT
7566 if (aggregate->count > 0)
7567 aggregate->count--;
7568
7569 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7570 aggregate->incomplete_origin_count--;
7571 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7572 aggregate->egp_origin_count--;
7573
7574 if (aggregate->as_set) {
7575 /* Remove as-path from aggregate.
7576 */
7577 bgp_remove_aspath_from_aggregate(aggregate,
7578 pi->attr->aspath);
7579
7580 if (pi->attr->community)
7581 /* Remove community from aggregate.
7582 */
7583 bgp_remove_community_from_aggregate(
7584 aggregate,
7585 pi->attr->community);
7586
7587 if (pi->attr->ecommunity)
7588 /* Remove ecommunity from aggregate.
7589 */
7590 bgp_remove_ecommunity_from_aggregate(
7591 aggregate,
7592 pi->attr->ecommunity);
7593
7594 if (pi->attr->lcommunity)
7595 /* Remove lcommunity from aggregate.
7596 */
7597 bgp_remove_lcommunity_from_aggregate(
7598 aggregate,
7599 pi->attr->lcommunity);
7600 }
7601
7602 /* If this node was suppressed, process the change. */
7603 if (match)
7604 bgp_process(bgp, pi->net, afi, safi);
7605
7606 origin = BGP_ORIGIN_IGP;
7607 if (aggregate->incomplete_origin_count > 0)
7608 origin = BGP_ORIGIN_INCOMPLETE;
7609 else if (aggregate->egp_origin_count > 0)
7610 origin = BGP_ORIGIN_EGP;
7611
229757f1
DA
7612 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7613 origin = aggregate->origin;
7614
fc968841
NT
7615 if (aggregate->as_set) {
7616 /* Retrieve aggregate route's as-path.
7617 */
7618 if (aggregate->aspath)
7619 aspath = aspath_dup(aggregate->aspath);
7620
7621 /* Retrieve aggregate route's community.
7622 */
7623 if (aggregate->community)
7624 community = community_dup(aggregate->community);
7625
7626 /* Retrieve aggregate route's ecommunity.
7627 */
7628 if (aggregate->ecommunity)
7629 ecommunity = ecommunity_dup(aggregate->ecommunity);
7630
7631 /* Retrieve aggregate route's lcommunity.
7632 */
7633 if (aggregate->lcommunity)
7634 lcommunity = lcommunity_dup(aggregate->lcommunity);
7635 }
7636
7637 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7638 aspath, community, ecommunity,
7639 lcommunity, atomic_aggregate, aggregate);
7640}
7641
5a1ae2c2 7642void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7643 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7644{
9bcb3eef
DS
7645 struct bgp_dest *child;
7646 struct bgp_dest *dest;
d62a17ae 7647 struct bgp_aggregate *aggregate;
7648 struct bgp_table *table;
718e3744 7649
d62a17ae 7650 table = bgp->aggregate[afi][safi];
f018db83 7651
d62a17ae 7652 /* No aggregates configured. */
7653 if (bgp_table_top_nolock(table) == NULL)
7654 return;
f018db83 7655
d62a17ae 7656 if (p->prefixlen == 0)
7657 return;
718e3744 7658
40381db7 7659 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7660 return;
718e3744 7661
a77e2f4b
S
7662 /* If suppress fib is enabled and route not installed
7663 * in FIB, do not update the aggregate route
7664 */
7665 if (!bgp_check_advertise(bgp, pi->net))
7666 return;
7667
d62a17ae 7668 child = bgp_node_get(table, p);
718e3744 7669
d62a17ae 7670 /* Aggregate address configuration check. */
9bcb3eef
DS
7671 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7672 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7673
9bcb3eef
DS
7674 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7675 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7676 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7677 aggregate);
d62a17ae 7678 }
b1e62edd 7679 }
9bcb3eef 7680 bgp_dest_unlock_node(child);
718e3744 7681}
7682
5a1ae2c2 7683void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7684 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7685{
9bcb3eef
DS
7686 struct bgp_dest *child;
7687 struct bgp_dest *dest;
d62a17ae 7688 struct bgp_aggregate *aggregate;
7689 struct bgp_table *table;
718e3744 7690
d62a17ae 7691 table = bgp->aggregate[afi][safi];
718e3744 7692
d62a17ae 7693 /* No aggregates configured. */
7694 if (bgp_table_top_nolock(table) == NULL)
7695 return;
718e3744 7696
d62a17ae 7697 if (p->prefixlen == 0)
7698 return;
718e3744 7699
d62a17ae 7700 child = bgp_node_get(table, p);
718e3744 7701
d62a17ae 7702 /* Aggregate address configuration check. */
9bcb3eef
DS
7703 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7704 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7705
9bcb3eef
DS
7706 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7707 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7708 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7709 aggregate, dest_p);
d62a17ae 7710 }
b1e62edd 7711 }
9bcb3eef 7712 bgp_dest_unlock_node(child);
d62a17ae 7713}
718e3744 7714
718e3744 7715/* Aggregate route attribute. */
7716#define AGGREGATE_SUMMARY_ONLY 1
7717#define AGGREGATE_AS_SET 1
fb29348a 7718#define AGGREGATE_AS_UNSET 0
718e3744 7719
229757f1
DA
7720static const char *bgp_origin2str(uint8_t origin)
7721{
7722 switch (origin) {
7723 case BGP_ORIGIN_IGP:
7724 return "igp";
7725 case BGP_ORIGIN_EGP:
7726 return "egp";
7727 case BGP_ORIGIN_INCOMPLETE:
7728 return "incomplete";
7729 }
7730 return "n/a";
7731}
7732
fdeb5a81 7733static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7734{
7735 switch (v_state) {
fdeb5a81
DS
7736 case RPKI_NOT_BEING_USED:
7737 return "not used";
7738 case RPKI_VALID:
b5b99af8 7739 return "valid";
fdeb5a81 7740 case RPKI_NOTFOUND:
b5b99af8 7741 return "not found";
fdeb5a81 7742 case RPKI_INVALID:
b5b99af8 7743 return "invalid";
b5b99af8 7744 }
fdeb5a81
DS
7745
7746 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7747 return "ERROR";
7748}
7749
585f1adc
IR
7750static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7751 afi_t afi, safi_t safi)
718e3744 7752{
585f1adc
IR
7753 VTY_DECLVAR_CONTEXT(bgp, bgp);
7754 int ret;
7755 struct prefix p;
9bcb3eef 7756 struct bgp_dest *dest;
d62a17ae 7757 struct bgp_aggregate *aggregate;
718e3744 7758
585f1adc
IR
7759 /* Convert string to prefix structure. */
7760 ret = str2prefix(prefix_str, &p);
7761 if (!ret) {
7762 vty_out(vty, "Malformed prefix\n");
7763 return CMD_WARNING_CONFIG_FAILED;
7764 }
7765 apply_mask(&p);
a4559740 7766
d62a17ae 7767 /* Old configuration check. */
585f1adc 7768 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 7769 if (!dest) {
585f1adc
IR
7770 vty_out(vty,
7771 "%% There is no aggregate-address configuration.\n");
7772 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7773 }
f6269b4f 7774
9bcb3eef 7775 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
7776 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
7777 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
7778 NULL, NULL, 0, aggregate);
d62a17ae 7779
7780 /* Unlock aggregate address configuration. */
9bcb3eef 7781 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7782
7783 if (aggregate->community)
7784 community_free(&aggregate->community);
7785
7786 if (aggregate->community_hash) {
7787 /* Delete all communities in the hash.
7788 */
7789 hash_clean(aggregate->community_hash,
7790 bgp_aggr_community_remove);
7791 /* Free up the community_hash.
7792 */
7793 hash_free(aggregate->community_hash);
7794 }
7795
7796 if (aggregate->ecommunity)
7797 ecommunity_free(&aggregate->ecommunity);
7798
7799 if (aggregate->ecommunity_hash) {
7800 /* Delete all ecommunities in the hash.
7801 */
7802 hash_clean(aggregate->ecommunity_hash,
7803 bgp_aggr_ecommunity_remove);
7804 /* Free up the ecommunity_hash.
7805 */
7806 hash_free(aggregate->ecommunity_hash);
7807 }
7808
7809 if (aggregate->lcommunity)
7810 lcommunity_free(&aggregate->lcommunity);
7811
7812 if (aggregate->lcommunity_hash) {
7813 /* Delete all lcommunities in the hash.
7814 */
7815 hash_clean(aggregate->lcommunity_hash,
7816 bgp_aggr_lcommunity_remove);
7817 /* Free up the lcommunity_hash.
7818 */
7819 hash_free(aggregate->lcommunity_hash);
7820 }
7821
7822 if (aggregate->aspath)
7823 aspath_free(aggregate->aspath);
7824
7825 if (aggregate->aspath_hash) {
7826 /* Delete all as-paths in the hash.
7827 */
7828 hash_clean(aggregate->aspath_hash,
7829 bgp_aggr_aspath_remove);
7830 /* Free up the aspath_hash.
7831 */
7832 hash_free(aggregate->aspath_hash);
7833 }
7834
d62a17ae 7835 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7836 bgp_dest_unlock_node(dest);
7837 bgp_dest_unlock_node(dest);
d62a17ae 7838
585f1adc 7839 return CMD_SUCCESS;
d62a17ae 7840}
7841
585f1adc
IR
7842static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
7843 safi_t safi, const char *rmap,
7844 uint8_t summary_only, uint8_t as_set,
7845 uint8_t origin, bool match_med,
7846 const char *suppress_map)
d62a17ae 7847{
585f1adc 7848 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 7849 int ret;
585f1adc 7850 struct prefix p;
9bcb3eef 7851 struct bgp_dest *dest;
d62a17ae 7852 struct bgp_aggregate *aggregate;
fb29348a 7853 uint8_t as_set_new = as_set;
d62a17ae 7854
365ab2e7 7855 if (suppress_map && summary_only) {
585f1adc 7856 vty_out(vty,
365ab2e7 7857 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 7858 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
7859 }
7860
585f1adc
IR
7861 /* Convert string to prefix structure. */
7862 ret = str2prefix(prefix_str, &p);
7863 if (!ret) {
7864 vty_out(vty, "Malformed prefix\n");
7865 return CMD_WARNING_CONFIG_FAILED;
7866 }
7867 apply_mask(&p);
d62a17ae 7868
585f1adc
IR
7869 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
7870 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
7871 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7872 prefix_str);
7873 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
7874 }
7875
d62a17ae 7876 /* Old configuration check. */
585f1adc 7877 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 7878 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7879
20894f50 7880 if (aggregate) {
585f1adc 7881 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 7882 /* try to remove the old entry */
585f1adc 7883 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 7884 if (ret) {
585f1adc 7885 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 7886 bgp_dest_unlock_node(dest);
585f1adc 7887 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7888 }
7889 }
718e3744 7890
d62a17ae 7891 /* Make aggregate address structure. */
7892 aggregate = bgp_aggregate_new();
7893 aggregate->summary_only = summary_only;
6aabb15d 7894 aggregate->match_med = match_med;
fb29348a
DA
7895
7896 /* Network operators MUST NOT locally generate any new
7897 * announcements containing AS_SET or AS_CONFED_SET. If they have
7898 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7899 * SHOULD withdraw those routes and re-announce routes for the
7900 * aggregate or component prefixes (i.e., the more-specific routes
7901 * subsumed by the previously aggregated route) without AS_SET
7902 * or AS_CONFED_SET in the updates.
7903 */
7f972cd8 7904 if (bgp->reject_as_sets) {
fb29348a
DA
7905 if (as_set == AGGREGATE_AS_SET) {
7906 as_set_new = AGGREGATE_AS_UNSET;
7907 zlog_warn(
63efca0e 7908 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7909 __func__);
585f1adc 7910 vty_out(vty,
fb29348a
DA
7911 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7912 }
7913 }
7914
7915 aggregate->as_set = as_set_new;
d62a17ae 7916 aggregate->safi = safi;
229757f1
DA
7917 /* Override ORIGIN attribute if defined.
7918 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7919 * to IGP which is not what rfc4271 says.
7920 * This enables the same behavior, optionally.
7921 */
7922 aggregate->origin = origin;
20894f50
DA
7923
7924 if (rmap) {
7925 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7926 route_map_counter_decrement(aggregate->rmap.map);
7927 aggregate->rmap.name =
7928 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7929 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7930 route_map_counter_increment(aggregate->rmap.map);
7931 }
365ab2e7
RZ
7932
7933 if (suppress_map) {
7934 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7935 route_map_counter_decrement(aggregate->suppress_map);
7936
7937 aggregate->suppress_map_name =
7938 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7939 aggregate->suppress_map =
7940 route_map_lookup_by_name(aggregate->suppress_map_name);
7941 route_map_counter_increment(aggregate->suppress_map);
7942 }
7943
9bcb3eef 7944 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7945
d62a17ae 7946 /* Aggregate address insert into BGP routing table. */
585f1adc 7947 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 7948
585f1adc 7949 return CMD_SUCCESS;
718e3744 7950}
7951
585f1adc
IR
7952DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
7953 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
7954 "as-set$as_set_s"
7955 "|summary-only$summary_only"
7956 "|route-map WORD$rmap_name"
7957 "|origin <egp|igp|incomplete>$origin_s"
7958 "|matching-MED-only$match_med"
7959 "|suppress-map WORD$suppress_map"
7960 "}]",
7961 NO_STR
7962 "Configure BGP aggregate entries\n"
7963 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
7964 "Generate AS set path information\n"
7965 "Filter more specific routes from updates\n"
7966 "Apply route map to aggregate network\n"
7967 "Route map name\n"
7968 "BGP origin code\n"
7969 "Remote EGP\n"
7970 "Local IGP\n"
7971 "Unknown heritage\n"
7972 "Only aggregate routes with matching MED\n"
7973 "Suppress the selected more specific routes\n"
7974 "Route map with the route selectors\n")
7975{
7976 const char *prefix_s = NULL;
554b3b10 7977 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
7978 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
7979 int as_set = AGGREGATE_AS_UNSET;
554b3b10 7980 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7981
554b3b10 7982 if (addr_str) {
7533cad7
QY
7983 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
7984 sizeof(prefix_buf))
554b3b10
RZ
7985 == 0) {
7986 vty_out(vty, "%% Inconsistent address and mask\n");
7987 return CMD_WARNING_CONFIG_FAILED;
7988 }
585f1adc
IR
7989 prefix_s = prefix_buf;
7990 } else
7991 prefix_s = prefix_str;
37a87b8f 7992
585f1adc
IR
7993 if (origin_s) {
7994 if (strcmp(origin_s, "egp") == 0)
7995 origin = BGP_ORIGIN_EGP;
7996 else if (strcmp(origin_s, "igp") == 0)
7997 origin = BGP_ORIGIN_IGP;
7998 else if (strcmp(origin_s, "incomplete") == 0)
7999 origin = BGP_ORIGIN_INCOMPLETE;
8000 }
90e21f35 8001
585f1adc
IR
8002 if (as_set_s)
8003 as_set = AGGREGATE_AS_SET;
554b3b10 8004
585f1adc 8005 /* Handle configuration removal, otherwise installation. */
554b3b10 8006 if (no)
585f1adc
IR
8007 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8008
8009 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8010 summary_only != NULL, as_set, origin,
8011 match_med != NULL, suppress_map);
8012}
8013
8014DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8015 "[no] aggregate-address X:X::X:X/M$prefix [{"
8016 "as-set$as_set_s"
8017 "|summary-only$summary_only"
8018 "|route-map WORD$rmap_name"
8019 "|origin <egp|igp|incomplete>$origin_s"
8020 "|matching-MED-only$match_med"
8021 "|suppress-map WORD$suppress_map"
8022 "}]",
8023 NO_STR
8024 "Configure BGP aggregate entries\n"
8025 "Aggregate prefix\n"
8026 "Generate AS set path information\n"
8027 "Filter more specific routes from updates\n"
8028 "Apply route map to aggregate network\n"
8029 "Route map name\n"
8030 "BGP origin code\n"
8031 "Remote EGP\n"
8032 "Local IGP\n"
8033 "Unknown heritage\n"
8034 "Only aggregate routes with matching MED\n"
8035 "Suppress the selected more specific routes\n"
8036 "Route map with the route selectors\n")
8037{
8038 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8039 int as_set = AGGREGATE_AS_UNSET;
8040
8041 if (origin_s) {
8042 if (strcmp(origin_s, "egp") == 0)
8043 origin = BGP_ORIGIN_EGP;
8044 else if (strcmp(origin_s, "igp") == 0)
8045 origin = BGP_ORIGIN_IGP;
8046 else if (strcmp(origin_s, "incomplete") == 0)
8047 origin = BGP_ORIGIN_INCOMPLETE;
8048 }
8049
8050 if (as_set_s)
8051 as_set = AGGREGATE_AS_SET;
8052
8053 /* Handle configuration removal, otherwise installation. */
554b3b10 8054 if (no)
585f1adc
IR
8055 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8056 SAFI_UNICAST);
554b3b10 8057
585f1adc
IR
8058 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8059 rmap_name, summary_only != NULL, as_set,
8060 origin, match_med != NULL, suppress_map);
718e3744 8061}
8062
718e3744 8063/* Redistribute route treatment. */
d62a17ae 8064void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8065 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3
DS
8066 enum nexthop_types_t nhtype, uint8_t distance,
8067 uint32_t metric, uint8_t type,
8068 unsigned short instance, route_tag_t tag)
d62a17ae 8069{
4b7e6066 8070 struct bgp_path_info *new;
40381db7
DS
8071 struct bgp_path_info *bpi;
8072 struct bgp_path_info rmap_path;
9bcb3eef 8073 struct bgp_dest *bn;
d62a17ae 8074 struct attr attr;
8075 struct attr *new_attr;
8076 afi_t afi;
b68885f9 8077 route_map_result_t ret;
d62a17ae 8078 struct bgp_redist *red;
8079
8080 /* Make default attribute. */
8081 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8082 /*
8083 * This must not be NULL to satisfy Coverity SA
8084 */
8085 assert(attr.aspath);
9de1f7ff 8086
a4d82a8a 8087 switch (nhtype) {
9de1f7ff
DS
8088 case NEXTHOP_TYPE_IFINDEX:
8089 break;
8090 case NEXTHOP_TYPE_IPV4:
8091 case NEXTHOP_TYPE_IPV4_IFINDEX:
8092 attr.nexthop = nexthop->ipv4;
8093 break;
8094 case NEXTHOP_TYPE_IPV6:
8095 case NEXTHOP_TYPE_IPV6_IFINDEX:
8096 attr.mp_nexthop_global = nexthop->ipv6;
8097 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8098 break;
8099 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8100 switch (p->family) {
8101 case AF_INET:
9de1f7ff 8102 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8103 break;
8104 case AF_INET6:
9de1f7ff
DS
8105 memset(&attr.mp_nexthop_global, 0,
8106 sizeof(attr.mp_nexthop_global));
74489921 8107 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8108 break;
74489921 8109 }
9de1f7ff 8110 break;
d62a17ae 8111 }
74489921 8112 attr.nh_ifindex = ifindex;
f04a80a5 8113
d62a17ae 8114 attr.med = metric;
957f74c3 8115 attr.distance = distance;
d62a17ae 8116 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8117 attr.tag = tag;
718e3744 8118
d62a17ae 8119 afi = family2afi(p->family);
6aeb9e78 8120
d62a17ae 8121 red = bgp_redist_lookup(bgp, afi, type, instance);
8122 if (red) {
8123 struct attr attr_new;
718e3744 8124
d62a17ae 8125 /* Copy attribute for modification. */
6f4f49b2 8126 attr_new = attr;
718e3744 8127
d62a17ae 8128 if (red->redist_metric_flag)
8129 attr_new.med = red->redist_metric;
718e3744 8130
d62a17ae 8131 /* Apply route-map. */
8132 if (red->rmap.name) {
40381db7
DS
8133 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8134 rmap_path.peer = bgp->peer_self;
8135 rmap_path.attr = &attr_new;
718e3744 8136
d62a17ae 8137 SET_FLAG(bgp->peer_self->rmap_type,
8138 PEER_RMAP_TYPE_REDISTRIBUTE);
8139
1782514f 8140 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8141
8142 bgp->peer_self->rmap_type = 0;
8143
8144 if (ret == RMAP_DENYMATCH) {
8145 /* Free uninterned attribute. */
8146 bgp_attr_flush(&attr_new);
8147
8148 /* Unintern original. */
8149 aspath_unintern(&attr.aspath);
8150 bgp_redistribute_delete(bgp, p, type, instance);
8151 return;
8152 }
8153 }
8154
637e5ba4 8155 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8156 bgp_attr_add_gshut_community(&attr_new);
8157
d62a17ae 8158 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8159 SAFI_UNICAST, p, NULL);
8160
8161 new_attr = bgp_attr_intern(&attr_new);
8162
9bcb3eef 8163 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8164 if (bpi->peer == bgp->peer_self
8165 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8166 break;
8167
40381db7 8168 if (bpi) {
d62a17ae 8169 /* Ensure the (source route) type is updated. */
40381db7
DS
8170 bpi->type = type;
8171 if (attrhash_cmp(bpi->attr, new_attr)
8172 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8173 bgp_attr_unintern(&new_attr);
8174 aspath_unintern(&attr.aspath);
9bcb3eef 8175 bgp_dest_unlock_node(bn);
d62a17ae 8176 return;
8177 } else {
8178 /* The attribute is changed. */
40381db7 8179 bgp_path_info_set_flag(bn, bpi,
18ee8310 8180 BGP_PATH_ATTR_CHANGED);
d62a17ae 8181
8182 /* Rewrite BGP route information. */
40381db7
DS
8183 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8184 bgp_path_info_restore(bn, bpi);
d62a17ae 8185 else
40381db7
DS
8186 bgp_aggregate_decrement(
8187 bgp, p, bpi, afi, SAFI_UNICAST);
8188 bgp_attr_unintern(&bpi->attr);
8189 bpi->attr = new_attr;
8190 bpi->uptime = bgp_clock();
d62a17ae 8191
8192 /* Process change. */
40381db7 8193 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8194 SAFI_UNICAST);
8195 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8196 bgp_dest_unlock_node(bn);
d62a17ae 8197 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8198
8199 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8200 || (bgp->inst_type
8201 == BGP_INSTANCE_TYPE_DEFAULT)) {
8202
8203 vpn_leak_from_vrf_update(
40381db7 8204 bgp_get_default(), bgp, bpi);
ddb5b488 8205 }
d62a17ae 8206 return;
8207 }
8208 }
8209
8210 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8211 bgp->peer_self, new_attr, bn);
1defdda8 8212 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8213
8214 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8215 bgp_path_info_add(bn, new);
9bcb3eef 8216 bgp_dest_unlock_node(bn);
d62a17ae 8217 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8218
8219 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8220 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8221
8222 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8223 }
d62a17ae 8224 }
8225
8226 /* Unintern original. */
8227 aspath_unintern(&attr.aspath);
718e3744 8228}
8229
d7c0a89a
QY
8230void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8231 unsigned short instance)
718e3744 8232{
d62a17ae 8233 afi_t afi;
9bcb3eef 8234 struct bgp_dest *dest;
40381db7 8235 struct bgp_path_info *pi;
d62a17ae 8236 struct bgp_redist *red;
718e3744 8237
d62a17ae 8238 afi = family2afi(p->family);
718e3744 8239
d62a17ae 8240 red = bgp_redist_lookup(bgp, afi, type, instance);
8241 if (red) {
9bcb3eef
DS
8242 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8243 SAFI_UNICAST, p, NULL);
d62a17ae 8244
9bcb3eef 8245 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8246 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8247 break;
8248
40381db7 8249 if (pi) {
ddb5b488
PZ
8250 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8251 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8252
8253 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8254 bgp, pi);
ddb5b488 8255 }
40381db7 8256 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8257 bgp_path_info_delete(dest, pi);
8258 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8259 }
9bcb3eef 8260 bgp_dest_unlock_node(dest);
d62a17ae 8261 }
8262}
8263
8264/* Withdraw specified route type's route. */
8265void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8266 unsigned short instance)
d62a17ae 8267{
9bcb3eef 8268 struct bgp_dest *dest;
40381db7 8269 struct bgp_path_info *pi;
d62a17ae 8270 struct bgp_table *table;
8271
8272 table = bgp->rib[afi][SAFI_UNICAST];
8273
9bcb3eef
DS
8274 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8275 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8276 if (pi->peer == bgp->peer_self && pi->type == type
8277 && pi->instance == instance)
d62a17ae 8278 break;
8279
40381db7 8280 if (pi) {
ddb5b488
PZ
8281 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8282 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8283
8284 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8285 bgp, pi);
ddb5b488 8286 }
9bcb3eef 8287 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8288 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8289 bgp_path_info_delete(dest, pi);
8290 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8291 }
718e3744 8292 }
718e3744 8293}
6b0655a2 8294
718e3744 8295/* Static function to display route. */
7d3cae70
DA
8296static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8297 struct vty *vty, json_object *json, bool wide)
718e3744 8298{
be054588 8299 int len = 0;
d62a17ae 8300 char buf[BUFSIZ];
50e05855 8301 char buf2[BUFSIZ];
718e3744 8302
d62a17ae 8303 if (p->family == AF_INET) {
c6462ff4 8304 if (!json) {
8228a9a7 8305 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8306 } else {
8307 json_object_string_add(json, "prefix",
8308 inet_ntop(p->family,
8309 &p->u.prefix, buf,
8310 BUFSIZ));
8311 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8312 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8313 json_object_string_add(json, "network", buf2);
7d3cae70 8314 json_object_int_add(json, "version", dest->version);
c6462ff4 8315 }
d62a17ae 8316 } else if (p->family == AF_ETHERNET) {
8228a9a7 8317 len = vty_out(vty, "%pFX", p);
b03b8898 8318 } else if (p->family == AF_EVPN) {
57f7feb6 8319 if (!json)
2dbe669b 8320 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8321 else
60466a63 8322 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8323 } else if (p->family == AF_FLOWSPEC) {
8324 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8325 json ?
8326 NLRI_STRING_FORMAT_JSON_SIMPLE :
8327 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8328 } else {
c6462ff4 8329 if (!json)
8228a9a7 8330 len = vty_out(vty, "%pFX", p);
50e05855
AD
8331 else {
8332 json_object_string_add(json, "prefix",
8333 inet_ntop(p->family,
8334 &p->u.prefix, buf,
8335 BUFSIZ));
8336 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8337 prefix2str(p, buf2, PREFIX_STRLEN);
8338 json_object_string_add(json, "network", buf2);
7d3cae70 8339 json_object_int_add(json, "version", dest->version);
37d4e0df 8340 }
9c92b5f7 8341 }
d62a17ae 8342
9c92b5f7 8343 if (!json) {
ae248832 8344 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8345 if (len < 1)
8346 vty_out(vty, "\n%*s", 20, " ");
8347 else
8348 vty_out(vty, "%*s", len, " ");
8349 }
718e3744 8350}
8351
d62a17ae 8352enum bgp_display_type {
8353 normal_list,
718e3744 8354};
8355
bbb46eb5
DA
8356static const char *
8357bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8358{
8359 switch (reason) {
8360 case bgp_path_selection_none:
8361 return "Nothing to Select";
8362 case bgp_path_selection_first:
8363 return "First path received";
8364 case bgp_path_selection_evpn_sticky_mac:
8365 return "EVPN Sticky Mac";
8366 case bgp_path_selection_evpn_seq:
8367 return "EVPN sequence number";
8368 case bgp_path_selection_evpn_lower_ip:
8369 return "EVPN lower IP";
8370 case bgp_path_selection_evpn_local_path:
8371 return "EVPN local ES path";
8372 case bgp_path_selection_evpn_non_proxy:
8373 return "EVPN non proxy";
8374 case bgp_path_selection_weight:
8375 return "Weight";
8376 case bgp_path_selection_local_pref:
8377 return "Local Pref";
8378 case bgp_path_selection_local_route:
8379 return "Local Route";
8380 case bgp_path_selection_confed_as_path:
8381 return "Confederation based AS Path";
8382 case bgp_path_selection_as_path:
8383 return "AS Path";
8384 case bgp_path_selection_origin:
8385 return "Origin";
8386 case bgp_path_selection_med:
8387 return "MED";
8388 case bgp_path_selection_peer:
8389 return "Peer Type";
8390 case bgp_path_selection_confed:
8391 return "Confed Peer Type";
8392 case bgp_path_selection_igp_metric:
8393 return "IGP Metric";
8394 case bgp_path_selection_older:
8395 return "Older Path";
8396 case bgp_path_selection_router_id:
8397 return "Router ID";
8398 case bgp_path_selection_cluster_length:
bcab253c 8399 return "Cluster length";
bbb46eb5
DA
8400 case bgp_path_selection_stale:
8401 return "Path Staleness";
8402 case bgp_path_selection_local_configured:
8403 return "Locally configured route";
8404 case bgp_path_selection_neighbor_ip:
8405 return "Neighbor IP";
8406 case bgp_path_selection_default:
8407 return "Nothing left to compare";
8408 }
8409 return "Invalid (internal error)";
8410}
8411
18ee8310 8412/* Print the short form route status for a bgp_path_info */
4b7e6066 8413static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8414 struct bgp_path_info *path,
82c298be 8415 const struct prefix *p,
d62a17ae 8416 json_object *json_path)
718e3744 8417{
82c298be
DA
8418 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8419
d62a17ae 8420 if (json_path) {
b05a1c8b 8421
d62a17ae 8422 /* Route status display. */
9b6d8fcf 8423 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8424 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8425
9b6d8fcf 8426 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8427 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8428
4056a5f6 8429 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8430 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8431
9b6d8fcf
DS
8432 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8433 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8434 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8435
d62a17ae 8436 /* Selected */
9b6d8fcf 8437 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8438 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8439
9b6d8fcf 8440 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8441 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8442
bbb46eb5 8443 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8444 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8445 json_object_string_add(json_path, "selectionReason",
8446 bgp_path_selection_reason2str(
8447 path->net->reason));
8448 }
b05a1c8b 8449
9b6d8fcf 8450 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8451 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8452
d62a17ae 8453 /* Internal route. */
9b6d8fcf
DS
8454 if ((path->peer->as)
8455 && (path->peer->as == path->peer->local_as))
d62a17ae 8456 json_object_string_add(json_path, "pathFrom",
8457 "internal");
8458 else
8459 json_object_string_add(json_path, "pathFrom",
8460 "external");
b05a1c8b 8461
d62a17ae 8462 return;
8463 }
b05a1c8b 8464
82c298be
DA
8465 /* RPKI validation state */
8466 rpki_state =
8467 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8468
8469 if (rpki_state == RPKI_VALID)
8470 vty_out(vty, "V");
8471 else if (rpki_state == RPKI_INVALID)
8472 vty_out(vty, "I");
8473 else if (rpki_state == RPKI_NOTFOUND)
8474 vty_out(vty, "N");
8475
d62a17ae 8476 /* Route status display. */
9b6d8fcf 8477 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8478 vty_out(vty, "R");
9b6d8fcf 8479 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8480 vty_out(vty, "S");
4056a5f6 8481 else if (bgp_path_suppressed(path))
d62a17ae 8482 vty_out(vty, "s");
9b6d8fcf
DS
8483 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8484 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8485 vty_out(vty, "*");
8486 else
8487 vty_out(vty, " ");
8488
8489 /* Selected */
9b6d8fcf 8490 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8491 vty_out(vty, "h");
9b6d8fcf 8492 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8493 vty_out(vty, "d");
9b6d8fcf 8494 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8495 vty_out(vty, ">");
9b6d8fcf 8496 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8497 vty_out(vty, "=");
8498 else
8499 vty_out(vty, " ");
718e3744 8500
d62a17ae 8501 /* Internal route. */
9b6d8fcf
DS
8502 if (path->peer && (path->peer->as)
8503 && (path->peer->as == path->peer->local_as))
d62a17ae 8504 vty_out(vty, "i");
8505 else
8506 vty_out(vty, " ");
b40d939b 8507}
8508
2ba93fd6
DA
8509static char *bgp_nexthop_hostname(struct peer *peer,
8510 struct bgp_nexthop_cache *bnc)
25b5da8d 8511{
892fedb6 8512 if (peer->hostname
aef999a2 8513 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8514 return peer->hostname;
8515 return NULL;
8516}
8517
b40d939b 8518/* called from terminal list command */
bd494ec5 8519void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8520 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8521 json_object *json_paths, bool wide)
d62a17ae 8522{
aef999a2 8523 int len;
515c2602 8524 struct attr *attr = path->attr;
d62a17ae 8525 json_object *json_path = NULL;
8526 json_object *json_nexthops = NULL;
8527 json_object *json_nexthop_global = NULL;
8528 json_object *json_nexthop_ll = NULL;
6f214dd3 8529 json_object *json_ext_community = NULL;
9df8b37c 8530 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8531 bool nexthop_self =
9b6d8fcf 8532 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8533 bool nexthop_othervrf = false;
43089216 8534 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8535 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8536 char *nexthop_hostname =
8537 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8538 char esi_buf[ESI_STR_LEN];
d62a17ae 8539
8540 if (json_paths)
8541 json_path = json_object_new_object();
8542
8543 /* short status lead text */
82c298be 8544 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8545
8546 if (!json_paths) {
8547 /* print prefix and mask */
8548 if (!display)
7d3cae70 8549 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8550 else
ae248832 8551 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8552 } else {
7d3cae70 8553 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8554 }
47fc97cc 8555
9df8b37c
PZ
8556 /*
8557 * If vrf id of nexthop is different from that of prefix,
8558 * set up printable string to append
8559 */
9b6d8fcf 8560 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8561 const char *self = "";
8562
8563 if (nexthop_self)
8564 self = "<";
8565
8566 nexthop_othervrf = true;
9b6d8fcf 8567 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8568
9b6d8fcf 8569 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8570 snprintf(vrf_id_str, sizeof(vrf_id_str),
8571 "@%s%s", VRFID_NONE_STR, self);
8572 else
8573 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8574 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8575
9b6d8fcf
DS
8576 if (path->extra->bgp_orig->inst_type
8577 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8578
9b6d8fcf 8579 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8580 } else {
8581 const char *self = "";
8582
8583 if (nexthop_self)
8584 self = "<";
8585
8586 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8587 }
8588
445c2480
DS
8589 /*
8590 * For ENCAP and EVPN routes, nexthop address family is not
8591 * neccessarily the same as the prefix address family.
8592 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8593 * EVPN routes are also exchanged with a MP nexthop. Currently,
8594 * this
8595 * is only IPv4, the value will be present in either
8596 * attr->nexthop or
8597 * attr->mp_nexthop_global_in
8598 */
8599 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8600 char buf[BUFSIZ];
8601 char nexthop[128];
8602 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8603
8604 switch (af) {
8605 case AF_INET:
772270f3
QY
8606 snprintf(nexthop, sizeof(nexthop), "%s",
8607 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8608 BUFSIZ));
445c2480
DS
8609 break;
8610 case AF_INET6:
772270f3
QY
8611 snprintf(nexthop, sizeof(nexthop), "%s",
8612 inet_ntop(af, &attr->mp_nexthop_global, buf,
8613 BUFSIZ));
445c2480
DS
8614 break;
8615 default:
772270f3 8616 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8617 break;
d62a17ae 8618 }
d62a17ae 8619
445c2480
DS
8620 if (json_paths) {
8621 json_nexthop_global = json_object_new_object();
8622
515c2602
DA
8623 json_object_string_add(json_nexthop_global, "ip",
8624 nexthop);
8625
939a97f4 8626 if (path->peer->hostname)
515c2602
DA
8627 json_object_string_add(json_nexthop_global,
8628 "hostname",
939a97f4 8629 path->peer->hostname);
515c2602
DA
8630
8631 json_object_string_add(json_nexthop_global, "afi",
8632 (af == AF_INET) ? "ipv4"
8633 : "ipv6");
445c2480
DS
8634 json_object_boolean_true_add(json_nexthop_global,
8635 "used");
aef999a2
DA
8636 } else {
8637 if (nexthop_hostname)
8638 len = vty_out(vty, "%s(%s)%s", nexthop,
8639 nexthop_hostname, vrf_id_str);
8640 else
8641 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8642
ae248832 8643 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8644 if (len < 1)
8645 vty_out(vty, "\n%*s", 36, " ");
8646 else
8647 vty_out(vty, "%*s", len, " ");
8648 }
445c2480
DS
8649 } else if (safi == SAFI_EVPN) {
8650 if (json_paths) {
23d0a753
DA
8651 char buf[BUFSIZ] = {0};
8652
445c2480
DS
8653 json_nexthop_global = json_object_new_object();
8654
515c2602 8655 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8656 inet_ntop(AF_INET,
8657 &attr->nexthop, buf,
8658 sizeof(buf)));
515c2602 8659
939a97f4 8660 if (path->peer->hostname)
515c2602
DA
8661 json_object_string_add(json_nexthop_global,
8662 "hostname",
939a97f4 8663 path->peer->hostname);
515c2602 8664
a4d82a8a
PZ
8665 json_object_string_add(json_nexthop_global, "afi",
8666 "ipv4");
445c2480
DS
8667 json_object_boolean_true_add(json_nexthop_global,
8668 "used");
aef999a2
DA
8669 } else {
8670 if (nexthop_hostname)
8671 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8672 nexthop_hostname, vrf_id_str);
8673 else
8674 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8675 vrf_id_str);
8676
ae248832 8677 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8678 if (len < 1)
8679 vty_out(vty, "\n%*s", 36, " ");
8680 else
8681 vty_out(vty, "%*s", len, " ");
8682 }
d33fc23b 8683 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8684 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8685 if (json_paths) {
23d0a753
DA
8686 char buf[BUFSIZ] = {0};
8687
026b914a 8688 json_nexthop_global = json_object_new_object();
515c2602 8689
026b914a
PG
8690 json_object_string_add(json_nexthop_global,
8691 "afi", "ipv4");
515c2602
DA
8692 json_object_string_add(
8693 json_nexthop_global, "ip",
23d0a753
DA
8694 inet_ntop(AF_INET, &attr->nexthop, buf,
8695 sizeof(buf)));
515c2602 8696
939a97f4 8697 if (path->peer->hostname)
515c2602
DA
8698 json_object_string_add(
8699 json_nexthop_global, "hostname",
939a97f4 8700 path->peer->hostname);
515c2602 8701
50e05855
AD
8702 json_object_boolean_true_add(
8703 json_nexthop_global,
026b914a
PG
8704 "used");
8705 } else {
aef999a2
DA
8706 if (nexthop_hostname)
8707 len = vty_out(vty, "%pI4(%s)%s",
8708 &attr->nexthop,
8709 nexthop_hostname,
8710 vrf_id_str);
8711 else
8712 len = vty_out(vty, "%pI4%s",
8713 &attr->nexthop,
8714 vrf_id_str);
8715
ae248832 8716 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8717 if (len < 1)
8718 vty_out(vty, "\n%*s", 36, " ");
8719 else
8720 vty_out(vty, "%*s", len, " ");
026b914a
PG
8721 }
8722 }
d33fc23b 8723 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8724 if (json_paths) {
23d0a753
DA
8725 char buf[BUFSIZ] = {0};
8726
445c2480 8727 json_nexthop_global = json_object_new_object();
d62a17ae 8728
515c2602 8729 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8730 inet_ntop(AF_INET,
8731 &attr->nexthop, buf,
8732 sizeof(buf)));
515c2602 8733
939a97f4 8734 if (path->peer->hostname)
515c2602
DA
8735 json_object_string_add(json_nexthop_global,
8736 "hostname",
939a97f4 8737 path->peer->hostname);
445c2480 8738
a4d82a8a
PZ
8739 json_object_string_add(json_nexthop_global, "afi",
8740 "ipv4");
445c2480
DS
8741 json_object_boolean_true_add(json_nexthop_global,
8742 "used");
8743 } else {
aef999a2
DA
8744 if (nexthop_hostname)
8745 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8746 nexthop_hostname, vrf_id_str);
8747 else
8748 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8749 vrf_id_str);
9df8b37c 8750
ae248832 8751 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8752 if (len < 1)
8753 vty_out(vty, "\n%*s", 36, " ");
8754 else
8755 vty_out(vty, "%*s", len, " ");
d62a17ae 8756 }
445c2480 8757 }
b05a1c8b 8758
445c2480 8759 /* IPv6 Next Hop */
a4d82a8a 8760 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8761 char buf[BUFSIZ];
d62a17ae 8762
445c2480
DS
8763 if (json_paths) {
8764 json_nexthop_global = json_object_new_object();
a4d82a8a 8765 json_object_string_add(
515c2602
DA
8766 json_nexthop_global, "ip",
8767 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8768 buf, BUFSIZ));
8769
939a97f4 8770 if (path->peer->hostname)
515c2602
DA
8771 json_object_string_add(json_nexthop_global,
8772 "hostname",
939a97f4 8773 path->peer->hostname);
515c2602 8774
a4d82a8a
PZ
8775 json_object_string_add(json_nexthop_global, "afi",
8776 "ipv6");
8777 json_object_string_add(json_nexthop_global, "scope",
8778 "global");
445c2480
DS
8779
8780 /* We display both LL & GL if both have been
8781 * received */
0606039c
DA
8782 if ((attr->mp_nexthop_len
8783 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8784 || (path->peer->conf_if)) {
a4d82a8a 8785 json_nexthop_ll = json_object_new_object();
d62a17ae 8786 json_object_string_add(
515c2602
DA
8787 json_nexthop_ll, "ip",
8788 inet_ntop(AF_INET6,
8789 &attr->mp_nexthop_local, buf,
8790 BUFSIZ));
8791
939a97f4 8792 if (path->peer->hostname)
515c2602
DA
8793 json_object_string_add(
8794 json_nexthop_ll, "hostname",
939a97f4 8795 path->peer->hostname);
515c2602 8796
a4d82a8a
PZ
8797 json_object_string_add(json_nexthop_ll, "afi",
8798 "ipv6");
8799 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8800 "link-local");
d62a17ae 8801
a4d82a8a
PZ
8802 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8803 &attr->mp_nexthop_local)
445c2480
DS
8804 != 0)
8805 && !attr->mp_nexthop_prefer_global)
d62a17ae 8806 json_object_boolean_true_add(
a4d82a8a 8807 json_nexthop_ll, "used");
445c2480
DS
8808 else
8809 json_object_boolean_true_add(
a4d82a8a 8810 json_nexthop_global, "used");
445c2480
DS
8811 } else
8812 json_object_boolean_true_add(
8813 json_nexthop_global, "used");
8814 } else {
8815 /* Display LL if LL/Global both in table unless
8816 * prefer-global is set */
0606039c
DA
8817 if (((attr->mp_nexthop_len
8818 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8819 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8820 || (path->peer->conf_if)) {
8821 if (path->peer->conf_if) {
a4d82a8a 8822 len = vty_out(vty, "%s",
9b6d8fcf 8823 path->peer->conf_if);
ae248832
MK
8824 /* len of IPv6 addr + max len of def
8825 * ifname */
8826 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8827
8828 if (len < 1)
a4d82a8a 8829 vty_out(vty, "\n%*s", 36, " ");
445c2480 8830 else
a4d82a8a 8831 vty_out(vty, "%*s", len, " ");
d62a17ae 8832 } else {
aef999a2
DA
8833 if (nexthop_hostname)
8834 len = vty_out(
8835 vty, "%pI6(%s)%s",
8836 &attr->mp_nexthop_local,
8837 nexthop_hostname,
8838 vrf_id_str);
8839 else
8840 len = vty_out(
8841 vty, "%pI6%s",
8842 &attr->mp_nexthop_local,
8843 vrf_id_str);
8844
ae248832 8845 len = wide ? (41 - len) : (16 - len);
d62a17ae 8846
8847 if (len < 1)
a4d82a8a 8848 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8849 else
a4d82a8a 8850 vty_out(vty, "%*s", len, " ");
d62a17ae 8851 }
445c2480 8852 } else {
aef999a2
DA
8853 if (nexthop_hostname)
8854 len = vty_out(vty, "%pI6(%s)%s",
8855 &attr->mp_nexthop_global,
8856 nexthop_hostname,
8857 vrf_id_str);
8858 else
8859 len = vty_out(vty, "%pI6%s",
8860 &attr->mp_nexthop_global,
8861 vrf_id_str);
8862
ae248832 8863 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8864
8865 if (len < 1)
8866 vty_out(vty, "\n%*s", 36, " ");
8867 else
8868 vty_out(vty, "%*s", len, " ");
d62a17ae 8869 }
8870 }
445c2480 8871 }
718e3744 8872
445c2480
DS
8873 /* MED/Metric */
8874 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8875 if (json_paths)
50e05855 8876 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8877 else if (wide)
8878 vty_out(vty, "%7u", attr->med);
0fbac0b4 8879 else
445c2480 8880 vty_out(vty, "%10u", attr->med);
ae248832
MK
8881 else if (!json_paths) {
8882 if (wide)
8883 vty_out(vty, "%*s", 7, " ");
8884 else
8885 vty_out(vty, "%*s", 10, " ");
8886 }
d62a17ae 8887
445c2480
DS
8888 /* Local Pref */
8889 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8890 if (json_paths)
50e05855 8891 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8892 attr->local_pref);
8893 else
445c2480
DS
8894 vty_out(vty, "%7u", attr->local_pref);
8895 else if (!json_paths)
8896 vty_out(vty, " ");
d62a17ae 8897
445c2480
DS
8898 if (json_paths)
8899 json_object_int_add(json_path, "weight", attr->weight);
8900 else
8901 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8902
445c2480
DS
8903 if (json_paths) {
8904 char buf[BUFSIZ];
a4d82a8a
PZ
8905 json_object_string_add(
8906 json_path, "peerId",
9b6d8fcf 8907 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8908 }
b05a1c8b 8909
445c2480
DS
8910 /* Print aspath */
8911 if (attr->aspath) {
0fbac0b4 8912 if (json_paths)
50e05855 8913 json_object_string_add(json_path, "path",
0fbac0b4
DA
8914 attr->aspath->str);
8915 else
445c2480 8916 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8917 }
f1aa5d8a 8918
445c2480
DS
8919 /* Print origin */
8920 if (json_paths)
a4d82a8a
PZ
8921 json_object_string_add(json_path, "origin",
8922 bgp_origin_long_str[attr->origin]);
445c2480
DS
8923 else
8924 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8925
9df8b37c 8926 if (json_paths) {
d071f237 8927 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8928 json_object_string_add(json_path, "esi",
8929 esi_to_str(&attr->esi,
8930 esi_buf, sizeof(esi_buf)));
8931 }
6f214dd3
CS
8932 if (safi == SAFI_EVPN &&
8933 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8934 json_ext_community = json_object_new_object();
8935 json_object_string_add(json_ext_community,
8936 "string",
8937 attr->ecommunity->str);
8938 json_object_object_add(json_path,
8939 "extendedCommunity",
8940 json_ext_community);
8941 }
8942
9df8b37c
PZ
8943 if (nexthop_self)
8944 json_object_boolean_true_add(json_path,
8945 "announceNexthopSelf");
8946 if (nexthop_othervrf) {
8947 json_object_string_add(json_path, "nhVrfName",
8948 nexthop_vrfname);
8949
8950 json_object_int_add(json_path, "nhVrfId",
8951 ((nexthop_vrfid == VRF_UNKNOWN)
8952 ? -1
8953 : (int)nexthop_vrfid));
8954 }
8955 }
8956
d62a17ae 8957 if (json_paths) {
8958 if (json_nexthop_global || json_nexthop_ll) {
8959 json_nexthops = json_object_new_array();
f1aa5d8a 8960
d62a17ae 8961 if (json_nexthop_global)
8962 json_object_array_add(json_nexthops,
8963 json_nexthop_global);
f1aa5d8a 8964
d62a17ae 8965 if (json_nexthop_ll)
8966 json_object_array_add(json_nexthops,
8967 json_nexthop_ll);
f1aa5d8a 8968
d62a17ae 8969 json_object_object_add(json_path, "nexthops",
8970 json_nexthops);
8971 }
8972
8973 json_object_array_add(json_paths, json_path);
8974 } else {
8975 vty_out(vty, "\n");
6f214dd3 8976
b5e140c8 8977 if (safi == SAFI_EVPN) {
229587fb
AK
8978 struct bgp_path_es_info *path_es_info = NULL;
8979
d071f237 8980 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8981 /* XXX - add these params to the json out */
b5e140c8 8982 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8983 vty_out(vty, "ESI:%s",
8984 esi_to_str(&attr->esi, esi_buf,
8985 sizeof(esi_buf)));
60605cbc
AK
8986
8987 if (path->extra && path->extra->mh_info)
8988 path_es_info =
8989 path->extra->mh_info->es_info;
8990
229587fb
AK
8991 if (path_es_info && path_es_info->es)
8992 vty_out(vty, " VNI: %u",
8993 path_es_info->vni);
8994 vty_out(vty, "\n");
b5e140c8
AK
8995 }
8996 if (attr->flag &
8997 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8998 vty_out(vty, "%*s", 20, " ");
8999 vty_out(vty, "%s\n", attr->ecommunity->str);
9000 }
6f214dd3
CS
9001 }
9002
49e5a4a0 9003#ifdef ENABLE_BGP_VNC
d62a17ae 9004 /* prints an additional line, indented, with VNC info, if
9005 * present */
9006 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9007 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9008#endif
d62a17ae 9009 }
9010}
718e3744 9011
9012/* called from terminal list command */
7d3cae70
DA
9013void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9014 const struct prefix *p, struct attr *attr, safi_t safi,
9015 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9016{
9017 json_object *json_status = NULL;
9018 json_object *json_net = NULL;
aef999a2 9019 int len;
d62a17ae 9020 char buff[BUFSIZ];
dc387b0f 9021
d62a17ae 9022 /* Route status display. */
9023 if (use_json) {
9024 json_status = json_object_new_object();
9025 json_net = json_object_new_object();
9026 } else {
9027 vty_out(vty, "*");
9028 vty_out(vty, ">");
9029 vty_out(vty, " ");
9030 }
718e3744 9031
d62a17ae 9032 /* print prefix and mask */
50e05855 9033 if (use_json) {
dc387b0f
LK
9034 if (safi == SAFI_EVPN)
9035 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9036 else if (p->family == AF_INET || p->family == AF_INET6) {
9037 json_object_string_add(
9038 json_net, "addrPrefix",
9039 inet_ntop(p->family, &p->u.prefix, buff,
9040 BUFSIZ));
9041 json_object_int_add(json_net, "prefixLen",
9042 p->prefixlen);
9043 prefix2str(p, buff, PREFIX_STRLEN);
9044 json_object_string_add(json_net, "network", buff);
9045 }
50e05855 9046 } else
7d3cae70 9047 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9048
9049 /* Print attribute */
9050 if (attr) {
9051 if (use_json) {
23d0a753
DA
9052 char buf[BUFSIZ] = {0};
9053
d62a17ae 9054 if (p->family == AF_INET
9055 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9056 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9057 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 9058 json_object_string_add(
9059 json_net, "nextHop",
23d0a753
DA
9060 inet_ntop(
9061 AF_INET,
9062 &attr->mp_nexthop_global_in,
9063 buf, sizeof(buf)));
d62a17ae 9064 else
9065 json_object_string_add(
9066 json_net, "nextHop",
23d0a753
DA
9067 inet_ntop(AF_INET,
9068 &attr->nexthop, buf,
9069 sizeof(buf)));
d62a17ae 9070 } else if (p->family == AF_INET6
9071 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9072 char buf[BUFSIZ];
9073
9074 json_object_string_add(
aa0a10fc 9075 json_net, "nextHopGlobal",
d62a17ae 9076 inet_ntop(AF_INET6,
9077 &attr->mp_nexthop_global, buf,
9078 BUFSIZ));
23d0a753
DA
9079 } else if (p->family == AF_EVPN
9080 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9081 char buf[BUFSIZ] = {0};
9082
9083 json_object_string_add(
9084 json_net, "nextHop",
9085 inet_ntop(AF_INET,
9086 &attr->mp_nexthop_global_in,
9087 buf, sizeof(buf)));
9088 }
d62a17ae 9089
9090 if (attr->flag
9091 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9092 json_object_int_add(json_net, "metric",
9093 attr->med);
9094
0fbac0b4 9095 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9096 json_object_int_add(json_net, "locPrf",
0fbac0b4 9097 attr->local_pref);
d62a17ae 9098
9099 json_object_int_add(json_net, "weight", attr->weight);
9100
9101 /* Print aspath */
0fbac0b4 9102 if (attr->aspath)
50e05855 9103 json_object_string_add(json_net, "path",
0fbac0b4 9104 attr->aspath->str);
d62a17ae 9105
9106 /* Print origin */
9107 json_object_string_add(json_net, "bgpOriginCode",
9108 bgp_origin_str[attr->origin]);
9109 } else {
9110 if (p->family == AF_INET
9111 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9112 || safi == SAFI_EVPN
9113 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9114 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9115 || safi == SAFI_EVPN)
23d0a753
DA
9116 vty_out(vty, "%-16pI4",
9117 &attr->mp_nexthop_global_in);
ae248832 9118 else if (wide)
23d0a753 9119 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9120 else
23d0a753 9121 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9122 } else if (p->family == AF_INET6
9123 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9124 char buf[BUFSIZ];
9125
9126 len = vty_out(
9127 vty, "%s",
9128 inet_ntop(AF_INET6,
9129 &attr->mp_nexthop_global, buf,
9130 BUFSIZ));
ae248832 9131 len = wide ? (41 - len) : (16 - len);
d62a17ae 9132 if (len < 1)
9133 vty_out(vty, "\n%*s", 36, " ");
9134 else
9135 vty_out(vty, "%*s", len, " ");
9136 }
9137 if (attr->flag
9138 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9139 if (wide)
9140 vty_out(vty, "%7u", attr->med);
9141 else
9142 vty_out(vty, "%10u", attr->med);
9143 else if (wide)
9144 vty_out(vty, " ");
d62a17ae 9145 else
9146 vty_out(vty, " ");
718e3744 9147
d62a17ae 9148 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9149 vty_out(vty, "%7u", attr->local_pref);
9150 else
9151 vty_out(vty, " ");
9152
9153 vty_out(vty, "%7u ", attr->weight);
9154
9155 /* Print aspath */
9156 if (attr->aspath)
9157 aspath_print_vty(vty, "%s", attr->aspath, " ");
9158
9159 /* Print origin */
9160 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9161 }
9162 }
9163 if (use_json) {
9164 json_object_boolean_true_add(json_status, "*");
9165 json_object_boolean_true_add(json_status, ">");
9166 json_object_object_add(json_net, "appliedStatusSymbols",
9167 json_status);
1608ff77 9168
dc387b0f
LK
9169 prefix2str(p, buff, PREFIX_STRLEN);
9170 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9171 } else
9172 vty_out(vty, "\n");
9173}
9174
bd494ec5 9175void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9176 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9177 json_object *json)
9178{
9179 json_object *json_out = NULL;
9180 struct attr *attr;
9181 mpls_label_t label = MPLS_INVALID_LABEL;
9182
9b6d8fcf 9183 if (!path->extra)
d62a17ae 9184 return;
9185
9186 if (json)
9187 json_out = json_object_new_object();
9188
9189 /* short status lead text */
82c298be 9190 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9191
9192 /* print prefix and mask */
9193 if (json == NULL) {
9194 if (!display)
7d3cae70 9195 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9196 else
9197 vty_out(vty, "%*s", 17, " ");
9198 }
9199
9200 /* Print attribute */
9b6d8fcf 9201 attr = path->attr;
05864da7
DS
9202 if (((p->family == AF_INET)
9203 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9204 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9205 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9206 char buf[BUFSIZ] = {0};
9207
05864da7
DS
9208 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9209 || safi == SAFI_EVPN) {
9210 if (json)
9211 json_object_string_add(
9212 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9213 inet_ntop(AF_INET,
9214 &attr->mp_nexthop_global_in,
9215 buf, sizeof(buf)));
05864da7 9216 else
23d0a753
DA
9217 vty_out(vty, "%-16pI4",
9218 &attr->mp_nexthop_global_in);
05864da7
DS
9219 } else {
9220 if (json)
9221 json_object_string_add(
9222 json_out, "nexthop",
23d0a753
DA
9223 inet_ntop(AF_INET, &attr->nexthop, buf,
9224 sizeof(buf)));
05864da7 9225 else
23d0a753 9226 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9227 }
9228 } else if (((p->family == AF_INET6)
9229 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9230 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9231 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9232 char buf_a[512];
9233
9234 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9235 if (json)
9236 json_object_string_add(
9237 json_out, "mpNexthopGlobalIn",
9238 inet_ntop(AF_INET6,
9239 &attr->mp_nexthop_global,
9240 buf_a, sizeof(buf_a)));
9241 else
9242 vty_out(vty, "%s",
9243 inet_ntop(AF_INET6,
9244 &attr->mp_nexthop_global,
9245 buf_a, sizeof(buf_a)));
9246 } else if (attr->mp_nexthop_len
9247 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9248 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9249 &attr->mp_nexthop_global,
9250 &attr->mp_nexthop_local);
9251 if (json)
9252 json_object_string_add(json_out,
9253 "mpNexthopGlobalLocal",
9254 buf_a);
9255 else
9256 vty_out(vty, "%s", buf_a);
d62a17ae 9257 }
9258 }
9259
9b6d8fcf 9260 label = decode_label(&path->extra->label[0]);
d62a17ae 9261
9262 if (bgp_is_valid_label(&label)) {
9263 if (json) {
9264 json_object_int_add(json_out, "notag", label);
9265 json_object_array_add(json, json_out);
9266 } else {
9267 vty_out(vty, "notag/%d", label);
9268 vty_out(vty, "\n");
9269 }
9270 }
9271}
718e3744 9272
bd494ec5 9273void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9274 struct bgp_path_info *path, int display,
d62a17ae 9275 json_object *json_paths)
718e3744 9276{
d62a17ae 9277 struct attr *attr;
14f51eba 9278 char buf[BUFSIZ] = {0};
d62a17ae 9279 json_object *json_path = NULL;
14f51eba
LK
9280 json_object *json_nexthop = NULL;
9281 json_object *json_overlay = NULL;
856ca177 9282
9b6d8fcf 9283 if (!path->extra)
d62a17ae 9284 return;
718e3744 9285
14f51eba
LK
9286 if (json_paths) {
9287 json_path = json_object_new_object();
9288 json_overlay = json_object_new_object();
9289 json_nexthop = json_object_new_object();
9290 }
9291
d62a17ae 9292 /* short status lead text */
82c298be 9293 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9294
d62a17ae 9295 /* print prefix and mask */
9296 if (!display)
7d3cae70 9297 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9298 else
9299 vty_out(vty, "%*s", 17, " ");
9300
9301 /* Print attribute */
9b6d8fcf 9302 attr = path->attr;
05864da7
DS
9303 char buf1[BUFSIZ];
9304 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9305
05864da7
DS
9306 switch (af) {
9307 case AF_INET:
9308 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9309 if (!json_path) {
9310 vty_out(vty, "%-16s", buf);
9311 } else {
9312 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9313
05864da7 9314 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9315
05864da7
DS
9316 json_object_object_add(json_path, "nexthop",
9317 json_nexthop);
9318 }
9319 break;
9320 case AF_INET6:
9321 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9322 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9323 if (!json_path) {
9324 vty_out(vty, "%s(%s)", buf, buf1);
9325 } else {
9326 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9327
05864da7
DS
9328 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9329 buf1);
14f51eba 9330
05864da7 9331 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9332
05864da7
DS
9333 json_object_object_add(json_path, "nexthop",
9334 json_nexthop);
9335 }
9336 break;
9337 default:
9338 if (!json_path) {
9339 vty_out(vty, "?");
9340 } else {
9341 json_object_string_add(json_nexthop, "Error",
9342 "Unsupported address-family");
d62a17ae 9343 }
05864da7 9344 }
988258b4 9345
6c924775
DS
9346 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9347
9348 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9349 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9350 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9351 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9352
05864da7
DS
9353 if (!json_path)
9354 vty_out(vty, "/%s", buf);
9355 else
9356 json_object_string_add(json_overlay, "gw", buf);
9357
9358 if (attr->ecommunity) {
9359 char *mac = NULL;
9360 struct ecommunity_val *routermac = ecommunity_lookup(
9361 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9362 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9363
9364 if (routermac)
9365 mac = ecom_mac2str((char *)routermac->val);
9366 if (mac) {
9367 if (!json_path) {
c4efd0f4 9368 vty_out(vty, "/%s", mac);
05864da7
DS
9369 } else {
9370 json_object_string_add(json_overlay, "rmac",
9371 mac);
988258b4 9372 }
05864da7 9373 XFREE(MTYPE_TMP, mac);
988258b4 9374 }
05864da7 9375 }
718e3744 9376
05864da7
DS
9377 if (!json_path) {
9378 vty_out(vty, "\n");
9379 } else {
9380 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9381
05864da7 9382 json_object_array_add(json_paths, json_path);
14f51eba 9383 }
d62a17ae 9384}
718e3744 9385
d62a17ae 9386/* dampening route */
5f040085
DS
9387static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9388 struct bgp_path_info *path, int display,
9389 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9390 json_object *json_paths)
d62a17ae 9391{
e5be8c1d 9392 struct attr *attr = path->attr;
d62a17ae 9393 int len;
9394 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9395 json_object *json_path = NULL;
9396
9397 if (use_json)
9398 json_path = json_object_new_object();
d62a17ae 9399
9400 /* short status lead text */
e5be8c1d 9401 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9402
9403 /* print prefix and mask */
9404 if (!use_json) {
9405 if (!display)
7d3cae70 9406 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9407 else
9408 vty_out(vty, "%*s", 17, " ");
d62a17ae 9409
e5be8c1d
DA
9410 len = vty_out(vty, "%s", path->peer->host);
9411 len = 17 - len;
9412
9413 if (len < 1)
d62a17ae 9414 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9415 else
9416 vty_out(vty, "%*s", len, " ");
d62a17ae 9417
9b6d8fcf
DS
9418 vty_out(vty, "%s ",
9419 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9420 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9421 use_json, NULL));
d62a17ae 9422
e5be8c1d 9423 if (attr->aspath)
05864da7 9424 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9425
05864da7
DS
9426 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9427
d62a17ae 9428 vty_out(vty, "\n");
e5be8c1d
DA
9429 } else {
9430 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9431 safi, use_json, json_path);
9432
9433 if (attr->aspath)
9434 json_object_string_add(json_path, "asPath",
9435 attr->aspath->str);
9436
9437 json_object_string_add(json_path, "origin",
9438 bgp_origin_str[attr->origin]);
9439 json_object_string_add(json_path, "peerHost", path->peer->host);
9440
9441 json_object_array_add(json_paths, json_path);
9442 }
d62a17ae 9443}
718e3744 9444
d62a17ae 9445/* flap route */
5f040085
DS
9446static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9447 struct bgp_path_info *path, int display,
9448 afi_t afi, safi_t safi, bool use_json,
31258046 9449 json_object *json_paths)
784d3a42 9450{
31258046 9451 struct attr *attr = path->attr;
d62a17ae 9452 struct bgp_damp_info *bdi;
9453 char timebuf[BGP_UPTIME_LEN];
9454 int len;
31258046 9455 json_object *json_path = NULL;
784d3a42 9456
9b6d8fcf 9457 if (!path->extra)
d62a17ae 9458 return;
784d3a42 9459
31258046
DA
9460 if (use_json)
9461 json_path = json_object_new_object();
9462
9b6d8fcf 9463 bdi = path->extra->damp_info;
784d3a42 9464
d62a17ae 9465 /* short status lead text */
31258046 9466 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9467
d62a17ae 9468 if (!use_json) {
9469 if (!display)
7d3cae70 9470 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9471 else
9472 vty_out(vty, "%*s", 17, " ");
784d3a42 9473
31258046
DA
9474 len = vty_out(vty, "%s", path->peer->host);
9475 len = 16 - len;
9476 if (len < 1)
d62a17ae 9477 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9478 else
9479 vty_out(vty, "%*s", len, " ");
784d3a42 9480
31258046
DA
9481 len = vty_out(vty, "%d", bdi->flap);
9482 len = 5 - len;
9483 if (len < 1)
d62a17ae 9484 vty_out(vty, " ");
d62a17ae 9485 else
9486 vty_out(vty, "%*s", len, " ");
d62a17ae 9487
996c9314
LB
9488 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9489 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9490
31258046
DA
9491 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9492 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9493 vty_out(vty, "%s ",
9b6d8fcf 9494 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9495 BGP_UPTIME_LEN, afi,
31258046
DA
9496 safi, use_json, NULL));
9497 else
d62a17ae 9498 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9499
31258046 9500 if (attr->aspath)
05864da7 9501 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9502
05864da7
DS
9503 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9504
d62a17ae 9505 vty_out(vty, "\n");
31258046
DA
9506 } else {
9507 json_object_string_add(json_path, "peerHost", path->peer->host);
9508 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9509
9510 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9511 json_path);
9512
9513 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9514 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9515 bgp_damp_reuse_time_vty(vty, path, timebuf,
9516 BGP_UPTIME_LEN, afi, safi,
9517 use_json, json_path);
9518
9519 if (attr->aspath)
9520 json_object_string_add(json_path, "asPath",
9521 attr->aspath->str);
9522
9523 json_object_string_add(json_path, "origin",
9524 bgp_origin_str[attr->origin]);
9525
9526 json_object_array_add(json_paths, json_path);
9527 }
d62a17ae 9528}
9529
9530static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9531 int *first, const char *header,
9532 json_object *json_adv_to)
9533{
9534 char buf1[INET6_ADDRSTRLEN];
9535 json_object *json_peer = NULL;
9536
9537 if (json_adv_to) {
9538 /* 'advertised-to' is a dictionary of peers we have advertised
9539 * this
9540 * prefix too. The key is the peer's IP or swpX, the value is
9541 * the
9542 * hostname if we know it and "" if not.
9543 */
9544 json_peer = json_object_new_object();
9545
9546 if (peer->hostname)
9547 json_object_string_add(json_peer, "hostname",
9548 peer->hostname);
9549
9550 if (peer->conf_if)
9551 json_object_object_add(json_adv_to, peer->conf_if,
9552 json_peer);
9553 else
9554 json_object_object_add(
9555 json_adv_to,
9556 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9557 json_peer);
9558 } else {
9559 if (*first) {
9560 vty_out(vty, "%s", header);
9561 *first = 0;
9562 }
9563
9564 if (peer->hostname
892fedb6 9565 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9566 if (peer->conf_if)
9567 vty_out(vty, " %s(%s)", peer->hostname,
9568 peer->conf_if);
9569 else
9570 vty_out(vty, " %s(%s)", peer->hostname,
9571 sockunion2str(&peer->su, buf1,
9572 SU_ADDRSTRLEN));
9573 } else {
9574 if (peer->conf_if)
9575 vty_out(vty, " %s", peer->conf_if);
9576 else
9577 vty_out(vty, " %s",
9578 sockunion2str(&peer->su, buf1,
9579 SU_ADDRSTRLEN));
9580 }
9581 }
784d3a42
PG
9582}
9583
dcc68b5e
MS
9584static void route_vty_out_tx_ids(struct vty *vty,
9585 struct bgp_addpath_info_data *d)
9586{
9587 int i;
9588
9589 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9590 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9591 d->addpath_tx_id[i],
9592 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9593 }
9594}
9595
5e4d4c8a 9596static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9597 struct bgp_path_info *pi,
9598 struct attr *attr,
9599 json_object *json_path)
5e4d4c8a
AK
9600{
9601 char esi_buf[ESI_STR_LEN];
9602 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9603 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9604 ATTR_ES_PEER_ROUTER);
9605 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9606 ATTR_ES_PEER_ACTIVE);
9607 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9608 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9609 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9610 if (json_path) {
9611 json_object *json_es_info = NULL;
9612
9613 json_object_string_add(
9614 json_path, "esi",
9615 esi_buf);
9616 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9617 json_es_info = json_object_new_object();
9618 if (es_local)
9619 json_object_boolean_true_add(
9620 json_es_info, "localEs");
9621 if (peer_active)
9622 json_object_boolean_true_add(
9623 json_es_info, "peerActive");
9624 if (peer_proxy)
9625 json_object_boolean_true_add(
9626 json_es_info, "peerProxy");
9627 if (peer_router)
9628 json_object_boolean_true_add(
9629 json_es_info, "peerRouter");
9630 if (attr->mm_sync_seqnum)
9631 json_object_int_add(
9632 json_es_info, "peerSeq",
9633 attr->mm_sync_seqnum);
9634 json_object_object_add(
9635 json_path, "es_info",
9636 json_es_info);
9637 }
9638 } else {
9639 if (bgp_evpn_attr_is_sync(attr))
9640 vty_out(vty,
9641 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9642 esi_buf,
9643 es_local ? "local-es":"",
9644 peer_proxy ? "proxy " : "",
9645 peer_active ? "active ":"",
9646 peer_router ? "router ":"",
9647 attr->mm_sync_seqnum);
9648 else
9649 vty_out(vty, " ESI %s %s\n",
9650 esi_buf,
9651 es_local ? "local-es":"");
9652 }
9653}
9654
4933eaaf
DS
9655void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9656 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9657 enum rpki_states rpki_curr_state,
9658 json_object *json_paths)
d62a17ae 9659{
9660 char buf[INET6_ADDRSTRLEN];
9661 char buf1[BUFSIZ];
515c2602 9662 struct attr *attr = path->attr;
d62a17ae 9663 int sockunion_vty_out(struct vty *, union sockunion *);
9664 time_t tbuf;
9665 json_object *json_bestpath = NULL;
9666 json_object *json_cluster_list = NULL;
9667 json_object *json_cluster_list_list = NULL;
9668 json_object *json_ext_community = NULL;
9669 json_object *json_last_update = NULL;
7fd077aa 9670 json_object *json_pmsi = NULL;
d62a17ae 9671 json_object *json_nexthop_global = NULL;
9672 json_object *json_nexthop_ll = NULL;
9673 json_object *json_nexthops = NULL;
9674 json_object *json_path = NULL;
9675 json_object *json_peer = NULL;
9676 json_object *json_string = NULL;
9677 json_object *json_adv_to = NULL;
9678 int first = 0;
9679 struct listnode *node, *nnode;
9680 struct peer *peer;
9681 int addpath_capable;
9682 int has_adj;
9683 unsigned int first_as;
1defdda8 9684 bool nexthop_self =
9b6d8fcf 9685 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9686 int i;
2ba93fd6
DA
9687 char *nexthop_hostname =
9688 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9689
9690 if (json_paths) {
9691 json_path = json_object_new_object();
9692 json_peer = json_object_new_object();
9693 json_nexthop_global = json_object_new_object();
9694 }
9695
8304dabf
AD
9696 if (safi == SAFI_EVPN) {
9697 if (!json_paths)
9698 vty_out(vty, " Route %pRN", bn);
9699 }
9700
44c69747 9701 if (path->extra) {
b57ba6d2 9702 char tag_buf[30];
d62a17ae 9703
d62a17ae 9704 tag_buf[0] = '\0';
9b6d8fcf
DS
9705 if (path->extra && path->extra->num_labels) {
9706 bgp_evpn_label2str(path->extra->label,
9707 path->extra->num_labels, tag_buf,
a4d82a8a 9708 sizeof(tag_buf));
d62a17ae 9709 }
d7325ee7 9710 if (safi == SAFI_EVPN) {
44c69747 9711 if (!json_paths) {
44c69747
LK
9712 if (tag_buf[0] != '\0')
9713 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9714 } else {
9715 if (tag_buf[0])
9716 json_object_string_add(json_path, "VNI",
9717 tag_buf);
9718 }
d7325ee7
DD
9719 }
9720
44c69747 9721 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9722 struct bgp_path_info *parent_ri;
9bcb3eef 9723 struct bgp_dest *dest, *pdest;
d62a17ae 9724
9b6d8fcf 9725 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9726 dest = parent_ri->net;
9727 if (dest && dest->pdest) {
9728 pdest = dest->pdest;
9729 prefix_rd2str(
9730 (struct prefix_rd *)bgp_dest_get_prefix(
9731 pdest),
9732 buf1, sizeof(buf1));
d7325ee7 9733 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9734 vty_out(vty,
58bff4d1 9735 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9736 buf1,
9737 (struct prefix_evpn *)
9738 bgp_dest_get_prefix(
9739 dest),
9740 tag_buf);
58bff4d1
AK
9741 if (attr->es_flags & ATTR_ES_L3_NHG)
9742 vty_out(vty, ", L3NHG %s",
9743 (attr->es_flags
9744 & ATTR_ES_L3_NHG_ACTIVE)
9745 ? "active"
9746 : "inactive");
9747 vty_out(vty, "\n");
9748
d7325ee7 9749 } else
2dbe669b
DA
9750 vty_out(vty,
9751 " Imported from %s:%pFX\n",
9752 buf1,
9753 (struct prefix_evpn *)
9754 bgp_dest_get_prefix(
9755 dest));
d62a17ae 9756 }
9757 }
9758 }
d62a17ae 9759
8304dabf
AD
9760 if (safi == SAFI_EVPN
9761 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9762 char gwip_buf[INET6_ADDRSTRLEN];
9763
9764 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9765 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9766 gwip_buf, sizeof(gwip_buf));
9767 else
9768 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9769 gwip_buf, sizeof(gwip_buf));
9770
9771 if (json_paths)
9772 json_object_string_add(json_path, "gatewayIP",
9773 gwip_buf);
9774 else
9775 vty_out(vty, " Gateway IP %s", gwip_buf);
9776 }
9777
9778 if (safi == SAFI_EVPN)
9779 vty_out(vty, "\n");
9780
05864da7
DS
9781 /* Line1 display AS-path, Aggregator */
9782 if (attr->aspath) {
9783 if (json_paths) {
9784 if (!attr->aspath->json)
9785 aspath_str_update(attr->aspath, true);
9786 json_object_lock(attr->aspath->json);
9787 json_object_object_add(json_path, "aspath",
9788 attr->aspath->json);
9789 } else {
9790 if (attr->aspath->segments)
9791 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9792 else
05864da7 9793 vty_out(vty, " Local");
d62a17ae 9794 }
05864da7 9795 }
d62a17ae 9796
05864da7
DS
9797 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9798 if (json_paths)
9799 json_object_boolean_true_add(json_path, "removed");
9800 else
9801 vty_out(vty, ", (removed)");
9802 }
d62a17ae 9803
05864da7
DS
9804 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9805 if (json_paths)
9806 json_object_boolean_true_add(json_path, "stale");
9807 else
9808 vty_out(vty, ", (stale)");
9809 }
d62a17ae 9810
05864da7
DS
9811 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9812 if (json_paths) {
23d0a753
DA
9813 char buf[BUFSIZ] = {0};
9814
05864da7
DS
9815 json_object_int_add(json_path, "aggregatorAs",
9816 attr->aggregator_as);
23d0a753
DA
9817 json_object_string_add(json_path, "aggregatorId",
9818 inet_ntop(AF_INET,
9819 &attr->aggregator_addr,
9820 buf, sizeof(buf)));
05864da7 9821 } else {
88d495a9
DA
9822 vty_out(vty, ", (aggregated by %u %pI4)",
9823 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9824 }
05864da7 9825 }
d62a17ae 9826
05864da7
DS
9827 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9828 PEER_FLAG_REFLECTOR_CLIENT)) {
9829 if (json_paths)
9830 json_object_boolean_true_add(json_path,
9831 "rxedFromRrClient");
9832 else
9833 vty_out(vty, ", (Received from a RR-client)");
9834 }
d62a17ae 9835
05864da7
DS
9836 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9837 PEER_FLAG_RSERVER_CLIENT)) {
9838 if (json_paths)
9839 json_object_boolean_true_add(json_path,
9840 "rxedFromRsClient");
9841 else
9842 vty_out(vty, ", (Received from a RS-client)");
9843 }
d62a17ae 9844
05864da7
DS
9845 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9846 if (json_paths)
9847 json_object_boolean_true_add(json_path,
9848 "dampeningHistoryEntry");
9849 else
9850 vty_out(vty, ", (history entry)");
9851 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9852 if (json_paths)
9853 json_object_boolean_true_add(json_path,
9854 "dampeningSuppressed");
9855 else
9856 vty_out(vty, ", (suppressed due to dampening)");
9857 }
d62a17ae 9858
05864da7
DS
9859 if (!json_paths)
9860 vty_out(vty, "\n");
d62a17ae 9861
05864da7
DS
9862 /* Line2 display Next-hop, Neighbor, Router-id */
9863 /* Display the nexthop */
9bcb3eef 9864 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9865
9866 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9867 || bn_p->family == AF_EVPN)
05864da7
DS
9868 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9869 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9870 char buf[BUFSIZ] = {0};
9871
05864da7
DS
9872 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9873 || safi == SAFI_EVPN) {
515c2602 9874 if (json_paths) {
d62a17ae 9875 json_object_string_add(
515c2602 9876 json_nexthop_global, "ip",
23d0a753
DA
9877 inet_ntop(AF_INET,
9878 &attr->mp_nexthop_global_in,
9879 buf, sizeof(buf)));
515c2602 9880
939a97f4 9881 if (path->peer->hostname)
515c2602
DA
9882 json_object_string_add(
9883 json_nexthop_global, "hostname",
939a97f4 9884 path->peer->hostname);
aef999a2
DA
9885 } else {
9886 if (nexthop_hostname)
9887 vty_out(vty, " %pI4(%s)",
9888 &attr->mp_nexthop_global_in,
9889 nexthop_hostname);
9890 else
9891 vty_out(vty, " %pI4",
9892 &attr->mp_nexthop_global_in);
9893 }
d62a17ae 9894 } else {
515c2602 9895 if (json_paths) {
05864da7 9896 json_object_string_add(
515c2602 9897 json_nexthop_global, "ip",
23d0a753
DA
9898 inet_ntop(AF_INET, &attr->nexthop, buf,
9899 sizeof(buf)));
515c2602 9900
939a97f4 9901 if (path->peer->hostname)
515c2602
DA
9902 json_object_string_add(
9903 json_nexthop_global, "hostname",
939a97f4 9904 path->peer->hostname);
aef999a2
DA
9905 } else {
9906 if (nexthop_hostname)
9907 vty_out(vty, " %pI4(%s)",
9908 &attr->nexthop,
9909 nexthop_hostname);
9910 else
9911 vty_out(vty, " %pI4",
9912 &attr->nexthop);
9913 }
d62a17ae 9914 }
9915
05864da7
DS
9916 if (json_paths)
9917 json_object_string_add(json_nexthop_global, "afi",
9918 "ipv4");
9919 } else {
9920 if (json_paths) {
9921 json_object_string_add(
515c2602
DA
9922 json_nexthop_global, "ip",
9923 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9924 buf, INET6_ADDRSTRLEN));
9925
939a97f4 9926 if (path->peer->hostname)
515c2602
DA
9927 json_object_string_add(json_nexthop_global,
9928 "hostname",
939a97f4 9929 path->peer->hostname);
515c2602 9930
05864da7
DS
9931 json_object_string_add(json_nexthop_global, "afi",
9932 "ipv6");
9933 json_object_string_add(json_nexthop_global, "scope",
9934 "global");
9935 } else {
aef999a2
DA
9936 if (nexthop_hostname)
9937 vty_out(vty, " %pI6(%s)",
9938 &attr->mp_nexthop_global,
9939 nexthop_hostname);
9940 else
9941 vty_out(vty, " %pI6",
9942 &attr->mp_nexthop_global);
d62a17ae 9943 }
05864da7 9944 }
d62a17ae 9945
05864da7
DS
9946 /* Display the IGP cost or 'inaccessible' */
9947 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9948 if (json_paths)
9949 json_object_boolean_false_add(json_nexthop_global,
9950 "accessible");
9951 else
9952 vty_out(vty, " (inaccessible)");
9953 } else {
9954 if (path->extra && path->extra->igpmetric) {
d62a17ae 9955 if (json_paths)
05864da7
DS
9956 json_object_int_add(json_nexthop_global,
9957 "metric",
9958 path->extra->igpmetric);
d62a17ae 9959 else
05864da7
DS
9960 vty_out(vty, " (metric %u)",
9961 path->extra->igpmetric);
d62a17ae 9962 }
9963
05864da7 9964 /* IGP cost is 0, display this only for json */
d62a17ae 9965 else {
d62a17ae 9966 if (json_paths)
05864da7
DS
9967 json_object_int_add(json_nexthop_global,
9968 "metric", 0);
d62a17ae 9969 }
d62a17ae 9970
05864da7
DS
9971 if (json_paths)
9972 json_object_boolean_true_add(json_nexthop_global,
9973 "accessible");
9974 }
d62a17ae 9975
05864da7
DS
9976 /* Display peer "from" output */
9977 /* This path was originated locally */
9978 if (path->peer == bgp->peer_self) {
d62a17ae 9979
05864da7 9980 if (safi == SAFI_EVPN
b54892e0 9981 || (bn_p->family == AF_INET
05864da7 9982 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9983 if (json_paths)
05864da7
DS
9984 json_object_string_add(json_peer, "peerId",
9985 "0.0.0.0");
d62a17ae 9986 else
05864da7
DS
9987 vty_out(vty, " from 0.0.0.0 ");
9988 } else {
d62a17ae 9989 if (json_paths)
05864da7
DS
9990 json_object_string_add(json_peer, "peerId",
9991 "::");
d62a17ae 9992 else
05864da7 9993 vty_out(vty, " from :: ");
d62a17ae 9994 }
d62a17ae 9995
23d0a753
DA
9996 if (json_paths) {
9997 char buf[BUFSIZ] = {0};
9998
05864da7 9999 json_object_string_add(json_peer, "routerId",
23d0a753
DA
10000 inet_ntop(AF_INET,
10001 &bgp->router_id, buf,
10002 sizeof(buf)));
10003 } else {
10004 vty_out(vty, "(%pI4)", &bgp->router_id);
10005 }
05864da7 10006 }
d62a17ae 10007
05864da7
DS
10008 /* We RXed this path from one of our peers */
10009 else {
10010
10011 if (json_paths) {
10012 json_object_string_add(json_peer, "peerId",
10013 sockunion2str(&path->peer->su,
10014 buf,
10015 SU_ADDRSTRLEN));
10016 json_object_string_add(json_peer, "routerId",
10017 inet_ntop(AF_INET,
10018 &path->peer->remote_id,
10019 buf1, sizeof(buf1)));
10020
10021 if (path->peer->hostname)
10022 json_object_string_add(json_peer, "hostname",
10023 path->peer->hostname);
10024
10025 if (path->peer->domainname)
10026 json_object_string_add(json_peer, "domainname",
10027 path->peer->domainname);
10028
10029 if (path->peer->conf_if)
10030 json_object_string_add(json_peer, "interface",
10031 path->peer->conf_if);
10032 } else {
10033 if (path->peer->conf_if) {
10034 if (path->peer->hostname
892fedb6
DA
10035 && CHECK_FLAG(path->peer->bgp->flags,
10036 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10037 vty_out(vty, " from %s(%s)",
10038 path->peer->hostname,
10039 path->peer->conf_if);
d62a17ae 10040 else
05864da7 10041 vty_out(vty, " from %s",
9b6d8fcf 10042 path->peer->conf_if);
d62a17ae 10043 } else {
05864da7 10044 if (path->peer->hostname
892fedb6
DA
10045 && CHECK_FLAG(path->peer->bgp->flags,
10046 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10047 vty_out(vty, " from %s(%s)",
10048 path->peer->hostname,
10049 path->peer->host);
d62a17ae 10050 else
05864da7
DS
10051 vty_out(vty, " from %s",
10052 sockunion2str(&path->peer->su,
10053 buf,
10054 SU_ADDRSTRLEN));
d62a17ae 10055 }
d62a17ae 10056
05864da7 10057 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10058 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10059 else
10060 vty_out(vty, " (%s)",
10061 inet_ntop(AF_INET,
10062 &path->peer->remote_id, buf1,
10063 sizeof(buf1)));
d62a17ae 10064 }
05864da7 10065 }
9df8b37c 10066
05864da7
DS
10067 /*
10068 * Note when vrfid of nexthop is different from that of prefix
10069 */
10070 if (path->extra && path->extra->bgp_orig) {
10071 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10072
05864da7
DS
10073 if (json_paths) {
10074 const char *vn;
9df8b37c 10075
05864da7
DS
10076 if (path->extra->bgp_orig->inst_type
10077 == BGP_INSTANCE_TYPE_DEFAULT)
10078 vn = VRF_DEFAULT_NAME;
10079 else
10080 vn = path->extra->bgp_orig->name;
9df8b37c 10081
05864da7 10082 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10083
05864da7
DS
10084 if (nexthop_vrfid == VRF_UNKNOWN) {
10085 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10086 } else {
05864da7
DS
10087 json_object_int_add(json_path, "nhVrfId",
10088 (int)nexthop_vrfid);
9df8b37c 10089 }
05864da7
DS
10090 } else {
10091 if (nexthop_vrfid == VRF_UNKNOWN)
10092 vty_out(vty, " vrf ?");
137147c6
DS
10093 else {
10094 struct vrf *vrf;
10095
10096 vrf = vrf_lookup_by_id(nexthop_vrfid);
10097 vty_out(vty, " vrf %s(%u)",
10098 VRF_LOGNAME(vrf), nexthop_vrfid);
10099 }
9df8b37c 10100 }
05864da7 10101 }
9df8b37c 10102
05864da7
DS
10103 if (nexthop_self) {
10104 if (json_paths) {
10105 json_object_boolean_true_add(json_path,
10106 "announceNexthopSelf");
10107 } else {
10108 vty_out(vty, " announce-nh-self");
9df8b37c 10109 }
05864da7 10110 }
9df8b37c 10111
05864da7
DS
10112 if (!json_paths)
10113 vty_out(vty, "\n");
d62a17ae 10114
05864da7
DS
10115 /* display the link-local nexthop */
10116 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10117 if (json_paths) {
10118 json_nexthop_ll = json_object_new_object();
10119 json_object_string_add(
515c2602
DA
10120 json_nexthop_ll, "ip",
10121 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10122 buf, INET6_ADDRSTRLEN));
10123
939a97f4 10124 if (path->peer->hostname)
515c2602
DA
10125 json_object_string_add(json_nexthop_ll,
10126 "hostname",
939a97f4 10127 path->peer->hostname);
515c2602 10128
05864da7
DS
10129 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10130 json_object_string_add(json_nexthop_ll, "scope",
10131 "link-local");
d62a17ae 10132
05864da7
DS
10133 json_object_boolean_true_add(json_nexthop_ll,
10134 "accessible");
d62a17ae 10135
05864da7 10136 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10137 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10138 "used");
10139 else
10140 json_object_boolean_true_add(
10141 json_nexthop_global, "used");
10142 } else {
10143 vty_out(vty, " (%s) %s\n",
10144 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10145 buf, INET6_ADDRSTRLEN),
10146 attr->mp_nexthop_prefer_global
10147 ? "(prefer-global)"
10148 : "(used)");
d62a17ae 10149 }
05864da7
DS
10150 }
10151 /* If we do not have a link-local nexthop then we must flag the
10152 global as "used" */
10153 else {
10154 if (json_paths)
10155 json_object_boolean_true_add(json_nexthop_global,
10156 "used");
10157 }
d62a17ae 10158
b5e140c8 10159 if (safi == SAFI_EVPN &&
5e4d4c8a 10160 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10161 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10162 }
10163
05864da7
DS
10164 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10165 * Int/Ext/Local, Atomic, best */
10166 if (json_paths)
10167 json_object_string_add(json_path, "origin",
10168 bgp_origin_long_str[attr->origin]);
10169 else
10170 vty_out(vty, " Origin %s",
10171 bgp_origin_long_str[attr->origin]);
9df8b37c 10172
05864da7 10173 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10174 if (json_paths)
05864da7 10175 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10176 else
05864da7
DS
10177 vty_out(vty, ", metric %u", attr->med);
10178 }
9df8b37c 10179
05864da7
DS
10180 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10181 if (json_paths)
0fbac0b4 10182 json_object_int_add(json_path, "locPrf",
05864da7
DS
10183 attr->local_pref);
10184 else
10185 vty_out(vty, ", localpref %u", attr->local_pref);
10186 }
9df8b37c 10187
05864da7
DS
10188 if (attr->weight != 0) {
10189 if (json_paths)
10190 json_object_int_add(json_path, "weight", attr->weight);
10191 else
10192 vty_out(vty, ", weight %u", attr->weight);
10193 }
9df8b37c 10194
05864da7
DS
10195 if (attr->tag != 0) {
10196 if (json_paths)
10197 json_object_int_add(json_path, "tag", attr->tag);
10198 else
10199 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10200 }
9df8b37c 10201
05864da7
DS
10202 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10203 if (json_paths)
10204 json_object_boolean_false_add(json_path, "valid");
10205 else
10206 vty_out(vty, ", invalid");
10207 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10208 if (json_paths)
10209 json_object_boolean_true_add(json_path, "valid");
10210 else
10211 vty_out(vty, ", valid");
10212 }
9df8b37c 10213
7d3cae70
DA
10214 if (json_paths)
10215 json_object_int_add(json_path, "version", bn->version);
10216
05864da7
DS
10217 if (path->peer != bgp->peer_self) {
10218 if (path->peer->as == path->peer->local_as) {
10219 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10220 if (json_paths)
10221 json_object_string_add(
10222 json_peer, "type",
10223 "confed-internal");
d62a17ae 10224 else
05864da7 10225 vty_out(vty, ", confed-internal");
d62a17ae 10226 } else {
05864da7
DS
10227 if (json_paths)
10228 json_object_string_add(
10229 json_peer, "type", "internal");
10230 else
10231 vty_out(vty, ", internal");
9df8b37c 10232 }
05864da7
DS
10233 } else {
10234 if (bgp_confederation_peers_check(bgp,
10235 path->peer->as)) {
10236 if (json_paths)
10237 json_object_string_add(
10238 json_peer, "type",
10239 "confed-external");
d62a17ae 10240 else
05864da7 10241 vty_out(vty, ", confed-external");
d62a17ae 10242 } else {
05864da7
DS
10243 if (json_paths)
10244 json_object_string_add(
10245 json_peer, "type", "external");
10246 else
10247 vty_out(vty, ", external");
d62a17ae 10248 }
10249 }
05864da7
DS
10250 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10251 if (json_paths) {
10252 json_object_boolean_true_add(json_path, "aggregated");
10253 json_object_boolean_true_add(json_path, "local");
10254 } else {
10255 vty_out(vty, ", aggregated, local");
10256 }
10257 } else if (path->type != ZEBRA_ROUTE_BGP) {
10258 if (json_paths)
10259 json_object_boolean_true_add(json_path, "sourced");
10260 else
10261 vty_out(vty, ", sourced");
10262 } else {
10263 if (json_paths) {
10264 json_object_boolean_true_add(json_path, "sourced");
10265 json_object_boolean_true_add(json_path, "local");
10266 } else {
10267 vty_out(vty, ", sourced, local");
d62a17ae 10268 }
05864da7 10269 }
718e3744 10270
05864da7 10271 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10272 if (json_paths)
05864da7
DS
10273 json_object_boolean_true_add(json_path,
10274 "atomicAggregate");
d62a17ae 10275 else
05864da7
DS
10276 vty_out(vty, ", atomic-aggregate");
10277 }
d62a17ae 10278
05864da7
DS
10279 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10280 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10281 && bgp_path_info_mpath_count(path))) {
10282 if (json_paths)
10283 json_object_boolean_true_add(json_path, "multipath");
10284 else
10285 vty_out(vty, ", multipath");
10286 }
50e05855 10287
05864da7
DS
10288 // Mark the bestpath(s)
10289 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10290 first_as = aspath_get_first_as(attr->aspath);
718e3744 10291
05864da7
DS
10292 if (json_paths) {
10293 if (!json_bestpath)
10294 json_bestpath = json_object_new_object();
10295 json_object_int_add(json_bestpath, "bestpathFromAs",
10296 first_as);
10297 } else {
10298 if (first_as)
10299 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10300 else
05864da7 10301 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10302 }
05864da7 10303 }
718e3744 10304
05864da7
DS
10305 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10306 if (json_paths) {
10307 if (!json_bestpath)
10308 json_bestpath = json_object_new_object();
10309 json_object_boolean_true_add(json_bestpath, "overall");
10310 json_object_string_add(
10311 json_bestpath, "selectionReason",
10312 bgp_path_selection_reason2str(bn->reason));
10313 } else {
10314 vty_out(vty, ", best");
10315 vty_out(vty, " (%s)",
10316 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10317 }
05864da7 10318 }
718e3744 10319
4027d19b 10320 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10321 if (json_paths)
10322 json_object_string_add(
10323 json_path, "rpkiValidationState",
4027d19b 10324 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10325 else
1d327209 10326 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10327 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10328 }
10329
05864da7
DS
10330 if (json_bestpath)
10331 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10332
05864da7
DS
10333 if (!json_paths)
10334 vty_out(vty, "\n");
10335
10336 /* Line 4 display Community */
29e72930 10337 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10338 if (json_paths) {
10339 if (!attr->community->json)
10340 community_str(attr->community, true);
10341 json_object_lock(attr->community->json);
10342 json_object_object_add(json_path, "community",
10343 attr->community->json);
10344 } else {
10345 vty_out(vty, " Community: %s\n",
10346 attr->community->str);
d62a17ae 10347 }
05864da7 10348 }
718e3744 10349
05864da7
DS
10350 /* Line 5 display Extended-community */
10351 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10352 if (json_paths) {
10353 json_ext_community = json_object_new_object();
10354 json_object_string_add(json_ext_community, "string",
10355 attr->ecommunity->str);
10356 json_object_object_add(json_path, "extendedCommunity",
10357 json_ext_community);
d62a17ae 10358 } else {
05864da7
DS
10359 vty_out(vty, " Extended Community: %s\n",
10360 attr->ecommunity->str);
d62a17ae 10361 }
05864da7 10362 }
718e3744 10363
05864da7
DS
10364 /* Line 6 display Large community */
10365 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10366 if (json_paths) {
10367 if (!attr->lcommunity->json)
10368 lcommunity_str(attr->lcommunity, true);
10369 json_object_lock(attr->lcommunity->json);
10370 json_object_object_add(json_path, "largeCommunity",
10371 attr->lcommunity->json);
10372 } else {
10373 vty_out(vty, " Large Community: %s\n",
10374 attr->lcommunity->str);
d62a17ae 10375 }
05864da7 10376 }
718e3744 10377
05864da7
DS
10378 /* Line 7 display Originator, Cluster-id */
10379 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10380 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10381 char buf[BUFSIZ] = {0};
10382
05864da7 10383 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10384 if (json_paths)
05864da7
DS
10385 json_object_string_add(
10386 json_path, "originatorId",
23d0a753
DA
10387 inet_ntop(AF_INET, &attr->originator_id,
10388 buf, sizeof(buf)));
d62a17ae 10389 else
23d0a753
DA
10390 vty_out(vty, " Originator: %pI4",
10391 &attr->originator_id);
d62a17ae 10392 }
856ca177 10393
05864da7 10394 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10395 struct cluster_list *cluster =
10396 bgp_attr_get_cluster(attr);
05864da7 10397 int i;
d62a17ae 10398
10399 if (json_paths) {
05864da7
DS
10400 json_cluster_list = json_object_new_object();
10401 json_cluster_list_list =
10402 json_object_new_array();
10403
779fee93 10404 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10405 json_string = json_object_new_string(
779fee93
DS
10406 inet_ntop(AF_INET,
10407 &cluster->list[i],
10408 buf, sizeof(buf)));
05864da7
DS
10409 json_object_array_add(
10410 json_cluster_list_list,
10411 json_string);
10412 }
718e3744 10413
05864da7
DS
10414 /*
10415 * struct cluster_list does not have
10416 * "str" variable like aspath and community
10417 * do. Add this someday if someone asks
10418 * for it.
10419 * json_object_string_add(json_cluster_list,
779fee93 10420 * "string", cluster->str);
05864da7
DS
10421 */
10422 json_object_object_add(json_cluster_list,
10423 "list",
10424 json_cluster_list_list);
10425 json_object_object_add(json_path, "clusterList",
10426 json_cluster_list);
0dc8ee70 10427 } else {
05864da7
DS
10428 vty_out(vty, ", Cluster list: ");
10429
779fee93 10430 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10431 vty_out(vty, "%pI4 ",
779fee93 10432 &cluster->list[i]);
05864da7 10433 }
0dc8ee70 10434 }
d62a17ae 10435 }
718e3744 10436
d62a17ae 10437 if (!json_paths)
10438 vty_out(vty, "\n");
05864da7 10439 }
d62a17ae 10440
05864da7 10441 if (path->extra && path->extra->damp_info)
b4f7f45b 10442 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10443
05864da7
DS
10444 /* Remote Label */
10445 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10446 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10447 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10448
05864da7
DS
10449 if (json_paths)
10450 json_object_int_add(json_path, "remoteLabel", label);
10451 else
10452 vty_out(vty, " Remote label: %d\n", label);
10453 }
d62a17ae 10454
e496b420
HS
10455 /* Remote SID */
10456 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10457 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10458 if (json_paths)
10459 json_object_string_add(json_path, "remoteSid", buf);
10460 else
10461 vty_out(vty, " Remote SID: %s\n", buf);
10462 }
10463
05864da7
DS
10464 /* Label Index */
10465 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10466 if (json_paths)
10467 json_object_int_add(json_path, "labelIndex",
10468 attr->label_index);
10469 else
10470 vty_out(vty, " Label Index: %d\n",
10471 attr->label_index);
10472 }
d62a17ae 10473
05864da7
DS
10474 /* Line 8 display Addpath IDs */
10475 if (path->addpath_rx_id
10476 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10477 if (json_paths) {
10478 json_object_int_add(json_path, "addpathRxId",
10479 path->addpath_rx_id);
d62a17ae 10480
05864da7
DS
10481 /* Keep backwards compatibility with the old API
10482 * by putting TX All's ID in the old field
10483 */
10484 json_object_int_add(
10485 json_path, "addpathTxId",
10486 path->tx_addpath
10487 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10488
05864da7
DS
10489 /* ... but create a specific field for each
10490 * strategy
10491 */
10492 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10493 json_object_int_add(
10494 json_path,
10495 bgp_addpath_names(i)->id_json_name,
10496 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10497 }
05864da7
DS
10498 } else {
10499 vty_out(vty, " AddPath ID: RX %u, ",
10500 path->addpath_rx_id);
d62a17ae 10501
05864da7 10502 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10503 }
05864da7 10504 }
520d5d76 10505
05864da7
DS
10506 /* If we used addpath to TX a non-bestpath we need to display
10507 * "Advertised to" on a path-by-path basis
10508 */
10509 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10510 first = 1;
dcc68b5e 10511
05864da7
DS
10512 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10513 addpath_capable =
10514 bgp_addpath_encode_tx(peer, afi, safi);
10515 has_adj = bgp_adj_out_lookup(
10516 peer, path->net,
10517 bgp_addpath_id_for_peer(peer, afi, safi,
10518 &path->tx_addpath));
10519
10520 if ((addpath_capable && has_adj)
10521 || (!addpath_capable && has_adj
10522 && CHECK_FLAG(path->flags,
10523 BGP_PATH_SELECTED))) {
10524 if (json_path && !json_adv_to)
10525 json_adv_to = json_object_new_object();
dcc68b5e 10526
05864da7
DS
10527 route_vty_out_advertised_to(
10528 vty, peer, &first,
10529 " Advertised to:", json_adv_to);
d62a17ae 10530 }
10531 }
718e3744 10532
05864da7
DS
10533 if (json_path) {
10534 if (json_adv_to) {
10535 json_object_object_add(
10536 json_path, "advertisedTo", json_adv_to);
d62a17ae 10537 }
05864da7
DS
10538 } else {
10539 if (!first) {
10540 vty_out(vty, "\n");
d62a17ae 10541 }
10542 }
05864da7 10543 }
b05a1c8b 10544
05864da7
DS
10545 /* Line 9 display Uptime */
10546 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10547 if (json_paths) {
10548 json_last_update = json_object_new_object();
10549 json_object_int_add(json_last_update, "epoch", tbuf);
10550 json_object_string_add(json_last_update, "string",
10551 ctime(&tbuf));
10552 json_object_object_add(json_path, "lastUpdate",
10553 json_last_update);
10554 } else
10555 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10556
05864da7
DS
10557 /* Line 10 display PMSI tunnel attribute, if present */
10558 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10559 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10560 bgp_attr_get_pmsi_tnl_type(attr),
10561 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10562
05864da7
DS
10563 if (json_paths) {
10564 json_pmsi = json_object_new_object();
10565 json_object_string_add(json_pmsi, "tunnelType", str);
10566 json_object_int_add(json_pmsi, "label",
10567 label2vni(&attr->label));
10568 json_object_object_add(json_path, "pmsi", json_pmsi);
10569 } else
10570 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10571 str, label2vni(&attr->label));
d62a17ae 10572 }
f1aa5d8a 10573
92269aa2
DS
10574 /* Output some debug about internal state of the dest flags */
10575 if (json_paths) {
10576 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10577 json_object_boolean_true_add(json_path, "processScheduled");
10578 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10579 json_object_boolean_true_add(json_path, "userCleared");
10580 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10581 json_object_boolean_true_add(json_path, "labelChanged");
10582 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10583 json_object_boolean_true_add(json_path, "registeredForLabel");
10584 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10585 json_object_boolean_true_add(json_path, "selectDefered");
10586 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10587 json_object_boolean_true_add(json_path, "fibInstalled");
10588 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10589 json_object_boolean_true_add(json_path, "fibPending");
10590 }
10591
d62a17ae 10592 /* We've constructed the json object for this path, add it to the json
10593 * array of paths
10594 */
10595 if (json_paths) {
10596 if (json_nexthop_global || json_nexthop_ll) {
10597 json_nexthops = json_object_new_array();
f1aa5d8a 10598
d62a17ae 10599 if (json_nexthop_global)
10600 json_object_array_add(json_nexthops,
10601 json_nexthop_global);
f1aa5d8a 10602
d62a17ae 10603 if (json_nexthop_ll)
10604 json_object_array_add(json_nexthops,
10605 json_nexthop_ll);
f1aa5d8a 10606
d62a17ae 10607 json_object_object_add(json_path, "nexthops",
10608 json_nexthops);
10609 }
10610
10611 json_object_object_add(json_path, "peer", json_peer);
10612 json_object_array_add(json_paths, json_path);
05864da7 10613 }
b366b518
BB
10614}
10615
96ade3ed 10616#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10617#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10618#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10619
d62a17ae 10620static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10621 const char *prefix_list_str, afi_t afi,
10622 safi_t safi, enum bgp_show_type type);
10623static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10624 const char *filter, afi_t afi, safi_t safi,
10625 enum bgp_show_type type);
10626static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10627 const char *rmap_str, afi_t afi, safi_t safi,
10628 enum bgp_show_type type);
10629static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10630 const char *com, int exact, afi_t afi,
10631 safi_t safi);
10632static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10633 const char *prefix, afi_t afi, safi_t safi,
10634 enum bgp_show_type type);
a4d82a8a 10635static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10636 afi_t afi, safi_t safi, enum bgp_show_type type,
10637 bool use_json);
7f323236
DW
10638static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10639 const char *comstr, int exact, afi_t afi,
96c81f66 10640 safi_t safi, uint16_t show_flags);
d62a17ae 10641
1ae44dfc 10642static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10643 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10644 void *output_arg, char *rd, int is_last,
10645 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10646 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10647 enum rpki_states rpki_target_state)
d62a17ae 10648{
40381db7 10649 struct bgp_path_info *pi;
9bcb3eef 10650 struct bgp_dest *dest;
d62a17ae 10651 int header = 1;
10652 int display;
1ae44dfc
LB
10653 unsigned long output_count = 0;
10654 unsigned long total_count = 0;
d62a17ae 10655 struct prefix *p;
d62a17ae 10656 json_object *json_paths = NULL;
10657 int first = 1;
96f3485c
MK
10658 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10659 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10660 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10661
1ae44dfc
LB
10662 if (output_cum && *output_cum != 0)
10663 header = 0;
10664
9386b588 10665 if (use_json && !*json_header_depth) {
96f3485c
MK
10666 if (all)
10667 *json_header_depth = 1;
10668 else {
10669 vty_out(vty, "{\n");
10670 *json_header_depth = 2;
10671 }
10672
d62a17ae 10673 vty_out(vty,
23d0a753
DA
10674 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10675 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10676 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10677 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10678 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10679 ? VRF_DEFAULT_NAME
10680 : bgp->name,
10681 table->version, &bgp->router_id,
01eced22 10682 bgp->default_local_pref, bgp->as);
9386b588 10683 if (rd) {
445c2480 10684 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10685 ++*json_header_depth;
10686 }
d62a17ae 10687 }
718e3744 10688
445c2480
DS
10689 if (use_json && rd) {
10690 vty_out(vty, " \"%s\" : { ", rd);
10691 }
10692
d62a17ae 10693 /* Start processing of routes. */
9bcb3eef
DS
10694 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10695 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10696 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10697
9bcb3eef 10698 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10699 if (pi == NULL)
98ce9a06 10700 continue;
d62a17ae 10701
98ce9a06 10702 display = 0;
98ce9a06
DS
10703 if (use_json)
10704 json_paths = json_object_new_array();
10705 else
10706 json_paths = NULL;
d62a17ae 10707
6f94b685 10708 for (; pi; pi = pi->next) {
98ce9a06 10709 total_count++;
1e2ce4f1 10710
7d3cae70
DA
10711 if (type == bgp_show_type_prefix_version) {
10712 uint32_t version =
10713 strtoul(output_arg, NULL, 10);
10714 if (dest->version < version)
10715 continue;
10716 }
10717
a70a28a5
DA
10718 if (type == bgp_show_type_community_alias) {
10719 char *alias = output_arg;
10720 char **communities;
10721 int num;
10722 bool found = false;
10723
10724 if (pi->attr->community) {
10725 frrstr_split(pi->attr->community->str,
10726 " ", &communities, &num);
10727 for (int i = 0; i < num; i++) {
10728 const char *com2alias =
10729 bgp_community2alias(
10730 communities[i]);
35a45e80 10731 if (strcmp(alias, com2alias)
a70a28a5
DA
10732 == 0) {
10733 found = true;
10734 break;
10735 }
10736 }
10737 }
10738
10739 if (!found && pi->attr->lcommunity) {
10740 frrstr_split(pi->attr->lcommunity->str,
10741 " ", &communities, &num);
10742 for (int i = 0; i < num; i++) {
10743 const char *com2alias =
10744 bgp_community2alias(
10745 communities[i]);
35a45e80 10746 if (strcmp(alias, com2alias)
a70a28a5
DA
10747 == 0) {
10748 found = true;
10749 break;
10750 }
10751 }
10752 }
10753
10754 if (!found)
10755 continue;
10756 }
10757
1e2ce4f1
DS
10758 if (type == bgp_show_type_rpki) {
10759 if (dest_p->family == AF_INET
10760 || dest_p->family == AF_INET6)
4027d19b 10761 rpki_curr_state = hook_call(
1e2ce4f1
DS
10762 bgp_rpki_prefix_status,
10763 pi->peer, pi->attr, dest_p);
4027d19b
DS
10764 if (rpki_target_state != RPKI_NOT_BEING_USED
10765 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10766 continue;
10767 }
10768
98ce9a06
DS
10769 if (type == bgp_show_type_flap_statistics
10770 || type == bgp_show_type_flap_neighbor
10771 || type == bgp_show_type_dampend_paths
10772 || type == bgp_show_type_damp_neighbor) {
40381db7 10773 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10774 continue;
10775 }
10776 if (type == bgp_show_type_regexp) {
10777 regex_t *regex = output_arg;
d62a17ae 10778
40381db7 10779 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10780 == REG_NOMATCH)
10781 continue;
10782 }
10783 if (type == bgp_show_type_prefix_list) {
10784 struct prefix_list *plist = output_arg;
d62a17ae 10785
9bcb3eef 10786 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10787 != PREFIX_PERMIT)
10788 continue;
10789 }
10790 if (type == bgp_show_type_filter_list) {
10791 struct as_list *as_list = output_arg;
d62a17ae 10792
40381db7 10793 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10794 != AS_FILTER_PERMIT)
10795 continue;
10796 }
10797 if (type == bgp_show_type_route_map) {
10798 struct route_map *rmap = output_arg;
9b6d8fcf 10799 struct bgp_path_info path;
98ce9a06 10800 struct attr dummy_attr;
b68885f9 10801 route_map_result_t ret;
d62a17ae 10802
6f4f49b2 10803 dummy_attr = *pi->attr;
d62a17ae 10804
40381db7 10805 path.peer = pi->peer;
9b6d8fcf 10806 path.attr = &dummy_attr;
d62a17ae 10807
1782514f 10808 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10809 if (ret == RMAP_DENYMATCH)
10810 continue;
10811 }
10812 if (type == bgp_show_type_neighbor
10813 || type == bgp_show_type_flap_neighbor
10814 || type == bgp_show_type_damp_neighbor) {
10815 union sockunion *su = output_arg;
10816
40381db7
DS
10817 if (pi->peer == NULL
10818 || pi->peer->su_remote == NULL
10819 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10820 continue;
10821 }
10822 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10823 uint32_t destination;
d62a17ae 10824
9bcb3eef 10825 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10826 if (IN_CLASSC(destination)
9bcb3eef 10827 && dest_p->prefixlen == 24)
98ce9a06
DS
10828 continue;
10829 if (IN_CLASSB(destination)
9bcb3eef 10830 && dest_p->prefixlen == 16)
98ce9a06
DS
10831 continue;
10832 if (IN_CLASSA(destination)
9bcb3eef 10833 && dest_p->prefixlen == 8)
98ce9a06
DS
10834 continue;
10835 }
10836 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10837 p = output_arg;
9bcb3eef 10838 if (!prefix_match(p, dest_p))
98ce9a06
DS
10839 continue;
10840 }
10841 if (type == bgp_show_type_community_all) {
40381db7 10842 if (!pi->attr->community)
98ce9a06
DS
10843 continue;
10844 }
10845 if (type == bgp_show_type_community) {
10846 struct community *com = output_arg;
d62a17ae 10847
40381db7
DS
10848 if (!pi->attr->community
10849 || !community_match(pi->attr->community,
98ce9a06
DS
10850 com))
10851 continue;
10852 }
10853 if (type == bgp_show_type_community_exact) {
10854 struct community *com = output_arg;
d62a17ae 10855
40381db7
DS
10856 if (!pi->attr->community
10857 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10858 continue;
10859 }
10860 if (type == bgp_show_type_community_list) {
10861 struct community_list *list = output_arg;
d62a17ae 10862
40381db7 10863 if (!community_list_match(pi->attr->community,
a4d82a8a 10864 list))
98ce9a06
DS
10865 continue;
10866 }
a4d82a8a 10867 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10868 struct community_list *list = output_arg;
d62a17ae 10869
98ce9a06 10870 if (!community_list_exact_match(
40381db7 10871 pi->attr->community, list))
98ce9a06
DS
10872 continue;
10873 }
10874 if (type == bgp_show_type_lcommunity) {
10875 struct lcommunity *lcom = output_arg;
d62a17ae 10876
40381db7
DS
10877 if (!pi->attr->lcommunity
10878 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10879 lcom))
10880 continue;
10881 }
36a206db 10882
10883 if (type == bgp_show_type_lcommunity_exact) {
10884 struct lcommunity *lcom = output_arg;
10885
10886 if (!pi->attr->lcommunity
10887 || !lcommunity_cmp(pi->attr->lcommunity,
10888 lcom))
10889 continue;
10890 }
98ce9a06
DS
10891 if (type == bgp_show_type_lcommunity_list) {
10892 struct community_list *list = output_arg;
d62a17ae 10893
40381db7 10894 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10895 list))
98ce9a06
DS
10896 continue;
10897 }
36a206db 10898 if (type
10899 == bgp_show_type_lcommunity_list_exact) {
10900 struct community_list *list = output_arg;
10901
10902 if (!lcommunity_list_exact_match(
10903 pi->attr->lcommunity, list))
10904 continue;
10905 }
98ce9a06 10906 if (type == bgp_show_type_lcommunity_all) {
40381db7 10907 if (!pi->attr->lcommunity)
98ce9a06
DS
10908 continue;
10909 }
10910 if (type == bgp_show_type_dampend_paths
10911 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10912 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10913 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10914 continue;
10915 }
10916
10917 if (!use_json && header) {
23d0a753
DA
10918 vty_out(vty,
10919 "BGP table version is %" PRIu64
10920 ", local router ID is %pI4, vrf id ",
10921 table->version, &bgp->router_id);
9df8b37c
PZ
10922 if (bgp->vrf_id == VRF_UNKNOWN)
10923 vty_out(vty, "%s", VRFID_NONE_STR);
10924 else
10925 vty_out(vty, "%u", bgp->vrf_id);
10926 vty_out(vty, "\n");
01eced22
AD
10927 vty_out(vty, "Default local pref %u, ",
10928 bgp->default_local_pref);
10929 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10930 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10931 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10932 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 10933 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 10934 if (type == bgp_show_type_dampend_paths
10935 || type == bgp_show_type_damp_neighbor)
98ce9a06 10936 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10937 else if (type == bgp_show_type_flap_statistics
10938 || type == bgp_show_type_flap_neighbor)
98ce9a06 10939 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10940 else
ae248832
MK
10941 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10942 : BGP_SHOW_HEADER));
98ce9a06 10943 header = 0;
d62a17ae 10944 }
98ce9a06
DS
10945 if (rd != NULL && !display && !output_count) {
10946 if (!use_json)
10947 vty_out(vty,
10948 "Route Distinguisher: %s\n",
10949 rd);
d62a17ae 10950 }
98ce9a06
DS
10951 if (type == bgp_show_type_dampend_paths
10952 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10953 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10954 AFI_IP, safi, use_json,
10955 json_paths);
98ce9a06
DS
10956 else if (type == bgp_show_type_flap_statistics
10957 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10958 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10959 AFI_IP, safi, use_json,
10960 json_paths);
f280c93b
DA
10961 else {
10962 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
10963 route_vty_out_detail(
10964 vty, bgp, dest, pi,
10965 family2afi(dest_p->family),
10966 safi, RPKI_NOT_BEING_USED,
10967 json_paths);
10968 else
10969 route_vty_out(vty, dest_p, pi, display,
10970 safi, json_paths, wide);
10971 }
98ce9a06 10972 display++;
d62a17ae 10973 }
10974
98ce9a06
DS
10975 if (display) {
10976 output_count++;
10977 if (!use_json)
10978 continue;
10979
625d2931 10980 /* encode prefix */
9bcb3eef 10981 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10982 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10983
1840384b 10984
b54892e0
DS
10985 bgp_fs_nlri_get_string(
10986 (unsigned char *)
9bcb3eef
DS
10987 dest_p->u.prefix_flowspec.ptr,
10988 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10989 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10990 family2afi(dest_p->u
10991 .prefix_flowspec.family));
625d2931 10992 if (first)
b54892e0 10993 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10994 dest_p->u.prefix_flowspec
b54892e0 10995 .prefixlen);
625d2931 10996 else
b54892e0 10997 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10998 dest_p->u.prefix_flowspec
b54892e0 10999 .prefixlen);
625d2931 11000 } else {
625d2931 11001 if (first)
1b78780b 11002 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11003 else
1b78780b 11004 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11005 }
98ce9a06 11006 vty_out(vty, "%s",
f4ec52f7
DA
11007 json_object_to_json_string_ext(
11008 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11009 json_object_free(json_paths);
449feb8e 11010 json_paths = NULL;
98ce9a06 11011 first = 0;
1f83ed02
DS
11012 } else
11013 json_object_free(json_paths);
98ce9a06
DS
11014 }
11015
1ae44dfc
LB
11016 if (output_cum) {
11017 output_count += *output_cum;
11018 *output_cum = output_count;
11019 }
11020 if (total_cum) {
11021 total_count += *total_cum;
11022 *total_cum = total_count;
11023 }
d62a17ae 11024 if (use_json) {
9386b588 11025 if (rd) {
a4d82a8a 11026 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11027 }
11028 if (is_last) {
a4d82a8a
PZ
11029 unsigned long i;
11030 for (i = 0; i < *json_header_depth; ++i)
11031 vty_out(vty, " } ");
96f3485c
MK
11032 if (!all)
11033 vty_out(vty, "\n");
9386b588 11034 }
d62a17ae 11035 } else {
1ae44dfc
LB
11036 if (is_last) {
11037 /* No route is displayed */
11038 if (output_count == 0) {
11039 if (type == bgp_show_type_normal)
11040 vty_out(vty,
11041 "No BGP prefixes displayed, %ld exist\n",
11042 total_count);
11043 } else
d62a17ae 11044 vty_out(vty,
1ae44dfc
LB
11045 "\nDisplayed %ld routes and %ld total paths\n",
11046 output_count, total_count);
11047 }
d62a17ae 11048 }
718e3744 11049
d62a17ae 11050 return CMD_SUCCESS;
718e3744 11051}
11052
1ae44dfc
LB
11053int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11054 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11055 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11056{
9bcb3eef 11057 struct bgp_dest *dest, *next;
1ae44dfc
LB
11058 unsigned long output_cum = 0;
11059 unsigned long total_cum = 0;
9386b588 11060 unsigned long json_header_depth = 0;
67009e22 11061 struct bgp_table *itable;
0136788c 11062 bool show_msg;
96c81f66 11063 uint16_t show_flags = 0;
0136788c
LB
11064
11065 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11066
96f3485c
MK
11067 if (use_json)
11068 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11069
9bcb3eef
DS
11070 for (dest = bgp_table_top(table); dest; dest = next) {
11071 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11072
9bcb3eef
DS
11073 next = bgp_route_next(dest);
11074 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11075 continue;
67009e22 11076
9bcb3eef 11077 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11078 if (itable != NULL) {
1ae44dfc 11079 struct prefix_rd prd;
06b9f471 11080 char rd[RD_ADDRSTRLEN];
1ae44dfc 11081
9bcb3eef 11082 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11083 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11084 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11085 rd, next == NULL, &output_cum,
11086 &total_cum, &json_header_depth,
1e2ce4f1 11087 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11088 if (next == NULL)
11089 show_msg = false;
1ae44dfc
LB
11090 }
11091 }
0136788c
LB
11092 if (show_msg) {
11093 if (output_cum == 0)
11094 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11095 total_cum);
11096 else
11097 vty_out(vty,
11098 "\nDisplayed %ld routes and %ld total paths\n",
11099 output_cum, total_cum);
11100 }
1ae44dfc
LB
11101 return CMD_SUCCESS;
11102}
d62a17ae 11103static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11104 enum bgp_show_type type, void *output_arg,
96c81f66 11105 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11106{
d62a17ae 11107 struct bgp_table *table;
9386b588 11108 unsigned long json_header_depth = 0;
96f3485c 11109 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11110
d62a17ae 11111 if (bgp == NULL) {
11112 bgp = bgp_get_default();
11113 }
fee0f4c6 11114
d62a17ae 11115 if (bgp == NULL) {
11116 if (!use_json)
11117 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11118 else
11119 vty_out(vty, "{}\n");
d62a17ae 11120 return CMD_WARNING;
11121 }
4dd6177e 11122
1ae44dfc 11123 table = bgp->rib[afi][safi];
d62a17ae 11124 /* use MPLS and ENCAP specific shows until they are merged */
11125 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11126 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11127 output_arg, use_json);
d62a17ae 11128 }
dba3c1d3
PG
11129
11130 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11131 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11132 output_arg, use_json,
11133 1, NULL, NULL);
11134 }
d62a17ae 11135 /* labeled-unicast routes live in the unicast table */
11136 else if (safi == SAFI_LABELED_UNICAST)
11137 safi = SAFI_UNICAST;
fee0f4c6 11138
96f3485c 11139 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11140 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11141 rpki_target_state);
fee0f4c6 11142}
11143
d62a17ae 11144static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11145 safi_t safi, uint16_t show_flags)
f186de26 11146{
d62a17ae 11147 struct listnode *node, *nnode;
11148 struct bgp *bgp;
11149 int is_first = 1;
9f049418 11150 bool route_output = false;
96f3485c 11151 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11152
d62a17ae 11153 if (use_json)
11154 vty_out(vty, "{\n");
9f689658 11155
d62a17ae 11156 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11157 route_output = true;
d62a17ae 11158 if (use_json) {
11159 if (!is_first)
11160 vty_out(vty, ",\n");
11161 else
11162 is_first = 0;
11163
11164 vty_out(vty, "\"%s\":",
11165 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11166 ? VRF_DEFAULT_NAME
d62a17ae 11167 : bgp->name);
11168 } else {
11169 vty_out(vty, "\nInstance %s:\n",
11170 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11171 ? VRF_DEFAULT_NAME
d62a17ae 11172 : bgp->name);
11173 }
11174 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11175 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11176 }
9f689658 11177
d62a17ae 11178 if (use_json)
11179 vty_out(vty, "}\n");
9f049418
DS
11180 else if (!route_output)
11181 vty_out(vty, "%% BGP instance not found\n");
f186de26 11182}
11183
718e3744 11184/* Header of detailed BGP route information */
d62a17ae 11185void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11186 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11187 afi_t afi, safi_t safi, json_object *json)
11188{
40381db7 11189 struct bgp_path_info *pi;
b54892e0 11190 const struct prefix *p;
d62a17ae 11191 struct peer *peer;
11192 struct listnode *node, *nnode;
06b9f471 11193 char buf1[RD_ADDRSTRLEN];
0291c246 11194 char prefix_str[BUFSIZ];
d62a17ae 11195 int count = 0;
11196 int best = 0;
11197 int suppress = 0;
c5f1e1b2
C
11198 int accept_own = 0;
11199 int route_filter_translated_v4 = 0;
11200 int route_filter_v4 = 0;
11201 int route_filter_translated_v6 = 0;
11202 int route_filter_v6 = 0;
11203 int llgr_stale = 0;
11204 int no_llgr = 0;
11205 int accept_own_nexthop = 0;
11206 int blackhole = 0;
d62a17ae 11207 int no_export = 0;
11208 int no_advertise = 0;
11209 int local_as = 0;
c5f1e1b2 11210 int no_peer = 0;
d62a17ae 11211 int first = 1;
11212 int has_valid_label = 0;
11213 mpls_label_t label = 0;
11214 json_object *json_adv_to = NULL;
9bedbb1e 11215
9bcb3eef
DS
11216 p = bgp_dest_get_prefix(dest);
11217 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11218
11219 if (has_valid_label)
9bcb3eef 11220 label = label_pton(&dest->local_label);
d62a17ae 11221
44c69747 11222 if (safi == SAFI_EVPN) {
d62a17ae 11223
44c69747 11224 if (!json) {
2dbe669b 11225 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11226 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11227 : "",
2dbe669b 11228 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11229 } else {
11230 json_object_string_add(json, "rd",
11231 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11232 "");
11233 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11234 }
11235 } else {
11236 if (!json) {
9119ef3a
DA
11237 vty_out(vty,
11238 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11239 "\n",
d62a17ae 11240 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11241 ? prefix_rd2str(prd, buf1,
11242 sizeof(buf1))
11243 : ""),
9119ef3a
DA
11244 safi == SAFI_MPLS_VPN ? ":" : "", p,
11245 dest->version);
cd1964ff 11246
9119ef3a 11247 } else {
44c69747
LK
11248 json_object_string_add(json, "prefix",
11249 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11250 json_object_int_add(json, "version", dest->version);
11251
11252 }
44c69747
LK
11253 }
11254
11255 if (has_valid_label) {
11256 if (json)
11257 json_object_int_add(json, "localLabel", label);
11258 else
d62a17ae 11259 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11260 }
11261
11262 if (!json)
d62a17ae 11263 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11264 vty_out(vty, "not allocated\n");
718e3744 11265
9bcb3eef 11266 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11267 count++;
40381db7 11268 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11269 best = count;
4056a5f6 11270 if (bgp_path_suppressed(pi))
d62a17ae 11271 suppress = 1;
cee9c031 11272
40381db7 11273 if (pi->attr->community == NULL)
cee9c031
QY
11274 continue;
11275
11276 no_advertise += community_include(
40381db7
DS
11277 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11278 no_export += community_include(pi->attr->community,
cee9c031 11279 COMMUNITY_NO_EXPORT);
40381db7 11280 local_as += community_include(pi->attr->community,
cee9c031 11281 COMMUNITY_LOCAL_AS);
40381db7 11282 accept_own += community_include(pi->attr->community,
cee9c031
QY
11283 COMMUNITY_ACCEPT_OWN);
11284 route_filter_translated_v4 += community_include(
40381db7 11285 pi->attr->community,
cee9c031
QY
11286 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11287 route_filter_translated_v6 += community_include(
40381db7 11288 pi->attr->community,
cee9c031
QY
11289 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11290 route_filter_v4 += community_include(
40381db7 11291 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11292 route_filter_v6 += community_include(
40381db7
DS
11293 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11294 llgr_stale += community_include(pi->attr->community,
cee9c031 11295 COMMUNITY_LLGR_STALE);
40381db7 11296 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11297 COMMUNITY_NO_LLGR);
11298 accept_own_nexthop +=
40381db7 11299 community_include(pi->attr->community,
cee9c031 11300 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11301 blackhole += community_include(pi->attr->community,
cee9c031 11302 COMMUNITY_BLACKHOLE);
40381db7 11303 no_peer += community_include(pi->attr->community,
cee9c031 11304 COMMUNITY_NO_PEER);
d62a17ae 11305 }
718e3744 11306 }
718e3744 11307
d62a17ae 11308 if (!json) {
11309 vty_out(vty, "Paths: (%d available", count);
11310 if (best) {
11311 vty_out(vty, ", best #%d", best);
b84060bb
PG
11312 if (safi == SAFI_UNICAST) {
11313 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11314 vty_out(vty, ", table %s",
11315 VRF_DEFAULT_NAME);
11316 else
11317 vty_out(vty, ", vrf %s",
11318 bgp->name);
11319 }
d62a17ae 11320 } else
11321 vty_out(vty, ", no best path");
11322
c5f1e1b2
C
11323 if (accept_own)
11324 vty_out(vty,
11325 ", accept own local route exported and imported in different VRF");
11326 else if (route_filter_translated_v4)
11327 vty_out(vty,
11328 ", mark translated RTs for VPNv4 route filtering");
11329 else if (route_filter_v4)
11330 vty_out(vty,
11331 ", attach RT as-is for VPNv4 route filtering");
11332 else if (route_filter_translated_v6)
11333 vty_out(vty,
11334 ", mark translated RTs for VPNv6 route filtering");
11335 else if (route_filter_v6)
11336 vty_out(vty,
11337 ", attach RT as-is for VPNv6 route filtering");
11338 else if (llgr_stale)
11339 vty_out(vty,
11340 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11341 else if (no_llgr)
11342 vty_out(vty,
11343 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11344 else if (accept_own_nexthop)
11345 vty_out(vty,
11346 ", accept local nexthop");
11347 else if (blackhole)
11348 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11349 else if (no_export)
11350 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11351 else if (no_advertise)
11352 vty_out(vty, ", not advertised to any peer");
d62a17ae 11353 else if (local_as)
11354 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11355 else if (no_peer)
11356 vty_out(vty,
11357 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11358
11359 if (suppress)
11360 vty_out(vty,
11361 ", Advertisements suppressed by an aggregate.");
11362 vty_out(vty, ")\n");
11363 }
718e3744 11364
d62a17ae 11365 /* If we are not using addpath then we can display Advertised to and
11366 * that will
11367 * show what peers we advertised the bestpath to. If we are using
11368 * addpath
11369 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11370 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11371 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11372 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11373 if (json && !json_adv_to)
11374 json_adv_to = json_object_new_object();
11375
11376 route_vty_out_advertised_to(
11377 vty, peer, &first,
11378 " Advertised to non peer-group peers:\n ",
11379 json_adv_to);
11380 }
11381 }
11382
11383 if (json) {
11384 if (json_adv_to) {
11385 json_object_object_add(json, "advertisedTo",
11386 json_adv_to);
11387 }
11388 } else {
11389 if (first)
11390 vty_out(vty, " Not advertised to any peer");
11391 vty_out(vty, "\n");
11392 }
11393 }
718e3744 11394}
11395
44c69747 11396static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11397 struct bgp_dest *bgp_node, struct vty *vty,
11398 struct bgp *bgp, afi_t afi, safi_t safi,
11399 json_object *json, enum bgp_path_type pathtype,
4027d19b 11400 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11401{
11402 struct bgp_path_info *pi;
11403 int header = 1;
11404 char rdbuf[RD_ADDRSTRLEN];
11405 json_object *json_header = NULL;
11406 json_object *json_paths = NULL;
4933eaaf 11407 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11408
9bcb3eef 11409 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11410 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11411
11412 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11413 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11414 pi->peer, pi->attr, p);
4933eaaf 11415
4027d19b
DS
11416 if (rpki_target_state != RPKI_NOT_BEING_USED
11417 && rpki_curr_state != rpki_target_state)
4933eaaf 11418 continue;
44c69747
LK
11419
11420 if (json && !json_paths) {
11421 /* Instantiate json_paths only if path is valid */
11422 json_paths = json_object_new_array();
11423 if (pfx_rd) {
11424 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11425 json_header = json_object_new_object();
11426 } else
11427 json_header = json;
11428 }
11429
11430 if (header) {
11431 route_vty_out_detail_header(
11432 vty, bgp, bgp_node, pfx_rd,
11433 AFI_IP, safi, json_header);
11434 header = 0;
11435 }
11436 (*display)++;
11437
11438 if (pathtype == BGP_PATH_SHOW_ALL
11439 || (pathtype == BGP_PATH_SHOW_BESTPATH
11440 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11441 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11442 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11443 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11444 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11445 safi, rpki_curr_state, json_paths);
44c69747
LK
11446 }
11447
11448 if (json && json_paths) {
11449 json_object_object_add(json_header, "paths", json_paths);
11450
11451 if (pfx_rd)
11452 json_object_object_add(json, rdbuf, json_header);
11453 }
11454}
11455
718e3744 11456/* Display specified route of BGP table. */
d62a17ae 11457static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11458 struct bgp_table *rib, const char *ip_str,
11459 afi_t afi, safi_t safi,
4027d19b 11460 enum rpki_states rpki_target_state,
d62a17ae 11461 struct prefix_rd *prd, int prefix_check,
9f049418 11462 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11463{
11464 int ret;
d62a17ae 11465 int display = 0;
11466 struct prefix match;
9bcb3eef
DS
11467 struct bgp_dest *dest;
11468 struct bgp_dest *rm;
d62a17ae 11469 struct bgp_table *table;
11470 json_object *json = NULL;
11471 json_object *json_paths = NULL;
11472
11473 /* Check IP address argument. */
11474 ret = str2prefix(ip_str, &match);
11475 if (!ret) {
11476 vty_out(vty, "address is malformed\n");
11477 return CMD_WARNING;
11478 }
718e3744 11479
d62a17ae 11480 match.family = afi2family(afi);
b05a1c8b 11481
44c69747 11482 if (use_json)
d62a17ae 11483 json = json_object_new_object();
718e3744 11484
44c69747 11485 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11486 for (dest = bgp_table_top(rib); dest;
11487 dest = bgp_route_next(dest)) {
11488 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11489
9bcb3eef 11490 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11491 continue;
9bcb3eef 11492 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11493 if (!table)
ea47320b 11494 continue;
d62a17ae 11495
4953391b
DA
11496 rm = bgp_node_match(table, &match);
11497 if (rm == NULL)
ea47320b 11498 continue;
d62a17ae 11499
9bcb3eef 11500 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11501 if (prefix_check
b54892e0 11502 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11503 bgp_dest_unlock_node(rm);
ea47320b
DL
11504 continue;
11505 }
d62a17ae 11506
9bcb3eef 11507 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11508 bgp, afi, safi, json, pathtype,
4027d19b 11509 &display, rpki_target_state);
44c69747 11510
9bcb3eef 11511 bgp_dest_unlock_node(rm);
44c69747
LK
11512 }
11513 } else if (safi == SAFI_EVPN) {
9bcb3eef 11514 struct bgp_dest *longest_pfx;
cded3b72 11515 bool is_exact_pfxlen_match = false;
44c69747 11516
9bcb3eef
DS
11517 for (dest = bgp_table_top(rib); dest;
11518 dest = bgp_route_next(dest)) {
11519 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11520
9bcb3eef 11521 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11522 continue;
9bcb3eef 11523 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11524 if (!table)
11525 continue;
11526
11527 longest_pfx = NULL;
cded3b72 11528 is_exact_pfxlen_match = false;
44c69747
LK
11529 /*
11530 * Search through all the prefixes for a match. The
11531 * pfx's are enumerated in ascending order of pfxlens.
11532 * So, the last pfx match is the longest match. Set
11533 * is_exact_pfxlen_match when we get exact pfxlen match
11534 */
11535 for (rm = bgp_table_top(table); rm;
11536 rm = bgp_route_next(rm)) {
b54892e0 11537 const struct prefix *rm_p =
9bcb3eef 11538 bgp_dest_get_prefix(rm);
44c69747
LK
11539 /*
11540 * Get prefixlen of the ip-prefix within type5
11541 * evpn route
11542 */
b54892e0
DS
11543 if (evpn_type5_prefix_match(rm_p, &match)
11544 && rm->info) {
44c69747
LK
11545 longest_pfx = rm;
11546 int type5_pfxlen =
b54892e0
DS
11547 bgp_evpn_get_type5_prefixlen(
11548 rm_p);
44c69747 11549 if (type5_pfxlen == match.prefixlen) {
cded3b72 11550 is_exact_pfxlen_match = true;
9bcb3eef 11551 bgp_dest_unlock_node(rm);
44c69747
LK
11552 break;
11553 }
d62a17ae 11554 }
11555 }
ea47320b 11556
44c69747
LK
11557 if (!longest_pfx)
11558 continue;
11559
11560 if (prefix_check && !is_exact_pfxlen_match)
11561 continue;
11562
11563 rm = longest_pfx;
9bcb3eef 11564 bgp_dest_lock_node(rm);
44c69747 11565
9bcb3eef 11566 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11567 bgp, afi, safi, json, pathtype,
4027d19b 11568 &display, rpki_target_state);
44c69747 11569
9bcb3eef 11570 bgp_dest_unlock_node(rm);
d62a17ae 11571 }
98a9dbc7 11572 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11573 if (use_json)
11574 json_paths = json_object_new_array();
11575
63a0b7a9
PG
11576 display = bgp_flowspec_display_match_per_ip(afi, rib,
11577 &match, prefix_check,
11578 vty,
11579 use_json,
11580 json_paths);
d5f20468
SP
11581 if (use_json) {
11582 if (display)
11583 json_object_object_add(json, "paths",
11584 json_paths);
11585 else
11586 json_object_free(json_paths);
11587 }
d62a17ae 11588 } else {
4953391b
DA
11589 dest = bgp_node_match(rib, &match);
11590 if (dest != NULL) {
9bcb3eef 11591 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11592 if (!prefix_check
9bcb3eef
DS
11593 || dest_p->prefixlen == match.prefixlen) {
11594 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11595 safi, json, pathtype,
4027d19b 11596 &display, rpki_target_state);
d62a17ae 11597 }
11598
9bcb3eef 11599 bgp_dest_unlock_node(dest);
d62a17ae 11600 }
11601 }
e5eee9af 11602
d62a17ae 11603 if (use_json) {
996c9314 11604 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11605 json, JSON_C_TO_STRING_PRETTY |
11606 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11607 json_object_free(json);
11608 } else {
11609 if (!display) {
11610 vty_out(vty, "%% Network not in table\n");
11611 return CMD_WARNING;
11612 }
11613 }
b05a1c8b 11614
d62a17ae 11615 return CMD_SUCCESS;
718e3744 11616}
11617
fee0f4c6 11618/* Display specified route of Main RIB */
d62a17ae 11619static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11620 afi_t afi, safi_t safi, struct prefix_rd *prd,
11621 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11622 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11623{
9b86009a 11624 if (!bgp) {
d62a17ae 11625 bgp = bgp_get_default();
9b86009a
RW
11626 if (!bgp) {
11627 if (!use_json)
11628 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11629 else
11630 vty_out(vty, "{}\n");
9b86009a
RW
11631 return CMD_WARNING;
11632 }
11633 }
d62a17ae 11634
11635 /* labeled-unicast routes live in the unicast table */
11636 if (safi == SAFI_LABELED_UNICAST)
11637 safi = SAFI_UNICAST;
11638
11639 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11640 afi, safi, rpki_target_state, prd,
8aa22bbb 11641 prefix_check, pathtype, use_json);
d62a17ae 11642}
11643
11644static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11645 struct cmd_token **argv, bool exact, afi_t afi,
11646 safi_t safi, bool uj)
d62a17ae 11647{
11648 struct lcommunity *lcom;
11649 struct buffer *b;
11650 int i;
11651 char *str;
11652 int first = 0;
96c81f66 11653 uint16_t show_flags = 0;
4f28b2b5 11654 int ret;
96f3485c
MK
11655
11656 if (uj)
11657 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11658
11659 b = buffer_new(1024);
11660 for (i = 0; i < argc; i++) {
11661 if (first)
11662 buffer_putc(b, ' ');
11663 else {
11664 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11665 first = 1;
11666 buffer_putstr(b, argv[i]->arg);
11667 }
11668 }
11669 }
11670 buffer_putc(b, '\0');
57d187bc 11671
d62a17ae 11672 str = buffer_getstr(b);
11673 buffer_free(b);
57d187bc 11674
d62a17ae 11675 lcom = lcommunity_str2com(str);
11676 XFREE(MTYPE_TMP, str);
11677 if (!lcom) {
11678 vty_out(vty, "%% Large-community malformed\n");
11679 return CMD_WARNING;
11680 }
57d187bc 11681
4f28b2b5 11682 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11683 (exact ? bgp_show_type_lcommunity_exact
11684 : bgp_show_type_lcommunity),
11685 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11686
11687 lcommunity_free(&lcom);
11688 return ret;
57d187bc
JS
11689}
11690
d62a17ae 11691static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11692 const char *lcom, bool exact, afi_t afi,
11693 safi_t safi, bool uj)
57d187bc 11694{
d62a17ae 11695 struct community_list *list;
96c81f66 11696 uint16_t show_flags = 0;
96f3485c
MK
11697
11698 if (uj)
11699 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11700
57d187bc 11701
e237b0d2 11702 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11703 LARGE_COMMUNITY_LIST_MASTER);
11704 if (list == NULL) {
11705 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11706 lcom);
11707 return CMD_WARNING;
11708 }
57d187bc 11709
36a206db 11710 return bgp_show(vty, bgp, afi, safi,
11711 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11712 : bgp_show_type_lcommunity_list),
1e2ce4f1 11713 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11714}
11715
52951b63
DS
11716DEFUN (show_ip_bgp_large_community_list,
11717 show_ip_bgp_large_community_list_cmd,
36a206db 11718 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
11719 SHOW_STR
11720 IP_STR
11721 BGP_STR
11722 BGP_INSTANCE_HELP_STR
9bedbb1e 11723 BGP_AFI_HELP_STR
4dd6177e 11724 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11725 "Display routes matching the large-community-list\n"
11726 "large-community-list number\n"
11727 "large-community-list name\n"
36a206db 11728 "Exact match of the large-communities\n"
52951b63
DS
11729 JSON_STR)
11730{
d62a17ae 11731 afi_t afi = AFI_IP6;
11732 safi_t safi = SAFI_UNICAST;
11733 int idx = 0;
36a206db 11734 bool exact_match = 0;
4d678463 11735 struct bgp *bgp = NULL;
9f049418 11736 bool uj = use_json(argc, argv);
d62a17ae 11737
ef3364f0
DA
11738 if (uj)
11739 argc--;
4d678463 11740
ef3364f0
DA
11741 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11742 &bgp, uj);
11743 if (!idx)
11744 return CMD_WARNING;
d62a17ae 11745
11746 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11747
11748 const char *clist_number_or_name = argv[++idx]->arg;
11749
11750 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11751 exact_match = 1;
11752
11753 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11754 exact_match, afi, safi, uj);
52951b63
DS
11755}
11756DEFUN (show_ip_bgp_large_community,
11757 show_ip_bgp_large_community_cmd,
36a206db 11758 "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
11759 SHOW_STR
11760 IP_STR
11761 BGP_STR
11762 BGP_INSTANCE_HELP_STR
9bedbb1e 11763 BGP_AFI_HELP_STR
4dd6177e 11764 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11765 "Display routes matching the large-communities\n"
11766 "List of large-community numbers\n"
36a206db 11767 "Exact match of the large-communities\n"
52951b63
DS
11768 JSON_STR)
11769{
d62a17ae 11770 afi_t afi = AFI_IP6;
11771 safi_t safi = SAFI_UNICAST;
11772 int idx = 0;
36a206db 11773 bool exact_match = 0;
4d678463 11774 struct bgp *bgp = NULL;
9f049418 11775 bool uj = use_json(argc, argv);
96c81f66 11776 uint16_t show_flags = 0;
d62a17ae 11777
96f3485c
MK
11778 if (uj) {
11779 argc--;
11780 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11781 }
4d678463 11782
96f3485c
MK
11783 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11784 &bgp, uj);
11785 if (!idx)
11786 return CMD_WARNING;
d62a17ae 11787
36a206db 11788 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11789 if (argv_find(argv, argc, "exact-match", &idx))
11790 exact_match = 1;
11791 return bgp_show_lcommunity(vty, bgp, argc, argv,
11792 exact_match, afi, safi, uj);
11793 } else
d62a17ae 11794 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11795 bgp_show_type_lcommunity_all, NULL, show_flags,
11796 RPKI_NOT_BEING_USED);
52951b63
DS
11797}
11798
71f1613a
DA
11799static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11800 safi_t safi, struct json_object *json_array);
d62a17ae 11801static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11802 safi_t safi, struct json_object *json);
e01ca200 11803
7b2ff250 11804
9ab0cf58
PG
11805DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11806 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11807 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11808 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11809{
11810 bool uj = use_json(argc, argv);
11811 struct bgp *bgp = NULL;
ec76a1d1
DA
11812 safi_t safi = SAFI_UNICAST;
11813 afi_t afi = AFI_IP6;
4265b261 11814 int idx = 0;
6c9d22e2
PG
11815 struct json_object *json_all = NULL;
11816 struct json_object *json_afi_safi = NULL;
4265b261
PG
11817
11818 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11819 &bgp, false);
71f1613a 11820 if (!idx)
4265b261 11821 return CMD_WARNING;
6c9d22e2 11822
4265b261 11823 if (uj)
6c9d22e2 11824 json_all = json_object_new_object();
4265b261 11825
9ab0cf58
PG
11826 FOREACH_AFI_SAFI (afi, safi) {
11827 /*
11828 * So limit output to those afi/safi pairs that
11829 * actually have something interesting in them
11830 */
11831 if (strmatch(get_afi_safi_str(afi, safi, true),
11832 "Unknown")) {
11833 continue;
11834 }
11835 if (uj) {
11836 json_afi_safi = json_object_new_array();
11837 json_object_object_add(
11838 json_all,
11839 get_afi_safi_str(afi, safi, true),
11840 json_afi_safi);
11841 } else {
11842 json_afi_safi = NULL;
6c9d22e2 11843 }
9ab0cf58
PG
11844
11845 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11846 }
6c9d22e2
PG
11847
11848 if (uj) {
9ab0cf58
PG
11849 vty_out(vty, "%s",
11850 json_object_to_json_string_ext(
11851 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11852 json_object_free(json_all);
4265b261 11853 }
6c9d22e2 11854
4265b261
PG
11855 return CMD_SUCCESS;
11856}
11857
7b2ff250 11858/* BGP route print out function without JSON */
14718643
PG
11859DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11860 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11861 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11862 SHOW_STR
11863 IP_STR
11864 BGP_STR
11865 BGP_INSTANCE_HELP_STR
11866 L2VPN_HELP_STR
11867 EVPN_HELP_STR
11868 "BGP RIB advertisement statistics\n"
11869 JSON_STR)
11870{
ec76a1d1
DA
11871 afi_t afi = AFI_IP6;
11872 safi_t safi = SAFI_UNICAST;
14718643
PG
11873 struct bgp *bgp = NULL;
11874 int idx = 0, ret;
11875 bool uj = use_json(argc, argv);
11876 struct json_object *json_afi_safi = NULL, *json = NULL;
11877
11878 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11879 &bgp, false);
11880 if (!idx)
11881 return CMD_WARNING;
11882
11883 if (uj)
11884 json_afi_safi = json_object_new_array();
11885 else
11886 json_afi_safi = NULL;
11887
11888 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11889
11890 if (uj) {
11891 json = json_object_new_object();
11892 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11893 json_afi_safi);
11894 vty_out(vty, "%s", json_object_to_json_string_ext(
11895 json, JSON_C_TO_STRING_PRETTY));
11896 json_object_free(json);
11897 }
11898 return ret;
11899}
11900
893cccd0 11901/* BGP route print out function without JSON */
9ab0cf58
PG
11902DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11903 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11904 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11905 "]]\
893cccd0 11906 statistics [json]",
9ab0cf58
PG
11907 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11908 BGP_SAFI_WITH_LABEL_HELP_STR
11909 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11910{
ec76a1d1
DA
11911 afi_t afi = AFI_IP6;
11912 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11913 struct bgp *bgp = NULL;
11914 int idx = 0, ret;
11915 bool uj = use_json(argc, argv);
6c9d22e2 11916 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11917
11918 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11919 &bgp, false);
11920 if (!idx)
11921 return CMD_WARNING;
6c9d22e2 11922
893cccd0 11923 if (uj)
6c9d22e2
PG
11924 json_afi_safi = json_object_new_array();
11925 else
11926 json_afi_safi = NULL;
11927
11928 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11929
11930 if (uj) {
11931 json = json_object_new_object();
11932 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11933 json_afi_safi);
9ab0cf58
PG
11934 vty_out(vty, "%s",
11935 json_object_to_json_string_ext(
11936 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11937 json_object_free(json);
11938 }
11939 return ret;
893cccd0 11940}
7b2ff250
DW
11941
11942/* BGP route print out function without JSON */
96f3485c 11943DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11944 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11945 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11946 "]]\
96f3485c 11947 <[all$all] dampening <parameters>\
7b2ff250
DW
11948 |route-map WORD\
11949 |prefix-list WORD\
11950 |filter-list WORD\
96870ecb 11951 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
7b2ff250
DW
11952 |A.B.C.D/M longer-prefixes\
11953 |X:X::X:X/M longer-prefixes\
893cccd0 11954 >",
9ab0cf58
PG
11955 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11956 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11957 "Display the entries for all address families\n"
9ab0cf58
PG
11958 "Display detailed information about dampening\n"
11959 "Display detail of configured dampening parameters\n"
11960 "Display routes matching the route-map\n"
11961 "A route-map to match on\n"
11962 "Display routes conforming to the prefix-list\n"
11963 "Prefix-list name\n"
11964 "Display routes conforming to the filter-list\n"
11965 "Regular expression access list name\n"
11966 "Display routes matching the community-list\n"
11967 "community-list number\n"
11968 "community-list name\n"
11969 "Exact match of the communities\n"
11970 "IPv4 prefix\n"
11971 "Display route and more specific routes\n"
11972 "IPv6 prefix\n"
11973 "Display route and more specific routes\n")
718e3744 11974{
d62a17ae 11975 afi_t afi = AFI_IP6;
11976 safi_t safi = SAFI_UNICAST;
11977 int exact_match = 0;
d62a17ae 11978 struct bgp *bgp = NULL;
11979 int idx = 0;
96c81f66 11980 uint16_t show_flags = 0;
96f3485c
MK
11981
11982 /* [<ipv4|ipv6> [all]] */
11983 if (all) {
11984 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11985 if (argv_find(argv, argc, "ipv4", &idx))
11986 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11987
11988 if (argv_find(argv, argc, "ipv6", &idx))
11989 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11990 }
d62a17ae 11991
11992 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11993 &bgp, false);
d62a17ae 11994 if (!idx)
11995 return CMD_WARNING;
11996
d62a17ae 11997 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11998 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11999 return bgp_show_dampening_parameters(vty, afi, safi,
12000 show_flags);
d62a17ae 12001 }
c016b6c7 12002
d62a17ae 12003 if (argv_find(argv, argc, "prefix-list", &idx))
12004 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12005 safi, bgp_show_type_prefix_list);
12006
12007 if (argv_find(argv, argc, "filter-list", &idx))
12008 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12009 safi, bgp_show_type_filter_list);
12010
d62a17ae 12011 if (argv_find(argv, argc, "route-map", &idx))
12012 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12013 safi, bgp_show_type_route_map);
12014
d62a17ae 12015 if (argv_find(argv, argc, "community-list", &idx)) {
12016 const char *clist_number_or_name = argv[++idx]->arg;
12017 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12018 exact_match = 1;
12019 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12020 exact_match, afi, safi);
12021 }
12022 /* prefix-longer */
12023 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12024 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12025 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12026 safi,
12027 bgp_show_type_prefix_longer);
12028
7b2ff250
DW
12029 return CMD_WARNING;
12030}
12031
12032/* BGP route print out function with JSON */
a70a28a5
DA
12033DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12034 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12035 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12036 "]]\
96f3485c 12037 [all$all]\
cf4898bc
QY
12038 [cidr-only\
12039 |dampening <flap-statistics|dampened-paths>\
12040 |community [AA:NN|local-AS|no-advertise|no-export\
12041 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12042 |accept-own|accept-own-nexthop|route-filter-v6\
12043 |route-filter-v4|route-filter-translated-v6\
12044 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 12045 |rpki <invalid|valid|notfound>\
7d3cae70 12046 |version (1-4294967295)\
b4ad2fae 12047 |alias ALIAS_NAME\
f280c93b 12048 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12049 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12050 BGP_SAFI_WITH_LABEL_HELP_STR
12051 "Display the entries for all address families\n"
12052 "Display only routes with non-natural netmasks\n"
12053 "Display detailed information about dampening\n"
12054 "Display flap statistics of routes\n"
12055 "Display paths suppressed due to dampening\n"
12056 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12057 "Do not send outside local AS (well-known community)\n"
12058 "Do not advertise to any peer (well-known community)\n"
12059 "Do not export to next AS (well-known community)\n"
12060 "Graceful shutdown (well-known community)\n"
12061 "Do not export to any peer (well-known community)\n"
12062 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12063 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12064 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12065 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12066 "Should accept VPN route with local nexthop (well-known community)\n"
12067 "RT VPNv6 route filtering (well-known community)\n"
12068 "RT VPNv4 route filtering (well-known community)\n"
12069 "RT translated VPNv6 route filtering (well-known community)\n"
12070 "RT translated VPNv4 route filtering (well-known community)\n"
12071 "Exact match of the communities\n"
12072 "RPKI route types\n"
12073 "A valid path as determined by rpki\n"
12074 "A invalid path as determined by rpki\n"
12075 "A path that has no rpki data\n"
12076 "Display prefixes with matching version numbers\n"
12077 "Version number and above\n"
12078 "Display prefixes with matching BGP community alias\n"
12079 "BGP community alias\n" JSON_STR
12080 "Display detailed version of JSON output\n"
12081 "Increase table width for longer prefixes\n")
7b2ff250
DW
12082{
12083 afi_t afi = AFI_IP6;
12084 safi_t safi = SAFI_UNICAST;
12085 enum bgp_show_type sh_type = bgp_show_type_normal;
12086 struct bgp *bgp = NULL;
12087 int idx = 0;
d0086e8e 12088 int exact_match = 0;
96f3485c 12089 char *community = NULL;
7d3cae70 12090 char *prefix_version = NULL;
a70a28a5 12091 char *bgp_community_alias = NULL;
96f3485c 12092 bool first = true;
96c81f66 12093 uint16_t show_flags = 0;
4027d19b 12094 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12095
12096 if (uj) {
9f049418 12097 argc--;
96f3485c
MK
12098 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12099 }
12100
f280c93b
DA
12101 if (detail)
12102 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12103
96f3485c
MK
12104 /* [<ipv4|ipv6> [all]] */
12105 if (all) {
12106 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12107
12108 if (argv_find(argv, argc, "ipv4", &idx))
12109 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12110
12111 if (argv_find(argv, argc, "ipv6", &idx))
12112 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12113 }
12114
12115 if (wide)
12116 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12117
12118 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12119 &bgp, uj);
7b2ff250
DW
12120 if (!idx)
12121 return CMD_WARNING;
12122
7b2ff250 12123 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12124 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12125
12126 if (argv_find(argv, argc, "dampening", &idx)) {
12127 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12128 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12129 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12130 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12131 }
12132
12133 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12134 char *maybecomm = NULL;
d0086e8e 12135
79bc257a
RW
12136 if (idx + 1 < argc) {
12137 if (argv[idx + 1]->type == VARIABLE_TKN)
12138 maybecomm = argv[idx + 1]->arg;
12139 else
12140 maybecomm = argv[idx + 1]->text;
12141 }
12142
cf4898bc
QY
12143 if (maybecomm && !strmatch(maybecomm, "json")
12144 && !strmatch(maybecomm, "exact-match"))
12145 community = maybecomm;
d0086e8e 12146
cf4898bc
QY
12147 if (argv_find(argv, argc, "exact-match", &idx))
12148 exact_match = 1;
d0086e8e 12149
96f3485c
MK
12150 if (!community)
12151 sh_type = bgp_show_type_community_all;
12152 }
12153
1e2ce4f1
DS
12154 if (argv_find(argv, argc, "rpki", &idx)) {
12155 sh_type = bgp_show_type_rpki;
12156 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12157 rpki_target_state = RPKI_VALID;
1e2ce4f1 12158 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12159 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12160 }
12161
7d3cae70
DA
12162 /* Display prefixes with matching version numbers */
12163 if (argv_find(argv, argc, "version", &idx)) {
12164 sh_type = bgp_show_type_prefix_version;
12165 prefix_version = argv[idx + 1]->arg;
12166 }
12167
a70a28a5
DA
12168 /* Display prefixes with matching BGP community alias */
12169 if (argv_find(argv, argc, "alias", &idx)) {
12170 sh_type = bgp_show_type_community_alias;
12171 bgp_community_alias = argv[idx + 1]->arg;
12172 }
12173
96f3485c
MK
12174 if (!all) {
12175 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12176 if (community)
12177 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12178 exact_match, afi, safi,
12179 show_flags);
7d3cae70
DA
12180 else if (prefix_version)
12181 return bgp_show(vty, bgp, afi, safi, sh_type,
12182 prefix_version, show_flags,
12183 rpki_target_state);
a70a28a5
DA
12184 else if (bgp_community_alias)
12185 return bgp_show(vty, bgp, afi, safi, sh_type,
12186 bgp_community_alias, show_flags,
12187 rpki_target_state);
cf4898bc 12188 else
96f3485c 12189 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12190 show_flags, rpki_target_state);
96f3485c
MK
12191 } else {
12192 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12193 * AFI_IP6 */
12194
12195 if (uj)
12196 vty_out(vty, "{\n");
12197
12198 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12199 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12200 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12201 ? AFI_IP
12202 : AFI_IP6;
12203 FOREACH_SAFI (safi) {
96f3485c
MK
12204 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12205 continue;
12206
12207 if (uj) {
12208 if (first)
12209 first = false;
12210 else
12211 vty_out(vty, ",\n");
12212 vty_out(vty, "\"%s\":{\n",
12213 get_afi_safi_str(afi, safi,
12214 true));
12215 } else
12216 vty_out(vty,
12217 "\nFor address family: %s\n",
12218 get_afi_safi_str(afi, safi,
12219 false));
12220
12221 if (community)
12222 bgp_show_community(vty, bgp, community,
12223 exact_match, afi,
12224 safi, show_flags);
7d3cae70
DA
12225 else if (prefix_version)
12226 return bgp_show(vty, bgp, afi, safi,
12227 sh_type, prefix_version,
12228 show_flags,
12229 rpki_target_state);
a70a28a5
DA
12230 else if (bgp_community_alias)
12231 return bgp_show(
12232 vty, bgp, afi, safi, sh_type,
12233 bgp_community_alias, show_flags,
12234 rpki_target_state);
96f3485c
MK
12235 else
12236 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12237 NULL, show_flags,
4027d19b 12238 rpki_target_state);
96f3485c
MK
12239 if (uj)
12240 vty_out(vty, "}\n");
12241 }
12242 } else {
12243 /* show <ip> bgp all: for each AFI and SAFI*/
12244 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12245 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12246 continue;
12247
12248 if (uj) {
12249 if (first)
12250 first = false;
12251 else
12252 vty_out(vty, ",\n");
d0086e8e 12253
96f3485c
MK
12254 vty_out(vty, "\"%s\":{\n",
12255 get_afi_safi_str(afi, safi,
12256 true));
12257 } else
12258 vty_out(vty,
12259 "\nFor address family: %s\n",
12260 get_afi_safi_str(afi, safi,
12261 false));
12262
12263 if (community)
12264 bgp_show_community(vty, bgp, community,
12265 exact_match, afi,
12266 safi, show_flags);
7d3cae70
DA
12267 else if (prefix_version)
12268 return bgp_show(vty, bgp, afi, safi,
12269 sh_type, prefix_version,
12270 show_flags,
12271 rpki_target_state);
96f3485c
MK
12272 else
12273 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12274 NULL, show_flags,
4027d19b 12275 rpki_target_state);
96f3485c
MK
12276 if (uj)
12277 vty_out(vty, "}\n");
12278 }
12279 }
12280 if (uj)
12281 vty_out(vty, "}\n");
12282 }
12283 return CMD_SUCCESS;
a636c635 12284}
47fc97cc 12285
718e3744 12286DEFUN (show_ip_bgp_route,
12287 show_ip_bgp_route_cmd,
8aa22bbb 12288 "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 12289 SHOW_STR
12290 IP_STR
12291 BGP_STR
a636c635 12292 BGP_INSTANCE_HELP_STR
4f280b15 12293 BGP_AFI_HELP_STR
4dd6177e 12294 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12295 "Network in the BGP routing table to display\n"
0c7b1b01 12296 "IPv4 prefix\n"
8c3deaae 12297 "Network in the BGP routing table to display\n"
0c7b1b01 12298 "IPv6 prefix\n"
4092b06c 12299 "Display only the bestpath\n"
b05a1c8b 12300 "Display only multipaths\n"
8aa22bbb
DS
12301 "Display only paths that match the specified rpki state\n"
12302 "A valid path as determined by rpki\n"
12303 "A invalid path as determined by rpki\n"
12304 "A path that has no rpki data\n"
9973d184 12305 JSON_STR)
4092b06c 12306{
d62a17ae 12307 int prefix_check = 0;
ae19d7dd 12308
d62a17ae 12309 afi_t afi = AFI_IP6;
12310 safi_t safi = SAFI_UNICAST;
12311 char *prefix = NULL;
12312 struct bgp *bgp = NULL;
12313 enum bgp_path_type path_type;
9f049418 12314 bool uj = use_json(argc, argv);
b05a1c8b 12315
d62a17ae 12316 int idx = 0;
ae19d7dd 12317
d62a17ae 12318 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12319 &bgp, uj);
d62a17ae 12320 if (!idx)
12321 return CMD_WARNING;
c41247f5 12322
d62a17ae 12323 if (!bgp) {
12324 vty_out(vty,
12325 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12326 return CMD_WARNING;
12327 }
a636c635 12328
d62a17ae 12329 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12330 if (argv_find(argv, argc, "A.B.C.D", &idx)
12331 || argv_find(argv, argc, "X:X::X:X", &idx))
12332 prefix_check = 0;
12333 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12334 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12335 prefix_check = 1;
12336
12337 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12338 && afi != AFI_IP6) {
12339 vty_out(vty,
12340 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12341 return CMD_WARNING;
12342 }
12343 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12344 && afi != AFI_IP) {
12345 vty_out(vty,
12346 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12347 return CMD_WARNING;
12348 }
12349
12350 prefix = argv[idx]->arg;
12351
12352 /* [<bestpath|multipath>] */
12353 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12354 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12355 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12356 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12357 else
360660c6 12358 path_type = BGP_PATH_SHOW_ALL;
a636c635 12359
d62a17ae 12360 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12361 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12362}
12363
8c3deaae
QY
12364DEFUN (show_ip_bgp_regexp,
12365 show_ip_bgp_regexp_cmd,
3e5b31b3 12366 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12367 SHOW_STR
12368 IP_STR
12369 BGP_STR
b00b230a 12370 BGP_INSTANCE_HELP_STR
4f280b15 12371 BGP_AFI_HELP_STR
4dd6177e 12372 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12373 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12374 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12375 JSON_STR)
8c3deaae 12376{
d62a17ae 12377 afi_t afi = AFI_IP6;
12378 safi_t safi = SAFI_UNICAST;
12379 struct bgp *bgp = NULL;
3e5b31b3
DA
12380 bool uj = use_json(argc, argv);
12381 char *regstr = NULL;
8c3deaae 12382
d62a17ae 12383 int idx = 0;
12384 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12385 &bgp, false);
d62a17ae 12386 if (!idx)
12387 return CMD_WARNING;
8c3deaae 12388
d62a17ae 12389 // get index of regex
3e5b31b3
DA
12390 if (argv_find(argv, argc, "REGEX", &idx))
12391 regstr = argv[idx]->arg;
8c3deaae 12392
5f71d11c 12393 assert(regstr);
3e5b31b3
DA
12394 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12395 bgp_show_type_regexp, uj);
8c3deaae
QY
12396}
12397
ae248832 12398DEFPY (show_ip_bgp_instance_all,
a636c635 12399 show_ip_bgp_instance_all_cmd,
ae248832 12400 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12401 SHOW_STR
a636c635 12402 IP_STR
4092b06c 12403 BGP_STR
a636c635 12404 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12405 BGP_AFI_HELP_STR
4dd6177e 12406 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12407 JSON_STR
12408 "Increase table width for longer prefixes\n")
4092b06c 12409{
d62a17ae 12410 afi_t afi = AFI_IP;
12411 safi_t safi = SAFI_UNICAST;
12412 struct bgp *bgp = NULL;
d62a17ae 12413 int idx = 0;
96c81f66 12414 uint16_t show_flags = 0;
ae19d7dd 12415
96f3485c 12416 if (uj) {
d62a17ae 12417 argc--;
96f3485c
MK
12418 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12419 }
12420
12421 if (wide)
12422 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12423
9f049418
DS
12424 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12425 &bgp, uj);
12426 if (!idx)
12427 return CMD_WARNING;
12428
96f3485c 12429 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12430 return CMD_SUCCESS;
e3e29b32
LB
12431}
12432
a4d82a8a 12433static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12434 afi_t afi, safi_t safi, enum bgp_show_type type,
12435 bool use_json)
718e3744 12436{
d62a17ae 12437 regex_t *regex;
12438 int rc;
96c81f66 12439 uint16_t show_flags = 0;
96f3485c
MK
12440
12441 if (use_json)
12442 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12443
c3900853 12444 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12445 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12446 regstr);
12447 return CMD_WARNING_CONFIG_FAILED;
12448 }
12449
d62a17ae 12450 regex = bgp_regcomp(regstr);
12451 if (!regex) {
12452 vty_out(vty, "Can't compile regexp %s\n", regstr);
12453 return CMD_WARNING;
12454 }
a636c635 12455
1e2ce4f1
DS
12456 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12457 RPKI_NOT_BEING_USED);
d62a17ae 12458 bgp_regex_free(regex);
12459 return rc;
e3e29b32
LB
12460}
12461
d62a17ae 12462static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12463 const char *prefix_list_str, afi_t afi,
12464 safi_t safi, enum bgp_show_type type)
e3e29b32 12465{
d62a17ae 12466 struct prefix_list *plist;
96c81f66 12467 uint16_t show_flags = 0;
718e3744 12468
d62a17ae 12469 plist = prefix_list_lookup(afi, prefix_list_str);
12470 if (plist == NULL) {
12471 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12472 prefix_list_str);
12473 return CMD_WARNING;
12474 }
718e3744 12475
1e2ce4f1
DS
12476 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12477 RPKI_NOT_BEING_USED);
4092b06c
DS
12478}
12479
d62a17ae 12480static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12481 const char *filter, afi_t afi, safi_t safi,
12482 enum bgp_show_type type)
4092b06c 12483{
d62a17ae 12484 struct as_list *as_list;
96c81f66 12485 uint16_t show_flags = 0;
718e3744 12486
d62a17ae 12487 as_list = as_list_lookup(filter);
12488 if (as_list == NULL) {
12489 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12490 filter);
12491 return CMD_WARNING;
12492 }
a636c635 12493
1e2ce4f1
DS
12494 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12495 RPKI_NOT_BEING_USED);
718e3744 12496}
12497
d62a17ae 12498static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12499 const char *rmap_str, afi_t afi, safi_t safi,
12500 enum bgp_show_type type)
718e3744 12501{
d62a17ae 12502 struct route_map *rmap;
96c81f66 12503 uint16_t show_flags = 0;
bb46e94f 12504
d62a17ae 12505 rmap = route_map_lookup_by_name(rmap_str);
12506 if (!rmap) {
12507 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12508 return CMD_WARNING;
12509 }
12510
1e2ce4f1
DS
12511 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12512 RPKI_NOT_BEING_USED);
d62a17ae 12513}
12514
7f323236
DW
12515static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12516 const char *comstr, int exact, afi_t afi,
96c81f66 12517 safi_t safi, uint16_t show_flags)
d62a17ae 12518{
12519 struct community *com;
d62a17ae 12520 int ret = 0;
12521
7f323236 12522 com = community_str2com(comstr);
d62a17ae 12523 if (!com) {
7f323236 12524 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12525 return CMD_WARNING;
12526 }
12527
12528 ret = bgp_show(vty, bgp, afi, safi,
12529 (exact ? bgp_show_type_community_exact
12530 : bgp_show_type_community),
1e2ce4f1 12531 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12532 community_free(&com);
46c3ce83 12533
d62a17ae 12534 return ret;
718e3744 12535}
12536
d62a17ae 12537static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12538 const char *com, int exact, afi_t afi,
12539 safi_t safi)
50ef26d4 12540{
d62a17ae 12541 struct community_list *list;
96c81f66 12542 uint16_t show_flags = 0;
50ef26d4 12543
e237b0d2 12544 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12545 if (list == NULL) {
12546 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12547 return CMD_WARNING;
12548 }
718e3744 12549
d62a17ae 12550 return bgp_show(vty, bgp, afi, safi,
12551 (exact ? bgp_show_type_community_list_exact
12552 : bgp_show_type_community_list),
1e2ce4f1 12553 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12554}
12555
d62a17ae 12556static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12557 const char *prefix, afi_t afi, safi_t safi,
12558 enum bgp_show_type type)
718e3744 12559{
d62a17ae 12560 int ret;
12561 struct prefix *p;
96c81f66 12562 uint16_t show_flags = 0;
47fc97cc 12563
d62a17ae 12564 p = prefix_new();
95cbbd2a 12565
d62a17ae 12566 ret = str2prefix(prefix, p);
12567 if (!ret) {
12568 vty_out(vty, "%% Malformed Prefix\n");
12569 return CMD_WARNING;
12570 }
47e9b292 12571
1e2ce4f1
DS
12572 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12573 RPKI_NOT_BEING_USED);
63265b5c 12574 prefix_free(&p);
d62a17ae 12575 return ret;
12576}
12577
d62a17ae 12578enum bgp_stats {
12579 BGP_STATS_MAXBITLEN = 0,
12580 BGP_STATS_RIB,
12581 BGP_STATS_PREFIXES,
12582 BGP_STATS_TOTPLEN,
12583 BGP_STATS_UNAGGREGATEABLE,
12584 BGP_STATS_MAX_AGGREGATEABLE,
12585 BGP_STATS_AGGREGATES,
12586 BGP_STATS_SPACE,
12587 BGP_STATS_ASPATH_COUNT,
12588 BGP_STATS_ASPATH_MAXHOPS,
12589 BGP_STATS_ASPATH_TOTHOPS,
12590 BGP_STATS_ASPATH_MAXSIZE,
12591 BGP_STATS_ASPATH_TOTSIZE,
12592 BGP_STATS_ASN_HIGHEST,
12593 BGP_STATS_MAX,
a636c635 12594};
2815e61f 12595
9ab0cf58 12596#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12597#define TABLE_STATS_IDX_JSON 1
12598
12599static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12600 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12601 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12602 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12603 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12604 "unaggregateablePrefixes"},
12605 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12606 "maximumAggregateablePrefixes"},
12607 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12608 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12609 [BGP_STATS_SPACE] = {"Address space advertised",
12610 "addressSpaceAdvertised"},
9ab0cf58
PG
12611 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12612 "advertisementsWithPaths"},
12613 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12614 "longestAsPath"},
12615 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12616 "largestAsPath"},
12617 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12618 "averageAsPathLengthHops"},
12619 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12620 "averageAsPathSizeBytes"},
12621 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12622 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12623};
2815e61f 12624
d62a17ae 12625struct bgp_table_stats {
12626 struct bgp_table *table;
12627 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12628 double total_space;
ff7924f6
PJ
12629};
12630
9bcb3eef 12631static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12632 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12633{
9bcb3eef 12634 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12635 struct bgp_path_info *pi;
b54892e0 12636 const struct prefix *rn_p;
d62a17ae 12637
9bcb3eef 12638 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12639 return;
d62a17ae 12640
9bcb3eef 12641 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12642 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12643 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12644
9c14ec72 12645 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12646 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12647 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12648
9bcb3eef 12649 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12650 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12651 /* announced address space */
12652 if (space)
b54892e0 12653 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12654 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12655 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12656
9c14ec72 12657
9bcb3eef 12658 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12659 ts->counts[BGP_STATS_RIB]++;
12660
05864da7
DS
12661 if (CHECK_FLAG(pi->attr->flag,
12662 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12663 ts->counts[BGP_STATS_AGGREGATES]++;
12664
12665 /* as-path stats */
05864da7 12666 if (pi->attr->aspath) {
9c14ec72
RW
12667 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12668 unsigned int size = aspath_size(pi->attr->aspath);
12669 as_t highest = aspath_highest(pi->attr->aspath);
12670
12671 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12672
12673 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12674 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12675
12676 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12677 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12678
12679 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12680 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12681 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12682 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12683 }
12684 }
12685}
12686
12687static int bgp_table_stats_walker(struct thread *t)
12688{
9bcb3eef
DS
12689 struct bgp_dest *dest, *ndest;
12690 struct bgp_dest *top;
9c14ec72
RW
12691 struct bgp_table_stats *ts = THREAD_ARG(t);
12692 unsigned int space = 0;
12693
12694 if (!(top = bgp_table_top(ts->table)))
12695 return 0;
12696
12697 switch (ts->table->afi) {
12698 case AFI_IP:
12699 space = IPV4_MAX_BITLEN;
12700 break;
12701 case AFI_IP6:
12702 space = IPV6_MAX_BITLEN;
12703 break;
3ba7b4af
TA
12704 case AFI_L2VPN:
12705 space = EVPN_ROUTE_PREFIXLEN;
12706 break;
9c14ec72
RW
12707 default:
12708 return 0;
12709 }
12710
12711 ts->counts[BGP_STATS_MAXBITLEN] = space;
12712
9bcb3eef 12713 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12714 if (ts->table->safi == SAFI_MPLS_VPN
12715 || ts->table->safi == SAFI_ENCAP
12716 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12717 struct bgp_table *table;
12718
9bcb3eef 12719 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12720 if (!table)
12721 continue;
12722
12723 top = bgp_table_top(table);
9bcb3eef
DS
12724 for (ndest = bgp_table_top(table); ndest;
12725 ndest = bgp_route_next(ndest))
12726 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12727 } else {
9bcb3eef 12728 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12729 }
12730 }
9c14ec72 12731
d62a17ae 12732 return 0;
2815e61f 12733}
ff7924f6 12734
71f1613a
DA
12735static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12736 struct json_object *json_array)
12737{
12738 struct listnode *node, *nnode;
12739 struct bgp *bgp;
12740
12741 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12742 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12743}
12744
12745static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12746 safi_t safi, struct json_object *json_array)
2815e61f 12747{
d62a17ae 12748 struct bgp_table_stats ts;
12749 unsigned int i;
893cccd0
PG
12750 int ret = CMD_SUCCESS;
12751 char temp_buf[20];
6c9d22e2
PG
12752 struct json_object *json = NULL;
12753
12754 if (json_array)
12755 json = json_object_new_object();
019386c2 12756
d62a17ae 12757 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12758 char warning_msg[50];
12759
12760 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12761 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12762 safi);
6c9d22e2
PG
12763
12764 if (!json)
893cccd0
PG
12765 vty_out(vty, "%s\n", warning_msg);
12766 else
9ab0cf58 12767 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12768
893cccd0
PG
12769 ret = CMD_WARNING;
12770 goto end_table_stats;
d62a17ae 12771 }
019386c2 12772
893cccd0 12773 if (!json)
5290ceab
DA
12774 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12775 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12776 else
12777 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12778
d62a17ae 12779 /* labeled-unicast routes live in the unicast table */
12780 if (safi == SAFI_LABELED_UNICAST)
12781 safi = SAFI_UNICAST;
019386c2 12782
d62a17ae 12783 memset(&ts, 0, sizeof(ts));
12784 ts.table = bgp->rib[afi][safi];
12785 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12786
d62a17ae 12787 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12788 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12789 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12790 continue;
12791
12792 switch (i) {
d62a17ae 12793 case BGP_STATS_ASPATH_TOTHOPS:
12794 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12795 if (!json) {
9ab0cf58
PG
12796 snprintf(
12797 temp_buf, sizeof(temp_buf), "%12.2f",
12798 ts.counts[i]
12799 ? (float)ts.counts[i]
12800 / (float)ts.counts
12801 [BGP_STATS_ASPATH_COUNT]
12802 : 0);
893cccd0 12803 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12804 table_stats_strs[i]
12805 [TABLE_STATS_IDX_VTY],
893cccd0 12806 temp_buf);
9ab0cf58
PG
12807 } else {
12808 json_object_double_add(
12809 json,
12810 table_stats_strs[i]
12811 [TABLE_STATS_IDX_JSON],
12812 ts.counts[i]
12813 ? (double)ts.counts[i]
12814 / (double)ts.counts
d62a17ae 12815 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12816 : 0);
12817 }
d62a17ae 12818 break;
12819 case BGP_STATS_TOTPLEN:
6c9d22e2 12820 if (!json) {
9ab0cf58
PG
12821 snprintf(
12822 temp_buf, sizeof(temp_buf), "%12.2f",
12823 ts.counts[i]
12824 ? (float)ts.counts[i]
12825 / (float)ts.counts
12826 [BGP_STATS_PREFIXES]
12827 : 0);
893cccd0 12828 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12829 table_stats_strs[i]
12830 [TABLE_STATS_IDX_VTY],
893cccd0 12831 temp_buf);
9ab0cf58
PG
12832 } else {
12833 json_object_double_add(
12834 json,
12835 table_stats_strs[i]
12836 [TABLE_STATS_IDX_JSON],
12837 ts.counts[i]
12838 ? (double)ts.counts[i]
12839 / (double)ts.counts
d62a17ae 12840 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12841 : 0);
12842 }
d62a17ae 12843 break;
12844 case BGP_STATS_SPACE:
6c9d22e2
PG
12845 if (!json) {
12846 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12847 ts.total_space);
893cccd0 12848 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12849 table_stats_strs[i]
12850 [TABLE_STATS_IDX_VTY],
893cccd0 12851 temp_buf);
9ab0cf58
PG
12852 } else {
12853 json_object_double_add(
12854 json,
12855 table_stats_strs[i]
12856 [TABLE_STATS_IDX_JSON],
12857 (double)ts.total_space);
12858 }
8d0ab76d 12859 if (afi == AFI_IP6) {
6c9d22e2
PG
12860 if (!json) {
12861 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12862 "%12g",
12863 ts.total_space
12864 * pow(2.0, -128 + 32));
6c9d22e2
PG
12865 vty_out(vty, "%30s: %s\n",
12866 "/32 equivalent %s\n",
12867 temp_buf);
9ab0cf58
PG
12868 } else {
12869 json_object_double_add(
12870 json, "/32equivalent",
12871 (double)(ts.total_space
12872 * pow(2.0,
12873 -128 + 32)));
12874 }
6c9d22e2
PG
12875 if (!json) {
12876 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12877 "%12g",
12878 ts.total_space
12879 * pow(2.0, -128 + 48));
6c9d22e2
PG
12880 vty_out(vty, "%30s: %s\n",
12881 "/48 equivalent %s\n",
12882 temp_buf);
9ab0cf58
PG
12883 } else {
12884 json_object_double_add(
12885 json, "/48equivalent",
12886 (double)(ts.total_space
12887 * pow(2.0,
12888 -128 + 48)));
12889 }
8d0ab76d 12890 } else {
6c9d22e2
PG
12891 if (!json) {
12892 snprintf(temp_buf, sizeof(temp_buf),
12893 "%12.2f",
9ab0cf58
PG
12894 ts.total_space * 100.
12895 * pow(2.0, -32));
6c9d22e2 12896 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12897 "% announced ", temp_buf);
12898 } else {
12899 json_object_double_add(
12900 json, "%announced",
12901 (double)(ts.total_space * 100.
12902 * pow(2.0, -32)));
12903 }
6c9d22e2
PG
12904 if (!json) {
12905 snprintf(temp_buf, sizeof(temp_buf),
12906 "%12.2f",
9ab0cf58
PG
12907 ts.total_space
12908 * pow(2.0, -32 + 8));
6c9d22e2
PG
12909 vty_out(vty, "%30s: %s\n",
12910 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12911 } else {
12912 json_object_double_add(
12913 json, "/8equivalent",
12914 (double)(ts.total_space
12915 * pow(2.0, -32 + 8)));
12916 }
6c9d22e2
PG
12917 if (!json) {
12918 snprintf(temp_buf, sizeof(temp_buf),
12919 "%12.2f",
9ab0cf58
PG
12920 ts.total_space
12921 * pow(2.0, -32 + 24));
6c9d22e2 12922 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12923 "/24 equivalent ", temp_buf);
12924 } else {
12925 json_object_double_add(
12926 json, "/24equivalent",
12927 (double)(ts.total_space
12928 * pow(2.0, -32 + 24)));
12929 }
8d0ab76d 12930 }
d62a17ae 12931 break;
12932 default:
6c9d22e2
PG
12933 if (!json) {
12934 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12935 ts.counts[i]);
893cccd0 12936 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12937 table_stats_strs[i]
12938 [TABLE_STATS_IDX_VTY],
12939 temp_buf);
12940 } else {
12941 json_object_int_add(
12942 json,
12943 table_stats_strs[i]
12944 [TABLE_STATS_IDX_JSON],
12945 ts.counts[i]);
12946 }
d62a17ae 12947 }
893cccd0
PG
12948 if (!json)
12949 vty_out(vty, "\n");
d62a17ae 12950 }
9ab0cf58 12951end_table_stats:
6c9d22e2
PG
12952 if (json)
12953 json_object_array_add(json_array, json);
893cccd0 12954 return ret;
d62a17ae 12955}
12956
71f1613a
DA
12957static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12958 safi_t safi, struct json_object *json_array)
12959{
12960 if (!bgp) {
12961 bgp_table_stats_all(vty, afi, safi, json_array);
12962 return CMD_SUCCESS;
12963 }
12964
12965 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12966}
12967
d62a17ae 12968enum bgp_pcounts {
12969 PCOUNT_ADJ_IN = 0,
12970 PCOUNT_DAMPED,
12971 PCOUNT_REMOVED,
12972 PCOUNT_HISTORY,
12973 PCOUNT_STALE,
12974 PCOUNT_VALID,
12975 PCOUNT_ALL,
12976 PCOUNT_COUNTED,
7e3d9632 12977 PCOUNT_BPATH_SELECTED,
d62a17ae 12978 PCOUNT_PFCNT, /* the figure we display to users */
12979 PCOUNT_MAX,
a636c635 12980};
718e3744 12981
2b64873d 12982static const char *const pcount_strs[] = {
9d303b37
DL
12983 [PCOUNT_ADJ_IN] = "Adj-in",
12984 [PCOUNT_DAMPED] = "Damped",
12985 [PCOUNT_REMOVED] = "Removed",
12986 [PCOUNT_HISTORY] = "History",
12987 [PCOUNT_STALE] = "Stale",
12988 [PCOUNT_VALID] = "Valid",
12989 [PCOUNT_ALL] = "All RIB",
12990 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12991 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12992 [PCOUNT_PFCNT] = "Useable",
12993 [PCOUNT_MAX] = NULL,
a636c635 12994};
718e3744 12995
d62a17ae 12996struct peer_pcounts {
12997 unsigned int count[PCOUNT_MAX];
12998 const struct peer *peer;
12999 const struct bgp_table *table;
54317cba 13000 safi_t safi;
a636c635 13001};
47fc97cc 13002
9bcb3eef 13003static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13004{
54317cba
JW
13005 const struct bgp_adj_in *ain;
13006 const struct bgp_path_info *pi;
d62a17ae 13007 const struct peer *peer = pc->peer;
13008
54317cba
JW
13009 for (ain = rn->adj_in; ain; ain = ain->next)
13010 if (ain->peer == peer)
13011 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13012
9bcb3eef 13013 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13014
54317cba
JW
13015 if (pi->peer != peer)
13016 continue;
d62a17ae 13017
54317cba 13018 pc->count[PCOUNT_ALL]++;
d62a17ae 13019
54317cba
JW
13020 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13021 pc->count[PCOUNT_DAMPED]++;
13022 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13023 pc->count[PCOUNT_HISTORY]++;
13024 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13025 pc->count[PCOUNT_REMOVED]++;
13026 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13027 pc->count[PCOUNT_STALE]++;
13028 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13029 pc->count[PCOUNT_VALID]++;
13030 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13031 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13032 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13033 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13034
13035 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13036 pc->count[PCOUNT_COUNTED]++;
13037 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13038 flog_err(
13039 EC_LIB_DEVELOPMENT,
13040 "Attempting to count but flags say it is unusable");
13041 } else {
40381db7 13042 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13043 flog_err(
13044 EC_LIB_DEVELOPMENT,
13045 "Not counted but flags say we should");
d62a17ae 13046 }
13047 }
54317cba
JW
13048}
13049
13050static int bgp_peer_count_walker(struct thread *t)
13051{
9bcb3eef 13052 struct bgp_dest *rn, *rm;
54317cba
JW
13053 const struct bgp_table *table;
13054 struct peer_pcounts *pc = THREAD_ARG(t);
13055
13056 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13057 || pc->safi == SAFI_EVPN) {
13058 /* Special handling for 2-level routing tables. */
13059 for (rn = bgp_table_top(pc->table); rn;
13060 rn = bgp_route_next(rn)) {
9bcb3eef 13061 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13062 if (table != NULL)
13063 for (rm = bgp_table_top(table); rm;
13064 rm = bgp_route_next(rm))
13065 bgp_peer_count_proc(rm, pc);
13066 }
13067 } else
13068 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13069 bgp_peer_count_proc(rn, pc);
13070
d62a17ae 13071 return 0;
718e3744 13072}
13073
d62a17ae 13074static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13075 safi_t safi, bool use_json)
856ca177 13076{
d62a17ae 13077 struct peer_pcounts pcounts = {.peer = peer};
13078 unsigned int i;
13079 json_object *json = NULL;
13080 json_object *json_loop = NULL;
856ca177 13081
d62a17ae 13082 if (use_json) {
13083 json = json_object_new_object();
13084 json_loop = json_object_new_object();
13085 }
718e3744 13086
d62a17ae 13087 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13088 || !peer->bgp->rib[afi][safi]) {
13089 if (use_json) {
13090 json_object_string_add(
13091 json, "warning",
13092 "No such neighbor or address family");
13093 vty_out(vty, "%s\n", json_object_to_json_string(json));
13094 json_object_free(json);
d5f20468 13095 json_object_free(json_loop);
d62a17ae 13096 } else
13097 vty_out(vty, "%% No such neighbor or address family\n");
13098
13099 return CMD_WARNING;
13100 }
2a71e9ce 13101
d62a17ae 13102 memset(&pcounts, 0, sizeof(pcounts));
13103 pcounts.peer = peer;
13104 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13105 pcounts.safi = safi;
d62a17ae 13106
13107 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13108 * stats for the thread-walk (i.e. ensure this can't be blamed on
13109 * on just vty_read()).
13110 */
d62a17ae 13111 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13112
13113 if (use_json) {
13114 json_object_string_add(json, "prefixCountsFor", peer->host);
13115 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13116 get_afi_safi_str(afi, safi, true));
d62a17ae 13117 json_object_int_add(json, "pfxCounter",
13118 peer->pcount[afi][safi]);
13119
13120 for (i = 0; i < PCOUNT_MAX; i++)
13121 json_object_int_add(json_loop, pcount_strs[i],
13122 pcounts.count[i]);
13123
13124 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13125
13126 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13127 json_object_string_add(json, "pfxctDriftFor",
13128 peer->host);
13129 json_object_string_add(
13130 json, "recommended",
13131 "Please report this bug, with the above command output");
13132 }
996c9314
LB
13133 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13134 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13135 json_object_free(json);
13136 } else {
13137
13138 if (peer->hostname
892fedb6 13139 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13140 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13141 peer->hostname, peer->host,
5cb5f4d0 13142 get_afi_safi_str(afi, safi, false));
d62a17ae 13143 } else {
13144 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13145 get_afi_safi_str(afi, safi, false));
d62a17ae 13146 }
13147
6cde4b45 13148 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13149 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13150
13151 for (i = 0; i < PCOUNT_MAX; i++)
13152 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13153 pcounts.count[i]);
13154
13155 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13156 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13157 vty_out(vty,
13158 "Please report this bug, with the above command output\n");
13159 }
13160 }
13161
13162 return CMD_SUCCESS;
718e3744 13163}
13164
a636c635
DW
13165DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13166 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13167 "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 13168 SHOW_STR
13169 IP_STR
13170 BGP_STR
8386ac43 13171 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13172 BGP_AFI_HELP_STR
13173 BGP_SAFI_HELP_STR
0b16f239
DS
13174 "Detailed information on TCP and BGP neighbor connections\n"
13175 "Neighbor to display information about\n"
13176 "Neighbor to display information about\n"
91d37724 13177 "Neighbor on BGP configured interface\n"
a636c635 13178 "Display detailed prefix count information\n"
9973d184 13179 JSON_STR)
0b16f239 13180{
d62a17ae 13181 afi_t afi = AFI_IP6;
13182 safi_t safi = SAFI_UNICAST;
13183 struct peer *peer;
13184 int idx = 0;
13185 struct bgp *bgp = NULL;
9f049418
DS
13186 bool uj = use_json(argc, argv);
13187
13188 if (uj)
13189 argc--;
856ca177 13190
d62a17ae 13191 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13192 &bgp, uj);
d62a17ae 13193 if (!idx)
13194 return CMD_WARNING;
0b16f239 13195
d62a17ae 13196 argv_find(argv, argc, "neighbors", &idx);
13197 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13198 if (!peer)
13199 return CMD_WARNING;
bb46e94f 13200
29c8d9da 13201 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13202}
0b16f239 13203
d6902373
PG
13204#ifdef KEEP_OLD_VPN_COMMANDS
13205DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13206 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13207 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13208 SHOW_STR
13209 IP_STR
13210 BGP_STR
d6902373 13211 BGP_VPNVX_HELP_STR
91d37724 13212 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13213 "Detailed information on TCP and BGP neighbor connections\n"
13214 "Neighbor to display information about\n"
13215 "Neighbor to display information about\n"
91d37724 13216 "Neighbor on BGP configured interface\n"
a636c635 13217 "Display detailed prefix count information\n"
9973d184 13218 JSON_STR)
a636c635 13219{
d62a17ae 13220 int idx_peer = 6;
13221 struct peer *peer;
9f049418 13222 bool uj = use_json(argc, argv);
a636c635 13223
d62a17ae 13224 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13225 if (!peer)
13226 return CMD_WARNING;
13227
13228 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13229}
13230
d6902373
PG
13231DEFUN (show_ip_bgp_vpn_all_route_prefix,
13232 show_ip_bgp_vpn_all_route_prefix_cmd,
13233 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13234 SHOW_STR
13235 IP_STR
13236 BGP_STR
d6902373 13237 BGP_VPNVX_HELP_STR
91d37724
QY
13238 "Display information about all VPNv4 NLRIs\n"
13239 "Network in the BGP routing table to display\n"
3a2d747c 13240 "Network in the BGP routing table to display\n"
9973d184 13241 JSON_STR)
91d37724 13242{
d62a17ae 13243 int idx = 0;
13244 char *network = NULL;
13245 struct bgp *bgp = bgp_get_default();
13246 if (!bgp) {
13247 vty_out(vty, "Can't find default instance\n");
13248 return CMD_WARNING;
13249 }
87e34b58 13250
d62a17ae 13251 if (argv_find(argv, argc, "A.B.C.D", &idx))
13252 network = argv[idx]->arg;
13253 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13254 network = argv[idx]->arg;
13255 else {
13256 vty_out(vty, "Unable to figure out Network\n");
13257 return CMD_WARNING;
13258 }
87e34b58 13259
d62a17ae 13260 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13261 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13262 use_json(argc, argv));
91d37724 13263}
d6902373 13264#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13265
44c69747
LK
13266DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13267 show_bgp_l2vpn_evpn_route_prefix_cmd,
13268 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13269 SHOW_STR
4c63a661
PG
13270 BGP_STR
13271 L2VPN_HELP_STR
13272 EVPN_HELP_STR
44c69747
LK
13273 "Network in the BGP routing table to display\n"
13274 "Network in the BGP routing table to display\n"
4c63a661
PG
13275 "Network in the BGP routing table to display\n"
13276 "Network in the BGP routing table to display\n"
13277 JSON_STR)
13278{
d62a17ae 13279 int idx = 0;
13280 char *network = NULL;
44c69747 13281 int prefix_check = 0;
a636c635 13282
44c69747
LK
13283 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13284 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13285 network = argv[idx]->arg;
44c69747 13286 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13287 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13288 network = argv[idx]->arg;
44c69747
LK
13289 prefix_check = 1;
13290 } else {
d62a17ae 13291 vty_out(vty, "Unable to figure out Network\n");
13292 return CMD_WARNING;
13293 }
44c69747
LK
13294 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13295 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13296 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13297}
13298
2f9bc755
DS
13299static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13300 struct bgp_table *table, int *header1,
13301 int *header2, json_object *json,
13302 json_object *json_scode,
13303 json_object *json_ocode, bool wide)
13304{
13305 uint64_t version = table ? table->version : 0;
23d0a753 13306 char buf[BUFSIZ] = {0};
2f9bc755
DS
13307
13308 if (*header1) {
13309 if (json) {
13310 json_object_int_add(json, "bgpTableVersion", version);
13311 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13312 inet_ntop(AF_INET,
13313 &bgp->router_id, buf,
13314 sizeof(buf)));
2f9bc755
DS
13315 json_object_int_add(json, "defaultLocPrf",
13316 bgp->default_local_pref);
13317 json_object_int_add(json, "localAS", bgp->as);
13318 json_object_object_add(json, "bgpStatusCodes",
13319 json_scode);
13320 json_object_object_add(json, "bgpOriginCodes",
13321 json_ocode);
13322 } else {
13323 vty_out(vty,
23d0a753
DA
13324 "BGP table version is %" PRIu64
13325 ", local router ID is %pI4, vrf id ",
13326 version, &bgp->router_id);
2f9bc755
DS
13327 if (bgp->vrf_id == VRF_UNKNOWN)
13328 vty_out(vty, "%s", VRFID_NONE_STR);
13329 else
13330 vty_out(vty, "%u", bgp->vrf_id);
13331 vty_out(vty, "\n");
13332 vty_out(vty, "Default local pref %u, ",
13333 bgp->default_local_pref);
13334 vty_out(vty, "local AS %u\n", bgp->as);
13335 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13336 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13337 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13338 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13339 }
13340 *header1 = 0;
13341 }
13342 if (*header2) {
13343 if (!json)
13344 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13345 : BGP_SHOW_HEADER));
13346 *header2 = 0;
13347 }
13348}
13349
d9478df0
TA
13350static void
13351show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13352 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13353 const char *rmap_name, json_object *json, json_object *json_ar,
13354 json_object *json_scode, json_object *json_ocode,
96c81f66 13355 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13356 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13357{
d62a17ae 13358 struct bgp_adj_in *ain;
13359 struct bgp_adj_out *adj;
9bcb3eef 13360 struct bgp_dest *dest;
d62a17ae 13361 struct bgp *bgp;
d62a17ae 13362 struct attr attr;
13363 int ret;
13364 struct update_subgroup *subgrp;
d62a17ae 13365 struct peer_af *paf;
f99def61 13366 bool route_filtered;
96f3485c
MK
13367 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13368 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13369 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13370 || (safi == SAFI_EVPN))
13371 ? true
13372 : false;
a636c635 13373
d62a17ae 13374 bgp = peer->bgp;
a636c635 13375
d62a17ae 13376 if (!bgp) {
13377 if (use_json) {
13378 json_object_string_add(json, "alert", "no BGP");
13379 vty_out(vty, "%s\n", json_object_to_json_string(json));
13380 json_object_free(json);
13381 } else
13382 vty_out(vty, "%% No bgp\n");
13383 return;
13384 }
a636c635 13385
d62a17ae 13386 subgrp = peer_subgroup(peer, afi, safi);
13387
6392aaa6 13388 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13389 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13390 char buf[BUFSIZ] = {0};
13391
d62a17ae 13392 if (use_json) {
13393 json_object_int_add(json, "bgpTableVersion",
13394 table->version);
13395 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13396 inet_ntop(AF_INET,
13397 &bgp->router_id, buf,
13398 sizeof(buf)));
01eced22
AD
13399 json_object_int_add(json, "defaultLocPrf",
13400 bgp->default_local_pref);
13401 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13402 json_object_object_add(json, "bgpStatusCodes",
13403 json_scode);
13404 json_object_object_add(json, "bgpOriginCodes",
13405 json_ocode);
07d0c4ed
DA
13406 json_object_string_add(
13407 json, "bgpOriginatingDefaultNetwork",
13408 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13409 } else {
23d0a753
DA
13410 vty_out(vty,
13411 "BGP table version is %" PRIu64
13412 ", local router ID is %pI4, vrf id ",
13413 table->version, &bgp->router_id);
9df8b37c
PZ
13414 if (bgp->vrf_id == VRF_UNKNOWN)
13415 vty_out(vty, "%s", VRFID_NONE_STR);
13416 else
13417 vty_out(vty, "%u", bgp->vrf_id);
13418 vty_out(vty, "\n");
01eced22
AD
13419 vty_out(vty, "Default local pref %u, ",
13420 bgp->default_local_pref);
13421 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13422 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13423 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13424 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13425 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13426
07d0c4ed
DA
13427 vty_out(vty, "Originating default network %s\n\n",
13428 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13429 }
d9478df0 13430 *header1 = 0;
d62a17ae 13431 }
a636c635 13432
9bcb3eef 13433 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13434 if (type == bgp_show_adj_route_received
13435 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13436 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13437 if (ain->peer != peer)
ea47320b 13438 continue;
6392aaa6 13439
d9478df0
TA
13440 show_adj_route_header(vty, bgp, table, header1,
13441 header2, json, json_scode,
13442 json_ocode, wide);
13443
13444 if ((safi == SAFI_MPLS_VPN)
13445 || (safi == SAFI_ENCAP)
13446 || (safi == SAFI_EVPN)) {
13447 if (use_json)
13448 json_object_string_add(
13449 json_ar, "rd", rd_str);
13450 else if (show_rd && rd_str) {
13451 vty_out(vty,
13452 "Route Distinguisher: %s\n",
13453 rd_str);
13454 show_rd = false;
13455 }
13456 }
6392aaa6 13457
6f4f49b2 13458 attr = *ain->attr;
f99def61
AD
13459 route_filtered = false;
13460
13461 /* Filter prefix using distribute list,
13462 * filter list or prefix list
13463 */
b54892e0 13464 const struct prefix *rn_p =
9bcb3eef 13465 bgp_dest_get_prefix(dest);
b54892e0
DS
13466 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13467 safi))
13468 == FILTER_DENY)
f99def61
AD
13469 route_filtered = true;
13470
13471 /* Filter prefix using route-map */
b54892e0
DS
13472 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13473 safi, rmap_name, NULL,
13474 0, NULL);
6392aaa6 13475
13c8e163
AD
13476 if (type == bgp_show_adj_route_filtered &&
13477 !route_filtered && ret != RMAP_DENY) {
b755861b 13478 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13479 continue;
d62a17ae 13480 }
6392aaa6 13481
d9478df0
TA
13482 if (type == bgp_show_adj_route_received
13483 && (route_filtered || ret == RMAP_DENY))
13484 (*filtered_count)++;
6392aaa6 13485
7d3cae70 13486 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13487 use_json, json_ar, wide);
b755861b 13488 bgp_attr_undup(&attr, ain->attr);
d9478df0 13489 (*output_count)++;
d62a17ae 13490 }
6392aaa6 13491 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13492 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13493 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13494 if (paf->peer != peer || !adj->attr)
924c3f6a 13495 continue;
d62a17ae 13496
d9478df0
TA
13497 show_adj_route_header(vty, bgp, table,
13498 header1, header2,
13499 json, json_scode,
13500 json_ocode, wide);
d62a17ae 13501
b54892e0 13502 const struct prefix *rn_p =
9bcb3eef 13503 bgp_dest_get_prefix(dest);
b54892e0 13504
6f4f49b2 13505 attr = *adj->attr;
b755861b 13506 ret = bgp_output_modifier(
b54892e0 13507 peer, rn_p, &attr, afi, safi,
b755861b 13508 rmap_name);
f46d8e1e 13509
b755861b 13510 if (ret != RMAP_DENY) {
d9478df0
TA
13511 if ((safi == SAFI_MPLS_VPN)
13512 || (safi == SAFI_ENCAP)
13513 || (safi == SAFI_EVPN)) {
13514 if (use_json)
13515 json_object_string_add(
13516 json_ar,
13517 "rd",
13518 rd_str);
13519 else if (show_rd
13520 && rd_str) {
13521 vty_out(vty,
13522 "Route Distinguisher: %s\n",
13523 rd_str);
13524 show_rd = false;
13525 }
13526 }
b54892e0 13527 route_vty_out_tmp(
7d3cae70
DA
13528 vty, dest, rn_p, &attr,
13529 safi, use_json, json_ar,
ae248832 13530 wide);
d9478df0 13531 (*output_count)++;
b755861b 13532 } else {
d9478df0 13533 (*filtered_count)++;
a2addae8 13534 }
b755861b
PM
13535
13536 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13537 }
f20ce998
DS
13538 } else if (type == bgp_show_adj_route_bestpath) {
13539 struct bgp_path_info *pi;
13540
d9478df0
TA
13541 show_adj_route_header(vty, bgp, table, header1, header2,
13542 json, json_scode, json_ocode,
13543 wide);
f20ce998
DS
13544
13545 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13546 pi = pi->next) {
13547 if (pi->peer != peer)
13548 continue;
13549
13550 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13551 continue;
13552
7d3cae70 13553 route_vty_out_tmp(vty, dest,
f20ce998
DS
13554 bgp_dest_get_prefix(dest),
13555 pi->attr, safi, use_json,
13556 json_ar, wide);
d9478df0 13557 (*output_count)++;
f20ce998 13558 }
d62a17ae 13559 }
13560 }
a636c635 13561}
2a71e9ce 13562
d62a17ae 13563static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13564 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13565 const char *rmap_name, uint16_t show_flags)
0b16f239 13566{
d9478df0
TA
13567 struct bgp *bgp;
13568 struct bgp_table *table;
d62a17ae 13569 json_object *json = NULL;
d9478df0
TA
13570 json_object *json_scode = NULL;
13571 json_object *json_ocode = NULL;
13572 json_object *json_ar = NULL;
96f3485c 13573 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13574
d9478df0
TA
13575 /* Init BGP headers here so they're only displayed once
13576 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13577 */
13578 int header1 = 1;
13579 int header2 = 1;
13580
13581 /*
13582 * Initialize variables for each RD
13583 * All prefixes under an RD is aggregated within "json_routes"
13584 */
13585 char rd_str[BUFSIZ] = {0};
13586 json_object *json_routes = NULL;
13587
13588
13589 /* For 2-tier tables, prefix counts need to be
13590 * maintained across multiple runs of show_adj_route()
13591 */
13592 unsigned long output_count_per_rd;
13593 unsigned long filtered_count_per_rd;
13594 unsigned long output_count = 0;
13595 unsigned long filtered_count = 0;
13596
13597 if (use_json) {
d62a17ae 13598 json = json_object_new_object();
d9478df0
TA
13599 json_ar = json_object_new_object();
13600 json_scode = json_object_new_object();
13601 json_ocode = json_object_new_object();
13602
13603 json_object_string_add(json_scode, "suppressed", "s");
13604 json_object_string_add(json_scode, "damped", "d");
13605 json_object_string_add(json_scode, "history", "h");
13606 json_object_string_add(json_scode, "valid", "*");
13607 json_object_string_add(json_scode, "best", ">");
13608 json_object_string_add(json_scode, "multipath", "=");
13609 json_object_string_add(json_scode, "internal", "i");
13610 json_object_string_add(json_scode, "ribFailure", "r");
13611 json_object_string_add(json_scode, "stale", "S");
13612 json_object_string_add(json_scode, "removed", "R");
13613
13614 json_object_string_add(json_ocode, "igp", "i");
13615 json_object_string_add(json_ocode, "egp", "e");
13616 json_object_string_add(json_ocode, "incomplete", "?");
13617 }
0b16f239 13618
d62a17ae 13619 if (!peer || !peer->afc[afi][safi]) {
13620 if (use_json) {
13621 json_object_string_add(
13622 json, "warning",
13623 "No such neighbor or address family");
13624 vty_out(vty, "%s\n", json_object_to_json_string(json));
13625 json_object_free(json);
13626 } else
13627 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13628
d62a17ae 13629 return CMD_WARNING;
13630 }
13631
6392aaa6
PM
13632 if ((type == bgp_show_adj_route_received
13633 || type == bgp_show_adj_route_filtered)
d62a17ae 13634 && !CHECK_FLAG(peer->af_flags[afi][safi],
13635 PEER_FLAG_SOFT_RECONFIG)) {
13636 if (use_json) {
13637 json_object_string_add(
13638 json, "warning",
13639 "Inbound soft reconfiguration not enabled");
13640 vty_out(vty, "%s\n", json_object_to_json_string(json));
13641 json_object_free(json);
13642 } else
13643 vty_out(vty,
13644 "%% Inbound soft reconfiguration not enabled\n");
13645
13646 return CMD_WARNING;
13647 }
0b16f239 13648
d9478df0
TA
13649 bgp = peer->bgp;
13650
13651 /* labeled-unicast routes live in the unicast table */
13652 if (safi == SAFI_LABELED_UNICAST)
13653 table = bgp->rib[afi][SAFI_UNICAST];
13654 else
13655 table = bgp->rib[afi][safi];
13656
13657 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13658 || (safi == SAFI_EVPN)) {
13659
13660 struct bgp_dest *dest;
13661
13662 for (dest = bgp_table_top(table); dest;
13663 dest = bgp_route_next(dest)) {
13664 table = bgp_dest_get_bgp_table_info(dest);
13665 if (!table)
13666 continue;
13667
13668 output_count_per_rd = 0;
13669 filtered_count_per_rd = 0;
13670
13671 if (use_json)
13672 json_routes = json_object_new_object();
13673
13674 const struct prefix_rd *prd;
13675 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13676 dest);
13677
13678 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13679
13680 show_adj_route(vty, peer, table, afi, safi, type,
13681 rmap_name, json, json_routes, json_scode,
13682 json_ocode, show_flags, &header1,
13683 &header2, rd_str, &output_count_per_rd,
13684 &filtered_count_per_rd);
13685
13686 /* Don't include an empty RD in the output! */
13687 if (json_routes && (output_count_per_rd > 0))
13688 json_object_object_add(json_ar, rd_str,
13689 json_routes);
13690
13691 output_count += output_count_per_rd;
13692 filtered_count += filtered_count_per_rd;
13693 }
13694 } else
13695 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13696 json, json_ar, json_scode, json_ocode,
13697 show_flags, &header1, &header2, rd_str,
13698 &output_count, &filtered_count);
13699
13700 if (use_json) {
13701 json_object_object_add(json, "advertisedRoutes", json_ar);
13702 json_object_int_add(json, "totalPrefixCounter", output_count);
13703 json_object_int_add(json, "filteredPrefixCounter",
13704 filtered_count);
13705
13706 vty_out(vty, "%s\n",
13707 json_object_to_json_string_ext(
13708 json, JSON_C_TO_STRING_PRETTY));
13709
13710 if (!output_count && !filtered_count) {
13711 json_object_free(json_scode);
13712 json_object_free(json_ocode);
13713 }
13714
13715 if (json)
13716 json_object_free(json);
13717
13718 } else if (output_count > 0) {
13719 if (filtered_count > 0)
13720 vty_out(vty,
13721 "\nTotal number of prefixes %ld (%ld filtered)\n",
13722 output_count, filtered_count);
13723 else
13724 vty_out(vty, "\nTotal number of prefixes %ld\n",
13725 output_count);
13726 }
0b16f239 13727
d62a17ae 13728 return CMD_SUCCESS;
a636c635 13729}
50ef26d4 13730
f20ce998
DS
13731DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13732 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13733 "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]",
13734 SHOW_STR
13735 IP_STR
13736 BGP_STR
13737 BGP_INSTANCE_HELP_STR
13738 BGP_AFI_HELP_STR
13739 BGP_SAFI_WITH_LABEL_HELP_STR
13740 "Detailed information on TCP and BGP neighbor connections\n"
13741 "Neighbor to display information about\n"
13742 "Neighbor to display information about\n"
13743 "Neighbor on BGP configured interface\n"
13744 "Display the routes selected by best path\n"
13745 JSON_STR
13746 "Increase table width for longer prefixes\n")
13747{
13748 afi_t afi = AFI_IP6;
13749 safi_t safi = SAFI_UNICAST;
13750 char *rmap_name = NULL;
13751 char *peerstr = NULL;
13752 struct bgp *bgp = NULL;
13753 struct peer *peer;
13754 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13755 int idx = 0;
96c81f66 13756 uint16_t show_flags = 0;
96f3485c
MK
13757
13758 if (uj)
13759 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13760
13761 if (wide)
13762 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13763
13764 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13765 &bgp, uj);
13766
13767 if (!idx)
13768 return CMD_WARNING;
13769
13770 argv_find(argv, argc, "neighbors", &idx);
13771 peerstr = argv[++idx]->arg;
13772
13773 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13774 if (!peer)
13775 return CMD_WARNING;
13776
96f3485c
MK
13777 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13778 show_flags);
f20ce998
DS
13779}
13780
ae248832 13781DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13782 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13783 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
718e3744 13784 SHOW_STR
13785 IP_STR
13786 BGP_STR
a636c635 13787 BGP_INSTANCE_HELP_STR
7395a2c9 13788 BGP_AFI_HELP_STR
4dd6177e 13789 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13790 "Display the entries for all address families\n"
718e3744 13791 "Detailed information on TCP and BGP neighbor connections\n"
13792 "Neighbor to display information about\n"
13793 "Neighbor to display information about\n"
91d37724 13794 "Neighbor on BGP configured interface\n"
a636c635 13795 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13796 "Display the received routes from neighbor\n"
13797 "Display the filtered routes received from neighbor\n"
a636c635
DW
13798 "Route-map to modify the attributes\n"
13799 "Name of the route map\n"
ae248832
MK
13800 JSON_STR
13801 "Increase table width for longer prefixes\n")
718e3744 13802{
d62a17ae 13803 afi_t afi = AFI_IP6;
13804 safi_t safi = SAFI_UNICAST;
13805 char *rmap_name = NULL;
13806 char *peerstr = NULL;
d62a17ae 13807 struct bgp *bgp = NULL;
13808 struct peer *peer;
6392aaa6 13809 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13810 int idx = 0;
96f3485c 13811 bool first = true;
96c81f66 13812 uint16_t show_flags = 0;
6392aaa6 13813
96f3485c 13814 if (uj) {
d62a17ae 13815 argc--;
96f3485c
MK
13816 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13817 }
13818
13819 if (all) {
13820 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13821 if (argv_find(argv, argc, "ipv4", &idx))
13822 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13823
13824 if (argv_find(argv, argc, "ipv6", &idx))
13825 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13826 }
13827
13828 if (wide)
13829 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13830
9f049418
DS
13831 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13832 &bgp, uj);
13833 if (!idx)
13834 return CMD_WARNING;
13835
d62a17ae 13836 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13837 argv_find(argv, argc, "neighbors", &idx);
13838 peerstr = argv[++idx]->arg;
8c3deaae 13839
d62a17ae 13840 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13841 if (!peer)
13842 return CMD_WARNING;
856ca177 13843
d62a17ae 13844 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13845 type = bgp_show_adj_route_advertised;
13846 else if (argv_find(argv, argc, "received-routes", &idx))
13847 type = bgp_show_adj_route_received;
13848 else if (argv_find(argv, argc, "filtered-routes", &idx))
13849 type = bgp_show_adj_route_filtered;
13850
d62a17ae 13851 if (argv_find(argv, argc, "route-map", &idx))
13852 rmap_name = argv[++idx]->arg;
95cbbd2a 13853
96f3485c
MK
13854 if (!all)
13855 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13856 show_flags);
13857 if (uj)
13858 vty_out(vty, "{\n");
13859
13860 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13861 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13862 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13863 : AFI_IP6;
13864 FOREACH_SAFI (safi) {
96f3485c
MK
13865 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13866 continue;
13867
13868 if (uj) {
13869 if (first)
13870 first = false;
13871 else
13872 vty_out(vty, ",\n");
13873 vty_out(vty, "\"%s\":",
13874 get_afi_safi_str(afi, safi, true));
13875 } else
13876 vty_out(vty, "\nFor address family: %s\n",
13877 get_afi_safi_str(afi, safi, false));
13878
13879 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13880 show_flags);
13881 }
13882 } else {
13883 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13884 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13885 continue;
13886
13887 if (uj) {
13888 if (first)
13889 first = false;
13890 else
13891 vty_out(vty, ",\n");
13892 vty_out(vty, "\"%s\":",
13893 get_afi_safi_str(afi, safi, true));
13894 } else
13895 vty_out(vty, "\nFor address family: %s\n",
13896 get_afi_safi_str(afi, safi, false));
13897
13898 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13899 show_flags);
13900 }
13901 }
13902 if (uj)
13903 vty_out(vty, "}\n");
13904
13905 return CMD_SUCCESS;
95cbbd2a
ML
13906}
13907
718e3744 13908DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13909 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13910 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13911 SHOW_STR
13912 IP_STR
13913 BGP_STR
8c3deaae
QY
13914 "Address Family\n"
13915 "Address Family\n"
718e3744 13916 "Address Family modifier\n"
13917 "Detailed information on TCP and BGP neighbor connections\n"
13918 "Neighbor to display information about\n"
13919 "Neighbor to display information about\n"
91d37724 13920 "Neighbor on BGP configured interface\n"
718e3744 13921 "Display information received from a BGP neighbor\n"
856ca177 13922 "Display the prefixlist filter\n"
9973d184 13923 JSON_STR)
718e3744 13924{
d62a17ae 13925 afi_t afi = AFI_IP6;
13926 safi_t safi = SAFI_UNICAST;
13927 char *peerstr = NULL;
13928
13929 char name[BUFSIZ];
13930 union sockunion su;
13931 struct peer *peer;
13932 int count, ret;
13933
13934 int idx = 0;
13935
13936 /* show [ip] bgp */
13937 if (argv_find(argv, argc, "ip", &idx))
13938 afi = AFI_IP;
13939 /* [<ipv4|ipv6> [unicast]] */
13940 if (argv_find(argv, argc, "ipv4", &idx))
13941 afi = AFI_IP;
13942 if (argv_find(argv, argc, "ipv6", &idx))
13943 afi = AFI_IP6;
13944 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13945 argv_find(argv, argc, "neighbors", &idx);
13946 peerstr = argv[++idx]->arg;
13947
9f049418 13948 bool uj = use_json(argc, argv);
d62a17ae 13949
13950 ret = str2sockunion(peerstr, &su);
13951 if (ret < 0) {
13952 peer = peer_lookup_by_conf_if(NULL, peerstr);
13953 if (!peer) {
13954 if (uj)
13955 vty_out(vty, "{}\n");
13956 else
13957 vty_out(vty,
13958 "%% Malformed address or name: %s\n",
13959 peerstr);
13960 return CMD_WARNING;
13961 }
13962 } else {
13963 peer = peer_lookup(NULL, &su);
13964 if (!peer) {
13965 if (uj)
13966 vty_out(vty, "{}\n");
13967 else
13968 vty_out(vty, "No peer\n");
13969 return CMD_WARNING;
13970 }
13971 }
718e3744 13972
4ced1a2c 13973 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13974 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13975 if (count) {
13976 if (!uj)
13977 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13978 get_afi_safi_str(afi, safi, false));
d62a17ae 13979 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13980 } else {
13981 if (uj)
13982 vty_out(vty, "{}\n");
13983 else
13984 vty_out(vty, "No functional output\n");
13985 }
718e3744 13986
d62a17ae 13987 return CMD_SUCCESS;
13988}
13989
13990static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13991 afi_t afi, safi_t safi,
9f049418 13992 enum bgp_show_type type, bool use_json)
d62a17ae 13993{
96c81f66 13994 uint16_t show_flags = 0;
96f3485c
MK
13995
13996 if (use_json)
13997 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13998
d62a17ae 13999 if (!peer || !peer->afc[afi][safi]) {
14000 if (use_json) {
14001 json_object *json_no = NULL;
14002 json_no = json_object_new_object();
14003 json_object_string_add(
14004 json_no, "warning",
14005 "No such neighbor or address family");
14006 vty_out(vty, "%s\n",
14007 json_object_to_json_string(json_no));
14008 json_object_free(json_no);
14009 } else
14010 vty_out(vty, "%% No such neighbor or address family\n");
14011 return CMD_WARNING;
14012 }
47fc97cc 14013
7daf25a3
TA
14014 /* labeled-unicast routes live in the unicast table */
14015 if (safi == SAFI_LABELED_UNICAST)
14016 safi = SAFI_UNICAST;
14017
1e2ce4f1
DS
14018 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14019 RPKI_NOT_BEING_USED);
718e3744 14020}
14021
dba3c1d3
PG
14022DEFUN (show_ip_bgp_flowspec_routes_detailed,
14023 show_ip_bgp_flowspec_routes_detailed_cmd,
14024 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14025 SHOW_STR
14026 IP_STR
14027 BGP_STR
14028 BGP_INSTANCE_HELP_STR
14029 BGP_AFI_HELP_STR
14030 "SAFI Flowspec\n"
14031 "Detailed information on flowspec entries\n"
14032 JSON_STR)
14033{
14034 afi_t afi = AFI_IP;
14035 safi_t safi = SAFI_UNICAST;
14036 struct bgp *bgp = NULL;
14037 int idx = 0;
9f049418 14038 bool uj = use_json(argc, argv);
96c81f66 14039 uint16_t show_flags = 0;
9f049418 14040
96f3485c 14041 if (uj) {
9f049418 14042 argc--;
96f3485c
MK
14043 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14044 }
dba3c1d3
PG
14045
14046 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14047 &bgp, uj);
dba3c1d3
PG
14048 if (!idx)
14049 return CMD_WARNING;
14050
96f3485c 14051 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14052 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14053}
14054
718e3744 14055DEFUN (show_ip_bgp_neighbor_routes,
14056 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14057 "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 14058 SHOW_STR
14059 IP_STR
14060 BGP_STR
8386ac43 14061 BGP_INSTANCE_HELP_STR
4f280b15 14062 BGP_AFI_HELP_STR
4dd6177e 14063 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14064 "Detailed information on TCP and BGP neighbor connections\n"
14065 "Neighbor to display information about\n"
14066 "Neighbor to display information about\n"
91d37724 14067 "Neighbor on BGP configured interface\n"
2525cf39 14068 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14069 "Display the dampened routes received from neighbor\n"
14070 "Display routes learned from neighbor\n"
9973d184 14071 JSON_STR)
718e3744 14072{
d62a17ae 14073 char *peerstr = NULL;
14074 struct bgp *bgp = NULL;
14075 afi_t afi = AFI_IP6;
14076 safi_t safi = SAFI_UNICAST;
14077 struct peer *peer;
14078 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14079 int idx = 0;
9f049418
DS
14080 bool uj = use_json(argc, argv);
14081
14082 if (uj)
14083 argc--;
bb46e94f 14084
d62a17ae 14085 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14086 &bgp, uj);
d62a17ae 14087 if (!idx)
14088 return CMD_WARNING;
c493f2d8 14089
d62a17ae 14090 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14091 argv_find(argv, argc, "neighbors", &idx);
14092 peerstr = argv[++idx]->arg;
8c3deaae 14093
d62a17ae 14094 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14095 if (!peer)
d62a17ae 14096 return CMD_WARNING;
bb46e94f 14097
d62a17ae 14098 if (argv_find(argv, argc, "flap-statistics", &idx))
14099 sh_type = bgp_show_type_flap_neighbor;
14100 else if (argv_find(argv, argc, "dampened-routes", &idx))
14101 sh_type = bgp_show_type_damp_neighbor;
14102 else if (argv_find(argv, argc, "routes", &idx))
14103 sh_type = bgp_show_type_neighbor;
2525cf39 14104
d62a17ae 14105 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14106}
6b0655a2 14107
734b349e 14108struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14109
d62a17ae 14110struct bgp_distance {
14111 /* Distance value for the IP source prefix. */
d7c0a89a 14112 uint8_t distance;
718e3744 14113
d62a17ae 14114 /* Name of the access-list to be matched. */
14115 char *access_list;
718e3744 14116};
14117
4f280b15
LB
14118DEFUN (show_bgp_afi_vpn_rd_route,
14119 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14120 "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
14121 SHOW_STR
14122 BGP_STR
14123 BGP_AFI_HELP_STR
14124 "Address Family modifier\n"
14125 "Display information for a route distinguisher\n"
14126 "Route Distinguisher\n"
a111dd97 14127 "All Route Distinguishers\n"
7395a2c9
DS
14128 "Network in the BGP routing table to display\n"
14129 "Network in the BGP routing table to display\n"
14130 JSON_STR)
4f280b15 14131{
d62a17ae 14132 int ret;
14133 struct prefix_rd prd;
14134 afi_t afi = AFI_MAX;
14135 int idx = 0;
4f280b15 14136
ff6566f3
DS
14137 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14138 vty_out(vty, "%% Malformed Address Family\n");
14139 return CMD_WARNING;
14140 }
14141
a111dd97
TA
14142 if (!strcmp(argv[5]->arg, "all"))
14143 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14144 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14145 RPKI_NOT_BEING_USED,
14146 use_json(argc, argv));
14147
d62a17ae 14148 ret = str2prefix_rd(argv[5]->arg, &prd);
14149 if (!ret) {
14150 vty_out(vty, "%% Malformed Route Distinguisher\n");
14151 return CMD_WARNING;
14152 }
ff6566f3 14153
d62a17ae 14154 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14155 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14156 use_json(argc, argv));
4f280b15
LB
14157}
14158
d62a17ae 14159static struct bgp_distance *bgp_distance_new(void)
718e3744 14160{
d62a17ae 14161 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14162}
14163
d62a17ae 14164static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14165{
d62a17ae 14166 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14167}
14168
585f1adc
IR
14169static int bgp_distance_set(struct vty *vty, const char *distance_str,
14170 const char *ip_str, const char *access_list_str)
718e3744 14171{
d62a17ae 14172 int ret;
585f1adc
IR
14173 afi_t afi;
14174 safi_t safi;
d62a17ae 14175 struct prefix p;
585f1adc 14176 uint8_t distance;
9bcb3eef 14177 struct bgp_dest *dest;
d62a17ae 14178 struct bgp_distance *bdistance;
718e3744 14179
585f1adc
IR
14180 afi = bgp_node_afi(vty);
14181 safi = bgp_node_safi(vty);
14182
d62a17ae 14183 ret = str2prefix(ip_str, &p);
14184 if (ret == 0) {
585f1adc 14185 vty_out(vty, "Malformed prefix\n");
d62a17ae 14186 return CMD_WARNING_CONFIG_FAILED;
14187 }
718e3744 14188
585f1adc
IR
14189 distance = atoi(distance_str);
14190
d62a17ae 14191 /* Get BGP distance node. */
9bcb3eef
DS
14192 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14193 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14194 if (bdistance)
9bcb3eef 14195 bgp_dest_unlock_node(dest);
ca2e160d 14196 else {
d62a17ae 14197 bdistance = bgp_distance_new();
9bcb3eef 14198 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14199 }
718e3744 14200
d62a17ae 14201 /* Set distance value. */
14202 bdistance->distance = distance;
718e3744 14203
d62a17ae 14204 /* Reset access-list configuration. */
e1b36e13 14205 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14206 if (access_list_str)
14207 bdistance->access_list =
14208 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14209
d62a17ae 14210 return CMD_SUCCESS;
718e3744 14211}
14212
585f1adc
IR
14213static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14214 const char *ip_str, const char *access_list_str)
718e3744 14215{
d62a17ae 14216 int ret;
585f1adc
IR
14217 afi_t afi;
14218 safi_t safi;
d62a17ae 14219 struct prefix p;
585f1adc 14220 int distance;
9bcb3eef 14221 struct bgp_dest *dest;
d62a17ae 14222 struct bgp_distance *bdistance;
718e3744 14223
585f1adc
IR
14224 afi = bgp_node_afi(vty);
14225 safi = bgp_node_safi(vty);
14226
d62a17ae 14227 ret = str2prefix(ip_str, &p);
14228 if (ret == 0) {
585f1adc 14229 vty_out(vty, "Malformed prefix\n");
d62a17ae 14230 return CMD_WARNING_CONFIG_FAILED;
14231 }
718e3744 14232
9bcb3eef
DS
14233 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14234 if (!dest) {
585f1adc 14235 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14236 return CMD_WARNING_CONFIG_FAILED;
14237 }
718e3744 14238
9bcb3eef 14239 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14240 distance = atoi(distance_str);
1f9a9fff 14241
d62a17ae 14242 if (bdistance->distance != distance) {
585f1adc 14243 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14244 bgp_dest_unlock_node(dest);
d62a17ae 14245 return CMD_WARNING_CONFIG_FAILED;
14246 }
718e3744 14247
0a22ddfb 14248 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14249 bgp_distance_free(bdistance);
718e3744 14250
9bcb3eef
DS
14251 bgp_dest_set_bgp_path_info(dest, NULL);
14252 bgp_dest_unlock_node(dest);
14253 bgp_dest_unlock_node(dest);
718e3744 14254
d62a17ae 14255 return CMD_SUCCESS;
718e3744 14256}
14257
718e3744 14258/* Apply BGP information to distance method. */
b8685f9b 14259uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14260 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14261{
9bcb3eef 14262 struct bgp_dest *dest;
801bb996 14263 struct prefix q = {0};
d62a17ae 14264 struct peer *peer;
14265 struct bgp_distance *bdistance;
14266 struct access_list *alist;
14267 struct bgp_static *bgp_static;
14268
14269 if (!bgp)
14270 return 0;
14271
40381db7 14272 peer = pinfo->peer;
d62a17ae 14273
7b7d48e5
DS
14274 if (pinfo->attr->distance)
14275 return pinfo->attr->distance;
14276
801bb996
CS
14277 /* Check source address.
14278 * Note: for aggregate route, peer can have unspec af type.
14279 */
14280 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14281 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14282 return 0;
14283
9bcb3eef
DS
14284 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14285 if (dest) {
14286 bdistance = bgp_dest_get_bgp_distance_info(dest);
14287 bgp_dest_unlock_node(dest);
d62a17ae 14288
14289 if (bdistance->access_list) {
14290 alist = access_list_lookup(afi, bdistance->access_list);
14291 if (alist
14292 && access_list_apply(alist, p) == FILTER_PERMIT)
14293 return bdistance->distance;
14294 } else
14295 return bdistance->distance;
718e3744 14296 }
718e3744 14297
d62a17ae 14298 /* Backdoor check. */
9bcb3eef
DS
14299 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14300 if (dest) {
14301 bgp_static = bgp_dest_get_bgp_static_info(dest);
14302 bgp_dest_unlock_node(dest);
718e3744 14303
d62a17ae 14304 if (bgp_static->backdoor) {
14305 if (bgp->distance_local[afi][safi])
14306 return bgp->distance_local[afi][safi];
14307 else
14308 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14309 }
718e3744 14310 }
718e3744 14311
d62a17ae 14312 if (peer->sort == BGP_PEER_EBGP) {
14313 if (bgp->distance_ebgp[afi][safi])
14314 return bgp->distance_ebgp[afi][safi];
14315 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14316 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14317 if (bgp->distance_ibgp[afi][safi])
14318 return bgp->distance_ibgp[afi][safi];
14319 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14320 } else {
14321 if (bgp->distance_local[afi][safi])
14322 return bgp->distance_local[afi][safi];
14323 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14324 }
718e3744 14325}
14326
a612fb77
DA
14327/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14328 * we should tell ZEBRA update the routes for a specific
14329 * AFI/SAFI to reflect changes in RIB.
14330 */
585f1adc
IR
14331static void bgp_announce_routes_distance_update(struct bgp *bgp,
14332 afi_t update_afi,
14333 safi_t update_safi)
a612fb77
DA
14334{
14335 afi_t afi;
14336 safi_t safi;
14337
14338 FOREACH_AFI_SAFI (afi, safi) {
14339 if (!bgp_fibupd_safi(safi))
14340 continue;
14341
8b54bc30
DA
14342 if (afi != update_afi && safi != update_safi)
14343 continue;
14344
14345 if (BGP_DEBUG(zebra, ZEBRA))
14346 zlog_debug(
14347 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14348 __func__, afi, safi);
14349 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14350 }
14351}
14352
585f1adc
IR
14353DEFUN (bgp_distance,
14354 bgp_distance_cmd,
14355 "distance bgp (1-255) (1-255) (1-255)",
14356 "Define an administrative distance\n"
14357 "BGP distance\n"
14358 "Distance for routes external to the AS\n"
14359 "Distance for routes internal to the AS\n"
14360 "Distance for local routes\n")
718e3744 14361{
585f1adc 14362 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14363 int idx_number = 2;
14364 int idx_number_2 = 3;
14365 int idx_number_3 = 4;
585f1adc
IR
14366 int distance_ebgp = atoi(argv[idx_number]->arg);
14367 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14368 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14369 afi_t afi;
14370 safi_t safi;
718e3744 14371
d62a17ae 14372 afi = bgp_node_afi(vty);
14373 safi = bgp_node_safi(vty);
718e3744 14374
585f1adc
IR
14375 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14376 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14377 || bgp->distance_local[afi][safi] != distance_local) {
14378 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14379 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14380 bgp->distance_local[afi][safi] = distance_local;
14381 bgp_announce_routes_distance_update(bgp, afi, safi);
14382 }
14383 return CMD_SUCCESS;
14384}
37a87b8f 14385
585f1adc
IR
14386DEFUN (no_bgp_distance,
14387 no_bgp_distance_cmd,
14388 "no distance bgp [(1-255) (1-255) (1-255)]",
14389 NO_STR
14390 "Define an administrative distance\n"
14391 "BGP distance\n"
14392 "Distance for routes external to the AS\n"
14393 "Distance for routes internal to the AS\n"
14394 "Distance for local routes\n")
718e3744 14395{
585f1adc 14396 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14397 afi_t afi;
14398 safi_t safi;
37a87b8f
CS
14399
14400 afi = bgp_node_afi(vty);
14401 safi = bgp_node_safi(vty);
14402
585f1adc
IR
14403 if (bgp->distance_ebgp[afi][safi] != 0
14404 || bgp->distance_ibgp[afi][safi] != 0
14405 || bgp->distance_local[afi][safi] != 0) {
14406 bgp->distance_ebgp[afi][safi] = 0;
14407 bgp->distance_ibgp[afi][safi] = 0;
14408 bgp->distance_local[afi][safi] = 0;
14409 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14410 }
585f1adc
IR
14411 return CMD_SUCCESS;
14412}
37a87b8f 14413
37a87b8f 14414
585f1adc
IR
14415DEFUN (bgp_distance_source,
14416 bgp_distance_source_cmd,
14417 "distance (1-255) A.B.C.D/M",
14418 "Define an administrative distance\n"
14419 "Administrative distance\n"
14420 "IP source prefix\n")
14421{
14422 int idx_number = 1;
14423 int idx_ipv4_prefixlen = 2;
14424 bgp_distance_set(vty, argv[idx_number]->arg,
14425 argv[idx_ipv4_prefixlen]->arg, NULL);
14426 return CMD_SUCCESS;
734b349e
MZ
14427}
14428
585f1adc
IR
14429DEFUN (no_bgp_distance_source,
14430 no_bgp_distance_source_cmd,
14431 "no distance (1-255) A.B.C.D/M",
14432 NO_STR
14433 "Define an administrative distance\n"
14434 "Administrative distance\n"
14435 "IP source prefix\n")
37a87b8f 14436{
585f1adc
IR
14437 int idx_number = 2;
14438 int idx_ipv4_prefixlen = 3;
14439 bgp_distance_unset(vty, argv[idx_number]->arg,
14440 argv[idx_ipv4_prefixlen]->arg, NULL);
14441 return CMD_SUCCESS;
37a87b8f
CS
14442}
14443
585f1adc
IR
14444DEFUN (bgp_distance_source_access_list,
14445 bgp_distance_source_access_list_cmd,
14446 "distance (1-255) A.B.C.D/M WORD",
14447 "Define an administrative distance\n"
14448 "Administrative distance\n"
14449 "IP source prefix\n"
14450 "Access list name\n")
37a87b8f 14451{
585f1adc
IR
14452 int idx_number = 1;
14453 int idx_ipv4_prefixlen = 2;
14454 int idx_word = 3;
14455 bgp_distance_set(vty, argv[idx_number]->arg,
14456 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14457 return CMD_SUCCESS;
14458}
718e3744 14459
585f1adc
IR
14460DEFUN (no_bgp_distance_source_access_list,
14461 no_bgp_distance_source_access_list_cmd,
14462 "no distance (1-255) A.B.C.D/M WORD",
14463 NO_STR
14464 "Define an administrative distance\n"
14465 "Administrative distance\n"
14466 "IP source prefix\n"
14467 "Access list name\n")
14468{
14469 int idx_number = 2;
14470 int idx_ipv4_prefixlen = 3;
14471 int idx_word = 4;
14472 bgp_distance_unset(vty, argv[idx_number]->arg,
14473 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14474 return CMD_SUCCESS;
14475}
37a87b8f 14476
585f1adc
IR
14477DEFUN (ipv6_bgp_distance_source,
14478 ipv6_bgp_distance_source_cmd,
14479 "distance (1-255) X:X::X:X/M",
14480 "Define an administrative distance\n"
14481 "Administrative distance\n"
14482 "IP source prefix\n")
14483{
14484 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14485 return CMD_SUCCESS;
14486}
7ebe9748 14487
585f1adc
IR
14488DEFUN (no_ipv6_bgp_distance_source,
14489 no_ipv6_bgp_distance_source_cmd,
14490 "no distance (1-255) X:X::X:X/M",
14491 NO_STR
14492 "Define an administrative distance\n"
14493 "Administrative distance\n"
14494 "IP source prefix\n")
14495{
14496 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14497 return CMD_SUCCESS;
14498}
37a87b8f 14499
585f1adc
IR
14500DEFUN (ipv6_bgp_distance_source_access_list,
14501 ipv6_bgp_distance_source_access_list_cmd,
14502 "distance (1-255) X:X::X:X/M WORD",
14503 "Define an administrative distance\n"
14504 "Administrative distance\n"
14505 "IP source prefix\n"
14506 "Access list name\n")
14507{
14508 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14509 return CMD_SUCCESS;
718e3744 14510}
14511
585f1adc
IR
14512DEFUN (no_ipv6_bgp_distance_source_access_list,
14513 no_ipv6_bgp_distance_source_access_list_cmd,
14514 "no distance (1-255) X:X::X:X/M WORD",
14515 NO_STR
14516 "Define an administrative distance\n"
14517 "Administrative distance\n"
14518 "IP source prefix\n"
14519 "Access list name\n")
718e3744 14520{
585f1adc
IR
14521 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14522 return CMD_SUCCESS;
14523}
37a87b8f 14524
585f1adc
IR
14525DEFUN (bgp_damp_set,
14526 bgp_damp_set_cmd,
14527 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14528 "BGP Specific commands\n"
14529 "Enable route-flap dampening\n"
14530 "Half-life time for the penalty\n"
14531 "Value to start reusing a route\n"
14532 "Value to start suppressing a route\n"
14533 "Maximum duration to suppress a stable route\n")
14534{
14535 VTY_DECLVAR_CONTEXT(bgp, bgp);
14536 int idx_half_life = 2;
14537 int idx_reuse = 3;
14538 int idx_suppress = 4;
14539 int idx_max_suppress = 5;
37a87b8f
CS
14540 int half = DEFAULT_HALF_LIFE * 60;
14541 int reuse = DEFAULT_REUSE;
14542 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14543 int max = 4 * half;
14544
14545 if (argc == 6) {
14546 half = atoi(argv[idx_half_life]->arg) * 60;
14547 reuse = atoi(argv[idx_reuse]->arg);
14548 suppress = atoi(argv[idx_suppress]->arg);
14549 max = atoi(argv[idx_max_suppress]->arg) * 60;
14550 } else if (argc == 3) {
14551 half = atoi(argv[idx_half_life]->arg) * 60;
14552 max = 4 * half;
14553 }
14554
14555 /*
14556 * These can't be 0 but our SA doesn't understand the
14557 * way our cli is constructed
14558 */
14559 assert(reuse);
14560 assert(half);
14561 if (suppress < reuse) {
14562 vty_out(vty,
14563 "Suppress value cannot be less than reuse value \n");
14564 return 0;
14565 }
14566
14567 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14568 reuse, suppress, max);
14569}
14570
14571DEFUN (bgp_damp_unset,
14572 bgp_damp_unset_cmd,
14573 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14574 NO_STR
14575 "BGP Specific commands\n"
14576 "Enable route-flap dampening\n"
14577 "Half-life time for the penalty\n"
14578 "Value to start reusing a route\n"
14579 "Value to start suppressing a route\n"
14580 "Maximum duration to suppress a stable route\n")
14581{
14582 VTY_DECLVAR_CONTEXT(bgp, bgp);
14583 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14584}
14585
718e3744 14586/* Display specified route of BGP table. */
d62a17ae 14587static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14588 const char *ip_str, afi_t afi, safi_t safi,
14589 struct prefix_rd *prd, int prefix_check)
14590{
14591 int ret;
14592 struct prefix match;
9bcb3eef
DS
14593 struct bgp_dest *dest;
14594 struct bgp_dest *rm;
40381db7
DS
14595 struct bgp_path_info *pi;
14596 struct bgp_path_info *pi_temp;
d62a17ae 14597 struct bgp *bgp;
14598 struct bgp_table *table;
14599
14600 /* BGP structure lookup. */
14601 if (view_name) {
14602 bgp = bgp_lookup_by_name(view_name);
14603 if (bgp == NULL) {
14604 vty_out(vty, "%% Can't find BGP instance %s\n",
14605 view_name);
14606 return CMD_WARNING;
14607 }
14608 } else {
14609 bgp = bgp_get_default();
14610 if (bgp == NULL) {
14611 vty_out(vty, "%% No BGP process is configured\n");
14612 return CMD_WARNING;
14613 }
718e3744 14614 }
718e3744 14615
d62a17ae 14616 /* Check IP address argument. */
14617 ret = str2prefix(ip_str, &match);
14618 if (!ret) {
14619 vty_out(vty, "%% address is malformed\n");
14620 return CMD_WARNING;
14621 }
718e3744 14622
d62a17ae 14623 match.family = afi2family(afi);
14624
14625 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14626 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14627 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14628 dest = bgp_route_next(dest)) {
14629 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14630
9bcb3eef 14631 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14632 continue;
9bcb3eef 14633 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14634 if (!table)
ea47320b 14635 continue;
4953391b
DA
14636 rm = bgp_node_match(table, &match);
14637 if (rm == NULL)
ea47320b 14638 continue;
d62a17ae 14639
9bcb3eef 14640 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14641
ea47320b 14642 if (!prefix_check
b54892e0 14643 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14644 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14645 while (pi) {
14646 if (pi->extra && pi->extra->damp_info) {
14647 pi_temp = pi->next;
ea47320b 14648 bgp_damp_info_free(
19971c9a 14649 pi->extra->damp_info,
5c8846f6 14650 1, afi, safi);
40381db7 14651 pi = pi_temp;
ea47320b 14652 } else
40381db7 14653 pi = pi->next;
d62a17ae 14654 }
ea47320b
DL
14655 }
14656
9bcb3eef 14657 bgp_dest_unlock_node(rm);
d62a17ae 14658 }
14659 } else {
4953391b
DA
14660 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14661 if (dest != NULL) {
9bcb3eef 14662 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14663
d62a17ae 14664 if (!prefix_check
9bcb3eef
DS
14665 || dest_p->prefixlen == match.prefixlen) {
14666 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14667 while (pi) {
14668 if (pi->extra && pi->extra->damp_info) {
14669 pi_temp = pi->next;
d62a17ae 14670 bgp_damp_info_free(
19971c9a 14671 pi->extra->damp_info,
5c8846f6 14672 1, afi, safi);
40381db7 14673 pi = pi_temp;
d62a17ae 14674 } else
40381db7 14675 pi = pi->next;
d62a17ae 14676 }
14677 }
14678
9bcb3eef 14679 bgp_dest_unlock_node(dest);
d62a17ae 14680 }
14681 }
718e3744 14682
d62a17ae 14683 return CMD_SUCCESS;
718e3744 14684}
14685
14686DEFUN (clear_ip_bgp_dampening,
14687 clear_ip_bgp_dampening_cmd,
14688 "clear ip bgp dampening",
14689 CLEAR_STR
14690 IP_STR
14691 BGP_STR
14692 "Clear route flap dampening information\n")
14693{
b4f7f45b 14694 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14695 return CMD_SUCCESS;
718e3744 14696}
14697
14698DEFUN (clear_ip_bgp_dampening_prefix,
14699 clear_ip_bgp_dampening_prefix_cmd,
14700 "clear ip bgp dampening A.B.C.D/M",
14701 CLEAR_STR
14702 IP_STR
14703 BGP_STR
14704 "Clear route flap dampening information\n"
0c7b1b01 14705 "IPv4 prefix\n")
718e3744 14706{
d62a17ae 14707 int idx_ipv4_prefixlen = 4;
14708 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14709 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14710}
14711
14712DEFUN (clear_ip_bgp_dampening_address,
14713 clear_ip_bgp_dampening_address_cmd,
14714 "clear ip bgp dampening A.B.C.D",
14715 CLEAR_STR
14716 IP_STR
14717 BGP_STR
14718 "Clear route flap dampening information\n"
14719 "Network to clear damping information\n")
14720{
d62a17ae 14721 int idx_ipv4 = 4;
14722 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14723 SAFI_UNICAST, NULL, 0);
718e3744 14724}
14725
14726DEFUN (clear_ip_bgp_dampening_address_mask,
14727 clear_ip_bgp_dampening_address_mask_cmd,
14728 "clear ip bgp dampening A.B.C.D A.B.C.D",
14729 CLEAR_STR
14730 IP_STR
14731 BGP_STR
14732 "Clear route flap dampening information\n"
14733 "Network to clear damping information\n"
14734 "Network mask\n")
14735{
d62a17ae 14736 int idx_ipv4 = 4;
14737 int idx_ipv4_2 = 5;
14738 int ret;
14739 char prefix_str[BUFSIZ];
718e3744 14740
d62a17ae 14741 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14742 prefix_str, sizeof(prefix_str));
d62a17ae 14743 if (!ret) {
14744 vty_out(vty, "%% Inconsistent address and mask\n");
14745 return CMD_WARNING;
14746 }
718e3744 14747
d62a17ae 14748 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14749 NULL, 0);
718e3744 14750}
6b0655a2 14751
e3b78da8 14752static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14753{
14754 struct vty *vty = arg;
e3b78da8 14755 struct peer *peer = bucket->data;
825d9834
DS
14756 char buf[SU_ADDRSTRLEN];
14757
14758 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14759 sockunion2str(&peer->su, buf, sizeof(buf)));
14760}
14761
2a0e69ae
DS
14762DEFUN (show_bgp_listeners,
14763 show_bgp_listeners_cmd,
14764 "show bgp listeners",
14765 SHOW_STR
14766 BGP_STR
14767 "Display Listen Sockets and who created them\n")
14768{
14769 bgp_dump_listener_info(vty);
14770
14771 return CMD_SUCCESS;
14772}
14773
825d9834
DS
14774DEFUN (show_bgp_peerhash,
14775 show_bgp_peerhash_cmd,
14776 "show bgp peerhash",
14777 SHOW_STR
14778 BGP_STR
14779 "Display information about the BGP peerhash\n")
14780{
14781 struct list *instances = bm->bgp;
14782 struct listnode *node;
14783 struct bgp *bgp;
14784
14785 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14786 vty_out(vty, "BGP: %s\n", bgp->name);
14787 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14788 vty);
14789 }
14790
14791 return CMD_SUCCESS;
14792}
14793
587ff0fd 14794/* also used for encap safi */
2b791107
DL
14795static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14796 afi_t afi, safi_t safi)
d62a17ae 14797{
9bcb3eef
DS
14798 struct bgp_dest *pdest;
14799 struct bgp_dest *dest;
d62a17ae 14800 struct bgp_table *table;
b54892e0
DS
14801 const struct prefix *p;
14802 const struct prefix_rd *prd;
d62a17ae 14803 struct bgp_static *bgp_static;
14804 mpls_label_t label;
d62a17ae 14805 char rdbuf[RD_ADDRSTRLEN];
14806
14807 /* Network configuration. */
9bcb3eef
DS
14808 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14809 pdest = bgp_route_next(pdest)) {
14810 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14811 if (!table)
ea47320b 14812 continue;
d62a17ae 14813
9bcb3eef
DS
14814 for (dest = bgp_table_top(table); dest;
14815 dest = bgp_route_next(dest)) {
14816 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14817 if (bgp_static == NULL)
ea47320b 14818 continue;
d62a17ae 14819
9bcb3eef
DS
14820 p = bgp_dest_get_prefix(dest);
14821 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14822 pdest);
d62a17ae 14823
ea47320b 14824 /* "network" configuration display. */
06b9f471 14825 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14826 label = decode_label(&bgp_static->label);
14827
8228a9a7 14828 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14829 if (safi == SAFI_MPLS_VPN)
14830 vty_out(vty, " label %u", label);
14831
14832 if (bgp_static->rmap.name)
14833 vty_out(vty, " route-map %s",
14834 bgp_static->rmap.name);
e2a86ad9
DS
14835
14836 if (bgp_static->backdoor)
14837 vty_out(vty, " backdoor");
14838
ea47320b
DL
14839 vty_out(vty, "\n");
14840 }
14841 }
d62a17ae 14842}
14843
2b791107
DL
14844static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14845 afi_t afi, safi_t safi)
d62a17ae 14846{
9bcb3eef
DS
14847 struct bgp_dest *pdest;
14848 struct bgp_dest *dest;
d62a17ae 14849 struct bgp_table *table;
b54892e0
DS
14850 const struct prefix *p;
14851 const struct prefix_rd *prd;
d62a17ae 14852 struct bgp_static *bgp_static;
ff44f570 14853 char buf[PREFIX_STRLEN * 2];
d62a17ae 14854 char buf2[SU_ADDRSTRLEN];
14855 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14856 char esi_buf[ESI_BYTES];
d62a17ae 14857
14858 /* Network configuration. */
9bcb3eef
DS
14859 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14860 pdest = bgp_route_next(pdest)) {
14861 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14862 if (!table)
ea47320b 14863 continue;
d62a17ae 14864
9bcb3eef
DS
14865 for (dest = bgp_table_top(table); dest;
14866 dest = bgp_route_next(dest)) {
14867 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14868 if (bgp_static == NULL)
ea47320b 14869 continue;
d62a17ae 14870
ea47320b 14871 char *macrouter = NULL;
d62a17ae 14872
ea47320b
DL
14873 if (bgp_static->router_mac)
14874 macrouter = prefix_mac2str(
14875 bgp_static->router_mac, NULL, 0);
14876 if (bgp_static->eth_s_id)
0a50c248
AK
14877 esi_to_str(bgp_static->eth_s_id,
14878 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14879 p = bgp_dest_get_prefix(dest);
14880 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14881
ea47320b 14882 /* "network" configuration display. */
06b9f471 14883 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14884 if (p->u.prefix_evpn.route_type == 5) {
14885 char local_buf[PREFIX_STRLEN];
3714a385 14886 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14887 struct prefix_evpn *)p)
14888 ? AF_INET
14889 : AF_INET6;
3714a385 14890 inet_ntop(family,
14891 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14892 local_buf, PREFIX_STRLEN);
772270f3
QY
14893 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14894 p->u.prefix_evpn.prefix_addr
14895 .ip_prefix_length);
197cb530
PG
14896 } else {
14897 prefix2str(p, buf, sizeof(buf));
14898 }
ea47320b 14899
a4d82a8a
PZ
14900 if (bgp_static->gatewayIp.family == AF_INET
14901 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14902 inet_ntop(bgp_static->gatewayIp.family,
14903 &bgp_static->gatewayIp.u.prefix, buf2,
14904 sizeof(buf2));
ea47320b 14905 vty_out(vty,
7bcc8dac 14906 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14907 buf, rdbuf,
14908 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14909 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14910 macrouter);
14911
0a22ddfb 14912 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14913 }
14914 }
3da6fcd5
PG
14915}
14916
718e3744 14917/* Configuration of static route announcement and aggregate
14918 information. */
2b791107
DL
14919void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14920 safi_t safi)
d62a17ae 14921{
9bcb3eef 14922 struct bgp_dest *dest;
b54892e0 14923 const struct prefix *p;
d62a17ae 14924 struct bgp_static *bgp_static;
14925 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14926
2b791107
DL
14927 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14928 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14929 return;
14930 }
d62a17ae 14931
2b791107
DL
14932 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14933 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14934 return;
14935 }
d62a17ae 14936
14937 /* Network configuration. */
9bcb3eef
DS
14938 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14939 dest = bgp_route_next(dest)) {
14940 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14941 if (bgp_static == NULL)
ea47320b 14942 continue;
d62a17ae 14943
9bcb3eef 14944 p = bgp_dest_get_prefix(dest);
d62a17ae 14945
8228a9a7 14946 vty_out(vty, " network %pFX", p);
d62a17ae 14947
ea47320b
DL
14948 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14949 vty_out(vty, " label-index %u",
14950 bgp_static->label_index);
d62a17ae 14951
ea47320b
DL
14952 if (bgp_static->rmap.name)
14953 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14954
14955 if (bgp_static->backdoor)
14956 vty_out(vty, " backdoor");
718e3744 14957
ea47320b
DL
14958 vty_out(vty, "\n");
14959 }
14960
d62a17ae 14961 /* Aggregate-address configuration. */
9bcb3eef
DS
14962 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14963 dest = bgp_route_next(dest)) {
14964 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14965 if (bgp_aggregate == NULL)
ea47320b 14966 continue;
d62a17ae 14967
9bcb3eef 14968 p = bgp_dest_get_prefix(dest);
d62a17ae 14969
8228a9a7 14970 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14971
ea47320b
DL
14972 if (bgp_aggregate->as_set)
14973 vty_out(vty, " as-set");
d62a17ae 14974
ea47320b
DL
14975 if (bgp_aggregate->summary_only)
14976 vty_out(vty, " summary-only");
718e3744 14977
20894f50
DA
14978 if (bgp_aggregate->rmap.name)
14979 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14980
229757f1
DA
14981 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14982 vty_out(vty, " origin %s",
14983 bgp_origin2str(bgp_aggregate->origin));
14984
6aabb15d
RZ
14985 if (bgp_aggregate->match_med)
14986 vty_out(vty, " matching-MED-only");
14987
365ab2e7
RZ
14988 if (bgp_aggregate->suppress_map_name)
14989 vty_out(vty, " suppress-map %s",
14990 bgp_aggregate->suppress_map_name);
14991
ea47320b
DL
14992 vty_out(vty, "\n");
14993 }
d62a17ae 14994}
734b349e 14995
2b791107 14996void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14997 safi_t safi)
d62a17ae 14998{
9bcb3eef 14999 struct bgp_dest *dest;
d62a17ae 15000 struct bgp_distance *bdistance;
15001
15002 /* Distance configuration. */
15003 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15004 && bgp->distance_local[afi][safi]
15005 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15006 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15007 || bgp->distance_local[afi][safi]
15008 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15009 vty_out(vty, " distance bgp %d %d %d\n",
15010 bgp->distance_ebgp[afi][safi],
15011 bgp->distance_ibgp[afi][safi],
15012 bgp->distance_local[afi][safi]);
15013 }
734b349e 15014
9bcb3eef
DS
15015 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15016 dest = bgp_route_next(dest)) {
15017 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15018 if (bdistance != NULL)
56ca3b5b 15019 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15020 bdistance->distance, dest,
d62a17ae 15021 bdistance->access_list ? bdistance->access_list
15022 : "");
ca2e160d 15023 }
718e3744 15024}
15025
15026/* Allocate routing table structure and install commands. */
d62a17ae 15027void bgp_route_init(void)
15028{
15029 afi_t afi;
15030 safi_t safi;
15031
15032 /* Init BGP distance table. */
05c7a1cc 15033 FOREACH_AFI_SAFI (afi, safi)
960035b2 15034 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15035
15036 /* IPv4 BGP commands. */
15037 install_element(BGP_NODE, &bgp_table_map_cmd);
15038 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15039 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15040
554b3b10 15041 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15042
15043 /* IPv4 unicast configuration. */
15044 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15045 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15046 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15047
554b3b10 15048 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15049
15050 /* IPv4 multicast configuration. */
15051 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15052 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15053 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15054 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15055
15056 /* IPv4 labeled-unicast configuration. */
fb985e0c 15057 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15058 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15059
d62a17ae 15060 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15061 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 15062 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15063 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 15064 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 15065 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15066 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15067 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15068
15069 install_element(VIEW_NODE,
15070 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15071 install_element(VIEW_NODE,
15072 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15073 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15074 install_element(VIEW_NODE,
15075 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15076#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15077 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15078#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15079 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15080 install_element(VIEW_NODE,
44c69747 15081 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15082
d62a17ae 15083 /* BGP dampening clear commands */
15084 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15085 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15086
d62a17ae 15087 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15088 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15089
15090 /* prefix count */
15091 install_element(ENABLE_NODE,
15092 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15093#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15094 install_element(ENABLE_NODE,
15095 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15096#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15097
d62a17ae 15098 /* New config IPv6 BGP commands. */
15099 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15100 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15101 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15102
554b3b10 15103 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15104
15105 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15106
fb985e0c
DA
15107 /* IPv6 labeled unicast address family. */
15108 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15109 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15110
d62a17ae 15111 install_element(BGP_NODE, &bgp_distance_cmd);
15112 install_element(BGP_NODE, &no_bgp_distance_cmd);
15113 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15114 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15115 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15116 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15117 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15118 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15119 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15120 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15121 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15122 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15123 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15124 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15125 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15126 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15127 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15128 install_element(BGP_IPV4M_NODE,
15129 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15130 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15131 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15132 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15133 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15134 install_element(BGP_IPV6_NODE,
15135 &ipv6_bgp_distance_source_access_list_cmd);
15136 install_element(BGP_IPV6_NODE,
15137 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15138 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15139 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15140 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15141 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15142 install_element(BGP_IPV6M_NODE,
15143 &ipv6_bgp_distance_source_access_list_cmd);
15144 install_element(BGP_IPV6M_NODE,
15145 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15146
ef5f4b23 15147 /* BGP dampening */
585f1adc
IR
15148 install_element(BGP_NODE, &bgp_damp_set_cmd);
15149 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15150 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15151 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15152 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15153 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15154 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15155 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15156 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15157 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15158 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15159 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15160 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15161 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15162
15163 /* Large Communities */
15164 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15165 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15166
15167 /* show bgp ipv4 flowspec detailed */
15168 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15169
2a0e69ae 15170 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15171 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15172}
15173
15174void bgp_route_finish(void)
15175{
15176 afi_t afi;
15177 safi_t safi;
15178
05c7a1cc
QY
15179 FOREACH_AFI_SAFI (afi, safi) {
15180 bgp_table_unlock(bgp_distance_table[afi][safi]);
15181 bgp_distance_table[afi][safi] = NULL;
15182 }
228da428 15183}