]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #9645 from mjstapp/fix_show_bgp_lu
[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 }
9317 }
9318}
718e3744 9319
bd494ec5 9320void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9321 struct bgp_path_info *path, int display,
d62a17ae 9322 json_object *json_paths)
718e3744 9323{
d62a17ae 9324 struct attr *attr;
14f51eba 9325 char buf[BUFSIZ] = {0};
d62a17ae 9326 json_object *json_path = NULL;
14f51eba
LK
9327 json_object *json_nexthop = NULL;
9328 json_object *json_overlay = NULL;
856ca177 9329
9b6d8fcf 9330 if (!path->extra)
d62a17ae 9331 return;
718e3744 9332
14f51eba
LK
9333 if (json_paths) {
9334 json_path = json_object_new_object();
9335 json_overlay = json_object_new_object();
9336 json_nexthop = json_object_new_object();
9337 }
9338
d62a17ae 9339 /* short status lead text */
82c298be 9340 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9341
d62a17ae 9342 /* print prefix and mask */
9343 if (!display)
7d3cae70 9344 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9345 else
9346 vty_out(vty, "%*s", 17, " ");
9347
9348 /* Print attribute */
9b6d8fcf 9349 attr = path->attr;
05864da7
DS
9350 char buf1[BUFSIZ];
9351 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9352
05864da7
DS
9353 switch (af) {
9354 case AF_INET:
9355 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9356 if (!json_path) {
9357 vty_out(vty, "%-16s", buf);
9358 } else {
9359 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9360
05864da7 9361 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9362
05864da7
DS
9363 json_object_object_add(json_path, "nexthop",
9364 json_nexthop);
9365 }
9366 break;
9367 case AF_INET6:
9368 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9369 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9370 if (!json_path) {
9371 vty_out(vty, "%s(%s)", buf, buf1);
9372 } else {
9373 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9374
05864da7
DS
9375 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9376 buf1);
14f51eba 9377
05864da7 9378 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9379
05864da7
DS
9380 json_object_object_add(json_path, "nexthop",
9381 json_nexthop);
9382 }
9383 break;
9384 default:
9385 if (!json_path) {
9386 vty_out(vty, "?");
9387 } else {
9388 json_object_string_add(json_nexthop, "Error",
9389 "Unsupported address-family");
d62a17ae 9390 }
05864da7 9391 }
988258b4 9392
6c924775
DS
9393 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9394
9395 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9396 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9397 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9398 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9399
05864da7
DS
9400 if (!json_path)
9401 vty_out(vty, "/%s", buf);
9402 else
9403 json_object_string_add(json_overlay, "gw", buf);
9404
9405 if (attr->ecommunity) {
9406 char *mac = NULL;
9407 struct ecommunity_val *routermac = ecommunity_lookup(
9408 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9409 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9410
9411 if (routermac)
9412 mac = ecom_mac2str((char *)routermac->val);
9413 if (mac) {
9414 if (!json_path) {
c4efd0f4 9415 vty_out(vty, "/%s", mac);
05864da7
DS
9416 } else {
9417 json_object_string_add(json_overlay, "rmac",
9418 mac);
988258b4 9419 }
05864da7 9420 XFREE(MTYPE_TMP, mac);
988258b4 9421 }
05864da7 9422 }
718e3744 9423
05864da7
DS
9424 if (!json_path) {
9425 vty_out(vty, "\n");
9426 } else {
9427 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9428
05864da7 9429 json_object_array_add(json_paths, json_path);
14f51eba 9430 }
d62a17ae 9431}
718e3744 9432
d62a17ae 9433/* dampening route */
5f040085
DS
9434static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9435 struct bgp_path_info *path, int display,
9436 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9437 json_object *json_paths)
d62a17ae 9438{
e5be8c1d 9439 struct attr *attr = path->attr;
d62a17ae 9440 int len;
9441 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9442 json_object *json_path = NULL;
9443
9444 if (use_json)
9445 json_path = json_object_new_object();
d62a17ae 9446
9447 /* short status lead text */
e5be8c1d 9448 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9449
9450 /* print prefix and mask */
9451 if (!use_json) {
9452 if (!display)
7d3cae70 9453 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9454 else
9455 vty_out(vty, "%*s", 17, " ");
d62a17ae 9456
e5be8c1d
DA
9457 len = vty_out(vty, "%s", path->peer->host);
9458 len = 17 - len;
9459
9460 if (len < 1)
d62a17ae 9461 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9462 else
9463 vty_out(vty, "%*s", len, " ");
d62a17ae 9464
9b6d8fcf
DS
9465 vty_out(vty, "%s ",
9466 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9467 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9468 use_json, NULL));
d62a17ae 9469
e5be8c1d 9470 if (attr->aspath)
05864da7 9471 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9472
05864da7
DS
9473 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9474
d62a17ae 9475 vty_out(vty, "\n");
e5be8c1d
DA
9476 } else {
9477 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9478 safi, use_json, json_path);
9479
9480 if (attr->aspath)
9481 json_object_string_add(json_path, "asPath",
9482 attr->aspath->str);
9483
9484 json_object_string_add(json_path, "origin",
9485 bgp_origin_str[attr->origin]);
9486 json_object_string_add(json_path, "peerHost", path->peer->host);
9487
9488 json_object_array_add(json_paths, json_path);
9489 }
d62a17ae 9490}
718e3744 9491
d62a17ae 9492/* flap route */
5f040085
DS
9493static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9494 struct bgp_path_info *path, int display,
9495 afi_t afi, safi_t safi, bool use_json,
31258046 9496 json_object *json_paths)
784d3a42 9497{
31258046 9498 struct attr *attr = path->attr;
d62a17ae 9499 struct bgp_damp_info *bdi;
9500 char timebuf[BGP_UPTIME_LEN];
9501 int len;
31258046 9502 json_object *json_path = NULL;
784d3a42 9503
9b6d8fcf 9504 if (!path->extra)
d62a17ae 9505 return;
784d3a42 9506
31258046
DA
9507 if (use_json)
9508 json_path = json_object_new_object();
9509
9b6d8fcf 9510 bdi = path->extra->damp_info;
784d3a42 9511
d62a17ae 9512 /* short status lead text */
31258046 9513 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9514
d62a17ae 9515 if (!use_json) {
9516 if (!display)
7d3cae70 9517 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9518 else
9519 vty_out(vty, "%*s", 17, " ");
784d3a42 9520
31258046
DA
9521 len = vty_out(vty, "%s", path->peer->host);
9522 len = 16 - len;
9523 if (len < 1)
d62a17ae 9524 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9525 else
9526 vty_out(vty, "%*s", len, " ");
784d3a42 9527
31258046
DA
9528 len = vty_out(vty, "%d", bdi->flap);
9529 len = 5 - len;
9530 if (len < 1)
d62a17ae 9531 vty_out(vty, " ");
d62a17ae 9532 else
9533 vty_out(vty, "%*s", len, " ");
d62a17ae 9534
996c9314
LB
9535 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9536 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9537
31258046
DA
9538 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9539 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9540 vty_out(vty, "%s ",
9b6d8fcf 9541 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9542 BGP_UPTIME_LEN, afi,
31258046
DA
9543 safi, use_json, NULL));
9544 else
d62a17ae 9545 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9546
31258046 9547 if (attr->aspath)
05864da7 9548 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9549
05864da7
DS
9550 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9551
d62a17ae 9552 vty_out(vty, "\n");
31258046
DA
9553 } else {
9554 json_object_string_add(json_path, "peerHost", path->peer->host);
9555 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9556
9557 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9558 json_path);
9559
9560 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9561 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9562 bgp_damp_reuse_time_vty(vty, path, timebuf,
9563 BGP_UPTIME_LEN, afi, safi,
9564 use_json, json_path);
9565
9566 if (attr->aspath)
9567 json_object_string_add(json_path, "asPath",
9568 attr->aspath->str);
9569
9570 json_object_string_add(json_path, "origin",
9571 bgp_origin_str[attr->origin]);
9572
9573 json_object_array_add(json_paths, json_path);
9574 }
d62a17ae 9575}
9576
9577static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9578 int *first, const char *header,
9579 json_object *json_adv_to)
9580{
9581 char buf1[INET6_ADDRSTRLEN];
9582 json_object *json_peer = NULL;
9583
9584 if (json_adv_to) {
9585 /* 'advertised-to' is a dictionary of peers we have advertised
9586 * this
9587 * prefix too. The key is the peer's IP or swpX, the value is
9588 * the
9589 * hostname if we know it and "" if not.
9590 */
9591 json_peer = json_object_new_object();
9592
9593 if (peer->hostname)
9594 json_object_string_add(json_peer, "hostname",
9595 peer->hostname);
9596
9597 if (peer->conf_if)
9598 json_object_object_add(json_adv_to, peer->conf_if,
9599 json_peer);
9600 else
9601 json_object_object_add(
9602 json_adv_to,
9603 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9604 json_peer);
9605 } else {
9606 if (*first) {
9607 vty_out(vty, "%s", header);
9608 *first = 0;
9609 }
9610
9611 if (peer->hostname
892fedb6 9612 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9613 if (peer->conf_if)
9614 vty_out(vty, " %s(%s)", peer->hostname,
9615 peer->conf_if);
9616 else
9617 vty_out(vty, " %s(%s)", peer->hostname,
9618 sockunion2str(&peer->su, buf1,
9619 SU_ADDRSTRLEN));
9620 } else {
9621 if (peer->conf_if)
9622 vty_out(vty, " %s", peer->conf_if);
9623 else
9624 vty_out(vty, " %s",
9625 sockunion2str(&peer->su, buf1,
9626 SU_ADDRSTRLEN));
9627 }
9628 }
784d3a42
PG
9629}
9630
dcc68b5e
MS
9631static void route_vty_out_tx_ids(struct vty *vty,
9632 struct bgp_addpath_info_data *d)
9633{
9634 int i;
9635
9636 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9637 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9638 d->addpath_tx_id[i],
9639 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9640 }
9641}
9642
5e4d4c8a 9643static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9644 struct bgp_path_info *pi,
9645 struct attr *attr,
9646 json_object *json_path)
5e4d4c8a
AK
9647{
9648 char esi_buf[ESI_STR_LEN];
9649 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9650 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9651 ATTR_ES_PEER_ROUTER);
9652 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9653 ATTR_ES_PEER_ACTIVE);
9654 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9655 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9656 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9657 if (json_path) {
9658 json_object *json_es_info = NULL;
9659
9660 json_object_string_add(
9661 json_path, "esi",
9662 esi_buf);
9663 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9664 json_es_info = json_object_new_object();
9665 if (es_local)
9666 json_object_boolean_true_add(
9667 json_es_info, "localEs");
9668 if (peer_active)
9669 json_object_boolean_true_add(
9670 json_es_info, "peerActive");
9671 if (peer_proxy)
9672 json_object_boolean_true_add(
9673 json_es_info, "peerProxy");
9674 if (peer_router)
9675 json_object_boolean_true_add(
9676 json_es_info, "peerRouter");
9677 if (attr->mm_sync_seqnum)
9678 json_object_int_add(
9679 json_es_info, "peerSeq",
9680 attr->mm_sync_seqnum);
9681 json_object_object_add(
9682 json_path, "es_info",
9683 json_es_info);
9684 }
9685 } else {
9686 if (bgp_evpn_attr_is_sync(attr))
9687 vty_out(vty,
9688 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9689 esi_buf,
9690 es_local ? "local-es":"",
9691 peer_proxy ? "proxy " : "",
9692 peer_active ? "active ":"",
9693 peer_router ? "router ":"",
9694 attr->mm_sync_seqnum);
9695 else
9696 vty_out(vty, " ESI %s %s\n",
9697 esi_buf,
9698 es_local ? "local-es":"");
9699 }
9700}
9701
4933eaaf
DS
9702void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9703 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9704 enum rpki_states rpki_curr_state,
9705 json_object *json_paths)
d62a17ae 9706{
9707 char buf[INET6_ADDRSTRLEN];
9708 char buf1[BUFSIZ];
515c2602 9709 struct attr *attr = path->attr;
d62a17ae 9710 int sockunion_vty_out(struct vty *, union sockunion *);
9711 time_t tbuf;
9712 json_object *json_bestpath = NULL;
9713 json_object *json_cluster_list = NULL;
9714 json_object *json_cluster_list_list = NULL;
9715 json_object *json_ext_community = NULL;
9716 json_object *json_last_update = NULL;
7fd077aa 9717 json_object *json_pmsi = NULL;
d62a17ae 9718 json_object *json_nexthop_global = NULL;
9719 json_object *json_nexthop_ll = NULL;
9720 json_object *json_nexthops = NULL;
9721 json_object *json_path = NULL;
9722 json_object *json_peer = NULL;
9723 json_object *json_string = NULL;
9724 json_object *json_adv_to = NULL;
9725 int first = 0;
9726 struct listnode *node, *nnode;
9727 struct peer *peer;
9728 int addpath_capable;
9729 int has_adj;
9730 unsigned int first_as;
1defdda8 9731 bool nexthop_self =
9b6d8fcf 9732 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9733 int i;
2ba93fd6
DA
9734 char *nexthop_hostname =
9735 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9736
9737 if (json_paths) {
9738 json_path = json_object_new_object();
9739 json_peer = json_object_new_object();
9740 json_nexthop_global = json_object_new_object();
9741 }
9742
8304dabf
AD
9743 if (safi == SAFI_EVPN) {
9744 if (!json_paths)
9745 vty_out(vty, " Route %pRN", bn);
9746 }
9747
44c69747 9748 if (path->extra) {
b57ba6d2 9749 char tag_buf[30];
d62a17ae 9750
d62a17ae 9751 tag_buf[0] = '\0';
9b6d8fcf
DS
9752 if (path->extra && path->extra->num_labels) {
9753 bgp_evpn_label2str(path->extra->label,
9754 path->extra->num_labels, tag_buf,
a4d82a8a 9755 sizeof(tag_buf));
d62a17ae 9756 }
d7325ee7 9757 if (safi == SAFI_EVPN) {
44c69747 9758 if (!json_paths) {
44c69747
LK
9759 if (tag_buf[0] != '\0')
9760 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9761 } else {
9762 if (tag_buf[0])
9763 json_object_string_add(json_path, "VNI",
9764 tag_buf);
9765 }
d7325ee7
DD
9766 }
9767
44c69747 9768 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9769 struct bgp_path_info *parent_ri;
9bcb3eef 9770 struct bgp_dest *dest, *pdest;
d62a17ae 9771
9b6d8fcf 9772 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9773 dest = parent_ri->net;
9774 if (dest && dest->pdest) {
9775 pdest = dest->pdest;
9776 prefix_rd2str(
9777 (struct prefix_rd *)bgp_dest_get_prefix(
9778 pdest),
9779 buf1, sizeof(buf1));
d7325ee7 9780 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9781 vty_out(vty,
58bff4d1 9782 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9783 buf1,
9784 (struct prefix_evpn *)
9785 bgp_dest_get_prefix(
9786 dest),
9787 tag_buf);
58bff4d1
AK
9788 if (attr->es_flags & ATTR_ES_L3_NHG)
9789 vty_out(vty, ", L3NHG %s",
9790 (attr->es_flags
9791 & ATTR_ES_L3_NHG_ACTIVE)
9792 ? "active"
9793 : "inactive");
9794 vty_out(vty, "\n");
9795
d7325ee7 9796 } else
2dbe669b
DA
9797 vty_out(vty,
9798 " Imported from %s:%pFX\n",
9799 buf1,
9800 (struct prefix_evpn *)
9801 bgp_dest_get_prefix(
9802 dest));
d62a17ae 9803 }
9804 }
9805 }
d62a17ae 9806
8304dabf
AD
9807 if (safi == SAFI_EVPN
9808 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9809 char gwip_buf[INET6_ADDRSTRLEN];
9810
9811 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9812 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9813 gwip_buf, sizeof(gwip_buf));
9814 else
9815 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9816 gwip_buf, sizeof(gwip_buf));
9817
9818 if (json_paths)
9819 json_object_string_add(json_path, "gatewayIP",
9820 gwip_buf);
9821 else
9822 vty_out(vty, " Gateway IP %s", gwip_buf);
9823 }
9824
9825 if (safi == SAFI_EVPN)
9826 vty_out(vty, "\n");
9827
05864da7
DS
9828 /* Line1 display AS-path, Aggregator */
9829 if (attr->aspath) {
9830 if (json_paths) {
9831 if (!attr->aspath->json)
9832 aspath_str_update(attr->aspath, true);
9833 json_object_lock(attr->aspath->json);
9834 json_object_object_add(json_path, "aspath",
9835 attr->aspath->json);
9836 } else {
9837 if (attr->aspath->segments)
9838 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9839 else
05864da7 9840 vty_out(vty, " Local");
d62a17ae 9841 }
05864da7 9842 }
d62a17ae 9843
05864da7
DS
9844 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9845 if (json_paths)
9846 json_object_boolean_true_add(json_path, "removed");
9847 else
9848 vty_out(vty, ", (removed)");
9849 }
d62a17ae 9850
05864da7
DS
9851 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9852 if (json_paths)
9853 json_object_boolean_true_add(json_path, "stale");
9854 else
9855 vty_out(vty, ", (stale)");
9856 }
d62a17ae 9857
05864da7
DS
9858 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9859 if (json_paths) {
23d0a753
DA
9860 char buf[BUFSIZ] = {0};
9861
05864da7
DS
9862 json_object_int_add(json_path, "aggregatorAs",
9863 attr->aggregator_as);
23d0a753
DA
9864 json_object_string_add(json_path, "aggregatorId",
9865 inet_ntop(AF_INET,
9866 &attr->aggregator_addr,
9867 buf, sizeof(buf)));
05864da7 9868 } else {
88d495a9
DA
9869 vty_out(vty, ", (aggregated by %u %pI4)",
9870 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9871 }
05864da7 9872 }
d62a17ae 9873
05864da7
DS
9874 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9875 PEER_FLAG_REFLECTOR_CLIENT)) {
9876 if (json_paths)
9877 json_object_boolean_true_add(json_path,
9878 "rxedFromRrClient");
9879 else
9880 vty_out(vty, ", (Received from a RR-client)");
9881 }
d62a17ae 9882
05864da7
DS
9883 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9884 PEER_FLAG_RSERVER_CLIENT)) {
9885 if (json_paths)
9886 json_object_boolean_true_add(json_path,
9887 "rxedFromRsClient");
9888 else
9889 vty_out(vty, ", (Received from a RS-client)");
9890 }
d62a17ae 9891
05864da7
DS
9892 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9893 if (json_paths)
9894 json_object_boolean_true_add(json_path,
9895 "dampeningHistoryEntry");
9896 else
9897 vty_out(vty, ", (history entry)");
9898 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9899 if (json_paths)
9900 json_object_boolean_true_add(json_path,
9901 "dampeningSuppressed");
9902 else
9903 vty_out(vty, ", (suppressed due to dampening)");
9904 }
d62a17ae 9905
05864da7
DS
9906 if (!json_paths)
9907 vty_out(vty, "\n");
d62a17ae 9908
05864da7
DS
9909 /* Line2 display Next-hop, Neighbor, Router-id */
9910 /* Display the nexthop */
9bcb3eef 9911 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9912
9913 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9914 || bn_p->family == AF_EVPN)
05864da7
DS
9915 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9916 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9917 char buf[BUFSIZ] = {0};
9918
05864da7
DS
9919 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9920 || safi == SAFI_EVPN) {
515c2602 9921 if (json_paths) {
d62a17ae 9922 json_object_string_add(
515c2602 9923 json_nexthop_global, "ip",
23d0a753
DA
9924 inet_ntop(AF_INET,
9925 &attr->mp_nexthop_global_in,
9926 buf, sizeof(buf)));
515c2602 9927
939a97f4 9928 if (path->peer->hostname)
515c2602
DA
9929 json_object_string_add(
9930 json_nexthop_global, "hostname",
939a97f4 9931 path->peer->hostname);
aef999a2
DA
9932 } else {
9933 if (nexthop_hostname)
9934 vty_out(vty, " %pI4(%s)",
9935 &attr->mp_nexthop_global_in,
9936 nexthop_hostname);
9937 else
9938 vty_out(vty, " %pI4",
9939 &attr->mp_nexthop_global_in);
9940 }
d62a17ae 9941 } else {
515c2602 9942 if (json_paths) {
05864da7 9943 json_object_string_add(
515c2602 9944 json_nexthop_global, "ip",
23d0a753
DA
9945 inet_ntop(AF_INET, &attr->nexthop, buf,
9946 sizeof(buf)));
515c2602 9947
939a97f4 9948 if (path->peer->hostname)
515c2602
DA
9949 json_object_string_add(
9950 json_nexthop_global, "hostname",
939a97f4 9951 path->peer->hostname);
aef999a2
DA
9952 } else {
9953 if (nexthop_hostname)
9954 vty_out(vty, " %pI4(%s)",
9955 &attr->nexthop,
9956 nexthop_hostname);
9957 else
9958 vty_out(vty, " %pI4",
9959 &attr->nexthop);
9960 }
d62a17ae 9961 }
9962
05864da7
DS
9963 if (json_paths)
9964 json_object_string_add(json_nexthop_global, "afi",
9965 "ipv4");
9966 } else {
9967 if (json_paths) {
9968 json_object_string_add(
515c2602
DA
9969 json_nexthop_global, "ip",
9970 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9971 buf, INET6_ADDRSTRLEN));
9972
939a97f4 9973 if (path->peer->hostname)
515c2602
DA
9974 json_object_string_add(json_nexthop_global,
9975 "hostname",
939a97f4 9976 path->peer->hostname);
515c2602 9977
05864da7
DS
9978 json_object_string_add(json_nexthop_global, "afi",
9979 "ipv6");
9980 json_object_string_add(json_nexthop_global, "scope",
9981 "global");
9982 } else {
aef999a2
DA
9983 if (nexthop_hostname)
9984 vty_out(vty, " %pI6(%s)",
9985 &attr->mp_nexthop_global,
9986 nexthop_hostname);
9987 else
9988 vty_out(vty, " %pI6",
9989 &attr->mp_nexthop_global);
d62a17ae 9990 }
05864da7 9991 }
d62a17ae 9992
05864da7
DS
9993 /* Display the IGP cost or 'inaccessible' */
9994 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9995 if (json_paths)
9996 json_object_boolean_false_add(json_nexthop_global,
9997 "accessible");
9998 else
9999 vty_out(vty, " (inaccessible)");
10000 } else {
10001 if (path->extra && path->extra->igpmetric) {
d62a17ae 10002 if (json_paths)
05864da7
DS
10003 json_object_int_add(json_nexthop_global,
10004 "metric",
10005 path->extra->igpmetric);
d62a17ae 10006 else
05864da7
DS
10007 vty_out(vty, " (metric %u)",
10008 path->extra->igpmetric);
d62a17ae 10009 }
10010
05864da7 10011 /* IGP cost is 0, display this only for json */
d62a17ae 10012 else {
d62a17ae 10013 if (json_paths)
05864da7
DS
10014 json_object_int_add(json_nexthop_global,
10015 "metric", 0);
d62a17ae 10016 }
d62a17ae 10017
05864da7
DS
10018 if (json_paths)
10019 json_object_boolean_true_add(json_nexthop_global,
10020 "accessible");
10021 }
d62a17ae 10022
05864da7
DS
10023 /* Display peer "from" output */
10024 /* This path was originated locally */
10025 if (path->peer == bgp->peer_self) {
d62a17ae 10026
05864da7 10027 if (safi == SAFI_EVPN
b54892e0 10028 || (bn_p->family == AF_INET
05864da7 10029 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10030 if (json_paths)
05864da7
DS
10031 json_object_string_add(json_peer, "peerId",
10032 "0.0.0.0");
d62a17ae 10033 else
05864da7
DS
10034 vty_out(vty, " from 0.0.0.0 ");
10035 } else {
d62a17ae 10036 if (json_paths)
05864da7
DS
10037 json_object_string_add(json_peer, "peerId",
10038 "::");
d62a17ae 10039 else
05864da7 10040 vty_out(vty, " from :: ");
d62a17ae 10041 }
d62a17ae 10042
23d0a753
DA
10043 if (json_paths) {
10044 char buf[BUFSIZ] = {0};
10045
05864da7 10046 json_object_string_add(json_peer, "routerId",
23d0a753
DA
10047 inet_ntop(AF_INET,
10048 &bgp->router_id, buf,
10049 sizeof(buf)));
10050 } else {
10051 vty_out(vty, "(%pI4)", &bgp->router_id);
10052 }
05864da7 10053 }
d62a17ae 10054
05864da7
DS
10055 /* We RXed this path from one of our peers */
10056 else {
10057
10058 if (json_paths) {
10059 json_object_string_add(json_peer, "peerId",
10060 sockunion2str(&path->peer->su,
10061 buf,
10062 SU_ADDRSTRLEN));
10063 json_object_string_add(json_peer, "routerId",
10064 inet_ntop(AF_INET,
10065 &path->peer->remote_id,
10066 buf1, sizeof(buf1)));
10067
10068 if (path->peer->hostname)
10069 json_object_string_add(json_peer, "hostname",
10070 path->peer->hostname);
10071
10072 if (path->peer->domainname)
10073 json_object_string_add(json_peer, "domainname",
10074 path->peer->domainname);
10075
10076 if (path->peer->conf_if)
10077 json_object_string_add(json_peer, "interface",
10078 path->peer->conf_if);
10079 } else {
10080 if (path->peer->conf_if) {
10081 if (path->peer->hostname
892fedb6
DA
10082 && CHECK_FLAG(path->peer->bgp->flags,
10083 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10084 vty_out(vty, " from %s(%s)",
10085 path->peer->hostname,
10086 path->peer->conf_if);
d62a17ae 10087 else
05864da7 10088 vty_out(vty, " from %s",
9b6d8fcf 10089 path->peer->conf_if);
d62a17ae 10090 } else {
05864da7 10091 if (path->peer->hostname
892fedb6
DA
10092 && CHECK_FLAG(path->peer->bgp->flags,
10093 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10094 vty_out(vty, " from %s(%s)",
10095 path->peer->hostname,
10096 path->peer->host);
d62a17ae 10097 else
05864da7
DS
10098 vty_out(vty, " from %s",
10099 sockunion2str(&path->peer->su,
10100 buf,
10101 SU_ADDRSTRLEN));
d62a17ae 10102 }
d62a17ae 10103
05864da7 10104 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10105 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10106 else
10107 vty_out(vty, " (%s)",
10108 inet_ntop(AF_INET,
10109 &path->peer->remote_id, buf1,
10110 sizeof(buf1)));
d62a17ae 10111 }
05864da7 10112 }
9df8b37c 10113
05864da7
DS
10114 /*
10115 * Note when vrfid of nexthop is different from that of prefix
10116 */
10117 if (path->extra && path->extra->bgp_orig) {
10118 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10119
05864da7
DS
10120 if (json_paths) {
10121 const char *vn;
9df8b37c 10122
05864da7
DS
10123 if (path->extra->bgp_orig->inst_type
10124 == BGP_INSTANCE_TYPE_DEFAULT)
10125 vn = VRF_DEFAULT_NAME;
10126 else
10127 vn = path->extra->bgp_orig->name;
9df8b37c 10128
05864da7 10129 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10130
05864da7
DS
10131 if (nexthop_vrfid == VRF_UNKNOWN) {
10132 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10133 } else {
05864da7
DS
10134 json_object_int_add(json_path, "nhVrfId",
10135 (int)nexthop_vrfid);
9df8b37c 10136 }
05864da7
DS
10137 } else {
10138 if (nexthop_vrfid == VRF_UNKNOWN)
10139 vty_out(vty, " vrf ?");
137147c6
DS
10140 else {
10141 struct vrf *vrf;
10142
10143 vrf = vrf_lookup_by_id(nexthop_vrfid);
10144 vty_out(vty, " vrf %s(%u)",
10145 VRF_LOGNAME(vrf), nexthop_vrfid);
10146 }
9df8b37c 10147 }
05864da7 10148 }
9df8b37c 10149
05864da7
DS
10150 if (nexthop_self) {
10151 if (json_paths) {
10152 json_object_boolean_true_add(json_path,
10153 "announceNexthopSelf");
10154 } else {
10155 vty_out(vty, " announce-nh-self");
9df8b37c 10156 }
05864da7 10157 }
9df8b37c 10158
05864da7
DS
10159 if (!json_paths)
10160 vty_out(vty, "\n");
d62a17ae 10161
05864da7
DS
10162 /* display the link-local nexthop */
10163 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10164 if (json_paths) {
10165 json_nexthop_ll = json_object_new_object();
10166 json_object_string_add(
515c2602
DA
10167 json_nexthop_ll, "ip",
10168 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10169 buf, INET6_ADDRSTRLEN));
10170
939a97f4 10171 if (path->peer->hostname)
515c2602
DA
10172 json_object_string_add(json_nexthop_ll,
10173 "hostname",
939a97f4 10174 path->peer->hostname);
515c2602 10175
05864da7
DS
10176 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10177 json_object_string_add(json_nexthop_ll, "scope",
10178 "link-local");
d62a17ae 10179
05864da7
DS
10180 json_object_boolean_true_add(json_nexthop_ll,
10181 "accessible");
d62a17ae 10182
05864da7 10183 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10184 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10185 "used");
10186 else
10187 json_object_boolean_true_add(
10188 json_nexthop_global, "used");
10189 } else {
10190 vty_out(vty, " (%s) %s\n",
10191 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10192 buf, INET6_ADDRSTRLEN),
10193 attr->mp_nexthop_prefer_global
10194 ? "(prefer-global)"
10195 : "(used)");
d62a17ae 10196 }
05864da7
DS
10197 }
10198 /* If we do not have a link-local nexthop then we must flag the
10199 global as "used" */
10200 else {
10201 if (json_paths)
10202 json_object_boolean_true_add(json_nexthop_global,
10203 "used");
10204 }
d62a17ae 10205
b5e140c8 10206 if (safi == SAFI_EVPN &&
5e4d4c8a 10207 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10208 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10209 }
10210
05864da7
DS
10211 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10212 * Int/Ext/Local, Atomic, best */
10213 if (json_paths)
10214 json_object_string_add(json_path, "origin",
10215 bgp_origin_long_str[attr->origin]);
10216 else
10217 vty_out(vty, " Origin %s",
10218 bgp_origin_long_str[attr->origin]);
9df8b37c 10219
05864da7 10220 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10221 if (json_paths)
05864da7 10222 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10223 else
05864da7
DS
10224 vty_out(vty, ", metric %u", attr->med);
10225 }
9df8b37c 10226
05864da7
DS
10227 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10228 if (json_paths)
0fbac0b4 10229 json_object_int_add(json_path, "locPrf",
05864da7
DS
10230 attr->local_pref);
10231 else
10232 vty_out(vty, ", localpref %u", attr->local_pref);
10233 }
9df8b37c 10234
05864da7
DS
10235 if (attr->weight != 0) {
10236 if (json_paths)
10237 json_object_int_add(json_path, "weight", attr->weight);
10238 else
10239 vty_out(vty, ", weight %u", attr->weight);
10240 }
9df8b37c 10241
05864da7
DS
10242 if (attr->tag != 0) {
10243 if (json_paths)
10244 json_object_int_add(json_path, "tag", attr->tag);
10245 else
10246 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10247 }
9df8b37c 10248
05864da7
DS
10249 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10250 if (json_paths)
10251 json_object_boolean_false_add(json_path, "valid");
10252 else
10253 vty_out(vty, ", invalid");
10254 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10255 if (json_paths)
10256 json_object_boolean_true_add(json_path, "valid");
10257 else
10258 vty_out(vty, ", valid");
10259 }
9df8b37c 10260
7d3cae70
DA
10261 if (json_paths)
10262 json_object_int_add(json_path, "version", bn->version);
10263
05864da7
DS
10264 if (path->peer != bgp->peer_self) {
10265 if (path->peer->as == path->peer->local_as) {
10266 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10267 if (json_paths)
10268 json_object_string_add(
10269 json_peer, "type",
10270 "confed-internal");
d62a17ae 10271 else
05864da7 10272 vty_out(vty, ", confed-internal");
d62a17ae 10273 } else {
05864da7
DS
10274 if (json_paths)
10275 json_object_string_add(
10276 json_peer, "type", "internal");
10277 else
10278 vty_out(vty, ", internal");
9df8b37c 10279 }
05864da7
DS
10280 } else {
10281 if (bgp_confederation_peers_check(bgp,
10282 path->peer->as)) {
10283 if (json_paths)
10284 json_object_string_add(
10285 json_peer, "type",
10286 "confed-external");
d62a17ae 10287 else
05864da7 10288 vty_out(vty, ", confed-external");
d62a17ae 10289 } else {
05864da7
DS
10290 if (json_paths)
10291 json_object_string_add(
10292 json_peer, "type", "external");
10293 else
10294 vty_out(vty, ", external");
d62a17ae 10295 }
10296 }
05864da7
DS
10297 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10298 if (json_paths) {
10299 json_object_boolean_true_add(json_path, "aggregated");
10300 json_object_boolean_true_add(json_path, "local");
10301 } else {
10302 vty_out(vty, ", aggregated, local");
10303 }
10304 } else if (path->type != ZEBRA_ROUTE_BGP) {
10305 if (json_paths)
10306 json_object_boolean_true_add(json_path, "sourced");
10307 else
10308 vty_out(vty, ", sourced");
10309 } else {
10310 if (json_paths) {
10311 json_object_boolean_true_add(json_path, "sourced");
10312 json_object_boolean_true_add(json_path, "local");
10313 } else {
10314 vty_out(vty, ", sourced, local");
d62a17ae 10315 }
05864da7 10316 }
718e3744 10317
05864da7 10318 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10319 if (json_paths)
05864da7
DS
10320 json_object_boolean_true_add(json_path,
10321 "atomicAggregate");
d62a17ae 10322 else
05864da7
DS
10323 vty_out(vty, ", atomic-aggregate");
10324 }
d62a17ae 10325
05864da7
DS
10326 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10327 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10328 && bgp_path_info_mpath_count(path))) {
10329 if (json_paths)
10330 json_object_boolean_true_add(json_path, "multipath");
10331 else
10332 vty_out(vty, ", multipath");
10333 }
50e05855 10334
05864da7
DS
10335 // Mark the bestpath(s)
10336 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10337 first_as = aspath_get_first_as(attr->aspath);
718e3744 10338
05864da7
DS
10339 if (json_paths) {
10340 if (!json_bestpath)
10341 json_bestpath = json_object_new_object();
10342 json_object_int_add(json_bestpath, "bestpathFromAs",
10343 first_as);
10344 } else {
10345 if (first_as)
10346 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10347 else
05864da7 10348 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10349 }
05864da7 10350 }
718e3744 10351
05864da7
DS
10352 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10353 if (json_paths) {
10354 if (!json_bestpath)
10355 json_bestpath = json_object_new_object();
10356 json_object_boolean_true_add(json_bestpath, "overall");
10357 json_object_string_add(
10358 json_bestpath, "selectionReason",
10359 bgp_path_selection_reason2str(bn->reason));
10360 } else {
10361 vty_out(vty, ", best");
10362 vty_out(vty, " (%s)",
10363 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10364 }
05864da7 10365 }
718e3744 10366
4027d19b 10367 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10368 if (json_paths)
10369 json_object_string_add(
10370 json_path, "rpkiValidationState",
4027d19b 10371 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10372 else
1d327209 10373 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10374 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10375 }
10376
05864da7
DS
10377 if (json_bestpath)
10378 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10379
05864da7
DS
10380 if (!json_paths)
10381 vty_out(vty, "\n");
10382
10383 /* Line 4 display Community */
29e72930 10384 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10385 if (json_paths) {
10386 if (!attr->community->json)
10387 community_str(attr->community, true);
10388 json_object_lock(attr->community->json);
10389 json_object_object_add(json_path, "community",
10390 attr->community->json);
10391 } else {
10392 vty_out(vty, " Community: %s\n",
10393 attr->community->str);
d62a17ae 10394 }
05864da7 10395 }
718e3744 10396
05864da7
DS
10397 /* Line 5 display Extended-community */
10398 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10399 if (json_paths) {
10400 json_ext_community = json_object_new_object();
10401 json_object_string_add(json_ext_community, "string",
10402 attr->ecommunity->str);
10403 json_object_object_add(json_path, "extendedCommunity",
10404 json_ext_community);
d62a17ae 10405 } else {
05864da7
DS
10406 vty_out(vty, " Extended Community: %s\n",
10407 attr->ecommunity->str);
d62a17ae 10408 }
05864da7 10409 }
718e3744 10410
05864da7
DS
10411 /* Line 6 display Large community */
10412 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10413 if (json_paths) {
10414 if (!attr->lcommunity->json)
10415 lcommunity_str(attr->lcommunity, true);
10416 json_object_lock(attr->lcommunity->json);
10417 json_object_object_add(json_path, "largeCommunity",
10418 attr->lcommunity->json);
10419 } else {
10420 vty_out(vty, " Large Community: %s\n",
10421 attr->lcommunity->str);
d62a17ae 10422 }
05864da7 10423 }
718e3744 10424
05864da7
DS
10425 /* Line 7 display Originator, Cluster-id */
10426 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10427 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10428 char buf[BUFSIZ] = {0};
10429
05864da7 10430 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10431 if (json_paths)
05864da7
DS
10432 json_object_string_add(
10433 json_path, "originatorId",
23d0a753
DA
10434 inet_ntop(AF_INET, &attr->originator_id,
10435 buf, sizeof(buf)));
d62a17ae 10436 else
23d0a753
DA
10437 vty_out(vty, " Originator: %pI4",
10438 &attr->originator_id);
d62a17ae 10439 }
856ca177 10440
05864da7 10441 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10442 struct cluster_list *cluster =
10443 bgp_attr_get_cluster(attr);
05864da7 10444 int i;
d62a17ae 10445
10446 if (json_paths) {
05864da7
DS
10447 json_cluster_list = json_object_new_object();
10448 json_cluster_list_list =
10449 json_object_new_array();
10450
779fee93 10451 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10452 json_string = json_object_new_string(
779fee93
DS
10453 inet_ntop(AF_INET,
10454 &cluster->list[i],
10455 buf, sizeof(buf)));
05864da7
DS
10456 json_object_array_add(
10457 json_cluster_list_list,
10458 json_string);
10459 }
718e3744 10460
05864da7
DS
10461 /*
10462 * struct cluster_list does not have
10463 * "str" variable like aspath and community
10464 * do. Add this someday if someone asks
10465 * for it.
10466 * json_object_string_add(json_cluster_list,
779fee93 10467 * "string", cluster->str);
05864da7
DS
10468 */
10469 json_object_object_add(json_cluster_list,
10470 "list",
10471 json_cluster_list_list);
10472 json_object_object_add(json_path, "clusterList",
10473 json_cluster_list);
0dc8ee70 10474 } else {
05864da7
DS
10475 vty_out(vty, ", Cluster list: ");
10476
779fee93 10477 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10478 vty_out(vty, "%pI4 ",
779fee93 10479 &cluster->list[i]);
05864da7 10480 }
0dc8ee70 10481 }
d62a17ae 10482 }
718e3744 10483
d62a17ae 10484 if (!json_paths)
10485 vty_out(vty, "\n");
05864da7 10486 }
d62a17ae 10487
05864da7 10488 if (path->extra && path->extra->damp_info)
b4f7f45b 10489 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10490
05864da7
DS
10491 /* Remote Label */
10492 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10493 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10494 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10495
05864da7
DS
10496 if (json_paths)
10497 json_object_int_add(json_path, "remoteLabel", label);
10498 else
10499 vty_out(vty, " Remote label: %d\n", label);
10500 }
d62a17ae 10501
e496b420
HS
10502 /* Remote SID */
10503 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10504 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10505 if (json_paths)
10506 json_object_string_add(json_path, "remoteSid", buf);
10507 else
10508 vty_out(vty, " Remote SID: %s\n", buf);
10509 }
10510
05864da7
DS
10511 /* Label Index */
10512 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10513 if (json_paths)
10514 json_object_int_add(json_path, "labelIndex",
10515 attr->label_index);
10516 else
10517 vty_out(vty, " Label Index: %d\n",
10518 attr->label_index);
10519 }
d62a17ae 10520
05864da7
DS
10521 /* Line 8 display Addpath IDs */
10522 if (path->addpath_rx_id
10523 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10524 if (json_paths) {
10525 json_object_int_add(json_path, "addpathRxId",
10526 path->addpath_rx_id);
d62a17ae 10527
05864da7
DS
10528 /* Keep backwards compatibility with the old API
10529 * by putting TX All's ID in the old field
10530 */
10531 json_object_int_add(
10532 json_path, "addpathTxId",
10533 path->tx_addpath
10534 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10535
05864da7
DS
10536 /* ... but create a specific field for each
10537 * strategy
10538 */
10539 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10540 json_object_int_add(
10541 json_path,
10542 bgp_addpath_names(i)->id_json_name,
10543 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10544 }
05864da7
DS
10545 } else {
10546 vty_out(vty, " AddPath ID: RX %u, ",
10547 path->addpath_rx_id);
d62a17ae 10548
05864da7 10549 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10550 }
05864da7 10551 }
520d5d76 10552
05864da7
DS
10553 /* If we used addpath to TX a non-bestpath we need to display
10554 * "Advertised to" on a path-by-path basis
10555 */
10556 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10557 first = 1;
dcc68b5e 10558
05864da7
DS
10559 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10560 addpath_capable =
10561 bgp_addpath_encode_tx(peer, afi, safi);
10562 has_adj = bgp_adj_out_lookup(
10563 peer, path->net,
10564 bgp_addpath_id_for_peer(peer, afi, safi,
10565 &path->tx_addpath));
10566
10567 if ((addpath_capable && has_adj)
10568 || (!addpath_capable && has_adj
10569 && CHECK_FLAG(path->flags,
10570 BGP_PATH_SELECTED))) {
10571 if (json_path && !json_adv_to)
10572 json_adv_to = json_object_new_object();
dcc68b5e 10573
05864da7
DS
10574 route_vty_out_advertised_to(
10575 vty, peer, &first,
10576 " Advertised to:", json_adv_to);
d62a17ae 10577 }
10578 }
718e3744 10579
05864da7
DS
10580 if (json_path) {
10581 if (json_adv_to) {
10582 json_object_object_add(
10583 json_path, "advertisedTo", json_adv_to);
d62a17ae 10584 }
05864da7
DS
10585 } else {
10586 if (!first) {
10587 vty_out(vty, "\n");
d62a17ae 10588 }
10589 }
05864da7 10590 }
b05a1c8b 10591
05864da7
DS
10592 /* Line 9 display Uptime */
10593 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10594 if (json_paths) {
10595 json_last_update = json_object_new_object();
10596 json_object_int_add(json_last_update, "epoch", tbuf);
10597 json_object_string_add(json_last_update, "string",
10598 ctime(&tbuf));
10599 json_object_object_add(json_path, "lastUpdate",
10600 json_last_update);
10601 } else
10602 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10603
05864da7
DS
10604 /* Line 10 display PMSI tunnel attribute, if present */
10605 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10606 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10607 bgp_attr_get_pmsi_tnl_type(attr),
10608 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10609
05864da7
DS
10610 if (json_paths) {
10611 json_pmsi = json_object_new_object();
10612 json_object_string_add(json_pmsi, "tunnelType", str);
10613 json_object_int_add(json_pmsi, "label",
10614 label2vni(&attr->label));
10615 json_object_object_add(json_path, "pmsi", json_pmsi);
10616 } else
10617 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10618 str, label2vni(&attr->label));
d62a17ae 10619 }
f1aa5d8a 10620
92269aa2
DS
10621 /* Output some debug about internal state of the dest flags */
10622 if (json_paths) {
10623 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10624 json_object_boolean_true_add(json_path, "processScheduled");
10625 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10626 json_object_boolean_true_add(json_path, "userCleared");
10627 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10628 json_object_boolean_true_add(json_path, "labelChanged");
10629 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10630 json_object_boolean_true_add(json_path, "registeredForLabel");
10631 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10632 json_object_boolean_true_add(json_path, "selectDefered");
10633 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10634 json_object_boolean_true_add(json_path, "fibInstalled");
10635 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10636 json_object_boolean_true_add(json_path, "fibPending");
10637 }
10638
d62a17ae 10639 /* We've constructed the json object for this path, add it to the json
10640 * array of paths
10641 */
10642 if (json_paths) {
10643 if (json_nexthop_global || json_nexthop_ll) {
10644 json_nexthops = json_object_new_array();
f1aa5d8a 10645
d62a17ae 10646 if (json_nexthop_global)
10647 json_object_array_add(json_nexthops,
10648 json_nexthop_global);
f1aa5d8a 10649
d62a17ae 10650 if (json_nexthop_ll)
10651 json_object_array_add(json_nexthops,
10652 json_nexthop_ll);
f1aa5d8a 10653
d62a17ae 10654 json_object_object_add(json_path, "nexthops",
10655 json_nexthops);
10656 }
10657
10658 json_object_object_add(json_path, "peer", json_peer);
10659 json_object_array_add(json_paths, json_path);
05864da7 10660 }
b366b518
BB
10661}
10662
96ade3ed 10663#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10664#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10665#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10666
d62a17ae 10667static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10668 const char *prefix_list_str, afi_t afi,
10669 safi_t safi, enum bgp_show_type type);
10670static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10671 const char *filter, afi_t afi, safi_t safi,
10672 enum bgp_show_type type);
10673static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10674 const char *rmap_str, afi_t afi, safi_t safi,
10675 enum bgp_show_type type);
10676static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10677 const char *com, int exact, afi_t afi,
10678 safi_t safi);
10679static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10680 const char *prefix, afi_t afi, safi_t safi,
10681 enum bgp_show_type type);
a4d82a8a 10682static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10683 afi_t afi, safi_t safi, enum bgp_show_type type,
10684 bool use_json);
7f323236
DW
10685static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10686 const char *comstr, int exact, afi_t afi,
96c81f66 10687 safi_t safi, uint16_t show_flags);
d62a17ae 10688
1ae44dfc 10689static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10690 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10691 void *output_arg, char *rd, int is_last,
10692 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10693 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10694 enum rpki_states rpki_target_state)
d62a17ae 10695{
40381db7 10696 struct bgp_path_info *pi;
9bcb3eef 10697 struct bgp_dest *dest;
d62a17ae 10698 int header = 1;
10699 int display;
1ae44dfc
LB
10700 unsigned long output_count = 0;
10701 unsigned long total_count = 0;
d62a17ae 10702 struct prefix *p;
d62a17ae 10703 json_object *json_paths = NULL;
10704 int first = 1;
96f3485c
MK
10705 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10706 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10707 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10708
1ae44dfc
LB
10709 if (output_cum && *output_cum != 0)
10710 header = 0;
10711
9386b588 10712 if (use_json && !*json_header_depth) {
96f3485c
MK
10713 if (all)
10714 *json_header_depth = 1;
10715 else {
10716 vty_out(vty, "{\n");
10717 *json_header_depth = 2;
10718 }
10719
d62a17ae 10720 vty_out(vty,
23d0a753
DA
10721 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10722 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10723 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10724 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10725 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10726 ? VRF_DEFAULT_NAME
10727 : bgp->name,
10728 table->version, &bgp->router_id,
01eced22 10729 bgp->default_local_pref, bgp->as);
9386b588 10730 if (rd) {
445c2480 10731 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10732 ++*json_header_depth;
10733 }
d62a17ae 10734 }
718e3744 10735
445c2480
DS
10736 if (use_json && rd) {
10737 vty_out(vty, " \"%s\" : { ", rd);
10738 }
10739
d62a17ae 10740 /* Start processing of routes. */
9bcb3eef
DS
10741 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10742 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10743 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10744
9bcb3eef 10745 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10746 if (pi == NULL)
98ce9a06 10747 continue;
d62a17ae 10748
98ce9a06 10749 display = 0;
98ce9a06
DS
10750 if (use_json)
10751 json_paths = json_object_new_array();
10752 else
10753 json_paths = NULL;
d62a17ae 10754
6f94b685 10755 for (; pi; pi = pi->next) {
98ce9a06 10756 total_count++;
1e2ce4f1 10757
7d3cae70
DA
10758 if (type == bgp_show_type_prefix_version) {
10759 uint32_t version =
10760 strtoul(output_arg, NULL, 10);
10761 if (dest->version < version)
10762 continue;
10763 }
10764
a70a28a5
DA
10765 if (type == bgp_show_type_community_alias) {
10766 char *alias = output_arg;
10767 char **communities;
10768 int num;
10769 bool found = false;
10770
10771 if (pi->attr->community) {
10772 frrstr_split(pi->attr->community->str,
10773 " ", &communities, &num);
10774 for (int i = 0; i < num; i++) {
10775 const char *com2alias =
10776 bgp_community2alias(
10777 communities[i]);
cd9cc0e6
IR
10778 if (!found
10779 && strcmp(alias, com2alias)
10780 == 0)
a70a28a5 10781 found = true;
cd9cc0e6
IR
10782 XFREE(MTYPE_TMP,
10783 communities[i]);
a70a28a5 10784 }
cd9cc0e6 10785 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10786 }
10787
10788 if (!found && pi->attr->lcommunity) {
10789 frrstr_split(pi->attr->lcommunity->str,
10790 " ", &communities, &num);
10791 for (int i = 0; i < num; i++) {
10792 const char *com2alias =
10793 bgp_community2alias(
10794 communities[i]);
cd9cc0e6
IR
10795 if (!found
10796 && strcmp(alias, com2alias)
10797 == 0)
a70a28a5 10798 found = true;
cd9cc0e6
IR
10799 XFREE(MTYPE_TMP,
10800 communities[i]);
a70a28a5 10801 }
cd9cc0e6 10802 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10803 }
10804
10805 if (!found)
10806 continue;
10807 }
10808
1e2ce4f1
DS
10809 if (type == bgp_show_type_rpki) {
10810 if (dest_p->family == AF_INET
10811 || dest_p->family == AF_INET6)
4027d19b 10812 rpki_curr_state = hook_call(
1e2ce4f1
DS
10813 bgp_rpki_prefix_status,
10814 pi->peer, pi->attr, dest_p);
4027d19b
DS
10815 if (rpki_target_state != RPKI_NOT_BEING_USED
10816 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10817 continue;
10818 }
10819
98ce9a06
DS
10820 if (type == bgp_show_type_flap_statistics
10821 || type == bgp_show_type_flap_neighbor
10822 || type == bgp_show_type_dampend_paths
10823 || type == bgp_show_type_damp_neighbor) {
40381db7 10824 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10825 continue;
10826 }
10827 if (type == bgp_show_type_regexp) {
10828 regex_t *regex = output_arg;
d62a17ae 10829
40381db7 10830 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10831 == REG_NOMATCH)
10832 continue;
10833 }
10834 if (type == bgp_show_type_prefix_list) {
10835 struct prefix_list *plist = output_arg;
d62a17ae 10836
9bcb3eef 10837 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10838 != PREFIX_PERMIT)
10839 continue;
10840 }
10841 if (type == bgp_show_type_filter_list) {
10842 struct as_list *as_list = output_arg;
d62a17ae 10843
40381db7 10844 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10845 != AS_FILTER_PERMIT)
10846 continue;
10847 }
10848 if (type == bgp_show_type_route_map) {
10849 struct route_map *rmap = output_arg;
9b6d8fcf 10850 struct bgp_path_info path;
98ce9a06 10851 struct attr dummy_attr;
b68885f9 10852 route_map_result_t ret;
d62a17ae 10853
6f4f49b2 10854 dummy_attr = *pi->attr;
d62a17ae 10855
40381db7 10856 path.peer = pi->peer;
9b6d8fcf 10857 path.attr = &dummy_attr;
d62a17ae 10858
1782514f 10859 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 10860 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
10861 if (ret == RMAP_DENYMATCH)
10862 continue;
10863 }
10864 if (type == bgp_show_type_neighbor
10865 || type == bgp_show_type_flap_neighbor
10866 || type == bgp_show_type_damp_neighbor) {
10867 union sockunion *su = output_arg;
10868
40381db7
DS
10869 if (pi->peer == NULL
10870 || pi->peer->su_remote == NULL
10871 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10872 continue;
10873 }
10874 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10875 uint32_t destination;
d62a17ae 10876
9bcb3eef 10877 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10878 if (IN_CLASSC(destination)
9bcb3eef 10879 && dest_p->prefixlen == 24)
98ce9a06
DS
10880 continue;
10881 if (IN_CLASSB(destination)
9bcb3eef 10882 && dest_p->prefixlen == 16)
98ce9a06
DS
10883 continue;
10884 if (IN_CLASSA(destination)
9bcb3eef 10885 && dest_p->prefixlen == 8)
98ce9a06
DS
10886 continue;
10887 }
10888 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10889 p = output_arg;
9bcb3eef 10890 if (!prefix_match(p, dest_p))
98ce9a06
DS
10891 continue;
10892 }
10893 if (type == bgp_show_type_community_all) {
40381db7 10894 if (!pi->attr->community)
98ce9a06
DS
10895 continue;
10896 }
10897 if (type == bgp_show_type_community) {
10898 struct community *com = output_arg;
d62a17ae 10899
40381db7
DS
10900 if (!pi->attr->community
10901 || !community_match(pi->attr->community,
98ce9a06
DS
10902 com))
10903 continue;
10904 }
10905 if (type == bgp_show_type_community_exact) {
10906 struct community *com = output_arg;
d62a17ae 10907
40381db7
DS
10908 if (!pi->attr->community
10909 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10910 continue;
10911 }
10912 if (type == bgp_show_type_community_list) {
10913 struct community_list *list = output_arg;
d62a17ae 10914
40381db7 10915 if (!community_list_match(pi->attr->community,
a4d82a8a 10916 list))
98ce9a06
DS
10917 continue;
10918 }
a4d82a8a 10919 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10920 struct community_list *list = output_arg;
d62a17ae 10921
98ce9a06 10922 if (!community_list_exact_match(
40381db7 10923 pi->attr->community, list))
98ce9a06
DS
10924 continue;
10925 }
10926 if (type == bgp_show_type_lcommunity) {
10927 struct lcommunity *lcom = output_arg;
d62a17ae 10928
40381db7
DS
10929 if (!pi->attr->lcommunity
10930 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10931 lcom))
10932 continue;
10933 }
36a206db 10934
10935 if (type == bgp_show_type_lcommunity_exact) {
10936 struct lcommunity *lcom = output_arg;
10937
10938 if (!pi->attr->lcommunity
10939 || !lcommunity_cmp(pi->attr->lcommunity,
10940 lcom))
10941 continue;
10942 }
98ce9a06
DS
10943 if (type == bgp_show_type_lcommunity_list) {
10944 struct community_list *list = output_arg;
d62a17ae 10945
40381db7 10946 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10947 list))
98ce9a06
DS
10948 continue;
10949 }
36a206db 10950 if (type
10951 == bgp_show_type_lcommunity_list_exact) {
10952 struct community_list *list = output_arg;
10953
10954 if (!lcommunity_list_exact_match(
10955 pi->attr->lcommunity, list))
10956 continue;
10957 }
98ce9a06 10958 if (type == bgp_show_type_lcommunity_all) {
40381db7 10959 if (!pi->attr->lcommunity)
98ce9a06
DS
10960 continue;
10961 }
10962 if (type == bgp_show_type_dampend_paths
10963 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10964 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10965 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10966 continue;
10967 }
10968
10969 if (!use_json && header) {
23d0a753
DA
10970 vty_out(vty,
10971 "BGP table version is %" PRIu64
10972 ", local router ID is %pI4, vrf id ",
10973 table->version, &bgp->router_id);
9df8b37c
PZ
10974 if (bgp->vrf_id == VRF_UNKNOWN)
10975 vty_out(vty, "%s", VRFID_NONE_STR);
10976 else
10977 vty_out(vty, "%u", bgp->vrf_id);
10978 vty_out(vty, "\n");
01eced22
AD
10979 vty_out(vty, "Default local pref %u, ",
10980 bgp->default_local_pref);
10981 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10982 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10983 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10984 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 10985 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 10986 if (type == bgp_show_type_dampend_paths
10987 || type == bgp_show_type_damp_neighbor)
98ce9a06 10988 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10989 else if (type == bgp_show_type_flap_statistics
10990 || type == bgp_show_type_flap_neighbor)
98ce9a06 10991 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10992 else
ae248832
MK
10993 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10994 : BGP_SHOW_HEADER));
98ce9a06 10995 header = 0;
d62a17ae 10996 }
98ce9a06
DS
10997 if (rd != NULL && !display && !output_count) {
10998 if (!use_json)
10999 vty_out(vty,
11000 "Route Distinguisher: %s\n",
11001 rd);
d62a17ae 11002 }
98ce9a06
DS
11003 if (type == bgp_show_type_dampend_paths
11004 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11005 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11006 AFI_IP, safi, use_json,
11007 json_paths);
98ce9a06
DS
11008 else if (type == bgp_show_type_flap_statistics
11009 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11010 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11011 AFI_IP, safi, use_json,
11012 json_paths);
f280c93b
DA
11013 else {
11014 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11015 route_vty_out_detail(
11016 vty, bgp, dest, pi,
11017 family2afi(dest_p->family),
11018 safi, RPKI_NOT_BEING_USED,
11019 json_paths);
11020 else
11021 route_vty_out(vty, dest_p, pi, display,
11022 safi, json_paths, wide);
11023 }
98ce9a06 11024 display++;
d62a17ae 11025 }
11026
98ce9a06
DS
11027 if (display) {
11028 output_count++;
11029 if (!use_json)
11030 continue;
11031
625d2931 11032 /* encode prefix */
9bcb3eef 11033 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11034 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11035
1840384b 11036
b54892e0
DS
11037 bgp_fs_nlri_get_string(
11038 (unsigned char *)
9bcb3eef
DS
11039 dest_p->u.prefix_flowspec.ptr,
11040 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11041 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11042 family2afi(dest_p->u
11043 .prefix_flowspec.family));
625d2931 11044 if (first)
b54892e0 11045 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11046 dest_p->u.prefix_flowspec
b54892e0 11047 .prefixlen);
625d2931 11048 else
b54892e0 11049 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11050 dest_p->u.prefix_flowspec
b54892e0 11051 .prefixlen);
625d2931 11052 } else {
625d2931 11053 if (first)
1b78780b 11054 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11055 else
1b78780b 11056 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11057 }
98ce9a06 11058 vty_out(vty, "%s",
f4ec52f7
DA
11059 json_object_to_json_string_ext(
11060 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11061 json_object_free(json_paths);
449feb8e 11062 json_paths = NULL;
98ce9a06 11063 first = 0;
1f83ed02
DS
11064 } else
11065 json_object_free(json_paths);
98ce9a06
DS
11066 }
11067
1ae44dfc
LB
11068 if (output_cum) {
11069 output_count += *output_cum;
11070 *output_cum = output_count;
11071 }
11072 if (total_cum) {
11073 total_count += *total_cum;
11074 *total_cum = total_count;
11075 }
d62a17ae 11076 if (use_json) {
9386b588 11077 if (rd) {
a4d82a8a 11078 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11079 }
11080 if (is_last) {
a4d82a8a
PZ
11081 unsigned long i;
11082 for (i = 0; i < *json_header_depth; ++i)
11083 vty_out(vty, " } ");
96f3485c
MK
11084 if (!all)
11085 vty_out(vty, "\n");
9386b588 11086 }
d62a17ae 11087 } else {
1ae44dfc
LB
11088 if (is_last) {
11089 /* No route is displayed */
11090 if (output_count == 0) {
11091 if (type == bgp_show_type_normal)
11092 vty_out(vty,
11093 "No BGP prefixes displayed, %ld exist\n",
11094 total_count);
11095 } else
d62a17ae 11096 vty_out(vty,
1ae44dfc
LB
11097 "\nDisplayed %ld routes and %ld total paths\n",
11098 output_count, total_count);
11099 }
d62a17ae 11100 }
718e3744 11101
d62a17ae 11102 return CMD_SUCCESS;
718e3744 11103}
11104
1ae44dfc
LB
11105int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11106 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11107 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11108{
9bcb3eef 11109 struct bgp_dest *dest, *next;
1ae44dfc
LB
11110 unsigned long output_cum = 0;
11111 unsigned long total_cum = 0;
9386b588 11112 unsigned long json_header_depth = 0;
67009e22 11113 struct bgp_table *itable;
0136788c 11114 bool show_msg;
96c81f66 11115 uint16_t show_flags = 0;
0136788c
LB
11116
11117 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11118
96f3485c
MK
11119 if (use_json)
11120 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11121
9bcb3eef
DS
11122 for (dest = bgp_table_top(table); dest; dest = next) {
11123 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11124
9bcb3eef
DS
11125 next = bgp_route_next(dest);
11126 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11127 continue;
67009e22 11128
9bcb3eef 11129 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11130 if (itable != NULL) {
1ae44dfc 11131 struct prefix_rd prd;
06b9f471 11132 char rd[RD_ADDRSTRLEN];
1ae44dfc 11133
9bcb3eef 11134 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11135 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11136 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11137 rd, next == NULL, &output_cum,
11138 &total_cum, &json_header_depth,
1e2ce4f1 11139 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11140 if (next == NULL)
11141 show_msg = false;
1ae44dfc
LB
11142 }
11143 }
0136788c
LB
11144 if (show_msg) {
11145 if (output_cum == 0)
11146 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11147 total_cum);
11148 else
11149 vty_out(vty,
11150 "\nDisplayed %ld routes and %ld total paths\n",
11151 output_cum, total_cum);
11152 }
1ae44dfc
LB
11153 return CMD_SUCCESS;
11154}
d62a17ae 11155static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11156 enum bgp_show_type type, void *output_arg,
96c81f66 11157 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11158{
d62a17ae 11159 struct bgp_table *table;
9386b588 11160 unsigned long json_header_depth = 0;
96f3485c 11161 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11162
d62a17ae 11163 if (bgp == NULL) {
11164 bgp = bgp_get_default();
11165 }
fee0f4c6 11166
d62a17ae 11167 if (bgp == NULL) {
11168 if (!use_json)
11169 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11170 else
11171 vty_out(vty, "{}\n");
d62a17ae 11172 return CMD_WARNING;
11173 }
4dd6177e 11174
cd8c2a27
MS
11175 /* Labeled-unicast routes live in the unicast table. */
11176 if (safi == SAFI_LABELED_UNICAST)
11177 safi = SAFI_UNICAST;
11178
1ae44dfc 11179 table = bgp->rib[afi][safi];
d62a17ae 11180 /* use MPLS and ENCAP specific shows until they are merged */
11181 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11182 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11183 output_arg, use_json);
d62a17ae 11184 }
dba3c1d3
PG
11185
11186 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11187 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11188 output_arg, use_json,
11189 1, NULL, NULL);
11190 }
fee0f4c6 11191
96f3485c 11192 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11193 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11194 rpki_target_state);
fee0f4c6 11195}
11196
d62a17ae 11197static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11198 safi_t safi, uint16_t show_flags)
f186de26 11199{
d62a17ae 11200 struct listnode *node, *nnode;
11201 struct bgp *bgp;
11202 int is_first = 1;
9f049418 11203 bool route_output = false;
96f3485c 11204 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11205
d62a17ae 11206 if (use_json)
11207 vty_out(vty, "{\n");
9f689658 11208
d62a17ae 11209 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11210 route_output = true;
d62a17ae 11211 if (use_json) {
11212 if (!is_first)
11213 vty_out(vty, ",\n");
11214 else
11215 is_first = 0;
11216
11217 vty_out(vty, "\"%s\":",
11218 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11219 ? VRF_DEFAULT_NAME
d62a17ae 11220 : bgp->name);
11221 } else {
11222 vty_out(vty, "\nInstance %s:\n",
11223 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11224 ? VRF_DEFAULT_NAME
d62a17ae 11225 : bgp->name);
11226 }
11227 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11228 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11229 }
9f689658 11230
d62a17ae 11231 if (use_json)
11232 vty_out(vty, "}\n");
9f049418
DS
11233 else if (!route_output)
11234 vty_out(vty, "%% BGP instance not found\n");
f186de26 11235}
11236
718e3744 11237/* Header of detailed BGP route information */
d62a17ae 11238void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11239 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11240 afi_t afi, safi_t safi, json_object *json)
11241{
40381db7 11242 struct bgp_path_info *pi;
b54892e0 11243 const struct prefix *p;
d62a17ae 11244 struct peer *peer;
11245 struct listnode *node, *nnode;
06b9f471 11246 char buf1[RD_ADDRSTRLEN];
0291c246 11247 char prefix_str[BUFSIZ];
d62a17ae 11248 int count = 0;
11249 int best = 0;
11250 int suppress = 0;
c5f1e1b2
C
11251 int accept_own = 0;
11252 int route_filter_translated_v4 = 0;
11253 int route_filter_v4 = 0;
11254 int route_filter_translated_v6 = 0;
11255 int route_filter_v6 = 0;
11256 int llgr_stale = 0;
11257 int no_llgr = 0;
11258 int accept_own_nexthop = 0;
11259 int blackhole = 0;
d62a17ae 11260 int no_export = 0;
11261 int no_advertise = 0;
11262 int local_as = 0;
c5f1e1b2 11263 int no_peer = 0;
d62a17ae 11264 int first = 1;
11265 int has_valid_label = 0;
11266 mpls_label_t label = 0;
11267 json_object *json_adv_to = NULL;
9bedbb1e 11268
9bcb3eef
DS
11269 p = bgp_dest_get_prefix(dest);
11270 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11271
11272 if (has_valid_label)
9bcb3eef 11273 label = label_pton(&dest->local_label);
d62a17ae 11274
44c69747 11275 if (safi == SAFI_EVPN) {
d62a17ae 11276
44c69747 11277 if (!json) {
2dbe669b 11278 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11279 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11280 : "",
2dbe669b 11281 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11282 } else {
11283 json_object_string_add(json, "rd",
11284 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11285 "");
11286 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11287 }
11288 } else {
11289 if (!json) {
9119ef3a
DA
11290 vty_out(vty,
11291 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11292 "\n",
d62a17ae 11293 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11294 ? prefix_rd2str(prd, buf1,
11295 sizeof(buf1))
11296 : ""),
9119ef3a
DA
11297 safi == SAFI_MPLS_VPN ? ":" : "", p,
11298 dest->version);
cd1964ff 11299
9119ef3a 11300 } else {
44c69747
LK
11301 json_object_string_add(json, "prefix",
11302 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11303 json_object_int_add(json, "version", dest->version);
11304
11305 }
44c69747
LK
11306 }
11307
11308 if (has_valid_label) {
11309 if (json)
11310 json_object_int_add(json, "localLabel", label);
11311 else
d62a17ae 11312 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11313 }
11314
11315 if (!json)
d62a17ae 11316 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11317 vty_out(vty, "not allocated\n");
718e3744 11318
9bcb3eef 11319 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11320 count++;
40381db7 11321 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11322 best = count;
4056a5f6 11323 if (bgp_path_suppressed(pi))
d62a17ae 11324 suppress = 1;
cee9c031 11325
40381db7 11326 if (pi->attr->community == NULL)
cee9c031
QY
11327 continue;
11328
11329 no_advertise += community_include(
40381db7
DS
11330 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11331 no_export += community_include(pi->attr->community,
cee9c031 11332 COMMUNITY_NO_EXPORT);
40381db7 11333 local_as += community_include(pi->attr->community,
cee9c031 11334 COMMUNITY_LOCAL_AS);
40381db7 11335 accept_own += community_include(pi->attr->community,
cee9c031
QY
11336 COMMUNITY_ACCEPT_OWN);
11337 route_filter_translated_v4 += community_include(
40381db7 11338 pi->attr->community,
cee9c031
QY
11339 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11340 route_filter_translated_v6 += community_include(
40381db7 11341 pi->attr->community,
cee9c031
QY
11342 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11343 route_filter_v4 += community_include(
40381db7 11344 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11345 route_filter_v6 += community_include(
40381db7
DS
11346 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11347 llgr_stale += community_include(pi->attr->community,
cee9c031 11348 COMMUNITY_LLGR_STALE);
40381db7 11349 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11350 COMMUNITY_NO_LLGR);
11351 accept_own_nexthop +=
40381db7 11352 community_include(pi->attr->community,
cee9c031 11353 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11354 blackhole += community_include(pi->attr->community,
cee9c031 11355 COMMUNITY_BLACKHOLE);
40381db7 11356 no_peer += community_include(pi->attr->community,
cee9c031 11357 COMMUNITY_NO_PEER);
d62a17ae 11358 }
718e3744 11359 }
718e3744 11360
d62a17ae 11361 if (!json) {
11362 vty_out(vty, "Paths: (%d available", count);
11363 if (best) {
11364 vty_out(vty, ", best #%d", best);
b84060bb
PG
11365 if (safi == SAFI_UNICAST) {
11366 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11367 vty_out(vty, ", table %s",
11368 VRF_DEFAULT_NAME);
11369 else
11370 vty_out(vty, ", vrf %s",
11371 bgp->name);
11372 }
d62a17ae 11373 } else
11374 vty_out(vty, ", no best path");
11375
c5f1e1b2
C
11376 if (accept_own)
11377 vty_out(vty,
11378 ", accept own local route exported and imported in different VRF");
11379 else if (route_filter_translated_v4)
11380 vty_out(vty,
11381 ", mark translated RTs for VPNv4 route filtering");
11382 else if (route_filter_v4)
11383 vty_out(vty,
11384 ", attach RT as-is for VPNv4 route filtering");
11385 else if (route_filter_translated_v6)
11386 vty_out(vty,
11387 ", mark translated RTs for VPNv6 route filtering");
11388 else if (route_filter_v6)
11389 vty_out(vty,
11390 ", attach RT as-is for VPNv6 route filtering");
11391 else if (llgr_stale)
11392 vty_out(vty,
11393 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11394 else if (no_llgr)
11395 vty_out(vty,
11396 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11397 else if (accept_own_nexthop)
11398 vty_out(vty,
11399 ", accept local nexthop");
11400 else if (blackhole)
11401 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11402 else if (no_export)
11403 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11404 else if (no_advertise)
11405 vty_out(vty, ", not advertised to any peer");
d62a17ae 11406 else if (local_as)
11407 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11408 else if (no_peer)
11409 vty_out(vty,
11410 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11411
11412 if (suppress)
11413 vty_out(vty,
11414 ", Advertisements suppressed by an aggregate.");
11415 vty_out(vty, ")\n");
11416 }
718e3744 11417
d62a17ae 11418 /* If we are not using addpath then we can display Advertised to and
11419 * that will
11420 * show what peers we advertised the bestpath to. If we are using
11421 * addpath
11422 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11423 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11424 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11425 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11426 if (json && !json_adv_to)
11427 json_adv_to = json_object_new_object();
11428
11429 route_vty_out_advertised_to(
11430 vty, peer, &first,
11431 " Advertised to non peer-group peers:\n ",
11432 json_adv_to);
11433 }
11434 }
11435
11436 if (json) {
11437 if (json_adv_to) {
11438 json_object_object_add(json, "advertisedTo",
11439 json_adv_to);
11440 }
11441 } else {
11442 if (first)
11443 vty_out(vty, " Not advertised to any peer");
11444 vty_out(vty, "\n");
11445 }
11446 }
718e3744 11447}
11448
44c69747 11449static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11450 struct bgp_dest *bgp_node, struct vty *vty,
11451 struct bgp *bgp, afi_t afi, safi_t safi,
11452 json_object *json, enum bgp_path_type pathtype,
4027d19b 11453 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11454{
11455 struct bgp_path_info *pi;
11456 int header = 1;
11457 char rdbuf[RD_ADDRSTRLEN];
11458 json_object *json_header = NULL;
11459 json_object *json_paths = NULL;
4933eaaf 11460 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11461
9bcb3eef 11462 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11463 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11464
11465 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11466 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11467 pi->peer, pi->attr, p);
4933eaaf 11468
4027d19b
DS
11469 if (rpki_target_state != RPKI_NOT_BEING_USED
11470 && rpki_curr_state != rpki_target_state)
4933eaaf 11471 continue;
44c69747
LK
11472
11473 if (json && !json_paths) {
11474 /* Instantiate json_paths only if path is valid */
11475 json_paths = json_object_new_array();
11476 if (pfx_rd) {
11477 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11478 json_header = json_object_new_object();
11479 } else
11480 json_header = json;
11481 }
11482
11483 if (header) {
11484 route_vty_out_detail_header(
11485 vty, bgp, bgp_node, pfx_rd,
11486 AFI_IP, safi, json_header);
11487 header = 0;
11488 }
11489 (*display)++;
11490
11491 if (pathtype == BGP_PATH_SHOW_ALL
11492 || (pathtype == BGP_PATH_SHOW_BESTPATH
11493 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11494 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11495 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11496 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11497 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11498 safi, rpki_curr_state, json_paths);
44c69747
LK
11499 }
11500
11501 if (json && json_paths) {
11502 json_object_object_add(json_header, "paths", json_paths);
11503
11504 if (pfx_rd)
11505 json_object_object_add(json, rdbuf, json_header);
11506 }
11507}
11508
718e3744 11509/* Display specified route of BGP table. */
d62a17ae 11510static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11511 struct bgp_table *rib, const char *ip_str,
11512 afi_t afi, safi_t safi,
4027d19b 11513 enum rpki_states rpki_target_state,
d62a17ae 11514 struct prefix_rd *prd, int prefix_check,
9f049418 11515 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11516{
11517 int ret;
d62a17ae 11518 int display = 0;
11519 struct prefix match;
9bcb3eef
DS
11520 struct bgp_dest *dest;
11521 struct bgp_dest *rm;
d62a17ae 11522 struct bgp_table *table;
11523 json_object *json = NULL;
11524 json_object *json_paths = NULL;
11525
11526 /* Check IP address argument. */
11527 ret = str2prefix(ip_str, &match);
11528 if (!ret) {
11529 vty_out(vty, "address is malformed\n");
11530 return CMD_WARNING;
11531 }
718e3744 11532
d62a17ae 11533 match.family = afi2family(afi);
b05a1c8b 11534
44c69747 11535 if (use_json)
d62a17ae 11536 json = json_object_new_object();
718e3744 11537
44c69747 11538 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11539 for (dest = bgp_table_top(rib); dest;
11540 dest = bgp_route_next(dest)) {
11541 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11542
9bcb3eef 11543 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11544 continue;
9bcb3eef 11545 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11546 if (!table)
ea47320b 11547 continue;
d62a17ae 11548
4953391b
DA
11549 rm = bgp_node_match(table, &match);
11550 if (rm == NULL)
ea47320b 11551 continue;
d62a17ae 11552
9bcb3eef 11553 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11554 if (prefix_check
b54892e0 11555 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11556 bgp_dest_unlock_node(rm);
ea47320b
DL
11557 continue;
11558 }
d62a17ae 11559
9bcb3eef 11560 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11561 bgp, afi, safi, json, pathtype,
4027d19b 11562 &display, rpki_target_state);
44c69747 11563
9bcb3eef 11564 bgp_dest_unlock_node(rm);
44c69747
LK
11565 }
11566 } else if (safi == SAFI_EVPN) {
9bcb3eef 11567 struct bgp_dest *longest_pfx;
cded3b72 11568 bool is_exact_pfxlen_match = false;
44c69747 11569
9bcb3eef
DS
11570 for (dest = bgp_table_top(rib); dest;
11571 dest = bgp_route_next(dest)) {
11572 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11573
9bcb3eef 11574 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11575 continue;
9bcb3eef 11576 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11577 if (!table)
11578 continue;
11579
11580 longest_pfx = NULL;
cded3b72 11581 is_exact_pfxlen_match = false;
44c69747
LK
11582 /*
11583 * Search through all the prefixes for a match. The
11584 * pfx's are enumerated in ascending order of pfxlens.
11585 * So, the last pfx match is the longest match. Set
11586 * is_exact_pfxlen_match when we get exact pfxlen match
11587 */
11588 for (rm = bgp_table_top(table); rm;
11589 rm = bgp_route_next(rm)) {
b54892e0 11590 const struct prefix *rm_p =
9bcb3eef 11591 bgp_dest_get_prefix(rm);
44c69747
LK
11592 /*
11593 * Get prefixlen of the ip-prefix within type5
11594 * evpn route
11595 */
b54892e0
DS
11596 if (evpn_type5_prefix_match(rm_p, &match)
11597 && rm->info) {
44c69747
LK
11598 longest_pfx = rm;
11599 int type5_pfxlen =
b54892e0
DS
11600 bgp_evpn_get_type5_prefixlen(
11601 rm_p);
44c69747 11602 if (type5_pfxlen == match.prefixlen) {
cded3b72 11603 is_exact_pfxlen_match = true;
9bcb3eef 11604 bgp_dest_unlock_node(rm);
44c69747
LK
11605 break;
11606 }
d62a17ae 11607 }
11608 }
ea47320b 11609
44c69747
LK
11610 if (!longest_pfx)
11611 continue;
11612
11613 if (prefix_check && !is_exact_pfxlen_match)
11614 continue;
11615
11616 rm = longest_pfx;
9bcb3eef 11617 bgp_dest_lock_node(rm);
44c69747 11618
9bcb3eef 11619 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11620 bgp, afi, safi, json, pathtype,
4027d19b 11621 &display, rpki_target_state);
44c69747 11622
9bcb3eef 11623 bgp_dest_unlock_node(rm);
d62a17ae 11624 }
98a9dbc7 11625 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11626 if (use_json)
11627 json_paths = json_object_new_array();
11628
63a0b7a9
PG
11629 display = bgp_flowspec_display_match_per_ip(afi, rib,
11630 &match, prefix_check,
11631 vty,
11632 use_json,
11633 json_paths);
d5f20468
SP
11634 if (use_json) {
11635 if (display)
11636 json_object_object_add(json, "paths",
11637 json_paths);
11638 else
11639 json_object_free(json_paths);
11640 }
d62a17ae 11641 } else {
4953391b
DA
11642 dest = bgp_node_match(rib, &match);
11643 if (dest != NULL) {
9bcb3eef 11644 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11645 if (!prefix_check
9bcb3eef
DS
11646 || dest_p->prefixlen == match.prefixlen) {
11647 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11648 safi, json, pathtype,
4027d19b 11649 &display, rpki_target_state);
d62a17ae 11650 }
11651
9bcb3eef 11652 bgp_dest_unlock_node(dest);
d62a17ae 11653 }
11654 }
e5eee9af 11655
d62a17ae 11656 if (use_json) {
996c9314 11657 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11658 json, JSON_C_TO_STRING_PRETTY |
11659 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11660 json_object_free(json);
11661 } else {
11662 if (!display) {
11663 vty_out(vty, "%% Network not in table\n");
11664 return CMD_WARNING;
11665 }
11666 }
b05a1c8b 11667
d62a17ae 11668 return CMD_SUCCESS;
718e3744 11669}
11670
fee0f4c6 11671/* Display specified route of Main RIB */
d62a17ae 11672static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11673 afi_t afi, safi_t safi, struct prefix_rd *prd,
11674 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11675 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11676{
9b86009a 11677 if (!bgp) {
d62a17ae 11678 bgp = bgp_get_default();
9b86009a
RW
11679 if (!bgp) {
11680 if (!use_json)
11681 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11682 else
11683 vty_out(vty, "{}\n");
9b86009a
RW
11684 return CMD_WARNING;
11685 }
11686 }
d62a17ae 11687
11688 /* labeled-unicast routes live in the unicast table */
11689 if (safi == SAFI_LABELED_UNICAST)
11690 safi = SAFI_UNICAST;
11691
11692 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11693 afi, safi, rpki_target_state, prd,
8aa22bbb 11694 prefix_check, pathtype, use_json);
d62a17ae 11695}
11696
11697static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11698 struct cmd_token **argv, bool exact, afi_t afi,
11699 safi_t safi, bool uj)
d62a17ae 11700{
11701 struct lcommunity *lcom;
11702 struct buffer *b;
11703 int i;
11704 char *str;
11705 int first = 0;
96c81f66 11706 uint16_t show_flags = 0;
4f28b2b5 11707 int ret;
96f3485c
MK
11708
11709 if (uj)
11710 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11711
11712 b = buffer_new(1024);
11713 for (i = 0; i < argc; i++) {
11714 if (first)
11715 buffer_putc(b, ' ');
11716 else {
11717 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11718 first = 1;
11719 buffer_putstr(b, argv[i]->arg);
11720 }
11721 }
11722 }
11723 buffer_putc(b, '\0');
57d187bc 11724
d62a17ae 11725 str = buffer_getstr(b);
11726 buffer_free(b);
57d187bc 11727
d62a17ae 11728 lcom = lcommunity_str2com(str);
11729 XFREE(MTYPE_TMP, str);
11730 if (!lcom) {
11731 vty_out(vty, "%% Large-community malformed\n");
11732 return CMD_WARNING;
11733 }
57d187bc 11734
4f28b2b5 11735 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11736 (exact ? bgp_show_type_lcommunity_exact
11737 : bgp_show_type_lcommunity),
11738 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11739
11740 lcommunity_free(&lcom);
11741 return ret;
57d187bc
JS
11742}
11743
d62a17ae 11744static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11745 const char *lcom, bool exact, afi_t afi,
11746 safi_t safi, bool uj)
57d187bc 11747{
d62a17ae 11748 struct community_list *list;
96c81f66 11749 uint16_t show_flags = 0;
96f3485c
MK
11750
11751 if (uj)
11752 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11753
57d187bc 11754
e237b0d2 11755 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11756 LARGE_COMMUNITY_LIST_MASTER);
11757 if (list == NULL) {
11758 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11759 lcom);
11760 return CMD_WARNING;
11761 }
57d187bc 11762
36a206db 11763 return bgp_show(vty, bgp, afi, safi,
11764 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11765 : bgp_show_type_lcommunity_list),
1e2ce4f1 11766 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11767}
11768
52951b63
DS
11769DEFUN (show_ip_bgp_large_community_list,
11770 show_ip_bgp_large_community_list_cmd,
77a3a95e 11771 "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
11772 SHOW_STR
11773 IP_STR
11774 BGP_STR
11775 BGP_INSTANCE_HELP_STR
9bedbb1e 11776 BGP_AFI_HELP_STR
4dd6177e 11777 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11778 "Display routes matching the large-community-list\n"
11779 "large-community-list number\n"
11780 "large-community-list name\n"
36a206db 11781 "Exact match of the large-communities\n"
52951b63
DS
11782 JSON_STR)
11783{
d62a17ae 11784 afi_t afi = AFI_IP6;
11785 safi_t safi = SAFI_UNICAST;
11786 int idx = 0;
36a206db 11787 bool exact_match = 0;
4d678463 11788 struct bgp *bgp = NULL;
9f049418 11789 bool uj = use_json(argc, argv);
d62a17ae 11790
ef3364f0
DA
11791 if (uj)
11792 argc--;
4d678463 11793
ef3364f0
DA
11794 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11795 &bgp, uj);
11796 if (!idx)
11797 return CMD_WARNING;
d62a17ae 11798
11799 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11800
11801 const char *clist_number_or_name = argv[++idx]->arg;
11802
11803 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11804 exact_match = 1;
11805
11806 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11807 exact_match, afi, safi, uj);
52951b63
DS
11808}
11809DEFUN (show_ip_bgp_large_community,
11810 show_ip_bgp_large_community_cmd,
36a206db 11811 "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
11812 SHOW_STR
11813 IP_STR
11814 BGP_STR
11815 BGP_INSTANCE_HELP_STR
9bedbb1e 11816 BGP_AFI_HELP_STR
4dd6177e 11817 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11818 "Display routes matching the large-communities\n"
11819 "List of large-community numbers\n"
36a206db 11820 "Exact match of the large-communities\n"
52951b63
DS
11821 JSON_STR)
11822{
d62a17ae 11823 afi_t afi = AFI_IP6;
11824 safi_t safi = SAFI_UNICAST;
11825 int idx = 0;
36a206db 11826 bool exact_match = 0;
4d678463 11827 struct bgp *bgp = NULL;
9f049418 11828 bool uj = use_json(argc, argv);
96c81f66 11829 uint16_t show_flags = 0;
d62a17ae 11830
96f3485c
MK
11831 if (uj) {
11832 argc--;
11833 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11834 }
4d678463 11835
96f3485c
MK
11836 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11837 &bgp, uj);
11838 if (!idx)
11839 return CMD_WARNING;
d62a17ae 11840
36a206db 11841 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11842 if (argv_find(argv, argc, "exact-match", &idx))
11843 exact_match = 1;
11844 return bgp_show_lcommunity(vty, bgp, argc, argv,
11845 exact_match, afi, safi, uj);
11846 } else
d62a17ae 11847 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11848 bgp_show_type_lcommunity_all, NULL, show_flags,
11849 RPKI_NOT_BEING_USED);
52951b63
DS
11850}
11851
71f1613a
DA
11852static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11853 safi_t safi, struct json_object *json_array);
d62a17ae 11854static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11855 safi_t safi, struct json_object *json);
e01ca200 11856
7b2ff250 11857
9ab0cf58
PG
11858DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11859 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11860 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11861 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11862{
11863 bool uj = use_json(argc, argv);
11864 struct bgp *bgp = NULL;
ec76a1d1
DA
11865 safi_t safi = SAFI_UNICAST;
11866 afi_t afi = AFI_IP6;
4265b261 11867 int idx = 0;
6c9d22e2
PG
11868 struct json_object *json_all = NULL;
11869 struct json_object *json_afi_safi = NULL;
4265b261
PG
11870
11871 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11872 &bgp, false);
71f1613a 11873 if (!idx)
4265b261 11874 return CMD_WARNING;
6c9d22e2 11875
4265b261 11876 if (uj)
6c9d22e2 11877 json_all = json_object_new_object();
4265b261 11878
9ab0cf58
PG
11879 FOREACH_AFI_SAFI (afi, safi) {
11880 /*
11881 * So limit output to those afi/safi pairs that
11882 * actually have something interesting in them
11883 */
11884 if (strmatch(get_afi_safi_str(afi, safi, true),
11885 "Unknown")) {
11886 continue;
11887 }
11888 if (uj) {
11889 json_afi_safi = json_object_new_array();
11890 json_object_object_add(
11891 json_all,
11892 get_afi_safi_str(afi, safi, true),
11893 json_afi_safi);
11894 } else {
11895 json_afi_safi = NULL;
6c9d22e2 11896 }
9ab0cf58
PG
11897
11898 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11899 }
6c9d22e2
PG
11900
11901 if (uj) {
9ab0cf58
PG
11902 vty_out(vty, "%s",
11903 json_object_to_json_string_ext(
11904 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11905 json_object_free(json_all);
4265b261 11906 }
6c9d22e2 11907
4265b261
PG
11908 return CMD_SUCCESS;
11909}
11910
7b2ff250 11911/* BGP route print out function without JSON */
14718643
PG
11912DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11913 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11914 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11915 SHOW_STR
11916 IP_STR
11917 BGP_STR
11918 BGP_INSTANCE_HELP_STR
11919 L2VPN_HELP_STR
11920 EVPN_HELP_STR
11921 "BGP RIB advertisement statistics\n"
11922 JSON_STR)
11923{
ec76a1d1
DA
11924 afi_t afi = AFI_IP6;
11925 safi_t safi = SAFI_UNICAST;
14718643
PG
11926 struct bgp *bgp = NULL;
11927 int idx = 0, ret;
11928 bool uj = use_json(argc, argv);
11929 struct json_object *json_afi_safi = NULL, *json = NULL;
11930
11931 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11932 &bgp, false);
11933 if (!idx)
11934 return CMD_WARNING;
11935
11936 if (uj)
11937 json_afi_safi = json_object_new_array();
11938 else
11939 json_afi_safi = NULL;
11940
11941 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11942
11943 if (uj) {
11944 json = json_object_new_object();
11945 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11946 json_afi_safi);
11947 vty_out(vty, "%s", json_object_to_json_string_ext(
11948 json, JSON_C_TO_STRING_PRETTY));
11949 json_object_free(json);
11950 }
11951 return ret;
11952}
11953
893cccd0 11954/* BGP route print out function without JSON */
9ab0cf58
PG
11955DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11956 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11957 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11958 "]]\
893cccd0 11959 statistics [json]",
9ab0cf58
PG
11960 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11961 BGP_SAFI_WITH_LABEL_HELP_STR
11962 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11963{
ec76a1d1
DA
11964 afi_t afi = AFI_IP6;
11965 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11966 struct bgp *bgp = NULL;
11967 int idx = 0, ret;
11968 bool uj = use_json(argc, argv);
6c9d22e2 11969 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11970
11971 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11972 &bgp, false);
11973 if (!idx)
11974 return CMD_WARNING;
6c9d22e2 11975
893cccd0 11976 if (uj)
6c9d22e2
PG
11977 json_afi_safi = json_object_new_array();
11978 else
11979 json_afi_safi = NULL;
11980
11981 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11982
11983 if (uj) {
11984 json = json_object_new_object();
11985 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11986 json_afi_safi);
9ab0cf58
PG
11987 vty_out(vty, "%s",
11988 json_object_to_json_string_ext(
11989 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11990 json_object_free(json);
11991 }
11992 return ret;
893cccd0 11993}
7b2ff250
DW
11994
11995/* BGP route print out function without JSON */
96f3485c 11996DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11997 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11998 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11999 "]]\
96f3485c 12000 <[all$all] dampening <parameters>\
7b2ff250
DW
12001 |route-map WORD\
12002 |prefix-list WORD\
12003 |filter-list WORD\
96870ecb 12004 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
7b2ff250
DW
12005 |A.B.C.D/M longer-prefixes\
12006 |X:X::X:X/M longer-prefixes\
893cccd0 12007 >",
9ab0cf58
PG
12008 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12009 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12010 "Display the entries for all address families\n"
9ab0cf58
PG
12011 "Display detailed information about dampening\n"
12012 "Display detail of configured dampening parameters\n"
12013 "Display routes matching the route-map\n"
12014 "A route-map to match on\n"
12015 "Display routes conforming to the prefix-list\n"
12016 "Prefix-list name\n"
12017 "Display routes conforming to the filter-list\n"
12018 "Regular expression access list name\n"
12019 "Display routes matching the community-list\n"
12020 "community-list number\n"
12021 "community-list name\n"
12022 "Exact match of the communities\n"
12023 "IPv4 prefix\n"
12024 "Display route and more specific routes\n"
12025 "IPv6 prefix\n"
12026 "Display route and more specific routes\n")
718e3744 12027{
d62a17ae 12028 afi_t afi = AFI_IP6;
12029 safi_t safi = SAFI_UNICAST;
12030 int exact_match = 0;
d62a17ae 12031 struct bgp *bgp = NULL;
12032 int idx = 0;
96c81f66 12033 uint16_t show_flags = 0;
96f3485c
MK
12034
12035 /* [<ipv4|ipv6> [all]] */
12036 if (all) {
12037 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12038 if (argv_find(argv, argc, "ipv4", &idx))
12039 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12040
12041 if (argv_find(argv, argc, "ipv6", &idx))
12042 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12043 }
d62a17ae 12044
12045 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12046 &bgp, false);
d62a17ae 12047 if (!idx)
12048 return CMD_WARNING;
12049
d62a17ae 12050 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 12051 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
12052 return bgp_show_dampening_parameters(vty, afi, safi,
12053 show_flags);
d62a17ae 12054 }
c016b6c7 12055
d62a17ae 12056 if (argv_find(argv, argc, "prefix-list", &idx))
12057 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12058 safi, bgp_show_type_prefix_list);
12059
12060 if (argv_find(argv, argc, "filter-list", &idx))
12061 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12062 safi, bgp_show_type_filter_list);
12063
d62a17ae 12064 if (argv_find(argv, argc, "route-map", &idx))
12065 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12066 safi, bgp_show_type_route_map);
12067
d62a17ae 12068 if (argv_find(argv, argc, "community-list", &idx)) {
12069 const char *clist_number_or_name = argv[++idx]->arg;
12070 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12071 exact_match = 1;
12072 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12073 exact_match, afi, safi);
12074 }
12075 /* prefix-longer */
12076 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12077 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12078 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12079 safi,
12080 bgp_show_type_prefix_longer);
12081
7b2ff250
DW
12082 return CMD_WARNING;
12083}
12084
12085/* BGP route print out function with JSON */
a70a28a5
DA
12086DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12087 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12088 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12089 "]]\
96f3485c 12090 [all$all]\
cf4898bc
QY
12091 [cidr-only\
12092 |dampening <flap-statistics|dampened-paths>\
12093 |community [AA:NN|local-AS|no-advertise|no-export\
12094 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12095 |accept-own|accept-own-nexthop|route-filter-v6\
12096 |route-filter-v4|route-filter-translated-v6\
12097 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 12098 |rpki <invalid|valid|notfound>\
7d3cae70 12099 |version (1-4294967295)\
b4ad2fae 12100 |alias ALIAS_NAME\
f280c93b 12101 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12102 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12103 BGP_SAFI_WITH_LABEL_HELP_STR
12104 "Display the entries for all address families\n"
12105 "Display only routes with non-natural netmasks\n"
12106 "Display detailed information about dampening\n"
12107 "Display flap statistics of routes\n"
12108 "Display paths suppressed due to dampening\n"
12109 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12110 "Do not send outside local AS (well-known community)\n"
12111 "Do not advertise to any peer (well-known community)\n"
12112 "Do not export to next AS (well-known community)\n"
12113 "Graceful shutdown (well-known community)\n"
12114 "Do not export to any peer (well-known community)\n"
12115 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12116 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12117 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12118 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12119 "Should accept VPN route with local nexthop (well-known community)\n"
12120 "RT VPNv6 route filtering (well-known community)\n"
12121 "RT VPNv4 route filtering (well-known community)\n"
12122 "RT translated VPNv6 route filtering (well-known community)\n"
12123 "RT translated VPNv4 route filtering (well-known community)\n"
12124 "Exact match of the communities\n"
12125 "RPKI route types\n"
12126 "A valid path as determined by rpki\n"
12127 "A invalid path as determined by rpki\n"
12128 "A path that has no rpki data\n"
12129 "Display prefixes with matching version numbers\n"
12130 "Version number and above\n"
12131 "Display prefixes with matching BGP community alias\n"
12132 "BGP community alias\n" JSON_STR
12133 "Display detailed version of JSON output\n"
12134 "Increase table width for longer prefixes\n")
7b2ff250
DW
12135{
12136 afi_t afi = AFI_IP6;
12137 safi_t safi = SAFI_UNICAST;
12138 enum bgp_show_type sh_type = bgp_show_type_normal;
12139 struct bgp *bgp = NULL;
12140 int idx = 0;
d0086e8e 12141 int exact_match = 0;
96f3485c 12142 char *community = NULL;
7d3cae70 12143 char *prefix_version = NULL;
a70a28a5 12144 char *bgp_community_alias = NULL;
96f3485c 12145 bool first = true;
96c81f66 12146 uint16_t show_flags = 0;
4027d19b 12147 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12148
12149 if (uj) {
9f049418 12150 argc--;
96f3485c
MK
12151 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12152 }
12153
f280c93b
DA
12154 if (detail)
12155 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12156
96f3485c
MK
12157 /* [<ipv4|ipv6> [all]] */
12158 if (all) {
12159 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12160
12161 if (argv_find(argv, argc, "ipv4", &idx))
12162 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12163
12164 if (argv_find(argv, argc, "ipv6", &idx))
12165 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12166 }
12167
12168 if (wide)
12169 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12170
12171 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12172 &bgp, uj);
7b2ff250
DW
12173 if (!idx)
12174 return CMD_WARNING;
12175
7b2ff250 12176 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12177 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12178
12179 if (argv_find(argv, argc, "dampening", &idx)) {
12180 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12181 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12182 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12183 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12184 }
12185
12186 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12187 char *maybecomm = NULL;
d0086e8e 12188
79bc257a
RW
12189 if (idx + 1 < argc) {
12190 if (argv[idx + 1]->type == VARIABLE_TKN)
12191 maybecomm = argv[idx + 1]->arg;
12192 else
12193 maybecomm = argv[idx + 1]->text;
12194 }
12195
cf4898bc
QY
12196 if (maybecomm && !strmatch(maybecomm, "json")
12197 && !strmatch(maybecomm, "exact-match"))
12198 community = maybecomm;
d0086e8e 12199
cf4898bc
QY
12200 if (argv_find(argv, argc, "exact-match", &idx))
12201 exact_match = 1;
d0086e8e 12202
96f3485c
MK
12203 if (!community)
12204 sh_type = bgp_show_type_community_all;
12205 }
12206
1e2ce4f1
DS
12207 if (argv_find(argv, argc, "rpki", &idx)) {
12208 sh_type = bgp_show_type_rpki;
12209 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12210 rpki_target_state = RPKI_VALID;
1e2ce4f1 12211 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12212 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12213 }
12214
7d3cae70
DA
12215 /* Display prefixes with matching version numbers */
12216 if (argv_find(argv, argc, "version", &idx)) {
12217 sh_type = bgp_show_type_prefix_version;
12218 prefix_version = argv[idx + 1]->arg;
12219 }
12220
a70a28a5
DA
12221 /* Display prefixes with matching BGP community alias */
12222 if (argv_find(argv, argc, "alias", &idx)) {
12223 sh_type = bgp_show_type_community_alias;
12224 bgp_community_alias = argv[idx + 1]->arg;
12225 }
12226
96f3485c
MK
12227 if (!all) {
12228 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12229 if (community)
12230 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12231 exact_match, afi, safi,
12232 show_flags);
7d3cae70
DA
12233 else if (prefix_version)
12234 return bgp_show(vty, bgp, afi, safi, sh_type,
12235 prefix_version, show_flags,
12236 rpki_target_state);
a70a28a5
DA
12237 else if (bgp_community_alias)
12238 return bgp_show(vty, bgp, afi, safi, sh_type,
12239 bgp_community_alias, show_flags,
12240 rpki_target_state);
cf4898bc 12241 else
96f3485c 12242 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12243 show_flags, rpki_target_state);
96f3485c
MK
12244 } else {
12245 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12246 * AFI_IP6 */
12247
12248 if (uj)
12249 vty_out(vty, "{\n");
12250
12251 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12252 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12253 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12254 ? AFI_IP
12255 : AFI_IP6;
12256 FOREACH_SAFI (safi) {
96f3485c
MK
12257 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12258 continue;
12259
12260 if (uj) {
12261 if (first)
12262 first = false;
12263 else
12264 vty_out(vty, ",\n");
12265 vty_out(vty, "\"%s\":{\n",
12266 get_afi_safi_str(afi, safi,
12267 true));
12268 } else
12269 vty_out(vty,
12270 "\nFor address family: %s\n",
12271 get_afi_safi_str(afi, safi,
12272 false));
12273
12274 if (community)
12275 bgp_show_community(vty, bgp, community,
12276 exact_match, afi,
12277 safi, show_flags);
7d3cae70
DA
12278 else if (prefix_version)
12279 return bgp_show(vty, bgp, afi, safi,
12280 sh_type, prefix_version,
12281 show_flags,
12282 rpki_target_state);
a70a28a5
DA
12283 else if (bgp_community_alias)
12284 return bgp_show(
12285 vty, bgp, afi, safi, sh_type,
12286 bgp_community_alias, show_flags,
12287 rpki_target_state);
96f3485c
MK
12288 else
12289 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12290 NULL, show_flags,
4027d19b 12291 rpki_target_state);
96f3485c
MK
12292 if (uj)
12293 vty_out(vty, "}\n");
12294 }
12295 } else {
12296 /* show <ip> bgp all: for each AFI and SAFI*/
12297 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12298 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12299 continue;
12300
12301 if (uj) {
12302 if (first)
12303 first = false;
12304 else
12305 vty_out(vty, ",\n");
d0086e8e 12306
96f3485c
MK
12307 vty_out(vty, "\"%s\":{\n",
12308 get_afi_safi_str(afi, safi,
12309 true));
12310 } else
12311 vty_out(vty,
12312 "\nFor address family: %s\n",
12313 get_afi_safi_str(afi, safi,
12314 false));
12315
12316 if (community)
12317 bgp_show_community(vty, bgp, community,
12318 exact_match, afi,
12319 safi, show_flags);
7d3cae70
DA
12320 else if (prefix_version)
12321 return bgp_show(vty, bgp, afi, safi,
12322 sh_type, prefix_version,
12323 show_flags,
12324 rpki_target_state);
96f3485c
MK
12325 else
12326 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12327 NULL, show_flags,
4027d19b 12328 rpki_target_state);
96f3485c
MK
12329 if (uj)
12330 vty_out(vty, "}\n");
12331 }
12332 }
12333 if (uj)
12334 vty_out(vty, "}\n");
12335 }
12336 return CMD_SUCCESS;
a636c635 12337}
47fc97cc 12338
718e3744 12339DEFUN (show_ip_bgp_route,
12340 show_ip_bgp_route_cmd,
8aa22bbb 12341 "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 12342 SHOW_STR
12343 IP_STR
12344 BGP_STR
a636c635 12345 BGP_INSTANCE_HELP_STR
4f280b15 12346 BGP_AFI_HELP_STR
4dd6177e 12347 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12348 "Network in the BGP routing table to display\n"
0c7b1b01 12349 "IPv4 prefix\n"
8c3deaae 12350 "Network in the BGP routing table to display\n"
0c7b1b01 12351 "IPv6 prefix\n"
4092b06c 12352 "Display only the bestpath\n"
b05a1c8b 12353 "Display only multipaths\n"
8aa22bbb
DS
12354 "Display only paths that match the specified rpki state\n"
12355 "A valid path as determined by rpki\n"
12356 "A invalid path as determined by rpki\n"
12357 "A path that has no rpki data\n"
9973d184 12358 JSON_STR)
4092b06c 12359{
d62a17ae 12360 int prefix_check = 0;
ae19d7dd 12361
d62a17ae 12362 afi_t afi = AFI_IP6;
12363 safi_t safi = SAFI_UNICAST;
12364 char *prefix = NULL;
12365 struct bgp *bgp = NULL;
12366 enum bgp_path_type path_type;
9f049418 12367 bool uj = use_json(argc, argv);
b05a1c8b 12368
d62a17ae 12369 int idx = 0;
ae19d7dd 12370
d62a17ae 12371 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12372 &bgp, uj);
d62a17ae 12373 if (!idx)
12374 return CMD_WARNING;
c41247f5 12375
d62a17ae 12376 if (!bgp) {
12377 vty_out(vty,
12378 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12379 return CMD_WARNING;
12380 }
a636c635 12381
d62a17ae 12382 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12383 if (argv_find(argv, argc, "A.B.C.D", &idx)
12384 || argv_find(argv, argc, "X:X::X:X", &idx))
12385 prefix_check = 0;
12386 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12387 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12388 prefix_check = 1;
12389
12390 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12391 && afi != AFI_IP6) {
12392 vty_out(vty,
12393 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12394 return CMD_WARNING;
12395 }
12396 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12397 && afi != AFI_IP) {
12398 vty_out(vty,
12399 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12400 return CMD_WARNING;
12401 }
12402
12403 prefix = argv[idx]->arg;
12404
12405 /* [<bestpath|multipath>] */
12406 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12407 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12408 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12409 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12410 else
360660c6 12411 path_type = BGP_PATH_SHOW_ALL;
a636c635 12412
d62a17ae 12413 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12414 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12415}
12416
8c3deaae
QY
12417DEFUN (show_ip_bgp_regexp,
12418 show_ip_bgp_regexp_cmd,
3e5b31b3 12419 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12420 SHOW_STR
12421 IP_STR
12422 BGP_STR
b00b230a 12423 BGP_INSTANCE_HELP_STR
4f280b15 12424 BGP_AFI_HELP_STR
4dd6177e 12425 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12426 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12427 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12428 JSON_STR)
8c3deaae 12429{
d62a17ae 12430 afi_t afi = AFI_IP6;
12431 safi_t safi = SAFI_UNICAST;
12432 struct bgp *bgp = NULL;
3e5b31b3
DA
12433 bool uj = use_json(argc, argv);
12434 char *regstr = NULL;
8c3deaae 12435
d62a17ae 12436 int idx = 0;
12437 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12438 &bgp, false);
d62a17ae 12439 if (!idx)
12440 return CMD_WARNING;
8c3deaae 12441
d62a17ae 12442 // get index of regex
3e5b31b3
DA
12443 if (argv_find(argv, argc, "REGEX", &idx))
12444 regstr = argv[idx]->arg;
8c3deaae 12445
5f71d11c 12446 assert(regstr);
3e5b31b3
DA
12447 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12448 bgp_show_type_regexp, uj);
8c3deaae
QY
12449}
12450
ae248832 12451DEFPY (show_ip_bgp_instance_all,
a636c635 12452 show_ip_bgp_instance_all_cmd,
ae248832 12453 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12454 SHOW_STR
a636c635 12455 IP_STR
4092b06c 12456 BGP_STR
a636c635 12457 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12458 BGP_AFI_HELP_STR
4dd6177e 12459 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12460 JSON_STR
12461 "Increase table width for longer prefixes\n")
4092b06c 12462{
d62a17ae 12463 afi_t afi = AFI_IP;
12464 safi_t safi = SAFI_UNICAST;
12465 struct bgp *bgp = NULL;
d62a17ae 12466 int idx = 0;
96c81f66 12467 uint16_t show_flags = 0;
ae19d7dd 12468
96f3485c 12469 if (uj) {
d62a17ae 12470 argc--;
96f3485c
MK
12471 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12472 }
12473
12474 if (wide)
12475 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12476
9f049418
DS
12477 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12478 &bgp, uj);
12479 if (!idx)
12480 return CMD_WARNING;
12481
96f3485c 12482 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12483 return CMD_SUCCESS;
e3e29b32
LB
12484}
12485
a4d82a8a 12486static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12487 afi_t afi, safi_t safi, enum bgp_show_type type,
12488 bool use_json)
718e3744 12489{
d62a17ae 12490 regex_t *regex;
12491 int rc;
96c81f66 12492 uint16_t show_flags = 0;
96f3485c
MK
12493
12494 if (use_json)
12495 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12496
c3900853 12497 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12498 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12499 regstr);
12500 return CMD_WARNING_CONFIG_FAILED;
12501 }
12502
d62a17ae 12503 regex = bgp_regcomp(regstr);
12504 if (!regex) {
12505 vty_out(vty, "Can't compile regexp %s\n", regstr);
12506 return CMD_WARNING;
12507 }
a636c635 12508
1e2ce4f1
DS
12509 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12510 RPKI_NOT_BEING_USED);
d62a17ae 12511 bgp_regex_free(regex);
12512 return rc;
e3e29b32
LB
12513}
12514
d62a17ae 12515static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12516 const char *prefix_list_str, afi_t afi,
12517 safi_t safi, enum bgp_show_type type)
e3e29b32 12518{
d62a17ae 12519 struct prefix_list *plist;
96c81f66 12520 uint16_t show_flags = 0;
718e3744 12521
d62a17ae 12522 plist = prefix_list_lookup(afi, prefix_list_str);
12523 if (plist == NULL) {
12524 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12525 prefix_list_str);
12526 return CMD_WARNING;
12527 }
718e3744 12528
1e2ce4f1
DS
12529 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12530 RPKI_NOT_BEING_USED);
4092b06c
DS
12531}
12532
d62a17ae 12533static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12534 const char *filter, afi_t afi, safi_t safi,
12535 enum bgp_show_type type)
4092b06c 12536{
d62a17ae 12537 struct as_list *as_list;
96c81f66 12538 uint16_t show_flags = 0;
718e3744 12539
d62a17ae 12540 as_list = as_list_lookup(filter);
12541 if (as_list == NULL) {
12542 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12543 filter);
12544 return CMD_WARNING;
12545 }
a636c635 12546
1e2ce4f1
DS
12547 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12548 RPKI_NOT_BEING_USED);
718e3744 12549}
12550
d62a17ae 12551static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12552 const char *rmap_str, afi_t afi, safi_t safi,
12553 enum bgp_show_type type)
718e3744 12554{
d62a17ae 12555 struct route_map *rmap;
96c81f66 12556 uint16_t show_flags = 0;
bb46e94f 12557
d62a17ae 12558 rmap = route_map_lookup_by_name(rmap_str);
12559 if (!rmap) {
12560 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12561 return CMD_WARNING;
12562 }
12563
1e2ce4f1
DS
12564 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12565 RPKI_NOT_BEING_USED);
d62a17ae 12566}
12567
7f323236
DW
12568static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12569 const char *comstr, int exact, afi_t afi,
96c81f66 12570 safi_t safi, uint16_t show_flags)
d62a17ae 12571{
12572 struct community *com;
d62a17ae 12573 int ret = 0;
12574
7f323236 12575 com = community_str2com(comstr);
d62a17ae 12576 if (!com) {
7f323236 12577 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12578 return CMD_WARNING;
12579 }
12580
12581 ret = bgp_show(vty, bgp, afi, safi,
12582 (exact ? bgp_show_type_community_exact
12583 : bgp_show_type_community),
1e2ce4f1 12584 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12585 community_free(&com);
46c3ce83 12586
d62a17ae 12587 return ret;
718e3744 12588}
12589
d62a17ae 12590static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12591 const char *com, int exact, afi_t afi,
12592 safi_t safi)
50ef26d4 12593{
d62a17ae 12594 struct community_list *list;
96c81f66 12595 uint16_t show_flags = 0;
50ef26d4 12596
e237b0d2 12597 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12598 if (list == NULL) {
12599 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12600 return CMD_WARNING;
12601 }
718e3744 12602
d62a17ae 12603 return bgp_show(vty, bgp, afi, safi,
12604 (exact ? bgp_show_type_community_list_exact
12605 : bgp_show_type_community_list),
1e2ce4f1 12606 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12607}
12608
d62a17ae 12609static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12610 const char *prefix, afi_t afi, safi_t safi,
12611 enum bgp_show_type type)
718e3744 12612{
d62a17ae 12613 int ret;
12614 struct prefix *p;
96c81f66 12615 uint16_t show_flags = 0;
47fc97cc 12616
d62a17ae 12617 p = prefix_new();
95cbbd2a 12618
d62a17ae 12619 ret = str2prefix(prefix, p);
12620 if (!ret) {
12621 vty_out(vty, "%% Malformed Prefix\n");
12622 return CMD_WARNING;
12623 }
47e9b292 12624
1e2ce4f1
DS
12625 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12626 RPKI_NOT_BEING_USED);
63265b5c 12627 prefix_free(&p);
d62a17ae 12628 return ret;
12629}
12630
d62a17ae 12631enum bgp_stats {
12632 BGP_STATS_MAXBITLEN = 0,
12633 BGP_STATS_RIB,
12634 BGP_STATS_PREFIXES,
12635 BGP_STATS_TOTPLEN,
12636 BGP_STATS_UNAGGREGATEABLE,
12637 BGP_STATS_MAX_AGGREGATEABLE,
12638 BGP_STATS_AGGREGATES,
12639 BGP_STATS_SPACE,
12640 BGP_STATS_ASPATH_COUNT,
12641 BGP_STATS_ASPATH_MAXHOPS,
12642 BGP_STATS_ASPATH_TOTHOPS,
12643 BGP_STATS_ASPATH_MAXSIZE,
12644 BGP_STATS_ASPATH_TOTSIZE,
12645 BGP_STATS_ASN_HIGHEST,
12646 BGP_STATS_MAX,
a636c635 12647};
2815e61f 12648
9ab0cf58 12649#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12650#define TABLE_STATS_IDX_JSON 1
12651
12652static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12653 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12654 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12655 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12656 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12657 "unaggregateablePrefixes"},
12658 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12659 "maximumAggregateablePrefixes"},
12660 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12661 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12662 [BGP_STATS_SPACE] = {"Address space advertised",
12663 "addressSpaceAdvertised"},
9ab0cf58
PG
12664 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12665 "advertisementsWithPaths"},
12666 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12667 "longestAsPath"},
12668 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12669 "largestAsPath"},
12670 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12671 "averageAsPathLengthHops"},
12672 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12673 "averageAsPathSizeBytes"},
12674 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12675 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12676};
2815e61f 12677
d62a17ae 12678struct bgp_table_stats {
12679 struct bgp_table *table;
12680 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12681 double total_space;
ff7924f6
PJ
12682};
12683
9bcb3eef 12684static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12685 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12686{
9bcb3eef 12687 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12688 struct bgp_path_info *pi;
b54892e0 12689 const struct prefix *rn_p;
d62a17ae 12690
9bcb3eef 12691 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12692 return;
d62a17ae 12693
9bcb3eef 12694 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12695 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12696 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12697
9c14ec72 12698 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12699 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12700 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12701
9bcb3eef 12702 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12703 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12704 /* announced address space */
12705 if (space)
b54892e0 12706 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12707 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12708 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12709
9c14ec72 12710
9bcb3eef 12711 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12712 ts->counts[BGP_STATS_RIB]++;
12713
05864da7
DS
12714 if (CHECK_FLAG(pi->attr->flag,
12715 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12716 ts->counts[BGP_STATS_AGGREGATES]++;
12717
12718 /* as-path stats */
05864da7 12719 if (pi->attr->aspath) {
9c14ec72
RW
12720 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12721 unsigned int size = aspath_size(pi->attr->aspath);
12722 as_t highest = aspath_highest(pi->attr->aspath);
12723
12724 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12725
12726 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12727 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12728
12729 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12730 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12731
12732 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12733 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12734 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12735 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12736 }
12737 }
12738}
12739
12740static int bgp_table_stats_walker(struct thread *t)
12741{
9bcb3eef
DS
12742 struct bgp_dest *dest, *ndest;
12743 struct bgp_dest *top;
9c14ec72
RW
12744 struct bgp_table_stats *ts = THREAD_ARG(t);
12745 unsigned int space = 0;
12746
12747 if (!(top = bgp_table_top(ts->table)))
12748 return 0;
12749
12750 switch (ts->table->afi) {
12751 case AFI_IP:
12752 space = IPV4_MAX_BITLEN;
12753 break;
12754 case AFI_IP6:
12755 space = IPV6_MAX_BITLEN;
12756 break;
3ba7b4af
TA
12757 case AFI_L2VPN:
12758 space = EVPN_ROUTE_PREFIXLEN;
12759 break;
9c14ec72
RW
12760 default:
12761 return 0;
12762 }
12763
12764 ts->counts[BGP_STATS_MAXBITLEN] = space;
12765
9bcb3eef 12766 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12767 if (ts->table->safi == SAFI_MPLS_VPN
12768 || ts->table->safi == SAFI_ENCAP
12769 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12770 struct bgp_table *table;
12771
9bcb3eef 12772 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12773 if (!table)
12774 continue;
12775
12776 top = bgp_table_top(table);
9bcb3eef
DS
12777 for (ndest = bgp_table_top(table); ndest;
12778 ndest = bgp_route_next(ndest))
12779 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12780 } else {
9bcb3eef 12781 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12782 }
12783 }
9c14ec72 12784
d62a17ae 12785 return 0;
2815e61f 12786}
ff7924f6 12787
71f1613a
DA
12788static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12789 struct json_object *json_array)
12790{
12791 struct listnode *node, *nnode;
12792 struct bgp *bgp;
12793
12794 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12795 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12796}
12797
12798static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12799 safi_t safi, struct json_object *json_array)
2815e61f 12800{
d62a17ae 12801 struct bgp_table_stats ts;
12802 unsigned int i;
893cccd0
PG
12803 int ret = CMD_SUCCESS;
12804 char temp_buf[20];
6c9d22e2
PG
12805 struct json_object *json = NULL;
12806
12807 if (json_array)
12808 json = json_object_new_object();
019386c2 12809
d62a17ae 12810 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12811 char warning_msg[50];
12812
12813 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12814 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12815 safi);
6c9d22e2
PG
12816
12817 if (!json)
893cccd0
PG
12818 vty_out(vty, "%s\n", warning_msg);
12819 else
9ab0cf58 12820 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12821
893cccd0
PG
12822 ret = CMD_WARNING;
12823 goto end_table_stats;
d62a17ae 12824 }
019386c2 12825
893cccd0 12826 if (!json)
5290ceab
DA
12827 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12828 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12829 else
12830 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12831
d62a17ae 12832 /* labeled-unicast routes live in the unicast table */
12833 if (safi == SAFI_LABELED_UNICAST)
12834 safi = SAFI_UNICAST;
019386c2 12835
d62a17ae 12836 memset(&ts, 0, sizeof(ts));
12837 ts.table = bgp->rib[afi][safi];
12838 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12839
d62a17ae 12840 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12841 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12842 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12843 continue;
12844
12845 switch (i) {
d62a17ae 12846 case BGP_STATS_ASPATH_TOTHOPS:
12847 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12848 if (!json) {
9ab0cf58
PG
12849 snprintf(
12850 temp_buf, sizeof(temp_buf), "%12.2f",
12851 ts.counts[i]
12852 ? (float)ts.counts[i]
12853 / (float)ts.counts
12854 [BGP_STATS_ASPATH_COUNT]
12855 : 0);
893cccd0 12856 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12857 table_stats_strs[i]
12858 [TABLE_STATS_IDX_VTY],
893cccd0 12859 temp_buf);
9ab0cf58
PG
12860 } else {
12861 json_object_double_add(
12862 json,
12863 table_stats_strs[i]
12864 [TABLE_STATS_IDX_JSON],
12865 ts.counts[i]
12866 ? (double)ts.counts[i]
12867 / (double)ts.counts
d62a17ae 12868 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12869 : 0);
12870 }
d62a17ae 12871 break;
12872 case BGP_STATS_TOTPLEN:
6c9d22e2 12873 if (!json) {
9ab0cf58
PG
12874 snprintf(
12875 temp_buf, sizeof(temp_buf), "%12.2f",
12876 ts.counts[i]
12877 ? (float)ts.counts[i]
12878 / (float)ts.counts
12879 [BGP_STATS_PREFIXES]
12880 : 0);
893cccd0 12881 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12882 table_stats_strs[i]
12883 [TABLE_STATS_IDX_VTY],
893cccd0 12884 temp_buf);
9ab0cf58
PG
12885 } else {
12886 json_object_double_add(
12887 json,
12888 table_stats_strs[i]
12889 [TABLE_STATS_IDX_JSON],
12890 ts.counts[i]
12891 ? (double)ts.counts[i]
12892 / (double)ts.counts
d62a17ae 12893 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12894 : 0);
12895 }
d62a17ae 12896 break;
12897 case BGP_STATS_SPACE:
6c9d22e2
PG
12898 if (!json) {
12899 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12900 ts.total_space);
893cccd0 12901 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12902 table_stats_strs[i]
12903 [TABLE_STATS_IDX_VTY],
893cccd0 12904 temp_buf);
9ab0cf58
PG
12905 } else {
12906 json_object_double_add(
12907 json,
12908 table_stats_strs[i]
12909 [TABLE_STATS_IDX_JSON],
12910 (double)ts.total_space);
12911 }
8d0ab76d 12912 if (afi == AFI_IP6) {
6c9d22e2
PG
12913 if (!json) {
12914 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12915 "%12g",
12916 ts.total_space
12917 * pow(2.0, -128 + 32));
6c9d22e2
PG
12918 vty_out(vty, "%30s: %s\n",
12919 "/32 equivalent %s\n",
12920 temp_buf);
9ab0cf58
PG
12921 } else {
12922 json_object_double_add(
12923 json, "/32equivalent",
12924 (double)(ts.total_space
12925 * pow(2.0,
12926 -128 + 32)));
12927 }
6c9d22e2
PG
12928 if (!json) {
12929 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12930 "%12g",
12931 ts.total_space
12932 * pow(2.0, -128 + 48));
6c9d22e2
PG
12933 vty_out(vty, "%30s: %s\n",
12934 "/48 equivalent %s\n",
12935 temp_buf);
9ab0cf58
PG
12936 } else {
12937 json_object_double_add(
12938 json, "/48equivalent",
12939 (double)(ts.total_space
12940 * pow(2.0,
12941 -128 + 48)));
12942 }
8d0ab76d 12943 } else {
6c9d22e2
PG
12944 if (!json) {
12945 snprintf(temp_buf, sizeof(temp_buf),
12946 "%12.2f",
9ab0cf58
PG
12947 ts.total_space * 100.
12948 * pow(2.0, -32));
6c9d22e2 12949 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12950 "% announced ", temp_buf);
12951 } else {
12952 json_object_double_add(
12953 json, "%announced",
12954 (double)(ts.total_space * 100.
12955 * pow(2.0, -32)));
12956 }
6c9d22e2
PG
12957 if (!json) {
12958 snprintf(temp_buf, sizeof(temp_buf),
12959 "%12.2f",
9ab0cf58
PG
12960 ts.total_space
12961 * pow(2.0, -32 + 8));
6c9d22e2
PG
12962 vty_out(vty, "%30s: %s\n",
12963 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12964 } else {
12965 json_object_double_add(
12966 json, "/8equivalent",
12967 (double)(ts.total_space
12968 * pow(2.0, -32 + 8)));
12969 }
6c9d22e2
PG
12970 if (!json) {
12971 snprintf(temp_buf, sizeof(temp_buf),
12972 "%12.2f",
9ab0cf58
PG
12973 ts.total_space
12974 * pow(2.0, -32 + 24));
6c9d22e2 12975 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12976 "/24 equivalent ", temp_buf);
12977 } else {
12978 json_object_double_add(
12979 json, "/24equivalent",
12980 (double)(ts.total_space
12981 * pow(2.0, -32 + 24)));
12982 }
8d0ab76d 12983 }
d62a17ae 12984 break;
12985 default:
6c9d22e2
PG
12986 if (!json) {
12987 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12988 ts.counts[i]);
893cccd0 12989 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12990 table_stats_strs[i]
12991 [TABLE_STATS_IDX_VTY],
12992 temp_buf);
12993 } else {
12994 json_object_int_add(
12995 json,
12996 table_stats_strs[i]
12997 [TABLE_STATS_IDX_JSON],
12998 ts.counts[i]);
12999 }
d62a17ae 13000 }
893cccd0
PG
13001 if (!json)
13002 vty_out(vty, "\n");
d62a17ae 13003 }
9ab0cf58 13004end_table_stats:
6c9d22e2
PG
13005 if (json)
13006 json_object_array_add(json_array, json);
893cccd0 13007 return ret;
d62a17ae 13008}
13009
71f1613a
DA
13010static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13011 safi_t safi, struct json_object *json_array)
13012{
13013 if (!bgp) {
13014 bgp_table_stats_all(vty, afi, safi, json_array);
13015 return CMD_SUCCESS;
13016 }
13017
13018 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13019}
13020
d62a17ae 13021enum bgp_pcounts {
13022 PCOUNT_ADJ_IN = 0,
13023 PCOUNT_DAMPED,
13024 PCOUNT_REMOVED,
13025 PCOUNT_HISTORY,
13026 PCOUNT_STALE,
13027 PCOUNT_VALID,
13028 PCOUNT_ALL,
13029 PCOUNT_COUNTED,
7e3d9632 13030 PCOUNT_BPATH_SELECTED,
d62a17ae 13031 PCOUNT_PFCNT, /* the figure we display to users */
13032 PCOUNT_MAX,
a636c635 13033};
718e3744 13034
2b64873d 13035static const char *const pcount_strs[] = {
9d303b37
DL
13036 [PCOUNT_ADJ_IN] = "Adj-in",
13037 [PCOUNT_DAMPED] = "Damped",
13038 [PCOUNT_REMOVED] = "Removed",
13039 [PCOUNT_HISTORY] = "History",
13040 [PCOUNT_STALE] = "Stale",
13041 [PCOUNT_VALID] = "Valid",
13042 [PCOUNT_ALL] = "All RIB",
13043 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13044 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13045 [PCOUNT_PFCNT] = "Useable",
13046 [PCOUNT_MAX] = NULL,
a636c635 13047};
718e3744 13048
d62a17ae 13049struct peer_pcounts {
13050 unsigned int count[PCOUNT_MAX];
13051 const struct peer *peer;
13052 const struct bgp_table *table;
54317cba 13053 safi_t safi;
a636c635 13054};
47fc97cc 13055
9bcb3eef 13056static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13057{
54317cba
JW
13058 const struct bgp_adj_in *ain;
13059 const struct bgp_path_info *pi;
d62a17ae 13060 const struct peer *peer = pc->peer;
13061
54317cba
JW
13062 for (ain = rn->adj_in; ain; ain = ain->next)
13063 if (ain->peer == peer)
13064 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13065
9bcb3eef 13066 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13067
54317cba
JW
13068 if (pi->peer != peer)
13069 continue;
d62a17ae 13070
54317cba 13071 pc->count[PCOUNT_ALL]++;
d62a17ae 13072
54317cba
JW
13073 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13074 pc->count[PCOUNT_DAMPED]++;
13075 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13076 pc->count[PCOUNT_HISTORY]++;
13077 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13078 pc->count[PCOUNT_REMOVED]++;
13079 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13080 pc->count[PCOUNT_STALE]++;
13081 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13082 pc->count[PCOUNT_VALID]++;
13083 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13084 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13085 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13086 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13087
13088 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13089 pc->count[PCOUNT_COUNTED]++;
13090 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13091 flog_err(
13092 EC_LIB_DEVELOPMENT,
13093 "Attempting to count but flags say it is unusable");
13094 } else {
40381db7 13095 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13096 flog_err(
13097 EC_LIB_DEVELOPMENT,
13098 "Not counted but flags say we should");
d62a17ae 13099 }
13100 }
54317cba
JW
13101}
13102
13103static int bgp_peer_count_walker(struct thread *t)
13104{
9bcb3eef 13105 struct bgp_dest *rn, *rm;
54317cba
JW
13106 const struct bgp_table *table;
13107 struct peer_pcounts *pc = THREAD_ARG(t);
13108
13109 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13110 || pc->safi == SAFI_EVPN) {
13111 /* Special handling for 2-level routing tables. */
13112 for (rn = bgp_table_top(pc->table); rn;
13113 rn = bgp_route_next(rn)) {
9bcb3eef 13114 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13115 if (table != NULL)
13116 for (rm = bgp_table_top(table); rm;
13117 rm = bgp_route_next(rm))
13118 bgp_peer_count_proc(rm, pc);
13119 }
13120 } else
13121 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13122 bgp_peer_count_proc(rn, pc);
13123
d62a17ae 13124 return 0;
718e3744 13125}
13126
d62a17ae 13127static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13128 safi_t safi, bool use_json)
856ca177 13129{
d62a17ae 13130 struct peer_pcounts pcounts = {.peer = peer};
13131 unsigned int i;
13132 json_object *json = NULL;
13133 json_object *json_loop = NULL;
856ca177 13134
d62a17ae 13135 if (use_json) {
13136 json = json_object_new_object();
13137 json_loop = json_object_new_object();
13138 }
718e3744 13139
d62a17ae 13140 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13141 || !peer->bgp->rib[afi][safi]) {
13142 if (use_json) {
13143 json_object_string_add(
13144 json, "warning",
13145 "No such neighbor or address family");
13146 vty_out(vty, "%s\n", json_object_to_json_string(json));
13147 json_object_free(json);
d5f20468 13148 json_object_free(json_loop);
d62a17ae 13149 } else
13150 vty_out(vty, "%% No such neighbor or address family\n");
13151
13152 return CMD_WARNING;
13153 }
2a71e9ce 13154
d62a17ae 13155 memset(&pcounts, 0, sizeof(pcounts));
13156 pcounts.peer = peer;
13157 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13158 pcounts.safi = safi;
d62a17ae 13159
13160 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13161 * stats for the thread-walk (i.e. ensure this can't be blamed on
13162 * on just vty_read()).
13163 */
d62a17ae 13164 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13165
13166 if (use_json) {
13167 json_object_string_add(json, "prefixCountsFor", peer->host);
13168 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13169 get_afi_safi_str(afi, safi, true));
d62a17ae 13170 json_object_int_add(json, "pfxCounter",
13171 peer->pcount[afi][safi]);
13172
13173 for (i = 0; i < PCOUNT_MAX; i++)
13174 json_object_int_add(json_loop, pcount_strs[i],
13175 pcounts.count[i]);
13176
13177 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13178
13179 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13180 json_object_string_add(json, "pfxctDriftFor",
13181 peer->host);
13182 json_object_string_add(
13183 json, "recommended",
13184 "Please report this bug, with the above command output");
13185 }
996c9314
LB
13186 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13187 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13188 json_object_free(json);
13189 } else {
13190
13191 if (peer->hostname
892fedb6 13192 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13193 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13194 peer->hostname, peer->host,
5cb5f4d0 13195 get_afi_safi_str(afi, safi, false));
d62a17ae 13196 } else {
13197 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13198 get_afi_safi_str(afi, safi, false));
d62a17ae 13199 }
13200
6cde4b45 13201 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13202 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13203
13204 for (i = 0; i < PCOUNT_MAX; i++)
13205 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13206 pcounts.count[i]);
13207
13208 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13209 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13210 vty_out(vty,
13211 "Please report this bug, with the above command output\n");
13212 }
13213 }
13214
13215 return CMD_SUCCESS;
718e3744 13216}
13217
a636c635
DW
13218DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13219 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13220 "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 13221 SHOW_STR
13222 IP_STR
13223 BGP_STR
8386ac43 13224 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13225 BGP_AFI_HELP_STR
13226 BGP_SAFI_HELP_STR
0b16f239
DS
13227 "Detailed information on TCP and BGP neighbor connections\n"
13228 "Neighbor to display information about\n"
13229 "Neighbor to display information about\n"
91d37724 13230 "Neighbor on BGP configured interface\n"
a636c635 13231 "Display detailed prefix count information\n"
9973d184 13232 JSON_STR)
0b16f239 13233{
d62a17ae 13234 afi_t afi = AFI_IP6;
13235 safi_t safi = SAFI_UNICAST;
13236 struct peer *peer;
13237 int idx = 0;
13238 struct bgp *bgp = NULL;
9f049418
DS
13239 bool uj = use_json(argc, argv);
13240
13241 if (uj)
13242 argc--;
856ca177 13243
d62a17ae 13244 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13245 &bgp, uj);
d62a17ae 13246 if (!idx)
13247 return CMD_WARNING;
0b16f239 13248
d62a17ae 13249 argv_find(argv, argc, "neighbors", &idx);
13250 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13251 if (!peer)
13252 return CMD_WARNING;
bb46e94f 13253
29c8d9da 13254 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13255}
0b16f239 13256
d6902373
PG
13257#ifdef KEEP_OLD_VPN_COMMANDS
13258DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13259 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13260 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13261 SHOW_STR
13262 IP_STR
13263 BGP_STR
d6902373 13264 BGP_VPNVX_HELP_STR
91d37724 13265 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13266 "Detailed information on TCP and BGP neighbor connections\n"
13267 "Neighbor to display information about\n"
13268 "Neighbor to display information about\n"
91d37724 13269 "Neighbor on BGP configured interface\n"
a636c635 13270 "Display detailed prefix count information\n"
9973d184 13271 JSON_STR)
a636c635 13272{
d62a17ae 13273 int idx_peer = 6;
13274 struct peer *peer;
9f049418 13275 bool uj = use_json(argc, argv);
a636c635 13276
d62a17ae 13277 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13278 if (!peer)
13279 return CMD_WARNING;
13280
13281 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13282}
13283
d6902373
PG
13284DEFUN (show_ip_bgp_vpn_all_route_prefix,
13285 show_ip_bgp_vpn_all_route_prefix_cmd,
13286 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13287 SHOW_STR
13288 IP_STR
13289 BGP_STR
d6902373 13290 BGP_VPNVX_HELP_STR
91d37724
QY
13291 "Display information about all VPNv4 NLRIs\n"
13292 "Network in the BGP routing table to display\n"
3a2d747c 13293 "Network in the BGP routing table to display\n"
9973d184 13294 JSON_STR)
91d37724 13295{
d62a17ae 13296 int idx = 0;
13297 char *network = NULL;
13298 struct bgp *bgp = bgp_get_default();
13299 if (!bgp) {
13300 vty_out(vty, "Can't find default instance\n");
13301 return CMD_WARNING;
13302 }
87e34b58 13303
d62a17ae 13304 if (argv_find(argv, argc, "A.B.C.D", &idx))
13305 network = argv[idx]->arg;
13306 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13307 network = argv[idx]->arg;
13308 else {
13309 vty_out(vty, "Unable to figure out Network\n");
13310 return CMD_WARNING;
13311 }
87e34b58 13312
d62a17ae 13313 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13314 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13315 use_json(argc, argv));
91d37724 13316}
d6902373 13317#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13318
44c69747
LK
13319DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13320 show_bgp_l2vpn_evpn_route_prefix_cmd,
13321 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13322 SHOW_STR
4c63a661
PG
13323 BGP_STR
13324 L2VPN_HELP_STR
13325 EVPN_HELP_STR
44c69747
LK
13326 "Network in the BGP routing table to display\n"
13327 "Network in the BGP routing table to display\n"
4c63a661
PG
13328 "Network in the BGP routing table to display\n"
13329 "Network in the BGP routing table to display\n"
13330 JSON_STR)
13331{
d62a17ae 13332 int idx = 0;
13333 char *network = NULL;
44c69747 13334 int prefix_check = 0;
a636c635 13335
44c69747
LK
13336 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13337 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13338 network = argv[idx]->arg;
44c69747 13339 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13340 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13341 network = argv[idx]->arg;
44c69747
LK
13342 prefix_check = 1;
13343 } else {
d62a17ae 13344 vty_out(vty, "Unable to figure out Network\n");
13345 return CMD_WARNING;
13346 }
44c69747
LK
13347 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13348 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13349 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13350}
13351
2f9bc755
DS
13352static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13353 struct bgp_table *table, int *header1,
13354 int *header2, json_object *json,
13355 json_object *json_scode,
13356 json_object *json_ocode, bool wide)
13357{
13358 uint64_t version = table ? table->version : 0;
23d0a753 13359 char buf[BUFSIZ] = {0};
2f9bc755
DS
13360
13361 if (*header1) {
13362 if (json) {
13363 json_object_int_add(json, "bgpTableVersion", version);
13364 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13365 inet_ntop(AF_INET,
13366 &bgp->router_id, buf,
13367 sizeof(buf)));
2f9bc755
DS
13368 json_object_int_add(json, "defaultLocPrf",
13369 bgp->default_local_pref);
13370 json_object_int_add(json, "localAS", bgp->as);
13371 json_object_object_add(json, "bgpStatusCodes",
13372 json_scode);
13373 json_object_object_add(json, "bgpOriginCodes",
13374 json_ocode);
13375 } else {
13376 vty_out(vty,
23d0a753
DA
13377 "BGP table version is %" PRIu64
13378 ", local router ID is %pI4, vrf id ",
13379 version, &bgp->router_id);
2f9bc755
DS
13380 if (bgp->vrf_id == VRF_UNKNOWN)
13381 vty_out(vty, "%s", VRFID_NONE_STR);
13382 else
13383 vty_out(vty, "%u", bgp->vrf_id);
13384 vty_out(vty, "\n");
13385 vty_out(vty, "Default local pref %u, ",
13386 bgp->default_local_pref);
13387 vty_out(vty, "local AS %u\n", bgp->as);
13388 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13389 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13390 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13391 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13392 }
13393 *header1 = 0;
13394 }
13395 if (*header2) {
13396 if (!json)
13397 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13398 : BGP_SHOW_HEADER));
13399 *header2 = 0;
13400 }
13401}
13402
d9478df0
TA
13403static void
13404show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13405 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13406 const char *rmap_name, json_object *json, json_object *json_ar,
13407 json_object *json_scode, json_object *json_ocode,
96c81f66 13408 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13409 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13410{
d62a17ae 13411 struct bgp_adj_in *ain;
13412 struct bgp_adj_out *adj;
9bcb3eef 13413 struct bgp_dest *dest;
d62a17ae 13414 struct bgp *bgp;
d62a17ae 13415 struct attr attr;
13416 int ret;
13417 struct update_subgroup *subgrp;
d62a17ae 13418 struct peer_af *paf;
f99def61 13419 bool route_filtered;
96f3485c
MK
13420 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13421 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13422 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13423 || (safi == SAFI_EVPN))
13424 ? true
13425 : false;
a636c635 13426
d62a17ae 13427 bgp = peer->bgp;
a636c635 13428
d62a17ae 13429 if (!bgp) {
13430 if (use_json) {
13431 json_object_string_add(json, "alert", "no BGP");
13432 vty_out(vty, "%s\n", json_object_to_json_string(json));
13433 json_object_free(json);
13434 } else
13435 vty_out(vty, "%% No bgp\n");
13436 return;
13437 }
a636c635 13438
d62a17ae 13439 subgrp = peer_subgroup(peer, afi, safi);
13440
6392aaa6 13441 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13442 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13443 char buf[BUFSIZ] = {0};
13444
d62a17ae 13445 if (use_json) {
13446 json_object_int_add(json, "bgpTableVersion",
13447 table->version);
13448 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13449 inet_ntop(AF_INET,
13450 &bgp->router_id, buf,
13451 sizeof(buf)));
01eced22
AD
13452 json_object_int_add(json, "defaultLocPrf",
13453 bgp->default_local_pref);
13454 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13455 json_object_object_add(json, "bgpStatusCodes",
13456 json_scode);
13457 json_object_object_add(json, "bgpOriginCodes",
13458 json_ocode);
07d0c4ed
DA
13459 json_object_string_add(
13460 json, "bgpOriginatingDefaultNetwork",
13461 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13462 } else {
23d0a753
DA
13463 vty_out(vty,
13464 "BGP table version is %" PRIu64
13465 ", local router ID is %pI4, vrf id ",
13466 table->version, &bgp->router_id);
9df8b37c
PZ
13467 if (bgp->vrf_id == VRF_UNKNOWN)
13468 vty_out(vty, "%s", VRFID_NONE_STR);
13469 else
13470 vty_out(vty, "%u", bgp->vrf_id);
13471 vty_out(vty, "\n");
01eced22
AD
13472 vty_out(vty, "Default local pref %u, ",
13473 bgp->default_local_pref);
13474 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13475 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13476 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13477 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13478 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13479
07d0c4ed
DA
13480 vty_out(vty, "Originating default network %s\n\n",
13481 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13482 }
d9478df0 13483 *header1 = 0;
d62a17ae 13484 }
a636c635 13485
9bcb3eef 13486 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13487 if (type == bgp_show_adj_route_received
13488 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13489 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13490 if (ain->peer != peer)
ea47320b 13491 continue;
6392aaa6 13492
d9478df0
TA
13493 show_adj_route_header(vty, bgp, table, header1,
13494 header2, json, json_scode,
13495 json_ocode, wide);
13496
13497 if ((safi == SAFI_MPLS_VPN)
13498 || (safi == SAFI_ENCAP)
13499 || (safi == SAFI_EVPN)) {
13500 if (use_json)
13501 json_object_string_add(
13502 json_ar, "rd", rd_str);
13503 else if (show_rd && rd_str) {
13504 vty_out(vty,
13505 "Route Distinguisher: %s\n",
13506 rd_str);
13507 show_rd = false;
13508 }
13509 }
6392aaa6 13510
6f4f49b2 13511 attr = *ain->attr;
f99def61
AD
13512 route_filtered = false;
13513
13514 /* Filter prefix using distribute list,
13515 * filter list or prefix list
13516 */
b54892e0 13517 const struct prefix *rn_p =
9bcb3eef 13518 bgp_dest_get_prefix(dest);
b54892e0
DS
13519 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13520 safi))
13521 == FILTER_DENY)
f99def61
AD
13522 route_filtered = true;
13523
13524 /* Filter prefix using route-map */
b54892e0
DS
13525 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13526 safi, rmap_name, NULL,
13527 0, NULL);
6392aaa6 13528
13c8e163
AD
13529 if (type == bgp_show_adj_route_filtered &&
13530 !route_filtered && ret != RMAP_DENY) {
b755861b 13531 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13532 continue;
d62a17ae 13533 }
6392aaa6 13534
d9478df0
TA
13535 if (type == bgp_show_adj_route_received
13536 && (route_filtered || ret == RMAP_DENY))
13537 (*filtered_count)++;
6392aaa6 13538
7d3cae70 13539 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13540 use_json, json_ar, wide);
b755861b 13541 bgp_attr_undup(&attr, ain->attr);
d9478df0 13542 (*output_count)++;
d62a17ae 13543 }
6392aaa6 13544 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13545 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13546 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13547 if (paf->peer != peer || !adj->attr)
924c3f6a 13548 continue;
d62a17ae 13549
d9478df0
TA
13550 show_adj_route_header(vty, bgp, table,
13551 header1, header2,
13552 json, json_scode,
13553 json_ocode, wide);
d62a17ae 13554
b54892e0 13555 const struct prefix *rn_p =
9bcb3eef 13556 bgp_dest_get_prefix(dest);
b54892e0 13557
6f4f49b2 13558 attr = *adj->attr;
b755861b 13559 ret = bgp_output_modifier(
b54892e0 13560 peer, rn_p, &attr, afi, safi,
b755861b 13561 rmap_name);
f46d8e1e 13562
b755861b 13563 if (ret != RMAP_DENY) {
d9478df0
TA
13564 if ((safi == SAFI_MPLS_VPN)
13565 || (safi == SAFI_ENCAP)
13566 || (safi == SAFI_EVPN)) {
13567 if (use_json)
13568 json_object_string_add(
13569 json_ar,
13570 "rd",
13571 rd_str);
13572 else if (show_rd
13573 && rd_str) {
13574 vty_out(vty,
13575 "Route Distinguisher: %s\n",
13576 rd_str);
13577 show_rd = false;
13578 }
13579 }
b54892e0 13580 route_vty_out_tmp(
7d3cae70
DA
13581 vty, dest, rn_p, &attr,
13582 safi, use_json, json_ar,
ae248832 13583 wide);
d9478df0 13584 (*output_count)++;
b755861b 13585 } else {
d9478df0 13586 (*filtered_count)++;
a2addae8 13587 }
b755861b
PM
13588
13589 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13590 }
f20ce998
DS
13591 } else if (type == bgp_show_adj_route_bestpath) {
13592 struct bgp_path_info *pi;
13593
d9478df0
TA
13594 show_adj_route_header(vty, bgp, table, header1, header2,
13595 json, json_scode, json_ocode,
13596 wide);
f20ce998
DS
13597
13598 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13599 pi = pi->next) {
13600 if (pi->peer != peer)
13601 continue;
13602
13603 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13604 continue;
13605
7d3cae70 13606 route_vty_out_tmp(vty, dest,
f20ce998
DS
13607 bgp_dest_get_prefix(dest),
13608 pi->attr, safi, use_json,
13609 json_ar, wide);
d9478df0 13610 (*output_count)++;
f20ce998 13611 }
d62a17ae 13612 }
13613 }
a636c635 13614}
2a71e9ce 13615
d62a17ae 13616static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13617 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13618 const char *rmap_name, uint16_t show_flags)
0b16f239 13619{
d9478df0
TA
13620 struct bgp *bgp;
13621 struct bgp_table *table;
d62a17ae 13622 json_object *json = NULL;
d9478df0
TA
13623 json_object *json_scode = NULL;
13624 json_object *json_ocode = NULL;
13625 json_object *json_ar = NULL;
96f3485c 13626 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13627
d9478df0
TA
13628 /* Init BGP headers here so they're only displayed once
13629 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13630 */
13631 int header1 = 1;
13632 int header2 = 1;
13633
13634 /*
13635 * Initialize variables for each RD
13636 * All prefixes under an RD is aggregated within "json_routes"
13637 */
13638 char rd_str[BUFSIZ] = {0};
13639 json_object *json_routes = NULL;
13640
13641
13642 /* For 2-tier tables, prefix counts need to be
13643 * maintained across multiple runs of show_adj_route()
13644 */
13645 unsigned long output_count_per_rd;
13646 unsigned long filtered_count_per_rd;
13647 unsigned long output_count = 0;
13648 unsigned long filtered_count = 0;
13649
13650 if (use_json) {
d62a17ae 13651 json = json_object_new_object();
d9478df0
TA
13652 json_ar = json_object_new_object();
13653 json_scode = json_object_new_object();
13654 json_ocode = json_object_new_object();
13655
13656 json_object_string_add(json_scode, "suppressed", "s");
13657 json_object_string_add(json_scode, "damped", "d");
13658 json_object_string_add(json_scode, "history", "h");
13659 json_object_string_add(json_scode, "valid", "*");
13660 json_object_string_add(json_scode, "best", ">");
13661 json_object_string_add(json_scode, "multipath", "=");
13662 json_object_string_add(json_scode, "internal", "i");
13663 json_object_string_add(json_scode, "ribFailure", "r");
13664 json_object_string_add(json_scode, "stale", "S");
13665 json_object_string_add(json_scode, "removed", "R");
13666
13667 json_object_string_add(json_ocode, "igp", "i");
13668 json_object_string_add(json_ocode, "egp", "e");
13669 json_object_string_add(json_ocode, "incomplete", "?");
13670 }
0b16f239 13671
d62a17ae 13672 if (!peer || !peer->afc[afi][safi]) {
13673 if (use_json) {
13674 json_object_string_add(
13675 json, "warning",
13676 "No such neighbor or address family");
13677 vty_out(vty, "%s\n", json_object_to_json_string(json));
13678 json_object_free(json);
13679 } else
13680 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13681
d62a17ae 13682 return CMD_WARNING;
13683 }
13684
6392aaa6
PM
13685 if ((type == bgp_show_adj_route_received
13686 || type == bgp_show_adj_route_filtered)
d62a17ae 13687 && !CHECK_FLAG(peer->af_flags[afi][safi],
13688 PEER_FLAG_SOFT_RECONFIG)) {
13689 if (use_json) {
13690 json_object_string_add(
13691 json, "warning",
13692 "Inbound soft reconfiguration not enabled");
13693 vty_out(vty, "%s\n", json_object_to_json_string(json));
13694 json_object_free(json);
13695 } else
13696 vty_out(vty,
13697 "%% Inbound soft reconfiguration not enabled\n");
13698
13699 return CMD_WARNING;
13700 }
0b16f239 13701
d9478df0
TA
13702 bgp = peer->bgp;
13703
13704 /* labeled-unicast routes live in the unicast table */
13705 if (safi == SAFI_LABELED_UNICAST)
13706 table = bgp->rib[afi][SAFI_UNICAST];
13707 else
13708 table = bgp->rib[afi][safi];
13709
13710 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13711 || (safi == SAFI_EVPN)) {
13712
13713 struct bgp_dest *dest;
13714
13715 for (dest = bgp_table_top(table); dest;
13716 dest = bgp_route_next(dest)) {
13717 table = bgp_dest_get_bgp_table_info(dest);
13718 if (!table)
13719 continue;
13720
13721 output_count_per_rd = 0;
13722 filtered_count_per_rd = 0;
13723
13724 if (use_json)
13725 json_routes = json_object_new_object();
13726
13727 const struct prefix_rd *prd;
13728 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13729 dest);
13730
13731 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13732
13733 show_adj_route(vty, peer, table, afi, safi, type,
13734 rmap_name, json, json_routes, json_scode,
13735 json_ocode, show_flags, &header1,
13736 &header2, rd_str, &output_count_per_rd,
13737 &filtered_count_per_rd);
13738
13739 /* Don't include an empty RD in the output! */
13740 if (json_routes && (output_count_per_rd > 0))
13741 json_object_object_add(json_ar, rd_str,
13742 json_routes);
13743
13744 output_count += output_count_per_rd;
13745 filtered_count += filtered_count_per_rd;
13746 }
13747 } else
13748 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13749 json, json_ar, json_scode, json_ocode,
13750 show_flags, &header1, &header2, rd_str,
13751 &output_count, &filtered_count);
13752
13753 if (use_json) {
13754 json_object_object_add(json, "advertisedRoutes", json_ar);
13755 json_object_int_add(json, "totalPrefixCounter", output_count);
13756 json_object_int_add(json, "filteredPrefixCounter",
13757 filtered_count);
13758
13759 vty_out(vty, "%s\n",
13760 json_object_to_json_string_ext(
13761 json, JSON_C_TO_STRING_PRETTY));
13762
13763 if (!output_count && !filtered_count) {
13764 json_object_free(json_scode);
13765 json_object_free(json_ocode);
13766 }
13767
13768 if (json)
13769 json_object_free(json);
13770
13771 } else if (output_count > 0) {
13772 if (filtered_count > 0)
13773 vty_out(vty,
13774 "\nTotal number of prefixes %ld (%ld filtered)\n",
13775 output_count, filtered_count);
13776 else
13777 vty_out(vty, "\nTotal number of prefixes %ld\n",
13778 output_count);
13779 }
0b16f239 13780
d62a17ae 13781 return CMD_SUCCESS;
a636c635 13782}
50ef26d4 13783
f20ce998
DS
13784DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13785 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13786 "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]",
13787 SHOW_STR
13788 IP_STR
13789 BGP_STR
13790 BGP_INSTANCE_HELP_STR
13791 BGP_AFI_HELP_STR
13792 BGP_SAFI_WITH_LABEL_HELP_STR
13793 "Detailed information on TCP and BGP neighbor connections\n"
13794 "Neighbor to display information about\n"
13795 "Neighbor to display information about\n"
13796 "Neighbor on BGP configured interface\n"
13797 "Display the routes selected by best path\n"
13798 JSON_STR
13799 "Increase table width for longer prefixes\n")
13800{
13801 afi_t afi = AFI_IP6;
13802 safi_t safi = SAFI_UNICAST;
13803 char *rmap_name = NULL;
13804 char *peerstr = NULL;
13805 struct bgp *bgp = NULL;
13806 struct peer *peer;
13807 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13808 int idx = 0;
96c81f66 13809 uint16_t show_flags = 0;
96f3485c
MK
13810
13811 if (uj)
13812 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13813
13814 if (wide)
13815 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13816
13817 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13818 &bgp, uj);
13819
13820 if (!idx)
13821 return CMD_WARNING;
13822
13823 argv_find(argv, argc, "neighbors", &idx);
13824 peerstr = argv[++idx]->arg;
13825
13826 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13827 if (!peer)
13828 return CMD_WARNING;
13829
96f3485c
MK
13830 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13831 show_flags);
f20ce998
DS
13832}
13833
ae248832 13834DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13835 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13836 "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 13837 SHOW_STR
13838 IP_STR
13839 BGP_STR
a636c635 13840 BGP_INSTANCE_HELP_STR
7395a2c9 13841 BGP_AFI_HELP_STR
4dd6177e 13842 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13843 "Display the entries for all address families\n"
718e3744 13844 "Detailed information on TCP and BGP neighbor connections\n"
13845 "Neighbor to display information about\n"
13846 "Neighbor to display information about\n"
91d37724 13847 "Neighbor on BGP configured interface\n"
a636c635 13848 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13849 "Display the received routes from neighbor\n"
13850 "Display the filtered routes received from neighbor\n"
a636c635
DW
13851 "Route-map to modify the attributes\n"
13852 "Name of the route map\n"
ae248832
MK
13853 JSON_STR
13854 "Increase table width for longer prefixes\n")
718e3744 13855{
d62a17ae 13856 afi_t afi = AFI_IP6;
13857 safi_t safi = SAFI_UNICAST;
13858 char *rmap_name = NULL;
13859 char *peerstr = NULL;
d62a17ae 13860 struct bgp *bgp = NULL;
13861 struct peer *peer;
6392aaa6 13862 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13863 int idx = 0;
96f3485c 13864 bool first = true;
96c81f66 13865 uint16_t show_flags = 0;
6392aaa6 13866
96f3485c 13867 if (uj) {
d62a17ae 13868 argc--;
96f3485c
MK
13869 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13870 }
13871
13872 if (all) {
13873 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13874 if (argv_find(argv, argc, "ipv4", &idx))
13875 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13876
13877 if (argv_find(argv, argc, "ipv6", &idx))
13878 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13879 }
13880
13881 if (wide)
13882 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13883
9f049418
DS
13884 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13885 &bgp, uj);
13886 if (!idx)
13887 return CMD_WARNING;
13888
d62a17ae 13889 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13890 argv_find(argv, argc, "neighbors", &idx);
13891 peerstr = argv[++idx]->arg;
8c3deaae 13892
d62a17ae 13893 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13894 if (!peer)
13895 return CMD_WARNING;
856ca177 13896
d62a17ae 13897 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13898 type = bgp_show_adj_route_advertised;
13899 else if (argv_find(argv, argc, "received-routes", &idx))
13900 type = bgp_show_adj_route_received;
13901 else if (argv_find(argv, argc, "filtered-routes", &idx))
13902 type = bgp_show_adj_route_filtered;
13903
d62a17ae 13904 if (argv_find(argv, argc, "route-map", &idx))
13905 rmap_name = argv[++idx]->arg;
95cbbd2a 13906
96f3485c
MK
13907 if (!all)
13908 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13909 show_flags);
13910 if (uj)
13911 vty_out(vty, "{\n");
13912
13913 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13914 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13915 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13916 : AFI_IP6;
13917 FOREACH_SAFI (safi) {
96f3485c
MK
13918 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13919 continue;
13920
13921 if (uj) {
13922 if (first)
13923 first = false;
13924 else
13925 vty_out(vty, ",\n");
13926 vty_out(vty, "\"%s\":",
13927 get_afi_safi_str(afi, safi, true));
13928 } else
13929 vty_out(vty, "\nFor address family: %s\n",
13930 get_afi_safi_str(afi, safi, false));
13931
13932 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13933 show_flags);
13934 }
13935 } else {
13936 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13937 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13938 continue;
13939
13940 if (uj) {
13941 if (first)
13942 first = false;
13943 else
13944 vty_out(vty, ",\n");
13945 vty_out(vty, "\"%s\":",
13946 get_afi_safi_str(afi, safi, true));
13947 } else
13948 vty_out(vty, "\nFor address family: %s\n",
13949 get_afi_safi_str(afi, safi, false));
13950
13951 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13952 show_flags);
13953 }
13954 }
13955 if (uj)
13956 vty_out(vty, "}\n");
13957
13958 return CMD_SUCCESS;
95cbbd2a
ML
13959}
13960
718e3744 13961DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13962 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13963 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13964 SHOW_STR
13965 IP_STR
13966 BGP_STR
8c3deaae
QY
13967 "Address Family\n"
13968 "Address Family\n"
718e3744 13969 "Address Family modifier\n"
13970 "Detailed information on TCP and BGP neighbor connections\n"
13971 "Neighbor to display information about\n"
13972 "Neighbor to display information about\n"
91d37724 13973 "Neighbor on BGP configured interface\n"
718e3744 13974 "Display information received from a BGP neighbor\n"
856ca177 13975 "Display the prefixlist filter\n"
9973d184 13976 JSON_STR)
718e3744 13977{
d62a17ae 13978 afi_t afi = AFI_IP6;
13979 safi_t safi = SAFI_UNICAST;
13980 char *peerstr = NULL;
13981
13982 char name[BUFSIZ];
13983 union sockunion su;
13984 struct peer *peer;
13985 int count, ret;
13986
13987 int idx = 0;
13988
13989 /* show [ip] bgp */
13990 if (argv_find(argv, argc, "ip", &idx))
13991 afi = AFI_IP;
13992 /* [<ipv4|ipv6> [unicast]] */
13993 if (argv_find(argv, argc, "ipv4", &idx))
13994 afi = AFI_IP;
13995 if (argv_find(argv, argc, "ipv6", &idx))
13996 afi = AFI_IP6;
13997 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13998 argv_find(argv, argc, "neighbors", &idx);
13999 peerstr = argv[++idx]->arg;
14000
9f049418 14001 bool uj = use_json(argc, argv);
d62a17ae 14002
14003 ret = str2sockunion(peerstr, &su);
14004 if (ret < 0) {
14005 peer = peer_lookup_by_conf_if(NULL, peerstr);
14006 if (!peer) {
14007 if (uj)
14008 vty_out(vty, "{}\n");
14009 else
14010 vty_out(vty,
14011 "%% Malformed address or name: %s\n",
14012 peerstr);
14013 return CMD_WARNING;
14014 }
14015 } else {
14016 peer = peer_lookup(NULL, &su);
14017 if (!peer) {
14018 if (uj)
14019 vty_out(vty, "{}\n");
14020 else
14021 vty_out(vty, "No peer\n");
14022 return CMD_WARNING;
14023 }
14024 }
718e3744 14025
4ced1a2c 14026 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14027 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14028 if (count) {
14029 if (!uj)
14030 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14031 get_afi_safi_str(afi, safi, false));
d62a17ae 14032 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14033 } else {
14034 if (uj)
14035 vty_out(vty, "{}\n");
14036 else
14037 vty_out(vty, "No functional output\n");
14038 }
718e3744 14039
d62a17ae 14040 return CMD_SUCCESS;
14041}
14042
14043static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14044 afi_t afi, safi_t safi,
9f049418 14045 enum bgp_show_type type, bool use_json)
d62a17ae 14046{
96c81f66 14047 uint16_t show_flags = 0;
96f3485c
MK
14048
14049 if (use_json)
14050 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14051
d62a17ae 14052 if (!peer || !peer->afc[afi][safi]) {
14053 if (use_json) {
14054 json_object *json_no = NULL;
14055 json_no = json_object_new_object();
14056 json_object_string_add(
14057 json_no, "warning",
14058 "No such neighbor or address family");
14059 vty_out(vty, "%s\n",
14060 json_object_to_json_string(json_no));
14061 json_object_free(json_no);
14062 } else
14063 vty_out(vty, "%% No such neighbor or address family\n");
14064 return CMD_WARNING;
14065 }
47fc97cc 14066
7daf25a3
TA
14067 /* labeled-unicast routes live in the unicast table */
14068 if (safi == SAFI_LABELED_UNICAST)
14069 safi = SAFI_UNICAST;
14070
1e2ce4f1
DS
14071 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14072 RPKI_NOT_BEING_USED);
718e3744 14073}
14074
dba3c1d3
PG
14075DEFUN (show_ip_bgp_flowspec_routes_detailed,
14076 show_ip_bgp_flowspec_routes_detailed_cmd,
14077 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14078 SHOW_STR
14079 IP_STR
14080 BGP_STR
14081 BGP_INSTANCE_HELP_STR
14082 BGP_AFI_HELP_STR
14083 "SAFI Flowspec\n"
14084 "Detailed information on flowspec entries\n"
14085 JSON_STR)
14086{
14087 afi_t afi = AFI_IP;
14088 safi_t safi = SAFI_UNICAST;
14089 struct bgp *bgp = NULL;
14090 int idx = 0;
9f049418 14091 bool uj = use_json(argc, argv);
96c81f66 14092 uint16_t show_flags = 0;
9f049418 14093
96f3485c 14094 if (uj) {
9f049418 14095 argc--;
96f3485c
MK
14096 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14097 }
dba3c1d3
PG
14098
14099 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14100 &bgp, uj);
dba3c1d3
PG
14101 if (!idx)
14102 return CMD_WARNING;
14103
96f3485c 14104 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14105 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14106}
14107
718e3744 14108DEFUN (show_ip_bgp_neighbor_routes,
14109 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14110 "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 14111 SHOW_STR
14112 IP_STR
14113 BGP_STR
8386ac43 14114 BGP_INSTANCE_HELP_STR
4f280b15 14115 BGP_AFI_HELP_STR
4dd6177e 14116 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14117 "Detailed information on TCP and BGP neighbor connections\n"
14118 "Neighbor to display information about\n"
14119 "Neighbor to display information about\n"
91d37724 14120 "Neighbor on BGP configured interface\n"
2525cf39 14121 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14122 "Display the dampened routes received from neighbor\n"
14123 "Display routes learned from neighbor\n"
9973d184 14124 JSON_STR)
718e3744 14125{
d62a17ae 14126 char *peerstr = NULL;
14127 struct bgp *bgp = NULL;
14128 afi_t afi = AFI_IP6;
14129 safi_t safi = SAFI_UNICAST;
14130 struct peer *peer;
14131 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14132 int idx = 0;
9f049418
DS
14133 bool uj = use_json(argc, argv);
14134
14135 if (uj)
14136 argc--;
bb46e94f 14137
d62a17ae 14138 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14139 &bgp, uj);
d62a17ae 14140 if (!idx)
14141 return CMD_WARNING;
c493f2d8 14142
d62a17ae 14143 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14144 argv_find(argv, argc, "neighbors", &idx);
14145 peerstr = argv[++idx]->arg;
8c3deaae 14146
d62a17ae 14147 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14148 if (!peer)
d62a17ae 14149 return CMD_WARNING;
bb46e94f 14150
d62a17ae 14151 if (argv_find(argv, argc, "flap-statistics", &idx))
14152 sh_type = bgp_show_type_flap_neighbor;
14153 else if (argv_find(argv, argc, "dampened-routes", &idx))
14154 sh_type = bgp_show_type_damp_neighbor;
14155 else if (argv_find(argv, argc, "routes", &idx))
14156 sh_type = bgp_show_type_neighbor;
2525cf39 14157
d62a17ae 14158 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14159}
6b0655a2 14160
734b349e 14161struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14162
d62a17ae 14163struct bgp_distance {
14164 /* Distance value for the IP source prefix. */
d7c0a89a 14165 uint8_t distance;
718e3744 14166
d62a17ae 14167 /* Name of the access-list to be matched. */
14168 char *access_list;
718e3744 14169};
14170
4f280b15
LB
14171DEFUN (show_bgp_afi_vpn_rd_route,
14172 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14173 "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
14174 SHOW_STR
14175 BGP_STR
14176 BGP_AFI_HELP_STR
14177 "Address Family modifier\n"
14178 "Display information for a route distinguisher\n"
14179 "Route Distinguisher\n"
a111dd97 14180 "All Route Distinguishers\n"
7395a2c9
DS
14181 "Network in the BGP routing table to display\n"
14182 "Network in the BGP routing table to display\n"
14183 JSON_STR)
4f280b15 14184{
d62a17ae 14185 int ret;
14186 struct prefix_rd prd;
14187 afi_t afi = AFI_MAX;
14188 int idx = 0;
4f280b15 14189
ff6566f3
DS
14190 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14191 vty_out(vty, "%% Malformed Address Family\n");
14192 return CMD_WARNING;
14193 }
14194
a111dd97
TA
14195 if (!strcmp(argv[5]->arg, "all"))
14196 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14197 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14198 RPKI_NOT_BEING_USED,
14199 use_json(argc, argv));
14200
d62a17ae 14201 ret = str2prefix_rd(argv[5]->arg, &prd);
14202 if (!ret) {
14203 vty_out(vty, "%% Malformed Route Distinguisher\n");
14204 return CMD_WARNING;
14205 }
ff6566f3 14206
d62a17ae 14207 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14208 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14209 use_json(argc, argv));
4f280b15
LB
14210}
14211
d62a17ae 14212static struct bgp_distance *bgp_distance_new(void)
718e3744 14213{
d62a17ae 14214 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14215}
14216
d62a17ae 14217static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14218{
d62a17ae 14219 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14220}
14221
585f1adc
IR
14222static int bgp_distance_set(struct vty *vty, const char *distance_str,
14223 const char *ip_str, const char *access_list_str)
718e3744 14224{
d62a17ae 14225 int ret;
585f1adc
IR
14226 afi_t afi;
14227 safi_t safi;
d62a17ae 14228 struct prefix p;
585f1adc 14229 uint8_t distance;
9bcb3eef 14230 struct bgp_dest *dest;
d62a17ae 14231 struct bgp_distance *bdistance;
718e3744 14232
585f1adc
IR
14233 afi = bgp_node_afi(vty);
14234 safi = bgp_node_safi(vty);
14235
d62a17ae 14236 ret = str2prefix(ip_str, &p);
14237 if (ret == 0) {
585f1adc 14238 vty_out(vty, "Malformed prefix\n");
d62a17ae 14239 return CMD_WARNING_CONFIG_FAILED;
14240 }
718e3744 14241
585f1adc
IR
14242 distance = atoi(distance_str);
14243
d62a17ae 14244 /* Get BGP distance node. */
9bcb3eef
DS
14245 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14246 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14247 if (bdistance)
9bcb3eef 14248 bgp_dest_unlock_node(dest);
ca2e160d 14249 else {
d62a17ae 14250 bdistance = bgp_distance_new();
9bcb3eef 14251 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14252 }
718e3744 14253
d62a17ae 14254 /* Set distance value. */
14255 bdistance->distance = distance;
718e3744 14256
d62a17ae 14257 /* Reset access-list configuration. */
e1b36e13 14258 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14259 if (access_list_str)
14260 bdistance->access_list =
14261 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14262
d62a17ae 14263 return CMD_SUCCESS;
718e3744 14264}
14265
585f1adc
IR
14266static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14267 const char *ip_str, const char *access_list_str)
718e3744 14268{
d62a17ae 14269 int ret;
585f1adc
IR
14270 afi_t afi;
14271 safi_t safi;
d62a17ae 14272 struct prefix p;
585f1adc 14273 int distance;
9bcb3eef 14274 struct bgp_dest *dest;
d62a17ae 14275 struct bgp_distance *bdistance;
718e3744 14276
585f1adc
IR
14277 afi = bgp_node_afi(vty);
14278 safi = bgp_node_safi(vty);
14279
d62a17ae 14280 ret = str2prefix(ip_str, &p);
14281 if (ret == 0) {
585f1adc 14282 vty_out(vty, "Malformed prefix\n");
d62a17ae 14283 return CMD_WARNING_CONFIG_FAILED;
14284 }
718e3744 14285
9bcb3eef
DS
14286 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14287 if (!dest) {
585f1adc 14288 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14289 return CMD_WARNING_CONFIG_FAILED;
14290 }
718e3744 14291
9bcb3eef 14292 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14293 distance = atoi(distance_str);
1f9a9fff 14294
d62a17ae 14295 if (bdistance->distance != distance) {
585f1adc 14296 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14297 bgp_dest_unlock_node(dest);
d62a17ae 14298 return CMD_WARNING_CONFIG_FAILED;
14299 }
718e3744 14300
0a22ddfb 14301 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14302 bgp_distance_free(bdistance);
718e3744 14303
9bcb3eef
DS
14304 bgp_dest_set_bgp_path_info(dest, NULL);
14305 bgp_dest_unlock_node(dest);
14306 bgp_dest_unlock_node(dest);
718e3744 14307
d62a17ae 14308 return CMD_SUCCESS;
718e3744 14309}
14310
718e3744 14311/* Apply BGP information to distance method. */
b8685f9b 14312uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14313 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14314{
9bcb3eef 14315 struct bgp_dest *dest;
801bb996 14316 struct prefix q = {0};
d62a17ae 14317 struct peer *peer;
14318 struct bgp_distance *bdistance;
14319 struct access_list *alist;
14320 struct bgp_static *bgp_static;
14321
14322 if (!bgp)
14323 return 0;
14324
40381db7 14325 peer = pinfo->peer;
d62a17ae 14326
7b7d48e5
DS
14327 if (pinfo->attr->distance)
14328 return pinfo->attr->distance;
14329
801bb996
CS
14330 /* Check source address.
14331 * Note: for aggregate route, peer can have unspec af type.
14332 */
14333 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14334 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14335 return 0;
14336
9bcb3eef
DS
14337 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14338 if (dest) {
14339 bdistance = bgp_dest_get_bgp_distance_info(dest);
14340 bgp_dest_unlock_node(dest);
d62a17ae 14341
14342 if (bdistance->access_list) {
14343 alist = access_list_lookup(afi, bdistance->access_list);
14344 if (alist
14345 && access_list_apply(alist, p) == FILTER_PERMIT)
14346 return bdistance->distance;
14347 } else
14348 return bdistance->distance;
718e3744 14349 }
718e3744 14350
d62a17ae 14351 /* Backdoor check. */
9bcb3eef
DS
14352 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14353 if (dest) {
14354 bgp_static = bgp_dest_get_bgp_static_info(dest);
14355 bgp_dest_unlock_node(dest);
718e3744 14356
d62a17ae 14357 if (bgp_static->backdoor) {
14358 if (bgp->distance_local[afi][safi])
14359 return bgp->distance_local[afi][safi];
14360 else
14361 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14362 }
718e3744 14363 }
718e3744 14364
d62a17ae 14365 if (peer->sort == BGP_PEER_EBGP) {
14366 if (bgp->distance_ebgp[afi][safi])
14367 return bgp->distance_ebgp[afi][safi];
14368 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14369 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14370 if (bgp->distance_ibgp[afi][safi])
14371 return bgp->distance_ibgp[afi][safi];
14372 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14373 } else {
14374 if (bgp->distance_local[afi][safi])
14375 return bgp->distance_local[afi][safi];
14376 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14377 }
718e3744 14378}
14379
a612fb77
DA
14380/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14381 * we should tell ZEBRA update the routes for a specific
14382 * AFI/SAFI to reflect changes in RIB.
14383 */
585f1adc
IR
14384static void bgp_announce_routes_distance_update(struct bgp *bgp,
14385 afi_t update_afi,
14386 safi_t update_safi)
a612fb77
DA
14387{
14388 afi_t afi;
14389 safi_t safi;
14390
14391 FOREACH_AFI_SAFI (afi, safi) {
14392 if (!bgp_fibupd_safi(safi))
14393 continue;
14394
8b54bc30
DA
14395 if (afi != update_afi && safi != update_safi)
14396 continue;
14397
14398 if (BGP_DEBUG(zebra, ZEBRA))
14399 zlog_debug(
14400 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14401 __func__, afi, safi);
14402 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14403 }
14404}
14405
585f1adc
IR
14406DEFUN (bgp_distance,
14407 bgp_distance_cmd,
14408 "distance bgp (1-255) (1-255) (1-255)",
14409 "Define an administrative distance\n"
14410 "BGP distance\n"
14411 "Distance for routes external to the AS\n"
14412 "Distance for routes internal to the AS\n"
14413 "Distance for local routes\n")
718e3744 14414{
585f1adc 14415 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14416 int idx_number = 2;
14417 int idx_number_2 = 3;
14418 int idx_number_3 = 4;
585f1adc
IR
14419 int distance_ebgp = atoi(argv[idx_number]->arg);
14420 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14421 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14422 afi_t afi;
14423 safi_t safi;
718e3744 14424
d62a17ae 14425 afi = bgp_node_afi(vty);
14426 safi = bgp_node_safi(vty);
718e3744 14427
585f1adc
IR
14428 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14429 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14430 || bgp->distance_local[afi][safi] != distance_local) {
14431 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14432 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14433 bgp->distance_local[afi][safi] = distance_local;
14434 bgp_announce_routes_distance_update(bgp, afi, safi);
14435 }
14436 return CMD_SUCCESS;
14437}
37a87b8f 14438
585f1adc
IR
14439DEFUN (no_bgp_distance,
14440 no_bgp_distance_cmd,
14441 "no distance bgp [(1-255) (1-255) (1-255)]",
14442 NO_STR
14443 "Define an administrative distance\n"
14444 "BGP distance\n"
14445 "Distance for routes external to the AS\n"
14446 "Distance for routes internal to the AS\n"
14447 "Distance for local routes\n")
718e3744 14448{
585f1adc 14449 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14450 afi_t afi;
14451 safi_t safi;
37a87b8f
CS
14452
14453 afi = bgp_node_afi(vty);
14454 safi = bgp_node_safi(vty);
14455
585f1adc
IR
14456 if (bgp->distance_ebgp[afi][safi] != 0
14457 || bgp->distance_ibgp[afi][safi] != 0
14458 || bgp->distance_local[afi][safi] != 0) {
14459 bgp->distance_ebgp[afi][safi] = 0;
14460 bgp->distance_ibgp[afi][safi] = 0;
14461 bgp->distance_local[afi][safi] = 0;
14462 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14463 }
585f1adc
IR
14464 return CMD_SUCCESS;
14465}
37a87b8f 14466
37a87b8f 14467
585f1adc
IR
14468DEFUN (bgp_distance_source,
14469 bgp_distance_source_cmd,
14470 "distance (1-255) A.B.C.D/M",
14471 "Define an administrative distance\n"
14472 "Administrative distance\n"
14473 "IP source prefix\n")
14474{
14475 int idx_number = 1;
14476 int idx_ipv4_prefixlen = 2;
14477 bgp_distance_set(vty, argv[idx_number]->arg,
14478 argv[idx_ipv4_prefixlen]->arg, NULL);
14479 return CMD_SUCCESS;
734b349e
MZ
14480}
14481
585f1adc
IR
14482DEFUN (no_bgp_distance_source,
14483 no_bgp_distance_source_cmd,
14484 "no distance (1-255) A.B.C.D/M",
14485 NO_STR
14486 "Define an administrative distance\n"
14487 "Administrative distance\n"
14488 "IP source prefix\n")
37a87b8f 14489{
585f1adc
IR
14490 int idx_number = 2;
14491 int idx_ipv4_prefixlen = 3;
14492 bgp_distance_unset(vty, argv[idx_number]->arg,
14493 argv[idx_ipv4_prefixlen]->arg, NULL);
14494 return CMD_SUCCESS;
37a87b8f
CS
14495}
14496
585f1adc
IR
14497DEFUN (bgp_distance_source_access_list,
14498 bgp_distance_source_access_list_cmd,
14499 "distance (1-255) A.B.C.D/M WORD",
14500 "Define an administrative distance\n"
14501 "Administrative distance\n"
14502 "IP source prefix\n"
14503 "Access list name\n")
37a87b8f 14504{
585f1adc
IR
14505 int idx_number = 1;
14506 int idx_ipv4_prefixlen = 2;
14507 int idx_word = 3;
14508 bgp_distance_set(vty, argv[idx_number]->arg,
14509 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14510 return CMD_SUCCESS;
14511}
718e3744 14512
585f1adc
IR
14513DEFUN (no_bgp_distance_source_access_list,
14514 no_bgp_distance_source_access_list_cmd,
14515 "no distance (1-255) A.B.C.D/M WORD",
14516 NO_STR
14517 "Define an administrative distance\n"
14518 "Administrative distance\n"
14519 "IP source prefix\n"
14520 "Access list name\n")
14521{
14522 int idx_number = 2;
14523 int idx_ipv4_prefixlen = 3;
14524 int idx_word = 4;
14525 bgp_distance_unset(vty, argv[idx_number]->arg,
14526 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14527 return CMD_SUCCESS;
14528}
37a87b8f 14529
585f1adc
IR
14530DEFUN (ipv6_bgp_distance_source,
14531 ipv6_bgp_distance_source_cmd,
14532 "distance (1-255) X:X::X:X/M",
14533 "Define an administrative distance\n"
14534 "Administrative distance\n"
14535 "IP source prefix\n")
14536{
14537 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14538 return CMD_SUCCESS;
14539}
7ebe9748 14540
585f1adc
IR
14541DEFUN (no_ipv6_bgp_distance_source,
14542 no_ipv6_bgp_distance_source_cmd,
14543 "no distance (1-255) X:X::X:X/M",
14544 NO_STR
14545 "Define an administrative distance\n"
14546 "Administrative distance\n"
14547 "IP source prefix\n")
14548{
14549 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14550 return CMD_SUCCESS;
14551}
37a87b8f 14552
585f1adc
IR
14553DEFUN (ipv6_bgp_distance_source_access_list,
14554 ipv6_bgp_distance_source_access_list_cmd,
14555 "distance (1-255) X:X::X:X/M WORD",
14556 "Define an administrative distance\n"
14557 "Administrative distance\n"
14558 "IP source prefix\n"
14559 "Access list name\n")
14560{
14561 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14562 return CMD_SUCCESS;
718e3744 14563}
14564
585f1adc
IR
14565DEFUN (no_ipv6_bgp_distance_source_access_list,
14566 no_ipv6_bgp_distance_source_access_list_cmd,
14567 "no distance (1-255) X:X::X:X/M WORD",
14568 NO_STR
14569 "Define an administrative distance\n"
14570 "Administrative distance\n"
14571 "IP source prefix\n"
14572 "Access list name\n")
718e3744 14573{
585f1adc
IR
14574 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14575 return CMD_SUCCESS;
14576}
37a87b8f 14577
585f1adc
IR
14578DEFUN (bgp_damp_set,
14579 bgp_damp_set_cmd,
14580 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14581 "BGP Specific commands\n"
14582 "Enable route-flap dampening\n"
14583 "Half-life time for the penalty\n"
14584 "Value to start reusing a route\n"
14585 "Value to start suppressing a route\n"
14586 "Maximum duration to suppress a stable route\n")
14587{
14588 VTY_DECLVAR_CONTEXT(bgp, bgp);
14589 int idx_half_life = 2;
14590 int idx_reuse = 3;
14591 int idx_suppress = 4;
14592 int idx_max_suppress = 5;
37a87b8f
CS
14593 int half = DEFAULT_HALF_LIFE * 60;
14594 int reuse = DEFAULT_REUSE;
14595 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14596 int max = 4 * half;
14597
14598 if (argc == 6) {
14599 half = atoi(argv[idx_half_life]->arg) * 60;
14600 reuse = atoi(argv[idx_reuse]->arg);
14601 suppress = atoi(argv[idx_suppress]->arg);
14602 max = atoi(argv[idx_max_suppress]->arg) * 60;
14603 } else if (argc == 3) {
14604 half = atoi(argv[idx_half_life]->arg) * 60;
14605 max = 4 * half;
14606 }
14607
14608 /*
14609 * These can't be 0 but our SA doesn't understand the
14610 * way our cli is constructed
14611 */
14612 assert(reuse);
14613 assert(half);
14614 if (suppress < reuse) {
14615 vty_out(vty,
14616 "Suppress value cannot be less than reuse value \n");
14617 return 0;
14618 }
14619
14620 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14621 reuse, suppress, max);
14622}
14623
14624DEFUN (bgp_damp_unset,
14625 bgp_damp_unset_cmd,
14626 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14627 NO_STR
14628 "BGP Specific commands\n"
14629 "Enable route-flap dampening\n"
14630 "Half-life time for the penalty\n"
14631 "Value to start reusing a route\n"
14632 "Value to start suppressing a route\n"
14633 "Maximum duration to suppress a stable route\n")
14634{
14635 VTY_DECLVAR_CONTEXT(bgp, bgp);
14636 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14637}
14638
718e3744 14639/* Display specified route of BGP table. */
d62a17ae 14640static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14641 const char *ip_str, afi_t afi, safi_t safi,
14642 struct prefix_rd *prd, int prefix_check)
14643{
14644 int ret;
14645 struct prefix match;
9bcb3eef
DS
14646 struct bgp_dest *dest;
14647 struct bgp_dest *rm;
40381db7
DS
14648 struct bgp_path_info *pi;
14649 struct bgp_path_info *pi_temp;
d62a17ae 14650 struct bgp *bgp;
14651 struct bgp_table *table;
14652
14653 /* BGP structure lookup. */
14654 if (view_name) {
14655 bgp = bgp_lookup_by_name(view_name);
14656 if (bgp == NULL) {
14657 vty_out(vty, "%% Can't find BGP instance %s\n",
14658 view_name);
14659 return CMD_WARNING;
14660 }
14661 } else {
14662 bgp = bgp_get_default();
14663 if (bgp == NULL) {
14664 vty_out(vty, "%% No BGP process is configured\n");
14665 return CMD_WARNING;
14666 }
718e3744 14667 }
718e3744 14668
d62a17ae 14669 /* Check IP address argument. */
14670 ret = str2prefix(ip_str, &match);
14671 if (!ret) {
14672 vty_out(vty, "%% address is malformed\n");
14673 return CMD_WARNING;
14674 }
718e3744 14675
d62a17ae 14676 match.family = afi2family(afi);
14677
14678 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14679 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14680 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14681 dest = bgp_route_next(dest)) {
14682 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14683
9bcb3eef 14684 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14685 continue;
9bcb3eef 14686 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14687 if (!table)
ea47320b 14688 continue;
4953391b
DA
14689 rm = bgp_node_match(table, &match);
14690 if (rm == NULL)
ea47320b 14691 continue;
d62a17ae 14692
9bcb3eef 14693 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14694
ea47320b 14695 if (!prefix_check
b54892e0 14696 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14697 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14698 while (pi) {
14699 if (pi->extra && pi->extra->damp_info) {
14700 pi_temp = pi->next;
ea47320b 14701 bgp_damp_info_free(
19971c9a 14702 pi->extra->damp_info,
5c8846f6 14703 1, afi, safi);
40381db7 14704 pi = pi_temp;
ea47320b 14705 } else
40381db7 14706 pi = pi->next;
d62a17ae 14707 }
ea47320b
DL
14708 }
14709
9bcb3eef 14710 bgp_dest_unlock_node(rm);
d62a17ae 14711 }
14712 } else {
4953391b
DA
14713 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14714 if (dest != NULL) {
9bcb3eef 14715 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14716
d62a17ae 14717 if (!prefix_check
9bcb3eef
DS
14718 || dest_p->prefixlen == match.prefixlen) {
14719 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14720 while (pi) {
14721 if (pi->extra && pi->extra->damp_info) {
14722 pi_temp = pi->next;
d62a17ae 14723 bgp_damp_info_free(
19971c9a 14724 pi->extra->damp_info,
5c8846f6 14725 1, afi, safi);
40381db7 14726 pi = pi_temp;
d62a17ae 14727 } else
40381db7 14728 pi = pi->next;
d62a17ae 14729 }
14730 }
14731
9bcb3eef 14732 bgp_dest_unlock_node(dest);
d62a17ae 14733 }
14734 }
718e3744 14735
d62a17ae 14736 return CMD_SUCCESS;
718e3744 14737}
14738
14739DEFUN (clear_ip_bgp_dampening,
14740 clear_ip_bgp_dampening_cmd,
14741 "clear ip bgp dampening",
14742 CLEAR_STR
14743 IP_STR
14744 BGP_STR
14745 "Clear route flap dampening information\n")
14746{
b4f7f45b 14747 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14748 return CMD_SUCCESS;
718e3744 14749}
14750
14751DEFUN (clear_ip_bgp_dampening_prefix,
14752 clear_ip_bgp_dampening_prefix_cmd,
14753 "clear ip bgp dampening A.B.C.D/M",
14754 CLEAR_STR
14755 IP_STR
14756 BGP_STR
14757 "Clear route flap dampening information\n"
0c7b1b01 14758 "IPv4 prefix\n")
718e3744 14759{
d62a17ae 14760 int idx_ipv4_prefixlen = 4;
14761 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14762 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14763}
14764
14765DEFUN (clear_ip_bgp_dampening_address,
14766 clear_ip_bgp_dampening_address_cmd,
14767 "clear ip bgp dampening A.B.C.D",
14768 CLEAR_STR
14769 IP_STR
14770 BGP_STR
14771 "Clear route flap dampening information\n"
14772 "Network to clear damping information\n")
14773{
d62a17ae 14774 int idx_ipv4 = 4;
14775 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14776 SAFI_UNICAST, NULL, 0);
718e3744 14777}
14778
14779DEFUN (clear_ip_bgp_dampening_address_mask,
14780 clear_ip_bgp_dampening_address_mask_cmd,
14781 "clear ip bgp dampening A.B.C.D A.B.C.D",
14782 CLEAR_STR
14783 IP_STR
14784 BGP_STR
14785 "Clear route flap dampening information\n"
14786 "Network to clear damping information\n"
14787 "Network mask\n")
14788{
d62a17ae 14789 int idx_ipv4 = 4;
14790 int idx_ipv4_2 = 5;
14791 int ret;
14792 char prefix_str[BUFSIZ];
718e3744 14793
d62a17ae 14794 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14795 prefix_str, sizeof(prefix_str));
d62a17ae 14796 if (!ret) {
14797 vty_out(vty, "%% Inconsistent address and mask\n");
14798 return CMD_WARNING;
14799 }
718e3744 14800
d62a17ae 14801 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14802 NULL, 0);
718e3744 14803}
6b0655a2 14804
e3b78da8 14805static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14806{
14807 struct vty *vty = arg;
e3b78da8 14808 struct peer *peer = bucket->data;
825d9834
DS
14809 char buf[SU_ADDRSTRLEN];
14810
14811 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14812 sockunion2str(&peer->su, buf, sizeof(buf)));
14813}
14814
2a0e69ae
DS
14815DEFUN (show_bgp_listeners,
14816 show_bgp_listeners_cmd,
14817 "show bgp listeners",
14818 SHOW_STR
14819 BGP_STR
14820 "Display Listen Sockets and who created them\n")
14821{
14822 bgp_dump_listener_info(vty);
14823
14824 return CMD_SUCCESS;
14825}
14826
825d9834
DS
14827DEFUN (show_bgp_peerhash,
14828 show_bgp_peerhash_cmd,
14829 "show bgp peerhash",
14830 SHOW_STR
14831 BGP_STR
14832 "Display information about the BGP peerhash\n")
14833{
14834 struct list *instances = bm->bgp;
14835 struct listnode *node;
14836 struct bgp *bgp;
14837
14838 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14839 vty_out(vty, "BGP: %s\n", bgp->name);
14840 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14841 vty);
14842 }
14843
14844 return CMD_SUCCESS;
14845}
14846
587ff0fd 14847/* also used for encap safi */
2b791107
DL
14848static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14849 afi_t afi, safi_t safi)
d62a17ae 14850{
9bcb3eef
DS
14851 struct bgp_dest *pdest;
14852 struct bgp_dest *dest;
d62a17ae 14853 struct bgp_table *table;
b54892e0
DS
14854 const struct prefix *p;
14855 const struct prefix_rd *prd;
d62a17ae 14856 struct bgp_static *bgp_static;
14857 mpls_label_t label;
d62a17ae 14858 char rdbuf[RD_ADDRSTRLEN];
14859
14860 /* Network configuration. */
9bcb3eef
DS
14861 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14862 pdest = bgp_route_next(pdest)) {
14863 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14864 if (!table)
ea47320b 14865 continue;
d62a17ae 14866
9bcb3eef
DS
14867 for (dest = bgp_table_top(table); dest;
14868 dest = bgp_route_next(dest)) {
14869 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14870 if (bgp_static == NULL)
ea47320b 14871 continue;
d62a17ae 14872
9bcb3eef
DS
14873 p = bgp_dest_get_prefix(dest);
14874 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14875 pdest);
d62a17ae 14876
ea47320b 14877 /* "network" configuration display. */
06b9f471 14878 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14879 label = decode_label(&bgp_static->label);
14880
8228a9a7 14881 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14882 if (safi == SAFI_MPLS_VPN)
14883 vty_out(vty, " label %u", label);
14884
14885 if (bgp_static->rmap.name)
14886 vty_out(vty, " route-map %s",
14887 bgp_static->rmap.name);
e2a86ad9
DS
14888
14889 if (bgp_static->backdoor)
14890 vty_out(vty, " backdoor");
14891
ea47320b
DL
14892 vty_out(vty, "\n");
14893 }
14894 }
d62a17ae 14895}
14896
2b791107
DL
14897static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14898 afi_t afi, safi_t safi)
d62a17ae 14899{
9bcb3eef
DS
14900 struct bgp_dest *pdest;
14901 struct bgp_dest *dest;
d62a17ae 14902 struct bgp_table *table;
b54892e0
DS
14903 const struct prefix *p;
14904 const struct prefix_rd *prd;
d62a17ae 14905 struct bgp_static *bgp_static;
ff44f570 14906 char buf[PREFIX_STRLEN * 2];
d62a17ae 14907 char buf2[SU_ADDRSTRLEN];
14908 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14909 char esi_buf[ESI_BYTES];
d62a17ae 14910
14911 /* Network configuration. */
9bcb3eef
DS
14912 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14913 pdest = bgp_route_next(pdest)) {
14914 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14915 if (!table)
ea47320b 14916 continue;
d62a17ae 14917
9bcb3eef
DS
14918 for (dest = bgp_table_top(table); dest;
14919 dest = bgp_route_next(dest)) {
14920 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14921 if (bgp_static == NULL)
ea47320b 14922 continue;
d62a17ae 14923
ea47320b 14924 char *macrouter = NULL;
d62a17ae 14925
ea47320b
DL
14926 if (bgp_static->router_mac)
14927 macrouter = prefix_mac2str(
14928 bgp_static->router_mac, NULL, 0);
14929 if (bgp_static->eth_s_id)
0a50c248
AK
14930 esi_to_str(bgp_static->eth_s_id,
14931 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14932 p = bgp_dest_get_prefix(dest);
14933 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14934
ea47320b 14935 /* "network" configuration display. */
06b9f471 14936 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14937 if (p->u.prefix_evpn.route_type == 5) {
14938 char local_buf[PREFIX_STRLEN];
3714a385 14939 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14940 struct prefix_evpn *)p)
14941 ? AF_INET
14942 : AF_INET6;
3714a385 14943 inet_ntop(family,
14944 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14945 local_buf, PREFIX_STRLEN);
772270f3
QY
14946 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14947 p->u.prefix_evpn.prefix_addr
14948 .ip_prefix_length);
197cb530
PG
14949 } else {
14950 prefix2str(p, buf, sizeof(buf));
14951 }
ea47320b 14952
a4d82a8a
PZ
14953 if (bgp_static->gatewayIp.family == AF_INET
14954 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14955 inet_ntop(bgp_static->gatewayIp.family,
14956 &bgp_static->gatewayIp.u.prefix, buf2,
14957 sizeof(buf2));
ea47320b 14958 vty_out(vty,
7bcc8dac 14959 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14960 buf, rdbuf,
14961 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14962 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14963 macrouter);
14964
0a22ddfb 14965 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14966 }
14967 }
3da6fcd5
PG
14968}
14969
718e3744 14970/* Configuration of static route announcement and aggregate
14971 information. */
2b791107
DL
14972void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14973 safi_t safi)
d62a17ae 14974{
9bcb3eef 14975 struct bgp_dest *dest;
b54892e0 14976 const struct prefix *p;
d62a17ae 14977 struct bgp_static *bgp_static;
14978 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14979
2b791107
DL
14980 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14981 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14982 return;
14983 }
d62a17ae 14984
2b791107
DL
14985 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14986 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14987 return;
14988 }
d62a17ae 14989
14990 /* Network configuration. */
9bcb3eef
DS
14991 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14992 dest = bgp_route_next(dest)) {
14993 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14994 if (bgp_static == NULL)
ea47320b 14995 continue;
d62a17ae 14996
9bcb3eef 14997 p = bgp_dest_get_prefix(dest);
d62a17ae 14998
8228a9a7 14999 vty_out(vty, " network %pFX", p);
d62a17ae 15000
ea47320b
DL
15001 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15002 vty_out(vty, " label-index %u",
15003 bgp_static->label_index);
d62a17ae 15004
ea47320b
DL
15005 if (bgp_static->rmap.name)
15006 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15007
15008 if (bgp_static->backdoor)
15009 vty_out(vty, " backdoor");
718e3744 15010
ea47320b
DL
15011 vty_out(vty, "\n");
15012 }
15013
d62a17ae 15014 /* Aggregate-address configuration. */
9bcb3eef
DS
15015 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15016 dest = bgp_route_next(dest)) {
15017 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15018 if (bgp_aggregate == NULL)
ea47320b 15019 continue;
d62a17ae 15020
9bcb3eef 15021 p = bgp_dest_get_prefix(dest);
d62a17ae 15022
8228a9a7 15023 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15024
ea47320b
DL
15025 if (bgp_aggregate->as_set)
15026 vty_out(vty, " as-set");
d62a17ae 15027
ea47320b
DL
15028 if (bgp_aggregate->summary_only)
15029 vty_out(vty, " summary-only");
718e3744 15030
20894f50
DA
15031 if (bgp_aggregate->rmap.name)
15032 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15033
229757f1
DA
15034 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15035 vty_out(vty, " origin %s",
15036 bgp_origin2str(bgp_aggregate->origin));
15037
6aabb15d
RZ
15038 if (bgp_aggregate->match_med)
15039 vty_out(vty, " matching-MED-only");
15040
365ab2e7
RZ
15041 if (bgp_aggregate->suppress_map_name)
15042 vty_out(vty, " suppress-map %s",
15043 bgp_aggregate->suppress_map_name);
15044
ea47320b
DL
15045 vty_out(vty, "\n");
15046 }
d62a17ae 15047}
734b349e 15048
2b791107 15049void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15050 safi_t safi)
d62a17ae 15051{
9bcb3eef 15052 struct bgp_dest *dest;
d62a17ae 15053 struct bgp_distance *bdistance;
15054
15055 /* Distance configuration. */
15056 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15057 && bgp->distance_local[afi][safi]
15058 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15059 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15060 || bgp->distance_local[afi][safi]
15061 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15062 vty_out(vty, " distance bgp %d %d %d\n",
15063 bgp->distance_ebgp[afi][safi],
15064 bgp->distance_ibgp[afi][safi],
15065 bgp->distance_local[afi][safi]);
15066 }
734b349e 15067
9bcb3eef
DS
15068 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15069 dest = bgp_route_next(dest)) {
15070 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15071 if (bdistance != NULL)
56ca3b5b 15072 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15073 bdistance->distance, dest,
d62a17ae 15074 bdistance->access_list ? bdistance->access_list
15075 : "");
ca2e160d 15076 }
718e3744 15077}
15078
15079/* Allocate routing table structure and install commands. */
d62a17ae 15080void bgp_route_init(void)
15081{
15082 afi_t afi;
15083 safi_t safi;
15084
15085 /* Init BGP distance table. */
05c7a1cc 15086 FOREACH_AFI_SAFI (afi, safi)
960035b2 15087 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15088
15089 /* IPv4 BGP commands. */
15090 install_element(BGP_NODE, &bgp_table_map_cmd);
15091 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15092 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15093
554b3b10 15094 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15095
15096 /* IPv4 unicast configuration. */
15097 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15098 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15099 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15100
554b3b10 15101 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15102
15103 /* IPv4 multicast configuration. */
15104 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15105 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15106 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15107 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15108
15109 /* IPv4 labeled-unicast configuration. */
fb985e0c 15110 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15111 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15112
d62a17ae 15113 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15114 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 15115 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15116 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 15117 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 15118 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15119 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15120 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15121
15122 install_element(VIEW_NODE,
15123 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15124 install_element(VIEW_NODE,
15125 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15126 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15127 install_element(VIEW_NODE,
15128 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15129#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15130 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15131#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15132 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15133 install_element(VIEW_NODE,
44c69747 15134 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15135
d62a17ae 15136 /* BGP dampening clear commands */
15137 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15138 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15139
d62a17ae 15140 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15141 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15142
15143 /* prefix count */
15144 install_element(ENABLE_NODE,
15145 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15146#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15147 install_element(ENABLE_NODE,
15148 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15149#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15150
d62a17ae 15151 /* New config IPv6 BGP commands. */
15152 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15153 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15154 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15155
554b3b10 15156 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15157
15158 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15159
fb985e0c
DA
15160 /* IPv6 labeled unicast address family. */
15161 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15162 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15163
d62a17ae 15164 install_element(BGP_NODE, &bgp_distance_cmd);
15165 install_element(BGP_NODE, &no_bgp_distance_cmd);
15166 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15167 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15168 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15169 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15170 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15171 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15172 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15173 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15174 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15175 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15176 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15177 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15178 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15179 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15180 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15181 install_element(BGP_IPV4M_NODE,
15182 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15183 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15184 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15185 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15186 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15187 install_element(BGP_IPV6_NODE,
15188 &ipv6_bgp_distance_source_access_list_cmd);
15189 install_element(BGP_IPV6_NODE,
15190 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15191 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15192 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15193 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15194 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15195 install_element(BGP_IPV6M_NODE,
15196 &ipv6_bgp_distance_source_access_list_cmd);
15197 install_element(BGP_IPV6M_NODE,
15198 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15199
ef5f4b23 15200 /* BGP dampening */
585f1adc
IR
15201 install_element(BGP_NODE, &bgp_damp_set_cmd);
15202 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15203 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15204 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15205 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15206 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15207 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15208 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15209 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15210 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15211 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15212 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15213 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15214 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15215
15216 /* Large Communities */
15217 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15218 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15219
15220 /* show bgp ipv4 flowspec detailed */
15221 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15222
2a0e69ae 15223 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15224 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15225}
15226
15227void bgp_route_finish(void)
15228{
15229 afi_t afi;
15230 safi_t safi;
15231
05c7a1cc
QY
15232 FOREACH_AFI_SAFI (afi, safi) {
15233 bgp_table_unlock(bgp_distance_table[afi][safi]);
15234 bgp_distance_table[afi][safi] = NULL;
15235 }
228da428 15236}