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