]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #9675 from opensourcerouting/pim-bsm-uaf
[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(
27aa23a4
DA
2279 bgp->as, attr->ecommunity, cum_bw,
2280 CHECK_FLAG(peer->flags,
2281 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
7b651a32 2282
3dc339cd 2283 return true;
3f9c7369
DS
2284}
2285
f009ff26 2286static int bgp_route_select_timer_expire(struct thread *thread)
2287{
2288 struct afi_safi_info *info;
2289 afi_t afi;
2290 safi_t safi;
2291 struct bgp *bgp;
2292
2293 info = THREAD_ARG(thread);
2294 afi = info->afi;
2295 safi = info->safi;
2296 bgp = info->bgp;
2297
2298 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2299 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2300 safi);
f009ff26 2301
2302 bgp->gr_info[afi][safi].t_route_select = NULL;
2303
2304 XFREE(MTYPE_TMP, info);
2305
2306 /* Best path selection */
2307 return bgp_best_path_select_defer(bgp, afi, safi);
2308}
2309
9bcb3eef 2310void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2311 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2312 struct bgp_path_info_pair *result, afi_t afi,
2313 safi_t safi)
2314{
2315 struct bgp_path_info *new_select;
2316 struct bgp_path_info *old_select;
40381db7
DS
2317 struct bgp_path_info *pi;
2318 struct bgp_path_info *pi1;
2319 struct bgp_path_info *pi2;
2320 struct bgp_path_info *nextpi = NULL;
d62a17ae 2321 int paths_eq, do_mpath, debug;
2322 struct list mp_list;
2323 char pfx_buf[PREFIX2STR_BUFFER];
2324 char path_buf[PATH_ADDPATH_STR_BUFFER];
2325
2326 bgp_mp_list_init(&mp_list);
2327 do_mpath =
2328 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2329
9bcb3eef 2330 debug = bgp_debug_bestpath(dest);
d62a17ae 2331
2332 if (debug)
9bcb3eef 2333 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2334
9bcb3eef 2335 dest->reason = bgp_path_selection_none;
d62a17ae 2336 /* bgp deterministic-med */
2337 new_select = NULL;
892fedb6 2338 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2339
1defdda8 2340 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2341 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2342 pi1 = pi1->next)
9bcb3eef 2343 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2344 BGP_PATH_DMED_SELECTED);
d62a17ae 2345
9bcb3eef 2346 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2347 pi1 = pi1->next) {
40381db7 2348 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2349 continue;
40381db7 2350 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2351 continue;
ea8b2282 2352 if (pi1->peer != bgp->peer_self)
feb17238 2353 if (!peer_established(pi1->peer))
d62a17ae 2354 continue;
2355
40381db7
DS
2356 new_select = pi1;
2357 if (pi1->next) {
2358 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2359 if (CHECK_FLAG(pi2->flags,
1defdda8 2360 BGP_PATH_DMED_CHECK))
d62a17ae 2361 continue;
40381db7 2362 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2363 continue;
ea8b2282 2364 if (pi2->peer != bgp->peer_self
d62a17ae 2365 && !CHECK_FLAG(
ea8b2282
DS
2366 pi2->peer->sflags,
2367 PEER_STATUS_NSF_WAIT))
40381db7 2368 if (pi2->peer->status
d62a17ae 2369 != Established)
2370 continue;
2371
121e245d
DS
2372 if (!aspath_cmp_left(pi1->attr->aspath,
2373 pi2->attr->aspath)
2374 && !aspath_cmp_left_confed(
40381db7 2375 pi1->attr->aspath,
121e245d
DS
2376 pi2->attr->aspath))
2377 continue;
d62a17ae 2378
121e245d
DS
2379 if (bgp_path_info_cmp(
2380 bgp, pi2, new_select,
2381 &paths_eq, mpath_cfg, debug,
fdf81fa0 2382 pfx_buf, afi, safi,
9bcb3eef 2383 &dest->reason)) {
121e245d 2384 bgp_path_info_unset_flag(
9bcb3eef 2385 dest, new_select,
121e245d
DS
2386 BGP_PATH_DMED_SELECTED);
2387 new_select = pi2;
d62a17ae 2388 }
121e245d
DS
2389
2390 bgp_path_info_set_flag(
9bcb3eef 2391 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2392 }
2393 }
9bcb3eef 2394 bgp_path_info_set_flag(dest, new_select,
18ee8310 2395 BGP_PATH_DMED_CHECK);
9bcb3eef 2396 bgp_path_info_set_flag(dest, new_select,
18ee8310 2397 BGP_PATH_DMED_SELECTED);
d62a17ae 2398
2399 if (debug) {
18ee8310 2400 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2401 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2402 zlog_debug(
2403 "%pBD: %s is the bestpath from AS %u",
2404 dest, path_buf,
2405 aspath_get_first_as(
2406 new_select->attr->aspath));
d62a17ae 2407 }
2408 }
2409 }
96450faf 2410
d62a17ae 2411 /* Check old selected route and new selected route. */
2412 old_select = NULL;
2413 new_select = NULL;
9bcb3eef 2414 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2415 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2416 enum bgp_path_selection_reason reason;
2417
40381db7
DS
2418 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2419 old_select = pi;
d62a17ae 2420
40381db7 2421 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2422 /* reap REMOVED routes, if needs be
2423 * selected route must stay for a while longer though
2424 */
40381db7
DS
2425 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2426 && (pi != old_select))
9bcb3eef 2427 bgp_path_info_reap(dest, pi);
d62a17ae 2428
ddb5b488 2429 if (debug)
40381db7
DS
2430 zlog_debug("%s: pi %p in holddown", __func__,
2431 pi);
ddb5b488 2432
d62a17ae 2433 continue;
2434 }
96450faf 2435
40381db7
DS
2436 if (pi->peer && pi->peer != bgp->peer_self
2437 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2438 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2439
2440 if (debug)
2441 zlog_debug(
40381db7
DS
2442 "%s: pi %p non self peer %s not estab state",
2443 __func__, pi, pi->peer->host);
ddb5b488 2444
d62a17ae 2445 continue;
ddb5b488 2446 }
9fbdd100 2447
892fedb6 2448 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2449 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2450 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2451 if (debug)
40381db7 2452 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2453 continue;
2454 }
9fbdd100 2455
9bcb3eef 2456 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2457
9bcb3eef 2458 reason = dest->reason;
40381db7 2459 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2460 debug, pfx_buf, afi, safi,
2461 &dest->reason)) {
19ea4cec
DS
2462 if (new_select == NULL &&
2463 reason != bgp_path_selection_none)
9bcb3eef 2464 dest->reason = reason;
40381db7 2465 new_select = pi;
d62a17ae 2466 }
2467 }
718e3744 2468
d62a17ae 2469 /* Now that we know which path is the bestpath see if any of the other
2470 * paths
2471 * qualify as multipaths
2472 */
2473 if (debug) {
2474 if (new_select)
7533cad7
QY
2475 bgp_path_info_path_with_addpath_rx_str(
2476 new_select, path_buf, sizeof(path_buf));
d62a17ae 2477 else
772270f3 2478 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2479 zlog_debug(
8228a9a7
DS
2480 "%pBD: After path selection, newbest is %s oldbest was %s",
2481 dest, path_buf,
d62a17ae 2482 old_select ? old_select->peer->host : "NONE");
96450faf 2483 }
9fbdd100 2484
d62a17ae 2485 if (do_mpath && new_select) {
9bcb3eef 2486 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2487 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2488
2489 if (debug)
18ee8310 2490 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2491 pi, path_buf, sizeof(path_buf));
d62a17ae 2492
40381db7 2493 if (pi == new_select) {
d62a17ae 2494 if (debug)
2495 zlog_debug(
8228a9a7
DS
2496 "%pBD: %s is the bestpath, add to the multipath list",
2497 dest, path_buf);
40381db7 2498 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2499 continue;
2500 }
2501
40381db7 2502 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2503 continue;
2504
40381db7
DS
2505 if (pi->peer && pi->peer != bgp->peer_self
2506 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2507 PEER_STATUS_NSF_WAIT))
feb17238 2508 if (!peer_established(pi->peer))
d62a17ae 2509 continue;
2510
40381db7 2511 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2512 if (debug)
2513 zlog_debug(
8228a9a7
DS
2514 "%pBD: %s has the same nexthop as the bestpath, skip it",
2515 dest, path_buf);
d62a17ae 2516 continue;
2517 }
2518
40381db7 2519 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2520 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2521 &dest->reason);
d62a17ae 2522
2523 if (paths_eq) {
2524 if (debug)
2525 zlog_debug(
8228a9a7
DS
2526 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2527 dest, path_buf);
40381db7 2528 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2529 }
2530 }
2531 }
fee0f4c6 2532
9bcb3eef 2533 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2534 mpath_cfg);
2535 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2536 bgp_mp_list_clear(&mp_list);
96450faf 2537
9bcb3eef 2538 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2539
d62a17ae 2540 result->old = old_select;
2541 result->new = new_select;
96450faf 2542
d62a17ae 2543 return;
fee0f4c6 2544}
2545
3f9c7369
DS
2546/*
2547 * A new route/change in bestpath of an existing route. Evaluate the path
2548 * for advertisement to the subgroup.
2549 */
3dc339cd
DA
2550void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2551 struct bgp_path_info *selected,
9bcb3eef 2552 struct bgp_dest *dest,
3dc339cd 2553 uint32_t addpath_tx_id)
d62a17ae 2554{
b54892e0 2555 const struct prefix *p;
d62a17ae 2556 struct peer *onlypeer;
2557 struct attr attr;
2558 afi_t afi;
2559 safi_t safi;
a77e2f4b
S
2560 struct bgp *bgp;
2561 bool advertise;
adbac85e 2562
9bcb3eef 2563 p = bgp_dest_get_prefix(dest);
d62a17ae 2564 afi = SUBGRP_AFI(subgrp);
2565 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2566 bgp = SUBGRP_INST(subgrp);
d62a17ae 2567 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2568 : NULL);
2569
2dbe669b
DA
2570 if (BGP_DEBUG(update, UPDATE_OUT))
2571 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2572
d62a17ae 2573 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2574 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2575 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2576 return;
d62a17ae 2577
2578 memset(&attr, 0, sizeof(struct attr));
2579 /* It's initialized in bgp_announce_check() */
2580
a77e2f4b
S
2581 /* Announcement to the subgroup. If the route is filtered withdraw it.
2582 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2583 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2584 * route
d62a17ae 2585 */
a77e2f4b
S
2586 advertise = bgp_check_advertise(bgp, dest);
2587
d62a17ae 2588 if (selected) {
7f7940e6 2589 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2590 false)) {
2591 /* Route is selected, if the route is already installed
2592 * in FIB, then it is advertised
2593 */
2594 if (advertise)
2595 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2596 selected);
2597 } else
9bcb3eef 2598 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2599 addpath_tx_id);
d62a17ae 2600 }
2601
2602 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2603 else {
9bcb3eef 2604 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2605 }
200df115 2606}
fee0f4c6 2607
3064bf43 2608/*
e1072051 2609 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2610 * This is called at the end of route processing.
3064bf43 2611 */
9bcb3eef 2612void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2613{
40381db7 2614 struct bgp_path_info *pi;
3064bf43 2615
9bcb3eef 2616 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2617 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2618 continue;
40381db7
DS
2619 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2620 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2621 }
3064bf43 2622}
2623
2624/*
2625 * Has the route changed from the RIB's perspective? This is invoked only
2626 * if the route selection returns the same best route as earlier - to
2627 * determine if we need to update zebra or not.
2628 */
9bcb3eef 2629bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2630{
4b7e6066 2631 struct bgp_path_info *mpinfo;
d62a17ae 2632
2bb9eff4
DS
2633 /* If this is multipath, check all selected paths for any nexthop
2634 * change or attribute change. Some attribute changes (e.g., community)
2635 * aren't of relevance to the RIB, but we'll update zebra to ensure
2636 * we handle the case of BGP nexthop change. This is the behavior
2637 * when the best path has an attribute change anyway.
d62a17ae 2638 */
1defdda8 2639 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2640 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2641 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2642 return true;
d62a17ae 2643
2bb9eff4
DS
2644 /*
2645 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2646 */
18ee8310
DS
2647 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2648 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2649 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2650 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2651 return true;
d62a17ae 2652 }
3064bf43 2653
d62a17ae 2654 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2655 return false;
3064bf43 2656}
2657
d62a17ae 2658struct bgp_process_queue {
2659 struct bgp *bgp;
9bcb3eef 2660 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2661#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2662 unsigned int flags;
2663 unsigned int queued;
200df115 2664};
2665
3b0c17e1 2666static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2667 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2668 struct bgp_path_info *new_select,
2669 struct bgp_path_info *old_select)
2670{
9bcb3eef 2671 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2672
2673 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2674 return;
2675
2676 if (advertise_type5_routes(bgp, afi) && new_select
2677 && is_route_injectable_into_evpn(new_select)) {
2678
2679 /* apply the route-map */
2680 if (bgp->adv_cmd_rmap[afi][safi].map) {
2681 route_map_result_t ret;
2682 struct bgp_path_info rmap_path;
2683 struct bgp_path_info_extra rmap_path_extra;
2684 struct attr dummy_attr;
2685
2686 dummy_attr = *new_select->attr;
2687
2688 /* Fill temp path_info */
9bcb3eef 2689 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2690 new_select, new_select->peer,
2691 &dummy_attr);
2692
2693 RESET_FLAG(dummy_attr.rmap_change_flags);
2694
2695 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2696 p, &rmap_path);
3b0c17e1 2697
2698 if (ret == RMAP_DENYMATCH) {
2699 bgp_attr_flush(&dummy_attr);
2700 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2701 safi);
2702 } else
2703 bgp_evpn_advertise_type5_route(
2704 bgp, p, &dummy_attr, afi, safi);
2705 } else {
2706 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2707 afi, safi);
2708 }
2709 } else if (advertise_type5_routes(bgp, afi) && old_select
2710 && is_route_injectable_into_evpn(old_select))
2711 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2712}
2713
3103e8d2
DS
2714/*
2715 * old_select = The old best path
2716 * new_select = the new best path
2717 *
2718 * if (!old_select && new_select)
2719 * We are sending new information on.
2720 *
2721 * if (old_select && new_select) {
2722 * if (new_select != old_select)
2723 * We have a new best path send a change
2724 * else
2725 * We've received a update with new attributes that needs
2726 * to be passed on.
2727 * }
2728 *
2729 * if (old_select && !new_select)
2730 * We have no eligible route that we can announce or the rn
2731 * is being removed.
2732 */
9bcb3eef 2733static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2734 afi_t afi, safi_t safi)
d62a17ae 2735{
4b7e6066
DS
2736 struct bgp_path_info *new_select;
2737 struct bgp_path_info *old_select;
2738 struct bgp_path_info_pair old_and_new;
ddb5b488 2739 int debug = 0;
d62a17ae 2740
892fedb6 2741 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2742 if (dest)
2743 debug = bgp_debug_bestpath(dest);
b54892e0 2744 if (debug)
f4c713ae 2745 zlog_debug(
56ca3b5b 2746 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2747 __func__, dest);
f4c713ae
LB
2748 return;
2749 }
d62a17ae 2750 /* Is it end of initial update? (after startup) */
9bcb3eef 2751 if (!dest) {
d62a17ae 2752 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2753 sizeof(bgp->update_delay_zebra_resume_time));
2754
2755 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2756 FOREACH_AFI_SAFI (afi, safi) {
2757 if (bgp_fibupd_safi(safi))
2758 bgp_zebra_announce_table(bgp, afi, safi);
2759 }
d62a17ae 2760 bgp->main_peers_update_hold = 0;
2761
2762 bgp_start_routeadv(bgp);
aac24838 2763 return;
d62a17ae 2764 }
cb1faec9 2765
9bcb3eef 2766 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2767
9bcb3eef 2768 debug = bgp_debug_bestpath(dest);
b54892e0 2769 if (debug)
56ca3b5b 2770 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2771 afi2str(afi), safi2str(safi));
ddb5b488 2772
f009ff26 2773 /* The best path calculation for the route is deferred if
2774 * BGP_NODE_SELECT_DEFER is set
2775 */
9bcb3eef 2776 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2777 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2778 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2779 return;
2780 }
2781
d62a17ae 2782 /* Best path selection. */
9bcb3eef 2783 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2784 afi, safi);
2785 old_select = old_and_new.old;
2786 new_select = old_and_new.new;
2787
2788 /* Do we need to allocate or free labels?
2789 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2790 * necessary to do this upon changes to best path. Exceptions:
2791 * - label index has changed -> recalculate resulting label
2792 * - path_info sub_type changed -> switch to/from implicit-null
2793 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2794 */
318cac96 2795 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2796 if (new_select) {
2797 if (!old_select
2798 || bgp_label_index_differs(new_select, old_select)
57592a53 2799 || new_select->sub_type != old_select->sub_type
9bcb3eef 2800 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2801 /* Enforced penultimate hop popping:
2802 * implicit-null for local routes, aggregate
2803 * and redistributed routes
2804 */
d62a17ae 2805 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2806 || new_select->sub_type
2807 == BGP_ROUTE_AGGREGATE
2808 || new_select->sub_type
2809 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2810 if (CHECK_FLAG(
9bcb3eef 2811 dest->flags,
992dd67e
PR
2812 BGP_NODE_REGISTERED_FOR_LABEL)
2813 || CHECK_FLAG(
2814 dest->flags,
2815 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2816 bgp_unregister_for_label(dest);
70e98a7f 2817 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2818 &dest->local_label);
2819 bgp_set_valid_label(&dest->local_label);
d62a17ae 2820 } else
9bcb3eef
DS
2821 bgp_register_for_label(dest,
2822 new_select);
d62a17ae 2823 }
9bcb3eef 2824 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2825 BGP_NODE_REGISTERED_FOR_LABEL)
2826 || CHECK_FLAG(dest->flags,
2827 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2828 bgp_unregister_for_label(dest);
318cac96 2829 }
992dd67e
PR
2830 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2831 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2832 bgp_unregister_for_label(dest);
d62a17ae 2833 }
cd1964ff 2834
b54892e0 2835 if (debug)
ddb5b488 2836 zlog_debug(
56ca3b5b 2837 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2838 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2839 old_select, new_select);
ddb5b488 2840
d62a17ae 2841 /* If best route remains the same and this is not due to user-initiated
2842 * clear, see exactly what needs to be done.
2843 */
d62a17ae 2844 if (old_select && old_select == new_select
9bcb3eef 2845 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2846 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2847 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2848 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2849#ifdef ENABLE_BGP_VNC
d62a17ae 2850 vnc_import_bgp_add_route(bgp, p, old_select);
2851 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2852#endif
bb744275 2853 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2854 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2855
2856 if (new_select->type == ZEBRA_ROUTE_BGP
2857 && (new_select->sub_type == BGP_ROUTE_NORMAL
2858 || new_select->sub_type
2859 == BGP_ROUTE_IMPORTED))
2860
9bcb3eef 2861 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2862 bgp, afi, safi);
2863 }
d62a17ae 2864 }
d62a17ae 2865
2866 /* If there is a change of interest to peers, reannounce the
2867 * route. */
1defdda8 2868 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2869 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2870 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2871 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2872
2873 /* unicast routes must also be annouced to
2874 * labeled-unicast update-groups */
2875 if (safi == SAFI_UNICAST)
2876 group_announce_route(bgp, afi,
9bcb3eef 2877 SAFI_LABELED_UNICAST, dest,
d62a17ae 2878 new_select);
2879
1defdda8 2880 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2881 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2882 }
fee0f4c6 2883
3b0c17e1 2884 /* advertise/withdraw type-5 routes */
2885 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2886 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2887 bgp_process_evpn_route_injection(
9bcb3eef 2888 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2889
b1875e65 2890 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2891 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2892 bgp_zebra_clear_route_change_flags(dest);
2893 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2894 return;
d62a17ae 2895 }
8ad7271d 2896
d62a17ae 2897 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2898 */
9bcb3eef 2899 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2900
2901 /* bestpath has changed; bump version */
2902 if (old_select || new_select) {
9bcb3eef 2903 bgp_bump_version(dest);
d62a17ae 2904
2905 if (!bgp->t_rmap_def_originate_eval) {
2906 bgp_lock(bgp);
2907 thread_add_timer(
2908 bm->master,
2909 update_group_refresh_default_originate_route_map,
2910 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2911 &bgp->t_rmap_def_originate_eval);
2912 }
2913 }
3f9c7369 2914
d62a17ae 2915 if (old_select)
9bcb3eef 2916 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2917 if (new_select) {
ddb5b488
PZ
2918 if (debug)
2919 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2920 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2921 bgp_path_info_unset_flag(dest, new_select,
2922 BGP_PATH_ATTR_CHANGED);
1defdda8 2923 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2924 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2925 }
338b3424 2926
49e5a4a0 2927#ifdef ENABLE_BGP_VNC
d62a17ae 2928 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2929 if (old_select != new_select) {
2930 if (old_select) {
2931 vnc_import_bgp_exterior_del_route(bgp, p,
2932 old_select);
2933 vnc_import_bgp_del_route(bgp, p, old_select);
2934 }
2935 if (new_select) {
2936 vnc_import_bgp_exterior_add_route(bgp, p,
2937 new_select);
2938 vnc_import_bgp_add_route(bgp, p, new_select);
2939 }
2940 }
2941 }
65efcfce
LB
2942#endif
2943
9bcb3eef 2944 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2945
2946 /* unicast routes must also be annouced to labeled-unicast update-groups
2947 */
2948 if (safi == SAFI_UNICAST)
9bcb3eef 2949 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2950 new_select);
2951
2952 /* FIB update. */
2953 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2954 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2955 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2956 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2957 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2958 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2959
2960 /* if this is an evpn imported type-5 prefix,
2961 * we need to withdraw the route first to clear
2962 * the nh neigh and the RMAC entry.
2963 */
2964 if (old_select &&
2965 is_route_parent_evpn(old_select))
2966 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2967
9bcb3eef 2968 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2969 } else {
d62a17ae 2970 /* Withdraw the route from the kernel. */
2971 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2972 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2973 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2974 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2975
568e10ca 2976 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2977 }
718e3744 2978 }
3064bf43 2979
9bcb3eef 2980 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2981 old_select);
5424b7ba 2982
d62a17ae 2983 /* Clear any route change flags. */
9bcb3eef 2984 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2985
18ee8310 2986 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2987 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2988 bgp_path_info_reap(dest, old_select);
d62a17ae 2989
9bcb3eef 2990 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2991 return;
718e3744 2992}
2993
f009ff26 2994/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2995int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2996{
9bcb3eef 2997 struct bgp_dest *dest;
f009ff26 2998 int cnt = 0;
2999 struct afi_safi_info *thread_info;
f009ff26 3000
56c226e7
DS
3001 if (bgp->gr_info[afi][safi].t_route_select) {
3002 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3003
3004 thread_info = THREAD_ARG(t);
3005 XFREE(MTYPE_TMP, thread_info);
f009ff26 3006 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3007 }
f009ff26 3008
3009 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3010 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3011 get_afi_safi_str(afi, safi, false),
26742171 3012 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3013 }
3014
3015 /* Process the route list */
6338d242
DS
3016 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3017 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3018 dest = bgp_route_next(dest)) {
3019 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3020 continue;
3021
3022 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3023 bgp->gr_info[afi][safi].gr_deferred--;
3024 bgp_process_main_one(bgp, dest, afi, safi);
3025 cnt++;
3026 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3027 bgp_dest_unlock_node(dest);
3028 break;
f009ff26 3029 }
f009ff26 3030 }
3031
9e3b51a7 3032 /* Send EOR message when all routes are processed */
6338d242 3033 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3034 bgp_send_delayed_eor(bgp);
8c48b3b6 3035 /* Send route processing complete message to RIB */
3036 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3037 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3038 return 0;
9e3b51a7 3039 }
f009ff26 3040
3041 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3042
3043 thread_info->afi = afi;
3044 thread_info->safi = safi;
3045 thread_info->bgp = bgp;
3046
3047 /* If there are more routes to be processed, start the
3048 * selection timer
3049 */
3050 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3051 BGP_ROUTE_SELECT_DELAY,
3052 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3053 return 0;
3054}
3055
aac24838 3056static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3057{
aac24838
JB
3058 struct bgp_process_queue *pqnode = data;
3059 struct bgp *bgp = pqnode->bgp;
d62a17ae 3060 struct bgp_table *table;
9bcb3eef 3061 struct bgp_dest *dest;
aac24838
JB
3062
3063 /* eoiu marker */
3064 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3065 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3066 /* should always have dedicated wq call */
3067 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3068 return WQ_SUCCESS;
3069 }
3070
ac021f40 3071 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3072 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3073 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3074 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3075 table = bgp_dest_table(dest);
3076 /* note, new DESTs may be added as part of processing */
3077 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3078
9bcb3eef 3079 bgp_dest_unlock_node(dest);
d62a17ae 3080 bgp_table_unlock(table);
3081 }
aac24838
JB
3082
3083 return WQ_SUCCESS;
3084}
3085
3086static void bgp_processq_del(struct work_queue *wq, void *data)
3087{
3088 struct bgp_process_queue *pqnode = data;
3089
3090 bgp_unlock(pqnode->bgp);
3091
3092 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3093}
3094
b6c386bb 3095void bgp_process_queue_init(struct bgp *bgp)
200df115 3096{
b6c386bb
DS
3097 if (!bgp->process_queue) {
3098 char name[BUFSIZ];
3099
3100 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3101 bgp->process_queue = work_queue_new(bm->master, name);
3102 }
3103
3104 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3105 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3106 bgp->process_queue->spec.max_retries = 0;
3107 bgp->process_queue->spec.hold = 50;
d62a17ae 3108 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3109 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3110}
3111
cfe8d15a 3112static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3113{
3114 struct bgp_process_queue *pqnode;
3115
a4d82a8a
PZ
3116 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3117 sizeof(struct bgp_process_queue));
aac24838
JB
3118
3119 /* unlocked in bgp_processq_del */
3120 pqnode->bgp = bgp_lock(bgp);
3121 STAILQ_INIT(&pqnode->pqueue);
3122
aac24838
JB
3123 return pqnode;
3124}
3125
9bcb3eef 3126void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3127{
aac24838 3128#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3129 struct work_queue *wq = bgp->process_queue;
d62a17ae 3130 struct bgp_process_queue *pqnode;
cfe8d15a 3131 int pqnode_reuse = 0;
495f0b13 3132
d62a17ae 3133 /* already scheduled for processing? */
9bcb3eef 3134 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3135 return;
2e02b9b2 3136
f009ff26 3137 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3138 * the workqueue
3139 */
9bcb3eef 3140 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3141 if (BGP_DEBUG(update, UPDATE_OUT))
3142 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3143 dest);
f009ff26 3144 return;
3145 }
3146
46aeabed
LS
3147 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3148 if (BGP_DEBUG(update, UPDATE_OUT))
3149 zlog_debug(
3150 "Soft reconfigure table in progress for route %p",
3151 dest);
3152 return;
3153 }
3154
aac24838 3155 if (wq == NULL)
d62a17ae 3156 return;
3157
aac24838 3158 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3159 limit only if is from the same BGP view and it's not an EOIU marker
3160 */
aac24838
JB
3161 if (work_queue_item_count(wq)) {
3162 struct work_queue_item *item = work_queue_last_item(wq);
3163 pqnode = item->data;
228da428 3164
a4d82a8a
PZ
3165 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3166 || pqnode->bgp != bgp
3167 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3168 pqnode = bgp_processq_alloc(bgp);
3169 else
3170 pqnode_reuse = 1;
aac24838 3171 } else
cfe8d15a 3172 pqnode = bgp_processq_alloc(bgp);
aac24838 3173 /* all unlocked in bgp_process_wq */
9bcb3eef 3174 bgp_table_lock(bgp_dest_table(dest));
aac24838 3175
9bcb3eef
DS
3176 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3177 bgp_dest_lock_node(dest);
aac24838 3178
60466a63 3179 /* can't be enqueued twice */
9bcb3eef
DS
3180 assert(STAILQ_NEXT(dest, pq) == NULL);
3181 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3182 pqnode->queued++;
3183
cfe8d15a
LB
3184 if (!pqnode_reuse)
3185 work_queue_add(wq, pqnode);
3186
d62a17ae 3187 return;
fee0f4c6 3188}
0a486e5f 3189
d62a17ae 3190void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3191{
d62a17ae 3192 struct bgp_process_queue *pqnode;
cb1faec9 3193
b6c386bb 3194 if (bgp->process_queue == NULL)
d62a17ae 3195 return;
2e02b9b2 3196
cfe8d15a 3197 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3198
aac24838 3199 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3200 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3201}
3202
d62a17ae 3203static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3204{
d62a17ae 3205 struct peer *peer;
0a486e5f 3206
d62a17ae 3207 peer = THREAD_ARG(thread);
3208 peer->t_pmax_restart = NULL;
0a486e5f 3209
d62a17ae 3210 if (bgp_debug_neighbor_events(peer))
3211 zlog_debug(
3212 "%s Maximum-prefix restart timer expired, restore peering",
3213 peer->host);
0a486e5f 3214
a9bafa95 3215 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3216 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3217
d62a17ae 3218 return 0;
0a486e5f 3219}
3220
9cbd06e0
DA
3221static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3222 safi_t safi)
3223{
3224 uint32_t count = 0;
f41b0459 3225 bool filtered = false;
9cbd06e0
DA
3226 struct bgp_dest *dest;
3227 struct bgp_adj_in *ain;
40bb2ccf 3228 struct attr attr = {};
9cbd06e0
DA
3229 struct bgp_table *table = peer->bgp->rib[afi][safi];
3230
3231 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3232 for (ain = dest->adj_in; ain; ain = ain->next) {
3233 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3234
3235 attr = *ain->attr;
9cbd06e0
DA
3236
3237 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3238 == FILTER_DENY)
f41b0459
DA
3239 filtered = true;
3240
3241 if (bgp_input_modifier(
3242 peer, rn_p, &attr, afi, safi,
3243 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3244 NULL, 0, NULL)
3245 == RMAP_DENY)
3246 filtered = true;
3247
3248 if (filtered)
9cbd06e0 3249 count++;
f41b0459
DA
3250
3251 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3252 }
3253 }
3254
3255 return count;
3256}
3257
3dc339cd
DA
3258bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3259 int always)
718e3744 3260{
d62a17ae 3261 iana_afi_t pkt_afi;
5c525538 3262 iana_safi_t pkt_safi;
9cbd06e0
DA
3263 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3264 PEER_FLAG_MAX_PREFIX_FORCE))
3265 ? bgp_filtered_routes_count(peer, afi, safi)
3266 + peer->pcount[afi][safi]
3267 : peer->pcount[afi][safi];
9cabb64b 3268
d62a17ae 3269 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3270 return false;
e0701b79 3271
9cbd06e0 3272 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3273 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3274 PEER_STATUS_PREFIX_LIMIT)
3275 && !always)
3dc339cd 3276 return false;
e0701b79 3277
d62a17ae 3278 zlog_info(
6cde4b45 3279 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3280 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3281 peer->pmax[afi][safi]);
d62a17ae 3282 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3283
3284 if (CHECK_FLAG(peer->af_flags[afi][safi],
3285 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3286 return false;
d62a17ae 3287
3288 /* Convert AFI, SAFI to values for packet. */
3289 pkt_afi = afi_int2iana(afi);
3290 pkt_safi = safi_int2iana(safi);
3291 {
d7c0a89a 3292 uint8_t ndata[7];
d62a17ae 3293
3294 ndata[0] = (pkt_afi >> 8);
3295 ndata[1] = pkt_afi;
3296 ndata[2] = pkt_safi;
3297 ndata[3] = (peer->pmax[afi][safi] >> 24);
3298 ndata[4] = (peer->pmax[afi][safi] >> 16);
3299 ndata[5] = (peer->pmax[afi][safi] >> 8);
3300 ndata[6] = (peer->pmax[afi][safi]);
3301
3302 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3303 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3304 BGP_NOTIFY_CEASE_MAX_PREFIX,
3305 ndata, 7);
3306 }
3307
3308 /* Dynamic peers will just close their connection. */
3309 if (peer_dynamic_neighbor(peer))
3dc339cd 3310 return true;
d62a17ae 3311
3312 /* restart timer start */
3313 if (peer->pmax_restart[afi][safi]) {
3314 peer->v_pmax_restart =
3315 peer->pmax_restart[afi][safi] * 60;
3316
3317 if (bgp_debug_neighbor_events(peer))
3318 zlog_debug(
3319 "%s Maximum-prefix restart timer started for %d secs",
3320 peer->host, peer->v_pmax_restart);
3321
3322 BGP_TIMER_ON(peer->t_pmax_restart,
3323 bgp_maximum_prefix_restart_timer,
3324 peer->v_pmax_restart);
3325 }
3326
3dc339cd 3327 return true;
d62a17ae 3328 } else
3329 UNSET_FLAG(peer->af_sflags[afi][safi],
3330 PEER_STATUS_PREFIX_LIMIT);
3331
b1823b69
DS
3332 if (pcount
3333 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3334 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3335 PEER_STATUS_PREFIX_THRESHOLD)
3336 && !always)
3dc339cd 3337 return false;
d62a17ae 3338
3339 zlog_info(
6cde4b45 3340 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3341 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3342 peer->pmax[afi][safi]);
d62a17ae 3343 SET_FLAG(peer->af_sflags[afi][safi],
3344 PEER_STATUS_PREFIX_THRESHOLD);
3345 } else
3346 UNSET_FLAG(peer->af_sflags[afi][safi],
3347 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3348 return false;
718e3744 3349}
3350
b40d939b 3351/* Unconditionally remove the route from the RIB, without taking
3352 * damping into consideration (eg, because the session went down)
3353 */
9bcb3eef 3354void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3355 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3356{
f009ff26 3357
3358 struct bgp *bgp = NULL;
3359 bool delete_route = false;
3360
9bcb3eef
DS
3361 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3362 safi);
d62a17ae 3363
f009ff26 3364 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3365 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3366
f009ff26 3367 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3368 * flag
3369 */
3370 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3371 delete_route = true;
9bcb3eef 3372 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3373 delete_route = true;
f009ff26 3374 if (delete_route) {
9bcb3eef
DS
3375 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3376 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3377 bgp = pi->peer->bgp;
26742171 3378 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3379 }
3380 }
3381 }
4a11bf2c 3382
9bcb3eef
DS
3383 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3384 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3385}
3386
9bcb3eef 3387static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3388 struct peer *peer, afi_t afi, safi_t safi,
3389 struct prefix_rd *prd)
3390{
9bcb3eef 3391 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3392
d62a17ae 3393 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3394 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3395 */
b4f7f45b
IR
3396 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3397 && peer->sort == BGP_PEER_EBGP)
3398 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3399 == BGP_DAMP_SUPPRESSED) {
3400 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3401 safi);
3402 return;
d62a17ae 3403 }
3404
49e5a4a0 3405#ifdef ENABLE_BGP_VNC
d62a17ae 3406 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3407 struct bgp_dest *pdest = NULL;
d62a17ae 3408 struct bgp_table *table = NULL;
3409
9bcb3eef
DS
3410 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3411 (struct prefix *)prd);
3412 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3413 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3414
3415 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3416 peer->bgp, prd, table, p, pi);
d62a17ae 3417 }
9bcb3eef 3418 bgp_dest_unlock_node(pdest);
d62a17ae 3419 }
3420 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3421 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3422
b54892e0
DS
3423 vnc_import_bgp_del_route(peer->bgp, p, pi);
3424 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3425 }
65efcfce 3426 }
d62a17ae 3427#endif
128ea8ab 3428
d62a17ae 3429 /* If this is an EVPN route, process for un-import. */
3430 if (safi == SAFI_EVPN)
b54892e0 3431 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3432
9bcb3eef 3433 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3434}
3435
4b7e6066
DS
3436struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3437 struct peer *peer, struct attr *attr,
9bcb3eef 3438 struct bgp_dest *dest)
fb018d25 3439{
4b7e6066 3440 struct bgp_path_info *new;
fb018d25 3441
d62a17ae 3442 /* Make new BGP info. */
4b7e6066 3443 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3444 new->type = type;
3445 new->instance = instance;
3446 new->sub_type = sub_type;
3447 new->peer = peer;
3448 new->attr = attr;
3449 new->uptime = bgp_clock();
9bcb3eef 3450 new->net = dest;
d62a17ae 3451 return new;
fb018d25
DS
3452}
3453
40381db7 3454static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3455 union gw_addr *gw_ip)
3456{
6c924775
DS
3457 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3458 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3459 union {
0a50c248 3460 esi_t esi;
11ebf4ed
DS
3461 union gw_addr ip;
3462 } temp;
d62a17ae 3463
3464 if (afi != AFI_L2VPN)
3465 return true;
11ebf4ed 3466
6c924775 3467 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3468
3469 if (gw_ip == NULL) {
3470 memset(&temp, 0, sizeof(temp));
40381db7 3471 path_gw_ip_remote = &temp.ip;
11ebf4ed 3472 } else
40381db7 3473 path_gw_ip_remote = gw_ip;
11ebf4ed 3474
6c924775 3475 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3476}
3477
c265ee22 3478/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3479bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3480 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3481 struct bgp_dest *dest)
d62a17ae 3482{
2dbe3fa9 3483 bool ret = false;
b099a5c8
DA
3484 bool is_bgp_static_route =
3485 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3486 : false;
d62a17ae 3487
e8442016
DS
3488 /*
3489 * Only validated for unicast and multicast currently.
3490 * Also valid for EVPN where the nexthop is an IP address.
3491 * If we are a bgp static route being checked then there is
3492 * no need to check to see if the nexthop is martian as
3493 * that it should be ok.
3494 */
3495 if (is_bgp_static_route ||
3496 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3497 return false;
d62a17ae 3498
3499 /* If NEXT_HOP is present, validate it. */
3500 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3501 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3502 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3503 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3504 return true;
d62a17ae 3505 }
c265ee22 3506
d62a17ae 3507 /* If MP_NEXTHOP is present, validate it. */
3508 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3509 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3510 * it is not an IPv6 link-local address.
0355b41d
DA
3511 *
3512 * If we receive an UPDATE with nexthop length set to 32 bytes
3513 * we shouldn't discard an UPDATE if it's set to (::).
3514 * The link-local (2st) is validated along the code path later.
d62a17ae 3515 */
3516 if (attr->mp_nexthop_len) {
3517 switch (attr->mp_nexthop_len) {
3518 case BGP_ATTR_NHLEN_IPV4:
3519 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3520 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3521 || IPV4_CLASS_DE(
3522 ntohl(attr->mp_nexthop_global_in.s_addr))
3523 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3524 dest));
d62a17ae 3525 break;
3526
3527 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3528 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3529 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3530 &attr->mp_nexthop_global)
d62a17ae 3531 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3532 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3533 &attr->mp_nexthop_global)
3534 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3535 dest));
d62a17ae 3536 break;
0355b41d
DA
3537 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3538 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3539 || IN6_IS_ADDR_MULTICAST(
3540 &attr->mp_nexthop_global)
3541 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3542 dest));
0355b41d 3543 break;
d62a17ae 3544
3545 default:
3dc339cd 3546 ret = true;
d62a17ae 3547 break;
3548 }
3549 }
c265ee22 3550
d62a17ae 3551 return ret;
3552}
3553
aade37d7 3554static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3555{
3556 struct community *old;
3557 struct community *new;
3558 struct community *merge;
aade37d7 3559 struct community *no_export;
2721dd61
DA
3560
3561 old = attr->community;
aade37d7 3562 no_export = community_str2com("no-export");
2721dd61 3563
b4efa101
DA
3564 assert(no_export);
3565
2721dd61 3566 if (old) {
aade37d7 3567 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3568
3569 if (!old->refcnt)
3570 community_free(&old);
3571
3572 new = community_uniq_sort(merge);
3573 community_free(&merge);
3574 } else {
aade37d7 3575 new = community_dup(no_export);
2721dd61
DA
3576 }
3577
aade37d7 3578 community_free(&no_export);
2721dd61
DA
3579
3580 attr->community = new;
3581 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3582}
3583
5a1ae2c2 3584int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3585 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3586 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3587 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3588 struct bgp_route_evpn *evpn)
d62a17ae 3589{
3590 int ret;
3591 int aspath_loop_count = 0;
9bcb3eef 3592 struct bgp_dest *dest;
d62a17ae 3593 struct bgp *bgp;
3594 struct attr new_attr;
3595 struct attr *attr_new;
40381db7 3596 struct bgp_path_info *pi;
4b7e6066
DS
3597 struct bgp_path_info *new;
3598 struct bgp_path_info_extra *extra;
d62a17ae 3599 const char *reason;
3600 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3601 int connected = 0;
3602 int do_loop_check = 1;
3603 int has_valid_label = 0;
7c312383 3604 afi_t nh_afi;
949b0f24 3605 uint8_t pi_type = 0;
3606 uint8_t pi_sub_type = 0;
9146341f 3607 bool force_evpn_import = false;
949b0f24 3608
c7bb4f00 3609 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3610 char pfxprint[PREFIX2STR_BUFFER];
3611
3612 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3613 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3614 afi, safi, attr);
6401252f
QY
3615 }
3616
49e5a4a0 3617#ifdef ENABLE_BGP_VNC
d62a17ae 3618 int vnc_implicit_withdraw = 0;
65efcfce 3619#endif
d62a17ae 3620 int same_attr = 0;
718e3744 3621
d62a17ae 3622 memset(&new_attr, 0, sizeof(struct attr));
3623 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3624 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3625
d62a17ae 3626 bgp = peer->bgp;
9bcb3eef 3627 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3628 /* TODO: Check to see if we can get rid of "is_valid_label" */
3629 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3630 has_valid_label = (num_labels > 0) ? 1 : 0;
3631 else
3632 has_valid_label = bgp_is_valid_label(label);
718e3744 3633
28f66de2
MS
3634 if (has_valid_label)
3635 assert(label != NULL);
3636
66ff6089
AD
3637 /* Update overlay index of the attribute */
3638 if (afi == AFI_L2VPN && evpn)
3639 memcpy(&attr->evpn_overlay, evpn,
3640 sizeof(struct bgp_route_evpn));
3641
d62a17ae 3642 /* When peer's soft reconfiguration enabled. Record input packet in
3643 Adj-RIBs-In. */
3644 if (!soft_reconfig
3645 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3646 && peer != bgp->peer_self)
9bcb3eef 3647 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3648
3649 /* Check previously received route. */
9bcb3eef 3650 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3651 if (pi->peer == peer && pi->type == type
3652 && pi->sub_type == sub_type
3653 && pi->addpath_rx_id == addpath_id)
d62a17ae 3654 break;
3655
3656 /* AS path local-as loop check. */
3657 if (peer->change_local_as) {
c4368918
DW
3658 if (peer->allowas_in[afi][safi])
3659 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3660 else if (!CHECK_FLAG(peer->flags,
3661 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3662 aspath_loop_count = 1;
3663
3664 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3665 > aspath_loop_count) {
b4d46cc9 3666 peer->stat_pfx_aspath_loop++;
692174a1 3667 reason = "as-path contains our own AS;";
d62a17ae 3668 goto filtered;
3669 }
718e3744 3670 }
718e3744 3671
d62a17ae 3672 /* If the peer is configured for "allowas-in origin" and the last ASN in
3673 * the
3674 * as-path is our ASN then we do not need to call aspath_loop_check
3675 */
3676 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3677 if (aspath_get_last_as(attr->aspath) == bgp->as)
3678 do_loop_check = 0;
3679
3680 /* AS path loop check. */
3681 if (do_loop_check) {
3682 if (aspath_loop_check(attr->aspath, bgp->as)
3683 > peer->allowas_in[afi][safi]
3684 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3685 && aspath_loop_check(attr->aspath, bgp->confed_id)
3686 > peer->allowas_in[afi][safi])) {
b4d46cc9 3687 peer->stat_pfx_aspath_loop++;
d62a17ae 3688 reason = "as-path contains our own AS;";
3689 goto filtered;
3690 }
3691 }
aac9ef6c 3692
d62a17ae 3693 /* Route reflector originator ID check. */
3694 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3695 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3696 peer->stat_pfx_originator_loop++;
d62a17ae 3697 reason = "originator is us;";
3698 goto filtered;
3699 }
718e3744 3700
d62a17ae 3701 /* Route reflector cluster ID check. */
3702 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3703 peer->stat_pfx_cluster_loop++;
d62a17ae 3704 reason = "reflected from the same cluster;";
3705 goto filtered;
3706 }
718e3744 3707
d62a17ae 3708 /* Apply incoming filter. */
3709 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3710 peer->stat_pfx_filter++;
d62a17ae 3711 reason = "filter;";
3712 goto filtered;
3713 }
718e3744 3714
a8b72dc6
DA
3715 /* RFC 8212 to prevent route leaks.
3716 * This specification intends to improve this situation by requiring the
3717 * explicit configuration of both BGP Import and Export Policies for any
3718 * External BGP (EBGP) session such as customers, peers, or
3719 * confederation boundaries for all enabled address families. Through
3720 * codification of the aforementioned requirement, operators will
3721 * benefit from consistent behavior across different BGP
3722 * implementations.
3723 */
1d3fdccf 3724 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3725 if (!bgp_inbound_policy_exists(peer,
3726 &peer->filter[afi][safi])) {
3727 reason = "inbound policy missing";
3728 goto filtered;
3729 }
3730
fb29348a
DA
3731 /* draft-ietf-idr-deprecate-as-set-confed-set
3732 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3733 * Eventually, This document (if approved) updates RFC 4271
3734 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3735 * and obsoletes RFC 6472.
3736 */
7f972cd8 3737 if (peer->bgp->reject_as_sets)
fb29348a
DA
3738 if (aspath_check_as_sets(attr->aspath)) {
3739 reason =
3740 "as-path contains AS_SET or AS_CONFED_SET type;";
3741 goto filtered;
3742 }
3743
6f4f49b2 3744 new_attr = *attr;
d62a17ae 3745
3746 /* Apply incoming route-map.
3747 * NB: new_attr may now contain newly allocated values from route-map
3748 * "set"
3749 * commands, so we need bgp_attr_flush in the error paths, until we
3750 * intern
3751 * the attr (which takes over the memory references) */
9bcb3eef
DS
3752 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3753 num_labels, dest)
3754 == RMAP_DENY) {
b4d46cc9 3755 peer->stat_pfx_filter++;
d62a17ae 3756 reason = "route-map;";
3757 bgp_attr_flush(&new_attr);
3758 goto filtered;
3759 }
718e3744 3760
05864da7 3761 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3762 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3763 /* remove from RIB previous entry */
3764 bgp_zebra_withdraw(p, pi, bgp, safi);
3765 }
3766
7f323236
DW
3767 if (peer->sort == BGP_PEER_EBGP) {
3768
2721dd61
DA
3769 /* rfc7999:
3770 * A BGP speaker receiving an announcement tagged with the
3771 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3772 * NO_EXPORT community as defined in RFC1997, or a
3773 * similar community, to prevent propagation of the
3774 * prefix outside the local AS. The community to prevent
3775 * propagation SHOULD be chosen according to the operator's
3776 * routing policy.
3777 */
3778 if (new_attr.community
3779 && community_include(new_attr.community,
3780 COMMUNITY_BLACKHOLE))
aade37d7 3781 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3782
a4d82a8a
PZ
3783 /* If we receive the graceful-shutdown community from an eBGP
3784 * peer we must lower local-preference */
3785 if (new_attr.community
3786 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3787 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3788 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3789
a4d82a8a
PZ
3790 /* If graceful-shutdown is configured then add the GSHUT
3791 * community to all paths received from eBGP peers */
637e5ba4 3792 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3793 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3794 }
3795
949b0f24 3796 if (pi) {
3797 pi_type = pi->type;
3798 pi_sub_type = pi->sub_type;
3799 }
3800
d62a17ae 3801 /* next hop check. */
a4d82a8a 3802 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3803 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3804 &new_attr, dest)) {
b4d46cc9 3805 peer->stat_pfx_nh_invalid++;
d62a17ae 3806 reason = "martian or self next-hop;";
3807 bgp_attr_flush(&new_attr);
3808 goto filtered;
3809 }
718e3744 3810
5c14a191 3811 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3812 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3813 reason = "self mac;";
3814 goto filtered;
3815 }
3816
a1b773e2
DS
3817 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3818 * condition :
3819 * Suppress fib is enabled
3820 * BGP_OPT_NO_FIB is not enabled
3821 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3822 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3823 */
3824 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3825 && (sub_type == BGP_ROUTE_NORMAL)
3826 && (!bgp_option_check(BGP_OPT_NO_FIB))
3827 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3828 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3829
d62a17ae 3830 attr_new = bgp_attr_intern(&new_attr);
3831
9cbd06e0
DA
3832 /* If maximum prefix count is configured and current prefix
3833 * count exeed it.
3834 */
3835 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3836 return -1;
3837
d62a17ae 3838 /* If the update is implicit withdraw. */
40381db7
DS
3839 if (pi) {
3840 pi->uptime = bgp_clock();
3841 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3842
9bcb3eef 3843 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3844
d62a17ae 3845 /* Same attribute comes in. */
40381db7 3846 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3847 && same_attr
d62a17ae 3848 && (!has_valid_label
40381db7 3849 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3850 num_labels * sizeof(mpls_label_t))
66ff6089 3851 == 0)) {
b4f7f45b
IR
3852 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3853 BGP_CONFIG_DAMPENING)
d62a17ae 3854 && peer->sort == BGP_PEER_EBGP
40381db7 3855 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3856 if (bgp_debug_update(peer, p, NULL, 1)) {
3857 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3858 afi, safi, prd, p, label,
3859 num_labels, addpath_id ? 1 : 0,
66ff6089 3860 addpath_id, evpn, pfx_buf,
a4d82a8a 3861 sizeof(pfx_buf));
d62a17ae 3862 zlog_debug("%s rcvd %s", peer->host,
3863 pfx_buf);
3864 }
3865
9bcb3eef 3866 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3867 != BGP_DAMP_SUPPRESSED) {
40381db7 3868 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3869 safi);
9bcb3eef 3870 bgp_process(bgp, dest, afi, safi);
d62a17ae 3871 }
3872 } else /* Duplicate - odd */
3873 {
3874 if (bgp_debug_update(peer, p, NULL, 1)) {
3875 if (!peer->rcvd_attr_printed) {
3876 zlog_debug(
3877 "%s rcvd UPDATE w/ attr: %s",
3878 peer->host,
3879 peer->rcvd_attr_str);
3880 peer->rcvd_attr_printed = 1;
3881 }
3882
3883 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3884 afi, safi, prd, p, label,
3885 num_labels, addpath_id ? 1 : 0,
66ff6089 3886 addpath_id, evpn, pfx_buf,
a4d82a8a 3887 sizeof(pfx_buf));
d62a17ae 3888 zlog_debug(
3889 "%s rcvd %s...duplicate ignored",
3890 peer->host, pfx_buf);
3891 }
3892
3893 /* graceful restart STALE flag unset. */
40381db7 3894 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3895 bgp_path_info_unset_flag(
9bcb3eef
DS
3896 dest, pi, BGP_PATH_STALE);
3897 bgp_dest_set_defer_flag(dest, false);
3898 bgp_process(bgp, dest, afi, safi);
d62a17ae 3899 }
3900 }
3901
9bcb3eef 3902 bgp_dest_unlock_node(dest);
d62a17ae 3903 bgp_attr_unintern(&attr_new);
3904
3905 return 0;
3906 }
718e3744 3907
d62a17ae 3908 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3909 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3910 if (bgp_debug_update(peer, p, NULL, 1)) {
3911 bgp_debug_rdpfxpath2str(
a4d82a8a 3912 afi, safi, prd, p, label, num_labels,
66ff6089 3913 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 3914 pfx_buf, sizeof(pfx_buf));
d62a17ae 3915 zlog_debug(
3916 "%s rcvd %s, flapped quicker than processing",
3917 peer->host, pfx_buf);
3918 }
3919
9bcb3eef 3920 bgp_path_info_restore(dest, pi);
9146341f 3921
3922 /*
3923 * If the BGP_PATH_REMOVED flag is set, then EVPN
3924 * routes would have been unimported already when a
3925 * prior BGP withdraw processing happened. Such routes
3926 * need to be imported again, so flag accordingly.
3927 */
3928 force_evpn_import = true;
d62a17ae 3929 }
718e3744 3930
d62a17ae 3931 /* Received Logging. */
3932 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3933 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3934 num_labels, addpath_id ? 1 : 0,
66ff6089 3935 addpath_id, evpn, pfx_buf,
a4d82a8a 3936 sizeof(pfx_buf));
d62a17ae 3937 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3938 }
718e3744 3939
d62a17ae 3940 /* graceful restart STALE flag unset. */
f009ff26 3941 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3942 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3943 bgp_dest_set_defer_flag(dest, false);
f009ff26 3944 }
d62a17ae 3945
3946 /* The attribute is changed. */
9bcb3eef 3947 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3948
3949 /* implicit withdraw, decrement aggregate and pcount here.
3950 * only if update is accepted, they'll increment below.
3951 */
40381db7 3952 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3953
3954 /* Update bgp route dampening information. */
b4f7f45b 3955 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 3956 && peer->sort == BGP_PEER_EBGP) {
3957 /* This is implicit withdraw so we should update
b4f7f45b
IR
3958 dampening
3959 information. */
40381db7 3960 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3961 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3962 }
49e5a4a0 3963#ifdef ENABLE_BGP_VNC
d62a17ae 3964 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3965 struct bgp_dest *pdest = NULL;
d62a17ae 3966 struct bgp_table *table = NULL;
3967
9bcb3eef
DS
3968 pdest = bgp_node_get(bgp->rib[afi][safi],
3969 (struct prefix *)prd);
3970 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3971 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3972
3973 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3974 bgp, prd, table, p, pi);
d62a17ae 3975 }
9bcb3eef 3976 bgp_dest_unlock_node(pdest);
d62a17ae 3977 }
3978 if ((afi == AFI_IP || afi == AFI_IP6)
3979 && (safi == SAFI_UNICAST)) {
40381db7 3980 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3981 /*
3982 * Implicit withdraw case.
3983 */
3984 ++vnc_implicit_withdraw;
40381db7
DS
3985 vnc_import_bgp_del_route(bgp, p, pi);
3986 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3987 }
3988 }
65efcfce 3989#endif
128ea8ab 3990
d62a17ae 3991 /* Special handling for EVPN update of an existing route. If the
3992 * extended community attribute has changed, we need to
3993 * un-import
3994 * the route using its existing extended community. It will be
3995 * subsequently processed for import with the new extended
3996 * community.
3997 */
6f8c9c11
PR
3998 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3999 && !same_attr) {
40381db7 4000 if ((pi->attr->flag
d62a17ae 4001 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4002 && (attr_new->flag
4003 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4004 int cmp;
4005
40381db7 4006 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4007 attr_new->ecommunity);
4008 if (!cmp) {
4009 if (bgp_debug_update(peer, p, NULL, 1))
4010 zlog_debug(
4011 "Change in EXT-COMM, existing %s new %s",
4012 ecommunity_str(
40381db7 4013 pi->attr->ecommunity),
d62a17ae 4014 ecommunity_str(
4015 attr_new->ecommunity));
6f8c9c11
PR
4016 if (safi == SAFI_EVPN)
4017 bgp_evpn_unimport_route(
4018 bgp, afi, safi, p, pi);
4019 else /* SAFI_MPLS_VPN */
4020 vpn_leak_to_vrf_withdraw(bgp,
4021 pi);
d62a17ae 4022 }
4023 }
4024 }
718e3744 4025
d62a17ae 4026 /* Update to new attribute. */
40381db7
DS
4027 bgp_attr_unintern(&pi->attr);
4028 pi->attr = attr_new;
d62a17ae 4029
4030 /* Update MPLS label */
4031 if (has_valid_label) {
40381db7 4032 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4033 if (extra->label != label) {
4034 memcpy(&extra->label, label,
dbd587da 4035 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4036 extra->num_labels = num_labels;
4037 }
b57ba6d2
MK
4038 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4039 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4040 }
718e3744 4041
e496b420
HS
4042 /* Update SRv6 SID */
4043 if (attr->srv6_l3vpn) {
4044 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4045 if (sid_diff(&extra->sid[0].sid,
4046 &attr->srv6_l3vpn->sid)) {
4047 sid_copy(&extra->sid[0].sid,
e496b420
HS
4048 &attr->srv6_l3vpn->sid);
4049 extra->num_sids = 1;
cc8f05df 4050
16f3db2d
RS
4051 extra->sid[0].loc_block_len = 0;
4052 extra->sid[0].loc_node_len = 0;
4053 extra->sid[0].func_len = 0;
4054 extra->sid[0].arg_len = 0;
4055
4056 if (attr->srv6_l3vpn->loc_block_len != 0) {
4057 extra->sid[0].loc_block_len =
4058 attr->srv6_l3vpn->loc_block_len;
4059 extra->sid[0].loc_node_len =
4060 attr->srv6_l3vpn->loc_node_len;
4061 extra->sid[0].func_len =
4062 attr->srv6_l3vpn->func_len;
4063 extra->sid[0].arg_len =
4064 attr->srv6_l3vpn->arg_len;
4065 }
4066
cc8f05df
RS
4067 /*
4068 * draft-ietf-bess-srv6-services-07
4069 * The part of SRv6 SID may be encoded as MPLS
4070 * Label for the efficient packing.
4071 */
4072 if (attr->srv6_l3vpn->transposition_len != 0)
4073 transpose_sid(
16f3db2d 4074 &extra->sid[0].sid,
cc8f05df
RS
4075 decode_label(label),
4076 attr->srv6_l3vpn
4077 ->transposition_offset,
4078 attr->srv6_l3vpn
4079 ->transposition_len);
e496b420
HS
4080 }
4081 } else if (attr->srv6_vpn) {
4082 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4083 if (sid_diff(&extra->sid[0].sid,
4084 &attr->srv6_vpn->sid)) {
4085 sid_copy(&extra->sid[0].sid,
4086 &attr->srv6_vpn->sid);
e496b420
HS
4087 extra->num_sids = 1;
4088 }
4089 }
4090
49e5a4a0 4091#ifdef ENABLE_BGP_VNC
d62a17ae 4092 if ((afi == AFI_IP || afi == AFI_IP6)
4093 && (safi == SAFI_UNICAST)) {
4094 if (vnc_implicit_withdraw) {
4095 /*
4096 * Add back the route with its new attributes
4097 * (e.g., nexthop).
4098 * The route is still selected, until the route
4099 * selection
4100 * queued by bgp_process actually runs. We have
4101 * to make this
4102 * update to the VNC side immediately to avoid
4103 * racing against
4104 * configuration changes (e.g., route-map
4105 * changes) which
4106 * trigger re-importation of the entire RIB.
4107 */
40381db7
DS
4108 vnc_import_bgp_add_route(bgp, p, pi);
4109 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4110 }
4111 }
65efcfce
LB
4112#endif
4113
d62a17ae 4114 /* Update bgp route dampening information. */
b4f7f45b 4115 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4116 && peer->sort == BGP_PEER_EBGP) {
4117 /* Now we do normal update dampening. */
9bcb3eef 4118 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4119 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4120 bgp_dest_unlock_node(dest);
d62a17ae 4121 return 0;
4122 }
4123 }
128ea8ab 4124
d62a17ae 4125 /* Nexthop reachability check - for unicast and
4126 * labeled-unicast.. */
7c312383
AD
4127 if (((afi == AFI_IP || afi == AFI_IP6)
4128 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4129 || (safi == SAFI_EVPN &&
4130 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4131 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4132 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4133 && !CHECK_FLAG(peer->flags,
4134 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4135 && !CHECK_FLAG(bgp->flags,
4136 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4137 connected = 1;
4138 else
4139 connected = 0;
4140
960035b2
PZ
4141 struct bgp *bgp_nexthop = bgp;
4142
40381db7
DS
4143 if (pi->extra && pi->extra->bgp_orig)
4144 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4145
7c312383
AD
4146 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4147
4148 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4149 safi, pi, NULL, connected,
4150 p)
a4d82a8a 4151 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4152 bgp_path_info_set_flag(dest, pi,
4153 BGP_PATH_VALID);
d62a17ae 4154 else {
4155 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4156 zlog_debug("%s(%pI4): NH unresolved",
4157 __func__,
4158 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4159 }
9bcb3eef 4160 bgp_path_info_unset_flag(dest, pi,
18ee8310 4161 BGP_PATH_VALID);
d62a17ae 4162 }
4163 } else
9bcb3eef 4164 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4165
49e5a4a0 4166#ifdef ENABLE_BGP_VNC
d62a17ae 4167 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4168 struct bgp_dest *pdest = NULL;
d62a17ae 4169 struct bgp_table *table = NULL;
4170
9bcb3eef
DS
4171 pdest = bgp_node_get(bgp->rib[afi][safi],
4172 (struct prefix *)prd);
4173 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4174 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4175
4176 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4177 bgp, prd, table, p, pi);
d62a17ae 4178 }
9bcb3eef 4179 bgp_dest_unlock_node(pdest);
d62a17ae 4180 }
4181#endif
718e3744 4182
d62a17ae 4183 /* If this is an EVPN route and some attribute has changed,
9146341f 4184 * or we are explicitly told to perform a route import, process
d62a17ae 4185 * route for import. If the extended community has changed, we
4186 * would
4187 * have done the un-import earlier and the import would result
4188 * in the
4189 * route getting injected into appropriate L2 VNIs. If it is
4190 * just
4191 * some other attribute change, the import will result in
4192 * updating
4193 * the attributes for the route in the VNI(s).
4194 */
9146341f 4195 if (safi == SAFI_EVPN &&
4196 (!same_attr || force_evpn_import) &&
7c312383 4197 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4198 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4199
4200 /* Process change. */
40381db7 4201 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4202
9bcb3eef
DS
4203 bgp_process(bgp, dest, afi, safi);
4204 bgp_dest_unlock_node(dest);
558d1fec 4205
ddb5b488
PZ
4206 if (SAFI_UNICAST == safi
4207 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4208 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4209
40381db7 4210 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4211 }
4212 if ((SAFI_MPLS_VPN == safi)
4213 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4214
40381db7 4215 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4216 }
4217
49e5a4a0 4218#ifdef ENABLE_BGP_VNC
d62a17ae 4219 if (SAFI_MPLS_VPN == safi) {
4220 mpls_label_t label_decoded = decode_label(label);
28070ee3 4221
d62a17ae 4222 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4223 type, sub_type, &label_decoded);
4224 }
4225 if (SAFI_ENCAP == safi) {
4226 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4227 type, sub_type, NULL);
4228 }
28070ee3
PZ
4229#endif
4230
d62a17ae 4231 return 0;
4232 } // End of implicit withdraw
718e3744 4233
d62a17ae 4234 /* Received Logging. */
4235 if (bgp_debug_update(peer, p, NULL, 1)) {
4236 if (!peer->rcvd_attr_printed) {
4237 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4238 peer->rcvd_attr_str);
4239 peer->rcvd_attr_printed = 1;
4240 }
718e3744 4241
a4d82a8a 4242 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4243 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4244 pfx_buf, sizeof(pfx_buf));
d62a17ae 4245 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4246 }
718e3744 4247
d62a17ae 4248 /* Make new BGP info. */
9bcb3eef 4249 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4250
d62a17ae 4251 /* Update MPLS label */
4252 if (has_valid_label) {
18ee8310 4253 extra = bgp_path_info_extra_get(new);
8ba71050 4254 if (extra->label != label) {
dbd587da
QY
4255 memcpy(&extra->label, label,
4256 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4257 extra->num_labels = num_labels;
4258 }
b57ba6d2
MK
4259 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4260 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4261 }
718e3744 4262
e496b420
HS
4263 /* Update SRv6 SID */
4264 if (safi == SAFI_MPLS_VPN) {
4265 extra = bgp_path_info_extra_get(new);
4266 if (attr->srv6_l3vpn) {
16f3db2d 4267 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4268 extra->num_sids = 1;
cc8f05df 4269
16f3db2d
RS
4270 extra->sid[0].loc_block_len =
4271 attr->srv6_l3vpn->loc_block_len;
4272 extra->sid[0].loc_node_len =
4273 attr->srv6_l3vpn->loc_node_len;
4274 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4275 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
4276
cc8f05df
RS
4277 /*
4278 * draft-ietf-bess-srv6-services-07
4279 * The part of SRv6 SID may be encoded as MPLS Label for
4280 * the efficient packing.
4281 */
4282 if (attr->srv6_l3vpn->transposition_len != 0)
4283 transpose_sid(
16f3db2d 4284 &extra->sid[0].sid, decode_label(label),
cc8f05df
RS
4285 attr->srv6_l3vpn->transposition_offset,
4286 attr->srv6_l3vpn->transposition_len);
e496b420 4287 } else if (attr->srv6_vpn) {
16f3db2d 4288 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4289 extra->num_sids = 1;
4290 }
4291 }
4292
d62a17ae 4293 /* Nexthop reachability check. */
7c312383
AD
4294 if (((afi == AFI_IP || afi == AFI_IP6)
4295 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4296 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4297 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4298 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4299 && !CHECK_FLAG(peer->flags,
4300 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4301 && !CHECK_FLAG(bgp->flags,
4302 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4303 connected = 1;
4304 else
4305 connected = 0;
4306
7c312383
AD
4307 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4308
4053e952 4309 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4310 connected, p)
a4d82a8a 4311 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4312 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4313 else {
4314 if (BGP_DEBUG(nht, NHT)) {
4315 char buf1[INET6_ADDRSTRLEN];
4316 inet_ntop(AF_INET,
4317 (const void *)&attr_new->nexthop,
4318 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4319 zlog_debug("%s(%s): NH unresolved", __func__,
4320 buf1);
d62a17ae 4321 }
9bcb3eef 4322 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4323 }
4324 } else
9bcb3eef 4325 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4326
d62a17ae 4327 /* Addpath ID */
4328 new->addpath_rx_id = addpath_id;
4329
4330 /* Increment prefix */
4331 bgp_aggregate_increment(bgp, p, new, afi, safi);
4332
4333 /* Register new BGP information. */
9bcb3eef 4334 bgp_path_info_add(dest, new);
d62a17ae 4335
4336 /* route_node_get lock */
9bcb3eef 4337 bgp_dest_unlock_node(dest);
558d1fec 4338
49e5a4a0 4339#ifdef ENABLE_BGP_VNC
d62a17ae 4340 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4341 struct bgp_dest *pdest = NULL;
d62a17ae 4342 struct bgp_table *table = NULL;
4343
9bcb3eef
DS
4344 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4345 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4346 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4347
4348 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4349 bgp, prd, table, p, new);
4350 }
9bcb3eef 4351 bgp_dest_unlock_node(pdest);
d62a17ae 4352 }
65efcfce
LB
4353#endif
4354
d62a17ae 4355 /* If this is an EVPN route, process for import. */
7c312383 4356 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4357 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4358
9bcb3eef 4359 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4360
d62a17ae 4361 /* Process change. */
9bcb3eef 4362 bgp_process(bgp, dest, afi, safi);
718e3744 4363
ddb5b488
PZ
4364 if (SAFI_UNICAST == safi
4365 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4366 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4367 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4368 }
4369 if ((SAFI_MPLS_VPN == safi)
4370 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4371
4372 vpn_leak_to_vrf_update(bgp, new);
4373 }
49e5a4a0 4374#ifdef ENABLE_BGP_VNC
d62a17ae 4375 if (SAFI_MPLS_VPN == safi) {
4376 mpls_label_t label_decoded = decode_label(label);
28070ee3 4377
d62a17ae 4378 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4379 sub_type, &label_decoded);
4380 }
4381 if (SAFI_ENCAP == safi) {
4382 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4383 sub_type, NULL);
4384 }
28070ee3
PZ
4385#endif
4386
d62a17ae 4387 return 0;
718e3744 4388
d62a17ae 4389/* This BGP update is filtered. Log the reason then update BGP
4390 entry. */
4391filtered:
9bcb3eef 4392 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4393
d62a17ae 4394 if (bgp_debug_update(peer, p, NULL, 1)) {
4395 if (!peer->rcvd_attr_printed) {
4396 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4397 peer->rcvd_attr_str);
4398 peer->rcvd_attr_printed = 1;
4399 }
718e3744 4400
a4d82a8a 4401 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4402 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4403 pfx_buf, sizeof(pfx_buf));
d62a17ae 4404 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4405 peer->host, pfx_buf, reason);
4406 }
128ea8ab 4407
40381db7 4408 if (pi) {
d62a17ae 4409 /* If this is an EVPN route, un-import it as it is now filtered.
4410 */
4411 if (safi == SAFI_EVPN)
40381db7 4412 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4413
ddb5b488
PZ
4414 if (SAFI_UNICAST == safi
4415 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4416 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4417
40381db7 4418 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4419 }
4420 if ((SAFI_MPLS_VPN == safi)
4421 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4422
40381db7 4423 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4424 }
4425
9bcb3eef 4426 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4427 }
4428
9bcb3eef 4429 bgp_dest_unlock_node(dest);
558d1fec 4430
49e5a4a0 4431#ifdef ENABLE_BGP_VNC
d62a17ae 4432 /*
4433 * Filtered update is treated as an implicit withdrawal (see
4434 * bgp_rib_remove()
4435 * a few lines above)
4436 */
4437 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4438 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4439 0);
4440 }
97736e32
PZ
4441#endif
4442
d62a17ae 4443 return 0;
718e3744 4444}
4445
26a3ffd6 4446int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4447 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4448 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4449 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4450{
d62a17ae 4451 struct bgp *bgp;
4452 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4453 struct bgp_dest *dest;
40381db7 4454 struct bgp_path_info *pi;
718e3744 4455
49e5a4a0 4456#ifdef ENABLE_BGP_VNC
d62a17ae 4457 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4458 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4459 0);
4460 }
28070ee3
PZ
4461#endif
4462
d62a17ae 4463 bgp = peer->bgp;
4464
4465 /* Lookup node. */
9bcb3eef 4466 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4467
4468 /* If peer is soft reconfiguration enabled. Record input packet for
4469 * further calculation.
4470 *
4471 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4472 * routes that are filtered. This tanks out Quagga RS pretty badly due
4473 * to
4474 * the iteration over all RS clients.
4475 * Since we need to remove the entry from adj_in anyway, do that first
4476 * and
4477 * if there was no entry, we don't need to do anything more.
4478 */
4479 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4480 && peer != bgp->peer_self)
9bcb3eef 4481 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4482 peer->stat_pfx_dup_withdraw++;
4483
d62a17ae 4484 if (bgp_debug_update(peer, p, NULL, 1)) {
4485 bgp_debug_rdpfxpath2str(
a4d82a8a 4486 afi, safi, prd, p, label, num_labels,
6c995628
AD
4487 addpath_id ? 1 : 0, addpath_id, NULL,
4488 pfx_buf, sizeof(pfx_buf));
d62a17ae 4489 zlog_debug(
4490 "%s withdrawing route %s not in adj-in",
4491 peer->host, pfx_buf);
4492 }
9bcb3eef 4493 bgp_dest_unlock_node(dest);
d62a17ae 4494 return 0;
4495 }
cd808e74 4496
d62a17ae 4497 /* Lookup withdrawn route. */
9bcb3eef 4498 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4499 if (pi->peer == peer && pi->type == type
4500 && pi->sub_type == sub_type
4501 && pi->addpath_rx_id == addpath_id)
d62a17ae 4502 break;
4503
4504 /* Logging. */
4505 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4506 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4507 addpath_id ? 1 : 0, addpath_id, NULL,
4508 pfx_buf, sizeof(pfx_buf));
d62a17ae 4509 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4510 pfx_buf);
4511 }
718e3744 4512
d62a17ae 4513 /* Withdraw specified route from routing table. */
40381db7 4514 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4515 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4516 if (SAFI_UNICAST == safi
4517 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4518 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4519 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4520 }
4521 if ((SAFI_MPLS_VPN == safi)
4522 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4523
40381db7 4524 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4525 }
4526 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4527 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4528 addpath_id ? 1 : 0, addpath_id, NULL,
4529 pfx_buf, sizeof(pfx_buf));
d62a17ae 4530 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4531 }
718e3744 4532
d62a17ae 4533 /* Unlock bgp_node_get() lock. */
9bcb3eef 4534 bgp_dest_unlock_node(dest);
d62a17ae 4535
4536 return 0;
718e3744 4537}
6b0655a2 4538
d62a17ae 4539void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4540 int withdraw)
718e3744 4541{
d62a17ae 4542 struct update_subgroup *subgrp;
4543 subgrp = peer_subgroup(peer, afi, safi);
4544 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4545}
6182d65b 4546
718e3744 4547
3f9c7369
DS
4548/*
4549 * bgp_stop_announce_route_timer
4550 */
d62a17ae 4551void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4552{
d62a17ae 4553 if (!paf->t_announce_route)
4554 return;
4555
50478845 4556 thread_cancel(&paf->t_announce_route);
718e3744 4557}
6b0655a2 4558
3f9c7369
DS
4559/*
4560 * bgp_announce_route_timer_expired
4561 *
4562 * Callback that is invoked when the route announcement timer for a
4563 * peer_af expires.
4564 */
d62a17ae 4565static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4566{
d62a17ae 4567 struct peer_af *paf;
4568 struct peer *peer;
558d1fec 4569
d62a17ae 4570 paf = THREAD_ARG(t);
4571 peer = paf->peer;
718e3744 4572
feb17238 4573 if (!peer_established(peer))
d62a17ae 4574 return 0;
3f9c7369 4575
d62a17ae 4576 if (!peer->afc_nego[paf->afi][paf->safi])
4577 return 0;
3f9c7369 4578
d62a17ae 4579 peer_af_announce_route(paf, 1);
c5aec50b
MK
4580
4581 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4582 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4583
d62a17ae 4584 return 0;
718e3744 4585}
4586
3f9c7369
DS
4587/*
4588 * bgp_announce_route
4589 *
4590 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4591 */
d62a17ae 4592void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4593{
4594 struct peer_af *paf;
4595 struct update_subgroup *subgrp;
4596
4597 paf = peer_af_find(peer, afi, safi);
4598 if (!paf)
4599 return;
4600 subgrp = PAF_SUBGRP(paf);
4601
4602 /*
4603 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4604 * or a refresh has already been triggered.
4605 */
4606 if (!subgrp || paf->t_announce_route)
4607 return;
4608
4609 /*
4610 * Start a timer to stagger/delay the announce. This serves
4611 * two purposes - announcement can potentially be combined for
4612 * multiple peers and the announcement doesn't happen in the
4613 * vty context.
4614 */
4615 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4616 (subgrp->peer_count == 1)
4617 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4618 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4619 &paf->t_announce_route);
3f9c7369
DS
4620}
4621
4622/*
4623 * Announce routes from all AF tables to a peer.
4624 *
4625 * This should ONLY be called when there is a need to refresh the
4626 * routes to the peer based on a policy change for this peer alone
4627 * or a route refresh request received from the peer.
4628 * The operation will result in splitting the peer from its existing
4629 * subgroups and putting it in new subgroups.
4630 */
d62a17ae 4631void bgp_announce_route_all(struct peer *peer)
718e3744 4632{
d62a17ae 4633 afi_t afi;
4634 safi_t safi;
4635
05c7a1cc
QY
4636 FOREACH_AFI_SAFI (afi, safi)
4637 bgp_announce_route(peer, afi, safi);
718e3744 4638}
6b0655a2 4639
46aeabed
LS
4640/* Flag or unflag bgp_dest to determine whether it should be treated by
4641 * bgp_soft_reconfig_table_task.
4642 * Flag if flag is true. Unflag if flag is false.
4643 */
4644static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4645{
4646 struct bgp_dest *dest;
4647 struct bgp_adj_in *ain;
4648
4649 if (!table)
4650 return;
4651
4652 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4653 for (ain = dest->adj_in; ain; ain = ain->next) {
4654 if (ain->peer != NULL)
4655 break;
4656 }
4657 if (flag && ain != NULL && ain->peer != NULL)
4658 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4659 else
4660 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4661 }
4662}
4663
4664static int bgp_soft_reconfig_table_update(struct peer *peer,
4665 struct bgp_dest *dest,
4666 struct bgp_adj_in *ain, afi_t afi,
4667 safi_t safi, struct prefix_rd *prd)
4668{
4669 struct bgp_path_info *pi;
4670 uint32_t num_labels = 0;
4671 mpls_label_t *label_pnt = NULL;
4672 struct bgp_route_evpn evpn;
4673
4674 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4675 if (pi->peer == peer)
4676 break;
4677
4678 if (pi && pi->extra)
4679 num_labels = pi->extra->num_labels;
4680 if (num_labels)
4681 label_pnt = &pi->extra->label[0];
4682 if (pi)
4683 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4684 sizeof(evpn));
4685 else
4686 memset(&evpn, 0, sizeof(evpn));
4687
4688 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4689 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4690 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4691 &evpn);
4692}
4693
d62a17ae 4694static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4695 struct bgp_table *table,
4696 struct prefix_rd *prd)
718e3744 4697{
d62a17ae 4698 int ret;
9bcb3eef 4699 struct bgp_dest *dest;
d62a17ae 4700 struct bgp_adj_in *ain;
718e3744 4701
d62a17ae 4702 if (!table)
4703 table = peer->bgp->rib[afi][safi];
718e3744 4704
9bcb3eef
DS
4705 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4706 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4707 if (ain->peer != peer)
4708 continue;
8692c506 4709
46aeabed
LS
4710 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4711 afi, safi, prd);
ea47320b
DL
4712
4713 if (ret < 0) {
9bcb3eef 4714 bgp_dest_unlock_node(dest);
ea47320b 4715 return;
d62a17ae 4716 }
4717 }
718e3744 4718}
4719
46aeabed
LS
4720/* Do soft reconfig table per bgp table.
4721 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4722 * when BGP_NODE_SOFT_RECONFIG is set,
4723 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4724 * Schedule a new thread to continue the job.
4725 * Without splitting the full job into several part,
4726 * vtysh waits for the job to finish before responding to a BGP command
4727 */
4728static int bgp_soft_reconfig_table_task(struct thread *thread)
4729{
4730 uint32_t iter, max_iter;
4731 int ret;
4732 struct bgp_dest *dest;
4733 struct bgp_adj_in *ain;
4734 struct peer *peer;
4735 struct bgp_table *table;
4736 struct prefix_rd *prd;
4737 struct listnode *node, *nnode;
4738
4739 table = THREAD_ARG(thread);
4740 prd = NULL;
4741
4742 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4743 if (table->soft_reconfig_init) {
4744 /* first call of the function with a new srta structure.
4745 * Don't do any treatment this time on nodes
4746 * in order vtysh to respond quickly
4747 */
4748 max_iter = 0;
4749 }
4750
4751 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4752 dest = bgp_route_next(dest)) {
4753 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4754 continue;
4755
4756 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4757
4758 for (ain = dest->adj_in; ain; ain = ain->next) {
4759 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4760 nnode, peer)) {
4761 if (ain->peer != peer)
4762 continue;
4763
4764 ret = bgp_soft_reconfig_table_update(
4765 peer, dest, ain, table->afi,
4766 table->safi, prd);
4767 iter++;
4768
4769 if (ret < 0) {
4770 bgp_dest_unlock_node(dest);
4771 listnode_delete(
4772 table->soft_reconfig_peers,
4773 peer);
4774 bgp_announce_route(peer, table->afi,
4775 table->safi);
4776 if (list_isempty(
4777 table->soft_reconfig_peers)) {
4778 list_delete(
4779 &table->soft_reconfig_peers);
4780 bgp_soft_reconfig_table_flag(
4781 table, false);
4782 return 0;
4783 }
4784 }
4785 }
4786 }
4787 }
4788
4789 /* we're either starting the initial iteration,
4790 * or we're going to continue an ongoing iteration
4791 */
4792 if (dest || table->soft_reconfig_init) {
4793 table->soft_reconfig_init = false;
4794 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4795 table, 0, &table->soft_reconfig_thread);
4796 return 0;
4797 }
4798 /* we're done, clean up the background iteration context info and
4799 schedule route annoucement
4800 */
4801 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4802 listnode_delete(table->soft_reconfig_peers, peer);
4803 bgp_announce_route(peer, table->afi, table->safi);
4804 }
4805
4806 list_delete(&table->soft_reconfig_peers);
4807
4808 return 0;
4809}
4810
4811
4812/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4813 * and peer.
4814 * - bgp cannot be NULL
4815 * - if table and peer are NULL, cancel all threads within the bgp instance
4816 * - if table is NULL and peer is not,
4817 * remove peer in all threads within the bgp instance
4818 * - if peer is NULL, cancel all threads matching table within the bgp instance
4819 */
4820void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4821 const struct bgp_table *table,
4822 const struct peer *peer)
4823{
4824 struct peer *npeer;
4825 struct listnode *node, *nnode;
4826 int afi, safi;
4827 struct bgp_table *ntable;
4828
4829 if (!bgp)
4830 return;
4831
4832 FOREACH_AFI_SAFI (afi, safi) {
4833 ntable = bgp->rib[afi][safi];
4834 if (!ntable)
4835 continue;
4836 if (table && table != ntable)
4837 continue;
4838
4839 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4840 npeer)) {
4841 if (peer && peer != npeer)
4842 continue;
4843 listnode_delete(ntable->soft_reconfig_peers, npeer);
4844 }
4845
4846 if (!ntable->soft_reconfig_peers
4847 || !list_isempty(ntable->soft_reconfig_peers))
4848 continue;
4849
4850 list_delete(&ntable->soft_reconfig_peers);
4851 bgp_soft_reconfig_table_flag(ntable, false);
4852 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4853 }
4854}
4855
d62a17ae 4856void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4857{
9bcb3eef 4858 struct bgp_dest *dest;
d62a17ae 4859 struct bgp_table *table;
46aeabed
LS
4860 struct listnode *node, *nnode;
4861 struct peer *npeer;
4862 struct peer_af *paf;
718e3744 4863
feb17238 4864 if (!peer_established(peer))
d62a17ae 4865 return;
718e3744 4866
d62a17ae 4867 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
4868 && (safi != SAFI_EVPN)) {
4869 table = peer->bgp->rib[afi][safi];
4870 if (!table)
4871 return;
4872
4873 table->soft_reconfig_init = true;
4874
4875 if (!table->soft_reconfig_peers)
4876 table->soft_reconfig_peers = list_new();
4877 npeer = NULL;
4878 /* add peer to the table soft_reconfig_peers if not already
4879 * there
4880 */
4881 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
4882 npeer)) {
4883 if (peer == npeer)
4884 break;
4885 }
4886 if (peer != npeer)
4887 listnode_add(table->soft_reconfig_peers, peer);
4888
4889 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4890 * on table would start back at the beginning.
4891 */
4892 bgp_soft_reconfig_table_flag(table, true);
4893
4894 if (!table->soft_reconfig_thread)
4895 thread_add_event(bm->master,
4896 bgp_soft_reconfig_table_task, table, 0,
4897 &table->soft_reconfig_thread);
4898 /* Cancel bgp_announce_route_timer_expired threads.
4899 * bgp_announce_route_timer_expired threads have been scheduled
4900 * to announce routes as soon as the soft_reconfigure process
4901 * finishes.
4902 * In this case, soft_reconfigure is also scheduled by using
4903 * a thread but is planned after the
4904 * bgp_announce_route_timer_expired threads. It means that,
4905 * without cancelling the threads, the route announcement task
4906 * would run before the soft reconfiguration one. That would
4907 * useless and would block vtysh during several seconds. Route
4908 * announcements are rescheduled as soon as the soft_reconfigure
4909 * process finishes.
4910 */
4911 paf = peer_af_find(peer, afi, safi);
4912 if (paf)
4913 bgp_stop_announce_route_timer(paf);
4914 } else
9bcb3eef
DS
4915 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4916 dest = bgp_route_next(dest)) {
4917 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4918
b54892e0
DS
4919 if (table == NULL)
4920 continue;
8692c506 4921
9bcb3eef 4922 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4923 struct prefix_rd prd;
4924
4925 prd.family = AF_UNSPEC;
4926 prd.prefixlen = 64;
4927 memcpy(&prd.val, p->u.val, 8);
4928
4929 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4930 }
718e3744 4931}
6b0655a2 4932
228da428 4933
d62a17ae 4934struct bgp_clear_node_queue {
9bcb3eef 4935 struct bgp_dest *dest;
228da428
CC
4936};
4937
d62a17ae 4938static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4939{
d62a17ae 4940 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4941 struct bgp_dest *dest = cnq->dest;
d62a17ae 4942 struct peer *peer = wq->spec.data;
40381db7 4943 struct bgp_path_info *pi;
3103e8d2 4944 struct bgp *bgp;
9bcb3eef
DS
4945 afi_t afi = bgp_dest_table(dest)->afi;
4946 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4947
9bcb3eef 4948 assert(dest && peer);
3103e8d2 4949 bgp = peer->bgp;
d62a17ae 4950
4951 /* It is possible that we have multiple paths for a prefix from a peer
4952 * if that peer is using AddPath.
4953 */
9bcb3eef 4954 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4955 if (pi->peer != peer)
ea47320b
DL
4956 continue;
4957
4958 /* graceful restart STALE flag set. */
9af52ccf
DA
4959 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4960 && peer->nsf[afi][safi])
4961 || CHECK_FLAG(peer->af_sflags[afi][safi],
4962 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4963 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4964 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4965 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4966 else {
4967 /* If this is an EVPN route, process for
4968 * un-import. */
4969 if (safi == SAFI_EVPN)
9bcb3eef
DS
4970 bgp_evpn_unimport_route(
4971 bgp, afi, safi,
4972 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4973 /* Handle withdraw for VRF route-leaking and L3VPN */
4974 if (SAFI_UNICAST == safi
4975 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4976 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4977 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4978 bgp, pi);
960035b2 4979 }
3103e8d2 4980 if (SAFI_MPLS_VPN == safi &&
960035b2 4981 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4982 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4983 }
3103e8d2 4984
9bcb3eef 4985 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4986 }
ea47320b 4987 }
d62a17ae 4988 return WQ_SUCCESS;
200df115 4989}
4990
d62a17ae 4991static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4992{
d62a17ae 4993 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4994 struct bgp_dest *dest = cnq->dest;
4995 struct bgp_table *table = bgp_dest_table(dest);
228da428 4996
9bcb3eef 4997 bgp_dest_unlock_node(dest);
d62a17ae 4998 bgp_table_unlock(table);
4999 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5000}
5001
d62a17ae 5002static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5003{
d62a17ae 5004 struct peer *peer = wq->spec.data;
64e580a7 5005
d62a17ae 5006 /* Tickle FSM to start moving again */
5007 BGP_EVENT_ADD(peer, Clearing_Completed);
5008
5009 peer_unlock(peer); /* bgp_clear_route */
200df115 5010}
718e3744 5011
d62a17ae 5012static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5013{
d62a17ae 5014 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5015
5016 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5017#undef CLEAR_QUEUE_NAME_LEN
5018
0ce1ca80 5019 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5020 peer->clear_node_queue->spec.hold = 10;
5021 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5022 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5023 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5024 peer->clear_node_queue->spec.max_retries = 0;
5025
5026 /* we only 'lock' this peer reference when the queue is actually active
5027 */
5028 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5029}
5030
d62a17ae 5031static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5032 struct bgp_table *table)
65ca75e0 5033{
9bcb3eef 5034 struct bgp_dest *dest;
b6c386bb 5035 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5036
d62a17ae 5037 if (!table)
5038 table = peer->bgp->rib[afi][safi];
dc83d712 5039
d62a17ae 5040 /* If still no table => afi/safi isn't configured at all or smth. */
5041 if (!table)
5042 return;
dc83d712 5043
9bcb3eef 5044 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5045 struct bgp_path_info *pi, *next;
d62a17ae 5046 struct bgp_adj_in *ain;
5047 struct bgp_adj_in *ain_next;
5048
5049 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5050 * queued for every clearing peer, regardless of whether it is
5051 * relevant to the peer at hand.
5052 *
5053 * Overview: There are 3 different indices which need to be
5054 * scrubbed, potentially, when a peer is removed:
5055 *
5056 * 1 peer's routes visible via the RIB (ie accepted routes)
5057 * 2 peer's routes visible by the (optional) peer's adj-in index
5058 * 3 other routes visible by the peer's adj-out index
5059 *
5060 * 3 there is no hurry in scrubbing, once the struct peer is
5061 * removed from bgp->peer, we could just GC such deleted peer's
5062 * adj-outs at our leisure.
5063 *
5064 * 1 and 2 must be 'scrubbed' in some way, at least made
5065 * invisible via RIB index before peer session is allowed to be
5066 * brought back up. So one needs to know when such a 'search' is
5067 * complete.
5068 *
5069 * Ideally:
5070 *
5071 * - there'd be a single global queue or a single RIB walker
5072 * - rather than tracking which route_nodes still need to be
5073 * examined on a peer basis, we'd track which peers still
5074 * aren't cleared
5075 *
5076 * Given that our per-peer prefix-counts now should be reliable,
5077 * this may actually be achievable. It doesn't seem to be a huge
5078 * problem at this time,
5079 *
5080 * It is possible that we have multiple paths for a prefix from
5081 * a peer
5082 * if that peer is using AddPath.
5083 */
9bcb3eef 5084 ain = dest->adj_in;
d62a17ae 5085 while (ain) {
5086 ain_next = ain->next;
5087
6a840fd9 5088 if (ain->peer == peer)
9bcb3eef 5089 bgp_adj_in_remove(dest, ain);
d62a17ae 5090
5091 ain = ain_next;
5092 }
5093
9bcb3eef 5094 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5095 next = pi->next;
5096 if (pi->peer != peer)
d62a17ae 5097 continue;
5098
5099 if (force)
9bcb3eef 5100 bgp_path_info_reap(dest, pi);
d62a17ae 5101 else {
5102 struct bgp_clear_node_queue *cnq;
5103
5104 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5105 bgp_table_lock(bgp_dest_table(dest));
5106 bgp_dest_lock_node(dest);
d62a17ae 5107 cnq = XCALLOC(
5108 MTYPE_BGP_CLEAR_NODE_QUEUE,
5109 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5110 cnq->dest = dest;
d62a17ae 5111 work_queue_add(peer->clear_node_queue, cnq);
5112 break;
5113 }
5114 }
5115 }
5116 return;
5117}
5118
5119void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5120{
9bcb3eef 5121 struct bgp_dest *dest;
d62a17ae 5122 struct bgp_table *table;
5123
5124 if (peer->clear_node_queue == NULL)
5125 bgp_clear_node_queue_init(peer);
5126
5127 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5128 * Idle until it receives a Clearing_Completed event. This protects
5129 * against peers which flap faster than we can we clear, which could
5130 * lead to:
5131 *
5132 * a) race with routes from the new session being installed before
5133 * clear_route_node visits the node (to delete the route of that
5134 * peer)
5135 * b) resource exhaustion, clear_route_node likely leads to an entry
5136 * on the process_main queue. Fast-flapping could cause that queue
5137 * to grow and grow.
5138 */
5139
5140 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5141 * the unlock will happen upon work-queue completion; other wise, the
5142 * unlock happens at the end of this function.
5143 */
5144 if (!peer->clear_node_queue->thread)
5145 peer_lock(peer);
5146
5147 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5148 bgp_clear_route_table(peer, afi, safi, NULL);
5149 else
9bcb3eef
DS
5150 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5151 dest = bgp_route_next(dest)) {
5152 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5153 if (!table)
5154 continue;
5155
5156 bgp_clear_route_table(peer, afi, safi, table);
5157 }
d62a17ae 5158
5159 /* unlock if no nodes got added to the clear-node-queue. */
5160 if (!peer->clear_node_queue->thread)
5161 peer_unlock(peer);
718e3744 5162}
d62a17ae 5163
5164void bgp_clear_route_all(struct peer *peer)
718e3744 5165{
d62a17ae 5166 afi_t afi;
5167 safi_t safi;
718e3744 5168
05c7a1cc
QY
5169 FOREACH_AFI_SAFI (afi, safi)
5170 bgp_clear_route(peer, afi, safi);
65efcfce 5171
49e5a4a0 5172#ifdef ENABLE_BGP_VNC
d62a17ae 5173 rfapiProcessPeerDown(peer);
65efcfce 5174#endif
718e3744 5175}
5176
d62a17ae 5177void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5178{
d62a17ae 5179 struct bgp_table *table;
9bcb3eef 5180 struct bgp_dest *dest;
d62a17ae 5181 struct bgp_adj_in *ain;
5182 struct bgp_adj_in *ain_next;
718e3744 5183
d62a17ae 5184 table = peer->bgp->rib[afi][safi];
718e3744 5185
d62a17ae 5186 /* It is possible that we have multiple paths for a prefix from a peer
5187 * if that peer is using AddPath.
5188 */
9bcb3eef
DS
5189 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5190 ain = dest->adj_in;
43143c8f 5191
d62a17ae 5192 while (ain) {
5193 ain_next = ain->next;
43143c8f 5194
6a840fd9 5195 if (ain->peer == peer)
9bcb3eef 5196 bgp_adj_in_remove(dest, ain);
43143c8f 5197
d62a17ae 5198 ain = ain_next;
5199 }
5200 }
718e3744 5201}
93406d87 5202
d62a17ae 5203void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5204{
9bcb3eef 5205 struct bgp_dest *dest;
40381db7 5206 struct bgp_path_info *pi;
d62a17ae 5207 struct bgp_table *table;
5208
9af52ccf 5209 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5210 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5211 dest = bgp_route_next(dest)) {
5212 struct bgp_dest *rm;
d62a17ae 5213
5214 /* look for neighbor in tables */
9bcb3eef 5215 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5216 if (!table)
ea47320b
DL
5217 continue;
5218
5219 for (rm = bgp_table_top(table); rm;
5220 rm = bgp_route_next(rm))
9bcb3eef 5221 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5222 pi = pi->next) {
40381db7 5223 if (pi->peer != peer)
ea47320b 5224 continue;
40381db7 5225 if (!CHECK_FLAG(pi->flags,
1defdda8 5226 BGP_PATH_STALE))
ea47320b
DL
5227 break;
5228
40381db7 5229 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5230 break;
5231 }
d62a17ae 5232 }
5233 } else {
9bcb3eef
DS
5234 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5235 dest = bgp_route_next(dest))
5236 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5237 pi = pi->next) {
40381db7 5238 if (pi->peer != peer)
ea47320b 5239 continue;
40381db7 5240 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5241 break;
9bcb3eef 5242 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5243 break;
5244 }
d62a17ae 5245 }
93406d87 5246}
6b0655a2 5247
9af52ccf
DA
5248void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5249{
5250 struct bgp_dest *dest, *ndest;
5251 struct bgp_path_info *pi;
5252 struct bgp_table *table;
5253
5254 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5255 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5256 dest = bgp_route_next(dest)) {
5257 table = bgp_dest_get_bgp_table_info(dest);
5258 if (!table)
5259 continue;
5260
5261 for (ndest = bgp_table_top(table); ndest;
5262 ndest = bgp_route_next(ndest)) {
5263 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5264 pi = pi->next) {
5265 if (pi->peer != peer)
5266 continue;
5267
5268 if ((CHECK_FLAG(
5269 peer->af_sflags[afi][safi],
5270 PEER_STATUS_ENHANCED_REFRESH))
5271 && !CHECK_FLAG(pi->flags,
5272 BGP_PATH_STALE)
5273 && !CHECK_FLAG(
5274 pi->flags,
5275 BGP_PATH_UNUSEABLE)) {
5276 if (bgp_debug_neighbor_events(
5277 peer))
5278 zlog_debug(
5279 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5280 peer->host,
5281 afi2str(afi),
5282 safi2str(safi),
5283 bgp_dest_get_prefix(
5284 ndest));
5285
5286 bgp_path_info_set_flag(
5287 ndest, pi,
5288 BGP_PATH_STALE);
5289 }
5290 }
5291 }
5292 }
5293 } else {
5294 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5295 dest = bgp_route_next(dest)) {
5296 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5297 pi = pi->next) {
5298 if (pi->peer != peer)
5299 continue;
5300
5301 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5302 PEER_STATUS_ENHANCED_REFRESH))
5303 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5304 && !CHECK_FLAG(pi->flags,
5305 BGP_PATH_UNUSEABLE)) {
5306 if (bgp_debug_neighbor_events(peer))
5307 zlog_debug(
5308 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5309 peer->host,
5310 afi2str(afi),
5311 safi2str(safi),
5312 bgp_dest_get_prefix(
5313 dest));
5314
5315 bgp_path_info_set_flag(dest, pi,
5316 BGP_PATH_STALE);
5317 }
5318 }
5319 }
5320 }
5321}
5322
3dc339cd 5323bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5324{
e0df4c04 5325 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5326 return true;
e0df4c04 5327
9dac9fc8
DA
5328 if (peer->sort == BGP_PEER_EBGP
5329 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5330 || FILTER_LIST_OUT_NAME(filter)
5331 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5332 return true;
5333 return false;
9dac9fc8
DA
5334}
5335
3dc339cd 5336bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5337{
e0df4c04 5338 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5339 return true;
e0df4c04 5340
9dac9fc8
DA
5341 if (peer->sort == BGP_PEER_EBGP
5342 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5343 || FILTER_LIST_IN_NAME(filter)
5344 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5345 return true;
5346 return false;
9dac9fc8
DA
5347}
5348
568e10ca 5349static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5350 safi_t safi)
bb86c601 5351{
9bcb3eef 5352 struct bgp_dest *dest;
40381db7 5353 struct bgp_path_info *pi;
4b7e6066 5354 struct bgp_path_info *next;
bb86c601 5355
9bcb3eef
DS
5356 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5357 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5358 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5359
40381db7 5360 next = pi->next;
1b7bb747
CS
5361
5362 /* Unimport EVPN routes from VRFs */
5363 if (safi == SAFI_EVPN)
5364 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5365 SAFI_EVPN, p, pi);
1b7bb747 5366
40381db7
DS
5367 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5368 && pi->type == ZEBRA_ROUTE_BGP
5369 && (pi->sub_type == BGP_ROUTE_NORMAL
5370 || pi->sub_type == BGP_ROUTE_AGGREGATE
5371 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5372
d62a17ae 5373 if (bgp_fibupd_safi(safi))
b54892e0 5374 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5375 }
9514b37d 5376
9bcb3eef 5377 bgp_path_info_reap(dest, pi);
d62a17ae 5378 }
bb86c601
LB
5379}
5380
718e3744 5381/* Delete all kernel routes. */
d62a17ae 5382void bgp_cleanup_routes(struct bgp *bgp)
5383{
5384 afi_t afi;
9bcb3eef 5385 struct bgp_dest *dest;
67009e22 5386 struct bgp_table *table;
d62a17ae 5387
5388 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5389 if (afi == AFI_L2VPN)
5390 continue;
568e10ca 5391 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5392 SAFI_UNICAST);
d62a17ae 5393 /*
5394 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5395 */
5396 if (afi != AFI_L2VPN) {
5397 safi_t safi;
5398 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5399 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5400 dest = bgp_route_next(dest)) {
5401 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5402 if (table != NULL) {
5403 bgp_cleanup_table(bgp, table, safi);
5404 bgp_table_finish(&table);
9bcb3eef
DS
5405 bgp_dest_set_bgp_table_info(dest, NULL);
5406 bgp_dest_unlock_node(dest);
d62a17ae 5407 }
5408 }
5409 safi = SAFI_ENCAP;
9bcb3eef
DS
5410 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5411 dest = bgp_route_next(dest)) {
5412 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5413 if (table != NULL) {
5414 bgp_cleanup_table(bgp, table, safi);
5415 bgp_table_finish(&table);
9bcb3eef
DS
5416 bgp_dest_set_bgp_table_info(dest, NULL);
5417 bgp_dest_unlock_node(dest);
d62a17ae 5418 }
5419 }
5420 }
5421 }
9bcb3eef
DS
5422 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5423 dest = bgp_route_next(dest)) {
5424 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5425 if (table != NULL) {
5426 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5427 bgp_table_finish(&table);
9bcb3eef
DS
5428 bgp_dest_set_bgp_table_info(dest, NULL);
5429 bgp_dest_unlock_node(dest);
d62a17ae 5430 }
bb86c601 5431 }
718e3744 5432}
5433
d62a17ae 5434void bgp_reset(void)
718e3744 5435{
d62a17ae 5436 vty_reset();
5437 bgp_zclient_reset();
5438 access_list_reset();
5439 prefix_list_reset();
718e3744 5440}
6b0655a2 5441
d62a17ae 5442static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5443{
d62a17ae 5444 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5445 && CHECK_FLAG(peer->af_cap[afi][safi],
5446 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5447}
5448
718e3744 5449/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5450 value. */
d62a17ae 5451int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5452 struct bgp_nlri *packet)
5453{
d7c0a89a
QY
5454 uint8_t *pnt;
5455 uint8_t *lim;
d62a17ae 5456 struct prefix p;
5457 int psize;
5458 int ret;
5459 afi_t afi;
5460 safi_t safi;
5461 int addpath_encoded;
d7c0a89a 5462 uint32_t addpath_id;
d62a17ae 5463
d62a17ae 5464 pnt = packet->nlri;
5465 lim = pnt + packet->length;
5466 afi = packet->afi;
5467 safi = packet->safi;
5468 addpath_id = 0;
5469 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5470
5471 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5472 syntactic validity. If the field is syntactically incorrect,
5473 then the Error Subcode is set to Invalid Network Field. */
5474 for (; pnt < lim; pnt += psize) {
5475 /* Clear prefix structure. */
5476 memset(&p, 0, sizeof(struct prefix));
5477
5478 if (addpath_encoded) {
5479
5480 /* When packet overflow occurs return immediately. */
761ed665 5481 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5482 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5483
a3a850a1 5484 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5485 addpath_id = ntohl(addpath_id);
d62a17ae 5486 pnt += BGP_ADDPATH_ID_LEN;
5487 }
718e3744 5488
d62a17ae 5489 /* Fetch prefix length. */
5490 p.prefixlen = *pnt++;
5491 /* afi/safi validity already verified by caller,
5492 * bgp_update_receive */
5493 p.family = afi2family(afi);
5494
5495 /* Prefix length check. */
5496 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5497 flog_err(
e50f7cfd 5498 EC_BGP_UPDATE_RCV,
14454c9f 5499 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5500 peer->host, p.prefixlen, packet->afi);
513386b5 5501 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5502 }
6b0655a2 5503
d62a17ae 5504 /* Packet size overflow check. */
5505 psize = PSIZE(p.prefixlen);
5506
5507 /* When packet overflow occur return immediately. */
5508 if (pnt + psize > lim) {
af4c2728 5509 flog_err(
e50f7cfd 5510 EC_BGP_UPDATE_RCV,
d62a17ae 5511 "%s [Error] Update packet error (prefix length %d overflows packet)",
5512 peer->host, p.prefixlen);
513386b5 5513 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5514 }
5515
5516 /* Defensive coding, double-check the psize fits in a struct
5517 * prefix */
5518 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5519 flog_err(
e50f7cfd 5520 EC_BGP_UPDATE_RCV,
d62a17ae 5521 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5522 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5523 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5524 }
5525
5526 /* Fetch prefix from NLRI packet. */
a85297a7 5527 memcpy(p.u.val, pnt, psize);
d62a17ae 5528
5529 /* Check address. */
5530 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5531 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5532 /* From RFC4271 Section 6.3:
5533 *
5534 * If a prefix in the NLRI field is semantically
5535 * incorrect
5536 * (e.g., an unexpected multicast IP address),
5537 * an error SHOULD
5538 * be logged locally, and the prefix SHOULD be
5539 * ignored.
a4d82a8a 5540 */
af4c2728 5541 flog_err(
e50f7cfd 5542 EC_BGP_UPDATE_RCV,
23d0a753
DA
5543 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5544 peer->host, &p.u.prefix4);
d62a17ae 5545 continue;
5546 }
5547 }
5548
5549 /* Check address. */
5550 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5551 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5552 flog_err(
e50f7cfd 5553 EC_BGP_UPDATE_RCV,
c0d72166
DS
5554 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5555 peer->host, &p.u.prefix6);
d62a17ae 5556
5557 continue;
5558 }
5559 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5560 flog_err(
e50f7cfd 5561 EC_BGP_UPDATE_RCV,
c0d72166
DS
5562 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5563 peer->host, &p.u.prefix6);
d62a17ae 5564
5565 continue;
5566 }
5567 }
5568
5569 /* Normal process. */
5570 if (attr)
5571 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5572 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5573 NULL, NULL, 0, 0, NULL);
d62a17ae 5574 else
5575 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5576 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5577 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5578 NULL);
d62a17ae 5579
513386b5
DA
5580 /* Do not send BGP notification twice when maximum-prefix count
5581 * overflow. */
5582 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5583 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5584
5585 /* Address family configuration mismatch. */
d62a17ae 5586 if (ret < 0)
513386b5 5587 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5588 }
5589
5590 /* Packet length consistency check. */
5591 if (pnt != lim) {
af4c2728 5592 flog_err(
e50f7cfd 5593 EC_BGP_UPDATE_RCV,
d62a17ae 5594 "%s [Error] Update packet error (prefix length mismatch with total length)",
5595 peer->host);
513386b5 5596 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5597 }
6b0655a2 5598
513386b5 5599 return BGP_NLRI_PARSE_OK;
718e3744 5600}
5601
d62a17ae 5602static struct bgp_static *bgp_static_new(void)
718e3744 5603{
d62a17ae 5604 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5605}
5606
d62a17ae 5607static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5608{
0a22ddfb 5609 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5610 route_map_counter_decrement(bgp_static->rmap.map);
5611
0a22ddfb 5612 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5613 XFREE(MTYPE_BGP_STATIC, bgp_static);
5614}
5615
5f040085 5616void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5617 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5618{
9bcb3eef 5619 struct bgp_dest *dest;
40381db7 5620 struct bgp_path_info *pi;
4b7e6066 5621 struct bgp_path_info *new;
40381db7 5622 struct bgp_path_info rmap_path;
d62a17ae 5623 struct attr attr;
5624 struct attr *attr_new;
b68885f9 5625 route_map_result_t ret;
49e5a4a0 5626#ifdef ENABLE_BGP_VNC
d62a17ae 5627 int vnc_implicit_withdraw = 0;
65efcfce 5628#endif
fee0f4c6 5629
d62a17ae 5630 assert(bgp_static);
dd8103a9 5631
9bcb3eef 5632 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5633
d62a17ae 5634 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5635
d62a17ae 5636 attr.nexthop = bgp_static->igpnexthop;
5637 attr.med = bgp_static->igpmetric;
5638 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5639
d62a17ae 5640 if (bgp_static->atomic)
5641 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5642
d62a17ae 5643 /* Store label index, if required. */
5644 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5645 attr.label_index = bgp_static->label_index;
5646 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5647 }
718e3744 5648
d62a17ae 5649 /* Apply route-map. */
5650 if (bgp_static->rmap.name) {
5651 struct attr attr_tmp = attr;
80ced710 5652
40381db7
DS
5653 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5654 rmap_path.peer = bgp->peer_self;
5655 rmap_path.attr = &attr_tmp;
fee0f4c6 5656
d62a17ae 5657 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5658
1782514f 5659 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5660
d62a17ae 5661 bgp->peer_self->rmap_type = 0;
718e3744 5662
d62a17ae 5663 if (ret == RMAP_DENYMATCH) {
5664 /* Free uninterned attribute. */
5665 bgp_attr_flush(&attr_tmp);
718e3744 5666
d62a17ae 5667 /* Unintern original. */
5668 aspath_unintern(&attr.aspath);
5669 bgp_static_withdraw(bgp, p, afi, safi);
5670 return;
5671 }
7f323236 5672
637e5ba4 5673 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5674 bgp_attr_add_gshut_community(&attr_tmp);
5675
d62a17ae 5676 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5677 } else {
5678
637e5ba4 5679 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5680 bgp_attr_add_gshut_community(&attr);
5681
d62a17ae 5682 attr_new = bgp_attr_intern(&attr);
7f323236 5683 }
718e3744 5684
9bcb3eef 5685 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5686 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5687 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5688 break;
5689
40381db7
DS
5690 if (pi) {
5691 if (attrhash_cmp(pi->attr, attr_new)
5692 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5693 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5694 bgp_dest_unlock_node(dest);
d62a17ae 5695 bgp_attr_unintern(&attr_new);
5696 aspath_unintern(&attr.aspath);
5697 return;
5698 } else {
5699 /* The attribute is changed. */
9bcb3eef 5700 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5701
5702 /* Rewrite BGP route information. */
40381db7 5703 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5704 bgp_path_info_restore(dest, pi);
d62a17ae 5705 else
40381db7 5706 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5707#ifdef ENABLE_BGP_VNC
d62a17ae 5708 if ((afi == AFI_IP || afi == AFI_IP6)
5709 && (safi == SAFI_UNICAST)) {
40381db7 5710 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5711 /*
5712 * Implicit withdraw case.
40381db7 5713 * We have to do this before pi is
d62a17ae 5714 * changed
5715 */
5716 ++vnc_implicit_withdraw;
40381db7 5717 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5718 vnc_import_bgp_exterior_del_route(
40381db7 5719 bgp, p, pi);
d62a17ae 5720 }
5721 }
65efcfce 5722#endif
40381db7
DS
5723 bgp_attr_unintern(&pi->attr);
5724 pi->attr = attr_new;
5725 pi->uptime = bgp_clock();
49e5a4a0 5726#ifdef ENABLE_BGP_VNC
d62a17ae 5727 if ((afi == AFI_IP || afi == AFI_IP6)
5728 && (safi == SAFI_UNICAST)) {
5729 if (vnc_implicit_withdraw) {
40381db7 5730 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5731 vnc_import_bgp_exterior_add_route(
40381db7 5732 bgp, p, pi);
d62a17ae 5733 }
5734 }
65efcfce 5735#endif
718e3744 5736
d62a17ae 5737 /* Nexthop reachability check. */
892fedb6 5738 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5739 && (safi == SAFI_UNICAST
5740 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5741
5742 struct bgp *bgp_nexthop = bgp;
5743
40381db7
DS
5744 if (pi->extra && pi->extra->bgp_orig)
5745 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5746
5747 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5748 afi, safi, pi, NULL,
654a5978 5749 0, p))
9bcb3eef 5750 bgp_path_info_set_flag(dest, pi,
18ee8310 5751 BGP_PATH_VALID);
d62a17ae 5752 else {
5753 if (BGP_DEBUG(nht, NHT)) {
5754 char buf1[INET6_ADDRSTRLEN];
5755 inet_ntop(p->family,
5756 &p->u.prefix, buf1,
5757 INET6_ADDRSTRLEN);
5758 zlog_debug(
5759 "%s(%s): Route not in table, not advertising",
15569c58 5760 __func__, buf1);
d62a17ae 5761 }
18ee8310 5762 bgp_path_info_unset_flag(
9bcb3eef 5763 dest, pi, BGP_PATH_VALID);
d62a17ae 5764 }
5765 } else {
5766 /* Delete the NHT structure if any, if we're
5767 * toggling between
5768 * enabling/disabling import check. We
5769 * deregister the route
5770 * from NHT to avoid overloading NHT and the
5771 * process interaction
5772 */
40381db7 5773 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5774 bgp_path_info_set_flag(dest, pi,
5775 BGP_PATH_VALID);
d62a17ae 5776 }
5777 /* Process change. */
40381db7 5778 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5779 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5780
5781 if (SAFI_UNICAST == safi
5782 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5783 || bgp->inst_type
5784 == BGP_INSTANCE_TYPE_DEFAULT)) {
5785 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5786 pi);
ddb5b488
PZ
5787 }
5788
9bcb3eef 5789 bgp_dest_unlock_node(dest);
d62a17ae 5790 aspath_unintern(&attr.aspath);
5791 return;
5792 }
718e3744 5793 }
718e3744 5794
d62a17ae 5795 /* Make new BGP info. */
5796 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5797 attr_new, dest);
d62a17ae 5798 /* Nexthop reachability check. */
892fedb6 5799 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5800 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5801 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5802 p))
9bcb3eef 5803 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5804 else {
5805 if (BGP_DEBUG(nht, NHT)) {
5806 char buf1[INET6_ADDRSTRLEN];
5807 inet_ntop(p->family, &p->u.prefix, buf1,
5808 INET6_ADDRSTRLEN);
5809 zlog_debug(
5810 "%s(%s): Route not in table, not advertising",
15569c58 5811 __func__, buf1);
d62a17ae 5812 }
9bcb3eef 5813 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5814 }
5815 } else {
5816 /* Delete the NHT structure if any, if we're toggling between
5817 * enabling/disabling import check. We deregister the route
5818 * from NHT to avoid overloading NHT and the process interaction
5819 */
5820 bgp_unlink_nexthop(new);
5821
9bcb3eef 5822 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5823 }
078430f6 5824
d62a17ae 5825 /* Aggregate address increment. */
5826 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5827
d62a17ae 5828 /* Register new BGP information. */
9bcb3eef 5829 bgp_path_info_add(dest, new);
718e3744 5830
d62a17ae 5831 /* route_node_get lock */
9bcb3eef 5832 bgp_dest_unlock_node(dest);
d62a17ae 5833
5834 /* Process change. */
9bcb3eef 5835 bgp_process(bgp, dest, afi, safi);
d62a17ae 5836
ddb5b488
PZ
5837 if (SAFI_UNICAST == safi
5838 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5839 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5840 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5841 }
5842
d62a17ae 5843 /* Unintern original. */
5844 aspath_unintern(&attr.aspath);
718e3744 5845}
5846
5f040085 5847void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5848 safi_t safi)
718e3744 5849{
9bcb3eef 5850 struct bgp_dest *dest;
40381db7 5851 struct bgp_path_info *pi;
718e3744 5852
9bcb3eef 5853 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5854
d62a17ae 5855 /* Check selected route and self inserted route. */
9bcb3eef 5856 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5857 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5858 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5859 break;
5860
5861 /* Withdraw static BGP route from routing table. */
40381db7 5862 if (pi) {
ddb5b488
PZ
5863 if (SAFI_UNICAST == safi
5864 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5865 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5866 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5867 }
40381db7
DS
5868 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5869 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5870 bgp_path_info_delete(dest, pi);
5871 bgp_process(bgp, dest, afi, safi);
d62a17ae 5872 }
718e3744 5873
d62a17ae 5874 /* Unlock bgp_node_lookup. */
9bcb3eef 5875 bgp_dest_unlock_node(dest);
718e3744 5876}
5877
137446f9
LB
5878/*
5879 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5880 */
5f040085 5881static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5882 afi_t afi, safi_t safi,
5883 struct prefix_rd *prd)
718e3744 5884{
9bcb3eef 5885 struct bgp_dest *dest;
40381db7 5886 struct bgp_path_info *pi;
718e3744 5887
9bcb3eef 5888 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5889
d62a17ae 5890 /* Check selected route and self inserted route. */
9bcb3eef 5891 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5892 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5893 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5894 break;
718e3744 5895
d62a17ae 5896 /* Withdraw static BGP route from routing table. */
40381db7 5897 if (pi) {
49e5a4a0 5898#ifdef ENABLE_BGP_VNC
d62a17ae 5899 rfapiProcessWithdraw(
40381db7 5900 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5901 1); /* Kill, since it is an administrative change */
65efcfce 5902#endif
ddb5b488
PZ
5903 if (SAFI_MPLS_VPN == safi
5904 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5905 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5906 }
40381db7 5907 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5908 bgp_path_info_delete(dest, pi);
5909 bgp_process(bgp, dest, afi, safi);
d62a17ae 5910 }
718e3744 5911
d62a17ae 5912 /* Unlock bgp_node_lookup. */
9bcb3eef 5913 bgp_dest_unlock_node(dest);
718e3744 5914}
5915
5f040085 5916static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5917 struct bgp_static *bgp_static, afi_t afi,
5918 safi_t safi)
137446f9 5919{
9bcb3eef 5920 struct bgp_dest *dest;
4b7e6066 5921 struct bgp_path_info *new;
d62a17ae 5922 struct attr *attr_new;
5923 struct attr attr = {0};
40381db7 5924 struct bgp_path_info *pi;
49e5a4a0 5925#ifdef ENABLE_BGP_VNC
d62a17ae 5926 mpls_label_t label = 0;
65efcfce 5927#endif
d7c0a89a 5928 uint32_t num_labels = 0;
d62a17ae 5929 union gw_addr add;
137446f9 5930
d62a17ae 5931 assert(bgp_static);
137446f9 5932
b57ba6d2
MK
5933 if (bgp_static->label != MPLS_INVALID_LABEL)
5934 num_labels = 1;
9bcb3eef
DS
5935 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5936 &bgp_static->prd);
137446f9 5937
d62a17ae 5938 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5939
d62a17ae 5940 attr.nexthop = bgp_static->igpnexthop;
5941 attr.med = bgp_static->igpmetric;
5942 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5943
d62a17ae 5944 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5945 || (safi == SAFI_ENCAP)) {
5946 if (afi == AFI_IP) {
5947 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5948 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5949 }
5950 }
5951 if (afi == AFI_L2VPN) {
5952 if (bgp_static->gatewayIp.family == AF_INET)
5953 add.ipv4.s_addr =
5954 bgp_static->gatewayIp.u.prefix4.s_addr;
5955 else if (bgp_static->gatewayIp.family == AF_INET6)
5956 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5957 sizeof(struct in6_addr));
0a50c248 5958 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5959 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5960 struct bgp_encap_type_vxlan bet;
5961 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5962 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5963 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5964 }
5965 if (bgp_static->router_mac) {
5966 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5967 }
5968 }
5969 /* Apply route-map. */
5970 if (bgp_static->rmap.name) {
5971 struct attr attr_tmp = attr;
40381db7 5972 struct bgp_path_info rmap_path;
b68885f9 5973 route_map_result_t ret;
137446f9 5974
40381db7
DS
5975 rmap_path.peer = bgp->peer_self;
5976 rmap_path.attr = &attr_tmp;
137446f9 5977
d62a17ae 5978 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5979
1782514f 5980 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5981
d62a17ae 5982 bgp->peer_self->rmap_type = 0;
137446f9 5983
d62a17ae 5984 if (ret == RMAP_DENYMATCH) {
5985 /* Free uninterned attribute. */
5986 bgp_attr_flush(&attr_tmp);
137446f9 5987
d62a17ae 5988 /* Unintern original. */
5989 aspath_unintern(&attr.aspath);
5990 bgp_static_withdraw_safi(bgp, p, afi, safi,
5991 &bgp_static->prd);
5992 return;
5993 }
137446f9 5994
d62a17ae 5995 attr_new = bgp_attr_intern(&attr_tmp);
5996 } else {
5997 attr_new = bgp_attr_intern(&attr);
5998 }
137446f9 5999
9bcb3eef 6000 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6001 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6002 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6003 break;
6004
40381db7 6005 if (pi) {
d62a17ae 6006 memset(&add, 0, sizeof(union gw_addr));
40381db7 6007 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 6008 && overlay_index_equal(afi, pi, &add)
40381db7 6009 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6010 bgp_dest_unlock_node(dest);
d62a17ae 6011 bgp_attr_unintern(&attr_new);
6012 aspath_unintern(&attr.aspath);
6013 return;
6014 } else {
6015 /* The attribute is changed. */
9bcb3eef 6016 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6017
6018 /* Rewrite BGP route information. */
40381db7 6019 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6020 bgp_path_info_restore(dest, pi);
d62a17ae 6021 else
40381db7
DS
6022 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6023 bgp_attr_unintern(&pi->attr);
6024 pi->attr = attr_new;
6025 pi->uptime = bgp_clock();
49e5a4a0 6026#ifdef ENABLE_BGP_VNC
40381db7
DS
6027 if (pi->extra)
6028 label = decode_label(&pi->extra->label[0]);
65efcfce 6029#endif
137446f9 6030
d62a17ae 6031 /* Process change. */
40381db7 6032 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6033 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6034
6035 if (SAFI_MPLS_VPN == safi
6036 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6037 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6038 }
49e5a4a0 6039#ifdef ENABLE_BGP_VNC
40381db7
DS
6040 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6041 pi->attr, afi, safi, pi->type,
6042 pi->sub_type, &label);
65efcfce 6043#endif
9bcb3eef 6044 bgp_dest_unlock_node(dest);
d62a17ae 6045 aspath_unintern(&attr.aspath);
6046 return;
6047 }
6048 }
137446f9
LB
6049
6050
d62a17ae 6051 /* Make new BGP info. */
6052 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6053 attr_new, dest);
1defdda8 6054 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 6055 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
6056 if (num_labels) {
6057 new->extra->label[0] = bgp_static->label;
6058 new->extra->num_labels = num_labels;
6059 }
49e5a4a0 6060#ifdef ENABLE_BGP_VNC
d62a17ae 6061 label = decode_label(&bgp_static->label);
65efcfce 6062#endif
137446f9 6063
d62a17ae 6064 /* Aggregate address increment. */
6065 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6066
d62a17ae 6067 /* Register new BGP information. */
9bcb3eef 6068 bgp_path_info_add(dest, new);
d62a17ae 6069 /* route_node_get lock */
9bcb3eef 6070 bgp_dest_unlock_node(dest);
137446f9 6071
d62a17ae 6072 /* Process change. */
9bcb3eef 6073 bgp_process(bgp, dest, afi, safi);
137446f9 6074
ddb5b488
PZ
6075 if (SAFI_MPLS_VPN == safi
6076 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6077 vpn_leak_to_vrf_update(bgp, new);
6078 }
49e5a4a0 6079#ifdef ENABLE_BGP_VNC
d62a17ae 6080 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6081 safi, new->type, new->sub_type, &label);
65efcfce
LB
6082#endif
6083
d62a17ae 6084 /* Unintern original. */
6085 aspath_unintern(&attr.aspath);
137446f9
LB
6086}
6087
718e3744 6088/* Configure static BGP network. When user don't run zebra, static
6089 route should be installed as valid. */
585f1adc
IR
6090static int bgp_static_set(struct vty *vty, const char *negate,
6091 const char *ip_str, afi_t afi, safi_t safi,
6092 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6093{
585f1adc
IR
6094 VTY_DECLVAR_CONTEXT(bgp, bgp);
6095 int ret;
d62a17ae 6096 struct prefix p;
6097 struct bgp_static *bgp_static;
9bcb3eef 6098 struct bgp_dest *dest;
d7c0a89a 6099 uint8_t need_update = 0;
d62a17ae 6100
585f1adc
IR
6101 /* Convert IP prefix string to struct prefix. */
6102 ret = str2prefix(ip_str, &p);
6103 if (!ret) {
6104 vty_out(vty, "%% Malformed prefix\n");
6105 return CMD_WARNING_CONFIG_FAILED;
6106 }
6107 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6108 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6109 return CMD_WARNING_CONFIG_FAILED;
6110 }
6111
d62a17ae 6112 apply_mask(&p);
718e3744 6113
e2a86ad9 6114 if (negate) {
718e3744 6115
e2a86ad9 6116 /* Set BGP static route configuration. */
9bcb3eef 6117 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6118
9bcb3eef 6119 if (!dest) {
585f1adc
IR
6120 vty_out(vty, "%% Can't find static route specified\n");
6121 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6122 }
6123
9bcb3eef 6124 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6125
e2a86ad9
DS
6126 if ((label_index != BGP_INVALID_LABEL_INDEX)
6127 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6128 vty_out(vty,
6129 "%% label-index doesn't match static route\n");
70d9b134 6130 bgp_dest_unlock_node(dest);
585f1adc 6131 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6132 }
d62a17ae 6133
e2a86ad9
DS
6134 if ((rmap && bgp_static->rmap.name)
6135 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6136 vty_out(vty,
6137 "%% route-map name doesn't match static route\n");
70d9b134 6138 bgp_dest_unlock_node(dest);
585f1adc 6139 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6140 }
718e3744 6141
e2a86ad9
DS
6142 /* Update BGP RIB. */
6143 if (!bgp_static->backdoor)
6144 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6145
e2a86ad9
DS
6146 /* Clear configuration. */
6147 bgp_static_free(bgp_static);
9bcb3eef
DS
6148 bgp_dest_set_bgp_static_info(dest, NULL);
6149 bgp_dest_unlock_node(dest);
6150 bgp_dest_unlock_node(dest);
e2a86ad9 6151 } else {
718e3744 6152
e2a86ad9 6153 /* Set BGP static route configuration. */
9bcb3eef
DS
6154 dest = bgp_node_get(bgp->route[afi][safi], &p);
6155 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6156 if (bgp_static) {
e2a86ad9 6157 /* Configuration change. */
e2a86ad9
DS
6158 /* Label index cannot be changed. */
6159 if (bgp_static->label_index != label_index) {
585f1adc
IR
6160 vty_out(vty, "%% cannot change label-index\n");
6161 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6162 }
d62a17ae 6163
e2a86ad9 6164 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6165 if (bgp_static->valid
6166 && bgp_static->backdoor != backdoor)
e2a86ad9 6167 need_update = 1;
718e3744 6168
e2a86ad9 6169 bgp_static->backdoor = backdoor;
718e3744 6170
e2a86ad9 6171 if (rmap) {
0a22ddfb
QY
6172 XFREE(MTYPE_ROUTE_MAP_NAME,
6173 bgp_static->rmap.name);
b4897fa5 6174 route_map_counter_decrement(
6175 bgp_static->rmap.map);
e2a86ad9
DS
6176 bgp_static->rmap.name =
6177 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6178 bgp_static->rmap.map =
6179 route_map_lookup_by_name(rmap);
b4897fa5 6180 route_map_counter_increment(
6181 bgp_static->rmap.map);
e2a86ad9 6182 } else {
0a22ddfb
QY
6183 XFREE(MTYPE_ROUTE_MAP_NAME,
6184 bgp_static->rmap.name);
b4897fa5 6185 route_map_counter_decrement(
6186 bgp_static->rmap.map);
e2a86ad9
DS
6187 bgp_static->rmap.map = NULL;
6188 bgp_static->valid = 0;
6189 }
9bcb3eef 6190 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6191 } else {
6192 /* New configuration. */
6193 bgp_static = bgp_static_new();
6194 bgp_static->backdoor = backdoor;
6195 bgp_static->valid = 0;
6196 bgp_static->igpmetric = 0;
975a328e 6197 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6198 bgp_static->label_index = label_index;
718e3744 6199
e2a86ad9 6200 if (rmap) {
0a22ddfb
QY
6201 XFREE(MTYPE_ROUTE_MAP_NAME,
6202 bgp_static->rmap.name);
b4897fa5 6203 route_map_counter_decrement(
6204 bgp_static->rmap.map);
e2a86ad9
DS
6205 bgp_static->rmap.name =
6206 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6207 bgp_static->rmap.map =
6208 route_map_lookup_by_name(rmap);
b4897fa5 6209 route_map_counter_increment(
6210 bgp_static->rmap.map);
e2a86ad9 6211 }
9bcb3eef 6212 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6213 }
d62a17ae 6214
e2a86ad9
DS
6215 bgp_static->valid = 1;
6216 if (need_update)
6217 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6218
e2a86ad9
DS
6219 if (!bgp_static->backdoor)
6220 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6221 }
d62a17ae 6222
585f1adc 6223 return CMD_SUCCESS;
d62a17ae 6224}
6225
6226void bgp_static_add(struct bgp *bgp)
6227{
6228 afi_t afi;
6229 safi_t safi;
9bcb3eef
DS
6230 struct bgp_dest *dest;
6231 struct bgp_dest *rm;
d62a17ae 6232 struct bgp_table *table;
6233 struct bgp_static *bgp_static;
6234
47fc6261 6235 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6236 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6237 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6238 dest = bgp_route_next(dest)) {
6239 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6240 continue;
ea47320b 6241
05c7a1cc
QY
6242 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6243 || (safi == SAFI_EVPN)) {
9bcb3eef 6244 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6245
6246 for (rm = bgp_table_top(table); rm;
6247 rm = bgp_route_next(rm)) {
a78beeb5 6248 bgp_static =
9bcb3eef 6249 bgp_dest_get_bgp_static_info(
5a8ba9fc 6250 rm);
9bcb3eef
DS
6251 bgp_static_update_safi(
6252 bgp, bgp_dest_get_prefix(rm),
6253 bgp_static, afi, safi);
d62a17ae 6254 }
05c7a1cc 6255 } else {
5a8ba9fc 6256 bgp_static_update(
9bcb3eef
DS
6257 bgp, bgp_dest_get_prefix(dest),
6258 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6259 safi);
ea47320b 6260 }
05c7a1cc 6261 }
47fc6261 6262 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6263}
6264
718e3744 6265/* Called from bgp_delete(). Delete all static routes from the BGP
6266 instance. */
d62a17ae 6267void bgp_static_delete(struct bgp *bgp)
6268{
6269 afi_t afi;
6270 safi_t safi;
9bcb3eef
DS
6271 struct bgp_dest *dest;
6272 struct bgp_dest *rm;
d62a17ae 6273 struct bgp_table *table;
6274 struct bgp_static *bgp_static;
6275
05c7a1cc 6276 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6277 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6278 dest = bgp_route_next(dest)) {
6279 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6280 continue;
ea47320b 6281
05c7a1cc
QY
6282 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6283 || (safi == SAFI_EVPN)) {
9bcb3eef 6284 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6285
6286 for (rm = bgp_table_top(table); rm;
6287 rm = bgp_route_next(rm)) {
a78beeb5 6288 bgp_static =
9bcb3eef 6289 bgp_dest_get_bgp_static_info(
5a8ba9fc 6290 rm);
c7d14ba6
PG
6291 if (!bgp_static)
6292 continue;
6293
05c7a1cc 6294 bgp_static_withdraw_safi(
9bcb3eef 6295 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6296 AFI_IP, safi,
6297 (struct prefix_rd *)
9bcb3eef
DS
6298 bgp_dest_get_prefix(
6299 dest));
ea47320b 6300 bgp_static_free(bgp_static);
811c6797 6301 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6302 NULL);
811c6797 6303 bgp_dest_unlock_node(rm);
d62a17ae 6304 }
05c7a1cc 6305 } else {
9bcb3eef 6306 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6307 bgp_static_withdraw(bgp,
9bcb3eef 6308 bgp_dest_get_prefix(dest),
b54892e0 6309 afi, safi);
05c7a1cc 6310 bgp_static_free(bgp_static);
9bcb3eef
DS
6311 bgp_dest_set_bgp_static_info(dest, NULL);
6312 bgp_dest_unlock_node(dest);
ea47320b 6313 }
05c7a1cc 6314 }
d62a17ae 6315}
6316
6317void bgp_static_redo_import_check(struct bgp *bgp)
6318{
6319 afi_t afi;
6320 safi_t safi;
9bcb3eef
DS
6321 struct bgp_dest *dest;
6322 struct bgp_dest *rm;
d62a17ae 6323 struct bgp_table *table;
6324 struct bgp_static *bgp_static;
6325
6326 /* Use this flag to force reprocessing of the route */
892fedb6 6327 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6328 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6329 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6330 dest = bgp_route_next(dest)) {
6331 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6332 continue;
ea47320b 6333
05c7a1cc
QY
6334 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6335 || (safi == SAFI_EVPN)) {
9bcb3eef 6336 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6337
6338 for (rm = bgp_table_top(table); rm;
6339 rm = bgp_route_next(rm)) {
a78beeb5 6340 bgp_static =
9bcb3eef 6341 bgp_dest_get_bgp_static_info(
5a8ba9fc 6342 rm);
9bcb3eef
DS
6343 bgp_static_update_safi(
6344 bgp, bgp_dest_get_prefix(rm),
6345 bgp_static, afi, safi);
d62a17ae 6346 }
05c7a1cc 6347 } else {
9bcb3eef
DS
6348 bgp_static = bgp_dest_get_bgp_static_info(dest);
6349 bgp_static_update(bgp,
6350 bgp_dest_get_prefix(dest),
6351 bgp_static, afi, safi);
ea47320b 6352 }
05c7a1cc
QY
6353 }
6354 }
892fedb6 6355 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6356}
6357
6358static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6359 safi_t safi)
6360{
6361 struct bgp_table *table;
9bcb3eef 6362 struct bgp_dest *dest;
40381db7 6363 struct bgp_path_info *pi;
d62a17ae 6364
dfb6fd1d
NT
6365 /* Do not install the aggregate route if BGP is in the
6366 * process of termination.
6367 */
892fedb6
DA
6368 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6369 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6370 return;
6371
d62a17ae 6372 table = bgp->rib[afi][safi];
9bcb3eef
DS
6373 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6374 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6375 if (pi->peer == bgp->peer_self
6376 && ((pi->type == ZEBRA_ROUTE_BGP
6377 && pi->sub_type == BGP_ROUTE_STATIC)
6378 || (pi->type != ZEBRA_ROUTE_BGP
6379 && pi->sub_type
d62a17ae 6380 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6381 bgp_aggregate_decrement(
6382 bgp, bgp_dest_get_prefix(dest), pi, afi,
6383 safi);
40381db7 6384 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6385 bgp_path_info_delete(dest, pi);
6386 bgp_process(bgp, dest, afi, safi);
d62a17ae 6387 }
6388 }
6389 }
ad4cbda1 6390}
6391
6392/*
6393 * Purge all networks and redistributed routes from routing table.
6394 * Invoked upon the instance going down.
6395 */
d62a17ae 6396void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6397{
d62a17ae 6398 afi_t afi;
6399 safi_t safi;
ad4cbda1 6400
05c7a1cc
QY
6401 FOREACH_AFI_SAFI (afi, safi)
6402 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6403}
6404
137446f9
LB
6405/*
6406 * gpz 110624
6407 * Currently this is used to set static routes for VPN and ENCAP.
6408 * I think it can probably be factored with bgp_static_set.
6409 */
d62a17ae 6410int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6411 const char *ip_str, const char *rd_str,
6412 const char *label_str, const char *rmap_str,
6413 int evpn_type, const char *esi, const char *gwip,
6414 const char *ethtag, const char *routermac)
6415{
6416 VTY_DECLVAR_CONTEXT(bgp, bgp);
6417 int ret;
6418 struct prefix p;
6419 struct prefix_rd prd;
9bcb3eef
DS
6420 struct bgp_dest *pdest;
6421 struct bgp_dest *dest;
d62a17ae 6422 struct bgp_table *table;
6423 struct bgp_static *bgp_static;
6424 mpls_label_t label = MPLS_INVALID_LABEL;
6425 struct prefix gw_ip;
6426
6427 /* validate ip prefix */
6428 ret = str2prefix(ip_str, &p);
6429 if (!ret) {
6430 vty_out(vty, "%% Malformed prefix\n");
6431 return CMD_WARNING_CONFIG_FAILED;
6432 }
6433 apply_mask(&p);
6434 if ((afi == AFI_L2VPN)
6435 && (bgp_build_evpn_prefix(evpn_type,
6436 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6437 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6438 return CMD_WARNING_CONFIG_FAILED;
6439 }
718e3744 6440
d62a17ae 6441 ret = str2prefix_rd(rd_str, &prd);
6442 if (!ret) {
6443 vty_out(vty, "%% Malformed rd\n");
6444 return CMD_WARNING_CONFIG_FAILED;
6445 }
718e3744 6446
d62a17ae 6447 if (label_str) {
6448 unsigned long label_val;
6449 label_val = strtoul(label_str, NULL, 10);
6450 encode_label(label_val, &label);
6451 }
9bedbb1e 6452
d62a17ae 6453 if (safi == SAFI_EVPN) {
6454 if (esi && str2esi(esi, NULL) == 0) {
6455 vty_out(vty, "%% Malformed ESI\n");
6456 return CMD_WARNING_CONFIG_FAILED;
6457 }
6458 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6459 vty_out(vty, "%% Malformed Router MAC\n");
6460 return CMD_WARNING_CONFIG_FAILED;
6461 }
6462 if (gwip) {
6463 memset(&gw_ip, 0, sizeof(struct prefix));
6464 ret = str2prefix(gwip, &gw_ip);
6465 if (!ret) {
6466 vty_out(vty, "%% Malformed GatewayIp\n");
6467 return CMD_WARNING_CONFIG_FAILED;
6468 }
6469 if ((gw_ip.family == AF_INET
3714a385 6470 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6471 (struct prefix_evpn *)&p))
6472 || (gw_ip.family == AF_INET6
3714a385 6473 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6474 (struct prefix_evpn *)&p))) {
6475 vty_out(vty,
6476 "%% GatewayIp family differs with IP prefix\n");
6477 return CMD_WARNING_CONFIG_FAILED;
6478 }
6479 }
6480 }
9bcb3eef
DS
6481 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6482 if (!bgp_dest_has_bgp_path_info_data(pdest))
6483 bgp_dest_set_bgp_table_info(pdest,
67009e22 6484 bgp_table_init(bgp, afi, safi));
9bcb3eef 6485 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6486
9bcb3eef 6487 dest = bgp_node_get(table, &p);
d62a17ae 6488
9bcb3eef 6489 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6490 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6491 bgp_dest_unlock_node(dest);
d62a17ae 6492 } else {
6493 /* New configuration. */
6494 bgp_static = bgp_static_new();
6495 bgp_static->backdoor = 0;
6496 bgp_static->valid = 0;
6497 bgp_static->igpmetric = 0;
975a328e 6498 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6499 bgp_static->label = label;
6500 bgp_static->prd = prd;
6501
6502 if (rmap_str) {
0a22ddfb 6503 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6504 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6505 bgp_static->rmap.name =
6506 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6507 bgp_static->rmap.map =
6508 route_map_lookup_by_name(rmap_str);
b4897fa5 6509 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6510 }
718e3744 6511
d62a17ae 6512 if (safi == SAFI_EVPN) {
6513 if (esi) {
6514 bgp_static->eth_s_id =
6515 XCALLOC(MTYPE_ATTR,
0a50c248 6516 sizeof(esi_t));
d62a17ae 6517 str2esi(esi, bgp_static->eth_s_id);
6518 }
6519 if (routermac) {
6520 bgp_static->router_mac =
28328ea9 6521 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6522 (void)prefix_str2mac(routermac,
6523 bgp_static->router_mac);
d62a17ae 6524 }
6525 if (gwip)
6526 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6527 }
9bcb3eef 6528 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6529
d62a17ae 6530 bgp_static->valid = 1;
6531 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6532 }
718e3744 6533
d62a17ae 6534 return CMD_SUCCESS;
718e3744 6535}
6536
6537/* Configure static BGP network. */
d62a17ae 6538int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6539 const char *ip_str, const char *rd_str,
6540 const char *label_str, int evpn_type, const char *esi,
6541 const char *gwip, const char *ethtag)
6542{
6543 VTY_DECLVAR_CONTEXT(bgp, bgp);
6544 int ret;
6545 struct prefix p;
6546 struct prefix_rd prd;
9bcb3eef
DS
6547 struct bgp_dest *pdest;
6548 struct bgp_dest *dest;
d62a17ae 6549 struct bgp_table *table;
6550 struct bgp_static *bgp_static;
6551 mpls_label_t label = MPLS_INVALID_LABEL;
6552
6553 /* Convert IP prefix string to struct prefix. */
6554 ret = str2prefix(ip_str, &p);
6555 if (!ret) {
6556 vty_out(vty, "%% Malformed prefix\n");
6557 return CMD_WARNING_CONFIG_FAILED;
6558 }
6559 apply_mask(&p);
6560 if ((afi == AFI_L2VPN)
6561 && (bgp_build_evpn_prefix(evpn_type,
6562 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6563 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6564 return CMD_WARNING_CONFIG_FAILED;
6565 }
6566 ret = str2prefix_rd(rd_str, &prd);
6567 if (!ret) {
6568 vty_out(vty, "%% Malformed rd\n");
6569 return CMD_WARNING_CONFIG_FAILED;
6570 }
718e3744 6571
d62a17ae 6572 if (label_str) {
6573 unsigned long label_val;
6574 label_val = strtoul(label_str, NULL, 10);
6575 encode_label(label_val, &label);
6576 }
718e3744 6577
9bcb3eef
DS
6578 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6579 if (!bgp_dest_has_bgp_path_info_data(pdest))
6580 bgp_dest_set_bgp_table_info(pdest,
67009e22 6581 bgp_table_init(bgp, afi, safi));
d62a17ae 6582 else
9bcb3eef
DS
6583 bgp_dest_unlock_node(pdest);
6584 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6585
9bcb3eef 6586 dest = bgp_node_lookup(table, &p);
6b0655a2 6587
9bcb3eef 6588 if (dest) {
d62a17ae 6589 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6590
9bcb3eef 6591 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6592 bgp_static_free(bgp_static);
9bcb3eef
DS
6593 bgp_dest_set_bgp_static_info(dest, NULL);
6594 bgp_dest_unlock_node(dest);
6595 bgp_dest_unlock_node(dest);
d62a17ae 6596 } else
6597 vty_out(vty, "%% Can't find the route\n");
6598
6599 return CMD_SUCCESS;
6600}
6601
6602static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6603 const char *rmap_name)
6604{
6605 VTY_DECLVAR_CONTEXT(bgp, bgp);
6606 struct bgp_rmap *rmap;
6607
6608 rmap = &bgp->table_map[afi][safi];
6609 if (rmap_name) {
0a22ddfb 6610 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6611 route_map_counter_decrement(rmap->map);
d62a17ae 6612 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6613 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6614 route_map_counter_increment(rmap->map);
d62a17ae 6615 } else {
0a22ddfb 6616 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6617 route_map_counter_decrement(rmap->map);
d62a17ae 6618 rmap->map = NULL;
6619 }
73ac8160 6620
d62a17ae 6621 if (bgp_fibupd_safi(safi))
6622 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6623
d62a17ae 6624 return CMD_SUCCESS;
73ac8160
DS
6625}
6626
d62a17ae 6627static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6628 const char *rmap_name)
73ac8160 6629{
d62a17ae 6630 VTY_DECLVAR_CONTEXT(bgp, bgp);
6631 struct bgp_rmap *rmap;
73ac8160 6632
d62a17ae 6633 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6634 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6635 route_map_counter_decrement(rmap->map);
d62a17ae 6636 rmap->map = NULL;
73ac8160 6637
d62a17ae 6638 if (bgp_fibupd_safi(safi))
6639 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6640
d62a17ae 6641 return CMD_SUCCESS;
73ac8160
DS
6642}
6643
2b791107 6644void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6645 safi_t safi)
73ac8160 6646{
d62a17ae 6647 if (bgp->table_map[afi][safi].name) {
d62a17ae 6648 vty_out(vty, " table-map %s\n",
6649 bgp->table_map[afi][safi].name);
6650 }
73ac8160
DS
6651}
6652
73ac8160
DS
6653DEFUN (bgp_table_map,
6654 bgp_table_map_cmd,
6655 "table-map WORD",
6656 "BGP table to RIB route download filter\n"
6657 "Name of the route map\n")
6658{
d62a17ae 6659 int idx_word = 1;
6660 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6661 argv[idx_word]->arg);
73ac8160
DS
6662}
6663DEFUN (no_bgp_table_map,
6664 no_bgp_table_map_cmd,
6665 "no table-map WORD",
3a2d747c 6666 NO_STR
73ac8160
DS
6667 "BGP table to RIB route download filter\n"
6668 "Name of the route map\n")
6669{
d62a17ae 6670 int idx_word = 2;
6671 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6672 argv[idx_word]->arg);
73ac8160
DS
6673}
6674
585f1adc
IR
6675DEFPY(bgp_network,
6676 bgp_network_cmd,
6677 "[no] network \
6678 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6679 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6680 backdoor$backdoor}]",
6681 NO_STR
6682 "Specify a network to announce via BGP\n"
6683 "IPv4 prefix\n"
6684 "Network number\n"
6685 "Network mask\n"
6686 "Network mask\n"
6687 "Route-map to modify the attributes\n"
6688 "Name of the route map\n"
6689 "Label index to associate with the prefix\n"
6690 "Label index value\n"
6691 "Specify a BGP backdoor route\n")
6692{
6693 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6694
6695 if (address_str) {
6696 int ret;
718e3744 6697
e2a86ad9 6698 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6699 addr_prefix_str,
6700 sizeof(addr_prefix_str));
e2a86ad9
DS
6701 if (!ret) {
6702 vty_out(vty, "%% Inconsistent address and mask\n");
6703 return CMD_WARNING_CONFIG_FAILED;
6704 }
d62a17ae 6705 }
718e3744 6706
585f1adc
IR
6707 return bgp_static_set(
6708 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6709 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6710 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6711}
6712
585f1adc
IR
6713DEFPY(ipv6_bgp_network,
6714 ipv6_bgp_network_cmd,
6715 "[no] network X:X::X:X/M$prefix \
6716 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6717 NO_STR
6718 "Specify a network to announce via BGP\n"
6719 "IPv6 prefix\n"
6720 "Route-map to modify the attributes\n"
6721 "Name of the route map\n"
6722 "Label index to associate with the prefix\n"
6723 "Label index value\n")
37a87b8f 6724{
585f1adc
IR
6725 return bgp_static_set(
6726 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6727 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6728}
6729
d62a17ae 6730static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6731{
d62a17ae 6732 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6733}
6734
d62a17ae 6735static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6736{
365ab2e7
RZ
6737 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6738 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6739 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6740 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6741 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6742}
718e3744 6743
365ab2e7
RZ
6744/**
6745 * Helper function to avoid repeated code: prepare variables for a
6746 * `route_map_apply` call.
6747 *
6748 * \returns `true` on route map match, otherwise `false`.
6749 */
6750static bool aggr_suppress_map_test(struct bgp *bgp,
6751 struct bgp_aggregate *aggregate,
6752 struct bgp_path_info *pi)
6753{
6754 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6755 route_map_result_t rmr = RMAP_DENYMATCH;
6756 struct bgp_path_info rmap_path = {};
6757 struct attr attr = {};
6758
6759 /* No route map entries created, just don't match. */
6760 if (aggregate->suppress_map == NULL)
6761 return false;
6762
6763 /* Call route map matching and return result. */
6764 attr.aspath = aspath_empty();
6765 rmap_path.peer = bgp->peer_self;
6766 rmap_path.attr = &attr;
6767
6768 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6769 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6770 bgp->peer_self->rmap_type = 0;
6771
6772 bgp_attr_flush(&attr);
6773
6774 return rmr == RMAP_PERMITMATCH;
6775}
6776
4056a5f6
RZ
6777/** Test whether the aggregation has suppressed this path or not. */
6778static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6779 struct bgp_path_info *pi)
6780{
6781 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6782 return false;
6783
6784 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6785}
6786
6787/**
6788 * Suppress this path and keep the reference.
6789 *
6790 * \returns `true` if needs processing otherwise `false`.
6791 */
6792static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6793 struct bgp_path_info *pi)
6794{
6795 struct bgp_path_info_extra *pie;
6796
6797 /* Path is already suppressed by this aggregation. */
6798 if (aggr_suppress_exists(aggregate, pi))
6799 return false;
6800
6801 pie = bgp_path_info_extra_get(pi);
6802
6803 /* This is the first suppression, allocate memory and list it. */
6804 if (pie->aggr_suppressors == NULL)
6805 pie->aggr_suppressors = list_new();
6806
6807 listnode_add(pie->aggr_suppressors, aggregate);
6808
6809 /* Only mark for processing if suppressed. */
6810 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6811 if (BGP_DEBUG(update, UPDATE_OUT))
6812 zlog_debug("aggregate-address suppressing: %pFX",
6813 bgp_dest_get_prefix(pi->net));
6814
4056a5f6
RZ
6815 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6816 return true;
6817 }
6818
6819 return false;
6820}
6821
6822/**
6823 * Unsuppress this path and remove the reference.
6824 *
6825 * \returns `true` if needs processing otherwise `false`.
6826 */
6827static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6828 struct bgp_path_info *pi)
6829{
6830 /* Path wasn't suppressed. */
6831 if (!aggr_suppress_exists(aggregate, pi))
6832 return false;
6833
6834 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6835
6836 /* Unsuppress and free extra memory if last item. */
6837 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6838 if (BGP_DEBUG(update, UPDATE_OUT))
6839 zlog_debug("aggregate-address unsuppressing: %pFX",
6840 bgp_dest_get_prefix(pi->net));
6841
4056a5f6
RZ
6842 list_delete(&pi->extra->aggr_suppressors);
6843 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6844 return true;
6845 }
6846
6847 return false;
6848}
6849
3dc339cd
DA
6850static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6851 struct aspath *aspath,
6852 struct community *comm,
6853 struct ecommunity *ecomm,
6854 struct lcommunity *lcomm)
eaaf8adb
DS
6855{
6856 static struct aspath *ae = NULL;
6857
6858 if (!ae)
6859 ae = aspath_empty();
6860
40381db7 6861 if (!pi)
3dc339cd 6862 return false;
eaaf8adb 6863
40381db7 6864 if (origin != pi->attr->origin)
3dc339cd 6865 return false;
eaaf8adb 6866
40381db7 6867 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6868 return false;
29f7d023 6869
40381db7 6870 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6871 return false;
eaaf8adb 6872
3da2cc32 6873 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6874 return false;
eaaf8adb 6875
dd18c5a9 6876 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6877 return false;
dd18c5a9 6878
40381db7 6879 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6880 return false;
7ce8a8e0 6881
3dc339cd 6882 return true;
eaaf8adb
DS
6883}
6884
5f040085
DS
6885static void bgp_aggregate_install(
6886 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6887 uint8_t origin, struct aspath *aspath, struct community *community,
6888 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6889 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6890{
9bcb3eef 6891 struct bgp_dest *dest;
c701010e 6892 struct bgp_table *table;
6f94b685 6893 struct bgp_path_info *pi, *orig, *new;
20894f50 6894 struct attr *attr;
c701010e
DS
6895
6896 table = bgp->rib[afi][safi];
6897
9bcb3eef 6898 dest = bgp_node_get(table, p);
eaaf8adb 6899
9bcb3eef 6900 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6901 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6902 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6903 break;
6904
6aabb15d
RZ
6905 /*
6906 * If we have paths with different MEDs, then don't install
6907 * (or uninstall) the aggregate route.
6908 */
6909 if (aggregate->match_med && aggregate->med_mismatched)
6910 goto uninstall_aggregate_route;
6911
c701010e 6912 if (aggregate->count > 0) {
eaaf8adb
DS
6913 /*
6914 * If the aggregate information has not changed
6915 * no need to re-install it again.
6916 */
6f94b685 6917 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6918 ecommunity, lcommunity)) {
9bcb3eef 6919 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6920
6921 if (aspath)
6922 aspath_free(aspath);
6923 if (community)
3c1f53de 6924 community_free(&community);
3da2cc32
DS
6925 if (ecommunity)
6926 ecommunity_free(&ecommunity);
dd18c5a9
DS
6927 if (lcommunity)
6928 lcommunity_free(&lcommunity);
eaaf8adb
DS
6929
6930 return;
6931 }
6932
6933 /*
6934 * Mark the old as unusable
6935 */
40381db7 6936 if (pi)
9bcb3eef 6937 bgp_path_info_delete(dest, pi);
eaaf8adb 6938
20894f50
DA
6939 attr = bgp_attr_aggregate_intern(
6940 bgp, origin, aspath, community, ecommunity, lcommunity,
6941 aggregate, atomic_aggregate, p);
6942
6943 if (!attr) {
6944 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6945 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6946 zlog_debug("%s: %pFX null attribute", __func__,
6947 p);
20894f50
DA
6948 return;
6949 }
6950
3da2cc32 6951 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6952 bgp->peer_self, attr, dest);
20894f50 6953
1defdda8 6954 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6955
9bcb3eef
DS
6956 bgp_path_info_add(dest, new);
6957 bgp_process(bgp, dest, afi, safi);
c701010e 6958 } else {
6aabb15d 6959 uninstall_aggregate_route:
6f94b685 6960 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6961 if (pi->peer == bgp->peer_self
6962 && pi->type == ZEBRA_ROUTE_BGP
6963 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6964 break;
6965
6966 /* Withdraw static BGP route from routing table. */
40381db7 6967 if (pi) {
9bcb3eef
DS
6968 bgp_path_info_delete(dest, pi);
6969 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6970 }
6971 }
6972
9bcb3eef 6973 bgp_dest_unlock_node(dest);
c701010e
DS
6974}
6975
6aabb15d
RZ
6976/**
6977 * Check if the current path has different MED than other known paths.
6978 *
6979 * \returns `true` if the MED matched the others else `false`.
6980 */
6981static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6982 struct bgp *bgp, struct bgp_path_info *pi)
6983{
6984 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6985
6986 /* This is the first route being analyzed. */
6987 if (!aggregate->med_initialized) {
6988 aggregate->med_initialized = true;
6989 aggregate->med_mismatched = false;
6990 aggregate->med_matched_value = cur_med;
6991 } else {
6992 /* Check if routes with different MED showed up. */
6993 if (cur_med != aggregate->med_matched_value)
6994 aggregate->med_mismatched = true;
6995 }
6996
6997 return !aggregate->med_mismatched;
6998}
6999
7000/**
7001 * Initializes and tests all routes in the aggregate address path for MED
7002 * values.
7003 *
7004 * \returns `true` if all MEDs are the same otherwise `false`.
7005 */
7006static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7007 struct bgp *bgp, const struct prefix *p,
7008 afi_t afi, safi_t safi)
7009{
7010 struct bgp_table *table = bgp->rib[afi][safi];
7011 const struct prefix *dest_p;
7012 struct bgp_dest *dest, *top;
7013 struct bgp_path_info *pi;
7014 bool med_matched = true;
7015
7016 aggregate->med_initialized = false;
7017
7018 top = bgp_node_get(table, p);
7019 for (dest = bgp_node_get(table, p); dest;
7020 dest = bgp_route_next_until(dest, top)) {
7021 dest_p = bgp_dest_get_prefix(dest);
7022 if (dest_p->prefixlen <= p->prefixlen)
7023 continue;
7024
7025 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7026 if (BGP_PATH_HOLDDOWN(pi))
7027 continue;
7028 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7029 continue;
7030 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7031 med_matched = false;
7032 break;
7033 }
7034 }
7035 if (!med_matched)
7036 break;
7037 }
7038 bgp_dest_unlock_node(top);
7039
7040 return med_matched;
7041}
7042
7043/**
7044 * Toggles the route suppression status for this aggregate address
7045 * configuration.
7046 */
4056a5f6
RZ
7047void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7048 struct bgp *bgp, const struct prefix *p,
7049 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7050{
7051 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7052 const struct prefix *dest_p;
7053 struct bgp_dest *dest, *top;
7054 struct bgp_path_info *pi;
7055 bool toggle_suppression;
7056
7057 /* We've found a different MED we must revert any suppressed routes. */
7058 top = bgp_node_get(table, p);
7059 for (dest = bgp_node_get(table, p); dest;
7060 dest = bgp_route_next_until(dest, top)) {
7061 dest_p = bgp_dest_get_prefix(dest);
7062 if (dest_p->prefixlen <= p->prefixlen)
7063 continue;
7064
7065 toggle_suppression = false;
7066 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7067 if (BGP_PATH_HOLDDOWN(pi))
7068 continue;
7069 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7070 continue;
7071
6aabb15d
RZ
7072 /* We are toggling suppression back. */
7073 if (suppress) {
6aabb15d 7074 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7075 if (aggr_suppress_path(aggregate, pi))
7076 toggle_suppression = true;
6aabb15d
RZ
7077 continue;
7078 }
7079
6aabb15d 7080 /* Install route if there is no more suppression. */
4056a5f6 7081 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7082 toggle_suppression = true;
6aabb15d
RZ
7083 }
7084
7085 if (toggle_suppression)
7086 bgp_process(bgp, dest, afi, safi);
7087 }
7088 bgp_dest_unlock_node(top);
7089}
7090
7091/**
7092 * Aggregate address MED matching incremental test: this function is called
7093 * when the initial aggregation occurred and we are only testing a single
7094 * new path.
7095 *
7096 * In addition to testing and setting the MED validity it also installs back
7097 * suppressed routes (if summary is configured).
7098 *
7099 * Must not be called in `bgp_aggregate_route`.
7100 */
7101static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7102 struct bgp *bgp, const struct prefix *p,
7103 afi_t afi, safi_t safi,
7104 struct bgp_path_info *pi, bool is_adding)
7105{
7106 /* MED matching disabled. */
7107 if (!aggregate->match_med)
7108 return;
7109
7110 /* Aggregation with different MED, nothing to do. */
7111 if (aggregate->med_mismatched)
7112 return;
7113
7114 /*
7115 * Test the current entry:
7116 *
7117 * is_adding == true: if the new entry doesn't match then we must
7118 * install all suppressed routes.
7119 *
7120 * is_adding == false: if the entry being removed was the last
7121 * unmatching entry then we can suppress all routes.
7122 */
7123 if (!is_adding) {
7124 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7125 && aggregate->summary_only)
7126 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7127 safi, true);
7128 } else
7129 bgp_aggregate_med_match(aggregate, bgp, pi);
7130
7131 /* No mismatches, just quit. */
7132 if (!aggregate->med_mismatched)
7133 return;
7134
7135 /* Route summarization is disabled. */
7136 if (!aggregate->summary_only)
7137 return;
7138
7139 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7140}
7141
b5d58c32 7142/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7143void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7144 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7145{
7146 struct bgp_table *table;
9bcb3eef
DS
7147 struct bgp_dest *top;
7148 struct bgp_dest *dest;
d7c0a89a 7149 uint8_t origin;
d62a17ae 7150 struct aspath *aspath = NULL;
d62a17ae 7151 struct community *community = NULL;
3da2cc32 7152 struct ecommunity *ecommunity = NULL;
dd18c5a9 7153 struct lcommunity *lcommunity = NULL;
40381db7 7154 struct bgp_path_info *pi;
d62a17ae 7155 unsigned long match = 0;
d7c0a89a 7156 uint8_t atomic_aggregate = 0;
d62a17ae 7157
9f822fa2
S
7158 /* If the bgp instance is being deleted or self peer is deleted
7159 * then do not create aggregate route
7160 */
892fedb6
DA
7161 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7162 || (bgp->peer_self == NULL))
9f822fa2
S
7163 return;
7164
6aabb15d
RZ
7165 /* Initialize and test routes for MED difference. */
7166 if (aggregate->match_med)
7167 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7168
4056a5f6
RZ
7169 /*
7170 * Reset aggregate count: we might've been called from route map
7171 * update so in that case we must retest all more specific routes.
7172 *
7173 * \see `bgp_route_map_process_update`.
7174 */
7175 aggregate->count = 0;
7176 aggregate->incomplete_origin_count = 0;
7177 aggregate->incomplete_origin_count = 0;
7178 aggregate->egp_origin_count = 0;
7179
d62a17ae 7180 /* ORIGIN attribute: If at least one route among routes that are
7181 aggregated has ORIGIN with the value INCOMPLETE, then the
7182 aggregated route must have the ORIGIN attribute with the value
7183 INCOMPLETE. Otherwise, if at least one route among routes that
7184 are aggregated has ORIGIN with the value EGP, then the aggregated
7185 route must have the origin attribute with the value EGP. In all
7186 other case the value of the ORIGIN attribute of the aggregated
7187 route is INTERNAL. */
7188 origin = BGP_ORIGIN_IGP;
718e3744 7189
d62a17ae 7190 table = bgp->rib[afi][safi];
718e3744 7191
d62a17ae 7192 top = bgp_node_get(table, p);
9bcb3eef
DS
7193 for (dest = bgp_node_get(table, p); dest;
7194 dest = bgp_route_next_until(dest, top)) {
7195 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7196
9bcb3eef 7197 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7198 continue;
d62a17ae 7199
a77e2f4b
S
7200 /* If suppress fib is enabled and route not installed
7201 * in FIB, skip the route
7202 */
7203 if (!bgp_check_advertise(bgp, dest))
7204 continue;
7205
c2ff8b3e 7206 match = 0;
d62a17ae 7207
9bcb3eef 7208 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7209 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7210 continue;
718e3744 7211
40381db7 7212 if (pi->attr->flag
c2ff8b3e
DS
7213 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7214 atomic_aggregate = 1;
d62a17ae 7215
40381db7 7216 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7217 continue;
d62a17ae 7218
f273fef1
DS
7219 /*
7220 * summary-only aggregate route suppress
7221 * aggregated route announcements.
6aabb15d
RZ
7222 *
7223 * MED matching:
7224 * Don't create summaries if MED didn't match
7225 * otherwise neither the specific routes and the
7226 * aggregation will be announced.
f273fef1 7227 */
6aabb15d
RZ
7228 if (aggregate->summary_only
7229 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7230 if (aggr_suppress_path(aggregate, pi))
7231 match++;
d62a17ae 7232 }
c2ff8b3e 7233
365ab2e7
RZ
7234 /*
7235 * Suppress more specific routes that match the route
7236 * map results.
7237 *
7238 * MED matching:
7239 * Don't suppress routes if MED matching is enabled and
7240 * it mismatched otherwise we might end up with no
7241 * routes for this path.
7242 */
7243 if (aggregate->suppress_map_name
7244 && AGGREGATE_MED_VALID(aggregate)
7245 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7246 if (aggr_suppress_path(aggregate, pi))
7247 match++;
d62a17ae 7248 }
c2ff8b3e
DS
7249
7250 aggregate->count++;
7251
f273fef1
DS
7252 /*
7253 * If at least one route among routes that are
7254 * aggregated has ORIGIN with the value INCOMPLETE,
7255 * then the aggregated route MUST have the ORIGIN
7256 * attribute with the value INCOMPLETE. Otherwise, if
7257 * at least one route among routes that are aggregated
7258 * has ORIGIN with the value EGP, then the aggregated
7259 * route MUST have the ORIGIN attribute with the value
7260 * EGP.
7261 */
fc968841
NT
7262 switch (pi->attr->origin) {
7263 case BGP_ORIGIN_INCOMPLETE:
7264 aggregate->incomplete_origin_count++;
7265 break;
7266 case BGP_ORIGIN_EGP:
7267 aggregate->egp_origin_count++;
7268 break;
7269 default:
7270 /*Do nothing.
7271 */
7272 break;
7273 }
c2ff8b3e
DS
7274
7275 if (!aggregate->as_set)
7276 continue;
7277
f273fef1
DS
7278 /*
7279 * as-set aggregate route generate origin, as path,
7280 * and community aggregation.
7281 */
fc968841
NT
7282 /* Compute aggregate route's as-path.
7283 */
ef51a7d8 7284 bgp_compute_aggregate_aspath_hash(aggregate,
7285 pi->attr->aspath);
c2ff8b3e 7286
fc968841
NT
7287 /* Compute aggregate route's community.
7288 */
7289 if (pi->attr->community)
21fec674 7290 bgp_compute_aggregate_community_hash(
fc968841
NT
7291 aggregate,
7292 pi->attr->community);
dd18c5a9 7293
fc968841
NT
7294 /* Compute aggregate route's extended community.
7295 */
7296 if (pi->attr->ecommunity)
4edd83f9 7297 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7298 aggregate,
7299 pi->attr->ecommunity);
7300
7301 /* Compute aggregate route's large community.
7302 */
7303 if (pi->attr->lcommunity)
f1eb1f05 7304 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7305 aggregate,
7306 pi->attr->lcommunity);
d62a17ae 7307 }
c2ff8b3e 7308 if (match)
9bcb3eef 7309 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7310 }
21fec674 7311 if (aggregate->as_set) {
ef51a7d8 7312 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7313 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7314 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7315 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7316 }
7317
f1eb1f05 7318
9bcb3eef 7319 bgp_dest_unlock_node(top);
718e3744 7320
718e3744 7321
fc968841
NT
7322 if (aggregate->incomplete_origin_count > 0)
7323 origin = BGP_ORIGIN_INCOMPLETE;
7324 else if (aggregate->egp_origin_count > 0)
7325 origin = BGP_ORIGIN_EGP;
d62a17ae 7326
229757f1
DA
7327 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7328 origin = aggregate->origin;
7329
fc968841
NT
7330 if (aggregate->as_set) {
7331 if (aggregate->aspath)
7332 /* Retrieve aggregate route's as-path.
7333 */
7334 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7335
fc968841
NT
7336 if (aggregate->community)
7337 /* Retrieve aggregate route's community.
7338 */
7339 community = community_dup(aggregate->community);
3da2cc32 7340
fc968841
NT
7341 if (aggregate->ecommunity)
7342 /* Retrieve aggregate route's ecommunity.
7343 */
7344 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7345
fc968841
NT
7346 if (aggregate->lcommunity)
7347 /* Retrieve aggregate route's lcommunity.
7348 */
7349 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7350 }
718e3744 7351
c701010e 7352 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7353 ecommunity, lcommunity, atomic_aggregate,
7354 aggregate);
718e3744 7355}
7356
5f040085
DS
7357void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7358 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7359{
7360 struct bgp_table *table;
9bcb3eef
DS
7361 struct bgp_dest *top;
7362 struct bgp_dest *dest;
40381db7 7363 struct bgp_path_info *pi;
3b7db173
DS
7364 unsigned long match;
7365
7366 table = bgp->rib[afi][safi];
7367
7368 /* If routes exists below this node, generate aggregate routes. */
7369 top = bgp_node_get(table, p);
9bcb3eef
DS
7370 for (dest = bgp_node_get(table, p); dest;
7371 dest = bgp_route_next_until(dest, top)) {
7372 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7373
9bcb3eef 7374 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7375 continue;
7376 match = 0;
7377
9bcb3eef 7378 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7379 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7380 continue;
7381
40381db7 7382 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7383 continue;
7384
6aabb15d
RZ
7385 if (aggregate->summary_only && pi->extra
7386 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7387 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7388 match++;
3b7db173 7389 }
3b7db173 7390
365ab2e7
RZ
7391 if (aggregate->suppress_map_name
7392 && AGGREGATE_MED_VALID(aggregate)
7393 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7394 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7395 match++;
3b7db173 7396 }
365ab2e7 7397
3b7db173 7398 aggregate->count--;
fc968841
NT
7399
7400 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7401 aggregate->incomplete_origin_count--;
7402 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7403 aggregate->egp_origin_count--;
7404
7405 if (aggregate->as_set) {
7406 /* Remove as-path from aggregate.
7407 */
ef51a7d8 7408 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7409 aggregate,
7410 pi->attr->aspath);
7411
7412 if (pi->attr->community)
7413 /* Remove community from aggregate.
7414 */
21fec674 7415 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7416 aggregate,
7417 pi->attr->community);
7418
7419 if (pi->attr->ecommunity)
7420 /* Remove ecommunity from aggregate.
7421 */
4edd83f9 7422 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7423 aggregate,
7424 pi->attr->ecommunity);
7425
7426 if (pi->attr->lcommunity)
7427 /* Remove lcommunity from aggregate.
7428 */
f1eb1f05 7429 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7430 aggregate,
7431 pi->attr->lcommunity);
7432 }
3b7db173
DS
7433 }
7434
7435 /* If this node was suppressed, process the change. */
7436 if (match)
9bcb3eef 7437 bgp_process(bgp, dest, afi, safi);
3b7db173 7438 }
f1eb1f05 7439 if (aggregate->as_set) {
ef51a7d8 7440 aspath_free(aggregate->aspath);
7441 aggregate->aspath = NULL;
21fec674 7442 if (aggregate->community)
7443 community_free(&aggregate->community);
4edd83f9 7444 if (aggregate->ecommunity)
7445 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7446 if (aggregate->lcommunity)
7447 lcommunity_free(&aggregate->lcommunity);
7448 }
7449
9bcb3eef 7450 bgp_dest_unlock_node(top);
3b7db173 7451}
718e3744 7452
5f040085
DS
7453static void bgp_add_route_to_aggregate(struct bgp *bgp,
7454 const struct prefix *aggr_p,
fc968841
NT
7455 struct bgp_path_info *pinew, afi_t afi,
7456 safi_t safi,
7457 struct bgp_aggregate *aggregate)
7458{
7459 uint8_t origin;
7460 struct aspath *aspath = NULL;
7461 uint8_t atomic_aggregate = 0;
7462 struct community *community = NULL;
7463 struct ecommunity *ecommunity = NULL;
7464 struct lcommunity *lcommunity = NULL;
7465
a4559740 7466 /* If the bgp instance is being deleted or self peer is deleted
7467 * then do not create aggregate route
7468 */
7469 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7470 || (bgp->peer_self == NULL))
7471 return;
7472
fc968841
NT
7473 /* ORIGIN attribute: If at least one route among routes that are
7474 * aggregated has ORIGIN with the value INCOMPLETE, then the
7475 * aggregated route must have the ORIGIN attribute with the value
7476 * INCOMPLETE. Otherwise, if at least one route among routes that
7477 * are aggregated has ORIGIN with the value EGP, then the aggregated
7478 * route must have the origin attribute with the value EGP. In all
7479 * other case the value of the ORIGIN attribute of the aggregated
7480 * route is INTERNAL.
7481 */
7482 origin = BGP_ORIGIN_IGP;
7483
7484 aggregate->count++;
7485
6aabb15d
RZ
7486 /*
7487 * This must be called before `summary` check to avoid
7488 * "suppressing" twice.
7489 */
7490 if (aggregate->match_med)
7491 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7492 pinew, true);
7493
7494 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7495 aggr_suppress_path(aggregate, pinew);
fc968841 7496
365ab2e7
RZ
7497 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7498 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7499 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7500
7501 switch (pinew->attr->origin) {
7502 case BGP_ORIGIN_INCOMPLETE:
7503 aggregate->incomplete_origin_count++;
7504 break;
7505 case BGP_ORIGIN_EGP:
7506 aggregate->egp_origin_count++;
7507 break;
7508 default:
7509 /* Do nothing.
7510 */
7511 break;
7512 }
7513
7514 if (aggregate->incomplete_origin_count > 0)
7515 origin = BGP_ORIGIN_INCOMPLETE;
7516 else if (aggregate->egp_origin_count > 0)
7517 origin = BGP_ORIGIN_EGP;
7518
229757f1
DA
7519 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7520 origin = aggregate->origin;
7521
fc968841
NT
7522 if (aggregate->as_set) {
7523 /* Compute aggregate route's as-path.
7524 */
7525 bgp_compute_aggregate_aspath(aggregate,
7526 pinew->attr->aspath);
7527
7528 /* Compute aggregate route's community.
7529 */
7530 if (pinew->attr->community)
7531 bgp_compute_aggregate_community(
7532 aggregate,
7533 pinew->attr->community);
7534
7535 /* Compute aggregate route's extended community.
7536 */
7537 if (pinew->attr->ecommunity)
7538 bgp_compute_aggregate_ecommunity(
7539 aggregate,
7540 pinew->attr->ecommunity);
7541
7542 /* Compute aggregate route's large community.
7543 */
7544 if (pinew->attr->lcommunity)
7545 bgp_compute_aggregate_lcommunity(
7546 aggregate,
7547 pinew->attr->lcommunity);
7548
7549 /* Retrieve aggregate route's as-path.
7550 */
7551 if (aggregate->aspath)
7552 aspath = aspath_dup(aggregate->aspath);
7553
7554 /* Retrieve aggregate route's community.
7555 */
7556 if (aggregate->community)
7557 community = community_dup(aggregate->community);
7558
7559 /* Retrieve aggregate route's ecommunity.
7560 */
7561 if (aggregate->ecommunity)
7562 ecommunity = ecommunity_dup(aggregate->ecommunity);
7563
7564 /* Retrieve aggregate route's lcommunity.
7565 */
7566 if (aggregate->lcommunity)
7567 lcommunity = lcommunity_dup(aggregate->lcommunity);
7568 }
7569
7570 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7571 aspath, community, ecommunity,
7572 lcommunity, atomic_aggregate, aggregate);
7573}
7574
7575static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7576 safi_t safi,
7577 struct bgp_path_info *pi,
7578 struct bgp_aggregate *aggregate,
5f040085 7579 const struct prefix *aggr_p)
fc968841
NT
7580{
7581 uint8_t origin;
7582 struct aspath *aspath = NULL;
7583 uint8_t atomic_aggregate = 0;
7584 struct community *community = NULL;
7585 struct ecommunity *ecommunity = NULL;
7586 struct lcommunity *lcommunity = NULL;
7587 unsigned long match = 0;
7588
a4559740 7589 /* If the bgp instance is being deleted or self peer is deleted
7590 * then do not create aggregate route
7591 */
7592 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7593 || (bgp->peer_self == NULL))
7594 return;
7595
fc968841
NT
7596 if (BGP_PATH_HOLDDOWN(pi))
7597 return;
7598
7599 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7600 return;
7601
4056a5f6
RZ
7602 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7603 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7604 match++;
fc968841 7605
365ab2e7 7606 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7607 && aggr_suppress_map_test(bgp, aggregate, pi))
7608 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7609 match++;
fc968841 7610
6aabb15d 7611 /*
365ab2e7 7612 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7613 * "unsuppressing" twice.
7614 */
7615 if (aggregate->match_med)
7616 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7617 true);
7618
fc968841
NT
7619 if (aggregate->count > 0)
7620 aggregate->count--;
7621
7622 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7623 aggregate->incomplete_origin_count--;
7624 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7625 aggregate->egp_origin_count--;
7626
7627 if (aggregate->as_set) {
7628 /* Remove as-path from aggregate.
7629 */
7630 bgp_remove_aspath_from_aggregate(aggregate,
7631 pi->attr->aspath);
7632
7633 if (pi->attr->community)
7634 /* Remove community from aggregate.
7635 */
7636 bgp_remove_community_from_aggregate(
7637 aggregate,
7638 pi->attr->community);
7639
7640 if (pi->attr->ecommunity)
7641 /* Remove ecommunity from aggregate.
7642 */
7643 bgp_remove_ecommunity_from_aggregate(
7644 aggregate,
7645 pi->attr->ecommunity);
7646
7647 if (pi->attr->lcommunity)
7648 /* Remove lcommunity from aggregate.
7649 */
7650 bgp_remove_lcommunity_from_aggregate(
7651 aggregate,
7652 pi->attr->lcommunity);
7653 }
7654
7655 /* If this node was suppressed, process the change. */
7656 if (match)
7657 bgp_process(bgp, pi->net, afi, safi);
7658
7659 origin = BGP_ORIGIN_IGP;
7660 if (aggregate->incomplete_origin_count > 0)
7661 origin = BGP_ORIGIN_INCOMPLETE;
7662 else if (aggregate->egp_origin_count > 0)
7663 origin = BGP_ORIGIN_EGP;
7664
229757f1
DA
7665 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7666 origin = aggregate->origin;
7667
fc968841
NT
7668 if (aggregate->as_set) {
7669 /* Retrieve aggregate route's as-path.
7670 */
7671 if (aggregate->aspath)
7672 aspath = aspath_dup(aggregate->aspath);
7673
7674 /* Retrieve aggregate route's community.
7675 */
7676 if (aggregate->community)
7677 community = community_dup(aggregate->community);
7678
7679 /* Retrieve aggregate route's ecommunity.
7680 */
7681 if (aggregate->ecommunity)
7682 ecommunity = ecommunity_dup(aggregate->ecommunity);
7683
7684 /* Retrieve aggregate route's lcommunity.
7685 */
7686 if (aggregate->lcommunity)
7687 lcommunity = lcommunity_dup(aggregate->lcommunity);
7688 }
7689
7690 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7691 aspath, community, ecommunity,
7692 lcommunity, atomic_aggregate, aggregate);
7693}
7694
5a1ae2c2 7695void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7696 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7697{
9bcb3eef
DS
7698 struct bgp_dest *child;
7699 struct bgp_dest *dest;
d62a17ae 7700 struct bgp_aggregate *aggregate;
7701 struct bgp_table *table;
718e3744 7702
d62a17ae 7703 table = bgp->aggregate[afi][safi];
f018db83 7704
d62a17ae 7705 /* No aggregates configured. */
7706 if (bgp_table_top_nolock(table) == NULL)
7707 return;
f018db83 7708
d62a17ae 7709 if (p->prefixlen == 0)
7710 return;
718e3744 7711
40381db7 7712 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7713 return;
718e3744 7714
a77e2f4b
S
7715 /* If suppress fib is enabled and route not installed
7716 * in FIB, do not update the aggregate route
7717 */
7718 if (!bgp_check_advertise(bgp, pi->net))
7719 return;
7720
d62a17ae 7721 child = bgp_node_get(table, p);
718e3744 7722
d62a17ae 7723 /* Aggregate address configuration check. */
9bcb3eef
DS
7724 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7725 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7726
9bcb3eef
DS
7727 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7728 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7729 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7730 aggregate);
d62a17ae 7731 }
b1e62edd 7732 }
9bcb3eef 7733 bgp_dest_unlock_node(child);
718e3744 7734}
7735
5a1ae2c2 7736void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7737 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7738{
9bcb3eef
DS
7739 struct bgp_dest *child;
7740 struct bgp_dest *dest;
d62a17ae 7741 struct bgp_aggregate *aggregate;
7742 struct bgp_table *table;
718e3744 7743
d62a17ae 7744 table = bgp->aggregate[afi][safi];
718e3744 7745
d62a17ae 7746 /* No aggregates configured. */
7747 if (bgp_table_top_nolock(table) == NULL)
7748 return;
718e3744 7749
d62a17ae 7750 if (p->prefixlen == 0)
7751 return;
718e3744 7752
d62a17ae 7753 child = bgp_node_get(table, p);
718e3744 7754
d62a17ae 7755 /* Aggregate address configuration check. */
9bcb3eef
DS
7756 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7757 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7758
9bcb3eef
DS
7759 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7760 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7761 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7762 aggregate, dest_p);
d62a17ae 7763 }
b1e62edd 7764 }
9bcb3eef 7765 bgp_dest_unlock_node(child);
d62a17ae 7766}
718e3744 7767
718e3744 7768/* Aggregate route attribute. */
7769#define AGGREGATE_SUMMARY_ONLY 1
7770#define AGGREGATE_AS_SET 1
fb29348a 7771#define AGGREGATE_AS_UNSET 0
718e3744 7772
229757f1
DA
7773static const char *bgp_origin2str(uint8_t origin)
7774{
7775 switch (origin) {
7776 case BGP_ORIGIN_IGP:
7777 return "igp";
7778 case BGP_ORIGIN_EGP:
7779 return "egp";
7780 case BGP_ORIGIN_INCOMPLETE:
7781 return "incomplete";
7782 }
7783 return "n/a";
7784}
7785
fdeb5a81 7786static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7787{
7788 switch (v_state) {
fdeb5a81
DS
7789 case RPKI_NOT_BEING_USED:
7790 return "not used";
7791 case RPKI_VALID:
b5b99af8 7792 return "valid";
fdeb5a81 7793 case RPKI_NOTFOUND:
b5b99af8 7794 return "not found";
fdeb5a81 7795 case RPKI_INVALID:
b5b99af8 7796 return "invalid";
b5b99af8 7797 }
fdeb5a81
DS
7798
7799 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7800 return "ERROR";
7801}
7802
585f1adc
IR
7803static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7804 afi_t afi, safi_t safi)
718e3744 7805{
585f1adc
IR
7806 VTY_DECLVAR_CONTEXT(bgp, bgp);
7807 int ret;
7808 struct prefix p;
9bcb3eef 7809 struct bgp_dest *dest;
d62a17ae 7810 struct bgp_aggregate *aggregate;
718e3744 7811
585f1adc
IR
7812 /* Convert string to prefix structure. */
7813 ret = str2prefix(prefix_str, &p);
7814 if (!ret) {
7815 vty_out(vty, "Malformed prefix\n");
7816 return CMD_WARNING_CONFIG_FAILED;
7817 }
7818 apply_mask(&p);
a4559740 7819
d62a17ae 7820 /* Old configuration check. */
585f1adc 7821 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 7822 if (!dest) {
585f1adc
IR
7823 vty_out(vty,
7824 "%% There is no aggregate-address configuration.\n");
7825 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7826 }
f6269b4f 7827
9bcb3eef 7828 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
7829 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
7830 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
7831 NULL, NULL, 0, aggregate);
d62a17ae 7832
7833 /* Unlock aggregate address configuration. */
9bcb3eef 7834 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7835
7836 if (aggregate->community)
7837 community_free(&aggregate->community);
7838
7839 if (aggregate->community_hash) {
7840 /* Delete all communities in the hash.
7841 */
7842 hash_clean(aggregate->community_hash,
7843 bgp_aggr_community_remove);
7844 /* Free up the community_hash.
7845 */
7846 hash_free(aggregate->community_hash);
7847 }
7848
7849 if (aggregate->ecommunity)
7850 ecommunity_free(&aggregate->ecommunity);
7851
7852 if (aggregate->ecommunity_hash) {
7853 /* Delete all ecommunities in the hash.
7854 */
7855 hash_clean(aggregate->ecommunity_hash,
7856 bgp_aggr_ecommunity_remove);
7857 /* Free up the ecommunity_hash.
7858 */
7859 hash_free(aggregate->ecommunity_hash);
7860 }
7861
7862 if (aggregate->lcommunity)
7863 lcommunity_free(&aggregate->lcommunity);
7864
7865 if (aggregate->lcommunity_hash) {
7866 /* Delete all lcommunities in the hash.
7867 */
7868 hash_clean(aggregate->lcommunity_hash,
7869 bgp_aggr_lcommunity_remove);
7870 /* Free up the lcommunity_hash.
7871 */
7872 hash_free(aggregate->lcommunity_hash);
7873 }
7874
7875 if (aggregate->aspath)
7876 aspath_free(aggregate->aspath);
7877
7878 if (aggregate->aspath_hash) {
7879 /* Delete all as-paths in the hash.
7880 */
7881 hash_clean(aggregate->aspath_hash,
7882 bgp_aggr_aspath_remove);
7883 /* Free up the aspath_hash.
7884 */
7885 hash_free(aggregate->aspath_hash);
7886 }
7887
d62a17ae 7888 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7889 bgp_dest_unlock_node(dest);
7890 bgp_dest_unlock_node(dest);
d62a17ae 7891
585f1adc 7892 return CMD_SUCCESS;
d62a17ae 7893}
7894
585f1adc
IR
7895static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
7896 safi_t safi, const char *rmap,
7897 uint8_t summary_only, uint8_t as_set,
7898 uint8_t origin, bool match_med,
7899 const char *suppress_map)
d62a17ae 7900{
585f1adc 7901 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 7902 int ret;
585f1adc 7903 struct prefix p;
9bcb3eef 7904 struct bgp_dest *dest;
d62a17ae 7905 struct bgp_aggregate *aggregate;
fb29348a 7906 uint8_t as_set_new = as_set;
d62a17ae 7907
365ab2e7 7908 if (suppress_map && summary_only) {
585f1adc 7909 vty_out(vty,
365ab2e7 7910 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 7911 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
7912 }
7913
585f1adc
IR
7914 /* Convert string to prefix structure. */
7915 ret = str2prefix(prefix_str, &p);
7916 if (!ret) {
7917 vty_out(vty, "Malformed prefix\n");
7918 return CMD_WARNING_CONFIG_FAILED;
7919 }
7920 apply_mask(&p);
d62a17ae 7921
585f1adc
IR
7922 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
7923 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
7924 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7925 prefix_str);
7926 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
7927 }
7928
d62a17ae 7929 /* Old configuration check. */
585f1adc 7930 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 7931 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7932
20894f50 7933 if (aggregate) {
585f1adc 7934 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 7935 /* try to remove the old entry */
585f1adc 7936 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 7937 if (ret) {
585f1adc 7938 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 7939 bgp_dest_unlock_node(dest);
585f1adc 7940 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7941 }
7942 }
718e3744 7943
d62a17ae 7944 /* Make aggregate address structure. */
7945 aggregate = bgp_aggregate_new();
7946 aggregate->summary_only = summary_only;
6aabb15d 7947 aggregate->match_med = match_med;
fb29348a
DA
7948
7949 /* Network operators MUST NOT locally generate any new
7950 * announcements containing AS_SET or AS_CONFED_SET. If they have
7951 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7952 * SHOULD withdraw those routes and re-announce routes for the
7953 * aggregate or component prefixes (i.e., the more-specific routes
7954 * subsumed by the previously aggregated route) without AS_SET
7955 * or AS_CONFED_SET in the updates.
7956 */
7f972cd8 7957 if (bgp->reject_as_sets) {
fb29348a
DA
7958 if (as_set == AGGREGATE_AS_SET) {
7959 as_set_new = AGGREGATE_AS_UNSET;
7960 zlog_warn(
63efca0e 7961 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7962 __func__);
585f1adc 7963 vty_out(vty,
fb29348a
DA
7964 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7965 }
7966 }
7967
7968 aggregate->as_set = as_set_new;
d62a17ae 7969 aggregate->safi = safi;
229757f1
DA
7970 /* Override ORIGIN attribute if defined.
7971 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7972 * to IGP which is not what rfc4271 says.
7973 * This enables the same behavior, optionally.
7974 */
7975 aggregate->origin = origin;
20894f50
DA
7976
7977 if (rmap) {
7978 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7979 route_map_counter_decrement(aggregate->rmap.map);
7980 aggregate->rmap.name =
7981 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7982 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7983 route_map_counter_increment(aggregate->rmap.map);
7984 }
365ab2e7
RZ
7985
7986 if (suppress_map) {
7987 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7988 route_map_counter_decrement(aggregate->suppress_map);
7989
7990 aggregate->suppress_map_name =
7991 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7992 aggregate->suppress_map =
7993 route_map_lookup_by_name(aggregate->suppress_map_name);
7994 route_map_counter_increment(aggregate->suppress_map);
7995 }
7996
9bcb3eef 7997 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7998
d62a17ae 7999 /* Aggregate address insert into BGP routing table. */
585f1adc 8000 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8001
585f1adc 8002 return CMD_SUCCESS;
718e3744 8003}
8004
585f1adc
IR
8005DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8006 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8007 "as-set$as_set_s"
8008 "|summary-only$summary_only"
8009 "|route-map WORD$rmap_name"
8010 "|origin <egp|igp|incomplete>$origin_s"
8011 "|matching-MED-only$match_med"
8012 "|suppress-map WORD$suppress_map"
8013 "}]",
8014 NO_STR
8015 "Configure BGP aggregate entries\n"
8016 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8017 "Generate AS set path information\n"
8018 "Filter more specific routes from updates\n"
8019 "Apply route map to aggregate network\n"
8020 "Route map name\n"
8021 "BGP origin code\n"
8022 "Remote EGP\n"
8023 "Local IGP\n"
8024 "Unknown heritage\n"
8025 "Only aggregate routes with matching MED\n"
8026 "Suppress the selected more specific routes\n"
8027 "Route map with the route selectors\n")
8028{
8029 const char *prefix_s = NULL;
554b3b10 8030 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8031 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8032 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8033 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8034
554b3b10 8035 if (addr_str) {
7533cad7
QY
8036 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8037 sizeof(prefix_buf))
554b3b10
RZ
8038 == 0) {
8039 vty_out(vty, "%% Inconsistent address and mask\n");
8040 return CMD_WARNING_CONFIG_FAILED;
8041 }
585f1adc
IR
8042 prefix_s = prefix_buf;
8043 } else
8044 prefix_s = prefix_str;
37a87b8f 8045
585f1adc
IR
8046 if (origin_s) {
8047 if (strcmp(origin_s, "egp") == 0)
8048 origin = BGP_ORIGIN_EGP;
8049 else if (strcmp(origin_s, "igp") == 0)
8050 origin = BGP_ORIGIN_IGP;
8051 else if (strcmp(origin_s, "incomplete") == 0)
8052 origin = BGP_ORIGIN_INCOMPLETE;
8053 }
90e21f35 8054
585f1adc
IR
8055 if (as_set_s)
8056 as_set = AGGREGATE_AS_SET;
554b3b10 8057
585f1adc 8058 /* Handle configuration removal, otherwise installation. */
554b3b10 8059 if (no)
585f1adc
IR
8060 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8061
8062 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8063 summary_only != NULL, as_set, origin,
8064 match_med != NULL, suppress_map);
8065}
8066
8067DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8068 "[no] aggregate-address X:X::X:X/M$prefix [{"
8069 "as-set$as_set_s"
8070 "|summary-only$summary_only"
8071 "|route-map WORD$rmap_name"
8072 "|origin <egp|igp|incomplete>$origin_s"
8073 "|matching-MED-only$match_med"
8074 "|suppress-map WORD$suppress_map"
8075 "}]",
8076 NO_STR
8077 "Configure BGP aggregate entries\n"
8078 "Aggregate prefix\n"
8079 "Generate AS set path information\n"
8080 "Filter more specific routes from updates\n"
8081 "Apply route map to aggregate network\n"
8082 "Route map name\n"
8083 "BGP origin code\n"
8084 "Remote EGP\n"
8085 "Local IGP\n"
8086 "Unknown heritage\n"
8087 "Only aggregate routes with matching MED\n"
8088 "Suppress the selected more specific routes\n"
8089 "Route map with the route selectors\n")
8090{
8091 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8092 int as_set = AGGREGATE_AS_UNSET;
8093
8094 if (origin_s) {
8095 if (strcmp(origin_s, "egp") == 0)
8096 origin = BGP_ORIGIN_EGP;
8097 else if (strcmp(origin_s, "igp") == 0)
8098 origin = BGP_ORIGIN_IGP;
8099 else if (strcmp(origin_s, "incomplete") == 0)
8100 origin = BGP_ORIGIN_INCOMPLETE;
8101 }
8102
8103 if (as_set_s)
8104 as_set = AGGREGATE_AS_SET;
8105
8106 /* Handle configuration removal, otherwise installation. */
554b3b10 8107 if (no)
585f1adc
IR
8108 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8109 SAFI_UNICAST);
554b3b10 8110
585f1adc
IR
8111 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8112 rmap_name, summary_only != NULL, as_set,
8113 origin, match_med != NULL, suppress_map);
718e3744 8114}
8115
718e3744 8116/* Redistribute route treatment. */
d62a17ae 8117void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8118 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8119 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8120 enum blackhole_type bhtype, uint32_t metric,
8121 uint8_t type, unsigned short instance,
8122 route_tag_t tag)
d62a17ae 8123{
4b7e6066 8124 struct bgp_path_info *new;
40381db7
DS
8125 struct bgp_path_info *bpi;
8126 struct bgp_path_info rmap_path;
9bcb3eef 8127 struct bgp_dest *bn;
d62a17ae 8128 struct attr attr;
8129 struct attr *new_attr;
8130 afi_t afi;
b68885f9 8131 route_map_result_t ret;
d62a17ae 8132 struct bgp_redist *red;
8133
8134 /* Make default attribute. */
8135 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8136 /*
8137 * This must not be NULL to satisfy Coverity SA
8138 */
8139 assert(attr.aspath);
9de1f7ff 8140
a4d82a8a 8141 switch (nhtype) {
9de1f7ff
DS
8142 case NEXTHOP_TYPE_IFINDEX:
8143 break;
8144 case NEXTHOP_TYPE_IPV4:
8145 case NEXTHOP_TYPE_IPV4_IFINDEX:
8146 attr.nexthop = nexthop->ipv4;
8147 break;
8148 case NEXTHOP_TYPE_IPV6:
8149 case NEXTHOP_TYPE_IPV6_IFINDEX:
8150 attr.mp_nexthop_global = nexthop->ipv6;
8151 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8152 break;
8153 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8154 switch (p->family) {
8155 case AF_INET:
9de1f7ff 8156 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8157 break;
8158 case AF_INET6:
9de1f7ff
DS
8159 memset(&attr.mp_nexthop_global, 0,
8160 sizeof(attr.mp_nexthop_global));
74489921 8161 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8162 break;
74489921 8163 }
0789eb69 8164 attr.bh_type = bhtype;
9de1f7ff 8165 break;
d62a17ae 8166 }
0789eb69 8167 attr.nh_type = nhtype;
74489921 8168 attr.nh_ifindex = ifindex;
f04a80a5 8169
d62a17ae 8170 attr.med = metric;
957f74c3 8171 attr.distance = distance;
d62a17ae 8172 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8173 attr.tag = tag;
718e3744 8174
d62a17ae 8175 afi = family2afi(p->family);
6aeb9e78 8176
d62a17ae 8177 red = bgp_redist_lookup(bgp, afi, type, instance);
8178 if (red) {
8179 struct attr attr_new;
718e3744 8180
d62a17ae 8181 /* Copy attribute for modification. */
6f4f49b2 8182 attr_new = attr;
718e3744 8183
d62a17ae 8184 if (red->redist_metric_flag)
8185 attr_new.med = red->redist_metric;
718e3744 8186
d62a17ae 8187 /* Apply route-map. */
8188 if (red->rmap.name) {
40381db7
DS
8189 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8190 rmap_path.peer = bgp->peer_self;
8191 rmap_path.attr = &attr_new;
718e3744 8192
d62a17ae 8193 SET_FLAG(bgp->peer_self->rmap_type,
8194 PEER_RMAP_TYPE_REDISTRIBUTE);
8195
1782514f 8196 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8197
8198 bgp->peer_self->rmap_type = 0;
8199
8200 if (ret == RMAP_DENYMATCH) {
8201 /* Free uninterned attribute. */
8202 bgp_attr_flush(&attr_new);
8203
8204 /* Unintern original. */
8205 aspath_unintern(&attr.aspath);
8206 bgp_redistribute_delete(bgp, p, type, instance);
8207 return;
8208 }
8209 }
8210
637e5ba4 8211 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8212 bgp_attr_add_gshut_community(&attr_new);
8213
d62a17ae 8214 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8215 SAFI_UNICAST, p, NULL);
8216
8217 new_attr = bgp_attr_intern(&attr_new);
8218
9bcb3eef 8219 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8220 if (bpi->peer == bgp->peer_self
8221 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8222 break;
8223
40381db7 8224 if (bpi) {
d62a17ae 8225 /* Ensure the (source route) type is updated. */
40381db7
DS
8226 bpi->type = type;
8227 if (attrhash_cmp(bpi->attr, new_attr)
8228 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8229 bgp_attr_unintern(&new_attr);
8230 aspath_unintern(&attr.aspath);
9bcb3eef 8231 bgp_dest_unlock_node(bn);
d62a17ae 8232 return;
8233 } else {
8234 /* The attribute is changed. */
40381db7 8235 bgp_path_info_set_flag(bn, bpi,
18ee8310 8236 BGP_PATH_ATTR_CHANGED);
d62a17ae 8237
8238 /* Rewrite BGP route information. */
40381db7
DS
8239 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8240 bgp_path_info_restore(bn, bpi);
d62a17ae 8241 else
40381db7
DS
8242 bgp_aggregate_decrement(
8243 bgp, p, bpi, afi, SAFI_UNICAST);
8244 bgp_attr_unintern(&bpi->attr);
8245 bpi->attr = new_attr;
8246 bpi->uptime = bgp_clock();
d62a17ae 8247
8248 /* Process change. */
40381db7 8249 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8250 SAFI_UNICAST);
8251 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8252 bgp_dest_unlock_node(bn);
d62a17ae 8253 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8254
8255 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8256 || (bgp->inst_type
8257 == BGP_INSTANCE_TYPE_DEFAULT)) {
8258
8259 vpn_leak_from_vrf_update(
40381db7 8260 bgp_get_default(), bgp, bpi);
ddb5b488 8261 }
d62a17ae 8262 return;
8263 }
8264 }
8265
8266 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8267 bgp->peer_self, new_attr, bn);
1defdda8 8268 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8269
8270 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8271 bgp_path_info_add(bn, new);
9bcb3eef 8272 bgp_dest_unlock_node(bn);
d62a17ae 8273 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8274
8275 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8276 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8277
8278 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8279 }
d62a17ae 8280 }
8281
8282 /* Unintern original. */
8283 aspath_unintern(&attr.aspath);
718e3744 8284}
8285
d7c0a89a
QY
8286void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8287 unsigned short instance)
718e3744 8288{
d62a17ae 8289 afi_t afi;
9bcb3eef 8290 struct bgp_dest *dest;
40381db7 8291 struct bgp_path_info *pi;
d62a17ae 8292 struct bgp_redist *red;
718e3744 8293
d62a17ae 8294 afi = family2afi(p->family);
718e3744 8295
d62a17ae 8296 red = bgp_redist_lookup(bgp, afi, type, instance);
8297 if (red) {
9bcb3eef
DS
8298 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8299 SAFI_UNICAST, p, NULL);
d62a17ae 8300
9bcb3eef 8301 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8302 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8303 break;
8304
40381db7 8305 if (pi) {
ddb5b488
PZ
8306 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8307 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8308
8309 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8310 bgp, pi);
ddb5b488 8311 }
40381db7 8312 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8313 bgp_path_info_delete(dest, pi);
8314 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8315 }
9bcb3eef 8316 bgp_dest_unlock_node(dest);
d62a17ae 8317 }
8318}
8319
8320/* Withdraw specified route type's route. */
8321void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8322 unsigned short instance)
d62a17ae 8323{
9bcb3eef 8324 struct bgp_dest *dest;
40381db7 8325 struct bgp_path_info *pi;
d62a17ae 8326 struct bgp_table *table;
8327
8328 table = bgp->rib[afi][SAFI_UNICAST];
8329
9bcb3eef
DS
8330 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8331 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8332 if (pi->peer == bgp->peer_self && pi->type == type
8333 && pi->instance == instance)
d62a17ae 8334 break;
8335
40381db7 8336 if (pi) {
ddb5b488
PZ
8337 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8338 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8339
8340 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8341 bgp, pi);
ddb5b488 8342 }
9bcb3eef 8343 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8344 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8345 bgp_path_info_delete(dest, pi);
8346 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8347 }
718e3744 8348 }
718e3744 8349}
6b0655a2 8350
718e3744 8351/* Static function to display route. */
7d3cae70
DA
8352static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8353 struct vty *vty, json_object *json, bool wide)
718e3744 8354{
be054588 8355 int len = 0;
d62a17ae 8356 char buf[BUFSIZ];
50e05855 8357 char buf2[BUFSIZ];
718e3744 8358
d62a17ae 8359 if (p->family == AF_INET) {
c6462ff4 8360 if (!json) {
8228a9a7 8361 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8362 } else {
8363 json_object_string_add(json, "prefix",
8364 inet_ntop(p->family,
8365 &p->u.prefix, buf,
8366 BUFSIZ));
8367 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8368 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8369 json_object_string_add(json, "network", buf2);
7d3cae70 8370 json_object_int_add(json, "version", dest->version);
c6462ff4 8371 }
d62a17ae 8372 } else if (p->family == AF_ETHERNET) {
8228a9a7 8373 len = vty_out(vty, "%pFX", p);
b03b8898 8374 } else if (p->family == AF_EVPN) {
57f7feb6 8375 if (!json)
2dbe669b 8376 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8377 else
60466a63 8378 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8379 } else if (p->family == AF_FLOWSPEC) {
8380 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8381 json ?
8382 NLRI_STRING_FORMAT_JSON_SIMPLE :
8383 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8384 } else {
c6462ff4 8385 if (!json)
8228a9a7 8386 len = vty_out(vty, "%pFX", p);
50e05855
AD
8387 else {
8388 json_object_string_add(json, "prefix",
8389 inet_ntop(p->family,
8390 &p->u.prefix, buf,
8391 BUFSIZ));
8392 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8393 prefix2str(p, buf2, PREFIX_STRLEN);
8394 json_object_string_add(json, "network", buf2);
7d3cae70 8395 json_object_int_add(json, "version", dest->version);
37d4e0df 8396 }
9c92b5f7 8397 }
d62a17ae 8398
9c92b5f7 8399 if (!json) {
ae248832 8400 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8401 if (len < 1)
8402 vty_out(vty, "\n%*s", 20, " ");
8403 else
8404 vty_out(vty, "%*s", len, " ");
8405 }
718e3744 8406}
8407
d62a17ae 8408enum bgp_display_type {
8409 normal_list,
718e3744 8410};
8411
bbb46eb5
DA
8412static const char *
8413bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8414{
8415 switch (reason) {
8416 case bgp_path_selection_none:
8417 return "Nothing to Select";
8418 case bgp_path_selection_first:
8419 return "First path received";
8420 case bgp_path_selection_evpn_sticky_mac:
8421 return "EVPN Sticky Mac";
8422 case bgp_path_selection_evpn_seq:
8423 return "EVPN sequence number";
8424 case bgp_path_selection_evpn_lower_ip:
8425 return "EVPN lower IP";
8426 case bgp_path_selection_evpn_local_path:
8427 return "EVPN local ES path";
8428 case bgp_path_selection_evpn_non_proxy:
8429 return "EVPN non proxy";
8430 case bgp_path_selection_weight:
8431 return "Weight";
8432 case bgp_path_selection_local_pref:
8433 return "Local Pref";
8434 case bgp_path_selection_local_route:
8435 return "Local Route";
8436 case bgp_path_selection_confed_as_path:
8437 return "Confederation based AS Path";
8438 case bgp_path_selection_as_path:
8439 return "AS Path";
8440 case bgp_path_selection_origin:
8441 return "Origin";
8442 case bgp_path_selection_med:
8443 return "MED";
8444 case bgp_path_selection_peer:
8445 return "Peer Type";
8446 case bgp_path_selection_confed:
8447 return "Confed Peer Type";
8448 case bgp_path_selection_igp_metric:
8449 return "IGP Metric";
8450 case bgp_path_selection_older:
8451 return "Older Path";
8452 case bgp_path_selection_router_id:
8453 return "Router ID";
8454 case bgp_path_selection_cluster_length:
bcab253c 8455 return "Cluster length";
bbb46eb5
DA
8456 case bgp_path_selection_stale:
8457 return "Path Staleness";
8458 case bgp_path_selection_local_configured:
8459 return "Locally configured route";
8460 case bgp_path_selection_neighbor_ip:
8461 return "Neighbor IP";
8462 case bgp_path_selection_default:
8463 return "Nothing left to compare";
8464 }
8465 return "Invalid (internal error)";
8466}
8467
18ee8310 8468/* Print the short form route status for a bgp_path_info */
4b7e6066 8469static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8470 struct bgp_path_info *path,
82c298be 8471 const struct prefix *p,
d62a17ae 8472 json_object *json_path)
718e3744 8473{
82c298be
DA
8474 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8475
d62a17ae 8476 if (json_path) {
b05a1c8b 8477
d62a17ae 8478 /* Route status display. */
9b6d8fcf 8479 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8480 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8481
9b6d8fcf 8482 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8483 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8484
4056a5f6 8485 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8486 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8487
9b6d8fcf
DS
8488 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8489 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8490 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8491
d62a17ae 8492 /* Selected */
9b6d8fcf 8493 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8494 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8495
9b6d8fcf 8496 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8497 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8498
bbb46eb5 8499 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8500 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8501 json_object_string_add(json_path, "selectionReason",
8502 bgp_path_selection_reason2str(
8503 path->net->reason));
8504 }
b05a1c8b 8505
9b6d8fcf 8506 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8507 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8508
d62a17ae 8509 /* Internal route. */
9b6d8fcf
DS
8510 if ((path->peer->as)
8511 && (path->peer->as == path->peer->local_as))
d62a17ae 8512 json_object_string_add(json_path, "pathFrom",
8513 "internal");
8514 else
8515 json_object_string_add(json_path, "pathFrom",
8516 "external");
b05a1c8b 8517
d62a17ae 8518 return;
8519 }
b05a1c8b 8520
82c298be
DA
8521 /* RPKI validation state */
8522 rpki_state =
8523 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8524
8525 if (rpki_state == RPKI_VALID)
8526 vty_out(vty, "V");
8527 else if (rpki_state == RPKI_INVALID)
8528 vty_out(vty, "I");
8529 else if (rpki_state == RPKI_NOTFOUND)
8530 vty_out(vty, "N");
8531
d62a17ae 8532 /* Route status display. */
9b6d8fcf 8533 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8534 vty_out(vty, "R");
9b6d8fcf 8535 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8536 vty_out(vty, "S");
4056a5f6 8537 else if (bgp_path_suppressed(path))
d62a17ae 8538 vty_out(vty, "s");
9b6d8fcf
DS
8539 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8540 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8541 vty_out(vty, "*");
8542 else
8543 vty_out(vty, " ");
8544
8545 /* Selected */
9b6d8fcf 8546 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8547 vty_out(vty, "h");
9b6d8fcf 8548 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8549 vty_out(vty, "d");
9b6d8fcf 8550 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8551 vty_out(vty, ">");
9b6d8fcf 8552 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8553 vty_out(vty, "=");
8554 else
8555 vty_out(vty, " ");
718e3744 8556
d62a17ae 8557 /* Internal route. */
9b6d8fcf
DS
8558 if (path->peer && (path->peer->as)
8559 && (path->peer->as == path->peer->local_as))
d62a17ae 8560 vty_out(vty, "i");
8561 else
8562 vty_out(vty, " ");
b40d939b 8563}
8564
2ba93fd6
DA
8565static char *bgp_nexthop_hostname(struct peer *peer,
8566 struct bgp_nexthop_cache *bnc)
25b5da8d 8567{
892fedb6 8568 if (peer->hostname
aef999a2 8569 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8570 return peer->hostname;
8571 return NULL;
8572}
8573
b40d939b 8574/* called from terminal list command */
bd494ec5 8575void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8576 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8577 json_object *json_paths, bool wide)
d62a17ae 8578{
aef999a2 8579 int len;
515c2602 8580 struct attr *attr = path->attr;
d62a17ae 8581 json_object *json_path = NULL;
8582 json_object *json_nexthops = NULL;
8583 json_object *json_nexthop_global = NULL;
8584 json_object *json_nexthop_ll = NULL;
6f214dd3 8585 json_object *json_ext_community = NULL;
9df8b37c 8586 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8587 bool nexthop_self =
9b6d8fcf 8588 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8589 bool nexthop_othervrf = false;
43089216 8590 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8591 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8592 char *nexthop_hostname =
8593 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8594 char esi_buf[ESI_STR_LEN];
d62a17ae 8595
8596 if (json_paths)
8597 json_path = json_object_new_object();
8598
8599 /* short status lead text */
82c298be 8600 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8601
8602 if (!json_paths) {
8603 /* print prefix and mask */
8604 if (!display)
7d3cae70 8605 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8606 else
ae248832 8607 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8608 } else {
7d3cae70 8609 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8610 }
47fc97cc 8611
9df8b37c
PZ
8612 /*
8613 * If vrf id of nexthop is different from that of prefix,
8614 * set up printable string to append
8615 */
9b6d8fcf 8616 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8617 const char *self = "";
8618
8619 if (nexthop_self)
8620 self = "<";
8621
8622 nexthop_othervrf = true;
9b6d8fcf 8623 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8624
9b6d8fcf 8625 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8626 snprintf(vrf_id_str, sizeof(vrf_id_str),
8627 "@%s%s", VRFID_NONE_STR, self);
8628 else
8629 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8630 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8631
9b6d8fcf
DS
8632 if (path->extra->bgp_orig->inst_type
8633 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8634
9b6d8fcf 8635 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8636 } else {
8637 const char *self = "";
8638
8639 if (nexthop_self)
8640 self = "<";
8641
8642 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8643 }
8644
445c2480
DS
8645 /*
8646 * For ENCAP and EVPN routes, nexthop address family is not
8647 * neccessarily the same as the prefix address family.
8648 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8649 * EVPN routes are also exchanged with a MP nexthop. Currently,
8650 * this
8651 * is only IPv4, the value will be present in either
8652 * attr->nexthop or
8653 * attr->mp_nexthop_global_in
8654 */
8655 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8656 char buf[BUFSIZ];
8657 char nexthop[128];
8658 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8659
8660 switch (af) {
8661 case AF_INET:
772270f3
QY
8662 snprintf(nexthop, sizeof(nexthop), "%s",
8663 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8664 BUFSIZ));
445c2480
DS
8665 break;
8666 case AF_INET6:
772270f3
QY
8667 snprintf(nexthop, sizeof(nexthop), "%s",
8668 inet_ntop(af, &attr->mp_nexthop_global, buf,
8669 BUFSIZ));
445c2480
DS
8670 break;
8671 default:
772270f3 8672 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8673 break;
d62a17ae 8674 }
d62a17ae 8675
445c2480
DS
8676 if (json_paths) {
8677 json_nexthop_global = json_object_new_object();
8678
515c2602
DA
8679 json_object_string_add(json_nexthop_global, "ip",
8680 nexthop);
8681
939a97f4 8682 if (path->peer->hostname)
515c2602
DA
8683 json_object_string_add(json_nexthop_global,
8684 "hostname",
939a97f4 8685 path->peer->hostname);
515c2602
DA
8686
8687 json_object_string_add(json_nexthop_global, "afi",
8688 (af == AF_INET) ? "ipv4"
8689 : "ipv6");
445c2480
DS
8690 json_object_boolean_true_add(json_nexthop_global,
8691 "used");
aef999a2
DA
8692 } else {
8693 if (nexthop_hostname)
8694 len = vty_out(vty, "%s(%s)%s", nexthop,
8695 nexthop_hostname, vrf_id_str);
8696 else
8697 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8698
ae248832 8699 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8700 if (len < 1)
8701 vty_out(vty, "\n%*s", 36, " ");
8702 else
8703 vty_out(vty, "%*s", len, " ");
8704 }
445c2480
DS
8705 } else if (safi == SAFI_EVPN) {
8706 if (json_paths) {
23d0a753
DA
8707 char buf[BUFSIZ] = {0};
8708
445c2480
DS
8709 json_nexthop_global = json_object_new_object();
8710
515c2602 8711 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8712 inet_ntop(AF_INET,
8713 &attr->nexthop, buf,
8714 sizeof(buf)));
515c2602 8715
939a97f4 8716 if (path->peer->hostname)
515c2602
DA
8717 json_object_string_add(json_nexthop_global,
8718 "hostname",
939a97f4 8719 path->peer->hostname);
515c2602 8720
a4d82a8a
PZ
8721 json_object_string_add(json_nexthop_global, "afi",
8722 "ipv4");
445c2480
DS
8723 json_object_boolean_true_add(json_nexthop_global,
8724 "used");
aef999a2
DA
8725 } else {
8726 if (nexthop_hostname)
8727 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8728 nexthop_hostname, vrf_id_str);
8729 else
8730 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8731 vrf_id_str);
8732
ae248832 8733 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8734 if (len < 1)
8735 vty_out(vty, "\n%*s", 36, " ");
8736 else
8737 vty_out(vty, "%*s", len, " ");
8738 }
d33fc23b 8739 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8740 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8741 if (json_paths) {
23d0a753
DA
8742 char buf[BUFSIZ] = {0};
8743
026b914a 8744 json_nexthop_global = json_object_new_object();
515c2602 8745
026b914a
PG
8746 json_object_string_add(json_nexthop_global,
8747 "afi", "ipv4");
515c2602
DA
8748 json_object_string_add(
8749 json_nexthop_global, "ip",
23d0a753
DA
8750 inet_ntop(AF_INET, &attr->nexthop, buf,
8751 sizeof(buf)));
515c2602 8752
939a97f4 8753 if (path->peer->hostname)
515c2602
DA
8754 json_object_string_add(
8755 json_nexthop_global, "hostname",
939a97f4 8756 path->peer->hostname);
515c2602 8757
50e05855
AD
8758 json_object_boolean_true_add(
8759 json_nexthop_global,
026b914a
PG
8760 "used");
8761 } else {
aef999a2
DA
8762 if (nexthop_hostname)
8763 len = vty_out(vty, "%pI4(%s)%s",
8764 &attr->nexthop,
8765 nexthop_hostname,
8766 vrf_id_str);
8767 else
8768 len = vty_out(vty, "%pI4%s",
8769 &attr->nexthop,
8770 vrf_id_str);
8771
ae248832 8772 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8773 if (len < 1)
8774 vty_out(vty, "\n%*s", 36, " ");
8775 else
8776 vty_out(vty, "%*s", len, " ");
026b914a
PG
8777 }
8778 }
d33fc23b 8779 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8780 if (json_paths) {
23d0a753
DA
8781 char buf[BUFSIZ] = {0};
8782
445c2480 8783 json_nexthop_global = json_object_new_object();
d62a17ae 8784
515c2602 8785 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8786 inet_ntop(AF_INET,
8787 &attr->nexthop, buf,
8788 sizeof(buf)));
515c2602 8789
939a97f4 8790 if (path->peer->hostname)
515c2602
DA
8791 json_object_string_add(json_nexthop_global,
8792 "hostname",
939a97f4 8793 path->peer->hostname);
445c2480 8794
a4d82a8a
PZ
8795 json_object_string_add(json_nexthop_global, "afi",
8796 "ipv4");
445c2480
DS
8797 json_object_boolean_true_add(json_nexthop_global,
8798 "used");
8799 } else {
aef999a2
DA
8800 if (nexthop_hostname)
8801 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8802 nexthop_hostname, vrf_id_str);
8803 else
8804 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8805 vrf_id_str);
9df8b37c 8806
ae248832 8807 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8808 if (len < 1)
8809 vty_out(vty, "\n%*s", 36, " ");
8810 else
8811 vty_out(vty, "%*s", len, " ");
d62a17ae 8812 }
445c2480 8813 }
b05a1c8b 8814
445c2480 8815 /* IPv6 Next Hop */
a4d82a8a 8816 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8817 char buf[BUFSIZ];
d62a17ae 8818
445c2480
DS
8819 if (json_paths) {
8820 json_nexthop_global = json_object_new_object();
a4d82a8a 8821 json_object_string_add(
515c2602
DA
8822 json_nexthop_global, "ip",
8823 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8824 buf, BUFSIZ));
8825
939a97f4 8826 if (path->peer->hostname)
515c2602
DA
8827 json_object_string_add(json_nexthop_global,
8828 "hostname",
939a97f4 8829 path->peer->hostname);
515c2602 8830
a4d82a8a
PZ
8831 json_object_string_add(json_nexthop_global, "afi",
8832 "ipv6");
8833 json_object_string_add(json_nexthop_global, "scope",
8834 "global");
445c2480
DS
8835
8836 /* We display both LL & GL if both have been
8837 * received */
0606039c
DA
8838 if ((attr->mp_nexthop_len
8839 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8840 || (path->peer->conf_if)) {
a4d82a8a 8841 json_nexthop_ll = json_object_new_object();
d62a17ae 8842 json_object_string_add(
515c2602
DA
8843 json_nexthop_ll, "ip",
8844 inet_ntop(AF_INET6,
8845 &attr->mp_nexthop_local, buf,
8846 BUFSIZ));
8847
939a97f4 8848 if (path->peer->hostname)
515c2602
DA
8849 json_object_string_add(
8850 json_nexthop_ll, "hostname",
939a97f4 8851 path->peer->hostname);
515c2602 8852
a4d82a8a
PZ
8853 json_object_string_add(json_nexthop_ll, "afi",
8854 "ipv6");
8855 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8856 "link-local");
d62a17ae 8857
a4d82a8a
PZ
8858 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8859 &attr->mp_nexthop_local)
445c2480
DS
8860 != 0)
8861 && !attr->mp_nexthop_prefer_global)
d62a17ae 8862 json_object_boolean_true_add(
a4d82a8a 8863 json_nexthop_ll, "used");
445c2480
DS
8864 else
8865 json_object_boolean_true_add(
a4d82a8a 8866 json_nexthop_global, "used");
445c2480
DS
8867 } else
8868 json_object_boolean_true_add(
8869 json_nexthop_global, "used");
8870 } else {
8871 /* Display LL if LL/Global both in table unless
8872 * prefer-global is set */
0606039c
DA
8873 if (((attr->mp_nexthop_len
8874 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8875 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8876 || (path->peer->conf_if)) {
8877 if (path->peer->conf_if) {
a4d82a8a 8878 len = vty_out(vty, "%s",
9b6d8fcf 8879 path->peer->conf_if);
ae248832
MK
8880 /* len of IPv6 addr + max len of def
8881 * ifname */
8882 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8883
8884 if (len < 1)
a4d82a8a 8885 vty_out(vty, "\n%*s", 36, " ");
445c2480 8886 else
a4d82a8a 8887 vty_out(vty, "%*s", len, " ");
d62a17ae 8888 } else {
aef999a2
DA
8889 if (nexthop_hostname)
8890 len = vty_out(
8891 vty, "%pI6(%s)%s",
8892 &attr->mp_nexthop_local,
8893 nexthop_hostname,
8894 vrf_id_str);
8895 else
8896 len = vty_out(
8897 vty, "%pI6%s",
8898 &attr->mp_nexthop_local,
8899 vrf_id_str);
8900
ae248832 8901 len = wide ? (41 - len) : (16 - len);
d62a17ae 8902
8903 if (len < 1)
a4d82a8a 8904 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8905 else
a4d82a8a 8906 vty_out(vty, "%*s", len, " ");
d62a17ae 8907 }
445c2480 8908 } else {
aef999a2
DA
8909 if (nexthop_hostname)
8910 len = vty_out(vty, "%pI6(%s)%s",
8911 &attr->mp_nexthop_global,
8912 nexthop_hostname,
8913 vrf_id_str);
8914 else
8915 len = vty_out(vty, "%pI6%s",
8916 &attr->mp_nexthop_global,
8917 vrf_id_str);
8918
ae248832 8919 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8920
8921 if (len < 1)
8922 vty_out(vty, "\n%*s", 36, " ");
8923 else
8924 vty_out(vty, "%*s", len, " ");
d62a17ae 8925 }
8926 }
445c2480 8927 }
718e3744 8928
445c2480
DS
8929 /* MED/Metric */
8930 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8931 if (json_paths)
50e05855 8932 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8933 else if (wide)
8934 vty_out(vty, "%7u", attr->med);
0fbac0b4 8935 else
445c2480 8936 vty_out(vty, "%10u", attr->med);
ae248832
MK
8937 else if (!json_paths) {
8938 if (wide)
8939 vty_out(vty, "%*s", 7, " ");
8940 else
8941 vty_out(vty, "%*s", 10, " ");
8942 }
d62a17ae 8943
445c2480
DS
8944 /* Local Pref */
8945 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8946 if (json_paths)
50e05855 8947 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8948 attr->local_pref);
8949 else
445c2480
DS
8950 vty_out(vty, "%7u", attr->local_pref);
8951 else if (!json_paths)
8952 vty_out(vty, " ");
d62a17ae 8953
445c2480
DS
8954 if (json_paths)
8955 json_object_int_add(json_path, "weight", attr->weight);
8956 else
8957 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8958
445c2480
DS
8959 if (json_paths) {
8960 char buf[BUFSIZ];
a4d82a8a
PZ
8961 json_object_string_add(
8962 json_path, "peerId",
9b6d8fcf 8963 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8964 }
b05a1c8b 8965
445c2480
DS
8966 /* Print aspath */
8967 if (attr->aspath) {
0fbac0b4 8968 if (json_paths)
50e05855 8969 json_object_string_add(json_path, "path",
0fbac0b4
DA
8970 attr->aspath->str);
8971 else
445c2480 8972 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8973 }
f1aa5d8a 8974
445c2480
DS
8975 /* Print origin */
8976 if (json_paths)
a4d82a8a
PZ
8977 json_object_string_add(json_path, "origin",
8978 bgp_origin_long_str[attr->origin]);
445c2480
DS
8979 else
8980 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8981
9df8b37c 8982 if (json_paths) {
d071f237 8983 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8984 json_object_string_add(json_path, "esi",
8985 esi_to_str(&attr->esi,
8986 esi_buf, sizeof(esi_buf)));
8987 }
6f214dd3
CS
8988 if (safi == SAFI_EVPN &&
8989 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8990 json_ext_community = json_object_new_object();
8991 json_object_string_add(json_ext_community,
8992 "string",
8993 attr->ecommunity->str);
8994 json_object_object_add(json_path,
8995 "extendedCommunity",
8996 json_ext_community);
8997 }
8998
9df8b37c
PZ
8999 if (nexthop_self)
9000 json_object_boolean_true_add(json_path,
9001 "announceNexthopSelf");
9002 if (nexthop_othervrf) {
9003 json_object_string_add(json_path, "nhVrfName",
9004 nexthop_vrfname);
9005
9006 json_object_int_add(json_path, "nhVrfId",
9007 ((nexthop_vrfid == VRF_UNKNOWN)
9008 ? -1
9009 : (int)nexthop_vrfid));
9010 }
9011 }
9012
d62a17ae 9013 if (json_paths) {
9014 if (json_nexthop_global || json_nexthop_ll) {
9015 json_nexthops = json_object_new_array();
f1aa5d8a 9016
d62a17ae 9017 if (json_nexthop_global)
9018 json_object_array_add(json_nexthops,
9019 json_nexthop_global);
f1aa5d8a 9020
d62a17ae 9021 if (json_nexthop_ll)
9022 json_object_array_add(json_nexthops,
9023 json_nexthop_ll);
f1aa5d8a 9024
d62a17ae 9025 json_object_object_add(json_path, "nexthops",
9026 json_nexthops);
9027 }
9028
9029 json_object_array_add(json_paths, json_path);
9030 } else {
9031 vty_out(vty, "\n");
6f214dd3 9032
b5e140c8 9033 if (safi == SAFI_EVPN) {
d071f237 9034 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9035 /* XXX - add these params to the json out */
b5e140c8 9036 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9037 vty_out(vty, "ESI:%s",
9038 esi_to_str(&attr->esi, esi_buf,
9039 sizeof(esi_buf)));
60605cbc 9040
229587fb 9041 vty_out(vty, "\n");
b5e140c8
AK
9042 }
9043 if (attr->flag &
9044 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9045 vty_out(vty, "%*s", 20, " ");
9046 vty_out(vty, "%s\n", attr->ecommunity->str);
9047 }
6f214dd3
CS
9048 }
9049
49e5a4a0 9050#ifdef ENABLE_BGP_VNC
d62a17ae 9051 /* prints an additional line, indented, with VNC info, if
9052 * present */
9053 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9054 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9055#endif
d62a17ae 9056 }
9057}
718e3744 9058
9059/* called from terminal list command */
7d3cae70
DA
9060void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9061 const struct prefix *p, struct attr *attr, safi_t safi,
9062 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9063{
9064 json_object *json_status = NULL;
9065 json_object *json_net = NULL;
aef999a2 9066 int len;
d62a17ae 9067 char buff[BUFSIZ];
dc387b0f 9068
d62a17ae 9069 /* Route status display. */
9070 if (use_json) {
9071 json_status = json_object_new_object();
9072 json_net = json_object_new_object();
9073 } else {
9074 vty_out(vty, "*");
9075 vty_out(vty, ">");
9076 vty_out(vty, " ");
9077 }
718e3744 9078
d62a17ae 9079 /* print prefix and mask */
50e05855 9080 if (use_json) {
dc387b0f
LK
9081 if (safi == SAFI_EVPN)
9082 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9083 else if (p->family == AF_INET || p->family == AF_INET6) {
9084 json_object_string_add(
9085 json_net, "addrPrefix",
9086 inet_ntop(p->family, &p->u.prefix, buff,
9087 BUFSIZ));
9088 json_object_int_add(json_net, "prefixLen",
9089 p->prefixlen);
9090 prefix2str(p, buff, PREFIX_STRLEN);
9091 json_object_string_add(json_net, "network", buff);
9092 }
50e05855 9093 } else
7d3cae70 9094 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9095
9096 /* Print attribute */
9097 if (attr) {
9098 if (use_json) {
23d0a753
DA
9099 char buf[BUFSIZ] = {0};
9100
d62a17ae 9101 if (p->family == AF_INET
9102 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9103 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9104 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 9105 json_object_string_add(
9106 json_net, "nextHop",
23d0a753
DA
9107 inet_ntop(
9108 AF_INET,
9109 &attr->mp_nexthop_global_in,
9110 buf, sizeof(buf)));
d62a17ae 9111 else
9112 json_object_string_add(
9113 json_net, "nextHop",
23d0a753
DA
9114 inet_ntop(AF_INET,
9115 &attr->nexthop, buf,
9116 sizeof(buf)));
d62a17ae 9117 } else if (p->family == AF_INET6
9118 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9119 char buf[BUFSIZ];
9120
9121 json_object_string_add(
aa0a10fc 9122 json_net, "nextHopGlobal",
d62a17ae 9123 inet_ntop(AF_INET6,
9124 &attr->mp_nexthop_global, buf,
9125 BUFSIZ));
23d0a753
DA
9126 } else if (p->family == AF_EVPN
9127 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9128 char buf[BUFSIZ] = {0};
9129
9130 json_object_string_add(
9131 json_net, "nextHop",
9132 inet_ntop(AF_INET,
9133 &attr->mp_nexthop_global_in,
9134 buf, sizeof(buf)));
9135 }
d62a17ae 9136
9137 if (attr->flag
9138 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9139 json_object_int_add(json_net, "metric",
9140 attr->med);
9141
0fbac0b4 9142 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9143 json_object_int_add(json_net, "locPrf",
0fbac0b4 9144 attr->local_pref);
d62a17ae 9145
9146 json_object_int_add(json_net, "weight", attr->weight);
9147
9148 /* Print aspath */
0fbac0b4 9149 if (attr->aspath)
50e05855 9150 json_object_string_add(json_net, "path",
0fbac0b4 9151 attr->aspath->str);
d62a17ae 9152
9153 /* Print origin */
9154 json_object_string_add(json_net, "bgpOriginCode",
9155 bgp_origin_str[attr->origin]);
9156 } else {
9157 if (p->family == AF_INET
9158 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9159 || safi == SAFI_EVPN
9160 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9161 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9162 || safi == SAFI_EVPN)
23d0a753
DA
9163 vty_out(vty, "%-16pI4",
9164 &attr->mp_nexthop_global_in);
ae248832 9165 else if (wide)
23d0a753 9166 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9167 else
23d0a753 9168 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9169 } else if (p->family == AF_INET6
9170 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9171 char buf[BUFSIZ];
9172
9173 len = vty_out(
9174 vty, "%s",
9175 inet_ntop(AF_INET6,
9176 &attr->mp_nexthop_global, buf,
9177 BUFSIZ));
ae248832 9178 len = wide ? (41 - len) : (16 - len);
d62a17ae 9179 if (len < 1)
9180 vty_out(vty, "\n%*s", 36, " ");
9181 else
9182 vty_out(vty, "%*s", len, " ");
9183 }
9184 if (attr->flag
9185 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9186 if (wide)
9187 vty_out(vty, "%7u", attr->med);
9188 else
9189 vty_out(vty, "%10u", attr->med);
9190 else if (wide)
9191 vty_out(vty, " ");
d62a17ae 9192 else
9193 vty_out(vty, " ");
718e3744 9194
d62a17ae 9195 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9196 vty_out(vty, "%7u", attr->local_pref);
9197 else
9198 vty_out(vty, " ");
9199
9200 vty_out(vty, "%7u ", attr->weight);
9201
9202 /* Print aspath */
9203 if (attr->aspath)
9204 aspath_print_vty(vty, "%s", attr->aspath, " ");
9205
9206 /* Print origin */
9207 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9208 }
9209 }
9210 if (use_json) {
9211 json_object_boolean_true_add(json_status, "*");
9212 json_object_boolean_true_add(json_status, ">");
9213 json_object_object_add(json_net, "appliedStatusSymbols",
9214 json_status);
1608ff77 9215
dc387b0f
LK
9216 prefix2str(p, buff, PREFIX_STRLEN);
9217 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9218 } else
9219 vty_out(vty, "\n");
9220}
9221
bd494ec5 9222void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9223 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9224 json_object *json)
9225{
9226 json_object *json_out = NULL;
9227 struct attr *attr;
9228 mpls_label_t label = MPLS_INVALID_LABEL;
9229
9b6d8fcf 9230 if (!path->extra)
d62a17ae 9231 return;
9232
9233 if (json)
9234 json_out = json_object_new_object();
9235
9236 /* short status lead text */
82c298be 9237 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9238
9239 /* print prefix and mask */
9240 if (json == NULL) {
9241 if (!display)
7d3cae70 9242 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9243 else
9244 vty_out(vty, "%*s", 17, " ");
9245 }
9246
9247 /* Print attribute */
9b6d8fcf 9248 attr = path->attr;
05864da7
DS
9249 if (((p->family == AF_INET)
9250 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9251 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9252 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9253 char buf[BUFSIZ] = {0};
9254
05864da7
DS
9255 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9256 || safi == SAFI_EVPN) {
9257 if (json)
9258 json_object_string_add(
9259 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9260 inet_ntop(AF_INET,
9261 &attr->mp_nexthop_global_in,
9262 buf, sizeof(buf)));
05864da7 9263 else
23d0a753
DA
9264 vty_out(vty, "%-16pI4",
9265 &attr->mp_nexthop_global_in);
05864da7
DS
9266 } else {
9267 if (json)
9268 json_object_string_add(
9269 json_out, "nexthop",
23d0a753
DA
9270 inet_ntop(AF_INET, &attr->nexthop, buf,
9271 sizeof(buf)));
05864da7 9272 else
23d0a753 9273 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9274 }
9275 } else if (((p->family == AF_INET6)
9276 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9277 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9278 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9279 char buf_a[512];
9280
9281 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9282 if (json)
9283 json_object_string_add(
9284 json_out, "mpNexthopGlobalIn",
9285 inet_ntop(AF_INET6,
9286 &attr->mp_nexthop_global,
9287 buf_a, sizeof(buf_a)));
9288 else
9289 vty_out(vty, "%s",
9290 inet_ntop(AF_INET6,
9291 &attr->mp_nexthop_global,
9292 buf_a, sizeof(buf_a)));
9293 } else if (attr->mp_nexthop_len
9294 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9295 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9296 &attr->mp_nexthop_global,
9297 &attr->mp_nexthop_local);
9298 if (json)
9299 json_object_string_add(json_out,
9300 "mpNexthopGlobalLocal",
9301 buf_a);
9302 else
9303 vty_out(vty, "%s", buf_a);
d62a17ae 9304 }
9305 }
9306
9b6d8fcf 9307 label = decode_label(&path->extra->label[0]);
d62a17ae 9308
9309 if (bgp_is_valid_label(&label)) {
9310 if (json) {
9311 json_object_int_add(json_out, "notag", label);
9312 json_object_array_add(json, json_out);
9313 } else {
9314 vty_out(vty, "notag/%d", label);
9315 vty_out(vty, "\n");
9316 }
700ddfed
PG
9317 } else if (!json)
9318 vty_out(vty, "\n");
d62a17ae 9319}
718e3744 9320
bd494ec5 9321void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9322 struct bgp_path_info *path, int display,
d62a17ae 9323 json_object *json_paths)
718e3744 9324{
d62a17ae 9325 struct attr *attr;
14f51eba 9326 char buf[BUFSIZ] = {0};
d62a17ae 9327 json_object *json_path = NULL;
14f51eba
LK
9328 json_object *json_nexthop = NULL;
9329 json_object *json_overlay = NULL;
856ca177 9330
9b6d8fcf 9331 if (!path->extra)
d62a17ae 9332 return;
718e3744 9333
14f51eba
LK
9334 if (json_paths) {
9335 json_path = json_object_new_object();
9336 json_overlay = json_object_new_object();
9337 json_nexthop = json_object_new_object();
9338 }
9339
d62a17ae 9340 /* short status lead text */
82c298be 9341 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9342
d62a17ae 9343 /* print prefix and mask */
9344 if (!display)
7d3cae70 9345 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9346 else
9347 vty_out(vty, "%*s", 17, " ");
9348
9349 /* Print attribute */
9b6d8fcf 9350 attr = path->attr;
05864da7
DS
9351 char buf1[BUFSIZ];
9352 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9353
05864da7
DS
9354 switch (af) {
9355 case AF_INET:
9356 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9357 if (!json_path) {
9358 vty_out(vty, "%-16s", buf);
9359 } else {
9360 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9361
05864da7 9362 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9363
05864da7
DS
9364 json_object_object_add(json_path, "nexthop",
9365 json_nexthop);
9366 }
9367 break;
9368 case AF_INET6:
9369 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9370 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9371 if (!json_path) {
9372 vty_out(vty, "%s(%s)", buf, buf1);
9373 } else {
9374 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9375
05864da7
DS
9376 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9377 buf1);
14f51eba 9378
05864da7 9379 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9380
05864da7
DS
9381 json_object_object_add(json_path, "nexthop",
9382 json_nexthop);
9383 }
9384 break;
9385 default:
9386 if (!json_path) {
9387 vty_out(vty, "?");
9388 } else {
9389 json_object_string_add(json_nexthop, "Error",
9390 "Unsupported address-family");
d62a17ae 9391 }
05864da7 9392 }
988258b4 9393
6c924775
DS
9394 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9395
9396 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9397 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9398 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9399 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9400
05864da7
DS
9401 if (!json_path)
9402 vty_out(vty, "/%s", buf);
9403 else
9404 json_object_string_add(json_overlay, "gw", buf);
9405
9406 if (attr->ecommunity) {
9407 char *mac = NULL;
9408 struct ecommunity_val *routermac = ecommunity_lookup(
9409 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9410 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9411
9412 if (routermac)
9413 mac = ecom_mac2str((char *)routermac->val);
9414 if (mac) {
9415 if (!json_path) {
c4efd0f4 9416 vty_out(vty, "/%s", mac);
05864da7
DS
9417 } else {
9418 json_object_string_add(json_overlay, "rmac",
9419 mac);
988258b4 9420 }
05864da7 9421 XFREE(MTYPE_TMP, mac);
988258b4 9422 }
05864da7 9423 }
718e3744 9424
05864da7
DS
9425 if (!json_path) {
9426 vty_out(vty, "\n");
9427 } else {
9428 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9429
05864da7 9430 json_object_array_add(json_paths, json_path);
14f51eba 9431 }
d62a17ae 9432}
718e3744 9433
d62a17ae 9434/* dampening route */
5f040085
DS
9435static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9436 struct bgp_path_info *path, int display,
9437 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9438 json_object *json_paths)
d62a17ae 9439{
e5be8c1d 9440 struct attr *attr = path->attr;
d62a17ae 9441 int len;
9442 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9443 json_object *json_path = NULL;
9444
9445 if (use_json)
9446 json_path = json_object_new_object();
d62a17ae 9447
9448 /* short status lead text */
e5be8c1d 9449 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9450
9451 /* print prefix and mask */
9452 if (!use_json) {
9453 if (!display)
7d3cae70 9454 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9455 else
9456 vty_out(vty, "%*s", 17, " ");
d62a17ae 9457
e5be8c1d
DA
9458 len = vty_out(vty, "%s", path->peer->host);
9459 len = 17 - len;
9460
9461 if (len < 1)
d62a17ae 9462 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9463 else
9464 vty_out(vty, "%*s", len, " ");
d62a17ae 9465
9b6d8fcf
DS
9466 vty_out(vty, "%s ",
9467 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9468 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9469 use_json, NULL));
d62a17ae 9470
e5be8c1d 9471 if (attr->aspath)
05864da7 9472 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9473
05864da7
DS
9474 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9475
d62a17ae 9476 vty_out(vty, "\n");
e5be8c1d
DA
9477 } else {
9478 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9479 safi, use_json, json_path);
9480
9481 if (attr->aspath)
9482 json_object_string_add(json_path, "asPath",
9483 attr->aspath->str);
9484
9485 json_object_string_add(json_path, "origin",
9486 bgp_origin_str[attr->origin]);
9487 json_object_string_add(json_path, "peerHost", path->peer->host);
9488
9489 json_object_array_add(json_paths, json_path);
9490 }
d62a17ae 9491}
718e3744 9492
d62a17ae 9493/* flap route */
5f040085
DS
9494static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9495 struct bgp_path_info *path, int display,
9496 afi_t afi, safi_t safi, bool use_json,
31258046 9497 json_object *json_paths)
784d3a42 9498{
31258046 9499 struct attr *attr = path->attr;
d62a17ae 9500 struct bgp_damp_info *bdi;
9501 char timebuf[BGP_UPTIME_LEN];
9502 int len;
31258046 9503 json_object *json_path = NULL;
784d3a42 9504
9b6d8fcf 9505 if (!path->extra)
d62a17ae 9506 return;
784d3a42 9507
31258046
DA
9508 if (use_json)
9509 json_path = json_object_new_object();
9510
9b6d8fcf 9511 bdi = path->extra->damp_info;
784d3a42 9512
d62a17ae 9513 /* short status lead text */
31258046 9514 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9515
d62a17ae 9516 if (!use_json) {
9517 if (!display)
7d3cae70 9518 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9519 else
9520 vty_out(vty, "%*s", 17, " ");
784d3a42 9521
31258046
DA
9522 len = vty_out(vty, "%s", path->peer->host);
9523 len = 16 - len;
9524 if (len < 1)
d62a17ae 9525 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9526 else
9527 vty_out(vty, "%*s", len, " ");
784d3a42 9528
31258046
DA
9529 len = vty_out(vty, "%d", bdi->flap);
9530 len = 5 - len;
9531 if (len < 1)
d62a17ae 9532 vty_out(vty, " ");
d62a17ae 9533 else
9534 vty_out(vty, "%*s", len, " ");
d62a17ae 9535
996c9314
LB
9536 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9537 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9538
31258046
DA
9539 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9540 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9541 vty_out(vty, "%s ",
9b6d8fcf 9542 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9543 BGP_UPTIME_LEN, afi,
31258046
DA
9544 safi, use_json, NULL));
9545 else
d62a17ae 9546 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9547
31258046 9548 if (attr->aspath)
05864da7 9549 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9550
05864da7
DS
9551 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9552
d62a17ae 9553 vty_out(vty, "\n");
31258046
DA
9554 } else {
9555 json_object_string_add(json_path, "peerHost", path->peer->host);
9556 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9557
9558 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9559 json_path);
9560
9561 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9562 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9563 bgp_damp_reuse_time_vty(vty, path, timebuf,
9564 BGP_UPTIME_LEN, afi, safi,
9565 use_json, json_path);
9566
9567 if (attr->aspath)
9568 json_object_string_add(json_path, "asPath",
9569 attr->aspath->str);
9570
9571 json_object_string_add(json_path, "origin",
9572 bgp_origin_str[attr->origin]);
9573
9574 json_object_array_add(json_paths, json_path);
9575 }
d62a17ae 9576}
9577
9578static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9579 int *first, const char *header,
9580 json_object *json_adv_to)
9581{
9582 char buf1[INET6_ADDRSTRLEN];
9583 json_object *json_peer = NULL;
9584
9585 if (json_adv_to) {
9586 /* 'advertised-to' is a dictionary of peers we have advertised
9587 * this
9588 * prefix too. The key is the peer's IP or swpX, the value is
9589 * the
9590 * hostname if we know it and "" if not.
9591 */
9592 json_peer = json_object_new_object();
9593
9594 if (peer->hostname)
9595 json_object_string_add(json_peer, "hostname",
9596 peer->hostname);
9597
9598 if (peer->conf_if)
9599 json_object_object_add(json_adv_to, peer->conf_if,
9600 json_peer);
9601 else
9602 json_object_object_add(
9603 json_adv_to,
9604 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9605 json_peer);
9606 } else {
9607 if (*first) {
9608 vty_out(vty, "%s", header);
9609 *first = 0;
9610 }
9611
9612 if (peer->hostname
892fedb6 9613 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9614 if (peer->conf_if)
9615 vty_out(vty, " %s(%s)", peer->hostname,
9616 peer->conf_if);
9617 else
9618 vty_out(vty, " %s(%s)", peer->hostname,
9619 sockunion2str(&peer->su, buf1,
9620 SU_ADDRSTRLEN));
9621 } else {
9622 if (peer->conf_if)
9623 vty_out(vty, " %s", peer->conf_if);
9624 else
9625 vty_out(vty, " %s",
9626 sockunion2str(&peer->su, buf1,
9627 SU_ADDRSTRLEN));
9628 }
9629 }
784d3a42
PG
9630}
9631
dcc68b5e
MS
9632static void route_vty_out_tx_ids(struct vty *vty,
9633 struct bgp_addpath_info_data *d)
9634{
9635 int i;
9636
9637 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9638 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9639 d->addpath_tx_id[i],
9640 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9641 }
9642}
9643
5e4d4c8a 9644static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9645 struct bgp_path_info *pi,
9646 struct attr *attr,
9647 json_object *json_path)
5e4d4c8a
AK
9648{
9649 char esi_buf[ESI_STR_LEN];
9650 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9651 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9652 ATTR_ES_PEER_ROUTER);
9653 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9654 ATTR_ES_PEER_ACTIVE);
9655 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9656 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9657 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9658 if (json_path) {
9659 json_object *json_es_info = NULL;
9660
9661 json_object_string_add(
9662 json_path, "esi",
9663 esi_buf);
9664 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9665 json_es_info = json_object_new_object();
9666 if (es_local)
9667 json_object_boolean_true_add(
9668 json_es_info, "localEs");
9669 if (peer_active)
9670 json_object_boolean_true_add(
9671 json_es_info, "peerActive");
9672 if (peer_proxy)
9673 json_object_boolean_true_add(
9674 json_es_info, "peerProxy");
9675 if (peer_router)
9676 json_object_boolean_true_add(
9677 json_es_info, "peerRouter");
9678 if (attr->mm_sync_seqnum)
9679 json_object_int_add(
9680 json_es_info, "peerSeq",
9681 attr->mm_sync_seqnum);
9682 json_object_object_add(
9683 json_path, "es_info",
9684 json_es_info);
9685 }
9686 } else {
9687 if (bgp_evpn_attr_is_sync(attr))
9688 vty_out(vty,
9689 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9690 esi_buf,
9691 es_local ? "local-es":"",
9692 peer_proxy ? "proxy " : "",
9693 peer_active ? "active ":"",
9694 peer_router ? "router ":"",
9695 attr->mm_sync_seqnum);
9696 else
9697 vty_out(vty, " ESI %s %s\n",
9698 esi_buf,
9699 es_local ? "local-es":"");
9700 }
9701}
9702
4933eaaf
DS
9703void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9704 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9705 enum rpki_states rpki_curr_state,
9706 json_object *json_paths)
d62a17ae 9707{
9708 char buf[INET6_ADDRSTRLEN];
9709 char buf1[BUFSIZ];
515c2602 9710 struct attr *attr = path->attr;
d62a17ae 9711 int sockunion_vty_out(struct vty *, union sockunion *);
9712 time_t tbuf;
9713 json_object *json_bestpath = NULL;
9714 json_object *json_cluster_list = NULL;
9715 json_object *json_cluster_list_list = NULL;
9716 json_object *json_ext_community = NULL;
9717 json_object *json_last_update = NULL;
7fd077aa 9718 json_object *json_pmsi = NULL;
d62a17ae 9719 json_object *json_nexthop_global = NULL;
9720 json_object *json_nexthop_ll = NULL;
9721 json_object *json_nexthops = NULL;
9722 json_object *json_path = NULL;
9723 json_object *json_peer = NULL;
9724 json_object *json_string = NULL;
9725 json_object *json_adv_to = NULL;
9726 int first = 0;
9727 struct listnode *node, *nnode;
9728 struct peer *peer;
9729 int addpath_capable;
9730 int has_adj;
9731 unsigned int first_as;
1defdda8 9732 bool nexthop_self =
9b6d8fcf 9733 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9734 int i;
2ba93fd6
DA
9735 char *nexthop_hostname =
9736 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9737
9738 if (json_paths) {
9739 json_path = json_object_new_object();
9740 json_peer = json_object_new_object();
9741 json_nexthop_global = json_object_new_object();
9742 }
9743
8304dabf
AD
9744 if (safi == SAFI_EVPN) {
9745 if (!json_paths)
9746 vty_out(vty, " Route %pRN", bn);
9747 }
9748
44c69747 9749 if (path->extra) {
b57ba6d2 9750 char tag_buf[30];
d62a17ae 9751
d62a17ae 9752 tag_buf[0] = '\0';
9b6d8fcf
DS
9753 if (path->extra && path->extra->num_labels) {
9754 bgp_evpn_label2str(path->extra->label,
9755 path->extra->num_labels, tag_buf,
a4d82a8a 9756 sizeof(tag_buf));
d62a17ae 9757 }
d7325ee7 9758 if (safi == SAFI_EVPN) {
44c69747 9759 if (!json_paths) {
44c69747
LK
9760 if (tag_buf[0] != '\0')
9761 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9762 } else {
9763 if (tag_buf[0])
9764 json_object_string_add(json_path, "VNI",
9765 tag_buf);
9766 }
d7325ee7
DD
9767 }
9768
44c69747 9769 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9770 struct bgp_path_info *parent_ri;
9bcb3eef 9771 struct bgp_dest *dest, *pdest;
d62a17ae 9772
9b6d8fcf 9773 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9774 dest = parent_ri->net;
9775 if (dest && dest->pdest) {
9776 pdest = dest->pdest;
9777 prefix_rd2str(
9778 (struct prefix_rd *)bgp_dest_get_prefix(
9779 pdest),
9780 buf1, sizeof(buf1));
d7325ee7 9781 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9782 vty_out(vty,
58bff4d1 9783 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9784 buf1,
9785 (struct prefix_evpn *)
9786 bgp_dest_get_prefix(
9787 dest),
9788 tag_buf);
58bff4d1
AK
9789 if (attr->es_flags & ATTR_ES_L3_NHG)
9790 vty_out(vty, ", L3NHG %s",
9791 (attr->es_flags
9792 & ATTR_ES_L3_NHG_ACTIVE)
9793 ? "active"
9794 : "inactive");
9795 vty_out(vty, "\n");
9796
d7325ee7 9797 } else
2dbe669b
DA
9798 vty_out(vty,
9799 " Imported from %s:%pFX\n",
9800 buf1,
9801 (struct prefix_evpn *)
9802 bgp_dest_get_prefix(
9803 dest));
d62a17ae 9804 }
9805 }
9806 }
d62a17ae 9807
8304dabf
AD
9808 if (safi == SAFI_EVPN
9809 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9810 char gwip_buf[INET6_ADDRSTRLEN];
9811
9812 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9813 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9814 gwip_buf, sizeof(gwip_buf));
9815 else
9816 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9817 gwip_buf, sizeof(gwip_buf));
9818
9819 if (json_paths)
9820 json_object_string_add(json_path, "gatewayIP",
9821 gwip_buf);
9822 else
9823 vty_out(vty, " Gateway IP %s", gwip_buf);
9824 }
9825
9826 if (safi == SAFI_EVPN)
9827 vty_out(vty, "\n");
9828
05864da7
DS
9829 /* Line1 display AS-path, Aggregator */
9830 if (attr->aspath) {
9831 if (json_paths) {
9832 if (!attr->aspath->json)
9833 aspath_str_update(attr->aspath, true);
9834 json_object_lock(attr->aspath->json);
9835 json_object_object_add(json_path, "aspath",
9836 attr->aspath->json);
9837 } else {
9838 if (attr->aspath->segments)
9839 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9840 else
05864da7 9841 vty_out(vty, " Local");
d62a17ae 9842 }
05864da7 9843 }
d62a17ae 9844
05864da7
DS
9845 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9846 if (json_paths)
9847 json_object_boolean_true_add(json_path, "removed");
9848 else
9849 vty_out(vty, ", (removed)");
9850 }
d62a17ae 9851
05864da7
DS
9852 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9853 if (json_paths)
9854 json_object_boolean_true_add(json_path, "stale");
9855 else
9856 vty_out(vty, ", (stale)");
9857 }
d62a17ae 9858
05864da7
DS
9859 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9860 if (json_paths) {
23d0a753
DA
9861 char buf[BUFSIZ] = {0};
9862
05864da7
DS
9863 json_object_int_add(json_path, "aggregatorAs",
9864 attr->aggregator_as);
23d0a753
DA
9865 json_object_string_add(json_path, "aggregatorId",
9866 inet_ntop(AF_INET,
9867 &attr->aggregator_addr,
9868 buf, sizeof(buf)));
05864da7 9869 } else {
88d495a9
DA
9870 vty_out(vty, ", (aggregated by %u %pI4)",
9871 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9872 }
05864da7 9873 }
d62a17ae 9874
05864da7
DS
9875 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9876 PEER_FLAG_REFLECTOR_CLIENT)) {
9877 if (json_paths)
9878 json_object_boolean_true_add(json_path,
9879 "rxedFromRrClient");
9880 else
9881 vty_out(vty, ", (Received from a RR-client)");
9882 }
d62a17ae 9883
05864da7
DS
9884 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9885 PEER_FLAG_RSERVER_CLIENT)) {
9886 if (json_paths)
9887 json_object_boolean_true_add(json_path,
9888 "rxedFromRsClient");
9889 else
9890 vty_out(vty, ", (Received from a RS-client)");
9891 }
d62a17ae 9892
05864da7
DS
9893 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9894 if (json_paths)
9895 json_object_boolean_true_add(json_path,
9896 "dampeningHistoryEntry");
9897 else
9898 vty_out(vty, ", (history entry)");
9899 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9900 if (json_paths)
9901 json_object_boolean_true_add(json_path,
9902 "dampeningSuppressed");
9903 else
9904 vty_out(vty, ", (suppressed due to dampening)");
9905 }
d62a17ae 9906
05864da7
DS
9907 if (!json_paths)
9908 vty_out(vty, "\n");
d62a17ae 9909
05864da7
DS
9910 /* Line2 display Next-hop, Neighbor, Router-id */
9911 /* Display the nexthop */
9bcb3eef 9912 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9913
9914 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9915 || bn_p->family == AF_EVPN)
05864da7
DS
9916 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9917 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9918 char buf[BUFSIZ] = {0};
9919
05864da7
DS
9920 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9921 || safi == SAFI_EVPN) {
515c2602 9922 if (json_paths) {
d62a17ae 9923 json_object_string_add(
515c2602 9924 json_nexthop_global, "ip",
23d0a753
DA
9925 inet_ntop(AF_INET,
9926 &attr->mp_nexthop_global_in,
9927 buf, sizeof(buf)));
515c2602 9928
939a97f4 9929 if (path->peer->hostname)
515c2602
DA
9930 json_object_string_add(
9931 json_nexthop_global, "hostname",
939a97f4 9932 path->peer->hostname);
aef999a2
DA
9933 } else {
9934 if (nexthop_hostname)
9935 vty_out(vty, " %pI4(%s)",
9936 &attr->mp_nexthop_global_in,
9937 nexthop_hostname);
9938 else
9939 vty_out(vty, " %pI4",
9940 &attr->mp_nexthop_global_in);
9941 }
d62a17ae 9942 } else {
515c2602 9943 if (json_paths) {
05864da7 9944 json_object_string_add(
515c2602 9945 json_nexthop_global, "ip",
23d0a753
DA
9946 inet_ntop(AF_INET, &attr->nexthop, buf,
9947 sizeof(buf)));
515c2602 9948
939a97f4 9949 if (path->peer->hostname)
515c2602
DA
9950 json_object_string_add(
9951 json_nexthop_global, "hostname",
939a97f4 9952 path->peer->hostname);
aef999a2
DA
9953 } else {
9954 if (nexthop_hostname)
9955 vty_out(vty, " %pI4(%s)",
9956 &attr->nexthop,
9957 nexthop_hostname);
9958 else
9959 vty_out(vty, " %pI4",
9960 &attr->nexthop);
9961 }
d62a17ae 9962 }
9963
05864da7
DS
9964 if (json_paths)
9965 json_object_string_add(json_nexthop_global, "afi",
9966 "ipv4");
9967 } else {
9968 if (json_paths) {
9969 json_object_string_add(
515c2602
DA
9970 json_nexthop_global, "ip",
9971 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9972 buf, INET6_ADDRSTRLEN));
9973
939a97f4 9974 if (path->peer->hostname)
515c2602
DA
9975 json_object_string_add(json_nexthop_global,
9976 "hostname",
939a97f4 9977 path->peer->hostname);
515c2602 9978
05864da7
DS
9979 json_object_string_add(json_nexthop_global, "afi",
9980 "ipv6");
9981 json_object_string_add(json_nexthop_global, "scope",
9982 "global");
9983 } else {
aef999a2
DA
9984 if (nexthop_hostname)
9985 vty_out(vty, " %pI6(%s)",
9986 &attr->mp_nexthop_global,
9987 nexthop_hostname);
9988 else
9989 vty_out(vty, " %pI6",
9990 &attr->mp_nexthop_global);
d62a17ae 9991 }
05864da7 9992 }
d62a17ae 9993
05864da7
DS
9994 /* Display the IGP cost or 'inaccessible' */
9995 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9996 if (json_paths)
9997 json_object_boolean_false_add(json_nexthop_global,
9998 "accessible");
9999 else
10000 vty_out(vty, " (inaccessible)");
10001 } else {
10002 if (path->extra && path->extra->igpmetric) {
d62a17ae 10003 if (json_paths)
05864da7
DS
10004 json_object_int_add(json_nexthop_global,
10005 "metric",
10006 path->extra->igpmetric);
d62a17ae 10007 else
05864da7
DS
10008 vty_out(vty, " (metric %u)",
10009 path->extra->igpmetric);
d62a17ae 10010 }
10011
05864da7 10012 /* IGP cost is 0, display this only for json */
d62a17ae 10013 else {
d62a17ae 10014 if (json_paths)
05864da7
DS
10015 json_object_int_add(json_nexthop_global,
10016 "metric", 0);
d62a17ae 10017 }
d62a17ae 10018
05864da7
DS
10019 if (json_paths)
10020 json_object_boolean_true_add(json_nexthop_global,
10021 "accessible");
10022 }
d62a17ae 10023
05864da7
DS
10024 /* Display peer "from" output */
10025 /* This path was originated locally */
10026 if (path->peer == bgp->peer_self) {
d62a17ae 10027
05864da7 10028 if (safi == SAFI_EVPN
b54892e0 10029 || (bn_p->family == AF_INET
05864da7 10030 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10031 if (json_paths)
05864da7
DS
10032 json_object_string_add(json_peer, "peerId",
10033 "0.0.0.0");
d62a17ae 10034 else
05864da7
DS
10035 vty_out(vty, " from 0.0.0.0 ");
10036 } else {
d62a17ae 10037 if (json_paths)
05864da7
DS
10038 json_object_string_add(json_peer, "peerId",
10039 "::");
d62a17ae 10040 else
05864da7 10041 vty_out(vty, " from :: ");
d62a17ae 10042 }
d62a17ae 10043
23d0a753
DA
10044 if (json_paths) {
10045 char buf[BUFSIZ] = {0};
10046
05864da7 10047 json_object_string_add(json_peer, "routerId",
23d0a753
DA
10048 inet_ntop(AF_INET,
10049 &bgp->router_id, buf,
10050 sizeof(buf)));
10051 } else {
10052 vty_out(vty, "(%pI4)", &bgp->router_id);
10053 }
05864da7 10054 }
d62a17ae 10055
05864da7
DS
10056 /* We RXed this path from one of our peers */
10057 else {
10058
10059 if (json_paths) {
10060 json_object_string_add(json_peer, "peerId",
10061 sockunion2str(&path->peer->su,
10062 buf,
10063 SU_ADDRSTRLEN));
10064 json_object_string_add(json_peer, "routerId",
10065 inet_ntop(AF_INET,
10066 &path->peer->remote_id,
10067 buf1, sizeof(buf1)));
10068
10069 if (path->peer->hostname)
10070 json_object_string_add(json_peer, "hostname",
10071 path->peer->hostname);
10072
10073 if (path->peer->domainname)
10074 json_object_string_add(json_peer, "domainname",
10075 path->peer->domainname);
10076
10077 if (path->peer->conf_if)
10078 json_object_string_add(json_peer, "interface",
10079 path->peer->conf_if);
10080 } else {
10081 if (path->peer->conf_if) {
10082 if (path->peer->hostname
892fedb6
DA
10083 && CHECK_FLAG(path->peer->bgp->flags,
10084 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10085 vty_out(vty, " from %s(%s)",
10086 path->peer->hostname,
10087 path->peer->conf_if);
d62a17ae 10088 else
05864da7 10089 vty_out(vty, " from %s",
9b6d8fcf 10090 path->peer->conf_if);
d62a17ae 10091 } else {
05864da7 10092 if (path->peer->hostname
892fedb6
DA
10093 && CHECK_FLAG(path->peer->bgp->flags,
10094 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10095 vty_out(vty, " from %s(%s)",
10096 path->peer->hostname,
10097 path->peer->host);
d62a17ae 10098 else
05864da7
DS
10099 vty_out(vty, " from %s",
10100 sockunion2str(&path->peer->su,
10101 buf,
10102 SU_ADDRSTRLEN));
d62a17ae 10103 }
d62a17ae 10104
05864da7 10105 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10106 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10107 else
10108 vty_out(vty, " (%s)",
10109 inet_ntop(AF_INET,
10110 &path->peer->remote_id, buf1,
10111 sizeof(buf1)));
d62a17ae 10112 }
05864da7 10113 }
9df8b37c 10114
05864da7
DS
10115 /*
10116 * Note when vrfid of nexthop is different from that of prefix
10117 */
10118 if (path->extra && path->extra->bgp_orig) {
10119 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10120
05864da7
DS
10121 if (json_paths) {
10122 const char *vn;
9df8b37c 10123
05864da7
DS
10124 if (path->extra->bgp_orig->inst_type
10125 == BGP_INSTANCE_TYPE_DEFAULT)
10126 vn = VRF_DEFAULT_NAME;
10127 else
10128 vn = path->extra->bgp_orig->name;
9df8b37c 10129
05864da7 10130 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10131
05864da7
DS
10132 if (nexthop_vrfid == VRF_UNKNOWN) {
10133 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10134 } else {
05864da7
DS
10135 json_object_int_add(json_path, "nhVrfId",
10136 (int)nexthop_vrfid);
9df8b37c 10137 }
05864da7
DS
10138 } else {
10139 if (nexthop_vrfid == VRF_UNKNOWN)
10140 vty_out(vty, " vrf ?");
137147c6
DS
10141 else {
10142 struct vrf *vrf;
10143
10144 vrf = vrf_lookup_by_id(nexthop_vrfid);
10145 vty_out(vty, " vrf %s(%u)",
10146 VRF_LOGNAME(vrf), nexthop_vrfid);
10147 }
9df8b37c 10148 }
05864da7 10149 }
9df8b37c 10150
05864da7
DS
10151 if (nexthop_self) {
10152 if (json_paths) {
10153 json_object_boolean_true_add(json_path,
10154 "announceNexthopSelf");
10155 } else {
10156 vty_out(vty, " announce-nh-self");
9df8b37c 10157 }
05864da7 10158 }
9df8b37c 10159
05864da7
DS
10160 if (!json_paths)
10161 vty_out(vty, "\n");
d62a17ae 10162
05864da7
DS
10163 /* display the link-local nexthop */
10164 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10165 if (json_paths) {
10166 json_nexthop_ll = json_object_new_object();
10167 json_object_string_add(
515c2602
DA
10168 json_nexthop_ll, "ip",
10169 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10170 buf, INET6_ADDRSTRLEN));
10171
939a97f4 10172 if (path->peer->hostname)
515c2602
DA
10173 json_object_string_add(json_nexthop_ll,
10174 "hostname",
939a97f4 10175 path->peer->hostname);
515c2602 10176
05864da7
DS
10177 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10178 json_object_string_add(json_nexthop_ll, "scope",
10179 "link-local");
d62a17ae 10180
05864da7
DS
10181 json_object_boolean_true_add(json_nexthop_ll,
10182 "accessible");
d62a17ae 10183
05864da7 10184 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10185 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10186 "used");
10187 else
10188 json_object_boolean_true_add(
10189 json_nexthop_global, "used");
10190 } else {
10191 vty_out(vty, " (%s) %s\n",
10192 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10193 buf, INET6_ADDRSTRLEN),
10194 attr->mp_nexthop_prefer_global
10195 ? "(prefer-global)"
10196 : "(used)");
d62a17ae 10197 }
05864da7
DS
10198 }
10199 /* If we do not have a link-local nexthop then we must flag the
10200 global as "used" */
10201 else {
10202 if (json_paths)
10203 json_object_boolean_true_add(json_nexthop_global,
10204 "used");
10205 }
d62a17ae 10206
b5e140c8 10207 if (safi == SAFI_EVPN &&
5e4d4c8a 10208 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10209 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10210 }
10211
05864da7
DS
10212 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10213 * Int/Ext/Local, Atomic, best */
10214 if (json_paths)
10215 json_object_string_add(json_path, "origin",
10216 bgp_origin_long_str[attr->origin]);
10217 else
10218 vty_out(vty, " Origin %s",
10219 bgp_origin_long_str[attr->origin]);
9df8b37c 10220
05864da7 10221 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10222 if (json_paths)
05864da7 10223 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10224 else
05864da7
DS
10225 vty_out(vty, ", metric %u", attr->med);
10226 }
9df8b37c 10227
05864da7
DS
10228 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10229 if (json_paths)
0fbac0b4 10230 json_object_int_add(json_path, "locPrf",
05864da7
DS
10231 attr->local_pref);
10232 else
10233 vty_out(vty, ", localpref %u", attr->local_pref);
10234 }
9df8b37c 10235
05864da7
DS
10236 if (attr->weight != 0) {
10237 if (json_paths)
10238 json_object_int_add(json_path, "weight", attr->weight);
10239 else
10240 vty_out(vty, ", weight %u", attr->weight);
10241 }
9df8b37c 10242
05864da7
DS
10243 if (attr->tag != 0) {
10244 if (json_paths)
10245 json_object_int_add(json_path, "tag", attr->tag);
10246 else
10247 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10248 }
9df8b37c 10249
05864da7
DS
10250 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10251 if (json_paths)
10252 json_object_boolean_false_add(json_path, "valid");
10253 else
10254 vty_out(vty, ", invalid");
10255 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10256 if (json_paths)
10257 json_object_boolean_true_add(json_path, "valid");
10258 else
10259 vty_out(vty, ", valid");
10260 }
9df8b37c 10261
7d3cae70
DA
10262 if (json_paths)
10263 json_object_int_add(json_path, "version", bn->version);
10264
05864da7
DS
10265 if (path->peer != bgp->peer_self) {
10266 if (path->peer->as == path->peer->local_as) {
10267 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10268 if (json_paths)
10269 json_object_string_add(
10270 json_peer, "type",
10271 "confed-internal");
d62a17ae 10272 else
05864da7 10273 vty_out(vty, ", confed-internal");
d62a17ae 10274 } else {
05864da7
DS
10275 if (json_paths)
10276 json_object_string_add(
10277 json_peer, "type", "internal");
10278 else
10279 vty_out(vty, ", internal");
9df8b37c 10280 }
05864da7
DS
10281 } else {
10282 if (bgp_confederation_peers_check(bgp,
10283 path->peer->as)) {
10284 if (json_paths)
10285 json_object_string_add(
10286 json_peer, "type",
10287 "confed-external");
d62a17ae 10288 else
05864da7 10289 vty_out(vty, ", confed-external");
d62a17ae 10290 } else {
05864da7
DS
10291 if (json_paths)
10292 json_object_string_add(
10293 json_peer, "type", "external");
10294 else
10295 vty_out(vty, ", external");
d62a17ae 10296 }
10297 }
05864da7
DS
10298 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10299 if (json_paths) {
10300 json_object_boolean_true_add(json_path, "aggregated");
10301 json_object_boolean_true_add(json_path, "local");
10302 } else {
10303 vty_out(vty, ", aggregated, local");
10304 }
10305 } else if (path->type != ZEBRA_ROUTE_BGP) {
10306 if (json_paths)
10307 json_object_boolean_true_add(json_path, "sourced");
10308 else
10309 vty_out(vty, ", sourced");
10310 } else {
10311 if (json_paths) {
10312 json_object_boolean_true_add(json_path, "sourced");
10313 json_object_boolean_true_add(json_path, "local");
10314 } else {
10315 vty_out(vty, ", sourced, local");
d62a17ae 10316 }
05864da7 10317 }
718e3744 10318
05864da7 10319 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10320 if (json_paths)
05864da7
DS
10321 json_object_boolean_true_add(json_path,
10322 "atomicAggregate");
d62a17ae 10323 else
05864da7
DS
10324 vty_out(vty, ", atomic-aggregate");
10325 }
d62a17ae 10326
05864da7
DS
10327 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10328 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10329 && bgp_path_info_mpath_count(path))) {
10330 if (json_paths)
10331 json_object_boolean_true_add(json_path, "multipath");
10332 else
10333 vty_out(vty, ", multipath");
10334 }
50e05855 10335
05864da7
DS
10336 // Mark the bestpath(s)
10337 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10338 first_as = aspath_get_first_as(attr->aspath);
718e3744 10339
05864da7
DS
10340 if (json_paths) {
10341 if (!json_bestpath)
10342 json_bestpath = json_object_new_object();
10343 json_object_int_add(json_bestpath, "bestpathFromAs",
10344 first_as);
10345 } else {
10346 if (first_as)
10347 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10348 else
05864da7 10349 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10350 }
05864da7 10351 }
718e3744 10352
05864da7
DS
10353 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10354 if (json_paths) {
10355 if (!json_bestpath)
10356 json_bestpath = json_object_new_object();
10357 json_object_boolean_true_add(json_bestpath, "overall");
10358 json_object_string_add(
10359 json_bestpath, "selectionReason",
10360 bgp_path_selection_reason2str(bn->reason));
10361 } else {
10362 vty_out(vty, ", best");
10363 vty_out(vty, " (%s)",
10364 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10365 }
05864da7 10366 }
718e3744 10367
4027d19b 10368 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10369 if (json_paths)
10370 json_object_string_add(
10371 json_path, "rpkiValidationState",
4027d19b 10372 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10373 else
1d327209 10374 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10375 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10376 }
10377
05864da7
DS
10378 if (json_bestpath)
10379 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10380
05864da7
DS
10381 if (!json_paths)
10382 vty_out(vty, "\n");
10383
10384 /* Line 4 display Community */
29e72930 10385 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10386 if (json_paths) {
10387 if (!attr->community->json)
10388 community_str(attr->community, true);
10389 json_object_lock(attr->community->json);
10390 json_object_object_add(json_path, "community",
10391 attr->community->json);
10392 } else {
10393 vty_out(vty, " Community: %s\n",
10394 attr->community->str);
d62a17ae 10395 }
05864da7 10396 }
718e3744 10397
05864da7
DS
10398 /* Line 5 display Extended-community */
10399 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10400 if (json_paths) {
10401 json_ext_community = json_object_new_object();
10402 json_object_string_add(json_ext_community, "string",
10403 attr->ecommunity->str);
10404 json_object_object_add(json_path, "extendedCommunity",
10405 json_ext_community);
d62a17ae 10406 } else {
05864da7
DS
10407 vty_out(vty, " Extended Community: %s\n",
10408 attr->ecommunity->str);
d62a17ae 10409 }
05864da7 10410 }
718e3744 10411
05864da7
DS
10412 /* Line 6 display Large community */
10413 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10414 if (json_paths) {
10415 if (!attr->lcommunity->json)
10416 lcommunity_str(attr->lcommunity, true);
10417 json_object_lock(attr->lcommunity->json);
10418 json_object_object_add(json_path, "largeCommunity",
10419 attr->lcommunity->json);
10420 } else {
10421 vty_out(vty, " Large Community: %s\n",
10422 attr->lcommunity->str);
d62a17ae 10423 }
05864da7 10424 }
718e3744 10425
05864da7
DS
10426 /* Line 7 display Originator, Cluster-id */
10427 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10428 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10429 char buf[BUFSIZ] = {0};
10430
05864da7 10431 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10432 if (json_paths)
05864da7
DS
10433 json_object_string_add(
10434 json_path, "originatorId",
23d0a753
DA
10435 inet_ntop(AF_INET, &attr->originator_id,
10436 buf, sizeof(buf)));
d62a17ae 10437 else
23d0a753
DA
10438 vty_out(vty, " Originator: %pI4",
10439 &attr->originator_id);
d62a17ae 10440 }
856ca177 10441
05864da7 10442 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10443 struct cluster_list *cluster =
10444 bgp_attr_get_cluster(attr);
05864da7 10445 int i;
d62a17ae 10446
10447 if (json_paths) {
05864da7
DS
10448 json_cluster_list = json_object_new_object();
10449 json_cluster_list_list =
10450 json_object_new_array();
10451
779fee93 10452 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10453 json_string = json_object_new_string(
779fee93
DS
10454 inet_ntop(AF_INET,
10455 &cluster->list[i],
10456 buf, sizeof(buf)));
05864da7
DS
10457 json_object_array_add(
10458 json_cluster_list_list,
10459 json_string);
10460 }
718e3744 10461
05864da7
DS
10462 /*
10463 * struct cluster_list does not have
10464 * "str" variable like aspath and community
10465 * do. Add this someday if someone asks
10466 * for it.
10467 * json_object_string_add(json_cluster_list,
779fee93 10468 * "string", cluster->str);
05864da7
DS
10469 */
10470 json_object_object_add(json_cluster_list,
10471 "list",
10472 json_cluster_list_list);
10473 json_object_object_add(json_path, "clusterList",
10474 json_cluster_list);
0dc8ee70 10475 } else {
05864da7
DS
10476 vty_out(vty, ", Cluster list: ");
10477
779fee93 10478 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10479 vty_out(vty, "%pI4 ",
779fee93 10480 &cluster->list[i]);
05864da7 10481 }
0dc8ee70 10482 }
d62a17ae 10483 }
718e3744 10484
d62a17ae 10485 if (!json_paths)
10486 vty_out(vty, "\n");
05864da7 10487 }
d62a17ae 10488
05864da7 10489 if (path->extra && path->extra->damp_info)
b4f7f45b 10490 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10491
05864da7
DS
10492 /* Remote Label */
10493 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10494 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10495 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10496
05864da7
DS
10497 if (json_paths)
10498 json_object_int_add(json_path, "remoteLabel", label);
10499 else
10500 vty_out(vty, " Remote label: %d\n", label);
10501 }
d62a17ae 10502
e496b420
HS
10503 /* Remote SID */
10504 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10505 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10506 if (json_paths)
10507 json_object_string_add(json_path, "remoteSid", buf);
10508 else
10509 vty_out(vty, " Remote SID: %s\n", buf);
10510 }
10511
05864da7
DS
10512 /* Label Index */
10513 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10514 if (json_paths)
10515 json_object_int_add(json_path, "labelIndex",
10516 attr->label_index);
10517 else
10518 vty_out(vty, " Label Index: %d\n",
10519 attr->label_index);
10520 }
d62a17ae 10521
05864da7
DS
10522 /* Line 8 display Addpath IDs */
10523 if (path->addpath_rx_id
10524 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10525 if (json_paths) {
10526 json_object_int_add(json_path, "addpathRxId",
10527 path->addpath_rx_id);
d62a17ae 10528
05864da7
DS
10529 /* Keep backwards compatibility with the old API
10530 * by putting TX All's ID in the old field
10531 */
10532 json_object_int_add(
10533 json_path, "addpathTxId",
10534 path->tx_addpath
10535 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10536
05864da7
DS
10537 /* ... but create a specific field for each
10538 * strategy
10539 */
10540 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10541 json_object_int_add(
10542 json_path,
10543 bgp_addpath_names(i)->id_json_name,
10544 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10545 }
05864da7
DS
10546 } else {
10547 vty_out(vty, " AddPath ID: RX %u, ",
10548 path->addpath_rx_id);
d62a17ae 10549
05864da7 10550 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10551 }
05864da7 10552 }
520d5d76 10553
05864da7
DS
10554 /* If we used addpath to TX a non-bestpath we need to display
10555 * "Advertised to" on a path-by-path basis
10556 */
10557 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10558 first = 1;
dcc68b5e 10559
05864da7
DS
10560 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10561 addpath_capable =
10562 bgp_addpath_encode_tx(peer, afi, safi);
10563 has_adj = bgp_adj_out_lookup(
10564 peer, path->net,
10565 bgp_addpath_id_for_peer(peer, afi, safi,
10566 &path->tx_addpath));
10567
10568 if ((addpath_capable && has_adj)
10569 || (!addpath_capable && has_adj
10570 && CHECK_FLAG(path->flags,
10571 BGP_PATH_SELECTED))) {
10572 if (json_path && !json_adv_to)
10573 json_adv_to = json_object_new_object();
dcc68b5e 10574
05864da7
DS
10575 route_vty_out_advertised_to(
10576 vty, peer, &first,
10577 " Advertised to:", json_adv_to);
d62a17ae 10578 }
10579 }
718e3744 10580
05864da7
DS
10581 if (json_path) {
10582 if (json_adv_to) {
10583 json_object_object_add(
10584 json_path, "advertisedTo", json_adv_to);
d62a17ae 10585 }
05864da7
DS
10586 } else {
10587 if (!first) {
10588 vty_out(vty, "\n");
d62a17ae 10589 }
10590 }
05864da7 10591 }
b05a1c8b 10592
05864da7
DS
10593 /* Line 9 display Uptime */
10594 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10595 if (json_paths) {
10596 json_last_update = json_object_new_object();
10597 json_object_int_add(json_last_update, "epoch", tbuf);
10598 json_object_string_add(json_last_update, "string",
10599 ctime(&tbuf));
10600 json_object_object_add(json_path, "lastUpdate",
10601 json_last_update);
10602 } else
10603 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10604
05864da7
DS
10605 /* Line 10 display PMSI tunnel attribute, if present */
10606 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10607 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10608 bgp_attr_get_pmsi_tnl_type(attr),
10609 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10610
05864da7
DS
10611 if (json_paths) {
10612 json_pmsi = json_object_new_object();
10613 json_object_string_add(json_pmsi, "tunnelType", str);
10614 json_object_int_add(json_pmsi, "label",
10615 label2vni(&attr->label));
10616 json_object_object_add(json_path, "pmsi", json_pmsi);
10617 } else
10618 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10619 str, label2vni(&attr->label));
d62a17ae 10620 }
f1aa5d8a 10621
92269aa2
DS
10622 /* Output some debug about internal state of the dest flags */
10623 if (json_paths) {
10624 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10625 json_object_boolean_true_add(json_path, "processScheduled");
10626 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10627 json_object_boolean_true_add(json_path, "userCleared");
10628 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10629 json_object_boolean_true_add(json_path, "labelChanged");
10630 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10631 json_object_boolean_true_add(json_path, "registeredForLabel");
10632 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10633 json_object_boolean_true_add(json_path, "selectDefered");
10634 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10635 json_object_boolean_true_add(json_path, "fibInstalled");
10636 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10637 json_object_boolean_true_add(json_path, "fibPending");
10638 }
10639
d62a17ae 10640 /* We've constructed the json object for this path, add it to the json
10641 * array of paths
10642 */
10643 if (json_paths) {
10644 if (json_nexthop_global || json_nexthop_ll) {
10645 json_nexthops = json_object_new_array();
f1aa5d8a 10646
d62a17ae 10647 if (json_nexthop_global)
10648 json_object_array_add(json_nexthops,
10649 json_nexthop_global);
f1aa5d8a 10650
d62a17ae 10651 if (json_nexthop_ll)
10652 json_object_array_add(json_nexthops,
10653 json_nexthop_ll);
f1aa5d8a 10654
d62a17ae 10655 json_object_object_add(json_path, "nexthops",
10656 json_nexthops);
10657 }
10658
10659 json_object_object_add(json_path, "peer", json_peer);
10660 json_object_array_add(json_paths, json_path);
05864da7 10661 }
b366b518
BB
10662}
10663
96ade3ed 10664#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10665#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10666#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10667
d62a17ae 10668static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10669 const char *prefix_list_str, afi_t afi,
10670 safi_t safi, enum bgp_show_type type);
10671static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10672 const char *filter, afi_t afi, safi_t safi,
10673 enum bgp_show_type type);
10674static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10675 const char *rmap_str, afi_t afi, safi_t safi,
10676 enum bgp_show_type type);
10677static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10678 const char *com, int exact, afi_t afi,
10679 safi_t safi);
10680static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10681 const char *prefix, afi_t afi, safi_t safi,
10682 enum bgp_show_type type);
a4d82a8a 10683static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10684 afi_t afi, safi_t safi, enum bgp_show_type type,
10685 bool use_json);
7f323236
DW
10686static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10687 const char *comstr, int exact, afi_t afi,
96c81f66 10688 safi_t safi, uint16_t show_flags);
d62a17ae 10689
1ae44dfc 10690static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10691 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10692 void *output_arg, char *rd, int is_last,
10693 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10694 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10695 enum rpki_states rpki_target_state)
d62a17ae 10696{
40381db7 10697 struct bgp_path_info *pi;
9bcb3eef 10698 struct bgp_dest *dest;
d62a17ae 10699 int header = 1;
10700 int display;
1ae44dfc
LB
10701 unsigned long output_count = 0;
10702 unsigned long total_count = 0;
d62a17ae 10703 struct prefix *p;
d62a17ae 10704 json_object *json_paths = NULL;
10705 int first = 1;
96f3485c
MK
10706 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10707 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10708 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10709
1ae44dfc
LB
10710 if (output_cum && *output_cum != 0)
10711 header = 0;
10712
9386b588 10713 if (use_json && !*json_header_depth) {
96f3485c
MK
10714 if (all)
10715 *json_header_depth = 1;
10716 else {
10717 vty_out(vty, "{\n");
10718 *json_header_depth = 2;
10719 }
10720
d62a17ae 10721 vty_out(vty,
23d0a753
DA
10722 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10723 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10724 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10725 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10726 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10727 ? VRF_DEFAULT_NAME
10728 : bgp->name,
10729 table->version, &bgp->router_id,
01eced22 10730 bgp->default_local_pref, bgp->as);
9386b588 10731 if (rd) {
445c2480 10732 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10733 ++*json_header_depth;
10734 }
d62a17ae 10735 }
718e3744 10736
445c2480
DS
10737 if (use_json && rd) {
10738 vty_out(vty, " \"%s\" : { ", rd);
10739 }
10740
d62a17ae 10741 /* Start processing of routes. */
9bcb3eef
DS
10742 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10743 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10744 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10745
9bcb3eef 10746 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10747 if (pi == NULL)
98ce9a06 10748 continue;
d62a17ae 10749
98ce9a06 10750 display = 0;
98ce9a06
DS
10751 if (use_json)
10752 json_paths = json_object_new_array();
10753 else
10754 json_paths = NULL;
d62a17ae 10755
6f94b685 10756 for (; pi; pi = pi->next) {
98ce9a06 10757 total_count++;
1e2ce4f1 10758
7d3cae70
DA
10759 if (type == bgp_show_type_prefix_version) {
10760 uint32_t version =
10761 strtoul(output_arg, NULL, 10);
10762 if (dest->version < version)
10763 continue;
10764 }
10765
a70a28a5
DA
10766 if (type == bgp_show_type_community_alias) {
10767 char *alias = output_arg;
10768 char **communities;
10769 int num;
10770 bool found = false;
10771
10772 if (pi->attr->community) {
10773 frrstr_split(pi->attr->community->str,
10774 " ", &communities, &num);
10775 for (int i = 0; i < num; i++) {
10776 const char *com2alias =
10777 bgp_community2alias(
10778 communities[i]);
cd9cc0e6
IR
10779 if (!found
10780 && strcmp(alias, com2alias)
10781 == 0)
a70a28a5 10782 found = true;
cd9cc0e6
IR
10783 XFREE(MTYPE_TMP,
10784 communities[i]);
a70a28a5 10785 }
cd9cc0e6 10786 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10787 }
10788
10789 if (!found && pi->attr->lcommunity) {
10790 frrstr_split(pi->attr->lcommunity->str,
10791 " ", &communities, &num);
10792 for (int i = 0; i < num; i++) {
10793 const char *com2alias =
10794 bgp_community2alias(
10795 communities[i]);
cd9cc0e6
IR
10796 if (!found
10797 && strcmp(alias, com2alias)
10798 == 0)
a70a28a5 10799 found = true;
cd9cc0e6
IR
10800 XFREE(MTYPE_TMP,
10801 communities[i]);
a70a28a5 10802 }
cd9cc0e6 10803 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10804 }
10805
10806 if (!found)
10807 continue;
10808 }
10809
1e2ce4f1
DS
10810 if (type == bgp_show_type_rpki) {
10811 if (dest_p->family == AF_INET
10812 || dest_p->family == AF_INET6)
4027d19b 10813 rpki_curr_state = hook_call(
1e2ce4f1
DS
10814 bgp_rpki_prefix_status,
10815 pi->peer, pi->attr, dest_p);
4027d19b
DS
10816 if (rpki_target_state != RPKI_NOT_BEING_USED
10817 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10818 continue;
10819 }
10820
98ce9a06
DS
10821 if (type == bgp_show_type_flap_statistics
10822 || type == bgp_show_type_flap_neighbor
10823 || type == bgp_show_type_dampend_paths
10824 || type == bgp_show_type_damp_neighbor) {
40381db7 10825 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10826 continue;
10827 }
10828 if (type == bgp_show_type_regexp) {
10829 regex_t *regex = output_arg;
d62a17ae 10830
40381db7 10831 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10832 == REG_NOMATCH)
10833 continue;
10834 }
10835 if (type == bgp_show_type_prefix_list) {
10836 struct prefix_list *plist = output_arg;
d62a17ae 10837
9bcb3eef 10838 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10839 != PREFIX_PERMIT)
10840 continue;
10841 }
10842 if (type == bgp_show_type_filter_list) {
10843 struct as_list *as_list = output_arg;
d62a17ae 10844
40381db7 10845 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10846 != AS_FILTER_PERMIT)
10847 continue;
10848 }
10849 if (type == bgp_show_type_route_map) {
10850 struct route_map *rmap = output_arg;
9b6d8fcf 10851 struct bgp_path_info path;
98ce9a06 10852 struct attr dummy_attr;
b68885f9 10853 route_map_result_t ret;
d62a17ae 10854
6f4f49b2 10855 dummy_attr = *pi->attr;
d62a17ae 10856
40381db7 10857 path.peer = pi->peer;
9b6d8fcf 10858 path.attr = &dummy_attr;
d62a17ae 10859
1782514f 10860 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 10861 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
10862 if (ret == RMAP_DENYMATCH)
10863 continue;
10864 }
10865 if (type == bgp_show_type_neighbor
10866 || type == bgp_show_type_flap_neighbor
10867 || type == bgp_show_type_damp_neighbor) {
10868 union sockunion *su = output_arg;
10869
40381db7
DS
10870 if (pi->peer == NULL
10871 || pi->peer->su_remote == NULL
10872 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10873 continue;
10874 }
10875 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10876 uint32_t destination;
d62a17ae 10877
9bcb3eef 10878 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10879 if (IN_CLASSC(destination)
9bcb3eef 10880 && dest_p->prefixlen == 24)
98ce9a06
DS
10881 continue;
10882 if (IN_CLASSB(destination)
9bcb3eef 10883 && dest_p->prefixlen == 16)
98ce9a06
DS
10884 continue;
10885 if (IN_CLASSA(destination)
9bcb3eef 10886 && dest_p->prefixlen == 8)
98ce9a06
DS
10887 continue;
10888 }
10889 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10890 p = output_arg;
9bcb3eef 10891 if (!prefix_match(p, dest_p))
98ce9a06
DS
10892 continue;
10893 }
10894 if (type == bgp_show_type_community_all) {
40381db7 10895 if (!pi->attr->community)
98ce9a06
DS
10896 continue;
10897 }
10898 if (type == bgp_show_type_community) {
10899 struct community *com = output_arg;
d62a17ae 10900
40381db7
DS
10901 if (!pi->attr->community
10902 || !community_match(pi->attr->community,
98ce9a06
DS
10903 com))
10904 continue;
10905 }
10906 if (type == bgp_show_type_community_exact) {
10907 struct community *com = output_arg;
d62a17ae 10908
40381db7
DS
10909 if (!pi->attr->community
10910 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10911 continue;
10912 }
10913 if (type == bgp_show_type_community_list) {
10914 struct community_list *list = output_arg;
d62a17ae 10915
40381db7 10916 if (!community_list_match(pi->attr->community,
a4d82a8a 10917 list))
98ce9a06
DS
10918 continue;
10919 }
a4d82a8a 10920 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10921 struct community_list *list = output_arg;
d62a17ae 10922
98ce9a06 10923 if (!community_list_exact_match(
40381db7 10924 pi->attr->community, list))
98ce9a06
DS
10925 continue;
10926 }
10927 if (type == bgp_show_type_lcommunity) {
10928 struct lcommunity *lcom = output_arg;
d62a17ae 10929
40381db7
DS
10930 if (!pi->attr->lcommunity
10931 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10932 lcom))
10933 continue;
10934 }
36a206db 10935
10936 if (type == bgp_show_type_lcommunity_exact) {
10937 struct lcommunity *lcom = output_arg;
10938
10939 if (!pi->attr->lcommunity
10940 || !lcommunity_cmp(pi->attr->lcommunity,
10941 lcom))
10942 continue;
10943 }
98ce9a06
DS
10944 if (type == bgp_show_type_lcommunity_list) {
10945 struct community_list *list = output_arg;
d62a17ae 10946
40381db7 10947 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10948 list))
98ce9a06
DS
10949 continue;
10950 }
36a206db 10951 if (type
10952 == bgp_show_type_lcommunity_list_exact) {
10953 struct community_list *list = output_arg;
10954
10955 if (!lcommunity_list_exact_match(
10956 pi->attr->lcommunity, list))
10957 continue;
10958 }
98ce9a06 10959 if (type == bgp_show_type_lcommunity_all) {
40381db7 10960 if (!pi->attr->lcommunity)
98ce9a06
DS
10961 continue;
10962 }
10963 if (type == bgp_show_type_dampend_paths
10964 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10965 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10966 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10967 continue;
10968 }
10969
10970 if (!use_json && header) {
23d0a753
DA
10971 vty_out(vty,
10972 "BGP table version is %" PRIu64
10973 ", local router ID is %pI4, vrf id ",
10974 table->version, &bgp->router_id);
9df8b37c
PZ
10975 if (bgp->vrf_id == VRF_UNKNOWN)
10976 vty_out(vty, "%s", VRFID_NONE_STR);
10977 else
10978 vty_out(vty, "%u", bgp->vrf_id);
10979 vty_out(vty, "\n");
01eced22
AD
10980 vty_out(vty, "Default local pref %u, ",
10981 bgp->default_local_pref);
10982 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10983 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10984 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10985 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 10986 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 10987 if (type == bgp_show_type_dampend_paths
10988 || type == bgp_show_type_damp_neighbor)
98ce9a06 10989 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10990 else if (type == bgp_show_type_flap_statistics
10991 || type == bgp_show_type_flap_neighbor)
98ce9a06 10992 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10993 else
ae248832
MK
10994 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10995 : BGP_SHOW_HEADER));
98ce9a06 10996 header = 0;
d62a17ae 10997 }
98ce9a06
DS
10998 if (rd != NULL && !display && !output_count) {
10999 if (!use_json)
11000 vty_out(vty,
11001 "Route Distinguisher: %s\n",
11002 rd);
d62a17ae 11003 }
98ce9a06
DS
11004 if (type == bgp_show_type_dampend_paths
11005 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11006 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11007 AFI_IP, safi, use_json,
11008 json_paths);
98ce9a06
DS
11009 else if (type == bgp_show_type_flap_statistics
11010 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11011 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11012 AFI_IP, safi, use_json,
11013 json_paths);
f280c93b
DA
11014 else {
11015 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11016 route_vty_out_detail(
11017 vty, bgp, dest, pi,
11018 family2afi(dest_p->family),
11019 safi, RPKI_NOT_BEING_USED,
11020 json_paths);
11021 else
11022 route_vty_out(vty, dest_p, pi, display,
11023 safi, json_paths, wide);
11024 }
98ce9a06 11025 display++;
d62a17ae 11026 }
11027
98ce9a06
DS
11028 if (display) {
11029 output_count++;
11030 if (!use_json)
11031 continue;
11032
625d2931 11033 /* encode prefix */
9bcb3eef 11034 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11035 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11036
1840384b 11037
b54892e0
DS
11038 bgp_fs_nlri_get_string(
11039 (unsigned char *)
9bcb3eef
DS
11040 dest_p->u.prefix_flowspec.ptr,
11041 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11042 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11043 family2afi(dest_p->u
11044 .prefix_flowspec.family));
625d2931 11045 if (first)
b54892e0 11046 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11047 dest_p->u.prefix_flowspec
b54892e0 11048 .prefixlen);
625d2931 11049 else
b54892e0 11050 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11051 dest_p->u.prefix_flowspec
b54892e0 11052 .prefixlen);
625d2931 11053 } else {
625d2931 11054 if (first)
1b78780b 11055 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11056 else
1b78780b 11057 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11058 }
98ce9a06 11059 vty_out(vty, "%s",
f4ec52f7
DA
11060 json_object_to_json_string_ext(
11061 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11062 json_object_free(json_paths);
449feb8e 11063 json_paths = NULL;
98ce9a06 11064 first = 0;
1f83ed02
DS
11065 } else
11066 json_object_free(json_paths);
98ce9a06
DS
11067 }
11068
1ae44dfc
LB
11069 if (output_cum) {
11070 output_count += *output_cum;
11071 *output_cum = output_count;
11072 }
11073 if (total_cum) {
11074 total_count += *total_cum;
11075 *total_cum = total_count;
11076 }
d62a17ae 11077 if (use_json) {
9386b588 11078 if (rd) {
a4d82a8a 11079 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11080 }
11081 if (is_last) {
a4d82a8a
PZ
11082 unsigned long i;
11083 for (i = 0; i < *json_header_depth; ++i)
11084 vty_out(vty, " } ");
96f3485c
MK
11085 if (!all)
11086 vty_out(vty, "\n");
9386b588 11087 }
d62a17ae 11088 } else {
1ae44dfc
LB
11089 if (is_last) {
11090 /* No route is displayed */
11091 if (output_count == 0) {
11092 if (type == bgp_show_type_normal)
11093 vty_out(vty,
11094 "No BGP prefixes displayed, %ld exist\n",
11095 total_count);
11096 } else
d62a17ae 11097 vty_out(vty,
1ae44dfc
LB
11098 "\nDisplayed %ld routes and %ld total paths\n",
11099 output_count, total_count);
11100 }
d62a17ae 11101 }
718e3744 11102
d62a17ae 11103 return CMD_SUCCESS;
718e3744 11104}
11105
1ae44dfc
LB
11106int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11107 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11108 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11109{
9bcb3eef 11110 struct bgp_dest *dest, *next;
1ae44dfc
LB
11111 unsigned long output_cum = 0;
11112 unsigned long total_cum = 0;
9386b588 11113 unsigned long json_header_depth = 0;
67009e22 11114 struct bgp_table *itable;
0136788c 11115 bool show_msg;
96c81f66 11116 uint16_t show_flags = 0;
0136788c
LB
11117
11118 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11119
96f3485c
MK
11120 if (use_json)
11121 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11122
9bcb3eef
DS
11123 for (dest = bgp_table_top(table); dest; dest = next) {
11124 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11125
9bcb3eef
DS
11126 next = bgp_route_next(dest);
11127 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11128 continue;
67009e22 11129
9bcb3eef 11130 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11131 if (itable != NULL) {
1ae44dfc 11132 struct prefix_rd prd;
06b9f471 11133 char rd[RD_ADDRSTRLEN];
1ae44dfc 11134
9bcb3eef 11135 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11136 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11137 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11138 rd, next == NULL, &output_cum,
11139 &total_cum, &json_header_depth,
1e2ce4f1 11140 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11141 if (next == NULL)
11142 show_msg = false;
1ae44dfc
LB
11143 }
11144 }
0136788c
LB
11145 if (show_msg) {
11146 if (output_cum == 0)
11147 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11148 total_cum);
11149 else
11150 vty_out(vty,
11151 "\nDisplayed %ld routes and %ld total paths\n",
11152 output_cum, total_cum);
11153 }
1ae44dfc
LB
11154 return CMD_SUCCESS;
11155}
d62a17ae 11156static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11157 enum bgp_show_type type, void *output_arg,
96c81f66 11158 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11159{
d62a17ae 11160 struct bgp_table *table;
9386b588 11161 unsigned long json_header_depth = 0;
96f3485c 11162 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11163
d62a17ae 11164 if (bgp == NULL) {
11165 bgp = bgp_get_default();
11166 }
fee0f4c6 11167
d62a17ae 11168 if (bgp == NULL) {
11169 if (!use_json)
11170 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11171 else
11172 vty_out(vty, "{}\n");
d62a17ae 11173 return CMD_WARNING;
11174 }
4dd6177e 11175
cd8c2a27
MS
11176 /* Labeled-unicast routes live in the unicast table. */
11177 if (safi == SAFI_LABELED_UNICAST)
11178 safi = SAFI_UNICAST;
11179
1ae44dfc 11180 table = bgp->rib[afi][safi];
d62a17ae 11181 /* use MPLS and ENCAP specific shows until they are merged */
11182 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11183 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11184 output_arg, use_json);
d62a17ae 11185 }
dba3c1d3
PG
11186
11187 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11188 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11189 output_arg, use_json,
11190 1, NULL, NULL);
11191 }
fee0f4c6 11192
96f3485c 11193 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11194 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11195 rpki_target_state);
fee0f4c6 11196}
11197
d62a17ae 11198static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11199 safi_t safi, uint16_t show_flags)
f186de26 11200{
d62a17ae 11201 struct listnode *node, *nnode;
11202 struct bgp *bgp;
11203 int is_first = 1;
9f049418 11204 bool route_output = false;
96f3485c 11205 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11206
d62a17ae 11207 if (use_json)
11208 vty_out(vty, "{\n");
9f689658 11209
d62a17ae 11210 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11211 route_output = true;
d62a17ae 11212 if (use_json) {
11213 if (!is_first)
11214 vty_out(vty, ",\n");
11215 else
11216 is_first = 0;
11217
11218 vty_out(vty, "\"%s\":",
11219 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11220 ? VRF_DEFAULT_NAME
d62a17ae 11221 : bgp->name);
11222 } else {
11223 vty_out(vty, "\nInstance %s:\n",
11224 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11225 ? VRF_DEFAULT_NAME
d62a17ae 11226 : bgp->name);
11227 }
11228 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11229 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11230 }
9f689658 11231
d62a17ae 11232 if (use_json)
11233 vty_out(vty, "}\n");
9f049418
DS
11234 else if (!route_output)
11235 vty_out(vty, "%% BGP instance not found\n");
f186de26 11236}
11237
718e3744 11238/* Header of detailed BGP route information */
d62a17ae 11239void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11240 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11241 afi_t afi, safi_t safi, json_object *json)
11242{
40381db7 11243 struct bgp_path_info *pi;
b54892e0 11244 const struct prefix *p;
d62a17ae 11245 struct peer *peer;
11246 struct listnode *node, *nnode;
06b9f471 11247 char buf1[RD_ADDRSTRLEN];
0291c246 11248 char prefix_str[BUFSIZ];
d62a17ae 11249 int count = 0;
11250 int best = 0;
11251 int suppress = 0;
c5f1e1b2
C
11252 int accept_own = 0;
11253 int route_filter_translated_v4 = 0;
11254 int route_filter_v4 = 0;
11255 int route_filter_translated_v6 = 0;
11256 int route_filter_v6 = 0;
11257 int llgr_stale = 0;
11258 int no_llgr = 0;
11259 int accept_own_nexthop = 0;
11260 int blackhole = 0;
d62a17ae 11261 int no_export = 0;
11262 int no_advertise = 0;
11263 int local_as = 0;
c5f1e1b2 11264 int no_peer = 0;
d62a17ae 11265 int first = 1;
11266 int has_valid_label = 0;
11267 mpls_label_t label = 0;
11268 json_object *json_adv_to = NULL;
9bedbb1e 11269
9bcb3eef
DS
11270 p = bgp_dest_get_prefix(dest);
11271 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11272
11273 if (has_valid_label)
9bcb3eef 11274 label = label_pton(&dest->local_label);
d62a17ae 11275
44c69747 11276 if (safi == SAFI_EVPN) {
d62a17ae 11277
44c69747 11278 if (!json) {
2dbe669b 11279 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11280 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11281 : "",
2dbe669b 11282 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11283 } else {
11284 json_object_string_add(json, "rd",
11285 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11286 "");
11287 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11288 }
11289 } else {
11290 if (!json) {
9119ef3a
DA
11291 vty_out(vty,
11292 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11293 "\n",
d62a17ae 11294 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11295 ? prefix_rd2str(prd, buf1,
11296 sizeof(buf1))
11297 : ""),
9119ef3a
DA
11298 safi == SAFI_MPLS_VPN ? ":" : "", p,
11299 dest->version);
cd1964ff 11300
9119ef3a 11301 } else {
44c69747
LK
11302 json_object_string_add(json, "prefix",
11303 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11304 json_object_int_add(json, "version", dest->version);
11305
11306 }
44c69747
LK
11307 }
11308
11309 if (has_valid_label) {
11310 if (json)
11311 json_object_int_add(json, "localLabel", label);
11312 else
d62a17ae 11313 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11314 }
11315
11316 if (!json)
d62a17ae 11317 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11318 vty_out(vty, "not allocated\n");
718e3744 11319
9bcb3eef 11320 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11321 count++;
40381db7 11322 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11323 best = count;
4056a5f6 11324 if (bgp_path_suppressed(pi))
d62a17ae 11325 suppress = 1;
cee9c031 11326
40381db7 11327 if (pi->attr->community == NULL)
cee9c031
QY
11328 continue;
11329
11330 no_advertise += community_include(
40381db7
DS
11331 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11332 no_export += community_include(pi->attr->community,
cee9c031 11333 COMMUNITY_NO_EXPORT);
40381db7 11334 local_as += community_include(pi->attr->community,
cee9c031 11335 COMMUNITY_LOCAL_AS);
40381db7 11336 accept_own += community_include(pi->attr->community,
cee9c031
QY
11337 COMMUNITY_ACCEPT_OWN);
11338 route_filter_translated_v4 += community_include(
40381db7 11339 pi->attr->community,
cee9c031
QY
11340 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11341 route_filter_translated_v6 += community_include(
40381db7 11342 pi->attr->community,
cee9c031
QY
11343 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11344 route_filter_v4 += community_include(
40381db7 11345 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11346 route_filter_v6 += community_include(
40381db7
DS
11347 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11348 llgr_stale += community_include(pi->attr->community,
cee9c031 11349 COMMUNITY_LLGR_STALE);
40381db7 11350 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11351 COMMUNITY_NO_LLGR);
11352 accept_own_nexthop +=
40381db7 11353 community_include(pi->attr->community,
cee9c031 11354 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11355 blackhole += community_include(pi->attr->community,
cee9c031 11356 COMMUNITY_BLACKHOLE);
40381db7 11357 no_peer += community_include(pi->attr->community,
cee9c031 11358 COMMUNITY_NO_PEER);
d62a17ae 11359 }
718e3744 11360 }
718e3744 11361
d62a17ae 11362 if (!json) {
11363 vty_out(vty, "Paths: (%d available", count);
11364 if (best) {
11365 vty_out(vty, ", best #%d", best);
b84060bb
PG
11366 if (safi == SAFI_UNICAST) {
11367 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11368 vty_out(vty, ", table %s",
11369 VRF_DEFAULT_NAME);
11370 else
11371 vty_out(vty, ", vrf %s",
11372 bgp->name);
11373 }
d62a17ae 11374 } else
11375 vty_out(vty, ", no best path");
11376
c5f1e1b2
C
11377 if (accept_own)
11378 vty_out(vty,
11379 ", accept own local route exported and imported in different VRF");
11380 else if (route_filter_translated_v4)
11381 vty_out(vty,
11382 ", mark translated RTs for VPNv4 route filtering");
11383 else if (route_filter_v4)
11384 vty_out(vty,
11385 ", attach RT as-is for VPNv4 route filtering");
11386 else if (route_filter_translated_v6)
11387 vty_out(vty,
11388 ", mark translated RTs for VPNv6 route filtering");
11389 else if (route_filter_v6)
11390 vty_out(vty,
11391 ", attach RT as-is for VPNv6 route filtering");
11392 else if (llgr_stale)
11393 vty_out(vty,
11394 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11395 else if (no_llgr)
11396 vty_out(vty,
11397 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11398 else if (accept_own_nexthop)
11399 vty_out(vty,
11400 ", accept local nexthop");
11401 else if (blackhole)
11402 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11403 else if (no_export)
11404 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11405 else if (no_advertise)
11406 vty_out(vty, ", not advertised to any peer");
d62a17ae 11407 else if (local_as)
11408 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11409 else if (no_peer)
11410 vty_out(vty,
11411 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11412
11413 if (suppress)
11414 vty_out(vty,
11415 ", Advertisements suppressed by an aggregate.");
11416 vty_out(vty, ")\n");
11417 }
718e3744 11418
d62a17ae 11419 /* If we are not using addpath then we can display Advertised to and
11420 * that will
11421 * show what peers we advertised the bestpath to. If we are using
11422 * addpath
11423 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11424 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11425 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11426 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11427 if (json && !json_adv_to)
11428 json_adv_to = json_object_new_object();
11429
11430 route_vty_out_advertised_to(
11431 vty, peer, &first,
11432 " Advertised to non peer-group peers:\n ",
11433 json_adv_to);
11434 }
11435 }
11436
11437 if (json) {
11438 if (json_adv_to) {
11439 json_object_object_add(json, "advertisedTo",
11440 json_adv_to);
11441 }
11442 } else {
11443 if (first)
11444 vty_out(vty, " Not advertised to any peer");
11445 vty_out(vty, "\n");
11446 }
11447 }
718e3744 11448}
11449
44c69747 11450static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11451 struct bgp_dest *bgp_node, struct vty *vty,
11452 struct bgp *bgp, afi_t afi, safi_t safi,
11453 json_object *json, enum bgp_path_type pathtype,
4027d19b 11454 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11455{
11456 struct bgp_path_info *pi;
11457 int header = 1;
11458 char rdbuf[RD_ADDRSTRLEN];
11459 json_object *json_header = NULL;
11460 json_object *json_paths = NULL;
4933eaaf 11461 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11462
9bcb3eef 11463 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11464 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11465
11466 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11467 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11468 pi->peer, pi->attr, p);
4933eaaf 11469
4027d19b
DS
11470 if (rpki_target_state != RPKI_NOT_BEING_USED
11471 && rpki_curr_state != rpki_target_state)
4933eaaf 11472 continue;
44c69747
LK
11473
11474 if (json && !json_paths) {
11475 /* Instantiate json_paths only if path is valid */
11476 json_paths = json_object_new_array();
11477 if (pfx_rd) {
11478 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11479 json_header = json_object_new_object();
11480 } else
11481 json_header = json;
11482 }
11483
11484 if (header) {
11485 route_vty_out_detail_header(
11486 vty, bgp, bgp_node, pfx_rd,
11487 AFI_IP, safi, json_header);
11488 header = 0;
11489 }
11490 (*display)++;
11491
11492 if (pathtype == BGP_PATH_SHOW_ALL
11493 || (pathtype == BGP_PATH_SHOW_BESTPATH
11494 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11495 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11496 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11497 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11498 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11499 safi, rpki_curr_state, json_paths);
44c69747
LK
11500 }
11501
11502 if (json && json_paths) {
11503 json_object_object_add(json_header, "paths", json_paths);
11504
11505 if (pfx_rd)
11506 json_object_object_add(json, rdbuf, json_header);
11507 }
11508}
11509
718e3744 11510/* Display specified route of BGP table. */
d62a17ae 11511static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11512 struct bgp_table *rib, const char *ip_str,
11513 afi_t afi, safi_t safi,
4027d19b 11514 enum rpki_states rpki_target_state,
d62a17ae 11515 struct prefix_rd *prd, int prefix_check,
9f049418 11516 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11517{
11518 int ret;
d62a17ae 11519 int display = 0;
11520 struct prefix match;
9bcb3eef
DS
11521 struct bgp_dest *dest;
11522 struct bgp_dest *rm;
d62a17ae 11523 struct bgp_table *table;
11524 json_object *json = NULL;
11525 json_object *json_paths = NULL;
11526
11527 /* Check IP address argument. */
11528 ret = str2prefix(ip_str, &match);
11529 if (!ret) {
11530 vty_out(vty, "address is malformed\n");
11531 return CMD_WARNING;
11532 }
718e3744 11533
d62a17ae 11534 match.family = afi2family(afi);
b05a1c8b 11535
44c69747 11536 if (use_json)
d62a17ae 11537 json = json_object_new_object();
718e3744 11538
44c69747 11539 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11540 for (dest = bgp_table_top(rib); dest;
11541 dest = bgp_route_next(dest)) {
11542 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11543
9bcb3eef 11544 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11545 continue;
9bcb3eef 11546 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11547 if (!table)
ea47320b 11548 continue;
d62a17ae 11549
4953391b
DA
11550 rm = bgp_node_match(table, &match);
11551 if (rm == NULL)
ea47320b 11552 continue;
d62a17ae 11553
9bcb3eef 11554 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11555 if (prefix_check
b54892e0 11556 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11557 bgp_dest_unlock_node(rm);
ea47320b
DL
11558 continue;
11559 }
d62a17ae 11560
9bcb3eef 11561 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11562 bgp, afi, safi, json, pathtype,
4027d19b 11563 &display, rpki_target_state);
44c69747 11564
9bcb3eef 11565 bgp_dest_unlock_node(rm);
44c69747
LK
11566 }
11567 } else if (safi == SAFI_EVPN) {
9bcb3eef 11568 struct bgp_dest *longest_pfx;
cded3b72 11569 bool is_exact_pfxlen_match = false;
44c69747 11570
9bcb3eef
DS
11571 for (dest = bgp_table_top(rib); dest;
11572 dest = bgp_route_next(dest)) {
11573 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11574
9bcb3eef 11575 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11576 continue;
9bcb3eef 11577 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11578 if (!table)
11579 continue;
11580
11581 longest_pfx = NULL;
cded3b72 11582 is_exact_pfxlen_match = false;
44c69747
LK
11583 /*
11584 * Search through all the prefixes for a match. The
11585 * pfx's are enumerated in ascending order of pfxlens.
11586 * So, the last pfx match is the longest match. Set
11587 * is_exact_pfxlen_match when we get exact pfxlen match
11588 */
11589 for (rm = bgp_table_top(table); rm;
11590 rm = bgp_route_next(rm)) {
b54892e0 11591 const struct prefix *rm_p =
9bcb3eef 11592 bgp_dest_get_prefix(rm);
44c69747
LK
11593 /*
11594 * Get prefixlen of the ip-prefix within type5
11595 * evpn route
11596 */
b54892e0
DS
11597 if (evpn_type5_prefix_match(rm_p, &match)
11598 && rm->info) {
44c69747
LK
11599 longest_pfx = rm;
11600 int type5_pfxlen =
b54892e0
DS
11601 bgp_evpn_get_type5_prefixlen(
11602 rm_p);
44c69747 11603 if (type5_pfxlen == match.prefixlen) {
cded3b72 11604 is_exact_pfxlen_match = true;
9bcb3eef 11605 bgp_dest_unlock_node(rm);
44c69747
LK
11606 break;
11607 }
d62a17ae 11608 }
11609 }
ea47320b 11610
44c69747
LK
11611 if (!longest_pfx)
11612 continue;
11613
11614 if (prefix_check && !is_exact_pfxlen_match)
11615 continue;
11616
11617 rm = longest_pfx;
9bcb3eef 11618 bgp_dest_lock_node(rm);
44c69747 11619
9bcb3eef 11620 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11621 bgp, afi, safi, json, pathtype,
4027d19b 11622 &display, rpki_target_state);
44c69747 11623
9bcb3eef 11624 bgp_dest_unlock_node(rm);
d62a17ae 11625 }
98a9dbc7 11626 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11627 if (use_json)
11628 json_paths = json_object_new_array();
11629
63a0b7a9
PG
11630 display = bgp_flowspec_display_match_per_ip(afi, rib,
11631 &match, prefix_check,
11632 vty,
11633 use_json,
11634 json_paths);
d5f20468
SP
11635 if (use_json) {
11636 if (display)
11637 json_object_object_add(json, "paths",
11638 json_paths);
11639 else
11640 json_object_free(json_paths);
11641 }
d62a17ae 11642 } else {
4953391b
DA
11643 dest = bgp_node_match(rib, &match);
11644 if (dest != NULL) {
9bcb3eef 11645 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11646 if (!prefix_check
9bcb3eef
DS
11647 || dest_p->prefixlen == match.prefixlen) {
11648 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11649 safi, json, pathtype,
4027d19b 11650 &display, rpki_target_state);
d62a17ae 11651 }
11652
9bcb3eef 11653 bgp_dest_unlock_node(dest);
d62a17ae 11654 }
11655 }
e5eee9af 11656
d62a17ae 11657 if (use_json) {
996c9314 11658 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11659 json, JSON_C_TO_STRING_PRETTY |
11660 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11661 json_object_free(json);
11662 } else {
11663 if (!display) {
11664 vty_out(vty, "%% Network not in table\n");
11665 return CMD_WARNING;
11666 }
11667 }
b05a1c8b 11668
d62a17ae 11669 return CMD_SUCCESS;
718e3744 11670}
11671
fee0f4c6 11672/* Display specified route of Main RIB */
d62a17ae 11673static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11674 afi_t afi, safi_t safi, struct prefix_rd *prd,
11675 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11676 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11677{
9b86009a 11678 if (!bgp) {
d62a17ae 11679 bgp = bgp_get_default();
9b86009a
RW
11680 if (!bgp) {
11681 if (!use_json)
11682 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11683 else
11684 vty_out(vty, "{}\n");
9b86009a
RW
11685 return CMD_WARNING;
11686 }
11687 }
d62a17ae 11688
11689 /* labeled-unicast routes live in the unicast table */
11690 if (safi == SAFI_LABELED_UNICAST)
11691 safi = SAFI_UNICAST;
11692
11693 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11694 afi, safi, rpki_target_state, prd,
8aa22bbb 11695 prefix_check, pathtype, use_json);
d62a17ae 11696}
11697
11698static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11699 struct cmd_token **argv, bool exact, afi_t afi,
11700 safi_t safi, bool uj)
d62a17ae 11701{
11702 struct lcommunity *lcom;
11703 struct buffer *b;
11704 int i;
11705 char *str;
11706 int first = 0;
96c81f66 11707 uint16_t show_flags = 0;
4f28b2b5 11708 int ret;
96f3485c
MK
11709
11710 if (uj)
11711 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11712
11713 b = buffer_new(1024);
11714 for (i = 0; i < argc; i++) {
11715 if (first)
11716 buffer_putc(b, ' ');
11717 else {
11718 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11719 first = 1;
11720 buffer_putstr(b, argv[i]->arg);
11721 }
11722 }
11723 }
11724 buffer_putc(b, '\0');
57d187bc 11725
d62a17ae 11726 str = buffer_getstr(b);
11727 buffer_free(b);
57d187bc 11728
d62a17ae 11729 lcom = lcommunity_str2com(str);
11730 XFREE(MTYPE_TMP, str);
11731 if (!lcom) {
11732 vty_out(vty, "%% Large-community malformed\n");
11733 return CMD_WARNING;
11734 }
57d187bc 11735
4f28b2b5 11736 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11737 (exact ? bgp_show_type_lcommunity_exact
11738 : bgp_show_type_lcommunity),
11739 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11740
11741 lcommunity_free(&lcom);
11742 return ret;
57d187bc
JS
11743}
11744
d62a17ae 11745static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11746 const char *lcom, bool exact, afi_t afi,
11747 safi_t safi, bool uj)
57d187bc 11748{
d62a17ae 11749 struct community_list *list;
96c81f66 11750 uint16_t show_flags = 0;
96f3485c
MK
11751
11752 if (uj)
11753 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11754
57d187bc 11755
e237b0d2 11756 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11757 LARGE_COMMUNITY_LIST_MASTER);
11758 if (list == NULL) {
11759 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11760 lcom);
11761 return CMD_WARNING;
11762 }
57d187bc 11763
36a206db 11764 return bgp_show(vty, bgp, afi, safi,
11765 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11766 : bgp_show_type_lcommunity_list),
1e2ce4f1 11767 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11768}
11769
52951b63
DS
11770DEFUN (show_ip_bgp_large_community_list,
11771 show_ip_bgp_large_community_list_cmd,
77a3a95e 11772 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
52951b63
DS
11773 SHOW_STR
11774 IP_STR
11775 BGP_STR
11776 BGP_INSTANCE_HELP_STR
9bedbb1e 11777 BGP_AFI_HELP_STR
4dd6177e 11778 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11779 "Display routes matching the large-community-list\n"
11780 "large-community-list number\n"
11781 "large-community-list name\n"
36a206db 11782 "Exact match of the large-communities\n"
52951b63
DS
11783 JSON_STR)
11784{
d62a17ae 11785 afi_t afi = AFI_IP6;
11786 safi_t safi = SAFI_UNICAST;
11787 int idx = 0;
36a206db 11788 bool exact_match = 0;
4d678463 11789 struct bgp *bgp = NULL;
9f049418 11790 bool uj = use_json(argc, argv);
d62a17ae 11791
ef3364f0
DA
11792 if (uj)
11793 argc--;
4d678463 11794
ef3364f0
DA
11795 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11796 &bgp, uj);
11797 if (!idx)
11798 return CMD_WARNING;
d62a17ae 11799
11800 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11801
11802 const char *clist_number_or_name = argv[++idx]->arg;
11803
11804 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11805 exact_match = 1;
11806
11807 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11808 exact_match, afi, safi, uj);
52951b63
DS
11809}
11810DEFUN (show_ip_bgp_large_community,
11811 show_ip_bgp_large_community_cmd,
36a206db 11812 "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
11813 SHOW_STR
11814 IP_STR
11815 BGP_STR
11816 BGP_INSTANCE_HELP_STR
9bedbb1e 11817 BGP_AFI_HELP_STR
4dd6177e 11818 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11819 "Display routes matching the large-communities\n"
11820 "List of large-community numbers\n"
36a206db 11821 "Exact match of the large-communities\n"
52951b63
DS
11822 JSON_STR)
11823{
d62a17ae 11824 afi_t afi = AFI_IP6;
11825 safi_t safi = SAFI_UNICAST;
11826 int idx = 0;
36a206db 11827 bool exact_match = 0;
4d678463 11828 struct bgp *bgp = NULL;
9f049418 11829 bool uj = use_json(argc, argv);
96c81f66 11830 uint16_t show_flags = 0;
d62a17ae 11831
96f3485c
MK
11832 if (uj) {
11833 argc--;
11834 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11835 }
4d678463 11836
96f3485c
MK
11837 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11838 &bgp, uj);
11839 if (!idx)
11840 return CMD_WARNING;
d62a17ae 11841
36a206db 11842 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11843 if (argv_find(argv, argc, "exact-match", &idx))
11844 exact_match = 1;
11845 return bgp_show_lcommunity(vty, bgp, argc, argv,
11846 exact_match, afi, safi, uj);
11847 } else
d62a17ae 11848 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11849 bgp_show_type_lcommunity_all, NULL, show_flags,
11850 RPKI_NOT_BEING_USED);
52951b63
DS
11851}
11852
71f1613a
DA
11853static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11854 safi_t safi, struct json_object *json_array);
d62a17ae 11855static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11856 safi_t safi, struct json_object *json);
e01ca200 11857
7b2ff250 11858
9ab0cf58
PG
11859DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11860 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11861 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11862 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11863{
11864 bool uj = use_json(argc, argv);
11865 struct bgp *bgp = NULL;
ec76a1d1
DA
11866 safi_t safi = SAFI_UNICAST;
11867 afi_t afi = AFI_IP6;
4265b261 11868 int idx = 0;
6c9d22e2
PG
11869 struct json_object *json_all = NULL;
11870 struct json_object *json_afi_safi = NULL;
4265b261
PG
11871
11872 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11873 &bgp, false);
71f1613a 11874 if (!idx)
4265b261 11875 return CMD_WARNING;
6c9d22e2 11876
4265b261 11877 if (uj)
6c9d22e2 11878 json_all = json_object_new_object();
4265b261 11879
9ab0cf58
PG
11880 FOREACH_AFI_SAFI (afi, safi) {
11881 /*
11882 * So limit output to those afi/safi pairs that
11883 * actually have something interesting in them
11884 */
11885 if (strmatch(get_afi_safi_str(afi, safi, true),
11886 "Unknown")) {
11887 continue;
11888 }
11889 if (uj) {
11890 json_afi_safi = json_object_new_array();
11891 json_object_object_add(
11892 json_all,
11893 get_afi_safi_str(afi, safi, true),
11894 json_afi_safi);
11895 } else {
11896 json_afi_safi = NULL;
6c9d22e2 11897 }
9ab0cf58
PG
11898
11899 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11900 }
6c9d22e2
PG
11901
11902 if (uj) {
9ab0cf58
PG
11903 vty_out(vty, "%s",
11904 json_object_to_json_string_ext(
11905 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11906 json_object_free(json_all);
4265b261 11907 }
6c9d22e2 11908
4265b261
PG
11909 return CMD_SUCCESS;
11910}
11911
7b2ff250 11912/* BGP route print out function without JSON */
14718643
PG
11913DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11914 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11915 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11916 SHOW_STR
11917 IP_STR
11918 BGP_STR
11919 BGP_INSTANCE_HELP_STR
11920 L2VPN_HELP_STR
11921 EVPN_HELP_STR
11922 "BGP RIB advertisement statistics\n"
11923 JSON_STR)
11924{
ec76a1d1
DA
11925 afi_t afi = AFI_IP6;
11926 safi_t safi = SAFI_UNICAST;
14718643
PG
11927 struct bgp *bgp = NULL;
11928 int idx = 0, ret;
11929 bool uj = use_json(argc, argv);
11930 struct json_object *json_afi_safi = NULL, *json = NULL;
11931
11932 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11933 &bgp, false);
11934 if (!idx)
11935 return CMD_WARNING;
11936
11937 if (uj)
11938 json_afi_safi = json_object_new_array();
11939 else
11940 json_afi_safi = NULL;
11941
11942 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11943
11944 if (uj) {
11945 json = json_object_new_object();
11946 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11947 json_afi_safi);
11948 vty_out(vty, "%s", json_object_to_json_string_ext(
11949 json, JSON_C_TO_STRING_PRETTY));
11950 json_object_free(json);
11951 }
11952 return ret;
11953}
11954
893cccd0 11955/* BGP route print out function without JSON */
9ab0cf58
PG
11956DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11957 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11958 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11959 "]]\
893cccd0 11960 statistics [json]",
9ab0cf58
PG
11961 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11962 BGP_SAFI_WITH_LABEL_HELP_STR
11963 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11964{
ec76a1d1
DA
11965 afi_t afi = AFI_IP6;
11966 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11967 struct bgp *bgp = NULL;
11968 int idx = 0, ret;
11969 bool uj = use_json(argc, argv);
6c9d22e2 11970 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11971
11972 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11973 &bgp, false);
11974 if (!idx)
11975 return CMD_WARNING;
6c9d22e2 11976
893cccd0 11977 if (uj)
6c9d22e2
PG
11978 json_afi_safi = json_object_new_array();
11979 else
11980 json_afi_safi = NULL;
11981
11982 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11983
11984 if (uj) {
11985 json = json_object_new_object();
11986 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11987 json_afi_safi);
9ab0cf58
PG
11988 vty_out(vty, "%s",
11989 json_object_to_json_string_ext(
11990 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11991 json_object_free(json);
11992 }
11993 return ret;
893cccd0 11994}
7b2ff250
DW
11995
11996/* BGP route print out function without JSON */
96f3485c 11997DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11998 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11999 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12000 "]]\
96f3485c 12001 <[all$all] dampening <parameters>\
7b2ff250
DW
12002 |route-map WORD\
12003 |prefix-list WORD\
12004 |filter-list WORD\
96870ecb 12005 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
7b2ff250
DW
12006 |A.B.C.D/M longer-prefixes\
12007 |X:X::X:X/M longer-prefixes\
893cccd0 12008 >",
9ab0cf58
PG
12009 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12010 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12011 "Display the entries for all address families\n"
9ab0cf58
PG
12012 "Display detailed information about dampening\n"
12013 "Display detail of configured dampening parameters\n"
12014 "Display routes matching the route-map\n"
12015 "A route-map to match on\n"
12016 "Display routes conforming to the prefix-list\n"
12017 "Prefix-list name\n"
12018 "Display routes conforming to the filter-list\n"
12019 "Regular expression access list name\n"
12020 "Display routes matching the community-list\n"
12021 "community-list number\n"
12022 "community-list name\n"
12023 "Exact match of the communities\n"
12024 "IPv4 prefix\n"
12025 "Display route and more specific routes\n"
12026 "IPv6 prefix\n"
12027 "Display route and more specific routes\n")
718e3744 12028{
d62a17ae 12029 afi_t afi = AFI_IP6;
12030 safi_t safi = SAFI_UNICAST;
12031 int exact_match = 0;
d62a17ae 12032 struct bgp *bgp = NULL;
12033 int idx = 0;
96c81f66 12034 uint16_t show_flags = 0;
96f3485c
MK
12035
12036 /* [<ipv4|ipv6> [all]] */
12037 if (all) {
12038 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12039 if (argv_find(argv, argc, "ipv4", &idx))
12040 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12041
12042 if (argv_find(argv, argc, "ipv6", &idx))
12043 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12044 }
d62a17ae 12045
12046 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12047 &bgp, false);
d62a17ae 12048 if (!idx)
12049 return CMD_WARNING;
12050
d62a17ae 12051 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 12052 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
12053 return bgp_show_dampening_parameters(vty, afi, safi,
12054 show_flags);
d62a17ae 12055 }
c016b6c7 12056
d62a17ae 12057 if (argv_find(argv, argc, "prefix-list", &idx))
12058 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12059 safi, bgp_show_type_prefix_list);
12060
12061 if (argv_find(argv, argc, "filter-list", &idx))
12062 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12063 safi, bgp_show_type_filter_list);
12064
d62a17ae 12065 if (argv_find(argv, argc, "route-map", &idx))
12066 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12067 safi, bgp_show_type_route_map);
12068
d62a17ae 12069 if (argv_find(argv, argc, "community-list", &idx)) {
12070 const char *clist_number_or_name = argv[++idx]->arg;
12071 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12072 exact_match = 1;
12073 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12074 exact_match, afi, safi);
12075 }
12076 /* prefix-longer */
12077 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12078 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12079 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12080 safi,
12081 bgp_show_type_prefix_longer);
12082
7b2ff250
DW
12083 return CMD_WARNING;
12084}
12085
12086/* BGP route print out function with JSON */
a70a28a5
DA
12087DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12088 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12089 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12090 "]]\
96f3485c 12091 [all$all]\
cf4898bc
QY
12092 [cidr-only\
12093 |dampening <flap-statistics|dampened-paths>\
12094 |community [AA:NN|local-AS|no-advertise|no-export\
12095 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12096 |accept-own|accept-own-nexthop|route-filter-v6\
12097 |route-filter-v4|route-filter-translated-v6\
12098 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 12099 |rpki <invalid|valid|notfound>\
7d3cae70 12100 |version (1-4294967295)\
b4ad2fae 12101 |alias ALIAS_NAME\
f280c93b 12102 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12103 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12104 BGP_SAFI_WITH_LABEL_HELP_STR
12105 "Display the entries for all address families\n"
12106 "Display only routes with non-natural netmasks\n"
12107 "Display detailed information about dampening\n"
12108 "Display flap statistics of routes\n"
12109 "Display paths suppressed due to dampening\n"
12110 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12111 "Do not send outside local AS (well-known community)\n"
12112 "Do not advertise to any peer (well-known community)\n"
12113 "Do not export to next AS (well-known community)\n"
12114 "Graceful shutdown (well-known community)\n"
12115 "Do not export to any peer (well-known community)\n"
12116 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12117 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12118 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12119 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12120 "Should accept VPN route with local nexthop (well-known community)\n"
12121 "RT VPNv6 route filtering (well-known community)\n"
12122 "RT VPNv4 route filtering (well-known community)\n"
12123 "RT translated VPNv6 route filtering (well-known community)\n"
12124 "RT translated VPNv4 route filtering (well-known community)\n"
12125 "Exact match of the communities\n"
12126 "RPKI route types\n"
12127 "A valid path as determined by rpki\n"
12128 "A invalid path as determined by rpki\n"
12129 "A path that has no rpki data\n"
12130 "Display prefixes with matching version numbers\n"
12131 "Version number and above\n"
12132 "Display prefixes with matching BGP community alias\n"
12133 "BGP community alias\n" JSON_STR
12134 "Display detailed version of JSON output\n"
12135 "Increase table width for longer prefixes\n")
7b2ff250
DW
12136{
12137 afi_t afi = AFI_IP6;
12138 safi_t safi = SAFI_UNICAST;
12139 enum bgp_show_type sh_type = bgp_show_type_normal;
12140 struct bgp *bgp = NULL;
12141 int idx = 0;
d0086e8e 12142 int exact_match = 0;
96f3485c 12143 char *community = NULL;
7d3cae70 12144 char *prefix_version = NULL;
a70a28a5 12145 char *bgp_community_alias = NULL;
96f3485c 12146 bool first = true;
96c81f66 12147 uint16_t show_flags = 0;
4027d19b 12148 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12149
12150 if (uj) {
9f049418 12151 argc--;
96f3485c
MK
12152 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12153 }
12154
f280c93b
DA
12155 if (detail)
12156 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12157
96f3485c
MK
12158 /* [<ipv4|ipv6> [all]] */
12159 if (all) {
12160 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12161
12162 if (argv_find(argv, argc, "ipv4", &idx))
12163 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12164
12165 if (argv_find(argv, argc, "ipv6", &idx))
12166 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12167 }
12168
12169 if (wide)
12170 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12171
12172 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12173 &bgp, uj);
7b2ff250
DW
12174 if (!idx)
12175 return CMD_WARNING;
12176
7b2ff250 12177 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12178 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12179
12180 if (argv_find(argv, argc, "dampening", &idx)) {
12181 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12182 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12183 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12184 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12185 }
12186
12187 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12188 char *maybecomm = NULL;
d0086e8e 12189
79bc257a
RW
12190 if (idx + 1 < argc) {
12191 if (argv[idx + 1]->type == VARIABLE_TKN)
12192 maybecomm = argv[idx + 1]->arg;
12193 else
12194 maybecomm = argv[idx + 1]->text;
12195 }
12196
cf4898bc
QY
12197 if (maybecomm && !strmatch(maybecomm, "json")
12198 && !strmatch(maybecomm, "exact-match"))
12199 community = maybecomm;
d0086e8e 12200
cf4898bc
QY
12201 if (argv_find(argv, argc, "exact-match", &idx))
12202 exact_match = 1;
d0086e8e 12203
96f3485c
MK
12204 if (!community)
12205 sh_type = bgp_show_type_community_all;
12206 }
12207
1e2ce4f1
DS
12208 if (argv_find(argv, argc, "rpki", &idx)) {
12209 sh_type = bgp_show_type_rpki;
12210 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12211 rpki_target_state = RPKI_VALID;
1e2ce4f1 12212 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12213 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12214 }
12215
7d3cae70
DA
12216 /* Display prefixes with matching version numbers */
12217 if (argv_find(argv, argc, "version", &idx)) {
12218 sh_type = bgp_show_type_prefix_version;
12219 prefix_version = argv[idx + 1]->arg;
12220 }
12221
a70a28a5
DA
12222 /* Display prefixes with matching BGP community alias */
12223 if (argv_find(argv, argc, "alias", &idx)) {
12224 sh_type = bgp_show_type_community_alias;
12225 bgp_community_alias = argv[idx + 1]->arg;
12226 }
12227
96f3485c
MK
12228 if (!all) {
12229 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12230 if (community)
12231 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12232 exact_match, afi, safi,
12233 show_flags);
7d3cae70
DA
12234 else if (prefix_version)
12235 return bgp_show(vty, bgp, afi, safi, sh_type,
12236 prefix_version, show_flags,
12237 rpki_target_state);
a70a28a5
DA
12238 else if (bgp_community_alias)
12239 return bgp_show(vty, bgp, afi, safi, sh_type,
12240 bgp_community_alias, show_flags,
12241 rpki_target_state);
cf4898bc 12242 else
96f3485c 12243 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12244 show_flags, rpki_target_state);
96f3485c
MK
12245 } else {
12246 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12247 * AFI_IP6 */
12248
12249 if (uj)
12250 vty_out(vty, "{\n");
12251
12252 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12253 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12254 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12255 ? AFI_IP
12256 : AFI_IP6;
12257 FOREACH_SAFI (safi) {
96f3485c
MK
12258 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12259 continue;
12260
12261 if (uj) {
12262 if (first)
12263 first = false;
12264 else
12265 vty_out(vty, ",\n");
12266 vty_out(vty, "\"%s\":{\n",
12267 get_afi_safi_str(afi, safi,
12268 true));
12269 } else
12270 vty_out(vty,
12271 "\nFor address family: %s\n",
12272 get_afi_safi_str(afi, safi,
12273 false));
12274
12275 if (community)
12276 bgp_show_community(vty, bgp, community,
12277 exact_match, afi,
12278 safi, show_flags);
7d3cae70
DA
12279 else if (prefix_version)
12280 return bgp_show(vty, bgp, afi, safi,
12281 sh_type, prefix_version,
12282 show_flags,
12283 rpki_target_state);
a70a28a5
DA
12284 else if (bgp_community_alias)
12285 return bgp_show(
12286 vty, bgp, afi, safi, sh_type,
12287 bgp_community_alias, show_flags,
12288 rpki_target_state);
96f3485c
MK
12289 else
12290 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12291 NULL, show_flags,
4027d19b 12292 rpki_target_state);
96f3485c
MK
12293 if (uj)
12294 vty_out(vty, "}\n");
12295 }
12296 } else {
12297 /* show <ip> bgp all: for each AFI and SAFI*/
12298 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12299 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12300 continue;
12301
12302 if (uj) {
12303 if (first)
12304 first = false;
12305 else
12306 vty_out(vty, ",\n");
d0086e8e 12307
96f3485c
MK
12308 vty_out(vty, "\"%s\":{\n",
12309 get_afi_safi_str(afi, safi,
12310 true));
12311 } else
12312 vty_out(vty,
12313 "\nFor address family: %s\n",
12314 get_afi_safi_str(afi, safi,
12315 false));
12316
12317 if (community)
12318 bgp_show_community(vty, bgp, community,
12319 exact_match, afi,
12320 safi, show_flags);
7d3cae70
DA
12321 else if (prefix_version)
12322 return bgp_show(vty, bgp, afi, safi,
12323 sh_type, prefix_version,
12324 show_flags,
12325 rpki_target_state);
96f3485c
MK
12326 else
12327 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12328 NULL, show_flags,
4027d19b 12329 rpki_target_state);
96f3485c
MK
12330 if (uj)
12331 vty_out(vty, "}\n");
12332 }
12333 }
12334 if (uj)
12335 vty_out(vty, "}\n");
12336 }
12337 return CMD_SUCCESS;
a636c635 12338}
47fc97cc 12339
718e3744 12340DEFUN (show_ip_bgp_route,
12341 show_ip_bgp_route_cmd,
8aa22bbb 12342 "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 12343 SHOW_STR
12344 IP_STR
12345 BGP_STR
a636c635 12346 BGP_INSTANCE_HELP_STR
4f280b15 12347 BGP_AFI_HELP_STR
4dd6177e 12348 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12349 "Network in the BGP routing table to display\n"
0c7b1b01 12350 "IPv4 prefix\n"
8c3deaae 12351 "Network in the BGP routing table to display\n"
0c7b1b01 12352 "IPv6 prefix\n"
4092b06c 12353 "Display only the bestpath\n"
b05a1c8b 12354 "Display only multipaths\n"
8aa22bbb
DS
12355 "Display only paths that match the specified rpki state\n"
12356 "A valid path as determined by rpki\n"
12357 "A invalid path as determined by rpki\n"
12358 "A path that has no rpki data\n"
9973d184 12359 JSON_STR)
4092b06c 12360{
d62a17ae 12361 int prefix_check = 0;
ae19d7dd 12362
d62a17ae 12363 afi_t afi = AFI_IP6;
12364 safi_t safi = SAFI_UNICAST;
12365 char *prefix = NULL;
12366 struct bgp *bgp = NULL;
12367 enum bgp_path_type path_type;
9f049418 12368 bool uj = use_json(argc, argv);
b05a1c8b 12369
d62a17ae 12370 int idx = 0;
ae19d7dd 12371
d62a17ae 12372 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12373 &bgp, uj);
d62a17ae 12374 if (!idx)
12375 return CMD_WARNING;
c41247f5 12376
d62a17ae 12377 if (!bgp) {
12378 vty_out(vty,
12379 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12380 return CMD_WARNING;
12381 }
a636c635 12382
d62a17ae 12383 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12384 if (argv_find(argv, argc, "A.B.C.D", &idx)
12385 || argv_find(argv, argc, "X:X::X:X", &idx))
12386 prefix_check = 0;
12387 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12388 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12389 prefix_check = 1;
12390
12391 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12392 && afi != AFI_IP6) {
12393 vty_out(vty,
12394 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12395 return CMD_WARNING;
12396 }
12397 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12398 && afi != AFI_IP) {
12399 vty_out(vty,
12400 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12401 return CMD_WARNING;
12402 }
12403
12404 prefix = argv[idx]->arg;
12405
12406 /* [<bestpath|multipath>] */
12407 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12408 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12409 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12410 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12411 else
360660c6 12412 path_type = BGP_PATH_SHOW_ALL;
a636c635 12413
d62a17ae 12414 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12415 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12416}
12417
8c3deaae
QY
12418DEFUN (show_ip_bgp_regexp,
12419 show_ip_bgp_regexp_cmd,
3e5b31b3 12420 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12421 SHOW_STR
12422 IP_STR
12423 BGP_STR
b00b230a 12424 BGP_INSTANCE_HELP_STR
4f280b15 12425 BGP_AFI_HELP_STR
4dd6177e 12426 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12427 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12428 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12429 JSON_STR)
8c3deaae 12430{
d62a17ae 12431 afi_t afi = AFI_IP6;
12432 safi_t safi = SAFI_UNICAST;
12433 struct bgp *bgp = NULL;
3e5b31b3
DA
12434 bool uj = use_json(argc, argv);
12435 char *regstr = NULL;
8c3deaae 12436
d62a17ae 12437 int idx = 0;
12438 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12439 &bgp, false);
d62a17ae 12440 if (!idx)
12441 return CMD_WARNING;
8c3deaae 12442
d62a17ae 12443 // get index of regex
3e5b31b3
DA
12444 if (argv_find(argv, argc, "REGEX", &idx))
12445 regstr = argv[idx]->arg;
8c3deaae 12446
5f71d11c 12447 assert(regstr);
3e5b31b3
DA
12448 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12449 bgp_show_type_regexp, uj);
8c3deaae
QY
12450}
12451
ae248832 12452DEFPY (show_ip_bgp_instance_all,
a636c635 12453 show_ip_bgp_instance_all_cmd,
ae248832 12454 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12455 SHOW_STR
a636c635 12456 IP_STR
4092b06c 12457 BGP_STR
a636c635 12458 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12459 BGP_AFI_HELP_STR
4dd6177e 12460 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12461 JSON_STR
12462 "Increase table width for longer prefixes\n")
4092b06c 12463{
d62a17ae 12464 afi_t afi = AFI_IP;
12465 safi_t safi = SAFI_UNICAST;
12466 struct bgp *bgp = NULL;
d62a17ae 12467 int idx = 0;
96c81f66 12468 uint16_t show_flags = 0;
ae19d7dd 12469
96f3485c 12470 if (uj) {
d62a17ae 12471 argc--;
96f3485c
MK
12472 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12473 }
12474
12475 if (wide)
12476 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12477
9f049418
DS
12478 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12479 &bgp, uj);
12480 if (!idx)
12481 return CMD_WARNING;
12482
96f3485c 12483 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12484 return CMD_SUCCESS;
e3e29b32
LB
12485}
12486
a4d82a8a 12487static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12488 afi_t afi, safi_t safi, enum bgp_show_type type,
12489 bool use_json)
718e3744 12490{
d62a17ae 12491 regex_t *regex;
12492 int rc;
96c81f66 12493 uint16_t show_flags = 0;
96f3485c
MK
12494
12495 if (use_json)
12496 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12497
c3900853 12498 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12499 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12500 regstr);
12501 return CMD_WARNING_CONFIG_FAILED;
12502 }
12503
d62a17ae 12504 regex = bgp_regcomp(regstr);
12505 if (!regex) {
12506 vty_out(vty, "Can't compile regexp %s\n", regstr);
12507 return CMD_WARNING;
12508 }
a636c635 12509
1e2ce4f1
DS
12510 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12511 RPKI_NOT_BEING_USED);
d62a17ae 12512 bgp_regex_free(regex);
12513 return rc;
e3e29b32
LB
12514}
12515
d62a17ae 12516static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12517 const char *prefix_list_str, afi_t afi,
12518 safi_t safi, enum bgp_show_type type)
e3e29b32 12519{
d62a17ae 12520 struct prefix_list *plist;
96c81f66 12521 uint16_t show_flags = 0;
718e3744 12522
d62a17ae 12523 plist = prefix_list_lookup(afi, prefix_list_str);
12524 if (plist == NULL) {
12525 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12526 prefix_list_str);
12527 return CMD_WARNING;
12528 }
718e3744 12529
1e2ce4f1
DS
12530 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12531 RPKI_NOT_BEING_USED);
4092b06c
DS
12532}
12533
d62a17ae 12534static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12535 const char *filter, afi_t afi, safi_t safi,
12536 enum bgp_show_type type)
4092b06c 12537{
d62a17ae 12538 struct as_list *as_list;
96c81f66 12539 uint16_t show_flags = 0;
718e3744 12540
d62a17ae 12541 as_list = as_list_lookup(filter);
12542 if (as_list == NULL) {
12543 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12544 filter);
12545 return CMD_WARNING;
12546 }
a636c635 12547
1e2ce4f1
DS
12548 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12549 RPKI_NOT_BEING_USED);
718e3744 12550}
12551
d62a17ae 12552static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12553 const char *rmap_str, afi_t afi, safi_t safi,
12554 enum bgp_show_type type)
718e3744 12555{
d62a17ae 12556 struct route_map *rmap;
96c81f66 12557 uint16_t show_flags = 0;
bb46e94f 12558
d62a17ae 12559 rmap = route_map_lookup_by_name(rmap_str);
12560 if (!rmap) {
12561 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12562 return CMD_WARNING;
12563 }
12564
1e2ce4f1
DS
12565 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12566 RPKI_NOT_BEING_USED);
d62a17ae 12567}
12568
7f323236
DW
12569static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12570 const char *comstr, int exact, afi_t afi,
96c81f66 12571 safi_t safi, uint16_t show_flags)
d62a17ae 12572{
12573 struct community *com;
d62a17ae 12574 int ret = 0;
12575
7f323236 12576 com = community_str2com(comstr);
d62a17ae 12577 if (!com) {
7f323236 12578 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12579 return CMD_WARNING;
12580 }
12581
12582 ret = bgp_show(vty, bgp, afi, safi,
12583 (exact ? bgp_show_type_community_exact
12584 : bgp_show_type_community),
1e2ce4f1 12585 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12586 community_free(&com);
46c3ce83 12587
d62a17ae 12588 return ret;
718e3744 12589}
12590
d62a17ae 12591static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12592 const char *com, int exact, afi_t afi,
12593 safi_t safi)
50ef26d4 12594{
d62a17ae 12595 struct community_list *list;
96c81f66 12596 uint16_t show_flags = 0;
50ef26d4 12597
e237b0d2 12598 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12599 if (list == NULL) {
12600 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12601 return CMD_WARNING;
12602 }
718e3744 12603
d62a17ae 12604 return bgp_show(vty, bgp, afi, safi,
12605 (exact ? bgp_show_type_community_list_exact
12606 : bgp_show_type_community_list),
1e2ce4f1 12607 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12608}
12609
d62a17ae 12610static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12611 const char *prefix, afi_t afi, safi_t safi,
12612 enum bgp_show_type type)
718e3744 12613{
d62a17ae 12614 int ret;
12615 struct prefix *p;
96c81f66 12616 uint16_t show_flags = 0;
47fc97cc 12617
d62a17ae 12618 p = prefix_new();
95cbbd2a 12619
d62a17ae 12620 ret = str2prefix(prefix, p);
12621 if (!ret) {
12622 vty_out(vty, "%% Malformed Prefix\n");
12623 return CMD_WARNING;
12624 }
47e9b292 12625
1e2ce4f1
DS
12626 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12627 RPKI_NOT_BEING_USED);
63265b5c 12628 prefix_free(&p);
d62a17ae 12629 return ret;
12630}
12631
d62a17ae 12632enum bgp_stats {
12633 BGP_STATS_MAXBITLEN = 0,
12634 BGP_STATS_RIB,
12635 BGP_STATS_PREFIXES,
12636 BGP_STATS_TOTPLEN,
12637 BGP_STATS_UNAGGREGATEABLE,
12638 BGP_STATS_MAX_AGGREGATEABLE,
12639 BGP_STATS_AGGREGATES,
12640 BGP_STATS_SPACE,
12641 BGP_STATS_ASPATH_COUNT,
12642 BGP_STATS_ASPATH_MAXHOPS,
12643 BGP_STATS_ASPATH_TOTHOPS,
12644 BGP_STATS_ASPATH_MAXSIZE,
12645 BGP_STATS_ASPATH_TOTSIZE,
12646 BGP_STATS_ASN_HIGHEST,
12647 BGP_STATS_MAX,
a636c635 12648};
2815e61f 12649
9ab0cf58 12650#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12651#define TABLE_STATS_IDX_JSON 1
12652
12653static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12654 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12655 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12656 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12657 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12658 "unaggregateablePrefixes"},
12659 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12660 "maximumAggregateablePrefixes"},
12661 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12662 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12663 [BGP_STATS_SPACE] = {"Address space advertised",
12664 "addressSpaceAdvertised"},
9ab0cf58
PG
12665 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12666 "advertisementsWithPaths"},
12667 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12668 "longestAsPath"},
12669 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12670 "largestAsPath"},
12671 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12672 "averageAsPathLengthHops"},
12673 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12674 "averageAsPathSizeBytes"},
12675 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12676 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12677};
2815e61f 12678
d62a17ae 12679struct bgp_table_stats {
12680 struct bgp_table *table;
12681 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12682 double total_space;
ff7924f6
PJ
12683};
12684
9bcb3eef 12685static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12686 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12687{
9bcb3eef 12688 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12689 struct bgp_path_info *pi;
b54892e0 12690 const struct prefix *rn_p;
d62a17ae 12691
9bcb3eef 12692 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12693 return;
d62a17ae 12694
9bcb3eef 12695 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12696 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12697 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12698
9c14ec72 12699 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12700 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12701 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12702
9bcb3eef 12703 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12704 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12705 /* announced address space */
12706 if (space)
b54892e0 12707 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12708 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12709 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12710
9c14ec72 12711
9bcb3eef 12712 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12713 ts->counts[BGP_STATS_RIB]++;
12714
05864da7
DS
12715 if (CHECK_FLAG(pi->attr->flag,
12716 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12717 ts->counts[BGP_STATS_AGGREGATES]++;
12718
12719 /* as-path stats */
05864da7 12720 if (pi->attr->aspath) {
9c14ec72
RW
12721 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12722 unsigned int size = aspath_size(pi->attr->aspath);
12723 as_t highest = aspath_highest(pi->attr->aspath);
12724
12725 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12726
12727 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12728 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12729
12730 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12731 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12732
12733 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12734 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12735 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12736 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12737 }
12738 }
12739}
12740
12741static int bgp_table_stats_walker(struct thread *t)
12742{
9bcb3eef
DS
12743 struct bgp_dest *dest, *ndest;
12744 struct bgp_dest *top;
9c14ec72
RW
12745 struct bgp_table_stats *ts = THREAD_ARG(t);
12746 unsigned int space = 0;
12747
12748 if (!(top = bgp_table_top(ts->table)))
12749 return 0;
12750
12751 switch (ts->table->afi) {
12752 case AFI_IP:
12753 space = IPV4_MAX_BITLEN;
12754 break;
12755 case AFI_IP6:
12756 space = IPV6_MAX_BITLEN;
12757 break;
3ba7b4af
TA
12758 case AFI_L2VPN:
12759 space = EVPN_ROUTE_PREFIXLEN;
12760 break;
9c14ec72
RW
12761 default:
12762 return 0;
12763 }
12764
12765 ts->counts[BGP_STATS_MAXBITLEN] = space;
12766
9bcb3eef 12767 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12768 if (ts->table->safi == SAFI_MPLS_VPN
12769 || ts->table->safi == SAFI_ENCAP
12770 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12771 struct bgp_table *table;
12772
9bcb3eef 12773 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12774 if (!table)
12775 continue;
12776
12777 top = bgp_table_top(table);
9bcb3eef
DS
12778 for (ndest = bgp_table_top(table); ndest;
12779 ndest = bgp_route_next(ndest))
12780 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12781 } else {
9bcb3eef 12782 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12783 }
12784 }
9c14ec72 12785
d62a17ae 12786 return 0;
2815e61f 12787}
ff7924f6 12788
71f1613a
DA
12789static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12790 struct json_object *json_array)
12791{
12792 struct listnode *node, *nnode;
12793 struct bgp *bgp;
12794
12795 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12796 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12797}
12798
12799static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12800 safi_t safi, struct json_object *json_array)
2815e61f 12801{
d62a17ae 12802 struct bgp_table_stats ts;
12803 unsigned int i;
893cccd0
PG
12804 int ret = CMD_SUCCESS;
12805 char temp_buf[20];
6c9d22e2
PG
12806 struct json_object *json = NULL;
12807
12808 if (json_array)
12809 json = json_object_new_object();
019386c2 12810
d62a17ae 12811 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12812 char warning_msg[50];
12813
12814 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12815 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12816 safi);
6c9d22e2
PG
12817
12818 if (!json)
893cccd0
PG
12819 vty_out(vty, "%s\n", warning_msg);
12820 else
9ab0cf58 12821 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12822
893cccd0
PG
12823 ret = CMD_WARNING;
12824 goto end_table_stats;
d62a17ae 12825 }
019386c2 12826
893cccd0 12827 if (!json)
5290ceab
DA
12828 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12829 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12830 else
12831 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12832
d62a17ae 12833 /* labeled-unicast routes live in the unicast table */
12834 if (safi == SAFI_LABELED_UNICAST)
12835 safi = SAFI_UNICAST;
019386c2 12836
d62a17ae 12837 memset(&ts, 0, sizeof(ts));
12838 ts.table = bgp->rib[afi][safi];
12839 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12840
d62a17ae 12841 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12842 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12843 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12844 continue;
12845
12846 switch (i) {
d62a17ae 12847 case BGP_STATS_ASPATH_TOTHOPS:
12848 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12849 if (!json) {
9ab0cf58
PG
12850 snprintf(
12851 temp_buf, sizeof(temp_buf), "%12.2f",
12852 ts.counts[i]
12853 ? (float)ts.counts[i]
12854 / (float)ts.counts
12855 [BGP_STATS_ASPATH_COUNT]
12856 : 0);
893cccd0 12857 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12858 table_stats_strs[i]
12859 [TABLE_STATS_IDX_VTY],
893cccd0 12860 temp_buf);
9ab0cf58
PG
12861 } else {
12862 json_object_double_add(
12863 json,
12864 table_stats_strs[i]
12865 [TABLE_STATS_IDX_JSON],
12866 ts.counts[i]
12867 ? (double)ts.counts[i]
12868 / (double)ts.counts
d62a17ae 12869 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12870 : 0);
12871 }
d62a17ae 12872 break;
12873 case BGP_STATS_TOTPLEN:
6c9d22e2 12874 if (!json) {
9ab0cf58
PG
12875 snprintf(
12876 temp_buf, sizeof(temp_buf), "%12.2f",
12877 ts.counts[i]
12878 ? (float)ts.counts[i]
12879 / (float)ts.counts
12880 [BGP_STATS_PREFIXES]
12881 : 0);
893cccd0 12882 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12883 table_stats_strs[i]
12884 [TABLE_STATS_IDX_VTY],
893cccd0 12885 temp_buf);
9ab0cf58
PG
12886 } else {
12887 json_object_double_add(
12888 json,
12889 table_stats_strs[i]
12890 [TABLE_STATS_IDX_JSON],
12891 ts.counts[i]
12892 ? (double)ts.counts[i]
12893 / (double)ts.counts
d62a17ae 12894 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12895 : 0);
12896 }
d62a17ae 12897 break;
12898 case BGP_STATS_SPACE:
6c9d22e2
PG
12899 if (!json) {
12900 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12901 ts.total_space);
893cccd0 12902 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12903 table_stats_strs[i]
12904 [TABLE_STATS_IDX_VTY],
893cccd0 12905 temp_buf);
9ab0cf58
PG
12906 } else {
12907 json_object_double_add(
12908 json,
12909 table_stats_strs[i]
12910 [TABLE_STATS_IDX_JSON],
12911 (double)ts.total_space);
12912 }
8d0ab76d 12913 if (afi == AFI_IP6) {
6c9d22e2
PG
12914 if (!json) {
12915 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12916 "%12g",
12917 ts.total_space
12918 * pow(2.0, -128 + 32));
6c9d22e2
PG
12919 vty_out(vty, "%30s: %s\n",
12920 "/32 equivalent %s\n",
12921 temp_buf);
9ab0cf58
PG
12922 } else {
12923 json_object_double_add(
12924 json, "/32equivalent",
12925 (double)(ts.total_space
12926 * pow(2.0,
12927 -128 + 32)));
12928 }
6c9d22e2
PG
12929 if (!json) {
12930 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12931 "%12g",
12932 ts.total_space
12933 * pow(2.0, -128 + 48));
6c9d22e2
PG
12934 vty_out(vty, "%30s: %s\n",
12935 "/48 equivalent %s\n",
12936 temp_buf);
9ab0cf58
PG
12937 } else {
12938 json_object_double_add(
12939 json, "/48equivalent",
12940 (double)(ts.total_space
12941 * pow(2.0,
12942 -128 + 48)));
12943 }
8d0ab76d 12944 } else {
6c9d22e2
PG
12945 if (!json) {
12946 snprintf(temp_buf, sizeof(temp_buf),
12947 "%12.2f",
9ab0cf58
PG
12948 ts.total_space * 100.
12949 * pow(2.0, -32));
6c9d22e2 12950 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12951 "% announced ", temp_buf);
12952 } else {
12953 json_object_double_add(
12954 json, "%announced",
12955 (double)(ts.total_space * 100.
12956 * pow(2.0, -32)));
12957 }
6c9d22e2
PG
12958 if (!json) {
12959 snprintf(temp_buf, sizeof(temp_buf),
12960 "%12.2f",
9ab0cf58
PG
12961 ts.total_space
12962 * pow(2.0, -32 + 8));
6c9d22e2
PG
12963 vty_out(vty, "%30s: %s\n",
12964 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12965 } else {
12966 json_object_double_add(
12967 json, "/8equivalent",
12968 (double)(ts.total_space
12969 * pow(2.0, -32 + 8)));
12970 }
6c9d22e2
PG
12971 if (!json) {
12972 snprintf(temp_buf, sizeof(temp_buf),
12973 "%12.2f",
9ab0cf58
PG
12974 ts.total_space
12975 * pow(2.0, -32 + 24));
6c9d22e2 12976 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12977 "/24 equivalent ", temp_buf);
12978 } else {
12979 json_object_double_add(
12980 json, "/24equivalent",
12981 (double)(ts.total_space
12982 * pow(2.0, -32 + 24)));
12983 }
8d0ab76d 12984 }
d62a17ae 12985 break;
12986 default:
6c9d22e2
PG
12987 if (!json) {
12988 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12989 ts.counts[i]);
893cccd0 12990 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12991 table_stats_strs[i]
12992 [TABLE_STATS_IDX_VTY],
12993 temp_buf);
12994 } else {
12995 json_object_int_add(
12996 json,
12997 table_stats_strs[i]
12998 [TABLE_STATS_IDX_JSON],
12999 ts.counts[i]);
13000 }
d62a17ae 13001 }
893cccd0
PG
13002 if (!json)
13003 vty_out(vty, "\n");
d62a17ae 13004 }
9ab0cf58 13005end_table_stats:
6c9d22e2
PG
13006 if (json)
13007 json_object_array_add(json_array, json);
893cccd0 13008 return ret;
d62a17ae 13009}
13010
71f1613a
DA
13011static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13012 safi_t safi, struct json_object *json_array)
13013{
13014 if (!bgp) {
13015 bgp_table_stats_all(vty, afi, safi, json_array);
13016 return CMD_SUCCESS;
13017 }
13018
13019 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13020}
13021
d62a17ae 13022enum bgp_pcounts {
13023 PCOUNT_ADJ_IN = 0,
13024 PCOUNT_DAMPED,
13025 PCOUNT_REMOVED,
13026 PCOUNT_HISTORY,
13027 PCOUNT_STALE,
13028 PCOUNT_VALID,
13029 PCOUNT_ALL,
13030 PCOUNT_COUNTED,
7e3d9632 13031 PCOUNT_BPATH_SELECTED,
d62a17ae 13032 PCOUNT_PFCNT, /* the figure we display to users */
13033 PCOUNT_MAX,
a636c635 13034};
718e3744 13035
2b64873d 13036static const char *const pcount_strs[] = {
9d303b37
DL
13037 [PCOUNT_ADJ_IN] = "Adj-in",
13038 [PCOUNT_DAMPED] = "Damped",
13039 [PCOUNT_REMOVED] = "Removed",
13040 [PCOUNT_HISTORY] = "History",
13041 [PCOUNT_STALE] = "Stale",
13042 [PCOUNT_VALID] = "Valid",
13043 [PCOUNT_ALL] = "All RIB",
13044 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13045 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13046 [PCOUNT_PFCNT] = "Useable",
13047 [PCOUNT_MAX] = NULL,
a636c635 13048};
718e3744 13049
d62a17ae 13050struct peer_pcounts {
13051 unsigned int count[PCOUNT_MAX];
13052 const struct peer *peer;
13053 const struct bgp_table *table;
54317cba 13054 safi_t safi;
a636c635 13055};
47fc97cc 13056
9bcb3eef 13057static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13058{
54317cba
JW
13059 const struct bgp_adj_in *ain;
13060 const struct bgp_path_info *pi;
d62a17ae 13061 const struct peer *peer = pc->peer;
13062
54317cba
JW
13063 for (ain = rn->adj_in; ain; ain = ain->next)
13064 if (ain->peer == peer)
13065 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13066
9bcb3eef 13067 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13068
54317cba
JW
13069 if (pi->peer != peer)
13070 continue;
d62a17ae 13071
54317cba 13072 pc->count[PCOUNT_ALL]++;
d62a17ae 13073
54317cba
JW
13074 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13075 pc->count[PCOUNT_DAMPED]++;
13076 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13077 pc->count[PCOUNT_HISTORY]++;
13078 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13079 pc->count[PCOUNT_REMOVED]++;
13080 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13081 pc->count[PCOUNT_STALE]++;
13082 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13083 pc->count[PCOUNT_VALID]++;
13084 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13085 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13086 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13087 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13088
13089 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13090 pc->count[PCOUNT_COUNTED]++;
13091 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13092 flog_err(
13093 EC_LIB_DEVELOPMENT,
13094 "Attempting to count but flags say it is unusable");
13095 } else {
40381db7 13096 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13097 flog_err(
13098 EC_LIB_DEVELOPMENT,
13099 "Not counted but flags say we should");
d62a17ae 13100 }
13101 }
54317cba
JW
13102}
13103
13104static int bgp_peer_count_walker(struct thread *t)
13105{
9bcb3eef 13106 struct bgp_dest *rn, *rm;
54317cba
JW
13107 const struct bgp_table *table;
13108 struct peer_pcounts *pc = THREAD_ARG(t);
13109
13110 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13111 || pc->safi == SAFI_EVPN) {
13112 /* Special handling for 2-level routing tables. */
13113 for (rn = bgp_table_top(pc->table); rn;
13114 rn = bgp_route_next(rn)) {
9bcb3eef 13115 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13116 if (table != NULL)
13117 for (rm = bgp_table_top(table); rm;
13118 rm = bgp_route_next(rm))
13119 bgp_peer_count_proc(rm, pc);
13120 }
13121 } else
13122 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13123 bgp_peer_count_proc(rn, pc);
13124
d62a17ae 13125 return 0;
718e3744 13126}
13127
d62a17ae 13128static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13129 safi_t safi, bool use_json)
856ca177 13130{
d62a17ae 13131 struct peer_pcounts pcounts = {.peer = peer};
13132 unsigned int i;
13133 json_object *json = NULL;
13134 json_object *json_loop = NULL;
856ca177 13135
d62a17ae 13136 if (use_json) {
13137 json = json_object_new_object();
13138 json_loop = json_object_new_object();
13139 }
718e3744 13140
d62a17ae 13141 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13142 || !peer->bgp->rib[afi][safi]) {
13143 if (use_json) {
13144 json_object_string_add(
13145 json, "warning",
13146 "No such neighbor or address family");
13147 vty_out(vty, "%s\n", json_object_to_json_string(json));
13148 json_object_free(json);
d5f20468 13149 json_object_free(json_loop);
d62a17ae 13150 } else
13151 vty_out(vty, "%% No such neighbor or address family\n");
13152
13153 return CMD_WARNING;
13154 }
2a71e9ce 13155
d62a17ae 13156 memset(&pcounts, 0, sizeof(pcounts));
13157 pcounts.peer = peer;
13158 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13159 pcounts.safi = safi;
d62a17ae 13160
13161 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13162 * stats for the thread-walk (i.e. ensure this can't be blamed on
13163 * on just vty_read()).
13164 */
d62a17ae 13165 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13166
13167 if (use_json) {
13168 json_object_string_add(json, "prefixCountsFor", peer->host);
13169 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13170 get_afi_safi_str(afi, safi, true));
d62a17ae 13171 json_object_int_add(json, "pfxCounter",
13172 peer->pcount[afi][safi]);
13173
13174 for (i = 0; i < PCOUNT_MAX; i++)
13175 json_object_int_add(json_loop, pcount_strs[i],
13176 pcounts.count[i]);
13177
13178 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13179
13180 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13181 json_object_string_add(json, "pfxctDriftFor",
13182 peer->host);
13183 json_object_string_add(
13184 json, "recommended",
13185 "Please report this bug, with the above command output");
13186 }
996c9314
LB
13187 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13188 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13189 json_object_free(json);
13190 } else {
13191
13192 if (peer->hostname
892fedb6 13193 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13194 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13195 peer->hostname, peer->host,
5cb5f4d0 13196 get_afi_safi_str(afi, safi, false));
d62a17ae 13197 } else {
13198 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13199 get_afi_safi_str(afi, safi, false));
d62a17ae 13200 }
13201
6cde4b45 13202 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13203 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13204
13205 for (i = 0; i < PCOUNT_MAX; i++)
13206 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13207 pcounts.count[i]);
13208
13209 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13210 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13211 vty_out(vty,
13212 "Please report this bug, with the above command output\n");
13213 }
13214 }
13215
13216 return CMD_SUCCESS;
718e3744 13217}
13218
a636c635
DW
13219DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13220 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13221 "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 13222 SHOW_STR
13223 IP_STR
13224 BGP_STR
8386ac43 13225 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13226 BGP_AFI_HELP_STR
13227 BGP_SAFI_HELP_STR
0b16f239
DS
13228 "Detailed information on TCP and BGP neighbor connections\n"
13229 "Neighbor to display information about\n"
13230 "Neighbor to display information about\n"
91d37724 13231 "Neighbor on BGP configured interface\n"
a636c635 13232 "Display detailed prefix count information\n"
9973d184 13233 JSON_STR)
0b16f239 13234{
d62a17ae 13235 afi_t afi = AFI_IP6;
13236 safi_t safi = SAFI_UNICAST;
13237 struct peer *peer;
13238 int idx = 0;
13239 struct bgp *bgp = NULL;
9f049418
DS
13240 bool uj = use_json(argc, argv);
13241
13242 if (uj)
13243 argc--;
856ca177 13244
d62a17ae 13245 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13246 &bgp, uj);
d62a17ae 13247 if (!idx)
13248 return CMD_WARNING;
0b16f239 13249
d62a17ae 13250 argv_find(argv, argc, "neighbors", &idx);
13251 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13252 if (!peer)
13253 return CMD_WARNING;
bb46e94f 13254
29c8d9da 13255 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13256}
0b16f239 13257
d6902373
PG
13258#ifdef KEEP_OLD_VPN_COMMANDS
13259DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13260 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13261 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13262 SHOW_STR
13263 IP_STR
13264 BGP_STR
d6902373 13265 BGP_VPNVX_HELP_STR
91d37724 13266 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13267 "Detailed information on TCP and BGP neighbor connections\n"
13268 "Neighbor to display information about\n"
13269 "Neighbor to display information about\n"
91d37724 13270 "Neighbor on BGP configured interface\n"
a636c635 13271 "Display detailed prefix count information\n"
9973d184 13272 JSON_STR)
a636c635 13273{
d62a17ae 13274 int idx_peer = 6;
13275 struct peer *peer;
9f049418 13276 bool uj = use_json(argc, argv);
a636c635 13277
d62a17ae 13278 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13279 if (!peer)
13280 return CMD_WARNING;
13281
13282 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13283}
13284
d6902373
PG
13285DEFUN (show_ip_bgp_vpn_all_route_prefix,
13286 show_ip_bgp_vpn_all_route_prefix_cmd,
13287 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13288 SHOW_STR
13289 IP_STR
13290 BGP_STR
d6902373 13291 BGP_VPNVX_HELP_STR
91d37724
QY
13292 "Display information about all VPNv4 NLRIs\n"
13293 "Network in the BGP routing table to display\n"
3a2d747c 13294 "Network in the BGP routing table to display\n"
9973d184 13295 JSON_STR)
91d37724 13296{
d62a17ae 13297 int idx = 0;
13298 char *network = NULL;
13299 struct bgp *bgp = bgp_get_default();
13300 if (!bgp) {
13301 vty_out(vty, "Can't find default instance\n");
13302 return CMD_WARNING;
13303 }
87e34b58 13304
d62a17ae 13305 if (argv_find(argv, argc, "A.B.C.D", &idx))
13306 network = argv[idx]->arg;
13307 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13308 network = argv[idx]->arg;
13309 else {
13310 vty_out(vty, "Unable to figure out Network\n");
13311 return CMD_WARNING;
13312 }
87e34b58 13313
d62a17ae 13314 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13315 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13316 use_json(argc, argv));
91d37724 13317}
d6902373 13318#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13319
44c69747
LK
13320DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13321 show_bgp_l2vpn_evpn_route_prefix_cmd,
13322 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13323 SHOW_STR
4c63a661
PG
13324 BGP_STR
13325 L2VPN_HELP_STR
13326 EVPN_HELP_STR
44c69747
LK
13327 "Network in the BGP routing table to display\n"
13328 "Network in the BGP routing table to display\n"
4c63a661
PG
13329 "Network in the BGP routing table to display\n"
13330 "Network in the BGP routing table to display\n"
13331 JSON_STR)
13332{
d62a17ae 13333 int idx = 0;
13334 char *network = NULL;
44c69747 13335 int prefix_check = 0;
a636c635 13336
44c69747
LK
13337 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13338 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13339 network = argv[idx]->arg;
44c69747 13340 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13341 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13342 network = argv[idx]->arg;
44c69747
LK
13343 prefix_check = 1;
13344 } else {
d62a17ae 13345 vty_out(vty, "Unable to figure out Network\n");
13346 return CMD_WARNING;
13347 }
44c69747
LK
13348 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13349 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13350 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13351}
13352
2f9bc755
DS
13353static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13354 struct bgp_table *table, int *header1,
13355 int *header2, json_object *json,
13356 json_object *json_scode,
13357 json_object *json_ocode, bool wide)
13358{
13359 uint64_t version = table ? table->version : 0;
23d0a753 13360 char buf[BUFSIZ] = {0};
2f9bc755
DS
13361
13362 if (*header1) {
13363 if (json) {
13364 json_object_int_add(json, "bgpTableVersion", version);
13365 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13366 inet_ntop(AF_INET,
13367 &bgp->router_id, buf,
13368 sizeof(buf)));
2f9bc755
DS
13369 json_object_int_add(json, "defaultLocPrf",
13370 bgp->default_local_pref);
13371 json_object_int_add(json, "localAS", bgp->as);
13372 json_object_object_add(json, "bgpStatusCodes",
13373 json_scode);
13374 json_object_object_add(json, "bgpOriginCodes",
13375 json_ocode);
13376 } else {
13377 vty_out(vty,
23d0a753
DA
13378 "BGP table version is %" PRIu64
13379 ", local router ID is %pI4, vrf id ",
13380 version, &bgp->router_id);
2f9bc755
DS
13381 if (bgp->vrf_id == VRF_UNKNOWN)
13382 vty_out(vty, "%s", VRFID_NONE_STR);
13383 else
13384 vty_out(vty, "%u", bgp->vrf_id);
13385 vty_out(vty, "\n");
13386 vty_out(vty, "Default local pref %u, ",
13387 bgp->default_local_pref);
13388 vty_out(vty, "local AS %u\n", bgp->as);
13389 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13390 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13391 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13392 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13393 }
13394 *header1 = 0;
13395 }
13396 if (*header2) {
13397 if (!json)
13398 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13399 : BGP_SHOW_HEADER));
13400 *header2 = 0;
13401 }
13402}
13403
d9478df0
TA
13404static void
13405show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13406 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13407 const char *rmap_name, json_object *json, json_object *json_ar,
13408 json_object *json_scode, json_object *json_ocode,
96c81f66 13409 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13410 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13411{
d62a17ae 13412 struct bgp_adj_in *ain;
13413 struct bgp_adj_out *adj;
9bcb3eef 13414 struct bgp_dest *dest;
d62a17ae 13415 struct bgp *bgp;
d62a17ae 13416 struct attr attr;
13417 int ret;
13418 struct update_subgroup *subgrp;
d62a17ae 13419 struct peer_af *paf;
f99def61 13420 bool route_filtered;
96f3485c
MK
13421 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13422 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13423 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13424 || (safi == SAFI_EVPN))
13425 ? true
13426 : false;
a636c635 13427
d62a17ae 13428 bgp = peer->bgp;
a636c635 13429
d62a17ae 13430 if (!bgp) {
13431 if (use_json) {
13432 json_object_string_add(json, "alert", "no BGP");
13433 vty_out(vty, "%s\n", json_object_to_json_string(json));
13434 json_object_free(json);
13435 } else
13436 vty_out(vty, "%% No bgp\n");
13437 return;
13438 }
a636c635 13439
d62a17ae 13440 subgrp = peer_subgroup(peer, afi, safi);
13441
6392aaa6 13442 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13443 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13444 char buf[BUFSIZ] = {0};
13445
d62a17ae 13446 if (use_json) {
13447 json_object_int_add(json, "bgpTableVersion",
13448 table->version);
13449 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13450 inet_ntop(AF_INET,
13451 &bgp->router_id, buf,
13452 sizeof(buf)));
01eced22
AD
13453 json_object_int_add(json, "defaultLocPrf",
13454 bgp->default_local_pref);
13455 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13456 json_object_object_add(json, "bgpStatusCodes",
13457 json_scode);
13458 json_object_object_add(json, "bgpOriginCodes",
13459 json_ocode);
07d0c4ed
DA
13460 json_object_string_add(
13461 json, "bgpOriginatingDefaultNetwork",
13462 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13463 } else {
23d0a753
DA
13464 vty_out(vty,
13465 "BGP table version is %" PRIu64
13466 ", local router ID is %pI4, vrf id ",
13467 table->version, &bgp->router_id);
9df8b37c
PZ
13468 if (bgp->vrf_id == VRF_UNKNOWN)
13469 vty_out(vty, "%s", VRFID_NONE_STR);
13470 else
13471 vty_out(vty, "%u", bgp->vrf_id);
13472 vty_out(vty, "\n");
01eced22
AD
13473 vty_out(vty, "Default local pref %u, ",
13474 bgp->default_local_pref);
13475 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13476 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13477 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13478 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13479 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13480
07d0c4ed
DA
13481 vty_out(vty, "Originating default network %s\n\n",
13482 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13483 }
d9478df0 13484 *header1 = 0;
d62a17ae 13485 }
a636c635 13486
9bcb3eef 13487 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13488 if (type == bgp_show_adj_route_received
13489 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13490 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13491 if (ain->peer != peer)
ea47320b 13492 continue;
6392aaa6 13493
d9478df0
TA
13494 show_adj_route_header(vty, bgp, table, header1,
13495 header2, json, json_scode,
13496 json_ocode, wide);
13497
13498 if ((safi == SAFI_MPLS_VPN)
13499 || (safi == SAFI_ENCAP)
13500 || (safi == SAFI_EVPN)) {
13501 if (use_json)
13502 json_object_string_add(
13503 json_ar, "rd", rd_str);
13504 else if (show_rd && rd_str) {
13505 vty_out(vty,
13506 "Route Distinguisher: %s\n",
13507 rd_str);
13508 show_rd = false;
13509 }
13510 }
6392aaa6 13511
6f4f49b2 13512 attr = *ain->attr;
f99def61
AD
13513 route_filtered = false;
13514
13515 /* Filter prefix using distribute list,
13516 * filter list or prefix list
13517 */
b54892e0 13518 const struct prefix *rn_p =
9bcb3eef 13519 bgp_dest_get_prefix(dest);
b54892e0
DS
13520 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13521 safi))
13522 == FILTER_DENY)
f99def61
AD
13523 route_filtered = true;
13524
13525 /* Filter prefix using route-map */
b54892e0
DS
13526 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13527 safi, rmap_name, NULL,
13528 0, NULL);
6392aaa6 13529
13c8e163
AD
13530 if (type == bgp_show_adj_route_filtered &&
13531 !route_filtered && ret != RMAP_DENY) {
b755861b 13532 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13533 continue;
d62a17ae 13534 }
6392aaa6 13535
d9478df0
TA
13536 if (type == bgp_show_adj_route_received
13537 && (route_filtered || ret == RMAP_DENY))
13538 (*filtered_count)++;
6392aaa6 13539
7d3cae70 13540 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13541 use_json, json_ar, wide);
b755861b 13542 bgp_attr_undup(&attr, ain->attr);
d9478df0 13543 (*output_count)++;
d62a17ae 13544 }
6392aaa6 13545 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13546 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13547 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13548 if (paf->peer != peer || !adj->attr)
924c3f6a 13549 continue;
d62a17ae 13550
d9478df0
TA
13551 show_adj_route_header(vty, bgp, table,
13552 header1, header2,
13553 json, json_scode,
13554 json_ocode, wide);
d62a17ae 13555
b54892e0 13556 const struct prefix *rn_p =
9bcb3eef 13557 bgp_dest_get_prefix(dest);
b54892e0 13558
6f4f49b2 13559 attr = *adj->attr;
b755861b 13560 ret = bgp_output_modifier(
b54892e0 13561 peer, rn_p, &attr, afi, safi,
b755861b 13562 rmap_name);
f46d8e1e 13563
b755861b 13564 if (ret != RMAP_DENY) {
d9478df0
TA
13565 if ((safi == SAFI_MPLS_VPN)
13566 || (safi == SAFI_ENCAP)
13567 || (safi == SAFI_EVPN)) {
13568 if (use_json)
13569 json_object_string_add(
13570 json_ar,
13571 "rd",
13572 rd_str);
13573 else if (show_rd
13574 && rd_str) {
13575 vty_out(vty,
13576 "Route Distinguisher: %s\n",
13577 rd_str);
13578 show_rd = false;
13579 }
13580 }
b54892e0 13581 route_vty_out_tmp(
7d3cae70
DA
13582 vty, dest, rn_p, &attr,
13583 safi, use_json, json_ar,
ae248832 13584 wide);
d9478df0 13585 (*output_count)++;
b755861b 13586 } else {
d9478df0 13587 (*filtered_count)++;
a2addae8 13588 }
b755861b
PM
13589
13590 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13591 }
f20ce998
DS
13592 } else if (type == bgp_show_adj_route_bestpath) {
13593 struct bgp_path_info *pi;
13594
d9478df0
TA
13595 show_adj_route_header(vty, bgp, table, header1, header2,
13596 json, json_scode, json_ocode,
13597 wide);
f20ce998
DS
13598
13599 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13600 pi = pi->next) {
13601 if (pi->peer != peer)
13602 continue;
13603
13604 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13605 continue;
13606
7d3cae70 13607 route_vty_out_tmp(vty, dest,
f20ce998
DS
13608 bgp_dest_get_prefix(dest),
13609 pi->attr, safi, use_json,
13610 json_ar, wide);
d9478df0 13611 (*output_count)++;
f20ce998 13612 }
d62a17ae 13613 }
13614 }
a636c635 13615}
2a71e9ce 13616
d62a17ae 13617static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13618 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13619 const char *rmap_name, uint16_t show_flags)
0b16f239 13620{
d9478df0
TA
13621 struct bgp *bgp;
13622 struct bgp_table *table;
d62a17ae 13623 json_object *json = NULL;
d9478df0
TA
13624 json_object *json_scode = NULL;
13625 json_object *json_ocode = NULL;
13626 json_object *json_ar = NULL;
96f3485c 13627 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13628
d9478df0
TA
13629 /* Init BGP headers here so they're only displayed once
13630 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13631 */
13632 int header1 = 1;
13633 int header2 = 1;
13634
13635 /*
13636 * Initialize variables for each RD
13637 * All prefixes under an RD is aggregated within "json_routes"
13638 */
13639 char rd_str[BUFSIZ] = {0};
13640 json_object *json_routes = NULL;
13641
13642
13643 /* For 2-tier tables, prefix counts need to be
13644 * maintained across multiple runs of show_adj_route()
13645 */
13646 unsigned long output_count_per_rd;
13647 unsigned long filtered_count_per_rd;
13648 unsigned long output_count = 0;
13649 unsigned long filtered_count = 0;
13650
13651 if (use_json) {
d62a17ae 13652 json = json_object_new_object();
d9478df0
TA
13653 json_ar = json_object_new_object();
13654 json_scode = json_object_new_object();
13655 json_ocode = json_object_new_object();
13656
13657 json_object_string_add(json_scode, "suppressed", "s");
13658 json_object_string_add(json_scode, "damped", "d");
13659 json_object_string_add(json_scode, "history", "h");
13660 json_object_string_add(json_scode, "valid", "*");
13661 json_object_string_add(json_scode, "best", ">");
13662 json_object_string_add(json_scode, "multipath", "=");
13663 json_object_string_add(json_scode, "internal", "i");
13664 json_object_string_add(json_scode, "ribFailure", "r");
13665 json_object_string_add(json_scode, "stale", "S");
13666 json_object_string_add(json_scode, "removed", "R");
13667
13668 json_object_string_add(json_ocode, "igp", "i");
13669 json_object_string_add(json_ocode, "egp", "e");
13670 json_object_string_add(json_ocode, "incomplete", "?");
13671 }
0b16f239 13672
d62a17ae 13673 if (!peer || !peer->afc[afi][safi]) {
13674 if (use_json) {
13675 json_object_string_add(
13676 json, "warning",
13677 "No such neighbor or address family");
13678 vty_out(vty, "%s\n", json_object_to_json_string(json));
13679 json_object_free(json);
13680 } else
13681 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13682
d62a17ae 13683 return CMD_WARNING;
13684 }
13685
6392aaa6
PM
13686 if ((type == bgp_show_adj_route_received
13687 || type == bgp_show_adj_route_filtered)
d62a17ae 13688 && !CHECK_FLAG(peer->af_flags[afi][safi],
13689 PEER_FLAG_SOFT_RECONFIG)) {
13690 if (use_json) {
13691 json_object_string_add(
13692 json, "warning",
13693 "Inbound soft reconfiguration not enabled");
13694 vty_out(vty, "%s\n", json_object_to_json_string(json));
13695 json_object_free(json);
13696 } else
13697 vty_out(vty,
13698 "%% Inbound soft reconfiguration not enabled\n");
13699
13700 return CMD_WARNING;
13701 }
0b16f239 13702
d9478df0
TA
13703 bgp = peer->bgp;
13704
13705 /* labeled-unicast routes live in the unicast table */
13706 if (safi == SAFI_LABELED_UNICAST)
13707 table = bgp->rib[afi][SAFI_UNICAST];
13708 else
13709 table = bgp->rib[afi][safi];
13710
13711 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13712 || (safi == SAFI_EVPN)) {
13713
13714 struct bgp_dest *dest;
13715
13716 for (dest = bgp_table_top(table); dest;
13717 dest = bgp_route_next(dest)) {
13718 table = bgp_dest_get_bgp_table_info(dest);
13719 if (!table)
13720 continue;
13721
13722 output_count_per_rd = 0;
13723 filtered_count_per_rd = 0;
13724
13725 if (use_json)
13726 json_routes = json_object_new_object();
13727
13728 const struct prefix_rd *prd;
13729 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13730 dest);
13731
13732 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13733
13734 show_adj_route(vty, peer, table, afi, safi, type,
13735 rmap_name, json, json_routes, json_scode,
13736 json_ocode, show_flags, &header1,
13737 &header2, rd_str, &output_count_per_rd,
13738 &filtered_count_per_rd);
13739
13740 /* Don't include an empty RD in the output! */
13741 if (json_routes && (output_count_per_rd > 0))
13742 json_object_object_add(json_ar, rd_str,
13743 json_routes);
13744
13745 output_count += output_count_per_rd;
13746 filtered_count += filtered_count_per_rd;
13747 }
13748 } else
13749 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13750 json, json_ar, json_scode, json_ocode,
13751 show_flags, &header1, &header2, rd_str,
13752 &output_count, &filtered_count);
13753
13754 if (use_json) {
13755 json_object_object_add(json, "advertisedRoutes", json_ar);
13756 json_object_int_add(json, "totalPrefixCounter", output_count);
13757 json_object_int_add(json, "filteredPrefixCounter",
13758 filtered_count);
13759
13760 vty_out(vty, "%s\n",
13761 json_object_to_json_string_ext(
13762 json, JSON_C_TO_STRING_PRETTY));
13763
13764 if (!output_count && !filtered_count) {
13765 json_object_free(json_scode);
13766 json_object_free(json_ocode);
13767 }
13768
13769 if (json)
13770 json_object_free(json);
13771
13772 } else if (output_count > 0) {
13773 if (filtered_count > 0)
13774 vty_out(vty,
13775 "\nTotal number of prefixes %ld (%ld filtered)\n",
13776 output_count, filtered_count);
13777 else
13778 vty_out(vty, "\nTotal number of prefixes %ld\n",
13779 output_count);
13780 }
0b16f239 13781
d62a17ae 13782 return CMD_SUCCESS;
a636c635 13783}
50ef26d4 13784
f20ce998
DS
13785DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13786 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13787 "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]",
13788 SHOW_STR
13789 IP_STR
13790 BGP_STR
13791 BGP_INSTANCE_HELP_STR
13792 BGP_AFI_HELP_STR
13793 BGP_SAFI_WITH_LABEL_HELP_STR
13794 "Detailed information on TCP and BGP neighbor connections\n"
13795 "Neighbor to display information about\n"
13796 "Neighbor to display information about\n"
13797 "Neighbor on BGP configured interface\n"
13798 "Display the routes selected by best path\n"
13799 JSON_STR
13800 "Increase table width for longer prefixes\n")
13801{
13802 afi_t afi = AFI_IP6;
13803 safi_t safi = SAFI_UNICAST;
13804 char *rmap_name = NULL;
13805 char *peerstr = NULL;
13806 struct bgp *bgp = NULL;
13807 struct peer *peer;
13808 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13809 int idx = 0;
96c81f66 13810 uint16_t show_flags = 0;
96f3485c
MK
13811
13812 if (uj)
13813 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13814
13815 if (wide)
13816 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13817
13818 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13819 &bgp, uj);
13820
13821 if (!idx)
13822 return CMD_WARNING;
13823
13824 argv_find(argv, argc, "neighbors", &idx);
13825 peerstr = argv[++idx]->arg;
13826
13827 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13828 if (!peer)
13829 return CMD_WARNING;
13830
96f3485c
MK
13831 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13832 show_flags);
f20ce998
DS
13833}
13834
ae248832 13835DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13836 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13837 "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 13838 SHOW_STR
13839 IP_STR
13840 BGP_STR
a636c635 13841 BGP_INSTANCE_HELP_STR
7395a2c9 13842 BGP_AFI_HELP_STR
4dd6177e 13843 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13844 "Display the entries for all address families\n"
718e3744 13845 "Detailed information on TCP and BGP neighbor connections\n"
13846 "Neighbor to display information about\n"
13847 "Neighbor to display information about\n"
91d37724 13848 "Neighbor on BGP configured interface\n"
a636c635 13849 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13850 "Display the received routes from neighbor\n"
13851 "Display the filtered routes received from neighbor\n"
a636c635
DW
13852 "Route-map to modify the attributes\n"
13853 "Name of the route map\n"
ae248832
MK
13854 JSON_STR
13855 "Increase table width for longer prefixes\n")
718e3744 13856{
d62a17ae 13857 afi_t afi = AFI_IP6;
13858 safi_t safi = SAFI_UNICAST;
13859 char *rmap_name = NULL;
13860 char *peerstr = NULL;
d62a17ae 13861 struct bgp *bgp = NULL;
13862 struct peer *peer;
6392aaa6 13863 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13864 int idx = 0;
96f3485c 13865 bool first = true;
96c81f66 13866 uint16_t show_flags = 0;
6392aaa6 13867
96f3485c 13868 if (uj) {
d62a17ae 13869 argc--;
96f3485c
MK
13870 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13871 }
13872
13873 if (all) {
13874 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13875 if (argv_find(argv, argc, "ipv4", &idx))
13876 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13877
13878 if (argv_find(argv, argc, "ipv6", &idx))
13879 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13880 }
13881
13882 if (wide)
13883 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13884
9f049418
DS
13885 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13886 &bgp, uj);
13887 if (!idx)
13888 return CMD_WARNING;
13889
d62a17ae 13890 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13891 argv_find(argv, argc, "neighbors", &idx);
13892 peerstr = argv[++idx]->arg;
8c3deaae 13893
d62a17ae 13894 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13895 if (!peer)
13896 return CMD_WARNING;
856ca177 13897
d62a17ae 13898 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13899 type = bgp_show_adj_route_advertised;
13900 else if (argv_find(argv, argc, "received-routes", &idx))
13901 type = bgp_show_adj_route_received;
13902 else if (argv_find(argv, argc, "filtered-routes", &idx))
13903 type = bgp_show_adj_route_filtered;
13904
d62a17ae 13905 if (argv_find(argv, argc, "route-map", &idx))
13906 rmap_name = argv[++idx]->arg;
95cbbd2a 13907
96f3485c
MK
13908 if (!all)
13909 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13910 show_flags);
13911 if (uj)
13912 vty_out(vty, "{\n");
13913
13914 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13915 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13916 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13917 : AFI_IP6;
13918 FOREACH_SAFI (safi) {
96f3485c
MK
13919 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13920 continue;
13921
13922 if (uj) {
13923 if (first)
13924 first = false;
13925 else
13926 vty_out(vty, ",\n");
13927 vty_out(vty, "\"%s\":",
13928 get_afi_safi_str(afi, safi, true));
13929 } else
13930 vty_out(vty, "\nFor address family: %s\n",
13931 get_afi_safi_str(afi, safi, false));
13932
13933 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13934 show_flags);
13935 }
13936 } else {
13937 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13938 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13939 continue;
13940
13941 if (uj) {
13942 if (first)
13943 first = false;
13944 else
13945 vty_out(vty, ",\n");
13946 vty_out(vty, "\"%s\":",
13947 get_afi_safi_str(afi, safi, true));
13948 } else
13949 vty_out(vty, "\nFor address family: %s\n",
13950 get_afi_safi_str(afi, safi, false));
13951
13952 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13953 show_flags);
13954 }
13955 }
13956 if (uj)
13957 vty_out(vty, "}\n");
13958
13959 return CMD_SUCCESS;
95cbbd2a
ML
13960}
13961
718e3744 13962DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13963 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13964 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13965 SHOW_STR
13966 IP_STR
13967 BGP_STR
8c3deaae
QY
13968 "Address Family\n"
13969 "Address Family\n"
718e3744 13970 "Address Family modifier\n"
13971 "Detailed information on TCP and BGP neighbor connections\n"
13972 "Neighbor to display information about\n"
13973 "Neighbor to display information about\n"
91d37724 13974 "Neighbor on BGP configured interface\n"
718e3744 13975 "Display information received from a BGP neighbor\n"
856ca177 13976 "Display the prefixlist filter\n"
9973d184 13977 JSON_STR)
718e3744 13978{
d62a17ae 13979 afi_t afi = AFI_IP6;
13980 safi_t safi = SAFI_UNICAST;
13981 char *peerstr = NULL;
13982
13983 char name[BUFSIZ];
13984 union sockunion su;
13985 struct peer *peer;
13986 int count, ret;
13987
13988 int idx = 0;
13989
13990 /* show [ip] bgp */
13991 if (argv_find(argv, argc, "ip", &idx))
13992 afi = AFI_IP;
13993 /* [<ipv4|ipv6> [unicast]] */
13994 if (argv_find(argv, argc, "ipv4", &idx))
13995 afi = AFI_IP;
13996 if (argv_find(argv, argc, "ipv6", &idx))
13997 afi = AFI_IP6;
13998 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13999 argv_find(argv, argc, "neighbors", &idx);
14000 peerstr = argv[++idx]->arg;
14001
9f049418 14002 bool uj = use_json(argc, argv);
d62a17ae 14003
14004 ret = str2sockunion(peerstr, &su);
14005 if (ret < 0) {
14006 peer = peer_lookup_by_conf_if(NULL, peerstr);
14007 if (!peer) {
14008 if (uj)
14009 vty_out(vty, "{}\n");
14010 else
14011 vty_out(vty,
14012 "%% Malformed address or name: %s\n",
14013 peerstr);
14014 return CMD_WARNING;
14015 }
14016 } else {
14017 peer = peer_lookup(NULL, &su);
14018 if (!peer) {
14019 if (uj)
14020 vty_out(vty, "{}\n");
14021 else
14022 vty_out(vty, "No peer\n");
14023 return CMD_WARNING;
14024 }
14025 }
718e3744 14026
4ced1a2c 14027 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14028 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14029 if (count) {
14030 if (!uj)
14031 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14032 get_afi_safi_str(afi, safi, false));
d62a17ae 14033 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14034 } else {
14035 if (uj)
14036 vty_out(vty, "{}\n");
14037 else
14038 vty_out(vty, "No functional output\n");
14039 }
718e3744 14040
d62a17ae 14041 return CMD_SUCCESS;
14042}
14043
14044static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14045 afi_t afi, safi_t safi,
9f049418 14046 enum bgp_show_type type, bool use_json)
d62a17ae 14047{
96c81f66 14048 uint16_t show_flags = 0;
96f3485c
MK
14049
14050 if (use_json)
14051 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14052
d62a17ae 14053 if (!peer || !peer->afc[afi][safi]) {
14054 if (use_json) {
14055 json_object *json_no = NULL;
14056 json_no = json_object_new_object();
14057 json_object_string_add(
14058 json_no, "warning",
14059 "No such neighbor or address family");
14060 vty_out(vty, "%s\n",
14061 json_object_to_json_string(json_no));
14062 json_object_free(json_no);
14063 } else
14064 vty_out(vty, "%% No such neighbor or address family\n");
14065 return CMD_WARNING;
14066 }
47fc97cc 14067
7daf25a3
TA
14068 /* labeled-unicast routes live in the unicast table */
14069 if (safi == SAFI_LABELED_UNICAST)
14070 safi = SAFI_UNICAST;
14071
1e2ce4f1
DS
14072 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14073 RPKI_NOT_BEING_USED);
718e3744 14074}
14075
dba3c1d3
PG
14076DEFUN (show_ip_bgp_flowspec_routes_detailed,
14077 show_ip_bgp_flowspec_routes_detailed_cmd,
14078 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14079 SHOW_STR
14080 IP_STR
14081 BGP_STR
14082 BGP_INSTANCE_HELP_STR
14083 BGP_AFI_HELP_STR
14084 "SAFI Flowspec\n"
14085 "Detailed information on flowspec entries\n"
14086 JSON_STR)
14087{
14088 afi_t afi = AFI_IP;
14089 safi_t safi = SAFI_UNICAST;
14090 struct bgp *bgp = NULL;
14091 int idx = 0;
9f049418 14092 bool uj = use_json(argc, argv);
96c81f66 14093 uint16_t show_flags = 0;
9f049418 14094
96f3485c 14095 if (uj) {
9f049418 14096 argc--;
96f3485c
MK
14097 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14098 }
dba3c1d3
PG
14099
14100 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14101 &bgp, uj);
dba3c1d3
PG
14102 if (!idx)
14103 return CMD_WARNING;
14104
96f3485c 14105 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14106 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14107}
14108
718e3744 14109DEFUN (show_ip_bgp_neighbor_routes,
14110 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14111 "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 14112 SHOW_STR
14113 IP_STR
14114 BGP_STR
8386ac43 14115 BGP_INSTANCE_HELP_STR
4f280b15 14116 BGP_AFI_HELP_STR
4dd6177e 14117 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14118 "Detailed information on TCP and BGP neighbor connections\n"
14119 "Neighbor to display information about\n"
14120 "Neighbor to display information about\n"
91d37724 14121 "Neighbor on BGP configured interface\n"
2525cf39 14122 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14123 "Display the dampened routes received from neighbor\n"
14124 "Display routes learned from neighbor\n"
9973d184 14125 JSON_STR)
718e3744 14126{
d62a17ae 14127 char *peerstr = NULL;
14128 struct bgp *bgp = NULL;
14129 afi_t afi = AFI_IP6;
14130 safi_t safi = SAFI_UNICAST;
14131 struct peer *peer;
14132 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14133 int idx = 0;
9f049418
DS
14134 bool uj = use_json(argc, argv);
14135
14136 if (uj)
14137 argc--;
bb46e94f 14138
d62a17ae 14139 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14140 &bgp, uj);
d62a17ae 14141 if (!idx)
14142 return CMD_WARNING;
c493f2d8 14143
d62a17ae 14144 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14145 argv_find(argv, argc, "neighbors", &idx);
14146 peerstr = argv[++idx]->arg;
8c3deaae 14147
d62a17ae 14148 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14149 if (!peer)
d62a17ae 14150 return CMD_WARNING;
bb46e94f 14151
d62a17ae 14152 if (argv_find(argv, argc, "flap-statistics", &idx))
14153 sh_type = bgp_show_type_flap_neighbor;
14154 else if (argv_find(argv, argc, "dampened-routes", &idx))
14155 sh_type = bgp_show_type_damp_neighbor;
14156 else if (argv_find(argv, argc, "routes", &idx))
14157 sh_type = bgp_show_type_neighbor;
2525cf39 14158
d62a17ae 14159 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14160}
6b0655a2 14161
734b349e 14162struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14163
d62a17ae 14164struct bgp_distance {
14165 /* Distance value for the IP source prefix. */
d7c0a89a 14166 uint8_t distance;
718e3744 14167
d62a17ae 14168 /* Name of the access-list to be matched. */
14169 char *access_list;
718e3744 14170};
14171
4f280b15
LB
14172DEFUN (show_bgp_afi_vpn_rd_route,
14173 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14174 "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
14175 SHOW_STR
14176 BGP_STR
14177 BGP_AFI_HELP_STR
14178 "Address Family modifier\n"
14179 "Display information for a route distinguisher\n"
14180 "Route Distinguisher\n"
a111dd97 14181 "All Route Distinguishers\n"
7395a2c9
DS
14182 "Network in the BGP routing table to display\n"
14183 "Network in the BGP routing table to display\n"
14184 JSON_STR)
4f280b15 14185{
d62a17ae 14186 int ret;
14187 struct prefix_rd prd;
14188 afi_t afi = AFI_MAX;
14189 int idx = 0;
4f280b15 14190
ff6566f3
DS
14191 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14192 vty_out(vty, "%% Malformed Address Family\n");
14193 return CMD_WARNING;
14194 }
14195
a111dd97
TA
14196 if (!strcmp(argv[5]->arg, "all"))
14197 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14198 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14199 RPKI_NOT_BEING_USED,
14200 use_json(argc, argv));
14201
d62a17ae 14202 ret = str2prefix_rd(argv[5]->arg, &prd);
14203 if (!ret) {
14204 vty_out(vty, "%% Malformed Route Distinguisher\n");
14205 return CMD_WARNING;
14206 }
ff6566f3 14207
d62a17ae 14208 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14209 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14210 use_json(argc, argv));
4f280b15
LB
14211}
14212
d62a17ae 14213static struct bgp_distance *bgp_distance_new(void)
718e3744 14214{
d62a17ae 14215 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14216}
14217
d62a17ae 14218static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14219{
d62a17ae 14220 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14221}
14222
585f1adc
IR
14223static int bgp_distance_set(struct vty *vty, const char *distance_str,
14224 const char *ip_str, const char *access_list_str)
718e3744 14225{
d62a17ae 14226 int ret;
585f1adc
IR
14227 afi_t afi;
14228 safi_t safi;
d62a17ae 14229 struct prefix p;
585f1adc 14230 uint8_t distance;
9bcb3eef 14231 struct bgp_dest *dest;
d62a17ae 14232 struct bgp_distance *bdistance;
718e3744 14233
585f1adc
IR
14234 afi = bgp_node_afi(vty);
14235 safi = bgp_node_safi(vty);
14236
d62a17ae 14237 ret = str2prefix(ip_str, &p);
14238 if (ret == 0) {
585f1adc 14239 vty_out(vty, "Malformed prefix\n");
d62a17ae 14240 return CMD_WARNING_CONFIG_FAILED;
14241 }
718e3744 14242
585f1adc
IR
14243 distance = atoi(distance_str);
14244
d62a17ae 14245 /* Get BGP distance node. */
9bcb3eef
DS
14246 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14247 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14248 if (bdistance)
9bcb3eef 14249 bgp_dest_unlock_node(dest);
ca2e160d 14250 else {
d62a17ae 14251 bdistance = bgp_distance_new();
9bcb3eef 14252 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14253 }
718e3744 14254
d62a17ae 14255 /* Set distance value. */
14256 bdistance->distance = distance;
718e3744 14257
d62a17ae 14258 /* Reset access-list configuration. */
e1b36e13 14259 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14260 if (access_list_str)
14261 bdistance->access_list =
14262 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14263
d62a17ae 14264 return CMD_SUCCESS;
718e3744 14265}
14266
585f1adc
IR
14267static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14268 const char *ip_str, const char *access_list_str)
718e3744 14269{
d62a17ae 14270 int ret;
585f1adc
IR
14271 afi_t afi;
14272 safi_t safi;
d62a17ae 14273 struct prefix p;
585f1adc 14274 int distance;
9bcb3eef 14275 struct bgp_dest *dest;
d62a17ae 14276 struct bgp_distance *bdistance;
718e3744 14277
585f1adc
IR
14278 afi = bgp_node_afi(vty);
14279 safi = bgp_node_safi(vty);
14280
d62a17ae 14281 ret = str2prefix(ip_str, &p);
14282 if (ret == 0) {
585f1adc 14283 vty_out(vty, "Malformed prefix\n");
d62a17ae 14284 return CMD_WARNING_CONFIG_FAILED;
14285 }
718e3744 14286
9bcb3eef
DS
14287 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14288 if (!dest) {
585f1adc 14289 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14290 return CMD_WARNING_CONFIG_FAILED;
14291 }
718e3744 14292
9bcb3eef 14293 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14294 distance = atoi(distance_str);
1f9a9fff 14295
d62a17ae 14296 if (bdistance->distance != distance) {
585f1adc 14297 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14298 bgp_dest_unlock_node(dest);
d62a17ae 14299 return CMD_WARNING_CONFIG_FAILED;
14300 }
718e3744 14301
0a22ddfb 14302 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14303 bgp_distance_free(bdistance);
718e3744 14304
9bcb3eef
DS
14305 bgp_dest_set_bgp_path_info(dest, NULL);
14306 bgp_dest_unlock_node(dest);
14307 bgp_dest_unlock_node(dest);
718e3744 14308
d62a17ae 14309 return CMD_SUCCESS;
718e3744 14310}
14311
718e3744 14312/* Apply BGP information to distance method. */
b8685f9b 14313uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14314 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14315{
9bcb3eef 14316 struct bgp_dest *dest;
801bb996 14317 struct prefix q = {0};
d62a17ae 14318 struct peer *peer;
14319 struct bgp_distance *bdistance;
14320 struct access_list *alist;
14321 struct bgp_static *bgp_static;
14322
14323 if (!bgp)
14324 return 0;
14325
40381db7 14326 peer = pinfo->peer;
d62a17ae 14327
7b7d48e5
DS
14328 if (pinfo->attr->distance)
14329 return pinfo->attr->distance;
14330
801bb996
CS
14331 /* Check source address.
14332 * Note: for aggregate route, peer can have unspec af type.
14333 */
14334 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14335 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14336 return 0;
14337
9bcb3eef
DS
14338 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14339 if (dest) {
14340 bdistance = bgp_dest_get_bgp_distance_info(dest);
14341 bgp_dest_unlock_node(dest);
d62a17ae 14342
14343 if (bdistance->access_list) {
14344 alist = access_list_lookup(afi, bdistance->access_list);
14345 if (alist
14346 && access_list_apply(alist, p) == FILTER_PERMIT)
14347 return bdistance->distance;
14348 } else
14349 return bdistance->distance;
718e3744 14350 }
718e3744 14351
d62a17ae 14352 /* Backdoor check. */
9bcb3eef
DS
14353 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14354 if (dest) {
14355 bgp_static = bgp_dest_get_bgp_static_info(dest);
14356 bgp_dest_unlock_node(dest);
718e3744 14357
d62a17ae 14358 if (bgp_static->backdoor) {
14359 if (bgp->distance_local[afi][safi])
14360 return bgp->distance_local[afi][safi];
14361 else
14362 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14363 }
718e3744 14364 }
718e3744 14365
d62a17ae 14366 if (peer->sort == BGP_PEER_EBGP) {
14367 if (bgp->distance_ebgp[afi][safi])
14368 return bgp->distance_ebgp[afi][safi];
14369 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14370 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14371 if (bgp->distance_ibgp[afi][safi])
14372 return bgp->distance_ibgp[afi][safi];
14373 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14374 } else {
14375 if (bgp->distance_local[afi][safi])
14376 return bgp->distance_local[afi][safi];
14377 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14378 }
718e3744 14379}
14380
a612fb77
DA
14381/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14382 * we should tell ZEBRA update the routes for a specific
14383 * AFI/SAFI to reflect changes in RIB.
14384 */
585f1adc
IR
14385static void bgp_announce_routes_distance_update(struct bgp *bgp,
14386 afi_t update_afi,
14387 safi_t update_safi)
a612fb77
DA
14388{
14389 afi_t afi;
14390 safi_t safi;
14391
14392 FOREACH_AFI_SAFI (afi, safi) {
14393 if (!bgp_fibupd_safi(safi))
14394 continue;
14395
8b54bc30
DA
14396 if (afi != update_afi && safi != update_safi)
14397 continue;
14398
14399 if (BGP_DEBUG(zebra, ZEBRA))
14400 zlog_debug(
14401 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14402 __func__, afi, safi);
14403 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14404 }
14405}
14406
585f1adc
IR
14407DEFUN (bgp_distance,
14408 bgp_distance_cmd,
14409 "distance bgp (1-255) (1-255) (1-255)",
14410 "Define an administrative distance\n"
14411 "BGP distance\n"
14412 "Distance for routes external to the AS\n"
14413 "Distance for routes internal to the AS\n"
14414 "Distance for local routes\n")
718e3744 14415{
585f1adc 14416 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14417 int idx_number = 2;
14418 int idx_number_2 = 3;
14419 int idx_number_3 = 4;
585f1adc
IR
14420 int distance_ebgp = atoi(argv[idx_number]->arg);
14421 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14422 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14423 afi_t afi;
14424 safi_t safi;
718e3744 14425
d62a17ae 14426 afi = bgp_node_afi(vty);
14427 safi = bgp_node_safi(vty);
718e3744 14428
585f1adc
IR
14429 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14430 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14431 || bgp->distance_local[afi][safi] != distance_local) {
14432 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14433 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14434 bgp->distance_local[afi][safi] = distance_local;
14435 bgp_announce_routes_distance_update(bgp, afi, safi);
14436 }
14437 return CMD_SUCCESS;
14438}
37a87b8f 14439
585f1adc
IR
14440DEFUN (no_bgp_distance,
14441 no_bgp_distance_cmd,
14442 "no distance bgp [(1-255) (1-255) (1-255)]",
14443 NO_STR
14444 "Define an administrative distance\n"
14445 "BGP distance\n"
14446 "Distance for routes external to the AS\n"
14447 "Distance for routes internal to the AS\n"
14448 "Distance for local routes\n")
718e3744 14449{
585f1adc 14450 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14451 afi_t afi;
14452 safi_t safi;
37a87b8f
CS
14453
14454 afi = bgp_node_afi(vty);
14455 safi = bgp_node_safi(vty);
14456
585f1adc
IR
14457 if (bgp->distance_ebgp[afi][safi] != 0
14458 || bgp->distance_ibgp[afi][safi] != 0
14459 || bgp->distance_local[afi][safi] != 0) {
14460 bgp->distance_ebgp[afi][safi] = 0;
14461 bgp->distance_ibgp[afi][safi] = 0;
14462 bgp->distance_local[afi][safi] = 0;
14463 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14464 }
585f1adc
IR
14465 return CMD_SUCCESS;
14466}
37a87b8f 14467
37a87b8f 14468
585f1adc
IR
14469DEFUN (bgp_distance_source,
14470 bgp_distance_source_cmd,
14471 "distance (1-255) A.B.C.D/M",
14472 "Define an administrative distance\n"
14473 "Administrative distance\n"
14474 "IP source prefix\n")
14475{
14476 int idx_number = 1;
14477 int idx_ipv4_prefixlen = 2;
14478 bgp_distance_set(vty, argv[idx_number]->arg,
14479 argv[idx_ipv4_prefixlen]->arg, NULL);
14480 return CMD_SUCCESS;
734b349e
MZ
14481}
14482
585f1adc
IR
14483DEFUN (no_bgp_distance_source,
14484 no_bgp_distance_source_cmd,
14485 "no distance (1-255) A.B.C.D/M",
14486 NO_STR
14487 "Define an administrative distance\n"
14488 "Administrative distance\n"
14489 "IP source prefix\n")
37a87b8f 14490{
585f1adc
IR
14491 int idx_number = 2;
14492 int idx_ipv4_prefixlen = 3;
14493 bgp_distance_unset(vty, argv[idx_number]->arg,
14494 argv[idx_ipv4_prefixlen]->arg, NULL);
14495 return CMD_SUCCESS;
37a87b8f
CS
14496}
14497
585f1adc
IR
14498DEFUN (bgp_distance_source_access_list,
14499 bgp_distance_source_access_list_cmd,
14500 "distance (1-255) A.B.C.D/M WORD",
14501 "Define an administrative distance\n"
14502 "Administrative distance\n"
14503 "IP source prefix\n"
14504 "Access list name\n")
37a87b8f 14505{
585f1adc
IR
14506 int idx_number = 1;
14507 int idx_ipv4_prefixlen = 2;
14508 int idx_word = 3;
14509 bgp_distance_set(vty, argv[idx_number]->arg,
14510 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14511 return CMD_SUCCESS;
14512}
718e3744 14513
585f1adc
IR
14514DEFUN (no_bgp_distance_source_access_list,
14515 no_bgp_distance_source_access_list_cmd,
14516 "no distance (1-255) A.B.C.D/M WORD",
14517 NO_STR
14518 "Define an administrative distance\n"
14519 "Administrative distance\n"
14520 "IP source prefix\n"
14521 "Access list name\n")
14522{
14523 int idx_number = 2;
14524 int idx_ipv4_prefixlen = 3;
14525 int idx_word = 4;
14526 bgp_distance_unset(vty, argv[idx_number]->arg,
14527 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14528 return CMD_SUCCESS;
14529}
37a87b8f 14530
585f1adc
IR
14531DEFUN (ipv6_bgp_distance_source,
14532 ipv6_bgp_distance_source_cmd,
14533 "distance (1-255) X:X::X:X/M",
14534 "Define an administrative distance\n"
14535 "Administrative distance\n"
14536 "IP source prefix\n")
14537{
14538 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14539 return CMD_SUCCESS;
14540}
7ebe9748 14541
585f1adc
IR
14542DEFUN (no_ipv6_bgp_distance_source,
14543 no_ipv6_bgp_distance_source_cmd,
14544 "no distance (1-255) X:X::X:X/M",
14545 NO_STR
14546 "Define an administrative distance\n"
14547 "Administrative distance\n"
14548 "IP source prefix\n")
14549{
14550 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14551 return CMD_SUCCESS;
14552}
37a87b8f 14553
585f1adc
IR
14554DEFUN (ipv6_bgp_distance_source_access_list,
14555 ipv6_bgp_distance_source_access_list_cmd,
14556 "distance (1-255) X:X::X:X/M WORD",
14557 "Define an administrative distance\n"
14558 "Administrative distance\n"
14559 "IP source prefix\n"
14560 "Access list name\n")
14561{
14562 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14563 return CMD_SUCCESS;
718e3744 14564}
14565
585f1adc
IR
14566DEFUN (no_ipv6_bgp_distance_source_access_list,
14567 no_ipv6_bgp_distance_source_access_list_cmd,
14568 "no distance (1-255) X:X::X:X/M WORD",
14569 NO_STR
14570 "Define an administrative distance\n"
14571 "Administrative distance\n"
14572 "IP source prefix\n"
14573 "Access list name\n")
718e3744 14574{
585f1adc
IR
14575 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14576 return CMD_SUCCESS;
14577}
37a87b8f 14578
585f1adc
IR
14579DEFUN (bgp_damp_set,
14580 bgp_damp_set_cmd,
14581 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14582 "BGP Specific commands\n"
14583 "Enable route-flap dampening\n"
14584 "Half-life time for the penalty\n"
14585 "Value to start reusing a route\n"
14586 "Value to start suppressing a route\n"
14587 "Maximum duration to suppress a stable route\n")
14588{
14589 VTY_DECLVAR_CONTEXT(bgp, bgp);
14590 int idx_half_life = 2;
14591 int idx_reuse = 3;
14592 int idx_suppress = 4;
14593 int idx_max_suppress = 5;
37a87b8f
CS
14594 int half = DEFAULT_HALF_LIFE * 60;
14595 int reuse = DEFAULT_REUSE;
14596 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14597 int max = 4 * half;
14598
14599 if (argc == 6) {
14600 half = atoi(argv[idx_half_life]->arg) * 60;
14601 reuse = atoi(argv[idx_reuse]->arg);
14602 suppress = atoi(argv[idx_suppress]->arg);
14603 max = atoi(argv[idx_max_suppress]->arg) * 60;
14604 } else if (argc == 3) {
14605 half = atoi(argv[idx_half_life]->arg) * 60;
14606 max = 4 * half;
14607 }
14608
14609 /*
14610 * These can't be 0 but our SA doesn't understand the
14611 * way our cli is constructed
14612 */
14613 assert(reuse);
14614 assert(half);
14615 if (suppress < reuse) {
14616 vty_out(vty,
14617 "Suppress value cannot be less than reuse value \n");
14618 return 0;
14619 }
14620
14621 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14622 reuse, suppress, max);
14623}
14624
14625DEFUN (bgp_damp_unset,
14626 bgp_damp_unset_cmd,
14627 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14628 NO_STR
14629 "BGP Specific commands\n"
14630 "Enable route-flap dampening\n"
14631 "Half-life time for the penalty\n"
14632 "Value to start reusing a route\n"
14633 "Value to start suppressing a route\n"
14634 "Maximum duration to suppress a stable route\n")
14635{
14636 VTY_DECLVAR_CONTEXT(bgp, bgp);
14637 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14638}
14639
718e3744 14640/* Display specified route of BGP table. */
d62a17ae 14641static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14642 const char *ip_str, afi_t afi, safi_t safi,
14643 struct prefix_rd *prd, int prefix_check)
14644{
14645 int ret;
14646 struct prefix match;
9bcb3eef
DS
14647 struct bgp_dest *dest;
14648 struct bgp_dest *rm;
40381db7
DS
14649 struct bgp_path_info *pi;
14650 struct bgp_path_info *pi_temp;
d62a17ae 14651 struct bgp *bgp;
14652 struct bgp_table *table;
14653
14654 /* BGP structure lookup. */
14655 if (view_name) {
14656 bgp = bgp_lookup_by_name(view_name);
14657 if (bgp == NULL) {
14658 vty_out(vty, "%% Can't find BGP instance %s\n",
14659 view_name);
14660 return CMD_WARNING;
14661 }
14662 } else {
14663 bgp = bgp_get_default();
14664 if (bgp == NULL) {
14665 vty_out(vty, "%% No BGP process is configured\n");
14666 return CMD_WARNING;
14667 }
718e3744 14668 }
718e3744 14669
d62a17ae 14670 /* Check IP address argument. */
14671 ret = str2prefix(ip_str, &match);
14672 if (!ret) {
14673 vty_out(vty, "%% address is malformed\n");
14674 return CMD_WARNING;
14675 }
718e3744 14676
d62a17ae 14677 match.family = afi2family(afi);
14678
14679 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14680 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14681 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14682 dest = bgp_route_next(dest)) {
14683 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14684
9bcb3eef 14685 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14686 continue;
9bcb3eef 14687 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14688 if (!table)
ea47320b 14689 continue;
4953391b
DA
14690 rm = bgp_node_match(table, &match);
14691 if (rm == NULL)
ea47320b 14692 continue;
d62a17ae 14693
9bcb3eef 14694 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14695
ea47320b 14696 if (!prefix_check
b54892e0 14697 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14698 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14699 while (pi) {
14700 if (pi->extra && pi->extra->damp_info) {
14701 pi_temp = pi->next;
ea47320b 14702 bgp_damp_info_free(
19971c9a 14703 pi->extra->damp_info,
5c8846f6 14704 1, afi, safi);
40381db7 14705 pi = pi_temp;
ea47320b 14706 } else
40381db7 14707 pi = pi->next;
d62a17ae 14708 }
ea47320b
DL
14709 }
14710
9bcb3eef 14711 bgp_dest_unlock_node(rm);
d62a17ae 14712 }
14713 } else {
4953391b
DA
14714 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14715 if (dest != NULL) {
9bcb3eef 14716 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14717
d62a17ae 14718 if (!prefix_check
9bcb3eef
DS
14719 || dest_p->prefixlen == match.prefixlen) {
14720 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14721 while (pi) {
14722 if (pi->extra && pi->extra->damp_info) {
14723 pi_temp = pi->next;
d62a17ae 14724 bgp_damp_info_free(
19971c9a 14725 pi->extra->damp_info,
5c8846f6 14726 1, afi, safi);
40381db7 14727 pi = pi_temp;
d62a17ae 14728 } else
40381db7 14729 pi = pi->next;
d62a17ae 14730 }
14731 }
14732
9bcb3eef 14733 bgp_dest_unlock_node(dest);
d62a17ae 14734 }
14735 }
718e3744 14736
d62a17ae 14737 return CMD_SUCCESS;
718e3744 14738}
14739
14740DEFUN (clear_ip_bgp_dampening,
14741 clear_ip_bgp_dampening_cmd,
14742 "clear ip bgp dampening",
14743 CLEAR_STR
14744 IP_STR
14745 BGP_STR
14746 "Clear route flap dampening information\n")
14747{
b4f7f45b 14748 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14749 return CMD_SUCCESS;
718e3744 14750}
14751
14752DEFUN (clear_ip_bgp_dampening_prefix,
14753 clear_ip_bgp_dampening_prefix_cmd,
14754 "clear ip bgp dampening A.B.C.D/M",
14755 CLEAR_STR
14756 IP_STR
14757 BGP_STR
14758 "Clear route flap dampening information\n"
0c7b1b01 14759 "IPv4 prefix\n")
718e3744 14760{
d62a17ae 14761 int idx_ipv4_prefixlen = 4;
14762 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14763 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14764}
14765
14766DEFUN (clear_ip_bgp_dampening_address,
14767 clear_ip_bgp_dampening_address_cmd,
14768 "clear ip bgp dampening A.B.C.D",
14769 CLEAR_STR
14770 IP_STR
14771 BGP_STR
14772 "Clear route flap dampening information\n"
14773 "Network to clear damping information\n")
14774{
d62a17ae 14775 int idx_ipv4 = 4;
14776 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14777 SAFI_UNICAST, NULL, 0);
718e3744 14778}
14779
14780DEFUN (clear_ip_bgp_dampening_address_mask,
14781 clear_ip_bgp_dampening_address_mask_cmd,
14782 "clear ip bgp dampening A.B.C.D A.B.C.D",
14783 CLEAR_STR
14784 IP_STR
14785 BGP_STR
14786 "Clear route flap dampening information\n"
14787 "Network to clear damping information\n"
14788 "Network mask\n")
14789{
d62a17ae 14790 int idx_ipv4 = 4;
14791 int idx_ipv4_2 = 5;
14792 int ret;
14793 char prefix_str[BUFSIZ];
718e3744 14794
d62a17ae 14795 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14796 prefix_str, sizeof(prefix_str));
d62a17ae 14797 if (!ret) {
14798 vty_out(vty, "%% Inconsistent address and mask\n");
14799 return CMD_WARNING;
14800 }
718e3744 14801
d62a17ae 14802 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14803 NULL, 0);
718e3744 14804}
6b0655a2 14805
e3b78da8 14806static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14807{
14808 struct vty *vty = arg;
e3b78da8 14809 struct peer *peer = bucket->data;
825d9834
DS
14810 char buf[SU_ADDRSTRLEN];
14811
14812 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14813 sockunion2str(&peer->su, buf, sizeof(buf)));
14814}
14815
2a0e69ae
DS
14816DEFUN (show_bgp_listeners,
14817 show_bgp_listeners_cmd,
14818 "show bgp listeners",
14819 SHOW_STR
14820 BGP_STR
14821 "Display Listen Sockets and who created them\n")
14822{
14823 bgp_dump_listener_info(vty);
14824
14825 return CMD_SUCCESS;
14826}
14827
825d9834
DS
14828DEFUN (show_bgp_peerhash,
14829 show_bgp_peerhash_cmd,
14830 "show bgp peerhash",
14831 SHOW_STR
14832 BGP_STR
14833 "Display information about the BGP peerhash\n")
14834{
14835 struct list *instances = bm->bgp;
14836 struct listnode *node;
14837 struct bgp *bgp;
14838
14839 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14840 vty_out(vty, "BGP: %s\n", bgp->name);
14841 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14842 vty);
14843 }
14844
14845 return CMD_SUCCESS;
14846}
14847
587ff0fd 14848/* also used for encap safi */
2b791107
DL
14849static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14850 afi_t afi, safi_t safi)
d62a17ae 14851{
9bcb3eef
DS
14852 struct bgp_dest *pdest;
14853 struct bgp_dest *dest;
d62a17ae 14854 struct bgp_table *table;
b54892e0
DS
14855 const struct prefix *p;
14856 const struct prefix_rd *prd;
d62a17ae 14857 struct bgp_static *bgp_static;
14858 mpls_label_t label;
d62a17ae 14859 char rdbuf[RD_ADDRSTRLEN];
14860
14861 /* Network configuration. */
9bcb3eef
DS
14862 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14863 pdest = bgp_route_next(pdest)) {
14864 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14865 if (!table)
ea47320b 14866 continue;
d62a17ae 14867
9bcb3eef
DS
14868 for (dest = bgp_table_top(table); dest;
14869 dest = bgp_route_next(dest)) {
14870 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14871 if (bgp_static == NULL)
ea47320b 14872 continue;
d62a17ae 14873
9bcb3eef
DS
14874 p = bgp_dest_get_prefix(dest);
14875 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14876 pdest);
d62a17ae 14877
ea47320b 14878 /* "network" configuration display. */
06b9f471 14879 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14880 label = decode_label(&bgp_static->label);
14881
8228a9a7 14882 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14883 if (safi == SAFI_MPLS_VPN)
14884 vty_out(vty, " label %u", label);
14885
14886 if (bgp_static->rmap.name)
14887 vty_out(vty, " route-map %s",
14888 bgp_static->rmap.name);
e2a86ad9
DS
14889
14890 if (bgp_static->backdoor)
14891 vty_out(vty, " backdoor");
14892
ea47320b
DL
14893 vty_out(vty, "\n");
14894 }
14895 }
d62a17ae 14896}
14897
2b791107
DL
14898static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14899 afi_t afi, safi_t safi)
d62a17ae 14900{
9bcb3eef
DS
14901 struct bgp_dest *pdest;
14902 struct bgp_dest *dest;
d62a17ae 14903 struct bgp_table *table;
b54892e0
DS
14904 const struct prefix *p;
14905 const struct prefix_rd *prd;
d62a17ae 14906 struct bgp_static *bgp_static;
ff44f570 14907 char buf[PREFIX_STRLEN * 2];
d62a17ae 14908 char buf2[SU_ADDRSTRLEN];
14909 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14910 char esi_buf[ESI_BYTES];
d62a17ae 14911
14912 /* Network configuration. */
9bcb3eef
DS
14913 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14914 pdest = bgp_route_next(pdest)) {
14915 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14916 if (!table)
ea47320b 14917 continue;
d62a17ae 14918
9bcb3eef
DS
14919 for (dest = bgp_table_top(table); dest;
14920 dest = bgp_route_next(dest)) {
14921 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14922 if (bgp_static == NULL)
ea47320b 14923 continue;
d62a17ae 14924
ea47320b 14925 char *macrouter = NULL;
d62a17ae 14926
ea47320b
DL
14927 if (bgp_static->router_mac)
14928 macrouter = prefix_mac2str(
14929 bgp_static->router_mac, NULL, 0);
14930 if (bgp_static->eth_s_id)
0a50c248
AK
14931 esi_to_str(bgp_static->eth_s_id,
14932 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14933 p = bgp_dest_get_prefix(dest);
14934 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14935
ea47320b 14936 /* "network" configuration display. */
06b9f471 14937 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14938 if (p->u.prefix_evpn.route_type == 5) {
14939 char local_buf[PREFIX_STRLEN];
3714a385 14940 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14941 struct prefix_evpn *)p)
14942 ? AF_INET
14943 : AF_INET6;
3714a385 14944 inet_ntop(family,
14945 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14946 local_buf, PREFIX_STRLEN);
772270f3
QY
14947 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14948 p->u.prefix_evpn.prefix_addr
14949 .ip_prefix_length);
197cb530
PG
14950 } else {
14951 prefix2str(p, buf, sizeof(buf));
14952 }
ea47320b 14953
a4d82a8a
PZ
14954 if (bgp_static->gatewayIp.family == AF_INET
14955 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14956 inet_ntop(bgp_static->gatewayIp.family,
14957 &bgp_static->gatewayIp.u.prefix, buf2,
14958 sizeof(buf2));
ea47320b 14959 vty_out(vty,
7bcc8dac 14960 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14961 buf, rdbuf,
14962 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14963 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14964 macrouter);
14965
0a22ddfb 14966 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14967 }
14968 }
3da6fcd5
PG
14969}
14970
718e3744 14971/* Configuration of static route announcement and aggregate
14972 information. */
2b791107
DL
14973void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14974 safi_t safi)
d62a17ae 14975{
9bcb3eef 14976 struct bgp_dest *dest;
b54892e0 14977 const struct prefix *p;
d62a17ae 14978 struct bgp_static *bgp_static;
14979 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14980
2b791107
DL
14981 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14982 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14983 return;
14984 }
d62a17ae 14985
2b791107
DL
14986 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14987 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14988 return;
14989 }
d62a17ae 14990
14991 /* Network configuration. */
9bcb3eef
DS
14992 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14993 dest = bgp_route_next(dest)) {
14994 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14995 if (bgp_static == NULL)
ea47320b 14996 continue;
d62a17ae 14997
9bcb3eef 14998 p = bgp_dest_get_prefix(dest);
d62a17ae 14999
8228a9a7 15000 vty_out(vty, " network %pFX", p);
d62a17ae 15001
ea47320b
DL
15002 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15003 vty_out(vty, " label-index %u",
15004 bgp_static->label_index);
d62a17ae 15005
ea47320b
DL
15006 if (bgp_static->rmap.name)
15007 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15008
15009 if (bgp_static->backdoor)
15010 vty_out(vty, " backdoor");
718e3744 15011
ea47320b
DL
15012 vty_out(vty, "\n");
15013 }
15014
d62a17ae 15015 /* Aggregate-address configuration. */
9bcb3eef
DS
15016 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15017 dest = bgp_route_next(dest)) {
15018 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15019 if (bgp_aggregate == NULL)
ea47320b 15020 continue;
d62a17ae 15021
9bcb3eef 15022 p = bgp_dest_get_prefix(dest);
d62a17ae 15023
8228a9a7 15024 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15025
ea47320b
DL
15026 if (bgp_aggregate->as_set)
15027 vty_out(vty, " as-set");
d62a17ae 15028
ea47320b
DL
15029 if (bgp_aggregate->summary_only)
15030 vty_out(vty, " summary-only");
718e3744 15031
20894f50
DA
15032 if (bgp_aggregate->rmap.name)
15033 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15034
229757f1
DA
15035 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15036 vty_out(vty, " origin %s",
15037 bgp_origin2str(bgp_aggregate->origin));
15038
6aabb15d
RZ
15039 if (bgp_aggregate->match_med)
15040 vty_out(vty, " matching-MED-only");
15041
365ab2e7
RZ
15042 if (bgp_aggregate->suppress_map_name)
15043 vty_out(vty, " suppress-map %s",
15044 bgp_aggregate->suppress_map_name);
15045
ea47320b
DL
15046 vty_out(vty, "\n");
15047 }
d62a17ae 15048}
734b349e 15049
2b791107 15050void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15051 safi_t safi)
d62a17ae 15052{
9bcb3eef 15053 struct bgp_dest *dest;
d62a17ae 15054 struct bgp_distance *bdistance;
15055
15056 /* Distance configuration. */
15057 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15058 && bgp->distance_local[afi][safi]
15059 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15060 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15061 || bgp->distance_local[afi][safi]
15062 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15063 vty_out(vty, " distance bgp %d %d %d\n",
15064 bgp->distance_ebgp[afi][safi],
15065 bgp->distance_ibgp[afi][safi],
15066 bgp->distance_local[afi][safi]);
15067 }
734b349e 15068
9bcb3eef
DS
15069 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15070 dest = bgp_route_next(dest)) {
15071 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15072 if (bdistance != NULL)
56ca3b5b 15073 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15074 bdistance->distance, dest,
d62a17ae 15075 bdistance->access_list ? bdistance->access_list
15076 : "");
ca2e160d 15077 }
718e3744 15078}
15079
15080/* Allocate routing table structure and install commands. */
d62a17ae 15081void bgp_route_init(void)
15082{
15083 afi_t afi;
15084 safi_t safi;
15085
15086 /* Init BGP distance table. */
05c7a1cc 15087 FOREACH_AFI_SAFI (afi, safi)
960035b2 15088 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15089
15090 /* IPv4 BGP commands. */
15091 install_element(BGP_NODE, &bgp_table_map_cmd);
15092 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15093 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15094
554b3b10 15095 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15096
15097 /* IPv4 unicast configuration. */
15098 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15099 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15100 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15101
554b3b10 15102 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15103
15104 /* IPv4 multicast configuration. */
15105 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15106 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15107 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15108 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15109
15110 /* IPv4 labeled-unicast configuration. */
fb985e0c 15111 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15112 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15113
d62a17ae 15114 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15115 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 15116 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15117 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 15118 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 15119 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15120 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15121 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15122
15123 install_element(VIEW_NODE,
15124 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15125 install_element(VIEW_NODE,
15126 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15127 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15128 install_element(VIEW_NODE,
15129 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15130#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15131 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15132#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15133 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15134 install_element(VIEW_NODE,
44c69747 15135 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15136
d62a17ae 15137 /* BGP dampening clear commands */
15138 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15139 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15140
d62a17ae 15141 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15142 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15143
15144 /* prefix count */
15145 install_element(ENABLE_NODE,
15146 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15147#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15148 install_element(ENABLE_NODE,
15149 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15150#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15151
d62a17ae 15152 /* New config IPv6 BGP commands. */
15153 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15154 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15155 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15156
554b3b10 15157 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15158
15159 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15160
fb985e0c
DA
15161 /* IPv6 labeled unicast address family. */
15162 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15163 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15164
d62a17ae 15165 install_element(BGP_NODE, &bgp_distance_cmd);
15166 install_element(BGP_NODE, &no_bgp_distance_cmd);
15167 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15168 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15169 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15170 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15171 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15172 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15173 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15174 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15175 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15176 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15177 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15178 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15179 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15180 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15181 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15182 install_element(BGP_IPV4M_NODE,
15183 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15184 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15185 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15186 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15187 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15188 install_element(BGP_IPV6_NODE,
15189 &ipv6_bgp_distance_source_access_list_cmd);
15190 install_element(BGP_IPV6_NODE,
15191 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15192 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15193 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15194 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15195 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15196 install_element(BGP_IPV6M_NODE,
15197 &ipv6_bgp_distance_source_access_list_cmd);
15198 install_element(BGP_IPV6M_NODE,
15199 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15200
ef5f4b23 15201 /* BGP dampening */
585f1adc
IR
15202 install_element(BGP_NODE, &bgp_damp_set_cmd);
15203 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15204 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15205 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15206 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15207 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15208 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15209 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15210 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15211 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15212 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15213 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15214 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15215 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15216
15217 /* Large Communities */
15218 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15219 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15220
15221 /* show bgp ipv4 flowspec detailed */
15222 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15223
2a0e69ae 15224 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15225 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15226}
15227
15228void bgp_route_finish(void)
15229{
15230 afi_t afi;
15231 safi_t safi;
15232
05c7a1cc
QY
15233 FOREACH_AFI_SAFI (afi, safi) {
15234 bgp_table_unlock(bgp_distance_table[afi][safi]);
15235 bgp_distance_table[afi][safi] = NULL;
15236 }
228da428 15237}