]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #12034 from opensourcerouting/fix/gr_hard_notification
[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
2aad8c42
MS
105/* Render dest to prefix_rd based on safi */
106static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
107 safi_t safi);
108
718e3744 109/* Extern from bgp_dump.c */
dde72586
SH
110extern const char *bgp_origin_str[];
111extern const char *bgp_origin_long_str[];
3742de8d 112
b7d08f5a 113/* PMSI strings. */
114#define PMSI_TNLTYPE_STR_NO_INFO "No info"
115#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116static const struct message bgp_pmsi_tnltype_str[] = {
117 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 125 {0}
126};
b7d08f5a 127
9df8b37c 128#define VRFID_NONE_STR "-"
46aeabed 129#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 130
4a11bf2c 131DEFINE_HOOK(bgp_process,
9bcb3eef
DS
132 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
133 struct peer *peer, bool withdraw),
8451921b 134 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 135
4056a5f6
RZ
136/** Test if path is suppressed. */
137static bool bgp_path_suppressed(struct bgp_path_info *pi)
138{
139 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
140 return false;
141
142 return listcount(pi->extra->aggr_suppressors) > 0;
143}
4a11bf2c 144
9bcb3eef 145struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 146 safi_t safi, const struct prefix *p,
d62a17ae 147 struct prefix_rd *prd)
148{
9bcb3eef
DS
149 struct bgp_dest *dest;
150 struct bgp_dest *pdest = NULL;
d62a17ae 151
152 assert(table);
d62a17ae 153
154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN)) {
9bcb3eef 156 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 157
9bcb3eef
DS
158 if (!bgp_dest_has_bgp_path_info_data(pdest))
159 bgp_dest_set_bgp_table_info(
160 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 161 else
9bcb3eef
DS
162 bgp_dest_unlock_node(pdest);
163 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 164 }
718e3744 165
9bcb3eef 166 dest = bgp_node_get(table, p);
718e3744 167
d62a17ae 168 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
169 || (safi == SAFI_EVPN))
9bcb3eef 170 dest->pdest = pdest;
718e3744 171
9bcb3eef 172 return dest;
718e3744 173}
6b0655a2 174
9bcb3eef 175struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 176 safi_t safi, const struct prefix *p,
d62a17ae 177 struct prefix_rd *prd)
128ea8ab 178{
9bcb3eef
DS
179 struct bgp_dest *dest;
180 struct bgp_dest *pdest = NULL;
128ea8ab 181
d62a17ae 182 if (!table)
183 return NULL;
128ea8ab 184
d62a17ae 185 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
186 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
187 pdest = bgp_node_lookup(table, (struct prefix *)prd);
188 if (!pdest)
d62a17ae 189 return NULL;
128ea8ab 190
9bcb3eef
DS
191 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
192 bgp_dest_unlock_node(pdest);
d62a17ae 193 return NULL;
194 }
128ea8ab 195
9bcb3eef 196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 197 }
128ea8ab 198
9bcb3eef 199 dest = bgp_node_lookup(table, p);
128ea8ab 200
9bcb3eef 201 return dest;
128ea8ab 202}
203
18ee8310
DS
204/* Allocate bgp_path_info_extra */
205static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 206{
4b7e6066
DS
207 struct bgp_path_info_extra *new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
209 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
210 new->label[0] = MPLS_INVALID_LABEL;
211 new->num_labels = 0;
3e3708cb
PG
212 new->bgp_fs_pbr = NULL;
213 new->bgp_fs_iprule = NULL;
d62a17ae 214 return new;
fb982c25
PJ
215}
216
a2e219fe 217void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 218{
4b7e6066 219 struct bgp_path_info_extra *e;
d62a17ae 220
c93a3b77
DS
221 if (!extra || !*extra)
222 return;
d62a17ae 223
c93a3b77 224 e = *extra;
4538f895 225 if (e->damp_info)
b4f7f45b
IR
226 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
227 e->damp_info->safi);
4538f895 228
c93a3b77
DS
229 e->damp_info = NULL;
230 if (e->parent) {
40381db7 231 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 232
40381db7 233 if (bpi->net) {
0e70e6c8
DL
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
237 *
40381db7
DS
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
0e70e6c8
DL
241 */
242 unsigned refcount;
243
40381db7 244 bpi = bgp_path_info_lock(bpi);
c10e14e9 245 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 246 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 247 if (!refcount)
40381db7
DS
248 bpi->net = NULL;
249 bgp_path_info_unlock(bpi);
0e70e6c8 250 }
18ee8310 251 bgp_path_info_unlock(e->parent);
c93a3b77 252 e->parent = NULL;
d62a17ae 253 }
c93a3b77
DS
254
255 if (e->bgp_orig)
256 bgp_unlock(e->bgp_orig);
c26edcda 257
4cd690ae
PG
258 if (e->peer_orig)
259 peer_unlock(e->peer_orig);
260
ff3bf9a4
DS
261 if (e->aggr_suppressors)
262 list_delete(&e->aggr_suppressors);
263
60605cbc
AK
264 if (e->mh_info)
265 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 266
ce3c0614
PG
267 if ((*extra)->bgp_fs_iprule)
268 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 269 if ((*extra)->bgp_fs_pbr)
6a154c88 270 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 271 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
272}
273
18ee8310
DS
274/* Get bgp_path_info extra information for the given bgp_path_info, lazy
275 * allocated if required.
fb982c25 276 */
40381db7 277struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 278{
40381db7
DS
279 if (!pi->extra)
280 pi->extra = bgp_path_info_extra_new();
281 return pi->extra;
fb982c25
PJ
282}
283
718e3744 284/* Free bgp route information. */
9b6d8fcf 285static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 286{
05864da7 287 bgp_attr_unintern(&path->attr);
fb018d25 288
9b6d8fcf
DS
289 bgp_unlink_nexthop(path);
290 bgp_path_info_extra_free(&path->extra);
291 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
292 if (path->net)
293 bgp_addpath_free_info_data(&path->tx_addpath,
294 &path->net->tx_addpath);
718e3744 295
9b6d8fcf 296 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 297
9b6d8fcf 298 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 299}
300
9b6d8fcf 301struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 302{
9b6d8fcf
DS
303 path->lock++;
304 return path;
200df115 305}
306
9b6d8fcf 307struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 308{
9b6d8fcf
DS
309 assert(path && path->lock > 0);
310 path->lock--;
d62a17ae 311
9b6d8fcf 312 if (path->lock == 0) {
9b6d8fcf 313 bgp_path_info_free(path);
d62a17ae 314 return NULL;
315 }
200df115 316
9b6d8fcf 317 return path;
200df115 318}
319
f009ff26 320/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 321static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 322{
323 struct peer *peer;
324 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 325 bool set_flag = false;
f009ff26 326 struct bgp *bgp = NULL;
327 struct bgp_table *table = NULL;
328 afi_t afi = 0;
329 safi_t safi = 0;
f009ff26 330
331 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
332 * then the route selection is deferred
333 */
9bcb3eef 334 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 335 return 0;
336
9bcb3eef 337 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 338 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 339 zlog_debug(
56ca3b5b
DL
340 "Route %pBD is in workqueue and being processed, not deferred.",
341 dest);
b54892e0 342
5f9c1aa2 343 return 0;
344 }
345
9bcb3eef 346 table = bgp_dest_table(dest);
f009ff26 347 if (table) {
348 bgp = table->bgp;
349 afi = table->afi;
350 safi = table->safi;
351 }
352
9bcb3eef 353 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 354 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
355 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
356 continue;
357
358 /* Route selection is deferred if there is a stale path which
359 * which indicates peer is in restart mode
360 */
36235319
QY
361 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
362 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 363 set_flag = true;
f009ff26 364 } else {
365 /* If the peer is graceful restart capable and peer is
366 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
367 */
368 peer = old_pi->peer;
36235319
QY
369 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
370 && BGP_PEER_RESTARTING_MODE(peer)
371 && (old_pi
372 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 373 set_flag = true;
f009ff26 374 }
375 }
376 if (set_flag)
377 break;
378 }
379
380 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
381 * is active
382 */
2ba1fe69 383 if (set_flag && table) {
f009ff26 384 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
385 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
386 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 387 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 388 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
389 zlog_debug("DEFER route %pBD, dest %p", dest,
390 dest);
f009ff26 391 return 0;
392 }
393 }
394 return -1;
395}
396
9bcb3eef 397void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 398{
4b7e6066 399 struct bgp_path_info *top;
718e3744 400
9bcb3eef 401 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 402
6f94b685 403 pi->next = top;
40381db7 404 pi->prev = NULL;
d62a17ae 405 if (top)
40381db7 406 top->prev = pi;
9bcb3eef 407 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 408
40381db7 409 bgp_path_info_lock(pi);
9bcb3eef 410 bgp_dest_lock_node(dest);
40381db7 411 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 412 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 413 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 414}
415
d62a17ae 416/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 417 completion callback *only* */
9bcb3eef 418void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 419{
40381db7
DS
420 if (pi->next)
421 pi->next->prev = pi->prev;
422 if (pi->prev)
423 pi->prev->next = pi->next;
d62a17ae 424 else
9bcb3eef 425 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 426
40381db7
DS
427 bgp_path_info_mpath_dequeue(pi);
428 bgp_path_info_unlock(pi);
7fd28dd2 429 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 430 bgp_dest_unlock_node(dest);
718e3744 431}
432
9bcb3eef 433void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 434{
9bcb3eef 435 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 436 /* set of previous already took care of pcount */
40381db7 437 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 438}
439
18ee8310 440/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
441 called when a route is deleted and then quickly re-added before the
442 deletion has been processed */
9bcb3eef 443void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 444{
9bcb3eef 445 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 446 /* unset of previous already took care of pcount */
40381db7 447 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
448}
449
d62a17ae 450/* Adjust pcount as required */
9bcb3eef 451static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 452{
d62a17ae 453 struct bgp_table *table;
67174041 454
9bcb3eef 455 assert(dest && bgp_dest_table(dest));
40381db7 456 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 457
9bcb3eef 458 table = bgp_dest_table(dest);
67174041 459
40381db7 460 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 461 return;
462
40381db7
DS
463 if (!BGP_PATH_COUNTABLE(pi)
464 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 465
40381db7 466 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 467
468 /* slight hack, but more robust against errors. */
40381db7
DS
469 if (pi->peer->pcount[table->afi][table->safi])
470 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 471 else
450971aa 472 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 473 "Asked to decrement 0 prefix count for peer");
40381db7
DS
474 } else if (BGP_PATH_COUNTABLE(pi)
475 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
476 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
477 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 478 }
1a392d46
PJ
479}
480
40381db7
DS
481static int bgp_label_index_differs(struct bgp_path_info *pi1,
482 struct bgp_path_info *pi2)
28d58fd7 483{
40381db7 484 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 485}
1a392d46 486
18ee8310 487/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
488 * This is here primarily to keep prefix-count in check.
489 */
9bcb3eef 490void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 491 uint32_t flag)
1a392d46 492{
40381db7 493 SET_FLAG(pi->flags, flag);
d62a17ae 494
495 /* early bath if we know it's not a flag that changes countability state
496 */
497 if (!CHECK_FLAG(flag,
1defdda8 498 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 499 return;
500
9bcb3eef 501 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
502}
503
9bcb3eef 504void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 505 uint32_t flag)
1a392d46 506{
40381db7 507 UNSET_FLAG(pi->flags, flag);
d62a17ae 508
509 /* early bath if we know it's not a flag that changes countability state
510 */
511 if (!CHECK_FLAG(flag,
1defdda8 512 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 513 return;
514
9bcb3eef 515 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
516}
517
718e3744 518/* Get MED value. If MED value is missing and "bgp bestpath
519 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 520static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 521{
522 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
523 return attr->med;
524 else {
892fedb6 525 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 526 return BGP_MED_MAX;
527 else
528 return 0;
529 }
718e3744 530}
531
7533cad7
QY
532void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
533 size_t buf_len)
2ec1e66f 534{
40381db7 535 if (pi->addpath_rx_id)
7533cad7
QY
536 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
537 pi->peer->host, pi->addpath_rx_id);
d62a17ae 538 else
7533cad7 539 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 540}
9fbdd100 541
da0c0ef7
KM
542
543/*
544 * Get the ultimate path info.
545 */
546struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
547{
548 struct bgp_path_info *bpi_ultimate;
549
550 if (info->sub_type != BGP_ROUTE_IMPORTED)
551 return info;
552
553 for (bpi_ultimate = info;
554 bpi_ultimate->extra && bpi_ultimate->extra->parent;
555 bpi_ultimate = bpi_ultimate->extra->parent)
556 ;
557
558 return bpi_ultimate;
559}
560
d62a17ae 561/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
562 */
18ee8310
DS
563static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
564 struct bgp_path_info *exist, int *paths_eq,
565 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
566 char *pfx_buf, afi_t afi, safi_t safi,
567 enum bgp_path_selection_reason *reason)
d62a17ae 568{
5df26422 569 const struct prefix *new_p;
d62a17ae 570 struct attr *newattr, *existattr;
3061acc2
DA
571 enum bgp_peer_sort new_sort;
572 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
573 uint32_t new_pref;
574 uint32_t exist_pref;
575 uint32_t new_med;
576 uint32_t exist_med;
577 uint32_t new_weight;
578 uint32_t exist_weight;
d62a17ae 579 uint32_t newm, existm;
580 struct in_addr new_id;
581 struct in_addr exist_id;
582 int new_cluster;
583 int exist_cluster;
584 int internal_as_route;
585 int confed_as_route;
04d14c8b 586 int ret = 0;
ee88563a
JM
587 int igp_metric_ret = 0;
588 int peer_sort_ret = -1;
d62a17ae 589 char new_buf[PATH_ADDPATH_STR_BUFFER];
590 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
591 uint32_t new_mm_seq;
592 uint32_t exist_mm_seq;
6d8c603a 593 int nh_cmp;
d071f237
AK
594 esi_t *exist_esi;
595 esi_t *new_esi;
596 bool same_esi;
597 bool old_proxy;
598 bool new_proxy;
33c6e933 599 bool new_origin, exist_origin;
da0c0ef7 600 struct bgp_path_info *bpi_ultimate;
d62a17ae 601
602 *paths_eq = 0;
603
604 /* 0. Null check. */
605 if (new == NULL) {
fdf81fa0 606 *reason = bgp_path_selection_none;
d62a17ae 607 if (debug)
608 zlog_debug("%s: new is NULL", pfx_buf);
609 return 0;
610 }
2ec1e66f 611
da0c0ef7
KM
612 if (debug) {
613 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
614 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 615 sizeof(new_buf));
da0c0ef7 616 }
718e3744 617
d62a17ae 618 if (exist == NULL) {
fdf81fa0 619 *reason = bgp_path_selection_first;
d62a17ae 620 if (debug)
4378495a
DS
621 zlog_debug("%s(%s): %s is the initial bestpath",
622 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 623 return 1;
624 }
2ec1e66f 625
d62a17ae 626 if (debug) {
da0c0ef7
KM
627 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
628 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 629 sizeof(exist_buf));
4378495a
DS
630 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
631 pfx_buf, bgp->name_pretty, new_buf, new->flags,
632 exist_buf, exist->flags);
d62a17ae 633 }
8ff56318 634
d62a17ae 635 newattr = new->attr;
636 existattr = exist->attr;
637
1479ed2f
DA
638 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
639 * Capability" to a neighbor MUST perform the following upon receiving
640 * a route from that neighbor with the "LLGR_STALE" community, or upon
641 * attaching the "LLGR_STALE" community itself per Section 4.2:
642 *
643 * Treat the route as the least-preferred in route selection (see
644 * below). See the Risks of Depreferencing Routes section (Section 5.2)
645 * for a discussion of potential risks inherent in doing this.
646 */
9a706b42
DA
647 if (bgp_attr_get_community(newattr) &&
648 community_include(bgp_attr_get_community(newattr),
649 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
650 if (debug)
651 zlog_debug(
652 "%s: %s wins over %s due to LLGR_STALE community",
653 pfx_buf, new_buf, exist_buf);
654 return 0;
655 }
656
9a706b42
DA
657 if (bgp_attr_get_community(existattr) &&
658 community_include(bgp_attr_get_community(existattr),
659 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
660 if (debug)
661 zlog_debug(
662 "%s: %s loses to %s due to LLGR_STALE community",
663 pfx_buf, new_buf, exist_buf);
664 return 1;
665 }
666
5df26422
NS
667 new_p = bgp_dest_get_prefix(new->net);
668
d62a17ae 669 /* For EVPN routes, we cannot just go by local vs remote, we have to
670 * look at the MAC mobility sequence number, if present.
671 */
5df26422
NS
672 if ((safi == SAFI_EVPN)
673 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 674 /* This is an error condition described in RFC 7432 Section
675 * 15.2. The RFC
676 * states that in this scenario "the PE MUST alert the operator"
677 * but it
678 * does not state what other action to take. In order to provide
679 * some
680 * consistency in this scenario we are going to prefer the path
681 * with the
682 * sticky flag.
683 */
684 if (newattr->sticky != existattr->sticky) {
685 if (!debug) {
5df26422
NS
686 prefix2str(new_p, pfx_buf,
687 sizeof(*pfx_buf)
688 * PREFIX2STR_BUFFER);
18ee8310 689 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
690 new, new_buf, sizeof(new_buf));
691 bgp_path_info_path_with_addpath_rx_str(
692 exist, exist_buf, sizeof(exist_buf));
d62a17ae 693 }
694
695 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 696 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
697 if (debug)
698 zlog_debug(
699 "%s: %s wins over %s due to sticky MAC flag",
700 pfx_buf, new_buf, exist_buf);
d62a17ae 701 return 1;
702 }
703
704 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 705 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
706 if (debug)
707 zlog_debug(
708 "%s: %s loses to %s due to sticky MAC flag",
709 pfx_buf, new_buf, exist_buf);
d62a17ae 710 return 0;
711 }
712 }
128ea8ab 713
d071f237
AK
714 new_esi = bgp_evpn_attr_get_esi(newattr);
715 exist_esi = bgp_evpn_attr_get_esi(existattr);
716 if (bgp_evpn_is_esi_valid(new_esi) &&
717 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
718 same_esi = true;
719 } else {
720 same_esi = false;
721 }
722
723 /* If both paths have the same non-zero ES and
724 * one path is local it wins.
725 * PS: Note the local path wins even if the remote
726 * has the higher MM seq. The local path's
727 * MM seq will be fixed up to match the highest
728 * rem seq, subsequently.
729 */
730 if (same_esi) {
731 char esi_buf[ESI_STR_LEN];
732
733 if (bgp_evpn_is_path_local(bgp, new)) {
734 *reason = bgp_path_selection_evpn_local_path;
735 if (debug)
736 zlog_debug(
737 "%s: %s wins over %s as ES %s is same and local",
738 pfx_buf, new_buf, exist_buf,
739 esi_to_str(new_esi, esi_buf,
740 sizeof(esi_buf)));
741 return 1;
742 }
743 if (bgp_evpn_is_path_local(bgp, exist)) {
744 *reason = bgp_path_selection_evpn_local_path;
745 if (debug)
746 zlog_debug(
747 "%s: %s loses to %s as ES %s is same and local",
748 pfx_buf, new_buf, exist_buf,
749 esi_to_str(new_esi, esi_buf,
750 sizeof(esi_buf)));
751 return 0;
752 }
753 }
754
d62a17ae 755 new_mm_seq = mac_mobility_seqnum(newattr);
756 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 757
d62a17ae 758 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 759 *reason = bgp_path_selection_evpn_seq;
d62a17ae 760 if (debug)
761 zlog_debug(
762 "%s: %s wins over %s due to MM seq %u > %u",
763 pfx_buf, new_buf, exist_buf, new_mm_seq,
764 exist_mm_seq);
765 return 1;
766 }
8ff56318 767
d62a17ae 768 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 769 *reason = bgp_path_selection_evpn_seq;
d62a17ae 770 if (debug)
771 zlog_debug(
772 "%s: %s loses to %s due to MM seq %u < %u",
773 pfx_buf, new_buf, exist_buf, new_mm_seq,
774 exist_mm_seq);
775 return 0;
776 }
6d8c603a 777
d071f237
AK
778 /* if the sequence numbers and ESI are the same and one path
779 * is non-proxy it wins (over proxy)
780 */
781 new_proxy = bgp_evpn_attr_is_proxy(newattr);
782 old_proxy = bgp_evpn_attr_is_proxy(existattr);
783 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
784 old_proxy != new_proxy) {
785 if (!new_proxy) {
786 *reason = bgp_path_selection_evpn_non_proxy;
787 if (debug)
788 zlog_debug(
789 "%s: %s wins over %s, same seq/es and non-proxy",
790 pfx_buf, new_buf, exist_buf);
791 return 1;
792 }
793
794 *reason = bgp_path_selection_evpn_non_proxy;
795 if (debug)
796 zlog_debug(
797 "%s: %s loses to %s, same seq/es and non-proxy",
798 pfx_buf, new_buf, exist_buf);
799 return 0;
800 }
801
6d8c603a
AK
802 /*
803 * if sequence numbers are the same path with the lowest IP
804 * wins
805 */
806 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
807 if (nh_cmp < 0) {
fdf81fa0 808 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
809 if (debug)
810 zlog_debug(
23d0a753 811 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 812 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 813 &new->attr->nexthop);
6d8c603a
AK
814 return 1;
815 }
816 if (nh_cmp > 0) {
fdf81fa0 817 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
818 if (debug)
819 zlog_debug(
23d0a753 820 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 821 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 822 &new->attr->nexthop);
6d8c603a
AK
823 return 0;
824 }
d62a17ae 825 }
9fbdd100 826
d62a17ae 827 /* 1. Weight check. */
d62a17ae 828 new_weight = newattr->weight;
829 exist_weight = existattr->weight;
8ff56318 830
d62a17ae 831 if (new_weight > exist_weight) {
fdf81fa0 832 *reason = bgp_path_selection_weight;
d62a17ae 833 if (debug)
834 zlog_debug("%s: %s wins over %s due to weight %d > %d",
835 pfx_buf, new_buf, exist_buf, new_weight,
836 exist_weight);
837 return 1;
838 }
718e3744 839
d62a17ae 840 if (new_weight < exist_weight) {
fdf81fa0 841 *reason = bgp_path_selection_weight;
d62a17ae 842 if (debug)
843 zlog_debug("%s: %s loses to %s due to weight %d < %d",
844 pfx_buf, new_buf, exist_buf, new_weight,
845 exist_weight);
846 return 0;
847 }
9fbdd100 848
d62a17ae 849 /* 2. Local preference check. */
850 new_pref = exist_pref = bgp->default_local_pref;
851
852 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
853 new_pref = newattr->local_pref;
854 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
855 exist_pref = existattr->local_pref;
856
857 if (new_pref > exist_pref) {
fdf81fa0 858 *reason = bgp_path_selection_local_pref;
d62a17ae 859 if (debug)
860 zlog_debug(
861 "%s: %s wins over %s due to localpref %d > %d",
862 pfx_buf, new_buf, exist_buf, new_pref,
863 exist_pref);
864 return 1;
865 }
718e3744 866
d62a17ae 867 if (new_pref < exist_pref) {
fdf81fa0 868 *reason = bgp_path_selection_local_pref;
d62a17ae 869 if (debug)
870 zlog_debug(
871 "%s: %s loses to %s due to localpref %d < %d",
872 pfx_buf, new_buf, exist_buf, new_pref,
873 exist_pref);
874 return 0;
875 }
9fbdd100 876
d62a17ae 877 /* 3. Local route check. We prefer:
878 * - BGP_ROUTE_STATIC
879 * - BGP_ROUTE_AGGREGATE
880 * - BGP_ROUTE_REDISTRIBUTE
881 */
33c6e933
DS
882 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
883 new->sub_type == BGP_ROUTE_IMPORTED);
884 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
885 exist->sub_type == BGP_ROUTE_IMPORTED);
886
887 if (new_origin && !exist_origin) {
fdf81fa0 888 *reason = bgp_path_selection_local_route;
d62a17ae 889 if (debug)
890 zlog_debug(
891 "%s: %s wins over %s due to preferred BGP_ROUTE type",
892 pfx_buf, new_buf, exist_buf);
893 return 1;
894 }
718e3744 895
33c6e933 896 if (!new_origin && exist_origin) {
fdf81fa0 897 *reason = bgp_path_selection_local_route;
d62a17ae 898 if (debug)
899 zlog_debug(
900 "%s: %s loses to %s due to preferred BGP_ROUTE type",
901 pfx_buf, new_buf, exist_buf);
902 return 0;
6811845b 903 }
718e3744 904
da0c0ef7
KM
905 /* Here if these are imported routes then get ultimate pi for
906 * path compare.
907 */
908 new = bgp_get_imported_bpi_ultimate(new);
909 exist = bgp_get_imported_bpi_ultimate(exist);
910 newattr = new->attr;
911 existattr = exist->attr;
912
d62a17ae 913 /* 4. AS path length check. */
892fedb6 914 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 915 int exist_hops = aspath_count_hops(existattr->aspath);
916 int exist_confeds = aspath_count_confeds(existattr->aspath);
917
892fedb6 918 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 919 int aspath_hops;
920
921 aspath_hops = aspath_count_hops(newattr->aspath);
922 aspath_hops += aspath_count_confeds(newattr->aspath);
923
924 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 925 *reason = bgp_path_selection_confed_as_path;
d62a17ae 926 if (debug)
927 zlog_debug(
928 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
929 pfx_buf, new_buf, exist_buf,
930 aspath_hops,
931 (exist_hops + exist_confeds));
932 return 1;
933 }
934
935 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 936 *reason = bgp_path_selection_confed_as_path;
d62a17ae 937 if (debug)
938 zlog_debug(
939 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
940 pfx_buf, new_buf, exist_buf,
941 aspath_hops,
942 (exist_hops + exist_confeds));
943 return 0;
944 }
945 } else {
946 int newhops = aspath_count_hops(newattr->aspath);
947
948 if (newhops < exist_hops) {
fdf81fa0 949 *reason = bgp_path_selection_as_path;
d62a17ae 950 if (debug)
951 zlog_debug(
952 "%s: %s wins over %s due to aspath hopcount %d < %d",
953 pfx_buf, new_buf, exist_buf,
954 newhops, exist_hops);
955 return 1;
956 }
957
958 if (newhops > exist_hops) {
fdf81fa0 959 *reason = bgp_path_selection_as_path;
d62a17ae 960 if (debug)
961 zlog_debug(
962 "%s: %s loses to %s due to aspath hopcount %d > %d",
963 pfx_buf, new_buf, exist_buf,
964 newhops, exist_hops);
965 return 0;
966 }
967 }
968 }
9fbdd100 969
d62a17ae 970 /* 5. Origin check. */
971 if (newattr->origin < existattr->origin) {
fdf81fa0 972 *reason = bgp_path_selection_origin;
d62a17ae 973 if (debug)
974 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
975 pfx_buf, new_buf, exist_buf,
976 bgp_origin_long_str[newattr->origin],
977 bgp_origin_long_str[existattr->origin]);
978 return 1;
979 }
718e3744 980
d62a17ae 981 if (newattr->origin > existattr->origin) {
fdf81fa0 982 *reason = bgp_path_selection_origin;
d62a17ae 983 if (debug)
984 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
985 pfx_buf, new_buf, exist_buf,
986 bgp_origin_long_str[newattr->origin],
987 bgp_origin_long_str[existattr->origin]);
988 return 0;
989 }
718e3744 990
d62a17ae 991 /* 6. MED check. */
992 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
993 && aspath_count_hops(existattr->aspath) == 0);
994 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
995 && aspath_count_confeds(existattr->aspath) > 0
996 && aspath_count_hops(newattr->aspath) == 0
997 && aspath_count_hops(existattr->aspath) == 0);
998
892fedb6
DA
999 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
1000 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 1001 || aspath_cmp_left(newattr->aspath, existattr->aspath)
1002 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1003 || internal_as_route) {
1004 new_med = bgp_med_value(new->attr, bgp);
1005 exist_med = bgp_med_value(exist->attr, bgp);
1006
1007 if (new_med < exist_med) {
fdf81fa0 1008 *reason = bgp_path_selection_med;
d62a17ae 1009 if (debug)
1010 zlog_debug(
1011 "%s: %s wins over %s due to MED %d < %d",
1012 pfx_buf, new_buf, exist_buf, new_med,
1013 exist_med);
1014 return 1;
1015 }
8ff56318 1016
d62a17ae 1017 if (new_med > exist_med) {
fdf81fa0 1018 *reason = bgp_path_selection_med;
d62a17ae 1019 if (debug)
1020 zlog_debug(
1021 "%s: %s loses to %s due to MED %d > %d",
1022 pfx_buf, new_buf, exist_buf, new_med,
1023 exist_med);
1024 return 0;
1025 }
1026 }
9fbdd100 1027
d62a17ae 1028 /* 7. Peer type check. */
1029 new_sort = new->peer->sort;
1030 exist_sort = exist->peer->sort;
1031
1032 if (new_sort == BGP_PEER_EBGP
1033 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1034 *reason = bgp_path_selection_peer;
d62a17ae 1035 if (debug)
1036 zlog_debug(
1037 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1038 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1039 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1040 return 1;
1041 peer_sort_ret = 1;
d62a17ae 1042 }
718e3744 1043
d62a17ae 1044 if (exist_sort == BGP_PEER_EBGP
1045 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1046 *reason = bgp_path_selection_peer;
d62a17ae 1047 if (debug)
1048 zlog_debug(
1049 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1050 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1051 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1052 return 0;
1053 peer_sort_ret = 0;
d62a17ae 1054 }
8ff56318 1055
d62a17ae 1056 /* 8. IGP metric check. */
1057 newm = existm = 0;
8ff56318 1058
d62a17ae 1059 if (new->extra)
1060 newm = new->extra->igpmetric;
1061 if (exist->extra)
1062 existm = exist->extra->igpmetric;
9fbdd100 1063
d62a17ae 1064 if (newm < existm) {
ee88563a 1065 if (debug && peer_sort_ret < 0)
d62a17ae 1066 zlog_debug(
d588b995 1067 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1068 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1069 igp_metric_ret = 1;
d62a17ae 1070 }
718e3744 1071
d62a17ae 1072 if (newm > existm) {
ee88563a 1073 if (debug && peer_sort_ret < 0)
d62a17ae 1074 zlog_debug(
d588b995 1075 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1076 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1077 igp_metric_ret = 0;
5e242b0d 1078 }
5e242b0d 1079
d62a17ae 1080 /* 9. Same IGP metric. Compare the cluster list length as
1081 representative of IGP hops metric. Rewrite the metric value
1082 pair (newm, existm) with the cluster list length. Prefer the
1083 path with smaller cluster list length. */
1084 if (newm == existm) {
aa53c036
DS
1085 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1086 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1087 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1088 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1089 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1090
1091 if (newm < existm) {
ee88563a 1092 if (debug && peer_sort_ret < 0)
d62a17ae 1093 zlog_debug(
d588b995 1094 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1095 pfx_buf, new_buf, exist_buf,
1096 newm, existm);
ee88563a 1097 igp_metric_ret = 1;
d62a17ae 1098 }
1099
1100 if (newm > existm) {
ee88563a 1101 if (debug && peer_sort_ret < 0)
d62a17ae 1102 zlog_debug(
d588b995 1103 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1104 pfx_buf, new_buf, exist_buf,
1105 newm, existm);
ee88563a 1106 igp_metric_ret = 0;
d62a17ae 1107 }
1108 }
1109 }
31a4638f 1110
d62a17ae 1111 /* 10. confed-external vs. confed-internal */
1112 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1113 if (new_sort == BGP_PEER_CONFED
1114 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1115 *reason = bgp_path_selection_confed;
d62a17ae 1116 if (debug)
1117 zlog_debug(
1118 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1119 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1120 if (!CHECK_FLAG(bgp->flags,
1121 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1122 return 1;
1123 peer_sort_ret = 1;
d62a17ae 1124 }
718e3744 1125
d62a17ae 1126 if (exist_sort == BGP_PEER_CONFED
1127 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1128 *reason = bgp_path_selection_confed;
d62a17ae 1129 if (debug)
1130 zlog_debug(
1131 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1132 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1133 if (!CHECK_FLAG(bgp->flags,
1134 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1135 return 0;
1136 peer_sort_ret = 0;
d62a17ae 1137 }
1138 }
718e3744 1139
d62a17ae 1140 /* 11. Maximum path check. */
1141 if (newm == existm) {
1142 /* If one path has a label but the other does not, do not treat
1143 * them as equals for multipath
1144 */
a4d82a8a 1145 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1146 != (exist->extra
b57ba6d2 1147 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1148 if (debug)
1149 zlog_debug(
1150 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1151 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1152 } else if (CHECK_FLAG(bgp->flags,
1153 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1154
1155 /*
1156 * For the two paths, all comparison steps till IGP
1157 * metric
1158 * have succeeded - including AS_PATH hop count. Since
1159 * 'bgp
1160 * bestpath as-path multipath-relax' knob is on, we
1161 * don't need
1162 * an exact match of AS_PATH. Thus, mark the paths are
1163 * equal.
1164 * That will trigger both these paths to get into the
1165 * multipath
1166 * array.
1167 */
1168 *paths_eq = 1;
1169
1170 if (debug)
1171 zlog_debug(
1172 "%s: %s and %s are equal via multipath-relax",
1173 pfx_buf, new_buf, exist_buf);
1174 } else if (new->peer->sort == BGP_PEER_IBGP) {
1175 if (aspath_cmp(new->attr->aspath,
1176 exist->attr->aspath)) {
1177 *paths_eq = 1;
1178
1179 if (debug)
1180 zlog_debug(
1181 "%s: %s and %s are equal via matching aspaths",
1182 pfx_buf, new_buf, exist_buf);
1183 }
1184 } else if (new->peer->as == exist->peer->as) {
1185 *paths_eq = 1;
1186
1187 if (debug)
1188 zlog_debug(
1189 "%s: %s and %s are equal via same remote-as",
1190 pfx_buf, new_buf, exist_buf);
1191 }
1192 } else {
1193 /*
1194 * TODO: If unequal cost ibgp multipath is enabled we can
1195 * mark the paths as equal here instead of returning
1196 */
ee88563a
JM
1197
1198 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1199 * if either step 7 or 10 (peer type checks) yielded a winner,
1200 * that result was returned immediately. Returning from step 10
1201 * ignored the return value computed in steps 8 and 9 (IGP
1202 * metric checks). In order to preserve that behavior, if
1203 * peer_sort_ret is set, return that rather than igp_metric_ret.
1204 */
1205 ret = peer_sort_ret;
1206 if (peer_sort_ret < 0) {
1207 ret = igp_metric_ret;
1208 if (debug) {
1209 if (ret == 1)
1210 zlog_debug(
1211 "%s: %s wins over %s after IGP metric comparison",
1212 pfx_buf, new_buf, exist_buf);
1213 else
1214 zlog_debug(
1215 "%s: %s loses to %s after IGP metric comparison",
1216 pfx_buf, new_buf, exist_buf);
1217 }
1218 *reason = bgp_path_selection_igp_metric;
d62a17ae 1219 }
1220 return ret;
1221 }
718e3744 1222
ee88563a
JM
1223 /*
1224 * At this point, the decision whether to set *paths_eq = 1 has been
1225 * completed. If we deferred returning because of bestpath peer-type
1226 * relax configuration, return now.
1227 */
1228 if (peer_sort_ret >= 0)
1229 return peer_sort_ret;
1230
d62a17ae 1231 /* 12. If both paths are external, prefer the path that was received
1232 first (the oldest one). This step minimizes route-flap, since a
1233 newer path won't displace an older one, even if it was the
1234 preferred route based on the additional decision criteria below. */
892fedb6 1235 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1236 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1237 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1238 *reason = bgp_path_selection_older;
d62a17ae 1239 if (debug)
1240 zlog_debug(
1241 "%s: %s wins over %s due to oldest external",
1242 pfx_buf, new_buf, exist_buf);
1243 return 1;
1244 }
9fbdd100 1245
1defdda8 1246 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1247 *reason = bgp_path_selection_older;
d62a17ae 1248 if (debug)
1249 zlog_debug(
1250 "%s: %s loses to %s due to oldest external",
1251 pfx_buf, new_buf, exist_buf);
1252 return 0;
1253 }
1254 }
718e3744 1255
ce5002c6 1256 /* 13. Router-ID comparison. */
d62a17ae 1257 /* If one of the paths is "stale", the corresponding peer router-id will
1258 * be 0 and would always win over the other path. If originator id is
ce5002c6 1259 * used for the comparison, it will decide which path is better.
d62a17ae 1260 */
1261 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1262 new_id.s_addr = newattr->originator_id.s_addr;
1263 else
1264 new_id.s_addr = new->peer->remote_id.s_addr;
1265 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1266 exist_id.s_addr = existattr->originator_id.s_addr;
1267 else
1268 exist_id.s_addr = exist->peer->remote_id.s_addr;
1269
1270 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1271 *reason = bgp_path_selection_router_id;
d62a17ae 1272 if (debug)
1273 zlog_debug(
1274 "%s: %s wins over %s due to Router-ID comparison",
1275 pfx_buf, new_buf, exist_buf);
1276 return 1;
1277 }
718e3744 1278
d62a17ae 1279 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1280 *reason = bgp_path_selection_router_id;
d62a17ae 1281 if (debug)
1282 zlog_debug(
1283 "%s: %s loses to %s due to Router-ID comparison",
1284 pfx_buf, new_buf, exist_buf);
1285 return 0;
1286 }
9fbdd100 1287
ce5002c6 1288 /* 14. Cluster length comparison. */
d62a17ae 1289 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1290 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1291
1292 if (new_cluster < exist_cluster) {
fdf81fa0 1293 *reason = bgp_path_selection_cluster_length;
d62a17ae 1294 if (debug)
1295 zlog_debug(
1296 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1297 pfx_buf, new_buf, exist_buf, new_cluster,
1298 exist_cluster);
1299 return 1;
1300 }
718e3744 1301
d62a17ae 1302 if (new_cluster > exist_cluster) {
fdf81fa0 1303 *reason = bgp_path_selection_cluster_length;
d62a17ae 1304 if (debug)
1305 zlog_debug(
1306 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1307 pfx_buf, new_buf, exist_buf, new_cluster,
1308 exist_cluster);
1309 return 0;
1310 }
9fbdd100 1311
ce5002c6 1312 /* 15. Neighbor address comparison. */
d62a17ae 1313 /* Do this only if neither path is "stale" as stale paths do not have
1314 * valid peer information (as the connection may or may not be up).
1315 */
1defdda8 1316 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1317 *reason = bgp_path_selection_stale;
d62a17ae 1318 if (debug)
1319 zlog_debug(
1320 "%s: %s wins over %s due to latter path being STALE",
1321 pfx_buf, new_buf, exist_buf);
1322 return 1;
1323 }
0de5153c 1324
1defdda8 1325 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1326 *reason = bgp_path_selection_stale;
d62a17ae 1327 if (debug)
1328 zlog_debug(
1329 "%s: %s loses to %s due to former path being STALE",
1330 pfx_buf, new_buf, exist_buf);
1331 return 0;
1332 }
718e3744 1333
d62a17ae 1334 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1335 if (new->peer->su_remote == NULL) {
1336 *reason = bgp_path_selection_local_configured;
d62a17ae 1337 return 0;
fdf81fa0
DS
1338 }
1339 if (exist->peer->su_remote == NULL) {
1340 *reason = bgp_path_selection_local_configured;
d62a17ae 1341 return 1;
fdf81fa0 1342 }
9fbdd100 1343
d62a17ae 1344 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1345
1346 if (ret == 1) {
fdf81fa0 1347 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1348 if (debug)
1349 zlog_debug(
1350 "%s: %s loses to %s due to Neighor IP comparison",
1351 pfx_buf, new_buf, exist_buf);
1352 return 0;
1353 }
1354
1355 if (ret == -1) {
fdf81fa0 1356 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1357 if (debug)
1358 zlog_debug(
1359 "%s: %s wins over %s due to Neighor IP comparison",
1360 pfx_buf, new_buf, exist_buf);
1361 return 1;
1362 }
9fbdd100 1363
fdf81fa0 1364 *reason = bgp_path_selection_default;
d62a17ae 1365 if (debug)
1366 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1367 pfx_buf, new_buf, exist_buf);
718e3744 1368
d62a17ae 1369 return 1;
718e3744 1370}
1371
d071f237
AK
1372
1373int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1374 struct bgp_path_info *exist, int *paths_eq)
1375{
1376 enum bgp_path_selection_reason reason;
1377 char pfx_buf[PREFIX2STR_BUFFER];
1378
1379 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1380 AFI_L2VPN, SAFI_EVPN, &reason);
1381}
1382
65efcfce
LB
1383/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1384 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1385 * multipath is enabled
65efcfce 1386 * This version is compatible with */
18ee8310
DS
1387int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1388 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1389 afi_t afi, safi_t safi,
1390 enum bgp_path_selection_reason *reason)
d62a17ae 1391{
1392 int paths_eq;
1393 int ret;
18ee8310 1394 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1395 afi, safi, reason);
d62a17ae 1396
1397 if (paths_eq)
1398 ret = 0;
1399 else {
1400 if (ret == 1)
1401 ret = -1;
1402 else
1403 ret = 1;
1404 }
1405 return ret;
65efcfce
LB
1406}
1407
5a1ae2c2
DS
1408static enum filter_type bgp_input_filter(struct peer *peer,
1409 const struct prefix *p,
d62a17ae 1410 struct attr *attr, afi_t afi,
1411 safi_t safi)
718e3744 1412{
d62a17ae 1413 struct bgp_filter *filter;
6401252f 1414 enum filter_type ret = FILTER_PERMIT;
718e3744 1415
d62a17ae 1416 filter = &peer->filter[afi][safi];
718e3744 1417
d62a17ae 1418#define FILTER_EXIST_WARN(F, f, filter) \
1419 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1420 zlog_debug("%s: Could not find configured input %s-list %s!", \
1421 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1422
1423 if (DISTRIBUTE_IN_NAME(filter)) {
1424 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1425
6401252f
QY
1426 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1427 == FILTER_DENY) {
1428 ret = FILTER_DENY;
1429 goto done;
1430 }
d62a17ae 1431 }
1432
1433 if (PREFIX_LIST_IN_NAME(filter)) {
1434 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1435
6401252f
QY
1436 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1437 == PREFIX_DENY) {
1438 ret = FILTER_DENY;
1439 goto done;
1440 }
d62a17ae 1441 }
1442
1443 if (FILTER_LIST_IN_NAME(filter)) {
1444 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1445
1446 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1447 == AS_FILTER_DENY) {
1448 ret = FILTER_DENY;
1449 goto done;
1450 }
d62a17ae 1451 }
1452
6401252f 1453done:
c7bb4f00 1454 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1455 char pfxprint[PREFIX2STR_BUFFER];
1456
1457 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1458 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1459 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1460 }
1461
1462 return ret;
650f76c2 1463#undef FILTER_EXIST_WARN
718e3744 1464}
1465
b8685f9b
DS
1466static enum filter_type bgp_output_filter(struct peer *peer,
1467 const struct prefix *p,
d62a17ae 1468 struct attr *attr, afi_t afi,
1469 safi_t safi)
718e3744 1470{
d62a17ae 1471 struct bgp_filter *filter;
6401252f 1472 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1473
1474 filter = &peer->filter[afi][safi];
1475
1476#define FILTER_EXIST_WARN(F, f, filter) \
1477 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1478 zlog_debug("%s: Could not find configured output %s-list %s!", \
1479 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1480
d62a17ae 1481 if (DISTRIBUTE_OUT_NAME(filter)) {
1482 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1483
6401252f
QY
1484 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1485 == FILTER_DENY) {
1486 ret = FILTER_DENY;
1487 goto done;
1488 }
d62a17ae 1489 }
1490
1491 if (PREFIX_LIST_OUT_NAME(filter)) {
1492 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1493
d62a17ae 1494 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1495 == PREFIX_DENY) {
1496 ret = FILTER_DENY;
1497 goto done;
1498 }
d62a17ae 1499 }
718e3744 1500
d62a17ae 1501 if (FILTER_LIST_OUT_NAME(filter)) {
1502 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1503
d62a17ae 1504 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1505 == AS_FILTER_DENY) {
1506 ret = FILTER_DENY;
1507 goto done;
1508 }
1509 }
1510
c7bb4f00 1511 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1512 char pfxprint[PREFIX2STR_BUFFER];
1513
1514 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1515 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1516 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1517 }
718e3744 1518
6401252f
QY
1519done:
1520 return ret;
650f76c2 1521#undef FILTER_EXIST_WARN
718e3744 1522}
1523
1524/* If community attribute includes no_export then return 1. */
3dc339cd 1525static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1526{
9a706b42 1527 if (bgp_attr_get_community(attr)) {
d62a17ae 1528 /* NO_ADVERTISE check. */
9a706b42
DA
1529 if (community_include(bgp_attr_get_community(attr),
1530 COMMUNITY_NO_ADVERTISE))
3dc339cd 1531 return true;
d62a17ae 1532
1533 /* NO_EXPORT check. */
9a706b42
DA
1534 if (peer->sort == BGP_PEER_EBGP &&
1535 community_include(bgp_attr_get_community(attr),
1536 COMMUNITY_NO_EXPORT))
3dc339cd 1537 return true;
d62a17ae 1538
1539 /* NO_EXPORT_SUBCONFED check. */
1540 if (peer->sort == BGP_PEER_EBGP
1541 || peer->sort == BGP_PEER_CONFED)
9a706b42 1542 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1543 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1544 return true;
d62a17ae 1545 }
3dc339cd 1546 return false;
718e3744 1547}
1548
1549/* Route reflection loop check. */
3dc339cd 1550static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1551{
d62a17ae 1552 struct in_addr cluster_id;
779fee93 1553 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1554
779fee93 1555 if (cluster) {
d62a17ae 1556 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1557 cluster_id = peer->bgp->cluster_id;
1558 else
1559 cluster_id = peer->bgp->router_id;
1560
779fee93 1561 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1562 return true;
d62a17ae 1563 }
3dc339cd 1564 return false;
718e3744 1565}
6b0655a2 1566
d864dd9e
EB
1567static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1568{
1569 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1570 if (peer->local_role == ROLE_PROVIDER ||
1571 peer->local_role == ROLE_RS_SERVER)
1572 return true;
1573 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1574 return true;
1575 return false;
1576 }
1577 if (peer->local_role == ROLE_CUSTOMER ||
1578 peer->local_role == ROLE_PEER ||
1579 peer->local_role == ROLE_RS_CLIENT) {
1580 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1581 attr->otc = peer->as;
1582 }
1583 return false;
1584}
1585
1586static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1587{
1588 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1589 if (peer->local_role == ROLE_CUSTOMER ||
1590 peer->local_role == ROLE_RS_CLIENT ||
1591 peer->local_role == ROLE_PEER)
1592 return true;
1593 return false;
1594 }
1595 if (peer->local_role == ROLE_PROVIDER ||
1596 peer->local_role == ROLE_PEER ||
1597 peer->local_role == ROLE_RS_SERVER) {
1598 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1599 attr->otc = peer->bgp->as;
1600 }
1601 return false;
1602}
1603
5a78f2bc
EB
1604static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1605{
1606 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1607}
1608
5a1ae2c2 1609static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1610 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1611 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1612 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1613{
d62a17ae 1614 struct bgp_filter *filter;
82b692c0
LK
1615 struct bgp_path_info rmap_path = { 0 };
1616 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1617 route_map_result_t ret;
1618 struct route_map *rmap = NULL;
718e3744 1619
d62a17ae 1620 filter = &peer->filter[afi][safi];
718e3744 1621
d62a17ae 1622 /* Apply default weight value. */
1623 if (peer->weight[afi][safi])
1624 attr->weight = peer->weight[afi][safi];
718e3744 1625
d62a17ae 1626 if (rmap_name) {
1627 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1628
d62a17ae 1629 if (rmap == NULL)
1630 return RMAP_DENY;
1631 } else {
1632 if (ROUTE_MAP_IN_NAME(filter)) {
1633 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1634
d62a17ae 1635 if (rmap == NULL)
1636 return RMAP_DENY;
1637 }
1638 }
0b16f239 1639
d62a17ae 1640 /* Route map apply. */
1641 if (rmap) {
6006b807 1642 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1643 /* Duplicate current value to new structure for modification. */
40381db7
DS
1644 rmap_path.peer = peer;
1645 rmap_path.attr = attr;
82b692c0 1646 rmap_path.extra = &extra;
9bcb3eef 1647 rmap_path.net = dest;
196c6b09 1648
82b692c0
LK
1649 extra.num_labels = num_labels;
1650 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1651 memcpy(extra.label, label,
1652 num_labels * sizeof(mpls_label_t));
718e3744 1653
d62a17ae 1654 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1655
d62a17ae 1656 /* Apply BGP route map to the attribute. */
1782514f 1657 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1658
d62a17ae 1659 peer->rmap_type = 0;
0b16f239 1660
1f2263be 1661 if (ret == RMAP_DENYMATCH)
d62a17ae 1662 return RMAP_DENY;
0b16f239 1663 }
d62a17ae 1664 return RMAP_PERMIT;
0b16f239
DS
1665}
1666
5f040085 1667static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1668 struct attr *attr, afi_t afi, safi_t safi,
1669 const char *rmap_name)
0b16f239 1670{
40381db7 1671 struct bgp_path_info rmap_path;
d62a17ae 1672 route_map_result_t ret;
1673 struct route_map *rmap = NULL;
d7c0a89a 1674 uint8_t rmap_type;
0b16f239 1675
b787157a
DS
1676 /*
1677 * So if we get to this point and have no rmap_name
1678 * we want to just show the output as it currently
1679 * exists.
1680 */
1681 if (!rmap_name)
1682 return RMAP_PERMIT;
0b16f239 1683
d62a17ae 1684 /* Apply default weight value. */
1685 if (peer->weight[afi][safi])
1686 attr->weight = peer->weight[afi][safi];
0b16f239 1687
b787157a 1688 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1689
b787157a
DS
1690 /*
1691 * If we have a route map name and we do not find
1692 * the routemap that means we have an implicit
1693 * deny.
1694 */
1695 if (rmap == NULL)
1696 return RMAP_DENY;
0b16f239 1697
6006b807 1698 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1699 /* Route map apply. */
544be979 1700 /* Duplicate current value to new structure for modification. */
40381db7
DS
1701 rmap_path.peer = peer;
1702 rmap_path.attr = attr;
0b16f239 1703
0f672529 1704 rmap_type = peer->rmap_type;
b787157a 1705 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1706
b787157a 1707 /* Apply BGP route map to the attribute. */
1782514f 1708 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1709
0f672529 1710 peer->rmap_type = rmap_type;
b787157a
DS
1711
1712 if (ret == RMAP_DENYMATCH)
1713 /*
1714 * caller has multiple error paths with bgp_attr_flush()
1715 */
1716 return RMAP_DENY;
ac41b2a2 1717
d62a17ae 1718 return RMAP_PERMIT;
718e3744 1719}
6b0655a2 1720
5000f21c 1721/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1722static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1723 struct peer *peer, struct attr *attr)
1724{
1725 if (peer->sort == BGP_PEER_EBGP
1726 && (peer_af_flag_check(peer, afi, safi,
1727 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1728 || peer_af_flag_check(peer, afi, safi,
1729 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1730 || peer_af_flag_check(peer, afi, safi,
1731 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1732 || peer_af_flag_check(peer, afi, safi,
1733 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1734 // Take action on the entire aspath
1735 if (peer_af_flag_check(peer, afi, safi,
1736 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1737 || peer_af_flag_check(peer, afi, safi,
1738 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1739 if (peer_af_flag_check(
1740 peer, afi, safi,
1741 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1742 attr->aspath = aspath_replace_private_asns(
bf26b80e 1743 attr->aspath, bgp->as, peer->as);
d62a17ae 1744
179d5a0e
TA
1745 /*
1746 * Even if the aspath consists of just private ASNs we
1747 * need to walk the AS-Path to maintain all instances
1748 * of the peer's ASN to break possible loops.
1749 */
d62a17ae 1750 else
1751 attr->aspath = aspath_remove_private_asns(
bf26b80e 1752 attr->aspath, peer->as);
d62a17ae 1753 }
1754
1755 // 'all' was not specified so the entire aspath must be private
1756 // ASNs
1757 // for us to do anything
1758 else if (aspath_private_as_check(attr->aspath)) {
1759 if (peer_af_flag_check(
1760 peer, afi, safi,
1761 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1762 attr->aspath = aspath_replace_private_asns(
bf26b80e 1763 attr->aspath, bgp->as, peer->as);
d62a17ae 1764 else
179d5a0e
TA
1765 /*
1766 * Walk the aspath to retain any instances of
1767 * the peer_asn
1768 */
1769 attr->aspath = aspath_remove_private_asns(
1770 attr->aspath, peer->as);
d62a17ae 1771 }
1772 }
5000f21c
DS
1773}
1774
c7122e14 1775/* If this is an EBGP peer with as-override */
d62a17ae 1776static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1777 struct peer *peer, struct attr *attr)
1778{
bbe7bc46
DA
1779 struct aspath *aspath;
1780
9bbdb457 1781 if (peer->sort == BGP_PEER_EBGP &&
bbe7bc46
DA
1782 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1783 if (attr->aspath->refcnt)
1784 aspath = aspath_dup(attr->aspath);
1785 else
1786 aspath = attr->aspath;
1787
1788 attr->aspath = aspath_intern(
1789 aspath_replace_specific_asn(aspath, peer->as, bgp->as));
1790
1791 aspath_free(aspath);
1792 }
d62a17ae 1793}
1794
1479ed2f
DA
1795void bgp_attr_add_llgr_community(struct attr *attr)
1796{
1797 struct community *old;
1798 struct community *new;
1799 struct community *merge;
1800 struct community *llgr;
1801
9a706b42 1802 old = bgp_attr_get_community(attr);
1479ed2f
DA
1803 llgr = community_str2com("llgr-stale");
1804
1805 assert(llgr);
1806
1807 if (old) {
1808 merge = community_merge(community_dup(old), llgr);
1809
1810 if (old->refcnt == 0)
1811 community_free(&old);
1812
1813 new = community_uniq_sort(merge);
1814 community_free(&merge);
1815 } else {
1816 new = community_dup(llgr);
1817 }
1818
1819 community_free(&llgr);
1820
9a706b42 1821 bgp_attr_set_community(attr, new);
1479ed2f
DA
1822}
1823
7f323236
DW
1824void bgp_attr_add_gshut_community(struct attr *attr)
1825{
1826 struct community *old;
1827 struct community *new;
1828 struct community *merge;
1829 struct community *gshut;
1830
9a706b42 1831 old = bgp_attr_get_community(attr);
7f323236
DW
1832 gshut = community_str2com("graceful-shutdown");
1833
990f4f91 1834 assert(gshut);
1835
7f323236
DW
1836 if (old) {
1837 merge = community_merge(community_dup(old), gshut);
1838
a4d82a8a 1839 if (old->refcnt == 0)
3c1f53de 1840 community_free(&old);
7f323236
DW
1841
1842 new = community_uniq_sort(merge);
3c1f53de 1843 community_free(&merge);
7f323236
DW
1844 } else {
1845 new = community_dup(gshut);
1846 }
1847
3c1f53de 1848 community_free(&gshut);
9a706b42 1849 bgp_attr_set_community(attr, new);
7f323236
DW
1850
1851 /* When we add the graceful-shutdown community we must also
1852 * lower the local-preference */
1853 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1854 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1855}
1856
1857
e73c112e
MK
1858/* Notify BGP Conditional advertisement scanner process. */
1859void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1860{
e73c112e 1861 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1862 afi_t afi = SUBGRP_AFI(subgrp);
1863 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1864 struct bgp_filter *filter = &peer->filter[afi][safi];
1865
1866 if (!ADVERTISE_MAP_NAME(filter))
1867 return;
1868
52979c3b
DS
1869 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1870 return;
e73c112e 1871
52979c3b 1872 peer->advmap_table_change = true;
e73c112e
MK
1873}
1874
1875
f2ee6d5c 1876void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1877{
960035b2 1878 if (family == AF_INET) {
975a328e
DA
1879 attr->nexthop.s_addr = INADDR_ANY;
1880 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1881 }
d62a17ae 1882 if (family == AF_INET6)
1883 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1884 if (family == AF_EVPN)
1885 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1886}
1887
9bcb3eef 1888bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1889 struct update_subgroup *subgrp,
7f7940e6 1890 const struct prefix *p, struct attr *attr,
51c3a7de 1891 struct attr *post_attr)
d62a17ae 1892{
1893 struct bgp_filter *filter;
1894 struct peer *from;
1895 struct peer *peer;
1896 struct peer *onlypeer;
1897 struct bgp *bgp;
40381db7 1898 struct attr *piattr;
b68885f9 1899 route_map_result_t ret;
d62a17ae 1900 int transparent;
1901 int reflect;
1902 afi_t afi;
1903 safi_t safi;
1904 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1905 bool nh_reset = false;
1906 uint64_t cum_bw;
d62a17ae 1907
1908 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1909 return false;
d62a17ae 1910
1911 afi = SUBGRP_AFI(subgrp);
1912 safi = SUBGRP_SAFI(subgrp);
1913 peer = SUBGRP_PEER(subgrp);
1914 onlypeer = NULL;
1915 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1916 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1917
40381db7 1918 from = pi->peer;
d62a17ae 1919 filter = &peer->filter[afi][safi];
1920 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1921 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1922 : pi->attr;
3f9c7369 1923
d0bf49ec
LS
1924 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1925 peer->pmax_out[afi][safi] != 0 &&
1926 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1927 if (BGP_DEBUG(update, UPDATE_OUT) ||
1928 BGP_DEBUG(update, UPDATE_PREFIX)) {
1929 zlog_debug("%s reached maximum prefix to be send (%u)",
1930 peer->host, peer->pmax_out[afi][safi]);
1931 }
1932 return false;
1933 }
1934
49e5a4a0 1935#ifdef ENABLE_BGP_VNC
d62a17ae 1936 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1937 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1938 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1939
1940 /*
1941 * direct and direct_ext type routes originate internally even
1942 * though they can have peer pointers that reference other
1943 * systems
1944 */
8228a9a7
DS
1945 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1946 __func__, p);
d62a17ae 1947 samepeer_safe = 1;
1948 }
65efcfce
LB
1949#endif
1950
ddb5b488
PZ
1951 if (((afi == AFI_IP) || (afi == AFI_IP6))
1952 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1953 && (pi->type == ZEBRA_ROUTE_BGP)
1954 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1955
1956 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1957
1958 samepeer_safe = 1;
1959 }
1960
d62a17ae 1961 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1962 * pi is valid */
1963 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1964 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1965 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1966 return false;
d62a17ae 1967 }
adbac85e 1968
d62a17ae 1969 /* If this is not the bestpath then check to see if there is an enabled
1970 * addpath
1971 * feature that requires us to advertise it */
40381db7 1972 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1973 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1974 return false;
d62a17ae 1975 }
1976 }
06370dac 1977
d62a17ae 1978 /* Aggregate-address suppress check. */
4056a5f6
RZ
1979 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1980 return false;
3f9c7369 1981
13b7e7f0
DS
1982 /*
1983 * If we are doing VRF 2 VRF leaking via the import
1984 * statement, we want to prevent the route going
1985 * off box as that the RT and RD created are localy
1986 * significant and globaly useless.
1987 */
40381db7
DS
1988 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1989 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1990 return false;
13b7e7f0 1991
d62a17ae 1992 /* If it's labeled safi, make sure the route has a valid label. */
1993 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1994 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1995 if (!bgp_is_valid_label(&label)) {
1996 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1997 zlog_debug("u%" PRIu64 ":s%" PRIu64
1998 " %pFX is filtered - no label (%p)",
d62a17ae 1999 subgrp->update_group->id, subgrp->id,
8228a9a7 2000 p, &label);
3dc339cd 2001 return false;
d62a17ae 2002 }
2003 }
cd1964ff 2004
d62a17ae 2005 /* Do not send back route to sender. */
2006 if (onlypeer && from == onlypeer) {
3dc339cd 2007 return false;
d62a17ae 2008 }
3f9c7369 2009
d62a17ae 2010 /* Do not send the default route in the BGP table if the neighbor is
2011 * configured for default-originate */
2012 if (CHECK_FLAG(peer->af_flags[afi][safi],
2013 PEER_FLAG_DEFAULT_ORIGINATE)) {
2014 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2015 return false;
d62a17ae 2016 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2017 return false;
d62a17ae 2018 }
4125bb67 2019
d62a17ae 2020 /* Transparency check. */
2021 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2022 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2023 transparent = 1;
2024 else
2025 transparent = 0;
2026
2027 /* If community is not disabled check the no-export and local. */
40381db7 2028 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2029 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2030 zlog_debug("%s: community filter check fail for %pFX",
2031 __func__, p);
3dc339cd 2032 return false;
d62a17ae 2033 }
3f9c7369 2034
d62a17ae 2035 /* If the attribute has originator-id and it is same as remote
2036 peer's id. */
40381db7
DS
2037 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2038 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2039 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2040 zlog_debug(
a9f3f4f5
DA
2041 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2042 onlypeer, p);
3dc339cd 2043 return false;
d62a17ae 2044 }
3f9c7369 2045
d62a17ae 2046 /* ORF prefix-list filter check */
2047 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2048 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2049 || CHECK_FLAG(peer->af_cap[afi][safi],
2050 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2051 if (peer->orf_plist[afi][safi]) {
2052 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2053 == PREFIX_DENY) {
2054 if (bgp_debug_update(NULL, p,
2055 subgrp->update_group, 0))
2056 zlog_debug(
a9f3f4f5
DA
2057 "%pBP [Update:SEND] %pFX is filtered via ORF",
2058 peer, p);
3dc339cd 2059 return false;
d62a17ae 2060 }
2061 }
2062
2063 /* Output filter check. */
40381db7 2064 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2065 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2066 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2067 p);
3dc339cd 2068 return false;
d62a17ae 2069 }
3f9c7369 2070
d62a17ae 2071 /* AS path loop check. */
2b31007c
RZ
2072 if (onlypeer && onlypeer->as_path_loop_detection
2073 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2074 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2075 zlog_debug(
a9f3f4f5
DA
2076 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2077 onlypeer, onlypeer->as);
3dc339cd 2078 return false;
d62a17ae 2079 }
3f9c7369 2080
d62a17ae 2081 /* If we're a CONFED we need to loop check the CONFED ID too */
2082 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2083 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2084 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2085 zlog_debug(
a9f3f4f5
DA
2086 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2087 peer, bgp->confed_id);
3dc339cd 2088 return false;
d62a17ae 2089 }
3f9c7369 2090 }
3f9c7369 2091
d62a17ae 2092 /* Route-Reflect check. */
2093 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2094 reflect = 1;
2095 else
2096 reflect = 0;
2097
2098 /* IBGP reflection check. */
2099 if (reflect && !samepeer_safe) {
2100 /* A route from a Client peer. */
2101 if (CHECK_FLAG(from->af_flags[afi][safi],
2102 PEER_FLAG_REFLECTOR_CLIENT)) {
2103 /* Reflect to all the Non-Client peers and also to the
2104 Client peers other than the originator. Originator
2105 check
2106 is already done. So there is noting to do. */
2107 /* no bgp client-to-client reflection check. */
892fedb6
DA
2108 if (CHECK_FLAG(bgp->flags,
2109 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2110 if (CHECK_FLAG(peer->af_flags[afi][safi],
2111 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2112 return false;
d62a17ae 2113 } else {
2114 /* A route from a Non-client peer. Reflect to all other
2115 clients. */
2116 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2117 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2118 return false;
d62a17ae 2119 }
2120 }
3f9c7369 2121
51c3a7de
DA
2122 /* For modify attribute, copy it to temporary structure.
2123 * post_attr comes from BGP conditional advertisements, where
2124 * attributes are already processed by advertise-map route-map,
2125 * and this needs to be saved instead of overwriting from the
2126 * path attributes.
2127 */
2128 if (post_attr)
2129 *attr = *post_attr;
2130 else
2131 *attr = *piattr;
d62a17ae 2132
2133 /* If local-preference is not set. */
2134 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2135 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2136 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2137 attr->local_pref = bgp->default_local_pref;
3f9c7369 2138 }
3f9c7369 2139
d62a17ae 2140 /* If originator-id is not set and the route is to be reflected,
2141 set the originator id */
2142 if (reflect
2143 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2144 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2145 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2146 }
3f9c7369 2147
d62a17ae 2148 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2149 */
2150 if (peer->sort == BGP_PEER_EBGP
2151 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2152 if (from != bgp->peer_self && !transparent
2153 && !CHECK_FLAG(peer->af_flags[afi][safi],
2154 PEER_FLAG_MED_UNCHANGED))
2155 attr->flag &=
2156 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2157 }
3f9c7369 2158
d62a17ae 2159 /* Since the nexthop attribute can vary per peer, it is not explicitly
2160 * set
2161 * in announce check, only certain flags and length (or number of
2162 * nexthops
2163 * -- for IPv6/MP_REACH) are set here in order to guide the update
2164 * formation
2165 * code in setting the nexthop(s) on a per peer basis in
2166 * reformat_peer().
2167 * Typically, the source nexthop in the attribute is preserved but in
2168 * the
2169 * scenarios where we know it will always be overwritten, we reset the
2170 * nexthop to "0" in an attempt to achieve better Update packing. An
2171 * example of this is when a prefix from each of 2 IBGP peers needs to
2172 * be
2173 * announced to an EBGP peer (and they have the same attributes barring
2174 * their nexthop).
2175 */
2176 if (reflect)
2177 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2178
2179#define NEXTHOP_IS_V6 \
2180 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2181 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2182 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2183 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2184
2185 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2186 * if
2187 * the peer (group) is configured to receive link-local nexthop
2188 * unchanged
c728d027
DA
2189 * and it is available in the prefix OR we're not reflecting the route,
2190 * link-local nexthop address is valid and
d62a17ae 2191 * the peer (group) to whom we're going to announce is on a shared
2192 * network
2193 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2194 * By checking if nexthop LL address is valid we are sure that
2195 * we do not announce LL address as `::`.
d62a17ae 2196 */
2197 if (NEXTHOP_IS_V6) {
2198 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2199 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2200 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2201 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2202 || (!reflect && !transparent
c728d027
DA
2203 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2204 && peer->shared_network
d62a17ae 2205 && (from == bgp->peer_self
2206 || peer->sort == BGP_PEER_EBGP))) {
2207 attr->mp_nexthop_len =
2208 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2209 }
3f9c7369 2210
d62a17ae 2211 /* Clear off link-local nexthop in source, whenever it is not
2212 * needed to
2213 * ensure more prefixes share the same attribute for
2214 * announcement.
2215 */
2216 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2217 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2218 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2219 }
3f9c7369 2220
5a78f2bc
EB
2221 if (bgp_check_role_applicability(afi, safi) &&
2222 bgp_otc_egress(peer, attr))
d864dd9e
EB
2223 return false;
2224
d62a17ae 2225 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2226 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2227
0655090c
QY
2228 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2229 filter->advmap.aname &&
2230 route_map_lookup_by_name(filter->advmap.aname)) {
2231 struct bgp_path_info rmap_path = {0};
2232 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2233 struct attr dummy_attr = *attr;
2234
2235 /* Fill temp path_info */
2236 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2237 pi, peer, &dummy_attr);
2238
2239 struct route_map *amap =
2240 route_map_lookup_by_name(filter->advmap.aname);
2241
2242 ret = route_map_apply(amap, p, &rmap_path);
2243
2244 bgp_attr_flush(&dummy_attr);
2245
2246 /*
2247 * The conditional advertisement mode is Withdraw and this
2248 * prefix is a conditional prefix. Don't advertise it
2249 */
2250 if (ret == RMAP_PERMITMATCH)
2251 return false;
2252 }
2253
d62a17ae 2254 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2255 if (!post_attr &&
2256 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2257 struct bgp_path_info rmap_path = {0};
2258 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2259 struct attr dummy_attr = {0};
d62a17ae 2260
e34291b8 2261 /* Fill temp path_info */
9bcb3eef
DS
2262 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2263 pi, peer, attr);
16f7ce2b 2264
d62a17ae 2265 /* don't confuse inbound and outbound setting */
2266 RESET_FLAG(attr->rmap_change_flags);
2267
2268 /*
2269 * The route reflector is not allowed to modify the attributes
2270 * of the reflected IBGP routes unless explicitly allowed.
2271 */
2272 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2273 && !CHECK_FLAG(bgp->flags,
2274 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2275 dummy_attr = *attr;
40381db7 2276 rmap_path.attr = &dummy_attr;
d62a17ae 2277 }
3f9c7369 2278
d62a17ae 2279 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2280
4056a5f6 2281 if (bgp_path_suppressed(pi))
d62a17ae 2282 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2283 &rmap_path);
d62a17ae 2284 else
2285 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2286 &rmap_path);
d62a17ae 2287
7e7639f5 2288 bgp_attr_flush(&dummy_attr);
d62a17ae 2289 peer->rmap_type = 0;
2290
2291 if (ret == RMAP_DENYMATCH) {
778048bf 2292 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2293 zlog_debug(
a9f3f4f5
DA
2294 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2295 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2296 bgp_attr_flush(rmap_path.attr);
3dc339cd 2297 return false;
d62a17ae 2298 }
3f9c7369 2299 }
3f9c7369 2300
9dac9fc8
DA
2301 /* RFC 8212 to prevent route leaks.
2302 * This specification intends to improve this situation by requiring the
2303 * explicit configuration of both BGP Import and Export Policies for any
2304 * External BGP (EBGP) session such as customers, peers, or
2305 * confederation boundaries for all enabled address families. Through
2306 * codification of the aforementioned requirement, operators will
2307 * benefit from consistent behavior across different BGP
2308 * implementations.
2309 */
1d3fdccf 2310 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2311 if (!bgp_outbound_policy_exists(peer, filter)) {
2312 if (monotime_since(&bgp->ebgprequirespolicywarning,
2313 NULL) > FIFTEENMINUTE2USEC ||
2314 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2315 zlog_warn(
2316 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2317 monotime(&bgp->ebgprequirespolicywarning);
2318 }
3dc339cd 2319 return false;
b17826b7 2320 }
9dac9fc8 2321
fb29348a
DA
2322 /* draft-ietf-idr-deprecate-as-set-confed-set
2323 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2324 * Eventually, This document (if approved) updates RFC 4271
2325 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2326 * and obsoletes RFC 6472.
2327 */
7f972cd8 2328 if (peer->bgp->reject_as_sets)
fb29348a 2329 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2330 return false;
fb29348a 2331
01da2d26
DA
2332 /* If neighbor sso is configured, then check if the route has
2333 * SoO extended community and validate against the configured
2334 * one. If they match, do not announce, to prevent routing
2335 * loops.
2336 */
2337 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2338 peer->soo[afi][safi]) {
2339 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2340 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2341
2342 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2343 ECOMMUNITY_SITE_ORIGIN) ||
2344 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
2345 ECOMMUNITY_SITE_ORIGIN)) &&
2346 ecommunity_include(ecomm, ecomm_soo)) {
2347 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2348 zlog_debug(
2349 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2350 peer, p, ecommunity_str(ecomm_soo));
2351 return false;
2352 }
2353 }
2354
33d022bc
DA
2355 /* Codification of AS 0 Processing */
2356 if (aspath_check_as_zero(attr->aspath))
e2369003 2357 return false;
33d022bc 2358
637e5ba4 2359 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2360 if (peer->sort == BGP_PEER_IBGP
2361 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2362 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2363 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2364 } else {
2365 bgp_attr_add_gshut_community(attr);
2366 }
2367 }
2368
1479ed2f
DA
2369 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2370 * Capability" to a neighbor MUST perform the following upon receiving
2371 * a route from that neighbor with the "LLGR_STALE" community, or upon
2372 * attaching the "LLGR_STALE" community itself per Section 4.2:
2373 *
2374 * The route SHOULD NOT be advertised to any neighbor from which the
2375 * Long-lived Graceful Restart Capability has not been received.
2376 */
9a706b42
DA
2377 if (bgp_attr_get_community(attr) &&
2378 community_include(bgp_attr_get_community(attr),
2379 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2380 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2381 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2382 return false;
2383
d62a17ae 2384 /* After route-map has been applied, we check to see if the nexthop to
2385 * be carried in the attribute (that is used for the announcement) can
2386 * be cleared off or not. We do this in all cases where we would be
2387 * setting the nexthop to "ourselves". For IPv6, we only need to
2388 * consider
2389 * the global nexthop here; the link-local nexthop would have been
2390 * cleared
2391 * already, and if not, it is required by the update formation code.
2392 * Also see earlier comments in this function.
2393 */
2394 /*
2395 * If route-map has performed some operation on the nexthop or the peer
2396 * configuration says to pass it unchanged, we cannot reset the nexthop
2397 * here, so only attempt to do it if these aren't true. Note that the
2398 * route-map handler itself might have cleared the nexthop, if for
2399 * example,
2400 * it is configured as 'peer-address'.
2401 */
2402 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2403 piattr->rmap_change_flags)
d62a17ae 2404 && !transparent
2405 && !CHECK_FLAG(peer->af_flags[afi][safi],
2406 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2407 /* We can reset the nexthop, if setting (or forcing) it to
2408 * 'self' */
2409 if (CHECK_FLAG(peer->af_flags[afi][safi],
2410 PEER_FLAG_NEXTHOP_SELF)
2411 || CHECK_FLAG(peer->af_flags[afi][safi],
2412 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2413 if (!reflect
2414 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2415 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2416 subgroup_announce_reset_nhop(
2417 (peer_cap_enhe(peer, afi, safi)
2418 ? AF_INET6
2419 : p->family),
2420 attr);
7b651a32 2421 nh_reset = true;
2422 }
d62a17ae 2423 } else if (peer->sort == BGP_PEER_EBGP) {
2424 /* Can also reset the nexthop if announcing to EBGP, but
2425 * only if
2426 * no peer in the subgroup is on a shared subnet.
2427 * Note: 3rd party nexthop currently implemented for
2428 * IPv4 only.
2429 */
737af885
BS
2430 if ((p->family == AF_INET) &&
2431 (!bgp_subgrp_multiaccess_check_v4(
2432 piattr->nexthop,
7b651a32 2433 subgrp, from))) {
d62a17ae 2434 subgroup_announce_reset_nhop(
2435 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2436 ? AF_INET6
2437 : p->family),
737af885 2438 attr);
7b651a32 2439 nh_reset = true;
2440 }
737af885
BS
2441
2442 if ((p->family == AF_INET6) &&
2443 (!bgp_subgrp_multiaccess_check_v6(
2444 piattr->mp_nexthop_global,
7b651a32 2445 subgrp, from))) {
737af885
BS
2446 subgroup_announce_reset_nhop(
2447 (peer_cap_enhe(peer, afi, safi)
2448 ? AF_INET6
2449 : p->family),
2450 attr);
7b651a32 2451 nh_reset = true;
2452 }
737af885
BS
2453
2454
2455
40381db7 2456 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2457 /*
2458 * This flag is used for leaked vpn-vrf routes
2459 */
2460 int family = p->family;
2461
2462 if (peer_cap_enhe(peer, afi, safi))
2463 family = AF_INET6;
2464
2465 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2466 zlog_debug(
1defdda8 2467 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2468 __func__, family2str(family));
2469 subgroup_announce_reset_nhop(family, attr);
7b651a32 2470 nh_reset = true;
d62a17ae 2471 }
63696f1d 2472 }
960035b2 2473
63696f1d 2474 /* If IPv6/MP and nexthop does not have any override and happens
2475 * to
2476 * be a link-local address, reset it so that we don't pass along
2477 * the
2478 * source's link-local IPv6 address to recipients who may not be
2479 * on
2480 * the same interface.
2481 */
2482 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2483 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2484 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2485 nh_reset = true;
2486 }
d62a17ae 2487 }
3f9c7369 2488
7b27cf7b
DA
2489 /* If this is an iBGP, send Origin Validation State (OVS)
2490 * extended community (rfc8097).
2491 */
2492 if (peer->sort == BGP_PEER_IBGP) {
2493 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
2494
2495 rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
2496
2497 if (rpki_state != RPKI_NOT_BEING_USED)
2498 bgp_attr_set_ecommunity(
2499 attr, ecommunity_add_origin_validation_state(
2500 rpki_state,
2501 bgp_attr_get_ecommunity(attr)));
2502 }
2503
7b651a32 2504 /*
2505 * When the next hop is set to ourselves, if all multipaths have
2506 * link-bandwidth announce the cumulative bandwidth as that makes
2507 * the most sense. However, don't modify if the link-bandwidth has
2508 * been explicitly set by user policy.
2509 */
2510 if (nh_reset &&
f7e1c681 2511 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2512 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2513 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2514 bgp_attr_set_ecommunity(
2515 attr,
2516 ecommunity_replace_linkbw(
2517 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2518 CHECK_FLAG(
2519 peer->flags,
2520 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2521
3dc339cd 2522 return true;
3f9c7369
DS
2523}
2524
cc9f21da 2525static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2526{
2527 struct afi_safi_info *info;
2528 afi_t afi;
2529 safi_t safi;
2530 struct bgp *bgp;
2531
2532 info = THREAD_ARG(thread);
2533 afi = info->afi;
2534 safi = info->safi;
2535 bgp = info->bgp;
2536
2537 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2538 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2539 safi);
f009ff26 2540
2541 bgp->gr_info[afi][safi].t_route_select = NULL;
2542
2543 XFREE(MTYPE_TMP, info);
2544
2545 /* Best path selection */
cc9f21da 2546 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2547}
2548
9bcb3eef 2549void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2550 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2551 struct bgp_path_info_pair *result, afi_t afi,
2552 safi_t safi)
2553{
2554 struct bgp_path_info *new_select;
2555 struct bgp_path_info *old_select;
40381db7
DS
2556 struct bgp_path_info *pi;
2557 struct bgp_path_info *pi1;
2558 struct bgp_path_info *pi2;
2559 struct bgp_path_info *nextpi = NULL;
d62a17ae 2560 int paths_eq, do_mpath, debug;
2561 struct list mp_list;
2562 char pfx_buf[PREFIX2STR_BUFFER];
2563 char path_buf[PATH_ADDPATH_STR_BUFFER];
2564
2565 bgp_mp_list_init(&mp_list);
2566 do_mpath =
2567 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2568
9bcb3eef 2569 debug = bgp_debug_bestpath(dest);
d62a17ae 2570
2571 if (debug)
9bcb3eef 2572 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2573
9bcb3eef 2574 dest->reason = bgp_path_selection_none;
d62a17ae 2575 /* bgp deterministic-med */
2576 new_select = NULL;
892fedb6 2577 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2578
1defdda8 2579 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2580 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2581 pi1 = pi1->next)
9bcb3eef 2582 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2583 BGP_PATH_DMED_SELECTED);
d62a17ae 2584
9bcb3eef 2585 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2586 pi1 = pi1->next) {
40381db7 2587 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2588 continue;
40381db7 2589 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2590 continue;
ea8b2282 2591 if (pi1->peer != bgp->peer_self)
feb17238 2592 if (!peer_established(pi1->peer))
d62a17ae 2593 continue;
2594
40381db7
DS
2595 new_select = pi1;
2596 if (pi1->next) {
2597 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2598 if (CHECK_FLAG(pi2->flags,
1defdda8 2599 BGP_PATH_DMED_CHECK))
d62a17ae 2600 continue;
40381db7 2601 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2602 continue;
ea8b2282 2603 if (pi2->peer != bgp->peer_self
d62a17ae 2604 && !CHECK_FLAG(
ea8b2282
DS
2605 pi2->peer->sflags,
2606 PEER_STATUS_NSF_WAIT))
40381db7 2607 if (pi2->peer->status
d62a17ae 2608 != Established)
2609 continue;
2610
121e245d
DS
2611 if (!aspath_cmp_left(pi1->attr->aspath,
2612 pi2->attr->aspath)
2613 && !aspath_cmp_left_confed(
40381db7 2614 pi1->attr->aspath,
121e245d
DS
2615 pi2->attr->aspath))
2616 continue;
d62a17ae 2617
121e245d
DS
2618 if (bgp_path_info_cmp(
2619 bgp, pi2, new_select,
2620 &paths_eq, mpath_cfg, debug,
fdf81fa0 2621 pfx_buf, afi, safi,
9bcb3eef 2622 &dest->reason)) {
121e245d 2623 bgp_path_info_unset_flag(
9bcb3eef 2624 dest, new_select,
121e245d
DS
2625 BGP_PATH_DMED_SELECTED);
2626 new_select = pi2;
d62a17ae 2627 }
121e245d
DS
2628
2629 bgp_path_info_set_flag(
9bcb3eef 2630 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2631 }
2632 }
9bcb3eef 2633 bgp_path_info_set_flag(dest, new_select,
18ee8310 2634 BGP_PATH_DMED_CHECK);
9bcb3eef 2635 bgp_path_info_set_flag(dest, new_select,
18ee8310 2636 BGP_PATH_DMED_SELECTED);
d62a17ae 2637
2638 if (debug) {
18ee8310 2639 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2640 new_select, path_buf, sizeof(path_buf));
8228a9a7 2641 zlog_debug(
4378495a
DS
2642 "%pBD(%s): %s is the bestpath from AS %u",
2643 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2644 aspath_get_first_as(
2645 new_select->attr->aspath));
d62a17ae 2646 }
2647 }
2648 }
96450faf 2649
d62a17ae 2650 /* Check old selected route and new selected route. */
2651 old_select = NULL;
2652 new_select = NULL;
9bcb3eef 2653 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2654 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2655 enum bgp_path_selection_reason reason;
2656
40381db7
DS
2657 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2658 old_select = pi;
d62a17ae 2659
40381db7 2660 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2661 /* reap REMOVED routes, if needs be
2662 * selected route must stay for a while longer though
2663 */
40381db7
DS
2664 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2665 && (pi != old_select))
9bcb3eef 2666 bgp_path_info_reap(dest, pi);
d62a17ae 2667
ddb5b488 2668 if (debug)
40381db7
DS
2669 zlog_debug("%s: pi %p in holddown", __func__,
2670 pi);
ddb5b488 2671
d62a17ae 2672 continue;
2673 }
96450faf 2674
40381db7
DS
2675 if (pi->peer && pi->peer != bgp->peer_self
2676 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2677 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2678
2679 if (debug)
2680 zlog_debug(
40381db7
DS
2681 "%s: pi %p non self peer %s not estab state",
2682 __func__, pi, pi->peer->host);
ddb5b488 2683
d62a17ae 2684 continue;
ddb5b488 2685 }
9fbdd100 2686
892fedb6 2687 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2688 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2689 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2690 if (debug)
40381db7 2691 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2692 continue;
2693 }
9fbdd100 2694
9bcb3eef 2695 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2696
9bcb3eef 2697 reason = dest->reason;
40381db7 2698 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2699 debug, pfx_buf, afi, safi,
2700 &dest->reason)) {
19ea4cec
DS
2701 if (new_select == NULL &&
2702 reason != bgp_path_selection_none)
9bcb3eef 2703 dest->reason = reason;
40381db7 2704 new_select = pi;
d62a17ae 2705 }
2706 }
718e3744 2707
d62a17ae 2708 /* Now that we know which path is the bestpath see if any of the other
2709 * paths
2710 * qualify as multipaths
2711 */
2712 if (debug) {
2713 if (new_select)
7533cad7
QY
2714 bgp_path_info_path_with_addpath_rx_str(
2715 new_select, path_buf, sizeof(path_buf));
d62a17ae 2716 else
772270f3 2717 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2718 zlog_debug(
4378495a
DS
2719 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2720 dest, bgp->name_pretty, path_buf,
d62a17ae 2721 old_select ? old_select->peer->host : "NONE");
96450faf 2722 }
9fbdd100 2723
d62a17ae 2724 if (do_mpath && new_select) {
9bcb3eef 2725 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2726 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2727
2728 if (debug)
18ee8310 2729 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2730 pi, path_buf, sizeof(path_buf));
d62a17ae 2731
40381db7 2732 if (pi == new_select) {
d62a17ae 2733 if (debug)
2734 zlog_debug(
4378495a
DS
2735 "%pBD(%s): %s is the bestpath, add to the multipath list",
2736 dest, bgp->name_pretty,
2737 path_buf);
40381db7 2738 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2739 continue;
2740 }
2741
40381db7 2742 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2743 continue;
2744
40381db7
DS
2745 if (pi->peer && pi->peer != bgp->peer_self
2746 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2747 PEER_STATUS_NSF_WAIT))
feb17238 2748 if (!peer_established(pi->peer))
d62a17ae 2749 continue;
2750
40381db7 2751 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2752 if (debug)
2753 zlog_debug(
8228a9a7
DS
2754 "%pBD: %s has the same nexthop as the bestpath, skip it",
2755 dest, path_buf);
d62a17ae 2756 continue;
2757 }
2758
40381db7 2759 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2760 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2761 &dest->reason);
d62a17ae 2762
2763 if (paths_eq) {
2764 if (debug)
2765 zlog_debug(
8228a9a7
DS
2766 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2767 dest, path_buf);
40381db7 2768 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2769 }
2770 }
2771 }
fee0f4c6 2772
4378495a 2773 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2774 mpath_cfg);
2775 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2776 bgp_mp_list_clear(&mp_list);
96450faf 2777
9bcb3eef 2778 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2779
d62a17ae 2780 result->old = old_select;
2781 result->new = new_select;
96450faf 2782
d62a17ae 2783 return;
fee0f4c6 2784}
2785
3f9c7369
DS
2786/*
2787 * A new route/change in bestpath of an existing route. Evaluate the path
2788 * for advertisement to the subgroup.
2789 */
3dc339cd
DA
2790void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2791 struct bgp_path_info *selected,
9bcb3eef 2792 struct bgp_dest *dest,
3dc339cd 2793 uint32_t addpath_tx_id)
d62a17ae 2794{
b54892e0 2795 const struct prefix *p;
d62a17ae 2796 struct peer *onlypeer;
2797 struct attr attr;
2798 afi_t afi;
2799 safi_t safi;
a77e2f4b
S
2800 struct bgp *bgp;
2801 bool advertise;
adbac85e 2802
9bcb3eef 2803 p = bgp_dest_get_prefix(dest);
d62a17ae 2804 afi = SUBGRP_AFI(subgrp);
2805 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2806 bgp = SUBGRP_INST(subgrp);
d62a17ae 2807 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2808 : NULL);
2809
2dbe669b
DA
2810 if (BGP_DEBUG(update, UPDATE_OUT))
2811 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2812
d62a17ae 2813 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2814 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2815 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2816 return;
d62a17ae 2817
6006b807 2818 memset(&attr, 0, sizeof(attr));
d62a17ae 2819 /* It's initialized in bgp_announce_check() */
2820
a77e2f4b
S
2821 /* Announcement to the subgroup. If the route is filtered withdraw it.
2822 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2823 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2824 * route
d62a17ae 2825 */
a77e2f4b
S
2826 advertise = bgp_check_advertise(bgp, dest);
2827
d62a17ae 2828 if (selected) {
7f7940e6 2829 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2830 NULL)) {
a77e2f4b
S
2831 /* Route is selected, if the route is already installed
2832 * in FIB, then it is advertised
2833 */
be785e35
DS
2834 if (advertise) {
2835 if (!bgp_check_withdrawal(bgp, dest))
2836 bgp_adj_out_set_subgroup(
2837 dest, subgrp, &attr, selected);
2838 else
2839 bgp_adj_out_unset_subgroup(
2840 dest, subgrp, 1, addpath_tx_id);
2841 }
a77e2f4b 2842 } else
9bcb3eef 2843 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2844 addpath_tx_id);
d62a17ae 2845 }
2846
2847 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2848 else {
9bcb3eef 2849 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2850 }
200df115 2851}
fee0f4c6 2852
3064bf43 2853/*
e1072051 2854 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2855 * This is called at the end of route processing.
3064bf43 2856 */
9bcb3eef 2857void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2858{
40381db7 2859 struct bgp_path_info *pi;
3064bf43 2860
9bcb3eef 2861 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2862 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2863 continue;
40381db7
DS
2864 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2865 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2866 }
3064bf43 2867}
2868
2869/*
2870 * Has the route changed from the RIB's perspective? This is invoked only
2871 * if the route selection returns the same best route as earlier - to
2872 * determine if we need to update zebra or not.
2873 */
9bcb3eef 2874bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2875{
4b7e6066 2876 struct bgp_path_info *mpinfo;
d62a17ae 2877
2bb9eff4
DS
2878 /* If this is multipath, check all selected paths for any nexthop
2879 * change or attribute change. Some attribute changes (e.g., community)
2880 * aren't of relevance to the RIB, but we'll update zebra to ensure
2881 * we handle the case of BGP nexthop change. This is the behavior
2882 * when the best path has an attribute change anyway.
d62a17ae 2883 */
1defdda8 2884 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2885 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2886 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2887 return true;
d62a17ae 2888
2bb9eff4
DS
2889 /*
2890 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2891 */
18ee8310
DS
2892 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2893 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2894 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2895 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2896 return true;
d62a17ae 2897 }
3064bf43 2898
d62a17ae 2899 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2900 return false;
3064bf43 2901}
2902
d62a17ae 2903struct bgp_process_queue {
2904 struct bgp *bgp;
9bcb3eef 2905 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2906#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2907 unsigned int flags;
2908 unsigned int queued;
200df115 2909};
2910
3b0c17e1 2911static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2912 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2913 struct bgp_path_info *new_select,
2914 struct bgp_path_info *old_select)
2915{
9bcb3eef 2916 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2917
2918 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2919 return;
2920
2921 if (advertise_type5_routes(bgp, afi) && new_select
2922 && is_route_injectable_into_evpn(new_select)) {
2923
2924 /* apply the route-map */
2925 if (bgp->adv_cmd_rmap[afi][safi].map) {
2926 route_map_result_t ret;
2927 struct bgp_path_info rmap_path;
2928 struct bgp_path_info_extra rmap_path_extra;
2929 struct attr dummy_attr;
2930
2931 dummy_attr = *new_select->attr;
2932
2933 /* Fill temp path_info */
9bcb3eef 2934 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2935 new_select, new_select->peer,
2936 &dummy_attr);
2937
2938 RESET_FLAG(dummy_attr.rmap_change_flags);
2939
2940 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2941 p, &rmap_path);
3b0c17e1 2942
2943 if (ret == RMAP_DENYMATCH) {
2944 bgp_attr_flush(&dummy_attr);
2945 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2946 safi);
2947 } else
2948 bgp_evpn_advertise_type5_route(
2949 bgp, p, &dummy_attr, afi, safi);
2950 } else {
2951 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2952 afi, safi);
2953 }
2954 } else if (advertise_type5_routes(bgp, afi) && old_select
2955 && is_route_injectable_into_evpn(old_select))
2956 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2957}
2958
bb2ca692
MS
2959/*
2960 * Utility to determine whether a particular path_info should use
2961 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2962 * in a path where we basically _know_ this is a BGP-LU route.
2963 */
2964static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2965{
2966 /* Certain types get imp null; so do paths where the nexthop is
2967 * not labeled.
2968 */
2969 if (new_select->sub_type == BGP_ROUTE_STATIC
2970 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2971 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2972 return true;
2973 else if (new_select->extra == NULL ||
2974 !bgp_is_valid_label(&new_select->extra->label[0]))
2975 /* TODO -- should be configurable? */
2976 return true;
2977 else
2978 return false;
2979}
2980
3103e8d2
DS
2981/*
2982 * old_select = The old best path
2983 * new_select = the new best path
2984 *
2985 * if (!old_select && new_select)
2986 * We are sending new information on.
2987 *
2988 * if (old_select && new_select) {
2989 * if (new_select != old_select)
2990 * We have a new best path send a change
2991 * else
2992 * We've received a update with new attributes that needs
2993 * to be passed on.
2994 * }
2995 *
2996 * if (old_select && !new_select)
2997 * We have no eligible route that we can announce or the rn
2998 * is being removed.
2999 */
9bcb3eef 3000static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 3001 afi_t afi, safi_t safi)
d62a17ae 3002{
4b7e6066
DS
3003 struct bgp_path_info *new_select;
3004 struct bgp_path_info *old_select;
3005 struct bgp_path_info_pair old_and_new;
ddb5b488 3006 int debug = 0;
d62a17ae 3007
892fedb6 3008 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
3009 if (dest)
3010 debug = bgp_debug_bestpath(dest);
b54892e0 3011 if (debug)
f4c713ae 3012 zlog_debug(
56ca3b5b 3013 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 3014 __func__, dest);
f4c713ae
LB
3015 return;
3016 }
d62a17ae 3017 /* Is it end of initial update? (after startup) */
9bcb3eef 3018 if (!dest) {
e36f61b5
DS
3019 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
3020 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 3021
3022 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
3023 FOREACH_AFI_SAFI (afi, safi) {
3024 if (bgp_fibupd_safi(safi))
3025 bgp_zebra_announce_table(bgp, afi, safi);
3026 }
d62a17ae 3027 bgp->main_peers_update_hold = 0;
3028
3029 bgp_start_routeadv(bgp);
aac24838 3030 return;
d62a17ae 3031 }
cb1faec9 3032
9bcb3eef 3033 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3034
9bcb3eef 3035 debug = bgp_debug_bestpath(dest);
b54892e0 3036 if (debug)
4378495a
DS
3037 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3038 dest, bgp->name_pretty, afi2str(afi),
3039 safi2str(safi));
ddb5b488 3040
f009ff26 3041 /* The best path calculation for the route is deferred if
3042 * BGP_NODE_SELECT_DEFER is set
3043 */
9bcb3eef 3044 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3045 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3046 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3047 return;
3048 }
3049
d62a17ae 3050 /* Best path selection. */
9bcb3eef 3051 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3052 afi, safi);
3053 old_select = old_and_new.old;
3054 new_select = old_and_new.new;
3055
3056 /* Do we need to allocate or free labels?
3057 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3058 * necessary to do this upon changes to best path. Exceptions:
3059 * - label index has changed -> recalculate resulting label
3060 * - path_info sub_type changed -> switch to/from implicit-null
3061 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3062 */
318cac96 3063 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3064 if (new_select) {
3065 if (!old_select
3066 || bgp_label_index_differs(new_select, old_select)
57592a53 3067 || new_select->sub_type != old_select->sub_type
9bcb3eef 3068 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3069 /* Enforced penultimate hop popping:
3070 * implicit-null for local routes, aggregate
3071 * and redistributed routes
3072 */
bb2ca692 3073 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3074 if (CHECK_FLAG(
9bcb3eef 3075 dest->flags,
992dd67e
PR
3076 BGP_NODE_REGISTERED_FOR_LABEL)
3077 || CHECK_FLAG(
3078 dest->flags,
3079 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3080 bgp_unregister_for_label(dest);
67f67ba4
DA
3081 dest->local_label = mpls_lse_encode(
3082 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3083 1);
9bcb3eef 3084 bgp_set_valid_label(&dest->local_label);
d62a17ae 3085 } else
9bcb3eef
DS
3086 bgp_register_for_label(dest,
3087 new_select);
d62a17ae 3088 }
9bcb3eef 3089 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3090 BGP_NODE_REGISTERED_FOR_LABEL)
3091 || CHECK_FLAG(dest->flags,
3092 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3093 bgp_unregister_for_label(dest);
318cac96 3094 }
992dd67e
PR
3095 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3096 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3097 bgp_unregister_for_label(dest);
d62a17ae 3098 }
cd1964ff 3099
b54892e0 3100 if (debug)
ddb5b488 3101 zlog_debug(
4378495a
DS
3102 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3103 __func__, dest, bgp->name_pretty, afi2str(afi),
3104 safi2str(safi), old_select, new_select);
ddb5b488 3105
d62a17ae 3106 /* If best route remains the same and this is not due to user-initiated
3107 * clear, see exactly what needs to be done.
3108 */
d62a17ae 3109 if (old_select && old_select == new_select
9bcb3eef 3110 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3111 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3112 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3113 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3114#ifdef ENABLE_BGP_VNC
d62a17ae 3115 vnc_import_bgp_add_route(bgp, p, old_select);
3116 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3117#endif
bb744275 3118 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3119 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3120
be785e35
DS
3121 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3122 && new_select->sub_type == BGP_ROUTE_NORMAL)
3123 SET_FLAG(dest->flags,
3124 BGP_NODE_FIB_INSTALL_PENDING);
3125
ddb5b488
PZ
3126 if (new_select->type == ZEBRA_ROUTE_BGP
3127 && (new_select->sub_type == BGP_ROUTE_NORMAL
3128 || new_select->sub_type
3129 == BGP_ROUTE_IMPORTED))
3130
9bcb3eef 3131 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3132 bgp, afi, safi);
3133 }
d62a17ae 3134 }
d62a17ae 3135
3136 /* If there is a change of interest to peers, reannounce the
3137 * route. */
1defdda8 3138 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3139 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3140 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3141 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3142
3143 /* unicast routes must also be annouced to
3144 * labeled-unicast update-groups */
3145 if (safi == SAFI_UNICAST)
3146 group_announce_route(bgp, afi,
9bcb3eef 3147 SAFI_LABELED_UNICAST, dest,
d62a17ae 3148 new_select);
3149
1defdda8 3150 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3151 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3152 }
fee0f4c6 3153
3b0c17e1 3154 /* advertise/withdraw type-5 routes */
3155 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3156 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3157 bgp_process_evpn_route_injection(
9bcb3eef 3158 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3159
b1875e65 3160 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3161 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3162 bgp_zebra_clear_route_change_flags(dest);
3163 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3164 return;
d62a17ae 3165 }
8ad7271d 3166
d62a17ae 3167 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3168 */
9bcb3eef 3169 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3170
3171 /* bestpath has changed; bump version */
3172 if (old_select || new_select) {
9bcb3eef 3173 bgp_bump_version(dest);
d62a17ae 3174
3175 if (!bgp->t_rmap_def_originate_eval) {
3176 bgp_lock(bgp);
3177 thread_add_timer(
3178 bm->master,
3179 update_group_refresh_default_originate_route_map,
3180 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3181 &bgp->t_rmap_def_originate_eval);
3182 }
3183 }
3f9c7369 3184
d62a17ae 3185 if (old_select)
9bcb3eef 3186 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3187 if (new_select) {
ddb5b488
PZ
3188 if (debug)
3189 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3190 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3191 bgp_path_info_unset_flag(dest, new_select,
3192 BGP_PATH_ATTR_CHANGED);
1defdda8 3193 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3194 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3195 }
338b3424 3196
49e5a4a0 3197#ifdef ENABLE_BGP_VNC
d62a17ae 3198 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3199 if (old_select != new_select) {
3200 if (old_select) {
3201 vnc_import_bgp_exterior_del_route(bgp, p,
3202 old_select);
3203 vnc_import_bgp_del_route(bgp, p, old_select);
3204 }
3205 if (new_select) {
3206 vnc_import_bgp_exterior_add_route(bgp, p,
3207 new_select);
3208 vnc_import_bgp_add_route(bgp, p, new_select);
3209 }
3210 }
3211 }
65efcfce
LB
3212#endif
3213
9bcb3eef 3214 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3215
3216 /* unicast routes must also be annouced to labeled-unicast update-groups
3217 */
3218 if (safi == SAFI_UNICAST)
9bcb3eef 3219 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3220 new_select);
3221
3222 /* FIB update. */
3223 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3224 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3225
d62a17ae 3226 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3227 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3228 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3229 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3230
be785e35
DS
3231 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3232 SET_FLAG(dest->flags,
3233 BGP_NODE_FIB_INSTALL_PENDING);
3234
2b659f33
MK
3235 /* if this is an evpn imported type-5 prefix,
3236 * we need to withdraw the route first to clear
3237 * the nh neigh and the RMAC entry.
3238 */
3239 if (old_select &&
3240 is_route_parent_evpn(old_select))
3241 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3242
9bcb3eef 3243 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3244 } else {
d62a17ae 3245 /* Withdraw the route from the kernel. */
3246 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3247 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3248 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3249 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3250
568e10ca 3251 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3252 }
718e3744 3253 }
3064bf43 3254
9bcb3eef 3255 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3256 old_select);
5424b7ba 3257
d62a17ae 3258 /* Clear any route change flags. */
9bcb3eef 3259 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3260
18ee8310 3261 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3262 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3263 bgp_path_info_reap(dest, old_select);
d62a17ae 3264
9bcb3eef 3265 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3266 return;
718e3744 3267}
3268
f009ff26 3269/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3270void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3271{
9bcb3eef 3272 struct bgp_dest *dest;
f009ff26 3273 int cnt = 0;
3274 struct afi_safi_info *thread_info;
f009ff26 3275
56c226e7
DS
3276 if (bgp->gr_info[afi][safi].t_route_select) {
3277 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3278
3279 thread_info = THREAD_ARG(t);
3280 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3281 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3282 }
f009ff26 3283
3284 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3285 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3286 get_afi_safi_str(afi, safi, false),
26742171 3287 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3288 }
3289
3290 /* Process the route list */
6338d242 3291 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3292 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3293 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3294 dest = bgp_route_next(dest)) {
3295 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3296 continue;
3297
3298 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3299 bgp->gr_info[afi][safi].gr_deferred--;
3300 bgp_process_main_one(bgp, dest, afi, safi);
3301 cnt++;
067ea165
CB
3302 }
3303 /* If iteration stopped before the entire table was traversed then the
3304 * node needs to be unlocked.
3305 */
3306 if (dest) {
3307 bgp_dest_unlock_node(dest);
3308 dest = NULL;
f009ff26 3309 }
3310
9e3b51a7 3311 /* Send EOR message when all routes are processed */
6338d242 3312 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3313 bgp_send_delayed_eor(bgp);
8c48b3b6 3314 /* Send route processing complete message to RIB */
3315 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3316 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3317 return;
9e3b51a7 3318 }
f009ff26 3319
3320 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3321
3322 thread_info->afi = afi;
3323 thread_info->safi = safi;
3324 thread_info->bgp = bgp;
3325
3326 /* If there are more routes to be processed, start the
3327 * selection timer
3328 */
3329 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3330 BGP_ROUTE_SELECT_DELAY,
3331 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3332}
3333
aac24838 3334static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3335{
aac24838
JB
3336 struct bgp_process_queue *pqnode = data;
3337 struct bgp *bgp = pqnode->bgp;
d62a17ae 3338 struct bgp_table *table;
9bcb3eef 3339 struct bgp_dest *dest;
aac24838
JB
3340
3341 /* eoiu marker */
3342 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3343 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3344 /* should always have dedicated wq call */
3345 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3346 return WQ_SUCCESS;
3347 }
3348
ac021f40 3349 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3350 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3351 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3352 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3353 table = bgp_dest_table(dest);
3354 /* note, new DESTs may be added as part of processing */
3355 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3356
9bcb3eef 3357 bgp_dest_unlock_node(dest);
d62a17ae 3358 bgp_table_unlock(table);
3359 }
aac24838
JB
3360
3361 return WQ_SUCCESS;
3362}
3363
3364static void bgp_processq_del(struct work_queue *wq, void *data)
3365{
3366 struct bgp_process_queue *pqnode = data;
3367
3368 bgp_unlock(pqnode->bgp);
3369
3370 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3371}
3372
b6c386bb 3373void bgp_process_queue_init(struct bgp *bgp)
200df115 3374{
b6c386bb
DS
3375 if (!bgp->process_queue) {
3376 char name[BUFSIZ];
3377
3378 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3379 bgp->process_queue = work_queue_new(bm->master, name);
3380 }
3381
3382 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3383 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3384 bgp->process_queue->spec.max_retries = 0;
3385 bgp->process_queue->spec.hold = 50;
d62a17ae 3386 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3387 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3388}
3389
cfe8d15a 3390static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3391{
3392 struct bgp_process_queue *pqnode;
3393
a4d82a8a
PZ
3394 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3395 sizeof(struct bgp_process_queue));
aac24838
JB
3396
3397 /* unlocked in bgp_processq_del */
3398 pqnode->bgp = bgp_lock(bgp);
3399 STAILQ_INIT(&pqnode->pqueue);
3400
aac24838
JB
3401 return pqnode;
3402}
3403
9bcb3eef 3404void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3405{
aac24838 3406#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3407 struct work_queue *wq = bgp->process_queue;
d62a17ae 3408 struct bgp_process_queue *pqnode;
cfe8d15a 3409 int pqnode_reuse = 0;
495f0b13 3410
d62a17ae 3411 /* already scheduled for processing? */
9bcb3eef 3412 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3413 return;
2e02b9b2 3414
f009ff26 3415 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3416 * the workqueue
3417 */
9bcb3eef 3418 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3419 if (BGP_DEBUG(update, UPDATE_OUT))
3420 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3421 dest);
f009ff26 3422 return;
3423 }
3424
46aeabed
LS
3425 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3426 if (BGP_DEBUG(update, UPDATE_OUT))
3427 zlog_debug(
3428 "Soft reconfigure table in progress for route %p",
3429 dest);
3430 return;
3431 }
3432
aac24838 3433 if (wq == NULL)
d62a17ae 3434 return;
3435
aac24838 3436 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3437 limit only if is from the same BGP view and it's not an EOIU marker
3438 */
aac24838
JB
3439 if (work_queue_item_count(wq)) {
3440 struct work_queue_item *item = work_queue_last_item(wq);
3441 pqnode = item->data;
228da428 3442
a4d82a8a
PZ
3443 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3444 || pqnode->bgp != bgp
3445 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3446 pqnode = bgp_processq_alloc(bgp);
3447 else
3448 pqnode_reuse = 1;
aac24838 3449 } else
cfe8d15a 3450 pqnode = bgp_processq_alloc(bgp);
aac24838 3451 /* all unlocked in bgp_process_wq */
9bcb3eef 3452 bgp_table_lock(bgp_dest_table(dest));
aac24838 3453
9bcb3eef
DS
3454 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3455 bgp_dest_lock_node(dest);
aac24838 3456
60466a63 3457 /* can't be enqueued twice */
9bcb3eef
DS
3458 assert(STAILQ_NEXT(dest, pq) == NULL);
3459 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3460 pqnode->queued++;
3461
cfe8d15a
LB
3462 if (!pqnode_reuse)
3463 work_queue_add(wq, pqnode);
3464
d62a17ae 3465 return;
fee0f4c6 3466}
0a486e5f 3467
d62a17ae 3468void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3469{
d62a17ae 3470 struct bgp_process_queue *pqnode;
cb1faec9 3471
b6c386bb 3472 if (bgp->process_queue == NULL)
d62a17ae 3473 return;
2e02b9b2 3474
cfe8d15a 3475 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3476
aac24838 3477 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3478 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3479}
3480
cc9f21da 3481static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3482{
d62a17ae 3483 struct peer *peer;
0a486e5f 3484
d62a17ae 3485 peer = THREAD_ARG(thread);
3486 peer->t_pmax_restart = NULL;
0a486e5f 3487
d62a17ae 3488 if (bgp_debug_neighbor_events(peer))
3489 zlog_debug(
3490 "%s Maximum-prefix restart timer expired, restore peering",
3491 peer->host);
0a486e5f 3492
a9bafa95 3493 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3494 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3495}
3496
9cbd06e0
DA
3497static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3498 safi_t safi)
3499{
3500 uint32_t count = 0;
f41b0459 3501 bool filtered = false;
9cbd06e0
DA
3502 struct bgp_dest *dest;
3503 struct bgp_adj_in *ain;
40bb2ccf 3504 struct attr attr = {};
9cbd06e0
DA
3505 struct bgp_table *table = peer->bgp->rib[afi][safi];
3506
3507 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3508 for (ain = dest->adj_in; ain; ain = ain->next) {
3509 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3510
3511 attr = *ain->attr;
9cbd06e0
DA
3512
3513 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3514 == FILTER_DENY)
f41b0459
DA
3515 filtered = true;
3516
3517 if (bgp_input_modifier(
3518 peer, rn_p, &attr, afi, safi,
3519 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3520 NULL, 0, NULL)
3521 == RMAP_DENY)
3522 filtered = true;
3523
3524 if (filtered)
9cbd06e0 3525 count++;
f41b0459 3526
d498917e 3527 bgp_attr_flush(&attr);
9cbd06e0
DA
3528 }
3529 }
3530
3531 return count;
3532}
3533
3dc339cd
DA
3534bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3535 int always)
718e3744 3536{
d62a17ae 3537 iana_afi_t pkt_afi;
5c525538 3538 iana_safi_t pkt_safi;
9cbd06e0
DA
3539 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3540 PEER_FLAG_MAX_PREFIX_FORCE))
3541 ? bgp_filtered_routes_count(peer, afi, safi)
3542 + peer->pcount[afi][safi]
3543 : peer->pcount[afi][safi];
9cabb64b 3544
d62a17ae 3545 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3546 return false;
e0701b79 3547
9cbd06e0 3548 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3549 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3550 PEER_STATUS_PREFIX_LIMIT)
3551 && !always)
3dc339cd 3552 return false;
e0701b79 3553
d62a17ae 3554 zlog_info(
f70c91dc
DA
3555 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3556 get_afi_safi_str(afi, safi, false), peer, pcount,
3557 peer->pmax[afi][safi]);
d62a17ae 3558 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3559
3560 if (CHECK_FLAG(peer->af_flags[afi][safi],
3561 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3562 return false;
d62a17ae 3563
3564 /* Convert AFI, SAFI to values for packet. */
3565 pkt_afi = afi_int2iana(afi);
3566 pkt_safi = safi_int2iana(safi);
3567 {
d7c0a89a 3568 uint8_t ndata[7];
d62a17ae 3569
3570 ndata[0] = (pkt_afi >> 8);
3571 ndata[1] = pkt_afi;
3572 ndata[2] = pkt_safi;
3573 ndata[3] = (peer->pmax[afi][safi] >> 24);
3574 ndata[4] = (peer->pmax[afi][safi] >> 16);
3575 ndata[5] = (peer->pmax[afi][safi] >> 8);
3576 ndata[6] = (peer->pmax[afi][safi]);
3577
3578 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3579 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3580 BGP_NOTIFY_CEASE_MAX_PREFIX,
3581 ndata, 7);
3582 }
3583
3584 /* Dynamic peers will just close their connection. */
3585 if (peer_dynamic_neighbor(peer))
3dc339cd 3586 return true;
d62a17ae 3587
3588 /* restart timer start */
3589 if (peer->pmax_restart[afi][safi]) {
3590 peer->v_pmax_restart =
3591 peer->pmax_restart[afi][safi] * 60;
3592
3593 if (bgp_debug_neighbor_events(peer))
3594 zlog_debug(
f70c91dc
DA
3595 "%pBP Maximum-prefix restart timer started for %d secs",
3596 peer, peer->v_pmax_restart);
d62a17ae 3597
3598 BGP_TIMER_ON(peer->t_pmax_restart,
3599 bgp_maximum_prefix_restart_timer,
3600 peer->v_pmax_restart);
3601 }
3602
3dc339cd 3603 return true;
d62a17ae 3604 } else
3605 UNSET_FLAG(peer->af_sflags[afi][safi],
3606 PEER_STATUS_PREFIX_LIMIT);
3607
b1823b69
DS
3608 if (pcount
3609 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3610 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3611 PEER_STATUS_PREFIX_THRESHOLD)
3612 && !always)
3dc339cd 3613 return false;
d62a17ae 3614
3615 zlog_info(
f70c91dc
DA
3616 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3617 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3618 peer->pmax[afi][safi]);
d62a17ae 3619 SET_FLAG(peer->af_sflags[afi][safi],
3620 PEER_STATUS_PREFIX_THRESHOLD);
3621 } else
3622 UNSET_FLAG(peer->af_sflags[afi][safi],
3623 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3624 return false;
718e3744 3625}
3626
b40d939b 3627/* Unconditionally remove the route from the RIB, without taking
3628 * damping into consideration (eg, because the session went down)
3629 */
9bcb3eef 3630void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3631 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3632{
f009ff26 3633
3634 struct bgp *bgp = NULL;
3635 bool delete_route = false;
3636
9bcb3eef
DS
3637 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3638 safi);
d62a17ae 3639
f009ff26 3640 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3641 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3642
f009ff26 3643 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3644 * flag
3645 */
3646 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3647 delete_route = true;
9bcb3eef 3648 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3649 delete_route = true;
f009ff26 3650 if (delete_route) {
9bcb3eef
DS
3651 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3652 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3653 bgp = pi->peer->bgp;
26742171 3654 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3655 }
3656 }
3657 }
4a11bf2c 3658
9bcb3eef
DS
3659 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3660 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3661}
3662
9bcb3eef 3663static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3664 struct peer *peer, afi_t afi, safi_t safi,
3665 struct prefix_rd *prd)
3666{
9bcb3eef 3667 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3668
d62a17ae 3669 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3670 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3671 */
b4f7f45b
IR
3672 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3673 && peer->sort == BGP_PEER_EBGP)
3674 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3675 == BGP_DAMP_SUPPRESSED) {
3676 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3677 safi);
3678 return;
d62a17ae 3679 }
3680
49e5a4a0 3681#ifdef ENABLE_BGP_VNC
d62a17ae 3682 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3683 struct bgp_dest *pdest = NULL;
d62a17ae 3684 struct bgp_table *table = NULL;
3685
9bcb3eef
DS
3686 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3687 (struct prefix *)prd);
3688 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3689 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3690
3691 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3692 peer->bgp, prd, table, p, pi);
d62a17ae 3693 }
9bcb3eef 3694 bgp_dest_unlock_node(pdest);
d62a17ae 3695 }
3696 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3697 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3698
b54892e0
DS
3699 vnc_import_bgp_del_route(peer->bgp, p, pi);
3700 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3701 }
65efcfce 3702 }
d62a17ae 3703#endif
128ea8ab 3704
d62a17ae 3705 /* If this is an EVPN route, process for un-import. */
3706 if (safi == SAFI_EVPN)
b54892e0 3707 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3708
9bcb3eef 3709 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3710}
3711
4b7e6066
DS
3712struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3713 struct peer *peer, struct attr *attr,
9bcb3eef 3714 struct bgp_dest *dest)
fb018d25 3715{
4b7e6066 3716 struct bgp_path_info *new;
fb018d25 3717
d62a17ae 3718 /* Make new BGP info. */
4b7e6066 3719 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3720 new->type = type;
3721 new->instance = instance;
3722 new->sub_type = sub_type;
3723 new->peer = peer;
3724 new->attr = attr;
083ec940 3725 new->uptime = monotime(NULL);
9bcb3eef 3726 new->net = dest;
d62a17ae 3727 return new;
fb018d25
DS
3728}
3729
c265ee22 3730/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3731bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3732 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3733 struct bgp_dest *dest)
d62a17ae 3734{
2dbe3fa9 3735 bool ret = false;
b099a5c8
DA
3736 bool is_bgp_static_route =
3737 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3738 : false;
d62a17ae 3739
e8442016
DS
3740 /*
3741 * Only validated for unicast and multicast currently.
3742 * Also valid for EVPN where the nexthop is an IP address.
3743 * If we are a bgp static route being checked then there is
3744 * no need to check to see if the nexthop is martian as
3745 * that it should be ok.
3746 */
3747 if (is_bgp_static_route ||
3748 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3749 return false;
d62a17ae 3750
3751 /* If NEXT_HOP is present, validate it. */
3752 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3753 if (attr->nexthop.s_addr == INADDR_ANY ||
3754 !ipv4_unicast_valid(&attr->nexthop) ||
3755 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3756 return true;
d62a17ae 3757 }
c265ee22 3758
d62a17ae 3759 /* If MP_NEXTHOP is present, validate it. */
3760 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3761 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3762 * it is not an IPv6 link-local address.
0355b41d
DA
3763 *
3764 * If we receive an UPDATE with nexthop length set to 32 bytes
3765 * we shouldn't discard an UPDATE if it's set to (::).
3766 * The link-local (2st) is validated along the code path later.
d62a17ae 3767 */
3768 if (attr->mp_nexthop_len) {
3769 switch (attr->mp_nexthop_len) {
3770 case BGP_ATTR_NHLEN_IPV4:
3771 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3772 ret = (attr->mp_nexthop_global_in.s_addr ==
3773 INADDR_ANY ||
3774 !ipv4_unicast_valid(
3775 &attr->mp_nexthop_global_in) ||
3776 bgp_nexthop_self(bgp, afi, type, stype, attr,
3777 dest));
d62a17ae 3778 break;
3779
3780 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3781 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3782 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3783 &attr->mp_nexthop_global)
d62a17ae 3784 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3785 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3786 &attr->mp_nexthop_global)
3787 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3788 dest));
d62a17ae 3789 break;
0355b41d
DA
3790 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3791 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3792 || IN6_IS_ADDR_MULTICAST(
3793 &attr->mp_nexthop_global)
3794 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3795 dest));
0355b41d 3796 break;
d62a17ae 3797
3798 default:
3dc339cd 3799 ret = true;
d62a17ae 3800 break;
3801 }
3802 }
c265ee22 3803
d62a17ae 3804 return ret;
3805}
3806
aade37d7 3807static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3808{
3809 struct community *old;
3810 struct community *new;
3811 struct community *merge;
aade37d7 3812 struct community *no_export;
2721dd61 3813
9a706b42 3814 old = bgp_attr_get_community(attr);
aade37d7 3815 no_export = community_str2com("no-export");
2721dd61 3816
b4efa101
DA
3817 assert(no_export);
3818
2721dd61 3819 if (old) {
aade37d7 3820 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3821
3822 if (!old->refcnt)
3823 community_free(&old);
3824
3825 new = community_uniq_sort(merge);
3826 community_free(&merge);
3827 } else {
aade37d7 3828 new = community_dup(no_export);
2721dd61
DA
3829 }
3830
aade37d7 3831 community_free(&no_export);
2721dd61 3832
9a706b42 3833 bgp_attr_set_community(attr, new);
2721dd61
DA
3834}
3835
5a1ae2c2 3836int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3837 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3838 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3839 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3840 struct bgp_route_evpn *evpn)
d62a17ae 3841{
3842 int ret;
3843 int aspath_loop_count = 0;
9bcb3eef 3844 struct bgp_dest *dest;
d62a17ae 3845 struct bgp *bgp;
3846 struct attr new_attr;
3847 struct attr *attr_new;
40381db7 3848 struct bgp_path_info *pi;
4b7e6066
DS
3849 struct bgp_path_info *new;
3850 struct bgp_path_info_extra *extra;
d62a17ae 3851 const char *reason;
3852 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3853 int connected = 0;
3854 int do_loop_check = 1;
3855 int has_valid_label = 0;
7c312383 3856 afi_t nh_afi;
949b0f24 3857 uint8_t pi_type = 0;
3858 uint8_t pi_sub_type = 0;
9146341f 3859 bool force_evpn_import = false;
907707db 3860 safi_t orig_safi = safi;
a486300b 3861 bool leak_success = true;
949b0f24 3862
c7bb4f00 3863 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3864 char pfxprint[PREFIX2STR_BUFFER];
3865
3866 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3867 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3868 afi, safi, attr);
6401252f
QY
3869 }
3870
49e5a4a0 3871#ifdef ENABLE_BGP_VNC
d62a17ae 3872 int vnc_implicit_withdraw = 0;
65efcfce 3873#endif
d62a17ae 3874 int same_attr = 0;
718e3744 3875
907707db
MS
3876 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3877 if (orig_safi == SAFI_LABELED_UNICAST)
3878 safi = SAFI_UNICAST;
3879
6006b807 3880 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3881 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3882 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3883
d62a17ae 3884 bgp = peer->bgp;
9bcb3eef 3885 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3886 /* TODO: Check to see if we can get rid of "is_valid_label" */
3887 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3888 has_valid_label = (num_labels > 0) ? 1 : 0;
3889 else
3890 has_valid_label = bgp_is_valid_label(label);
718e3744 3891
28f66de2
MS
3892 if (has_valid_label)
3893 assert(label != NULL);
3894
66ff6089
AD
3895 /* Update overlay index of the attribute */
3896 if (afi == AFI_L2VPN && evpn)
3897 memcpy(&attr->evpn_overlay, evpn,
3898 sizeof(struct bgp_route_evpn));
3899
d62a17ae 3900 /* When peer's soft reconfiguration enabled. Record input packet in
3901 Adj-RIBs-In. */
3902 if (!soft_reconfig
3903 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3904 && peer != bgp->peer_self)
9bcb3eef 3905 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3906
3907 /* Check previously received route. */
9bcb3eef 3908 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3909 if (pi->peer == peer && pi->type == type
3910 && pi->sub_type == sub_type
3911 && pi->addpath_rx_id == addpath_id)
d62a17ae 3912 break;
3913
3914 /* AS path local-as loop check. */
3915 if (peer->change_local_as) {
c4368918
DW
3916 if (peer->allowas_in[afi][safi])
3917 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3918 else if (!CHECK_FLAG(peer->flags,
3919 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3920 aspath_loop_count = 1;
3921
3922 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3923 > aspath_loop_count) {
b4d46cc9 3924 peer->stat_pfx_aspath_loop++;
692174a1 3925 reason = "as-path contains our own AS;";
d62a17ae 3926 goto filtered;
3927 }
718e3744 3928 }
718e3744 3929
d62a17ae 3930 /* If the peer is configured for "allowas-in origin" and the last ASN in
3931 * the
3932 * as-path is our ASN then we do not need to call aspath_loop_check
3933 */
3934 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3935 if (aspath_get_last_as(attr->aspath) == bgp->as)
3936 do_loop_check = 0;
3937
3938 /* AS path loop check. */
3939 if (do_loop_check) {
3940 if (aspath_loop_check(attr->aspath, bgp->as)
3941 > peer->allowas_in[afi][safi]
3942 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3943 && aspath_loop_check(attr->aspath, bgp->confed_id)
3944 > peer->allowas_in[afi][safi])) {
b4d46cc9 3945 peer->stat_pfx_aspath_loop++;
d62a17ae 3946 reason = "as-path contains our own AS;";
3947 goto filtered;
3948 }
3949 }
aac9ef6c 3950
d62a17ae 3951 /* Route reflector originator ID check. */
3952 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3953 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3954 peer->stat_pfx_originator_loop++;
d62a17ae 3955 reason = "originator is us;";
3956 goto filtered;
3957 }
718e3744 3958
d62a17ae 3959 /* Route reflector cluster ID check. */
3960 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3961 peer->stat_pfx_cluster_loop++;
d62a17ae 3962 reason = "reflected from the same cluster;";
3963 goto filtered;
3964 }
718e3744 3965
d62a17ae 3966 /* Apply incoming filter. */
907707db 3967 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3968 peer->stat_pfx_filter++;
d62a17ae 3969 reason = "filter;";
3970 goto filtered;
3971 }
718e3744 3972
a8b72dc6
DA
3973 /* RFC 8212 to prevent route leaks.
3974 * This specification intends to improve this situation by requiring the
3975 * explicit configuration of both BGP Import and Export Policies for any
3976 * External BGP (EBGP) session such as customers, peers, or
3977 * confederation boundaries for all enabled address families. Through
3978 * codification of the aforementioned requirement, operators will
3979 * benefit from consistent behavior across different BGP
3980 * implementations.
3981 */
1d3fdccf 3982 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3983 if (!bgp_inbound_policy_exists(peer,
3984 &peer->filter[afi][safi])) {
3985 reason = "inbound policy missing";
b17826b7
DS
3986 if (monotime_since(&bgp->ebgprequirespolicywarning,
3987 NULL) > FIFTEENMINUTE2USEC ||
3988 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3989 zlog_warn(
3990 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3991 monotime(&bgp->ebgprequirespolicywarning);
3992 }
a8b72dc6
DA
3993 goto filtered;
3994 }
3995
fb29348a
DA
3996 /* draft-ietf-idr-deprecate-as-set-confed-set
3997 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3998 * Eventually, This document (if approved) updates RFC 4271
3999 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
4000 * and obsoletes RFC 6472.
4001 */
7f972cd8 4002 if (peer->bgp->reject_as_sets)
fb29348a
DA
4003 if (aspath_check_as_sets(attr->aspath)) {
4004 reason =
4005 "as-path contains AS_SET or AS_CONFED_SET type;";
4006 goto filtered;
4007 }
4008
6f4f49b2 4009 new_attr = *attr;
d62a17ae 4010
4011 /* Apply incoming route-map.
4012 * NB: new_attr may now contain newly allocated values from route-map
4013 * "set"
4014 * commands, so we need bgp_attr_flush in the error paths, until we
4015 * intern
4016 * the attr (which takes over the memory references) */
907707db 4017 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
4018 num_labels, dest)
4019 == RMAP_DENY) {
b4d46cc9 4020 peer->stat_pfx_filter++;
d62a17ae 4021 reason = "route-map;";
4022 bgp_attr_flush(&new_attr);
4023 goto filtered;
4024 }
718e3744 4025
05864da7 4026 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4027 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4028 /* remove from RIB previous entry */
4029 bgp_zebra_withdraw(p, pi, bgp, safi);
4030 }
4031
7f323236
DW
4032 if (peer->sort == BGP_PEER_EBGP) {
4033
2721dd61
DA
4034 /* rfc7999:
4035 * A BGP speaker receiving an announcement tagged with the
4036 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4037 * NO_EXPORT community as defined in RFC1997, or a
4038 * similar community, to prevent propagation of the
4039 * prefix outside the local AS. The community to prevent
4040 * propagation SHOULD be chosen according to the operator's
4041 * routing policy.
4042 */
9a706b42
DA
4043 if (bgp_attr_get_community(&new_attr) &&
4044 community_include(bgp_attr_get_community(&new_attr),
4045 COMMUNITY_BLACKHOLE))
aade37d7 4046 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4047
a4d82a8a
PZ
4048 /* If we receive the graceful-shutdown community from an eBGP
4049 * peer we must lower local-preference */
9a706b42
DA
4050 if (bgp_attr_get_community(&new_attr) &&
4051 community_include(bgp_attr_get_community(&new_attr),
4052 COMMUNITY_GSHUT)) {
7f323236
DW
4053 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4054 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4055
a4d82a8a
PZ
4056 /* If graceful-shutdown is configured then add the GSHUT
4057 * community to all paths received from eBGP peers */
637e5ba4 4058 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4059 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4060 }
4061
949b0f24 4062 if (pi) {
4063 pi_type = pi->type;
4064 pi_sub_type = pi->sub_type;
4065 }
4066
d62a17ae 4067 /* next hop check. */
a4d82a8a 4068 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
4069 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
4070 &new_attr, dest)) {
b4d46cc9 4071 peer->stat_pfx_nh_invalid++;
d62a17ae 4072 reason = "martian or self next-hop;";
4073 bgp_attr_flush(&new_attr);
4074 goto filtered;
4075 }
718e3744 4076
5c14a191 4077 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4078 peer->stat_pfx_nh_invalid++;
4e802e66 4079 reason = "self mac;";
4dbf2038 4080 bgp_attr_flush(&new_attr);
4e802e66
DS
4081 goto filtered;
4082 }
4083
5a78f2bc
EB
4084 if (bgp_check_role_applicability(afi, safi) &&
4085 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4086 reason = "failing otc validation";
4087 bgp_attr_flush(&new_attr);
4088 goto filtered;
4089 }
a1b773e2
DS
4090 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4091 * condition :
4092 * Suppress fib is enabled
4093 * BGP_OPT_NO_FIB is not enabled
4094 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4095 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4096 */
4097 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4098 && (sub_type == BGP_ROUTE_NORMAL)
4099 && (!bgp_option_check(BGP_OPT_NO_FIB))
4100 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4101 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4102
9cbd06e0
DA
4103 /* If maximum prefix count is configured and current prefix
4104 * count exeed it.
4105 */
4dbf2038
IR
4106 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4107 bgp_attr_flush(&new_attr);
9cbd06e0 4108 return -1;
4dbf2038
IR
4109 }
4110
01da2d26
DA
4111 /* If neighbor soo is configured, tag all incoming routes with
4112 * this SoO tag and then filter out advertisements in
4113 * subgroup_announce_check() if it matches the configured SoO
4114 * on the other peer.
4115 */
4116 if (peer->soo[afi][safi]) {
4117 struct ecommunity *old_ecomm =
4118 bgp_attr_get_ecommunity(&new_attr);
4119 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4120 struct ecommunity *new_ecomm;
4121
4122 if (old_ecomm) {
4123 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4124 ecomm_soo);
4125
4126 if (!old_ecomm->refcnt)
4127 ecommunity_free(&old_ecomm);
4128 } else {
4129 new_ecomm = ecommunity_dup(ecomm_soo);
4130 }
4131
4132 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4133 }
4134
4dbf2038 4135 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4136
d62a17ae 4137 /* If the update is implicit withdraw. */
40381db7 4138 if (pi) {
083ec940 4139 pi->uptime = monotime(NULL);
40381db7 4140 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4141
9bcb3eef 4142 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4143
d62a17ae 4144 /* Same attribute comes in. */
40381db7 4145 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4146 && same_attr
d62a17ae 4147 && (!has_valid_label
40381db7 4148 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4149 num_labels * sizeof(mpls_label_t))
66ff6089 4150 == 0)) {
b4f7f45b
IR
4151 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4152 BGP_CONFIG_DAMPENING)
d62a17ae 4153 && peer->sort == BGP_PEER_EBGP
40381db7 4154 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4155 if (bgp_debug_update(peer, p, NULL, 1)) {
4156 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4157 afi, safi, prd, p, label,
4158 num_labels, addpath_id ? 1 : 0,
66ff6089 4159 addpath_id, evpn, pfx_buf,
a4d82a8a 4160 sizeof(pfx_buf));
f70c91dc 4161 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4162 pfx_buf);
4163 }
4164
9bcb3eef 4165 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4166 != BGP_DAMP_SUPPRESSED) {
40381db7 4167 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4168 safi);
9bcb3eef 4169 bgp_process(bgp, dest, afi, safi);
d62a17ae 4170 }
4171 } else /* Duplicate - odd */
4172 {
4173 if (bgp_debug_update(peer, p, NULL, 1)) {
4174 if (!peer->rcvd_attr_printed) {
4175 zlog_debug(
f70c91dc
DA
4176 "%pBP rcvd UPDATE w/ attr: %s",
4177 peer,
d62a17ae 4178 peer->rcvd_attr_str);
4179 peer->rcvd_attr_printed = 1;
4180 }
4181
4182 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4183 afi, safi, prd, p, label,
4184 num_labels, addpath_id ? 1 : 0,
66ff6089 4185 addpath_id, evpn, pfx_buf,
a4d82a8a 4186 sizeof(pfx_buf));
d62a17ae 4187 zlog_debug(
f70c91dc
DA
4188 "%pBP rcvd %s...duplicate ignored",
4189 peer, pfx_buf);
d62a17ae 4190 }
4191
4192 /* graceful restart STALE flag unset. */
40381db7 4193 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4194 bgp_path_info_unset_flag(
9bcb3eef
DS
4195 dest, pi, BGP_PATH_STALE);
4196 bgp_dest_set_defer_flag(dest, false);
4197 bgp_process(bgp, dest, afi, safi);
d62a17ae 4198 }
4199 }
4200
9bcb3eef 4201 bgp_dest_unlock_node(dest);
d62a17ae 4202 bgp_attr_unintern(&attr_new);
4203
4204 return 0;
4205 }
718e3744 4206
d62a17ae 4207 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4208 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4209 if (bgp_debug_update(peer, p, NULL, 1)) {
4210 bgp_debug_rdpfxpath2str(
a4d82a8a 4211 afi, safi, prd, p, label, num_labels,
66ff6089 4212 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4213 pfx_buf, sizeof(pfx_buf));
d62a17ae 4214 zlog_debug(
f70c91dc
DA
4215 "%pBP rcvd %s, flapped quicker than processing",
4216 peer, pfx_buf);
d62a17ae 4217 }
4218
9bcb3eef 4219 bgp_path_info_restore(dest, pi);
9146341f 4220
4221 /*
4222 * If the BGP_PATH_REMOVED flag is set, then EVPN
4223 * routes would have been unimported already when a
4224 * prior BGP withdraw processing happened. Such routes
4225 * need to be imported again, so flag accordingly.
4226 */
4227 force_evpn_import = true;
d62a17ae 4228 }
718e3744 4229
d62a17ae 4230 /* Received Logging. */
4231 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4232 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4233 num_labels, addpath_id ? 1 : 0,
66ff6089 4234 addpath_id, evpn, pfx_buf,
a4d82a8a 4235 sizeof(pfx_buf));
f70c91dc 4236 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4237 }
718e3744 4238
d62a17ae 4239 /* graceful restart STALE flag unset. */
f009ff26 4240 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4241 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4242 bgp_dest_set_defer_flag(dest, false);
f009ff26 4243 }
d62a17ae 4244
4245 /* The attribute is changed. */
9bcb3eef 4246 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4247
4248 /* implicit withdraw, decrement aggregate and pcount here.
4249 * only if update is accepted, they'll increment below.
4250 */
40381db7 4251 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4252
4253 /* Update bgp route dampening information. */
b4f7f45b 4254 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4255 && peer->sort == BGP_PEER_EBGP) {
4256 /* This is implicit withdraw so we should update
b4f7f45b
IR
4257 dampening
4258 information. */
40381db7 4259 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4260 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4261 }
49e5a4a0 4262#ifdef ENABLE_BGP_VNC
d62a17ae 4263 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4264 struct bgp_dest *pdest = NULL;
d62a17ae 4265 struct bgp_table *table = NULL;
4266
9bcb3eef
DS
4267 pdest = bgp_node_get(bgp->rib[afi][safi],
4268 (struct prefix *)prd);
4269 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4270 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4271
4272 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4273 bgp, prd, table, p, pi);
d62a17ae 4274 }
9bcb3eef 4275 bgp_dest_unlock_node(pdest);
d62a17ae 4276 }
4277 if ((afi == AFI_IP || afi == AFI_IP6)
4278 && (safi == SAFI_UNICAST)) {
40381db7 4279 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4280 /*
4281 * Implicit withdraw case.
4282 */
4283 ++vnc_implicit_withdraw;
40381db7
DS
4284 vnc_import_bgp_del_route(bgp, p, pi);
4285 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4286 }
4287 }
65efcfce 4288#endif
128ea8ab 4289
d62a17ae 4290 /* Special handling for EVPN update of an existing route. If the
4291 * extended community attribute has changed, we need to
4292 * un-import
4293 * the route using its existing extended community. It will be
4294 * subsequently processed for import with the new extended
4295 * community.
4296 */
6f8c9c11
PR
4297 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4298 && !same_attr) {
40381db7 4299 if ((pi->attr->flag
d62a17ae 4300 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4301 && (attr_new->flag
4302 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4303 int cmp;
4304
b53e67a3
DA
4305 cmp = ecommunity_cmp(
4306 bgp_attr_get_ecommunity(pi->attr),
4307 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4308 if (!cmp) {
4309 if (bgp_debug_update(peer, p, NULL, 1))
4310 zlog_debug(
4311 "Change in EXT-COMM, existing %s new %s",
4312 ecommunity_str(
b53e67a3
DA
4313 bgp_attr_get_ecommunity(
4314 pi->attr)),
d62a17ae 4315 ecommunity_str(
b53e67a3
DA
4316 bgp_attr_get_ecommunity(
4317 attr_new)));
6f8c9c11
PR
4318 if (safi == SAFI_EVPN)
4319 bgp_evpn_unimport_route(
4320 bgp, afi, safi, p, pi);
4321 else /* SAFI_MPLS_VPN */
4322 vpn_leak_to_vrf_withdraw(bgp,
4323 pi);
d62a17ae 4324 }
4325 }
4326 }
718e3744 4327
d62a17ae 4328 /* Update to new attribute. */
40381db7
DS
4329 bgp_attr_unintern(&pi->attr);
4330 pi->attr = attr_new;
d62a17ae 4331
4332 /* Update MPLS label */
4333 if (has_valid_label) {
40381db7 4334 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4335 if (extra->label != label) {
4336 memcpy(&extra->label, label,
dbd587da 4337 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4338 extra->num_labels = num_labels;
4339 }
b57ba6d2
MK
4340 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4341 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4342 }
718e3744 4343
e496b420
HS
4344 /* Update SRv6 SID */
4345 if (attr->srv6_l3vpn) {
4346 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4347 if (sid_diff(&extra->sid[0].sid,
4348 &attr->srv6_l3vpn->sid)) {
4349 sid_copy(&extra->sid[0].sid,
e496b420
HS
4350 &attr->srv6_l3vpn->sid);
4351 extra->num_sids = 1;
cc8f05df 4352
16f3db2d
RS
4353 extra->sid[0].loc_block_len = 0;
4354 extra->sid[0].loc_node_len = 0;
4355 extra->sid[0].func_len = 0;
4356 extra->sid[0].arg_len = 0;
ea7cd161
RS
4357 extra->sid[0].transposition_len = 0;
4358 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4359
4360 if (attr->srv6_l3vpn->loc_block_len != 0) {
4361 extra->sid[0].loc_block_len =
4362 attr->srv6_l3vpn->loc_block_len;
4363 extra->sid[0].loc_node_len =
4364 attr->srv6_l3vpn->loc_node_len;
4365 extra->sid[0].func_len =
4366 attr->srv6_l3vpn->func_len;
4367 extra->sid[0].arg_len =
4368 attr->srv6_l3vpn->arg_len;
ea7cd161 4369 extra->sid[0].transposition_len =
cc8f05df 4370 attr->srv6_l3vpn
ea7cd161
RS
4371 ->transposition_len;
4372 extra->sid[0].transposition_offset =
cc8f05df 4373 attr->srv6_l3vpn
ea7cd161
RS
4374 ->transposition_offset;
4375 }
e496b420
HS
4376 }
4377 } else if (attr->srv6_vpn) {
4378 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4379 if (sid_diff(&extra->sid[0].sid,
4380 &attr->srv6_vpn->sid)) {
4381 sid_copy(&extra->sid[0].sid,
4382 &attr->srv6_vpn->sid);
e496b420
HS
4383 extra->num_sids = 1;
4384 }
4385 }
4386
49e5a4a0 4387#ifdef ENABLE_BGP_VNC
d62a17ae 4388 if ((afi == AFI_IP || afi == AFI_IP6)
4389 && (safi == SAFI_UNICAST)) {
4390 if (vnc_implicit_withdraw) {
4391 /*
4392 * Add back the route with its new attributes
4393 * (e.g., nexthop).
4394 * The route is still selected, until the route
4395 * selection
4396 * queued by bgp_process actually runs. We have
4397 * to make this
4398 * update to the VNC side immediately to avoid
4399 * racing against
4400 * configuration changes (e.g., route-map
4401 * changes) which
4402 * trigger re-importation of the entire RIB.
4403 */
40381db7
DS
4404 vnc_import_bgp_add_route(bgp, p, pi);
4405 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4406 }
4407 }
65efcfce
LB
4408#endif
4409
d62a17ae 4410 /* Update bgp route dampening information. */
b4f7f45b 4411 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4412 && peer->sort == BGP_PEER_EBGP) {
4413 /* Now we do normal update dampening. */
9bcb3eef 4414 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4415 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4416 bgp_dest_unlock_node(dest);
d62a17ae 4417 return 0;
4418 }
4419 }
128ea8ab 4420
d62a17ae 4421 /* Nexthop reachability check - for unicast and
4422 * labeled-unicast.. */
7c312383
AD
4423 if (((afi == AFI_IP || afi == AFI_IP6)
4424 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4425 || (safi == SAFI_EVPN &&
4426 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4427 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4428 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4429 && !CHECK_FLAG(peer->flags,
4430 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4431 && !CHECK_FLAG(bgp->flags,
4432 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4433 connected = 1;
4434 else
4435 connected = 0;
4436
960035b2
PZ
4437 struct bgp *bgp_nexthop = bgp;
4438
40381db7
DS
4439 if (pi->extra && pi->extra->bgp_orig)
4440 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4441
7c312383
AD
4442 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4443
4444 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4445 safi, pi, NULL, connected,
4446 p)
a4d82a8a 4447 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4448 bgp_path_info_set_flag(dest, pi,
4449 BGP_PATH_VALID);
d62a17ae 4450 else {
4451 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4452 zlog_debug("%s(%pI4): NH unresolved",
4453 __func__,
4454 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4455 }
9bcb3eef 4456 bgp_path_info_unset_flag(dest, pi,
18ee8310 4457 BGP_PATH_VALID);
d62a17ae 4458 }
4459 } else
9bcb3eef 4460 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4461
49e5a4a0 4462#ifdef ENABLE_BGP_VNC
d62a17ae 4463 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4464 struct bgp_dest *pdest = NULL;
d62a17ae 4465 struct bgp_table *table = NULL;
4466
9bcb3eef
DS
4467 pdest = bgp_node_get(bgp->rib[afi][safi],
4468 (struct prefix *)prd);
4469 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4470 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4471
4472 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4473 bgp, prd, table, p, pi);
d62a17ae 4474 }
9bcb3eef 4475 bgp_dest_unlock_node(pdest);
d62a17ae 4476 }
4477#endif
718e3744 4478
d62a17ae 4479 /* If this is an EVPN route and some attribute has changed,
9146341f 4480 * or we are explicitly told to perform a route import, process
d62a17ae 4481 * route for import. If the extended community has changed, we
4482 * would
4483 * have done the un-import earlier and the import would result
4484 * in the
4485 * route getting injected into appropriate L2 VNIs. If it is
4486 * just
4487 * some other attribute change, the import will result in
4488 * updating
4489 * the attributes for the route in the VNI(s).
4490 */
9146341f 4491 if (safi == SAFI_EVPN &&
4492 (!same_attr || force_evpn_import) &&
7c312383 4493 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4494 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4495
4496 /* Process change. */
40381db7 4497 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4498
9bcb3eef
DS
4499 bgp_process(bgp, dest, afi, safi);
4500 bgp_dest_unlock_node(dest);
558d1fec 4501
ddb5b488
PZ
4502 if (SAFI_UNICAST == safi
4503 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4504 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4505
40381db7 4506 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4507 }
4508 if ((SAFI_MPLS_VPN == safi)
4509 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4510
a486300b 4511 leak_success = vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4512 }
4513
49e5a4a0 4514#ifdef ENABLE_BGP_VNC
d62a17ae 4515 if (SAFI_MPLS_VPN == safi) {
4516 mpls_label_t label_decoded = decode_label(label);
28070ee3 4517
d62a17ae 4518 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4519 type, sub_type, &label_decoded);
4520 }
4521 if (SAFI_ENCAP == safi) {
4522 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4523 type, sub_type, NULL);
4524 }
28070ee3 4525#endif
a486300b
PG
4526 if ((safi == SAFI_MPLS_VPN) &&
4527 !CHECK_FLAG(bgp->af_flags[afi][safi],
4528 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4529 !leak_success) {
4530 bgp_unlink_nexthop(pi);
4531 bgp_path_info_delete(dest, pi);
4532 }
d62a17ae 4533 return 0;
4534 } // End of implicit withdraw
718e3744 4535
d62a17ae 4536 /* Received Logging. */
4537 if (bgp_debug_update(peer, p, NULL, 1)) {
4538 if (!peer->rcvd_attr_printed) {
f70c91dc 4539 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4540 peer->rcvd_attr_str);
4541 peer->rcvd_attr_printed = 1;
4542 }
718e3744 4543
a4d82a8a 4544 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4545 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4546 pfx_buf, sizeof(pfx_buf));
f70c91dc 4547 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4548 }
718e3744 4549
d62a17ae 4550 /* Make new BGP info. */
9bcb3eef 4551 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4552
d62a17ae 4553 /* Update MPLS label */
4554 if (has_valid_label) {
18ee8310 4555 extra = bgp_path_info_extra_get(new);
8ba71050 4556 if (extra->label != label) {
dbd587da
QY
4557 memcpy(&extra->label, label,
4558 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4559 extra->num_labels = num_labels;
4560 }
b57ba6d2
MK
4561 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4562 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4563 }
718e3744 4564
e496b420
HS
4565 /* Update SRv6 SID */
4566 if (safi == SAFI_MPLS_VPN) {
4567 extra = bgp_path_info_extra_get(new);
4568 if (attr->srv6_l3vpn) {
16f3db2d 4569 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4570 extra->num_sids = 1;
cc8f05df 4571
16f3db2d
RS
4572 extra->sid[0].loc_block_len =
4573 attr->srv6_l3vpn->loc_block_len;
4574 extra->sid[0].loc_node_len =
4575 attr->srv6_l3vpn->loc_node_len;
4576 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4577 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4578 extra->sid[0].transposition_len =
4579 attr->srv6_l3vpn->transposition_len;
4580 extra->sid[0].transposition_offset =
4581 attr->srv6_l3vpn->transposition_offset;
e496b420 4582 } else if (attr->srv6_vpn) {
16f3db2d 4583 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4584 extra->num_sids = 1;
4585 }
4586 }
4587
d62a17ae 4588 /* Nexthop reachability check. */
7c312383
AD
4589 if (((afi == AFI_IP || afi == AFI_IP6)
4590 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4591 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4592 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4593 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4594 && !CHECK_FLAG(peer->flags,
4595 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4596 && !CHECK_FLAG(bgp->flags,
4597 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4598 connected = 1;
4599 else
4600 connected = 0;
4601
7c312383
AD
4602 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4603
4053e952 4604 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4605 connected, p)
a4d82a8a 4606 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4607 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4608 else {
4609 if (BGP_DEBUG(nht, NHT)) {
4610 char buf1[INET6_ADDRSTRLEN];
4611 inet_ntop(AF_INET,
4612 (const void *)&attr_new->nexthop,
4613 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4614 zlog_debug("%s(%s): NH unresolved", __func__,
4615 buf1);
d62a17ae 4616 }
9bcb3eef 4617 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4618 }
4619 } else
9bcb3eef 4620 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4621
d62a17ae 4622 /* Addpath ID */
4623 new->addpath_rx_id = addpath_id;
4624
4625 /* Increment prefix */
4626 bgp_aggregate_increment(bgp, p, new, afi, safi);
4627
4628 /* Register new BGP information. */
9bcb3eef 4629 bgp_path_info_add(dest, new);
d62a17ae 4630
4631 /* route_node_get lock */
9bcb3eef 4632 bgp_dest_unlock_node(dest);
558d1fec 4633
49e5a4a0 4634#ifdef ENABLE_BGP_VNC
d62a17ae 4635 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4636 struct bgp_dest *pdest = NULL;
d62a17ae 4637 struct bgp_table *table = NULL;
4638
9bcb3eef
DS
4639 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4640 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4641 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4642
4643 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4644 bgp, prd, table, p, new);
4645 }
9bcb3eef 4646 bgp_dest_unlock_node(pdest);
d62a17ae 4647 }
65efcfce
LB
4648#endif
4649
d62a17ae 4650 /* If this is an EVPN route, process for import. */
7c312383 4651 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4652 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4653
9bcb3eef 4654 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4655
d62a17ae 4656 /* Process change. */
9bcb3eef 4657 bgp_process(bgp, dest, afi, safi);
718e3744 4658
ddb5b488
PZ
4659 if (SAFI_UNICAST == safi
4660 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4661 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4662 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4663 }
4664 if ((SAFI_MPLS_VPN == safi)
4665 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
a486300b 4666 leak_success = vpn_leak_to_vrf_update(bgp, new);
ddb5b488 4667 }
49e5a4a0 4668#ifdef ENABLE_BGP_VNC
d62a17ae 4669 if (SAFI_MPLS_VPN == safi) {
4670 mpls_label_t label_decoded = decode_label(label);
28070ee3 4671
d62a17ae 4672 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4673 sub_type, &label_decoded);
4674 }
4675 if (SAFI_ENCAP == safi) {
4676 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4677 sub_type, NULL);
4678 }
28070ee3 4679#endif
a486300b
PG
4680 if ((safi == SAFI_MPLS_VPN) &&
4681 !CHECK_FLAG(bgp->af_flags[afi][safi],
4682 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4683 !leak_success) {
4684 bgp_unlink_nexthop(new);
4685 bgp_path_info_delete(dest, new);
4686 }
28070ee3 4687
d62a17ae 4688 return 0;
718e3744 4689
d62a17ae 4690/* This BGP update is filtered. Log the reason then update BGP
4691 entry. */
4692filtered:
9bcb3eef 4693 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4694
d62a17ae 4695 if (bgp_debug_update(peer, p, NULL, 1)) {
4696 if (!peer->rcvd_attr_printed) {
f70c91dc 4697 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4698 peer->rcvd_attr_str);
4699 peer->rcvd_attr_printed = 1;
4700 }
718e3744 4701
a4d82a8a 4702 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4703 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4704 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4705 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4706 peer, pfx_buf, reason);
d62a17ae 4707 }
128ea8ab 4708
40381db7 4709 if (pi) {
d62a17ae 4710 /* If this is an EVPN route, un-import it as it is now filtered.
4711 */
4712 if (safi == SAFI_EVPN)
40381db7 4713 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4714
ddb5b488
PZ
4715 if (SAFI_UNICAST == safi
4716 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4717 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4718
40381db7 4719 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4720 }
4721 if ((SAFI_MPLS_VPN == safi)
4722 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4723
40381db7 4724 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4725 }
4726
9bcb3eef 4727 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4728 }
4729
9bcb3eef 4730 bgp_dest_unlock_node(dest);
558d1fec 4731
49e5a4a0 4732#ifdef ENABLE_BGP_VNC
d62a17ae 4733 /*
4734 * Filtered update is treated as an implicit withdrawal (see
4735 * bgp_rib_remove()
4736 * a few lines above)
4737 */
4738 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4739 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4740 0);
4741 }
97736e32
PZ
4742#endif
4743
d62a17ae 4744 return 0;
718e3744 4745}
4746
26a3ffd6 4747int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4748 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4749 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4750 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4751{
d62a17ae 4752 struct bgp *bgp;
4753 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4754 struct bgp_dest *dest;
40381db7 4755 struct bgp_path_info *pi;
718e3744 4756
49e5a4a0 4757#ifdef ENABLE_BGP_VNC
d62a17ae 4758 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4759 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4760 0);
4761 }
28070ee3
PZ
4762#endif
4763
d62a17ae 4764 bgp = peer->bgp;
4765
4766 /* Lookup node. */
9bcb3eef 4767 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4768
4769 /* If peer is soft reconfiguration enabled. Record input packet for
4770 * further calculation.
4771 *
4772 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4773 * routes that are filtered. This tanks out Quagga RS pretty badly due
4774 * to
4775 * the iteration over all RS clients.
4776 * Since we need to remove the entry from adj_in anyway, do that first
4777 * and
4778 * if there was no entry, we don't need to do anything more.
4779 */
4780 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4781 && peer != bgp->peer_self)
9bcb3eef 4782 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4783 peer->stat_pfx_dup_withdraw++;
4784
d62a17ae 4785 if (bgp_debug_update(peer, p, NULL, 1)) {
4786 bgp_debug_rdpfxpath2str(
a4d82a8a 4787 afi, safi, prd, p, label, num_labels,
6c995628
AD
4788 addpath_id ? 1 : 0, addpath_id, NULL,
4789 pfx_buf, sizeof(pfx_buf));
d62a17ae 4790 zlog_debug(
4791 "%s withdrawing route %s not in adj-in",
4792 peer->host, pfx_buf);
4793 }
9bcb3eef 4794 bgp_dest_unlock_node(dest);
d62a17ae 4795 return 0;
4796 }
cd808e74 4797
d62a17ae 4798 /* Lookup withdrawn route. */
9bcb3eef 4799 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4800 if (pi->peer == peer && pi->type == type
4801 && pi->sub_type == sub_type
4802 && pi->addpath_rx_id == addpath_id)
d62a17ae 4803 break;
4804
4805 /* Logging. */
4806 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4807 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4808 addpath_id ? 1 : 0, addpath_id, NULL,
4809 pfx_buf, sizeof(pfx_buf));
f70c91dc 4810 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4811 pfx_buf);
4812 }
718e3744 4813
d62a17ae 4814 /* Withdraw specified route from routing table. */
40381db7 4815 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4816 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4817 if (SAFI_UNICAST == safi
4818 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4819 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4820 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4821 }
4822 if ((SAFI_MPLS_VPN == safi)
4823 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4824
40381db7 4825 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4826 }
4827 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4828 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4829 addpath_id ? 1 : 0, addpath_id, NULL,
4830 pfx_buf, sizeof(pfx_buf));
d62a17ae 4831 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4832 }
718e3744 4833
d62a17ae 4834 /* Unlock bgp_node_get() lock. */
9bcb3eef 4835 bgp_dest_unlock_node(dest);
d62a17ae 4836
4837 return 0;
718e3744 4838}
6b0655a2 4839
d62a17ae 4840void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4841 int withdraw)
718e3744 4842{
d62a17ae 4843 struct update_subgroup *subgrp;
4844 subgrp = peer_subgroup(peer, afi, safi);
4845 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4846}
6182d65b 4847
718e3744 4848
3f9c7369
DS
4849/*
4850 * bgp_stop_announce_route_timer
4851 */
d62a17ae 4852void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4853{
d62a17ae 4854 if (!paf->t_announce_route)
4855 return;
4856
c3aaa89a 4857 THREAD_OFF(paf->t_announce_route);
718e3744 4858}
6b0655a2 4859
3f9c7369
DS
4860/*
4861 * bgp_announce_route_timer_expired
4862 *
4863 * Callback that is invoked when the route announcement timer for a
4864 * peer_af expires.
4865 */
cc9f21da 4866static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4867{
d62a17ae 4868 struct peer_af *paf;
4869 struct peer *peer;
558d1fec 4870
d62a17ae 4871 paf = THREAD_ARG(t);
4872 peer = paf->peer;
718e3744 4873
feb17238 4874 if (!peer_established(peer))
cc9f21da 4875 return;
3f9c7369 4876
d62a17ae 4877 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4878 return;
3f9c7369 4879
d62a17ae 4880 peer_af_announce_route(paf, 1);
c5aec50b
MK
4881
4882 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4883 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4884}
4885
3f9c7369
DS
4886/*
4887 * bgp_announce_route
4888 *
4889 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4890 *
4891 * if force is true we will force an update even if the update
4892 * limiting code is attempted to kick in.
3f9c7369 4893 */
e1a32ec1 4894void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4895{
4896 struct peer_af *paf;
4897 struct update_subgroup *subgrp;
4898
4899 paf = peer_af_find(peer, afi, safi);
4900 if (!paf)
4901 return;
4902 subgrp = PAF_SUBGRP(paf);
4903
4904 /*
4905 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4906 * or a refresh has already been triggered.
4907 */
4908 if (!subgrp || paf->t_announce_route)
4909 return;
4910
e1a32ec1
DS
4911 if (force)
4912 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4913
d62a17ae 4914 /*
4915 * Start a timer to stagger/delay the announce. This serves
4916 * two purposes - announcement can potentially be combined for
4917 * multiple peers and the announcement doesn't happen in the
4918 * vty context.
4919 */
4920 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4921 (subgrp->peer_count == 1)
4922 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4923 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4924 &paf->t_announce_route);
3f9c7369
DS
4925}
4926
4927/*
4928 * Announce routes from all AF tables to a peer.
4929 *
4930 * This should ONLY be called when there is a need to refresh the
4931 * routes to the peer based on a policy change for this peer alone
4932 * or a route refresh request received from the peer.
4933 * The operation will result in splitting the peer from its existing
4934 * subgroups and putting it in new subgroups.
4935 */
d62a17ae 4936void bgp_announce_route_all(struct peer *peer)
718e3744 4937{
d62a17ae 4938 afi_t afi;
4939 safi_t safi;
4940
05c7a1cc 4941 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4942 bgp_announce_route(peer, afi, safi, false);
718e3744 4943}
6b0655a2 4944
46aeabed
LS
4945/* Flag or unflag bgp_dest to determine whether it should be treated by
4946 * bgp_soft_reconfig_table_task.
4947 * Flag if flag is true. Unflag if flag is false.
4948 */
4949static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4950{
4951 struct bgp_dest *dest;
4952 struct bgp_adj_in *ain;
4953
4954 if (!table)
4955 return;
4956
4957 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4958 for (ain = dest->adj_in; ain; ain = ain->next) {
4959 if (ain->peer != NULL)
4960 break;
4961 }
4962 if (flag && ain != NULL && ain->peer != NULL)
4963 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4964 else
4965 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4966 }
4967}
4968
4969static int bgp_soft_reconfig_table_update(struct peer *peer,
4970 struct bgp_dest *dest,
4971 struct bgp_adj_in *ain, afi_t afi,
4972 safi_t safi, struct prefix_rd *prd)
4973{
4974 struct bgp_path_info *pi;
4975 uint32_t num_labels = 0;
4976 mpls_label_t *label_pnt = NULL;
4977 struct bgp_route_evpn evpn;
4978
4979 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4980 if (pi->peer == peer)
4981 break;
4982
4983 if (pi && pi->extra)
4984 num_labels = pi->extra->num_labels;
4985 if (num_labels)
4986 label_pnt = &pi->extra->label[0];
4987 if (pi)
4988 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4989 sizeof(evpn));
4990 else
4991 memset(&evpn, 0, sizeof(evpn));
4992
4993 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4994 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4995 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4996 &evpn);
4997}
4998
d62a17ae 4999static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
5000 struct bgp_table *table,
5001 struct prefix_rd *prd)
718e3744 5002{
d62a17ae 5003 int ret;
9bcb3eef 5004 struct bgp_dest *dest;
d62a17ae 5005 struct bgp_adj_in *ain;
718e3744 5006
d62a17ae 5007 if (!table)
5008 table = peer->bgp->rib[afi][safi];
718e3744 5009
9bcb3eef
DS
5010 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5011 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
5012 if (ain->peer != peer)
5013 continue;
8692c506 5014
46aeabed
LS
5015 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
5016 afi, safi, prd);
ea47320b
DL
5017
5018 if (ret < 0) {
9bcb3eef 5019 bgp_dest_unlock_node(dest);
ea47320b 5020 return;
d62a17ae 5021 }
5022 }
718e3744 5023}
5024
46aeabed
LS
5025/* Do soft reconfig table per bgp table.
5026 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5027 * when BGP_NODE_SOFT_RECONFIG is set,
5028 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5029 * Schedule a new thread to continue the job.
5030 * Without splitting the full job into several part,
5031 * vtysh waits for the job to finish before responding to a BGP command
5032 */
cc9f21da 5033static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5034{
5035 uint32_t iter, max_iter;
5036 int ret;
5037 struct bgp_dest *dest;
5038 struct bgp_adj_in *ain;
5039 struct peer *peer;
5040 struct bgp_table *table;
5041 struct prefix_rd *prd;
5042 struct listnode *node, *nnode;
5043
5044 table = THREAD_ARG(thread);
5045 prd = NULL;
5046
5047 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5048 if (table->soft_reconfig_init) {
5049 /* first call of the function with a new srta structure.
5050 * Don't do any treatment this time on nodes
5051 * in order vtysh to respond quickly
5052 */
5053 max_iter = 0;
5054 }
5055
5056 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5057 dest = bgp_route_next(dest)) {
5058 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5059 continue;
5060
5061 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5062
5063 for (ain = dest->adj_in; ain; ain = ain->next) {
5064 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5065 nnode, peer)) {
5066 if (ain->peer != peer)
5067 continue;
5068
5069 ret = bgp_soft_reconfig_table_update(
5070 peer, dest, ain, table->afi,
5071 table->safi, prd);
5072 iter++;
5073
5074 if (ret < 0) {
5075 bgp_dest_unlock_node(dest);
5076 listnode_delete(
5077 table->soft_reconfig_peers,
5078 peer);
5079 bgp_announce_route(peer, table->afi,
e1a32ec1 5080 table->safi, false);
46aeabed
LS
5081 if (list_isempty(
5082 table->soft_reconfig_peers)) {
5083 list_delete(
5084 &table->soft_reconfig_peers);
5085 bgp_soft_reconfig_table_flag(
5086 table, false);
cc9f21da 5087 return;
46aeabed
LS
5088 }
5089 }
5090 }
5091 }
5092 }
5093
5094 /* we're either starting the initial iteration,
5095 * or we're going to continue an ongoing iteration
5096 */
5097 if (dest || table->soft_reconfig_init) {
5098 table->soft_reconfig_init = false;
5099 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5100 table, 0, &table->soft_reconfig_thread);
cc9f21da 5101 return;
46aeabed
LS
5102 }
5103 /* we're done, clean up the background iteration context info and
5104 schedule route annoucement
5105 */
5106 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5107 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5108 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5109 }
5110
5111 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5112}
5113
5114
5115/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5116 * and peer.
5117 * - bgp cannot be NULL
5118 * - if table and peer are NULL, cancel all threads within the bgp instance
5119 * - if table is NULL and peer is not,
5120 * remove peer in all threads within the bgp instance
5121 * - if peer is NULL, cancel all threads matching table within the bgp instance
5122 */
5123void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5124 const struct bgp_table *table,
5125 const struct peer *peer)
5126{
5127 struct peer *npeer;
5128 struct listnode *node, *nnode;
5129 int afi, safi;
5130 struct bgp_table *ntable;
5131
5132 if (!bgp)
5133 return;
5134
5135 FOREACH_AFI_SAFI (afi, safi) {
5136 ntable = bgp->rib[afi][safi];
5137 if (!ntable)
5138 continue;
5139 if (table && table != ntable)
5140 continue;
5141
5142 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5143 npeer)) {
5144 if (peer && peer != npeer)
5145 continue;
5146 listnode_delete(ntable->soft_reconfig_peers, npeer);
5147 }
5148
5149 if (!ntable->soft_reconfig_peers
5150 || !list_isempty(ntable->soft_reconfig_peers))
5151 continue;
5152
5153 list_delete(&ntable->soft_reconfig_peers);
5154 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5155 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5156 }
5157}
5158
d62a17ae 5159void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5160{
9bcb3eef 5161 struct bgp_dest *dest;
d62a17ae 5162 struct bgp_table *table;
46aeabed
LS
5163 struct listnode *node, *nnode;
5164 struct peer *npeer;
5165 struct peer_af *paf;
718e3744 5166
feb17238 5167 if (!peer_established(peer))
d62a17ae 5168 return;
718e3744 5169
d62a17ae 5170 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5171 && (safi != SAFI_EVPN)) {
5172 table = peer->bgp->rib[afi][safi];
5173 if (!table)
5174 return;
5175
5176 table->soft_reconfig_init = true;
5177
5178 if (!table->soft_reconfig_peers)
5179 table->soft_reconfig_peers = list_new();
5180 npeer = NULL;
5181 /* add peer to the table soft_reconfig_peers if not already
5182 * there
5183 */
5184 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5185 npeer)) {
5186 if (peer == npeer)
5187 break;
5188 }
5189 if (peer != npeer)
5190 listnode_add(table->soft_reconfig_peers, peer);
5191
5192 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5193 * on table would start back at the beginning.
5194 */
5195 bgp_soft_reconfig_table_flag(table, true);
5196
5197 if (!table->soft_reconfig_thread)
5198 thread_add_event(bm->master,
5199 bgp_soft_reconfig_table_task, table, 0,
5200 &table->soft_reconfig_thread);
5201 /* Cancel bgp_announce_route_timer_expired threads.
5202 * bgp_announce_route_timer_expired threads have been scheduled
5203 * to announce routes as soon as the soft_reconfigure process
5204 * finishes.
5205 * In this case, soft_reconfigure is also scheduled by using
5206 * a thread but is planned after the
5207 * bgp_announce_route_timer_expired threads. It means that,
5208 * without cancelling the threads, the route announcement task
5209 * would run before the soft reconfiguration one. That would
5210 * useless and would block vtysh during several seconds. Route
5211 * announcements are rescheduled as soon as the soft_reconfigure
5212 * process finishes.
5213 */
5214 paf = peer_af_find(peer, afi, safi);
5215 if (paf)
5216 bgp_stop_announce_route_timer(paf);
5217 } else
9bcb3eef
DS
5218 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5219 dest = bgp_route_next(dest)) {
5220 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5221
b54892e0
DS
5222 if (table == NULL)
5223 continue;
8692c506 5224
9bcb3eef 5225 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5226 struct prefix_rd prd;
5227
5228 prd.family = AF_UNSPEC;
5229 prd.prefixlen = 64;
5230 memcpy(&prd.val, p->u.val, 8);
5231
5232 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5233 }
718e3744 5234}
6b0655a2 5235
228da428 5236
d62a17ae 5237struct bgp_clear_node_queue {
9bcb3eef 5238 struct bgp_dest *dest;
228da428
CC
5239};
5240
d62a17ae 5241static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5242{
d62a17ae 5243 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5244 struct bgp_dest *dest = cnq->dest;
d62a17ae 5245 struct peer *peer = wq->spec.data;
40381db7 5246 struct bgp_path_info *pi;
3103e8d2 5247 struct bgp *bgp;
9bcb3eef
DS
5248 afi_t afi = bgp_dest_table(dest)->afi;
5249 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5250
9bcb3eef 5251 assert(dest && peer);
3103e8d2 5252 bgp = peer->bgp;
d62a17ae 5253
5254 /* It is possible that we have multiple paths for a prefix from a peer
5255 * if that peer is using AddPath.
5256 */
9bcb3eef 5257 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5258 if (pi->peer != peer)
ea47320b
DL
5259 continue;
5260
5261 /* graceful restart STALE flag set. */
9af52ccf
DA
5262 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5263 && peer->nsf[afi][safi])
5264 || CHECK_FLAG(peer->af_sflags[afi][safi],
5265 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5266 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5267 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5268 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5269 else {
5270 /* If this is an EVPN route, process for
5271 * un-import. */
5272 if (safi == SAFI_EVPN)
9bcb3eef
DS
5273 bgp_evpn_unimport_route(
5274 bgp, afi, safi,
5275 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5276 /* Handle withdraw for VRF route-leaking and L3VPN */
5277 if (SAFI_UNICAST == safi
5278 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5279 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5280 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5281 bgp, pi);
960035b2 5282 }
3103e8d2 5283 if (SAFI_MPLS_VPN == safi &&
960035b2 5284 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5285 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5286 }
3103e8d2 5287
9bcb3eef 5288 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5289 }
ea47320b 5290 }
d62a17ae 5291 return WQ_SUCCESS;
200df115 5292}
5293
d62a17ae 5294static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5295{
d62a17ae 5296 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5297 struct bgp_dest *dest = cnq->dest;
5298 struct bgp_table *table = bgp_dest_table(dest);
228da428 5299
9bcb3eef 5300 bgp_dest_unlock_node(dest);
d62a17ae 5301 bgp_table_unlock(table);
5302 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5303}
5304
d62a17ae 5305static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5306{
d62a17ae 5307 struct peer *peer = wq->spec.data;
64e580a7 5308
d62a17ae 5309 /* Tickle FSM to start moving again */
5310 BGP_EVENT_ADD(peer, Clearing_Completed);
5311
5312 peer_unlock(peer); /* bgp_clear_route */
200df115 5313}
718e3744 5314
d62a17ae 5315static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5316{
d62a17ae 5317 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5318
5319 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5320#undef CLEAR_QUEUE_NAME_LEN
5321
0ce1ca80 5322 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5323 peer->clear_node_queue->spec.hold = 10;
5324 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5325 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5326 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5327 peer->clear_node_queue->spec.max_retries = 0;
5328
5329 /* we only 'lock' this peer reference when the queue is actually active
5330 */
5331 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5332}
5333
d62a17ae 5334static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5335 struct bgp_table *table)
65ca75e0 5336{
9bcb3eef 5337 struct bgp_dest *dest;
b6c386bb 5338 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5339
d62a17ae 5340 if (!table)
5341 table = peer->bgp->rib[afi][safi];
dc83d712 5342
d62a17ae 5343 /* If still no table => afi/safi isn't configured at all or smth. */
5344 if (!table)
5345 return;
dc83d712 5346
9bcb3eef 5347 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5348 struct bgp_path_info *pi, *next;
d62a17ae 5349 struct bgp_adj_in *ain;
5350 struct bgp_adj_in *ain_next;
5351
5352 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5353 * queued for every clearing peer, regardless of whether it is
5354 * relevant to the peer at hand.
5355 *
5356 * Overview: There are 3 different indices which need to be
5357 * scrubbed, potentially, when a peer is removed:
5358 *
5359 * 1 peer's routes visible via the RIB (ie accepted routes)
5360 * 2 peer's routes visible by the (optional) peer's adj-in index
5361 * 3 other routes visible by the peer's adj-out index
5362 *
5363 * 3 there is no hurry in scrubbing, once the struct peer is
5364 * removed from bgp->peer, we could just GC such deleted peer's
5365 * adj-outs at our leisure.
5366 *
5367 * 1 and 2 must be 'scrubbed' in some way, at least made
5368 * invisible via RIB index before peer session is allowed to be
5369 * brought back up. So one needs to know when such a 'search' is
5370 * complete.
5371 *
5372 * Ideally:
5373 *
5374 * - there'd be a single global queue or a single RIB walker
5375 * - rather than tracking which route_nodes still need to be
5376 * examined on a peer basis, we'd track which peers still
5377 * aren't cleared
5378 *
5379 * Given that our per-peer prefix-counts now should be reliable,
5380 * this may actually be achievable. It doesn't seem to be a huge
5381 * problem at this time,
5382 *
5383 * It is possible that we have multiple paths for a prefix from
5384 * a peer
5385 * if that peer is using AddPath.
5386 */
9bcb3eef 5387 ain = dest->adj_in;
d62a17ae 5388 while (ain) {
5389 ain_next = ain->next;
5390
6a840fd9 5391 if (ain->peer == peer)
9bcb3eef 5392 bgp_adj_in_remove(dest, ain);
d62a17ae 5393
5394 ain = ain_next;
5395 }
5396
9bcb3eef 5397 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5398 next = pi->next;
5399 if (pi->peer != peer)
d62a17ae 5400 continue;
5401
5402 if (force)
9bcb3eef 5403 bgp_path_info_reap(dest, pi);
d62a17ae 5404 else {
5405 struct bgp_clear_node_queue *cnq;
5406
5407 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5408 bgp_table_lock(bgp_dest_table(dest));
5409 bgp_dest_lock_node(dest);
d62a17ae 5410 cnq = XCALLOC(
5411 MTYPE_BGP_CLEAR_NODE_QUEUE,
5412 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5413 cnq->dest = dest;
d62a17ae 5414 work_queue_add(peer->clear_node_queue, cnq);
5415 break;
5416 }
5417 }
5418 }
5419 return;
5420}
5421
5422void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5423{
9bcb3eef 5424 struct bgp_dest *dest;
d62a17ae 5425 struct bgp_table *table;
5426
5427 if (peer->clear_node_queue == NULL)
5428 bgp_clear_node_queue_init(peer);
5429
5430 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5431 * Idle until it receives a Clearing_Completed event. This protects
5432 * against peers which flap faster than we can we clear, which could
5433 * lead to:
5434 *
5435 * a) race with routes from the new session being installed before
5436 * clear_route_node visits the node (to delete the route of that
5437 * peer)
5438 * b) resource exhaustion, clear_route_node likely leads to an entry
5439 * on the process_main queue. Fast-flapping could cause that queue
5440 * to grow and grow.
5441 */
5442
5443 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5444 * the unlock will happen upon work-queue completion; other wise, the
5445 * unlock happens at the end of this function.
5446 */
5447 if (!peer->clear_node_queue->thread)
5448 peer_lock(peer);
5449
5450 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5451 bgp_clear_route_table(peer, afi, safi, NULL);
5452 else
9bcb3eef
DS
5453 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5454 dest = bgp_route_next(dest)) {
5455 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5456 if (!table)
5457 continue;
5458
5459 bgp_clear_route_table(peer, afi, safi, table);
5460 }
d62a17ae 5461
5462 /* unlock if no nodes got added to the clear-node-queue. */
5463 if (!peer->clear_node_queue->thread)
5464 peer_unlock(peer);
718e3744 5465}
d62a17ae 5466
5467void bgp_clear_route_all(struct peer *peer)
718e3744 5468{
d62a17ae 5469 afi_t afi;
5470 safi_t safi;
718e3744 5471
05c7a1cc
QY
5472 FOREACH_AFI_SAFI (afi, safi)
5473 bgp_clear_route(peer, afi, safi);
65efcfce 5474
49e5a4a0 5475#ifdef ENABLE_BGP_VNC
d62a17ae 5476 rfapiProcessPeerDown(peer);
65efcfce 5477#endif
718e3744 5478}
5479
d62a17ae 5480void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5481{
d62a17ae 5482 struct bgp_table *table;
9bcb3eef 5483 struct bgp_dest *dest;
d62a17ae 5484 struct bgp_adj_in *ain;
5485 struct bgp_adj_in *ain_next;
718e3744 5486
d62a17ae 5487 table = peer->bgp->rib[afi][safi];
718e3744 5488
d62a17ae 5489 /* It is possible that we have multiple paths for a prefix from a peer
5490 * if that peer is using AddPath.
5491 */
9bcb3eef
DS
5492 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5493 ain = dest->adj_in;
43143c8f 5494
d62a17ae 5495 while (ain) {
5496 ain_next = ain->next;
43143c8f 5497
6a840fd9 5498 if (ain->peer == peer)
9bcb3eef 5499 bgp_adj_in_remove(dest, ain);
43143c8f 5500
d62a17ae 5501 ain = ain_next;
5502 }
5503 }
718e3744 5504}
93406d87 5505
1479ed2f
DA
5506/* If any of the routes from the peer have been marked with the NO_LLGR
5507 * community, either as sent by the peer, or as the result of a configured
5508 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5509 * operation of [RFC4271].
5510 */
d62a17ae 5511void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5512{
9bcb3eef 5513 struct bgp_dest *dest;
40381db7 5514 struct bgp_path_info *pi;
d62a17ae 5515 struct bgp_table *table;
5516
9af52ccf 5517 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5518 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5519 dest = bgp_route_next(dest)) {
5520 struct bgp_dest *rm;
d62a17ae 5521
5522 /* look for neighbor in tables */
9bcb3eef 5523 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5524 if (!table)
ea47320b
DL
5525 continue;
5526
5527 for (rm = bgp_table_top(table); rm;
5528 rm = bgp_route_next(rm))
9bcb3eef 5529 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5530 pi = pi->next) {
40381db7 5531 if (pi->peer != peer)
ea47320b 5532 continue;
1479ed2f
DA
5533 if (CHECK_FLAG(
5534 peer->af_sflags[afi][safi],
5535 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5536 bgp_attr_get_community(pi->attr) &&
1479ed2f 5537 !community_include(
9a706b42
DA
5538 bgp_attr_get_community(
5539 pi->attr),
1479ed2f 5540 COMMUNITY_NO_LLGR))
e3015d91 5541 continue;
40381db7 5542 if (!CHECK_FLAG(pi->flags,
1defdda8 5543 BGP_PATH_STALE))
e3015d91 5544 continue;
ea47320b 5545
641065d4
KM
5546 /*
5547 * If this is VRF leaked route
5548 * process for withdraw.
5549 */
5550 if (pi->sub_type ==
5551 BGP_ROUTE_IMPORTED &&
5552 peer->bgp->inst_type ==
5553 BGP_INSTANCE_TYPE_DEFAULT)
5554 vpn_leak_to_vrf_withdraw(
5555 peer->bgp, pi);
5556
40381db7 5557 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5558 break;
5559 }
d62a17ae 5560 }
5561 } else {
9bcb3eef
DS
5562 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5563 dest = bgp_route_next(dest))
5564 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5565 pi = pi->next) {
40381db7 5566 if (pi->peer != peer)
ea47320b 5567 continue;
1479ed2f
DA
5568 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5569 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5570 bgp_attr_get_community(pi->attr) &&
5571 !community_include(
5572 bgp_attr_get_community(pi->attr),
5573 COMMUNITY_NO_LLGR))
e3015d91 5574 continue;
40381db7 5575 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5576 continue;
641065d4
KM
5577 if (safi == SAFI_UNICAST &&
5578 (peer->bgp->inst_type ==
5579 BGP_INSTANCE_TYPE_VRF ||
5580 peer->bgp->inst_type ==
5581 BGP_INSTANCE_TYPE_DEFAULT))
5582 vpn_leak_from_vrf_withdraw(
5583 bgp_get_default(), peer->bgp,
5584 pi);
5585
9bcb3eef 5586 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5587 break;
5588 }
d62a17ae 5589 }
93406d87 5590}
6b0655a2 5591
9af52ccf
DA
5592void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5593{
5594 struct bgp_dest *dest, *ndest;
5595 struct bgp_path_info *pi;
5596 struct bgp_table *table;
5597
5598 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5599 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5600 dest = bgp_route_next(dest)) {
5601 table = bgp_dest_get_bgp_table_info(dest);
5602 if (!table)
5603 continue;
5604
5605 for (ndest = bgp_table_top(table); ndest;
5606 ndest = bgp_route_next(ndest)) {
5607 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5608 pi = pi->next) {
5609 if (pi->peer != peer)
5610 continue;
5611
5612 if ((CHECK_FLAG(
5613 peer->af_sflags[afi][safi],
5614 PEER_STATUS_ENHANCED_REFRESH))
5615 && !CHECK_FLAG(pi->flags,
5616 BGP_PATH_STALE)
5617 && !CHECK_FLAG(
5618 pi->flags,
5619 BGP_PATH_UNUSEABLE)) {
5620 if (bgp_debug_neighbor_events(
5621 peer))
5622 zlog_debug(
58e111f6
DA
5623 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5624 peer,
9af52ccf
DA
5625 afi2str(afi),
5626 safi2str(safi),
5627 bgp_dest_get_prefix(
5628 ndest));
5629
5630 bgp_path_info_set_flag(
5631 ndest, pi,
5632 BGP_PATH_STALE);
5633 }
5634 }
5635 }
5636 }
5637 } else {
5638 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5639 dest = bgp_route_next(dest)) {
5640 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5641 pi = pi->next) {
5642 if (pi->peer != peer)
5643 continue;
5644
5645 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5646 PEER_STATUS_ENHANCED_REFRESH))
5647 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5648 && !CHECK_FLAG(pi->flags,
5649 BGP_PATH_UNUSEABLE)) {
5650 if (bgp_debug_neighbor_events(peer))
5651 zlog_debug(
58e111f6
DA
5652 "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
5653 peer, afi2str(afi),
9af52ccf
DA
5654 safi2str(safi),
5655 bgp_dest_get_prefix(
5656 dest));
5657
5658 bgp_path_info_set_flag(dest, pi,
5659 BGP_PATH_STALE);
5660 }
5661 }
5662 }
5663 }
5664}
5665
3dc339cd 5666bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5667{
e0df4c04 5668 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5669 return true;
e0df4c04 5670
9dac9fc8
DA
5671 if (peer->sort == BGP_PEER_EBGP
5672 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5673 || FILTER_LIST_OUT_NAME(filter)
5674 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5675 return true;
5676 return false;
9dac9fc8
DA
5677}
5678
3dc339cd 5679bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5680{
e0df4c04 5681 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5682 return true;
e0df4c04 5683
9dac9fc8
DA
5684 if (peer->sort == BGP_PEER_EBGP
5685 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5686 || FILTER_LIST_IN_NAME(filter)
5687 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5688 return true;
5689 return false;
9dac9fc8
DA
5690}
5691
568e10ca 5692static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5693 safi_t safi)
bb86c601 5694{
9bcb3eef 5695 struct bgp_dest *dest;
40381db7 5696 struct bgp_path_info *pi;
4b7e6066 5697 struct bgp_path_info *next;
bb86c601 5698
9bcb3eef
DS
5699 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5700 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5701 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5702
40381db7 5703 next = pi->next;
1b7bb747
CS
5704
5705 /* Unimport EVPN routes from VRFs */
5706 if (safi == SAFI_EVPN)
5707 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5708 SAFI_EVPN, p, pi);
1b7bb747 5709
40381db7
DS
5710 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5711 && pi->type == ZEBRA_ROUTE_BGP
5712 && (pi->sub_type == BGP_ROUTE_NORMAL
5713 || pi->sub_type == BGP_ROUTE_AGGREGATE
5714 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5715
d62a17ae 5716 if (bgp_fibupd_safi(safi))
b54892e0 5717 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5718 }
9514b37d 5719
9bcb3eef 5720 bgp_path_info_reap(dest, pi);
d62a17ae 5721 }
bb86c601
LB
5722}
5723
718e3744 5724/* Delete all kernel routes. */
d62a17ae 5725void bgp_cleanup_routes(struct bgp *bgp)
5726{
5727 afi_t afi;
9bcb3eef 5728 struct bgp_dest *dest;
67009e22 5729 struct bgp_table *table;
d62a17ae 5730
5731 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5732 if (afi == AFI_L2VPN)
5733 continue;
568e10ca 5734 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5735 SAFI_UNICAST);
d62a17ae 5736 /*
5737 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5738 */
5739 if (afi != AFI_L2VPN) {
5740 safi_t safi;
5741 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5742 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5743 dest = bgp_route_next(dest)) {
5744 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5745 if (table != NULL) {
5746 bgp_cleanup_table(bgp, table, safi);
5747 bgp_table_finish(&table);
9bcb3eef
DS
5748 bgp_dest_set_bgp_table_info(dest, NULL);
5749 bgp_dest_unlock_node(dest);
d62a17ae 5750 }
5751 }
5752 safi = SAFI_ENCAP;
9bcb3eef
DS
5753 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5754 dest = bgp_route_next(dest)) {
5755 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5756 if (table != NULL) {
5757 bgp_cleanup_table(bgp, table, safi);
5758 bgp_table_finish(&table);
9bcb3eef
DS
5759 bgp_dest_set_bgp_table_info(dest, NULL);
5760 bgp_dest_unlock_node(dest);
d62a17ae 5761 }
5762 }
5763 }
5764 }
9bcb3eef
DS
5765 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5766 dest = bgp_route_next(dest)) {
5767 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5768 if (table != NULL) {
5769 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5770 bgp_table_finish(&table);
9bcb3eef
DS
5771 bgp_dest_set_bgp_table_info(dest, NULL);
5772 bgp_dest_unlock_node(dest);
d62a17ae 5773 }
bb86c601 5774 }
718e3744 5775}
5776
d62a17ae 5777void bgp_reset(void)
718e3744 5778{
d62a17ae 5779 vty_reset();
5780 bgp_zclient_reset();
5781 access_list_reset();
5782 prefix_list_reset();
718e3744 5783}
6b0655a2 5784
be92fc9f 5785bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5786{
d62a17ae 5787 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5788 && CHECK_FLAG(peer->af_cap[afi][safi],
5789 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5790}
5791
718e3744 5792/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5793 value. */
d62a17ae 5794int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5795 struct bgp_nlri *packet)
5796{
d7c0a89a
QY
5797 uint8_t *pnt;
5798 uint8_t *lim;
d62a17ae 5799 struct prefix p;
5800 int psize;
5801 int ret;
5802 afi_t afi;
5803 safi_t safi;
be92fc9f 5804 bool addpath_capable;
d7c0a89a 5805 uint32_t addpath_id;
d62a17ae 5806
d62a17ae 5807 pnt = packet->nlri;
5808 lim = pnt + packet->length;
5809 afi = packet->afi;
5810 safi = packet->safi;
5811 addpath_id = 0;
be92fc9f 5812 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5813
5814 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5815 syntactic validity. If the field is syntactically incorrect,
5816 then the Error Subcode is set to Invalid Network Field. */
5817 for (; pnt < lim; pnt += psize) {
5818 /* Clear prefix structure. */
6006b807 5819 memset(&p, 0, sizeof(p));
d62a17ae 5820
be92fc9f 5821 if (addpath_capable) {
d62a17ae 5822
5823 /* When packet overflow occurs return immediately. */
761ed665 5824 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5825 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5826
a3a850a1 5827 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5828 addpath_id = ntohl(addpath_id);
d62a17ae 5829 pnt += BGP_ADDPATH_ID_LEN;
5830 }
718e3744 5831
d62a17ae 5832 /* Fetch prefix length. */
5833 p.prefixlen = *pnt++;
5834 /* afi/safi validity already verified by caller,
5835 * bgp_update_receive */
5836 p.family = afi2family(afi);
5837
5838 /* Prefix length check. */
5839 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5840 flog_err(
e50f7cfd 5841 EC_BGP_UPDATE_RCV,
14454c9f 5842 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5843 peer->host, p.prefixlen, packet->afi);
513386b5 5844 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5845 }
6b0655a2 5846
d62a17ae 5847 /* Packet size overflow check. */
5848 psize = PSIZE(p.prefixlen);
5849
5850 /* When packet overflow occur return immediately. */
5851 if (pnt + psize > lim) {
af4c2728 5852 flog_err(
e50f7cfd 5853 EC_BGP_UPDATE_RCV,
d62a17ae 5854 "%s [Error] Update packet error (prefix length %d overflows packet)",
5855 peer->host, p.prefixlen);
513386b5 5856 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5857 }
5858
5859 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5860 * prefix for the v4 and v6 afi's and unicast/multicast */
5861 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5862 flog_err(
e50f7cfd 5863 EC_BGP_UPDATE_RCV,
d62a17ae 5864 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5865 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5866 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5867 }
5868
5869 /* Fetch prefix from NLRI packet. */
a85297a7 5870 memcpy(p.u.val, pnt, psize);
d62a17ae 5871
5872 /* Check address. */
5873 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5874 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5875 /* From RFC4271 Section 6.3:
5876 *
5877 * If a prefix in the NLRI field is semantically
5878 * incorrect
5879 * (e.g., an unexpected multicast IP address),
5880 * an error SHOULD
5881 * be logged locally, and the prefix SHOULD be
5882 * ignored.
a4d82a8a 5883 */
af4c2728 5884 flog_err(
e50f7cfd 5885 EC_BGP_UPDATE_RCV,
23d0a753
DA
5886 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5887 peer->host, &p.u.prefix4);
d62a17ae 5888 continue;
5889 }
5890 }
5891
5892 /* Check address. */
5893 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5894 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5895 flog_err(
e50f7cfd 5896 EC_BGP_UPDATE_RCV,
c0d72166
DS
5897 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5898 peer->host, &p.u.prefix6);
d62a17ae 5899
5900 continue;
5901 }
5902 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5903 flog_err(
e50f7cfd 5904 EC_BGP_UPDATE_RCV,
c0d72166
DS
5905 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5906 peer->host, &p.u.prefix6);
d62a17ae 5907
5908 continue;
5909 }
5910 }
5911
5912 /* Normal process. */
5913 if (attr)
5914 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5915 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5916 NULL, NULL, 0, 0, NULL);
d62a17ae 5917 else
5918 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5919 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5920 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5921 NULL);
d62a17ae 5922
513386b5
DA
5923 /* Do not send BGP notification twice when maximum-prefix count
5924 * overflow. */
5925 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5926 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5927
5928 /* Address family configuration mismatch. */
d62a17ae 5929 if (ret < 0)
513386b5 5930 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5931 }
5932
5933 /* Packet length consistency check. */
5934 if (pnt != lim) {
af4c2728 5935 flog_err(
e50f7cfd 5936 EC_BGP_UPDATE_RCV,
d62a17ae 5937 "%s [Error] Update packet error (prefix length mismatch with total length)",
5938 peer->host);
513386b5 5939 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5940 }
6b0655a2 5941
513386b5 5942 return BGP_NLRI_PARSE_OK;
718e3744 5943}
5944
d62a17ae 5945static struct bgp_static *bgp_static_new(void)
718e3744 5946{
d62a17ae 5947 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5948}
5949
d62a17ae 5950static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5951{
0a22ddfb 5952 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5953 route_map_counter_decrement(bgp_static->rmap.map);
5954
0a22ddfb 5955 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5956 XFREE(MTYPE_BGP_STATIC, bgp_static);
5957}
5958
5f040085 5959void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5960 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5961{
9bcb3eef 5962 struct bgp_dest *dest;
40381db7 5963 struct bgp_path_info *pi;
4b7e6066 5964 struct bgp_path_info *new;
40381db7 5965 struct bgp_path_info rmap_path;
d62a17ae 5966 struct attr attr;
5967 struct attr *attr_new;
b68885f9 5968 route_map_result_t ret;
49e5a4a0 5969#ifdef ENABLE_BGP_VNC
d62a17ae 5970 int vnc_implicit_withdraw = 0;
65efcfce 5971#endif
fee0f4c6 5972
d62a17ae 5973 assert(bgp_static);
dd8103a9 5974
9bcb3eef 5975 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5976
0f05ea43 5977 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5978
d62a17ae 5979 attr.nexthop = bgp_static->igpnexthop;
5980 attr.med = bgp_static->igpmetric;
5981 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5982
7226bc40
TA
5983 if (afi == AFI_IP)
5984 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5985
d62a17ae 5986 if (bgp_static->atomic)
5987 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5988
d62a17ae 5989 /* Store label index, if required. */
5990 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5991 attr.label_index = bgp_static->label_index;
5992 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5993 }
718e3744 5994
d62a17ae 5995 /* Apply route-map. */
5996 if (bgp_static->rmap.name) {
5997 struct attr attr_tmp = attr;
80ced710 5998
6006b807 5999 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
6000 rmap_path.peer = bgp->peer_self;
6001 rmap_path.attr = &attr_tmp;
fee0f4c6 6002
d62a17ae 6003 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 6004
1782514f 6005 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 6006
d62a17ae 6007 bgp->peer_self->rmap_type = 0;
718e3744 6008
d62a17ae 6009 if (ret == RMAP_DENYMATCH) {
6010 /* Free uninterned attribute. */
6011 bgp_attr_flush(&attr_tmp);
718e3744 6012
d62a17ae 6013 /* Unintern original. */
6014 aspath_unintern(&attr.aspath);
6015 bgp_static_withdraw(bgp, p, afi, safi);
bbc52106 6016 bgp_dest_unlock_node(dest);
d62a17ae 6017 return;
6018 }
7f323236 6019
637e5ba4 6020 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6021 bgp_attr_add_gshut_community(&attr_tmp);
6022
d62a17ae 6023 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
6024 } else {
6025
637e5ba4 6026 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6027 bgp_attr_add_gshut_community(&attr);
6028
d62a17ae 6029 attr_new = bgp_attr_intern(&attr);
7f323236 6030 }
718e3744 6031
9bcb3eef 6032 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6033 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6034 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6035 break;
6036
40381db7
DS
6037 if (pi) {
6038 if (attrhash_cmp(pi->attr, attr_new)
6039 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6040 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6041 bgp_dest_unlock_node(dest);
d62a17ae 6042 bgp_attr_unintern(&attr_new);
6043 aspath_unintern(&attr.aspath);
6044 return;
6045 } else {
6046 /* The attribute is changed. */
9bcb3eef 6047 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6048
6049 /* Rewrite BGP route information. */
40381db7 6050 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6051 bgp_path_info_restore(dest, pi);
d62a17ae 6052 else
40381db7 6053 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6054#ifdef ENABLE_BGP_VNC
d62a17ae 6055 if ((afi == AFI_IP || afi == AFI_IP6)
6056 && (safi == SAFI_UNICAST)) {
40381db7 6057 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6058 /*
6059 * Implicit withdraw case.
40381db7 6060 * We have to do this before pi is
d62a17ae 6061 * changed
6062 */
6063 ++vnc_implicit_withdraw;
40381db7 6064 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6065 vnc_import_bgp_exterior_del_route(
40381db7 6066 bgp, p, pi);
d62a17ae 6067 }
6068 }
65efcfce 6069#endif
40381db7
DS
6070 bgp_attr_unintern(&pi->attr);
6071 pi->attr = attr_new;
083ec940 6072 pi->uptime = monotime(NULL);
49e5a4a0 6073#ifdef ENABLE_BGP_VNC
d62a17ae 6074 if ((afi == AFI_IP || afi == AFI_IP6)
6075 && (safi == SAFI_UNICAST)) {
6076 if (vnc_implicit_withdraw) {
40381db7 6077 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6078 vnc_import_bgp_exterior_add_route(
40381db7 6079 bgp, p, pi);
d62a17ae 6080 }
6081 }
65efcfce 6082#endif
718e3744 6083
d62a17ae 6084 /* Nexthop reachability check. */
892fedb6 6085 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6086 && (safi == SAFI_UNICAST
6087 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6088
6089 struct bgp *bgp_nexthop = bgp;
6090
40381db7
DS
6091 if (pi->extra && pi->extra->bgp_orig)
6092 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6093
6094 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6095 afi, safi, pi, NULL,
654a5978 6096 0, p))
9bcb3eef 6097 bgp_path_info_set_flag(dest, pi,
18ee8310 6098 BGP_PATH_VALID);
d62a17ae 6099 else {
6100 if (BGP_DEBUG(nht, NHT)) {
6101 char buf1[INET6_ADDRSTRLEN];
6102 inet_ntop(p->family,
6103 &p->u.prefix, buf1,
6104 INET6_ADDRSTRLEN);
6105 zlog_debug(
6106 "%s(%s): Route not in table, not advertising",
15569c58 6107 __func__, buf1);
d62a17ae 6108 }
18ee8310 6109 bgp_path_info_unset_flag(
9bcb3eef 6110 dest, pi, BGP_PATH_VALID);
d62a17ae 6111 }
6112 } else {
6113 /* Delete the NHT structure if any, if we're
6114 * toggling between
6115 * enabling/disabling import check. We
6116 * deregister the route
6117 * from NHT to avoid overloading NHT and the
6118 * process interaction
6119 */
40381db7 6120 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6121 bgp_path_info_set_flag(dest, pi,
6122 BGP_PATH_VALID);
d62a17ae 6123 }
6124 /* Process change. */
40381db7 6125 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6126 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6127
6128 if (SAFI_UNICAST == safi
6129 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6130 || bgp->inst_type
6131 == BGP_INSTANCE_TYPE_DEFAULT)) {
6132 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6133 pi);
ddb5b488
PZ
6134 }
6135
9bcb3eef 6136 bgp_dest_unlock_node(dest);
d62a17ae 6137 aspath_unintern(&attr.aspath);
6138 return;
6139 }
718e3744 6140 }
718e3744 6141
d62a17ae 6142 /* Make new BGP info. */
6143 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6144 attr_new, dest);
d62a17ae 6145 /* Nexthop reachability check. */
892fedb6 6146 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6147 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6148 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6149 p))
9bcb3eef 6150 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6151 else {
6152 if (BGP_DEBUG(nht, NHT)) {
6153 char buf1[INET6_ADDRSTRLEN];
6154 inet_ntop(p->family, &p->u.prefix, buf1,
6155 INET6_ADDRSTRLEN);
6156 zlog_debug(
6157 "%s(%s): Route not in table, not advertising",
15569c58 6158 __func__, buf1);
d62a17ae 6159 }
9bcb3eef 6160 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6161 }
6162 } else {
6163 /* Delete the NHT structure if any, if we're toggling between
6164 * enabling/disabling import check. We deregister the route
6165 * from NHT to avoid overloading NHT and the process interaction
6166 */
6167 bgp_unlink_nexthop(new);
6168
9bcb3eef 6169 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6170 }
078430f6 6171
d62a17ae 6172 /* Aggregate address increment. */
6173 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6174
d62a17ae 6175 /* Register new BGP information. */
9bcb3eef 6176 bgp_path_info_add(dest, new);
718e3744 6177
d62a17ae 6178 /* route_node_get lock */
9bcb3eef 6179 bgp_dest_unlock_node(dest);
d62a17ae 6180
6181 /* Process change. */
9bcb3eef 6182 bgp_process(bgp, dest, afi, safi);
d62a17ae 6183
ddb5b488
PZ
6184 if (SAFI_UNICAST == safi
6185 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6186 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6187 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6188 }
6189
d62a17ae 6190 /* Unintern original. */
6191 aspath_unintern(&attr.aspath);
718e3744 6192}
6193
5f040085 6194void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6195 safi_t safi)
718e3744 6196{
9bcb3eef 6197 struct bgp_dest *dest;
40381db7 6198 struct bgp_path_info *pi;
718e3744 6199
9bcb3eef 6200 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6201
d62a17ae 6202 /* Check selected route and self inserted route. */
9bcb3eef 6203 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6204 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6205 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6206 break;
6207
6208 /* Withdraw static BGP route from routing table. */
40381db7 6209 if (pi) {
ddb5b488
PZ
6210 if (SAFI_UNICAST == safi
6211 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6212 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6213 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6214 }
40381db7
DS
6215 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6216 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6217 bgp_path_info_delete(dest, pi);
6218 bgp_process(bgp, dest, afi, safi);
d62a17ae 6219 }
718e3744 6220
d62a17ae 6221 /* Unlock bgp_node_lookup. */
9bcb3eef 6222 bgp_dest_unlock_node(dest);
718e3744 6223}
6224
137446f9
LB
6225/*
6226 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6227 */
5f040085 6228static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6229 afi_t afi, safi_t safi,
6230 struct prefix_rd *prd)
718e3744 6231{
9bcb3eef 6232 struct bgp_dest *dest;
40381db7 6233 struct bgp_path_info *pi;
718e3744 6234
9bcb3eef 6235 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6236
d62a17ae 6237 /* Check selected route and self inserted route. */
9bcb3eef 6238 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6239 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6240 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6241 break;
718e3744 6242
d62a17ae 6243 /* Withdraw static BGP route from routing table. */
40381db7 6244 if (pi) {
49e5a4a0 6245#ifdef ENABLE_BGP_VNC
d62a17ae 6246 rfapiProcessWithdraw(
40381db7 6247 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6248 1); /* Kill, since it is an administrative change */
65efcfce 6249#endif
ddb5b488
PZ
6250 if (SAFI_MPLS_VPN == safi
6251 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6252 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6253 }
40381db7 6254 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6255 bgp_path_info_delete(dest, pi);
6256 bgp_process(bgp, dest, afi, safi);
d62a17ae 6257 }
718e3744 6258
d62a17ae 6259 /* Unlock bgp_node_lookup. */
9bcb3eef 6260 bgp_dest_unlock_node(dest);
718e3744 6261}
6262
5f040085 6263static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6264 struct bgp_static *bgp_static, afi_t afi,
6265 safi_t safi)
137446f9 6266{
9bcb3eef 6267 struct bgp_dest *dest;
4b7e6066 6268 struct bgp_path_info *new;
d62a17ae 6269 struct attr *attr_new;
6270 struct attr attr = {0};
40381db7 6271 struct bgp_path_info *pi;
49e5a4a0 6272#ifdef ENABLE_BGP_VNC
d62a17ae 6273 mpls_label_t label = 0;
65efcfce 6274#endif
d7c0a89a 6275 uint32_t num_labels = 0;
137446f9 6276
d62a17ae 6277 assert(bgp_static);
137446f9 6278
b57ba6d2
MK
6279 if (bgp_static->label != MPLS_INVALID_LABEL)
6280 num_labels = 1;
9bcb3eef
DS
6281 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6282 &bgp_static->prd);
137446f9 6283
0f05ea43 6284 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6285
d62a17ae 6286 attr.nexthop = bgp_static->igpnexthop;
6287 attr.med = bgp_static->igpmetric;
6288 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6289
d62a17ae 6290 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6291 || (safi == SAFI_ENCAP)) {
6292 if (afi == AFI_IP) {
6293 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6294 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6295 }
6296 }
6297 if (afi == AFI_L2VPN) {
b04c1e99
IR
6298 if (bgp_static->gatewayIp.family == AF_INET) {
6299 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6300 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6301 &bgp_static->gatewayIp.u.prefix4,
6302 IPV4_MAX_BYTELEN);
b04c1e99
IR
6303 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6304 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6305 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6306 &bgp_static->gatewayIp.u.prefix6,
6307 IPV6_MAX_BYTELEN);
b04c1e99 6308 }
0a50c248 6309 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6310 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6311 struct bgp_encap_type_vxlan bet;
6006b807 6312 memset(&bet, 0, sizeof(bet));
3714a385 6313 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6314 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6315 }
6316 if (bgp_static->router_mac) {
6317 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6318 }
6319 }
6320 /* Apply route-map. */
6321 if (bgp_static->rmap.name) {
6322 struct attr attr_tmp = attr;
40381db7 6323 struct bgp_path_info rmap_path;
b68885f9 6324 route_map_result_t ret;
137446f9 6325
40381db7
DS
6326 rmap_path.peer = bgp->peer_self;
6327 rmap_path.attr = &attr_tmp;
137446f9 6328
d62a17ae 6329 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6330
1782514f 6331 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6332
d62a17ae 6333 bgp->peer_self->rmap_type = 0;
137446f9 6334
d62a17ae 6335 if (ret == RMAP_DENYMATCH) {
6336 /* Free uninterned attribute. */
6337 bgp_attr_flush(&attr_tmp);
137446f9 6338
d62a17ae 6339 /* Unintern original. */
6340 aspath_unintern(&attr.aspath);
6341 bgp_static_withdraw_safi(bgp, p, afi, safi,
6342 &bgp_static->prd);
bbc52106 6343 bgp_dest_unlock_node(dest);
d62a17ae 6344 return;
6345 }
137446f9 6346
d62a17ae 6347 attr_new = bgp_attr_intern(&attr_tmp);
6348 } else {
6349 attr_new = bgp_attr_intern(&attr);
6350 }
137446f9 6351
9bcb3eef 6352 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6353 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6354 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6355 break;
6356
40381db7 6357 if (pi) {
40381db7 6358 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6359 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6360 bgp_dest_unlock_node(dest);
d62a17ae 6361 bgp_attr_unintern(&attr_new);
6362 aspath_unintern(&attr.aspath);
6363 return;
6364 } else {
6365 /* The attribute is changed. */
9bcb3eef 6366 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6367
6368 /* Rewrite BGP route information. */
40381db7 6369 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6370 bgp_path_info_restore(dest, pi);
d62a17ae 6371 else
40381db7
DS
6372 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6373 bgp_attr_unintern(&pi->attr);
6374 pi->attr = attr_new;
083ec940 6375 pi->uptime = monotime(NULL);
49e5a4a0 6376#ifdef ENABLE_BGP_VNC
40381db7
DS
6377 if (pi->extra)
6378 label = decode_label(&pi->extra->label[0]);
65efcfce 6379#endif
137446f9 6380
d62a17ae 6381 /* Process change. */
40381db7 6382 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6383 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6384
6385 if (SAFI_MPLS_VPN == safi
6386 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6387 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6388 }
49e5a4a0 6389#ifdef ENABLE_BGP_VNC
40381db7
DS
6390 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6391 pi->attr, afi, safi, pi->type,
6392 pi->sub_type, &label);
65efcfce 6393#endif
9bcb3eef 6394 bgp_dest_unlock_node(dest);
d62a17ae 6395 aspath_unintern(&attr.aspath);
6396 return;
6397 }
6398 }
137446f9
LB
6399
6400
d62a17ae 6401 /* Make new BGP info. */
6402 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6403 attr_new, dest);
1defdda8 6404 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6405 bgp_path_info_extra_get(new);
b57ba6d2
MK
6406 if (num_labels) {
6407 new->extra->label[0] = bgp_static->label;
6408 new->extra->num_labels = num_labels;
6409 }
49e5a4a0 6410#ifdef ENABLE_BGP_VNC
d62a17ae 6411 label = decode_label(&bgp_static->label);
65efcfce 6412#endif
137446f9 6413
d62a17ae 6414 /* Aggregate address increment. */
6415 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6416
d62a17ae 6417 /* Register new BGP information. */
9bcb3eef 6418 bgp_path_info_add(dest, new);
d62a17ae 6419 /* route_node_get lock */
9bcb3eef 6420 bgp_dest_unlock_node(dest);
137446f9 6421
d62a17ae 6422 /* Process change. */
9bcb3eef 6423 bgp_process(bgp, dest, afi, safi);
137446f9 6424
ddb5b488
PZ
6425 if (SAFI_MPLS_VPN == safi
6426 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6427 vpn_leak_to_vrf_update(bgp, new);
6428 }
49e5a4a0 6429#ifdef ENABLE_BGP_VNC
d62a17ae 6430 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6431 safi, new->type, new->sub_type, &label);
65efcfce
LB
6432#endif
6433
d62a17ae 6434 /* Unintern original. */
6435 aspath_unintern(&attr.aspath);
137446f9
LB
6436}
6437
718e3744 6438/* Configure static BGP network. When user don't run zebra, static
6439 route should be installed as valid. */
585f1adc
IR
6440static int bgp_static_set(struct vty *vty, const char *negate,
6441 const char *ip_str, afi_t afi, safi_t safi,
6442 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6443{
585f1adc
IR
6444 VTY_DECLVAR_CONTEXT(bgp, bgp);
6445 int ret;
d62a17ae 6446 struct prefix p;
6447 struct bgp_static *bgp_static;
9bcb3eef 6448 struct bgp_dest *dest;
d7c0a89a 6449 uint8_t need_update = 0;
d62a17ae 6450
585f1adc
IR
6451 /* Convert IP prefix string to struct prefix. */
6452 ret = str2prefix(ip_str, &p);
6453 if (!ret) {
6454 vty_out(vty, "%% Malformed prefix\n");
6455 return CMD_WARNING_CONFIG_FAILED;
6456 }
6457 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6458 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6459 return CMD_WARNING_CONFIG_FAILED;
6460 }
6461
d62a17ae 6462 apply_mask(&p);
718e3744 6463
e2a86ad9 6464 if (negate) {
718e3744 6465
e2a86ad9 6466 /* Set BGP static route configuration. */
9bcb3eef 6467 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6468
9bcb3eef 6469 if (!dest) {
585f1adc
IR
6470 vty_out(vty, "%% Can't find static route specified\n");
6471 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6472 }
6473
9bcb3eef 6474 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6475
e2a86ad9
DS
6476 if ((label_index != BGP_INVALID_LABEL_INDEX)
6477 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6478 vty_out(vty,
6479 "%% label-index doesn't match static route\n");
70d9b134 6480 bgp_dest_unlock_node(dest);
585f1adc 6481 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6482 }
d62a17ae 6483
e2a86ad9
DS
6484 if ((rmap && bgp_static->rmap.name)
6485 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6486 vty_out(vty,
6487 "%% route-map name doesn't match static route\n");
70d9b134 6488 bgp_dest_unlock_node(dest);
585f1adc 6489 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6490 }
718e3744 6491
e2a86ad9
DS
6492 /* Update BGP RIB. */
6493 if (!bgp_static->backdoor)
6494 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6495
e2a86ad9
DS
6496 /* Clear configuration. */
6497 bgp_static_free(bgp_static);
9bcb3eef
DS
6498 bgp_dest_set_bgp_static_info(dest, NULL);
6499 bgp_dest_unlock_node(dest);
6500 bgp_dest_unlock_node(dest);
e2a86ad9 6501 } else {
718e3744 6502
e2a86ad9 6503 /* Set BGP static route configuration. */
9bcb3eef
DS
6504 dest = bgp_node_get(bgp->route[afi][safi], &p);
6505 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6506 if (bgp_static) {
e2a86ad9 6507 /* Configuration change. */
e2a86ad9
DS
6508 /* Label index cannot be changed. */
6509 if (bgp_static->label_index != label_index) {
585f1adc 6510 vty_out(vty, "%% cannot change label-index\n");
8c0044f3 6511 bgp_dest_unlock_node(dest);
585f1adc 6512 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6513 }
d62a17ae 6514
e2a86ad9 6515 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6516 if (bgp_static->valid
6517 && bgp_static->backdoor != backdoor)
e2a86ad9 6518 need_update = 1;
718e3744 6519
e2a86ad9 6520 bgp_static->backdoor = backdoor;
718e3744 6521
e2a86ad9 6522 if (rmap) {
0a22ddfb
QY
6523 XFREE(MTYPE_ROUTE_MAP_NAME,
6524 bgp_static->rmap.name);
b4897fa5 6525 route_map_counter_decrement(
6526 bgp_static->rmap.map);
e2a86ad9
DS
6527 bgp_static->rmap.name =
6528 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6529 bgp_static->rmap.map =
6530 route_map_lookup_by_name(rmap);
b4897fa5 6531 route_map_counter_increment(
6532 bgp_static->rmap.map);
e2a86ad9 6533 } else {
0a22ddfb
QY
6534 XFREE(MTYPE_ROUTE_MAP_NAME,
6535 bgp_static->rmap.name);
b4897fa5 6536 route_map_counter_decrement(
6537 bgp_static->rmap.map);
e2a86ad9
DS
6538 bgp_static->rmap.map = NULL;
6539 bgp_static->valid = 0;
6540 }
9bcb3eef 6541 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6542 } else {
6543 /* New configuration. */
6544 bgp_static = bgp_static_new();
6545 bgp_static->backdoor = backdoor;
6546 bgp_static->valid = 0;
6547 bgp_static->igpmetric = 0;
975a328e 6548 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6549 bgp_static->label_index = label_index;
718e3744 6550
e2a86ad9 6551 if (rmap) {
0a22ddfb
QY
6552 XFREE(MTYPE_ROUTE_MAP_NAME,
6553 bgp_static->rmap.name);
b4897fa5 6554 route_map_counter_decrement(
6555 bgp_static->rmap.map);
e2a86ad9
DS
6556 bgp_static->rmap.name =
6557 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6558 bgp_static->rmap.map =
6559 route_map_lookup_by_name(rmap);
b4897fa5 6560 route_map_counter_increment(
6561 bgp_static->rmap.map);
e2a86ad9 6562 }
9bcb3eef 6563 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6564 }
d62a17ae 6565
e2a86ad9
DS
6566 bgp_static->valid = 1;
6567 if (need_update)
6568 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6569
e2a86ad9
DS
6570 if (!bgp_static->backdoor)
6571 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6572 }
d62a17ae 6573
585f1adc 6574 return CMD_SUCCESS;
d62a17ae 6575}
6576
6577void bgp_static_add(struct bgp *bgp)
6578{
6579 afi_t afi;
6580 safi_t safi;
9bcb3eef
DS
6581 struct bgp_dest *dest;
6582 struct bgp_dest *rm;
d62a17ae 6583 struct bgp_table *table;
6584 struct bgp_static *bgp_static;
6585
47fc6261 6586 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6587 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6588 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6589 dest = bgp_route_next(dest)) {
6590 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6591 continue;
ea47320b 6592
05c7a1cc
QY
6593 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6594 || (safi == SAFI_EVPN)) {
9bcb3eef 6595 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6596
6597 for (rm = bgp_table_top(table); rm;
6598 rm = bgp_route_next(rm)) {
a78beeb5 6599 bgp_static =
9bcb3eef 6600 bgp_dest_get_bgp_static_info(
5a8ba9fc 6601 rm);
9bcb3eef
DS
6602 bgp_static_update_safi(
6603 bgp, bgp_dest_get_prefix(rm),
6604 bgp_static, afi, safi);
d62a17ae 6605 }
05c7a1cc 6606 } else {
5a8ba9fc 6607 bgp_static_update(
9bcb3eef
DS
6608 bgp, bgp_dest_get_prefix(dest),
6609 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6610 safi);
ea47320b 6611 }
05c7a1cc 6612 }
47fc6261 6613 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6614}
6615
718e3744 6616/* Called from bgp_delete(). Delete all static routes from the BGP
6617 instance. */
d62a17ae 6618void bgp_static_delete(struct bgp *bgp)
6619{
6620 afi_t afi;
6621 safi_t safi;
9bcb3eef
DS
6622 struct bgp_dest *dest;
6623 struct bgp_dest *rm;
d62a17ae 6624 struct bgp_table *table;
6625 struct bgp_static *bgp_static;
6626
05c7a1cc 6627 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6628 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6629 dest = bgp_route_next(dest)) {
6630 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6631 continue;
ea47320b 6632
05c7a1cc
QY
6633 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6634 || (safi == SAFI_EVPN)) {
9bcb3eef 6635 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6636
6637 for (rm = bgp_table_top(table); rm;
6638 rm = bgp_route_next(rm)) {
a78beeb5 6639 bgp_static =
9bcb3eef 6640 bgp_dest_get_bgp_static_info(
5a8ba9fc 6641 rm);
c7d14ba6
PG
6642 if (!bgp_static)
6643 continue;
6644
05c7a1cc 6645 bgp_static_withdraw_safi(
9bcb3eef 6646 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6647 AFI_IP, safi,
6648 (struct prefix_rd *)
9bcb3eef
DS
6649 bgp_dest_get_prefix(
6650 dest));
ea47320b 6651 bgp_static_free(bgp_static);
811c6797 6652 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6653 NULL);
811c6797 6654 bgp_dest_unlock_node(rm);
d62a17ae 6655 }
05c7a1cc 6656 } else {
9bcb3eef 6657 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6658 bgp_static_withdraw(bgp,
9bcb3eef 6659 bgp_dest_get_prefix(dest),
b54892e0 6660 afi, safi);
05c7a1cc 6661 bgp_static_free(bgp_static);
9bcb3eef
DS
6662 bgp_dest_set_bgp_static_info(dest, NULL);
6663 bgp_dest_unlock_node(dest);
ea47320b 6664 }
05c7a1cc 6665 }
d62a17ae 6666}
6667
6668void bgp_static_redo_import_check(struct bgp *bgp)
6669{
6670 afi_t afi;
6671 safi_t safi;
9bcb3eef
DS
6672 struct bgp_dest *dest;
6673 struct bgp_dest *rm;
d62a17ae 6674 struct bgp_table *table;
6675 struct bgp_static *bgp_static;
6676
6677 /* Use this flag to force reprocessing of the route */
892fedb6 6678 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6679 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6680 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6681 dest = bgp_route_next(dest)) {
6682 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6683 continue;
ea47320b 6684
05c7a1cc
QY
6685 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6686 || (safi == SAFI_EVPN)) {
9bcb3eef 6687 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6688
6689 for (rm = bgp_table_top(table); rm;
6690 rm = bgp_route_next(rm)) {
a78beeb5 6691 bgp_static =
9bcb3eef 6692 bgp_dest_get_bgp_static_info(
5a8ba9fc 6693 rm);
9bcb3eef
DS
6694 bgp_static_update_safi(
6695 bgp, bgp_dest_get_prefix(rm),
6696 bgp_static, afi, safi);
d62a17ae 6697 }
05c7a1cc 6698 } else {
9bcb3eef
DS
6699 bgp_static = bgp_dest_get_bgp_static_info(dest);
6700 bgp_static_update(bgp,
6701 bgp_dest_get_prefix(dest),
6702 bgp_static, afi, safi);
ea47320b 6703 }
05c7a1cc
QY
6704 }
6705 }
892fedb6 6706 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6707}
6708
6709static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6710 safi_t safi)
6711{
6712 struct bgp_table *table;
9bcb3eef 6713 struct bgp_dest *dest;
40381db7 6714 struct bgp_path_info *pi;
d62a17ae 6715
dfb6fd1d
NT
6716 /* Do not install the aggregate route if BGP is in the
6717 * process of termination.
6718 */
892fedb6
DA
6719 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6720 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6721 return;
6722
d62a17ae 6723 table = bgp->rib[afi][safi];
9bcb3eef
DS
6724 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6725 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6726 if (pi->peer == bgp->peer_self
6727 && ((pi->type == ZEBRA_ROUTE_BGP
6728 && pi->sub_type == BGP_ROUTE_STATIC)
6729 || (pi->type != ZEBRA_ROUTE_BGP
6730 && pi->sub_type
d62a17ae 6731 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6732 bgp_aggregate_decrement(
6733 bgp, bgp_dest_get_prefix(dest), pi, afi,
6734 safi);
40381db7 6735 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6736 bgp_path_info_delete(dest, pi);
6737 bgp_process(bgp, dest, afi, safi);
d62a17ae 6738 }
6739 }
6740 }
ad4cbda1 6741}
6742
6743/*
6744 * Purge all networks and redistributed routes from routing table.
6745 * Invoked upon the instance going down.
6746 */
d62a17ae 6747void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6748{
d62a17ae 6749 afi_t afi;
6750 safi_t safi;
ad4cbda1 6751
05c7a1cc
QY
6752 FOREACH_AFI_SAFI (afi, safi)
6753 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6754}
6755
137446f9
LB
6756/*
6757 * gpz 110624
6758 * Currently this is used to set static routes for VPN and ENCAP.
6759 * I think it can probably be factored with bgp_static_set.
6760 */
d62a17ae 6761int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6762 const char *ip_str, const char *rd_str,
6763 const char *label_str, const char *rmap_str,
6764 int evpn_type, const char *esi, const char *gwip,
6765 const char *ethtag, const char *routermac)
6766{
6767 VTY_DECLVAR_CONTEXT(bgp, bgp);
6768 int ret;
6769 struct prefix p;
6770 struct prefix_rd prd;
9bcb3eef
DS
6771 struct bgp_dest *pdest;
6772 struct bgp_dest *dest;
d62a17ae 6773 struct bgp_table *table;
6774 struct bgp_static *bgp_static;
6775 mpls_label_t label = MPLS_INVALID_LABEL;
6776 struct prefix gw_ip;
6777
6778 /* validate ip prefix */
6779 ret = str2prefix(ip_str, &p);
6780 if (!ret) {
6781 vty_out(vty, "%% Malformed prefix\n");
6782 return CMD_WARNING_CONFIG_FAILED;
6783 }
6784 apply_mask(&p);
6785 if ((afi == AFI_L2VPN)
6786 && (bgp_build_evpn_prefix(evpn_type,
6787 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6788 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6789 return CMD_WARNING_CONFIG_FAILED;
6790 }
718e3744 6791
d62a17ae 6792 ret = str2prefix_rd(rd_str, &prd);
6793 if (!ret) {
6794 vty_out(vty, "%% Malformed rd\n");
6795 return CMD_WARNING_CONFIG_FAILED;
6796 }
718e3744 6797
d62a17ae 6798 if (label_str) {
6799 unsigned long label_val;
6800 label_val = strtoul(label_str, NULL, 10);
6801 encode_label(label_val, &label);
6802 }
9bedbb1e 6803
d62a17ae 6804 if (safi == SAFI_EVPN) {
6805 if (esi && str2esi(esi, NULL) == 0) {
6806 vty_out(vty, "%% Malformed ESI\n");
6807 return CMD_WARNING_CONFIG_FAILED;
6808 }
6809 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6810 vty_out(vty, "%% Malformed Router MAC\n");
6811 return CMD_WARNING_CONFIG_FAILED;
6812 }
6813 if (gwip) {
6006b807 6814 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6815 ret = str2prefix(gwip, &gw_ip);
6816 if (!ret) {
6817 vty_out(vty, "%% Malformed GatewayIp\n");
6818 return CMD_WARNING_CONFIG_FAILED;
6819 }
6820 if ((gw_ip.family == AF_INET
3714a385 6821 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6822 (struct prefix_evpn *)&p))
6823 || (gw_ip.family == AF_INET6
3714a385 6824 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6825 (struct prefix_evpn *)&p))) {
6826 vty_out(vty,
6827 "%% GatewayIp family differs with IP prefix\n");
6828 return CMD_WARNING_CONFIG_FAILED;
6829 }
6830 }
6831 }
9bcb3eef
DS
6832 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6833 if (!bgp_dest_has_bgp_path_info_data(pdest))
6834 bgp_dest_set_bgp_table_info(pdest,
67009e22 6835 bgp_table_init(bgp, afi, safi));
9bcb3eef 6836 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6837
9bcb3eef 6838 dest = bgp_node_get(table, &p);
d62a17ae 6839
9bcb3eef 6840 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6841 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6842 bgp_dest_unlock_node(dest);
d62a17ae 6843 } else {
6844 /* New configuration. */
6845 bgp_static = bgp_static_new();
6846 bgp_static->backdoor = 0;
6847 bgp_static->valid = 0;
6848 bgp_static->igpmetric = 0;
975a328e 6849 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6850 bgp_static->label = label;
6851 bgp_static->prd = prd;
6852
6853 if (rmap_str) {
0a22ddfb 6854 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6855 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6856 bgp_static->rmap.name =
6857 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6858 bgp_static->rmap.map =
6859 route_map_lookup_by_name(rmap_str);
b4897fa5 6860 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6861 }
718e3744 6862
d62a17ae 6863 if (safi == SAFI_EVPN) {
6864 if (esi) {
6865 bgp_static->eth_s_id =
6866 XCALLOC(MTYPE_ATTR,
0a50c248 6867 sizeof(esi_t));
d62a17ae 6868 str2esi(esi, bgp_static->eth_s_id);
6869 }
6870 if (routermac) {
6871 bgp_static->router_mac =
28328ea9 6872 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6873 (void)prefix_str2mac(routermac,
6874 bgp_static->router_mac);
d62a17ae 6875 }
6876 if (gwip)
6877 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6878 }
9bcb3eef 6879 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6880
d62a17ae 6881 bgp_static->valid = 1;
6882 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6883 }
718e3744 6884
d62a17ae 6885 return CMD_SUCCESS;
718e3744 6886}
6887
6888/* Configure static BGP network. */
d62a17ae 6889int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6890 const char *ip_str, const char *rd_str,
6891 const char *label_str, int evpn_type, const char *esi,
6892 const char *gwip, const char *ethtag)
6893{
6894 VTY_DECLVAR_CONTEXT(bgp, bgp);
6895 int ret;
6896 struct prefix p;
6897 struct prefix_rd prd;
9bcb3eef
DS
6898 struct bgp_dest *pdest;
6899 struct bgp_dest *dest;
d62a17ae 6900 struct bgp_table *table;
6901 struct bgp_static *bgp_static;
6902 mpls_label_t label = MPLS_INVALID_LABEL;
6903
6904 /* Convert IP prefix string to struct prefix. */
6905 ret = str2prefix(ip_str, &p);
6906 if (!ret) {
6907 vty_out(vty, "%% Malformed prefix\n");
6908 return CMD_WARNING_CONFIG_FAILED;
6909 }
6910 apply_mask(&p);
6911 if ((afi == AFI_L2VPN)
6912 && (bgp_build_evpn_prefix(evpn_type,
6913 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6914 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6915 return CMD_WARNING_CONFIG_FAILED;
6916 }
6917 ret = str2prefix_rd(rd_str, &prd);
6918 if (!ret) {
6919 vty_out(vty, "%% Malformed rd\n");
6920 return CMD_WARNING_CONFIG_FAILED;
6921 }
718e3744 6922
d62a17ae 6923 if (label_str) {
6924 unsigned long label_val;
6925 label_val = strtoul(label_str, NULL, 10);
6926 encode_label(label_val, &label);
6927 }
718e3744 6928
9bcb3eef
DS
6929 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6930 if (!bgp_dest_has_bgp_path_info_data(pdest))
6931 bgp_dest_set_bgp_table_info(pdest,
67009e22 6932 bgp_table_init(bgp, afi, safi));
d62a17ae 6933 else
9bcb3eef
DS
6934 bgp_dest_unlock_node(pdest);
6935 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6936
9bcb3eef 6937 dest = bgp_node_lookup(table, &p);
6b0655a2 6938
9bcb3eef 6939 if (dest) {
d62a17ae 6940 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6941
9bcb3eef 6942 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6943 bgp_static_free(bgp_static);
9bcb3eef
DS
6944 bgp_dest_set_bgp_static_info(dest, NULL);
6945 bgp_dest_unlock_node(dest);
6946 bgp_dest_unlock_node(dest);
d62a17ae 6947 } else
6948 vty_out(vty, "%% Can't find the route\n");
6949
6950 return CMD_SUCCESS;
6951}
6952
6953static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6954 const char *rmap_name)
6955{
6956 VTY_DECLVAR_CONTEXT(bgp, bgp);
6957 struct bgp_rmap *rmap;
6958
6959 rmap = &bgp->table_map[afi][safi];
6960 if (rmap_name) {
0a22ddfb 6961 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6962 route_map_counter_decrement(rmap->map);
d62a17ae 6963 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6964 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6965 route_map_counter_increment(rmap->map);
d62a17ae 6966 } else {
0a22ddfb 6967 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6968 route_map_counter_decrement(rmap->map);
d62a17ae 6969 rmap->map = NULL;
6970 }
73ac8160 6971
d62a17ae 6972 if (bgp_fibupd_safi(safi))
6973 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6974
d62a17ae 6975 return CMD_SUCCESS;
73ac8160
DS
6976}
6977
d62a17ae 6978static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6979 const char *rmap_name)
73ac8160 6980{
d62a17ae 6981 VTY_DECLVAR_CONTEXT(bgp, bgp);
6982 struct bgp_rmap *rmap;
73ac8160 6983
d62a17ae 6984 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6985 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6986 route_map_counter_decrement(rmap->map);
d62a17ae 6987 rmap->map = NULL;
73ac8160 6988
d62a17ae 6989 if (bgp_fibupd_safi(safi))
6990 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6991
d62a17ae 6992 return CMD_SUCCESS;
73ac8160
DS
6993}
6994
2b791107 6995void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6996 safi_t safi)
73ac8160 6997{
d62a17ae 6998 if (bgp->table_map[afi][safi].name) {
d62a17ae 6999 vty_out(vty, " table-map %s\n",
7000 bgp->table_map[afi][safi].name);
7001 }
73ac8160
DS
7002}
7003
73ac8160
DS
7004DEFUN (bgp_table_map,
7005 bgp_table_map_cmd,
7006 "table-map WORD",
7007 "BGP table to RIB route download filter\n"
7008 "Name of the route map\n")
7009{
d62a17ae 7010 int idx_word = 1;
7011 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7012 argv[idx_word]->arg);
73ac8160
DS
7013}
7014DEFUN (no_bgp_table_map,
7015 no_bgp_table_map_cmd,
7016 "no table-map WORD",
3a2d747c 7017 NO_STR
73ac8160
DS
7018 "BGP table to RIB route download filter\n"
7019 "Name of the route map\n")
7020{
d62a17ae 7021 int idx_word = 2;
7022 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
7023 argv[idx_word]->arg);
73ac8160
DS
7024}
7025
585f1adc
IR
7026DEFPY(bgp_network,
7027 bgp_network_cmd,
7028 "[no] network \
7029 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7030 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7031 backdoor$backdoor}]",
7032 NO_STR
7033 "Specify a network to announce via BGP\n"
7034 "IPv4 prefix\n"
7035 "Network number\n"
7036 "Network mask\n"
7037 "Network mask\n"
7038 "Route-map to modify the attributes\n"
7039 "Name of the route map\n"
7040 "Label index to associate with the prefix\n"
7041 "Label index value\n"
7042 "Specify a BGP backdoor route\n")
7043{
7044 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7045
7046 if (address_str) {
7047 int ret;
718e3744 7048
e2a86ad9 7049 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7050 addr_prefix_str,
7051 sizeof(addr_prefix_str));
e2a86ad9
DS
7052 if (!ret) {
7053 vty_out(vty, "%% Inconsistent address and mask\n");
7054 return CMD_WARNING_CONFIG_FAILED;
7055 }
d62a17ae 7056 }
718e3744 7057
585f1adc
IR
7058 return bgp_static_set(
7059 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7060 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7061 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7062}
7063
585f1adc
IR
7064DEFPY(ipv6_bgp_network,
7065 ipv6_bgp_network_cmd,
7066 "[no] network X:X::X:X/M$prefix \
70dd370f 7067 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7068 NO_STR
7069 "Specify a network to announce via BGP\n"
7070 "IPv6 prefix\n"
7071 "Route-map to modify the attributes\n"
7072 "Name of the route map\n"
7073 "Label index to associate with the prefix\n"
7074 "Label index value\n")
37a87b8f 7075{
585f1adc
IR
7076 return bgp_static_set(
7077 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7078 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7079}
7080
d62a17ae 7081static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7082{
d62a17ae 7083 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7084}
7085
d62a17ae 7086static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7087{
365ab2e7
RZ
7088 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7089 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7090 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7091 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7092 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7093}
718e3744 7094
365ab2e7
RZ
7095/**
7096 * Helper function to avoid repeated code: prepare variables for a
7097 * `route_map_apply` call.
7098 *
7099 * \returns `true` on route map match, otherwise `false`.
7100 */
7101static bool aggr_suppress_map_test(struct bgp *bgp,
7102 struct bgp_aggregate *aggregate,
7103 struct bgp_path_info *pi)
7104{
7105 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7106 route_map_result_t rmr = RMAP_DENYMATCH;
7107 struct bgp_path_info rmap_path = {};
7108 struct attr attr = {};
7109
7110 /* No route map entries created, just don't match. */
7111 if (aggregate->suppress_map == NULL)
7112 return false;
7113
7114 /* Call route map matching and return result. */
7115 attr.aspath = aspath_empty();
7116 rmap_path.peer = bgp->peer_self;
7117 rmap_path.attr = &attr;
7118
7119 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7120 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7121 bgp->peer_self->rmap_type = 0;
7122
7123 bgp_attr_flush(&attr);
afb254d7 7124 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7125
7126 return rmr == RMAP_PERMITMATCH;
7127}
7128
4056a5f6
RZ
7129/** Test whether the aggregation has suppressed this path or not. */
7130static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7131 struct bgp_path_info *pi)
7132{
7133 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7134 return false;
7135
7136 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7137}
7138
7139/**
7140 * Suppress this path and keep the reference.
7141 *
7142 * \returns `true` if needs processing otherwise `false`.
7143 */
7144static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7145 struct bgp_path_info *pi)
7146{
7147 struct bgp_path_info_extra *pie;
7148
7149 /* Path is already suppressed by this aggregation. */
7150 if (aggr_suppress_exists(aggregate, pi))
7151 return false;
7152
7153 pie = bgp_path_info_extra_get(pi);
7154
7155 /* This is the first suppression, allocate memory and list it. */
7156 if (pie->aggr_suppressors == NULL)
7157 pie->aggr_suppressors = list_new();
7158
7159 listnode_add(pie->aggr_suppressors, aggregate);
7160
7161 /* Only mark for processing if suppressed. */
7162 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7163 if (BGP_DEBUG(update, UPDATE_OUT))
7164 zlog_debug("aggregate-address suppressing: %pFX",
7165 bgp_dest_get_prefix(pi->net));
7166
4056a5f6
RZ
7167 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7168 return true;
7169 }
7170
7171 return false;
7172}
7173
7174/**
7175 * Unsuppress this path and remove the reference.
7176 *
7177 * \returns `true` if needs processing otherwise `false`.
7178 */
7179static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7180 struct bgp_path_info *pi)
7181{
7182 /* Path wasn't suppressed. */
7183 if (!aggr_suppress_exists(aggregate, pi))
7184 return false;
7185
7186 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7187
7188 /* Unsuppress and free extra memory if last item. */
7189 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7190 if (BGP_DEBUG(update, UPDATE_OUT))
7191 zlog_debug("aggregate-address unsuppressing: %pFX",
7192 bgp_dest_get_prefix(pi->net));
7193
4056a5f6
RZ
7194 list_delete(&pi->extra->aggr_suppressors);
7195 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7196 return true;
7197 }
7198
7199 return false;
7200}
7201
3dc339cd
DA
7202static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7203 struct aspath *aspath,
7204 struct community *comm,
7205 struct ecommunity *ecomm,
7206 struct lcommunity *lcomm)
eaaf8adb
DS
7207{
7208 static struct aspath *ae = NULL;
7209
7210 if (!ae)
7211 ae = aspath_empty();
7212
40381db7 7213 if (!pi)
3dc339cd 7214 return false;
eaaf8adb 7215
40381db7 7216 if (origin != pi->attr->origin)
3dc339cd 7217 return false;
eaaf8adb 7218
40381db7 7219 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7220 return false;
29f7d023 7221
9a706b42 7222 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7223 return false;
eaaf8adb 7224
b53e67a3 7225 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7226 return false;
eaaf8adb 7227
1bcf3a96 7228 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7229 return false;
dd18c5a9 7230
40381db7 7231 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7232 return false;
7ce8a8e0 7233
3dc339cd 7234 return true;
eaaf8adb
DS
7235}
7236
5f040085
DS
7237static void bgp_aggregate_install(
7238 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7239 uint8_t origin, struct aspath *aspath, struct community *community,
7240 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7241 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7242{
9bcb3eef 7243 struct bgp_dest *dest;
c701010e 7244 struct bgp_table *table;
6f94b685 7245 struct bgp_path_info *pi, *orig, *new;
20894f50 7246 struct attr *attr;
c701010e
DS
7247
7248 table = bgp->rib[afi][safi];
7249
9bcb3eef 7250 dest = bgp_node_get(table, p);
eaaf8adb 7251
9bcb3eef 7252 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7253 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7254 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7255 break;
7256
6aabb15d
RZ
7257 /*
7258 * If we have paths with different MEDs, then don't install
7259 * (or uninstall) the aggregate route.
7260 */
7261 if (aggregate->match_med && aggregate->med_mismatched)
7262 goto uninstall_aggregate_route;
7263
c701010e 7264 if (aggregate->count > 0) {
eaaf8adb
DS
7265 /*
7266 * If the aggregate information has not changed
7267 * no need to re-install it again.
7268 */
6f94b685 7269 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7270 ecommunity, lcommunity)) {
9bcb3eef 7271 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7272
7273 if (aspath)
7274 aspath_free(aspath);
7275 if (community)
3c1f53de 7276 community_free(&community);
3da2cc32
DS
7277 if (ecommunity)
7278 ecommunity_free(&ecommunity);
dd18c5a9
DS
7279 if (lcommunity)
7280 lcommunity_free(&lcommunity);
eaaf8adb
DS
7281
7282 return;
7283 }
7284
7285 /*
7286 * Mark the old as unusable
7287 */
40381db7 7288 if (pi)
9bcb3eef 7289 bgp_path_info_delete(dest, pi);
eaaf8adb 7290
20894f50
DA
7291 attr = bgp_attr_aggregate_intern(
7292 bgp, origin, aspath, community, ecommunity, lcommunity,
7293 aggregate, atomic_aggregate, p);
7294
7295 if (!attr) {
8c0044f3 7296 bgp_dest_unlock_node(dest);
20894f50 7297 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7298 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7299 zlog_debug("%s: %pFX null attribute", __func__,
7300 p);
20894f50
DA
7301 return;
7302 }
7303
3da2cc32 7304 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7305 bgp->peer_self, attr, dest);
20894f50 7306
1defdda8 7307 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7308
9bcb3eef
DS
7309 bgp_path_info_add(dest, new);
7310 bgp_process(bgp, dest, afi, safi);
c701010e 7311 } else {
6aabb15d 7312 uninstall_aggregate_route:
6f94b685 7313 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7314 if (pi->peer == bgp->peer_self
7315 && pi->type == ZEBRA_ROUTE_BGP
7316 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7317 break;
7318
7319 /* Withdraw static BGP route from routing table. */
40381db7 7320 if (pi) {
9bcb3eef
DS
7321 bgp_path_info_delete(dest, pi);
7322 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7323 }
7324 }
7325
9bcb3eef 7326 bgp_dest_unlock_node(dest);
c701010e
DS
7327}
7328
6aabb15d
RZ
7329/**
7330 * Check if the current path has different MED than other known paths.
7331 *
7332 * \returns `true` if the MED matched the others else `false`.
7333 */
7334static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7335 struct bgp *bgp, struct bgp_path_info *pi)
7336{
7337 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7338
7339 /* This is the first route being analyzed. */
7340 if (!aggregate->med_initialized) {
7341 aggregate->med_initialized = true;
7342 aggregate->med_mismatched = false;
7343 aggregate->med_matched_value = cur_med;
7344 } else {
7345 /* Check if routes with different MED showed up. */
7346 if (cur_med != aggregate->med_matched_value)
7347 aggregate->med_mismatched = true;
7348 }
7349
7350 return !aggregate->med_mismatched;
7351}
7352
7353/**
7354 * Initializes and tests all routes in the aggregate address path for MED
7355 * values.
7356 *
7357 * \returns `true` if all MEDs are the same otherwise `false`.
7358 */
7359static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7360 struct bgp *bgp, const struct prefix *p,
7361 afi_t afi, safi_t safi)
7362{
7363 struct bgp_table *table = bgp->rib[afi][safi];
7364 const struct prefix *dest_p;
7365 struct bgp_dest *dest, *top;
7366 struct bgp_path_info *pi;
7367 bool med_matched = true;
7368
7369 aggregate->med_initialized = false;
7370
7371 top = bgp_node_get(table, p);
7372 for (dest = bgp_node_get(table, p); dest;
7373 dest = bgp_route_next_until(dest, top)) {
7374 dest_p = bgp_dest_get_prefix(dest);
7375 if (dest_p->prefixlen <= p->prefixlen)
7376 continue;
7377
7378 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7379 if (BGP_PATH_HOLDDOWN(pi))
7380 continue;
7381 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7382 continue;
7383 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7384 med_matched = false;
7385 break;
7386 }
7387 }
7388 if (!med_matched)
7389 break;
7390 }
7391 bgp_dest_unlock_node(top);
7392
7393 return med_matched;
7394}
7395
7396/**
7397 * Toggles the route suppression status for this aggregate address
7398 * configuration.
7399 */
4056a5f6
RZ
7400void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7401 struct bgp *bgp, const struct prefix *p,
7402 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7403{
7404 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7405 const struct prefix *dest_p;
7406 struct bgp_dest *dest, *top;
7407 struct bgp_path_info *pi;
7408 bool toggle_suppression;
7409
7410 /* We've found a different MED we must revert any suppressed routes. */
7411 top = bgp_node_get(table, p);
7412 for (dest = bgp_node_get(table, p); dest;
7413 dest = bgp_route_next_until(dest, top)) {
7414 dest_p = bgp_dest_get_prefix(dest);
7415 if (dest_p->prefixlen <= p->prefixlen)
7416 continue;
7417
7418 toggle_suppression = false;
7419 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7420 if (BGP_PATH_HOLDDOWN(pi))
7421 continue;
7422 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7423 continue;
7424
6aabb15d
RZ
7425 /* We are toggling suppression back. */
7426 if (suppress) {
6aabb15d 7427 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7428 if (aggr_suppress_path(aggregate, pi))
7429 toggle_suppression = true;
6aabb15d
RZ
7430 continue;
7431 }
7432
6aabb15d 7433 /* Install route if there is no more suppression. */
4056a5f6 7434 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7435 toggle_suppression = true;
6aabb15d
RZ
7436 }
7437
7438 if (toggle_suppression)
7439 bgp_process(bgp, dest, afi, safi);
7440 }
7441 bgp_dest_unlock_node(top);
7442}
7443
7444/**
7445 * Aggregate address MED matching incremental test: this function is called
7446 * when the initial aggregation occurred and we are only testing a single
7447 * new path.
7448 *
7449 * In addition to testing and setting the MED validity it also installs back
7450 * suppressed routes (if summary is configured).
7451 *
7452 * Must not be called in `bgp_aggregate_route`.
7453 */
7454static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7455 struct bgp *bgp, const struct prefix *p,
7456 afi_t afi, safi_t safi,
f66624f5 7457 struct bgp_path_info *pi)
6aabb15d
RZ
7458{
7459 /* MED matching disabled. */
7460 if (!aggregate->match_med)
7461 return;
7462
f66624f5
DA
7463 /* Aggregation with different MED, recheck if we have got equal MEDs
7464 * now.
6aabb15d 7465 */
f66624f5
DA
7466 if (aggregate->med_mismatched &&
7467 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
7468 aggregate->summary_only)
7469 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
7470 true);
7471 else
6aabb15d
RZ
7472 bgp_aggregate_med_match(aggregate, bgp, pi);
7473
7474 /* No mismatches, just quit. */
7475 if (!aggregate->med_mismatched)
7476 return;
7477
7478 /* Route summarization is disabled. */
7479 if (!aggregate->summary_only)
7480 return;
7481
7482 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7483}
7484
b5d58c32 7485/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7486void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7487 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7488{
7489 struct bgp_table *table;
9bcb3eef
DS
7490 struct bgp_dest *top;
7491 struct bgp_dest *dest;
d7c0a89a 7492 uint8_t origin;
d62a17ae 7493 struct aspath *aspath = NULL;
d62a17ae 7494 struct community *community = NULL;
3da2cc32 7495 struct ecommunity *ecommunity = NULL;
dd18c5a9 7496 struct lcommunity *lcommunity = NULL;
40381db7 7497 struct bgp_path_info *pi;
d62a17ae 7498 unsigned long match = 0;
d7c0a89a 7499 uint8_t atomic_aggregate = 0;
d62a17ae 7500
9f822fa2
S
7501 /* If the bgp instance is being deleted or self peer is deleted
7502 * then do not create aggregate route
7503 */
892fedb6
DA
7504 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7505 || (bgp->peer_self == NULL))
9f822fa2
S
7506 return;
7507
6aabb15d
RZ
7508 /* Initialize and test routes for MED difference. */
7509 if (aggregate->match_med)
7510 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7511
4056a5f6
RZ
7512 /*
7513 * Reset aggregate count: we might've been called from route map
7514 * update so in that case we must retest all more specific routes.
7515 *
7516 * \see `bgp_route_map_process_update`.
7517 */
7518 aggregate->count = 0;
7519 aggregate->incomplete_origin_count = 0;
7520 aggregate->incomplete_origin_count = 0;
7521 aggregate->egp_origin_count = 0;
7522
d62a17ae 7523 /* ORIGIN attribute: If at least one route among routes that are
7524 aggregated has ORIGIN with the value INCOMPLETE, then the
7525 aggregated route must have the ORIGIN attribute with the value
7526 INCOMPLETE. Otherwise, if at least one route among routes that
7527 are aggregated has ORIGIN with the value EGP, then the aggregated
7528 route must have the origin attribute with the value EGP. In all
7529 other case the value of the ORIGIN attribute of the aggregated
7530 route is INTERNAL. */
7531 origin = BGP_ORIGIN_IGP;
718e3744 7532
d62a17ae 7533 table = bgp->rib[afi][safi];
718e3744 7534
d62a17ae 7535 top = bgp_node_get(table, p);
9bcb3eef
DS
7536 for (dest = bgp_node_get(table, p); dest;
7537 dest = bgp_route_next_until(dest, top)) {
7538 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7539
9bcb3eef 7540 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7541 continue;
d62a17ae 7542
a77e2f4b
S
7543 /* If suppress fib is enabled and route not installed
7544 * in FIB, skip the route
7545 */
7546 if (!bgp_check_advertise(bgp, dest))
7547 continue;
7548
c2ff8b3e 7549 match = 0;
d62a17ae 7550
9bcb3eef 7551 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7552 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7553 continue;
718e3744 7554
40381db7 7555 if (pi->attr->flag
c2ff8b3e
DS
7556 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7557 atomic_aggregate = 1;
d62a17ae 7558
40381db7 7559 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7560 continue;
d62a17ae 7561
f273fef1
DS
7562 /*
7563 * summary-only aggregate route suppress
7564 * aggregated route announcements.
6aabb15d
RZ
7565 *
7566 * MED matching:
7567 * Don't create summaries if MED didn't match
7568 * otherwise neither the specific routes and the
7569 * aggregation will be announced.
f273fef1 7570 */
6aabb15d
RZ
7571 if (aggregate->summary_only
7572 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7573 if (aggr_suppress_path(aggregate, pi))
7574 match++;
d62a17ae 7575 }
c2ff8b3e 7576
365ab2e7
RZ
7577 /*
7578 * Suppress more specific routes that match the route
7579 * map results.
7580 *
7581 * MED matching:
7582 * Don't suppress routes if MED matching is enabled and
7583 * it mismatched otherwise we might end up with no
7584 * routes for this path.
7585 */
7586 if (aggregate->suppress_map_name
7587 && AGGREGATE_MED_VALID(aggregate)
7588 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7589 if (aggr_suppress_path(aggregate, pi))
7590 match++;
d62a17ae 7591 }
c2ff8b3e
DS
7592
7593 aggregate->count++;
7594
f273fef1
DS
7595 /*
7596 * If at least one route among routes that are
7597 * aggregated has ORIGIN with the value INCOMPLETE,
7598 * then the aggregated route MUST have the ORIGIN
7599 * attribute with the value INCOMPLETE. Otherwise, if
7600 * at least one route among routes that are aggregated
7601 * has ORIGIN with the value EGP, then the aggregated
7602 * route MUST have the ORIGIN attribute with the value
7603 * EGP.
7604 */
fc968841
NT
7605 switch (pi->attr->origin) {
7606 case BGP_ORIGIN_INCOMPLETE:
7607 aggregate->incomplete_origin_count++;
7608 break;
7609 case BGP_ORIGIN_EGP:
7610 aggregate->egp_origin_count++;
7611 break;
7612 default:
7613 /*Do nothing.
7614 */
7615 break;
7616 }
c2ff8b3e
DS
7617
7618 if (!aggregate->as_set)
7619 continue;
7620
f273fef1
DS
7621 /*
7622 * as-set aggregate route generate origin, as path,
7623 * and community aggregation.
7624 */
fc968841
NT
7625 /* Compute aggregate route's as-path.
7626 */
ef51a7d8 7627 bgp_compute_aggregate_aspath_hash(aggregate,
7628 pi->attr->aspath);
c2ff8b3e 7629
fc968841
NT
7630 /* Compute aggregate route's community.
7631 */
9a706b42 7632 if (bgp_attr_get_community(pi->attr))
21fec674 7633 bgp_compute_aggregate_community_hash(
9a706b42
DA
7634 aggregate,
7635 bgp_attr_get_community(pi->attr));
dd18c5a9 7636
fc968841
NT
7637 /* Compute aggregate route's extended community.
7638 */
b53e67a3 7639 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7640 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7641 aggregate,
7642 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7643
7644 /* Compute aggregate route's large community.
7645 */
1bcf3a96 7646 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7647 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7648 aggregate,
7649 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7650 }
c2ff8b3e 7651 if (match)
9bcb3eef 7652 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7653 }
21fec674 7654 if (aggregate->as_set) {
ef51a7d8 7655 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7656 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7657 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7658 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7659 }
7660
f1eb1f05 7661
9bcb3eef 7662 bgp_dest_unlock_node(top);
718e3744 7663
718e3744 7664
fc968841
NT
7665 if (aggregate->incomplete_origin_count > 0)
7666 origin = BGP_ORIGIN_INCOMPLETE;
7667 else if (aggregate->egp_origin_count > 0)
7668 origin = BGP_ORIGIN_EGP;
d62a17ae 7669
229757f1
DA
7670 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7671 origin = aggregate->origin;
7672
fc968841
NT
7673 if (aggregate->as_set) {
7674 if (aggregate->aspath)
7675 /* Retrieve aggregate route's as-path.
7676 */
7677 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7678
fc968841
NT
7679 if (aggregate->community)
7680 /* Retrieve aggregate route's community.
7681 */
7682 community = community_dup(aggregate->community);
3da2cc32 7683
fc968841
NT
7684 if (aggregate->ecommunity)
7685 /* Retrieve aggregate route's ecommunity.
7686 */
7687 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7688
fc968841
NT
7689 if (aggregate->lcommunity)
7690 /* Retrieve aggregate route's lcommunity.
7691 */
7692 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7693 }
718e3744 7694
c701010e 7695 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7696 ecommunity, lcommunity, atomic_aggregate,
7697 aggregate);
718e3744 7698}
7699
5f040085
DS
7700void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7701 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7702{
7703 struct bgp_table *table;
9bcb3eef
DS
7704 struct bgp_dest *top;
7705 struct bgp_dest *dest;
40381db7 7706 struct bgp_path_info *pi;
3b7db173
DS
7707 unsigned long match;
7708
7709 table = bgp->rib[afi][safi];
7710
7711 /* If routes exists below this node, generate aggregate routes. */
7712 top = bgp_node_get(table, p);
9bcb3eef
DS
7713 for (dest = bgp_node_get(table, p); dest;
7714 dest = bgp_route_next_until(dest, top)) {
7715 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7716
9bcb3eef 7717 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7718 continue;
7719 match = 0;
7720
9bcb3eef 7721 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7722 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7723 continue;
7724
40381db7 7725 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7726 continue;
7727
92b175bd
RZ
7728 /*
7729 * This route is suppressed: attempt to unsuppress it.
7730 *
7731 * `aggr_unsuppress_path` will fail if this particular
7732 * aggregate route was not the suppressor.
7733 */
7734 if (pi->extra && pi->extra->aggr_suppressors &&
7735 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7736 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7737 match++;
3b7db173 7738 }
365ab2e7 7739
3b7db173 7740 aggregate->count--;
fc968841
NT
7741
7742 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7743 aggregate->incomplete_origin_count--;
7744 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7745 aggregate->egp_origin_count--;
7746
7747 if (aggregate->as_set) {
7748 /* Remove as-path from aggregate.
7749 */
ef51a7d8 7750 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7751 aggregate,
7752 pi->attr->aspath);
7753
9a706b42 7754 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7755 /* Remove community from aggregate.
7756 */
21fec674 7757 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7758 aggregate,
7759 bgp_attr_get_community(
7760 pi->attr));
fc968841 7761
b53e67a3 7762 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7763 /* Remove ecommunity from aggregate.
7764 */
4edd83f9 7765 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7766 aggregate,
7767 bgp_attr_get_ecommunity(
7768 pi->attr));
fc968841 7769
1bcf3a96 7770 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7771 /* Remove lcommunity from aggregate.
7772 */
f1eb1f05 7773 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7774 aggregate,
7775 bgp_attr_get_lcommunity(
7776 pi->attr));
fc968841 7777 }
3b7db173
DS
7778 }
7779
7780 /* If this node was suppressed, process the change. */
7781 if (match)
9bcb3eef 7782 bgp_process(bgp, dest, afi, safi);
3b7db173 7783 }
f1eb1f05 7784 if (aggregate->as_set) {
ef51a7d8 7785 aspath_free(aggregate->aspath);
7786 aggregate->aspath = NULL;
21fec674 7787 if (aggregate->community)
7788 community_free(&aggregate->community);
4edd83f9 7789 if (aggregate->ecommunity)
7790 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7791 if (aggregate->lcommunity)
7792 lcommunity_free(&aggregate->lcommunity);
7793 }
7794
9bcb3eef 7795 bgp_dest_unlock_node(top);
3b7db173 7796}
718e3744 7797
5f040085
DS
7798static void bgp_add_route_to_aggregate(struct bgp *bgp,
7799 const struct prefix *aggr_p,
fc968841
NT
7800 struct bgp_path_info *pinew, afi_t afi,
7801 safi_t safi,
7802 struct bgp_aggregate *aggregate)
7803{
7804 uint8_t origin;
7805 struct aspath *aspath = NULL;
7806 uint8_t atomic_aggregate = 0;
7807 struct community *community = NULL;
7808 struct ecommunity *ecommunity = NULL;
7809 struct lcommunity *lcommunity = NULL;
7810
a4559740 7811 /* If the bgp instance is being deleted or self peer is deleted
7812 * then do not create aggregate route
7813 */
7814 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7815 || (bgp->peer_self == NULL))
7816 return;
7817
fc968841
NT
7818 /* ORIGIN attribute: If at least one route among routes that are
7819 * aggregated has ORIGIN with the value INCOMPLETE, then the
7820 * aggregated route must have the ORIGIN attribute with the value
7821 * INCOMPLETE. Otherwise, if at least one route among routes that
7822 * are aggregated has ORIGIN with the value EGP, then the aggregated
7823 * route must have the origin attribute with the value EGP. In all
7824 * other case the value of the ORIGIN attribute of the aggregated
7825 * route is INTERNAL.
7826 */
7827 origin = BGP_ORIGIN_IGP;
7828
7829 aggregate->count++;
7830
6aabb15d
RZ
7831 /*
7832 * This must be called before `summary` check to avoid
7833 * "suppressing" twice.
7834 */
7835 if (aggregate->match_med)
7836 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
f66624f5 7837 pinew);
6aabb15d
RZ
7838
7839 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7840 aggr_suppress_path(aggregate, pinew);
fc968841 7841
365ab2e7
RZ
7842 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7843 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7844 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7845
7846 switch (pinew->attr->origin) {
7847 case BGP_ORIGIN_INCOMPLETE:
7848 aggregate->incomplete_origin_count++;
7849 break;
7850 case BGP_ORIGIN_EGP:
7851 aggregate->egp_origin_count++;
7852 break;
7853 default:
7854 /* Do nothing.
7855 */
7856 break;
7857 }
7858
7859 if (aggregate->incomplete_origin_count > 0)
7860 origin = BGP_ORIGIN_INCOMPLETE;
7861 else if (aggregate->egp_origin_count > 0)
7862 origin = BGP_ORIGIN_EGP;
7863
229757f1
DA
7864 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7865 origin = aggregate->origin;
7866
fc968841
NT
7867 if (aggregate->as_set) {
7868 /* Compute aggregate route's as-path.
7869 */
7870 bgp_compute_aggregate_aspath(aggregate,
7871 pinew->attr->aspath);
7872
7873 /* Compute aggregate route's community.
7874 */
9a706b42 7875 if (bgp_attr_get_community(pinew->attr))
fc968841 7876 bgp_compute_aggregate_community(
9a706b42 7877 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7878
7879 /* Compute aggregate route's extended community.
7880 */
b53e67a3 7881 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7882 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7883 aggregate,
7884 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7885
7886 /* Compute aggregate route's large community.
7887 */
1bcf3a96 7888 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7889 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7890 aggregate,
7891 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7892
7893 /* Retrieve aggregate route's as-path.
7894 */
7895 if (aggregate->aspath)
7896 aspath = aspath_dup(aggregate->aspath);
7897
7898 /* Retrieve aggregate route's community.
7899 */
7900 if (aggregate->community)
7901 community = community_dup(aggregate->community);
7902
7903 /* Retrieve aggregate route's ecommunity.
7904 */
7905 if (aggregate->ecommunity)
7906 ecommunity = ecommunity_dup(aggregate->ecommunity);
7907
7908 /* Retrieve aggregate route's lcommunity.
7909 */
7910 if (aggregate->lcommunity)
7911 lcommunity = lcommunity_dup(aggregate->lcommunity);
7912 }
7913
7914 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7915 aspath, community, ecommunity,
7916 lcommunity, atomic_aggregate, aggregate);
7917}
7918
7919static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7920 safi_t safi,
7921 struct bgp_path_info *pi,
7922 struct bgp_aggregate *aggregate,
5f040085 7923 const struct prefix *aggr_p)
fc968841
NT
7924{
7925 uint8_t origin;
7926 struct aspath *aspath = NULL;
7927 uint8_t atomic_aggregate = 0;
7928 struct community *community = NULL;
7929 struct ecommunity *ecommunity = NULL;
7930 struct lcommunity *lcommunity = NULL;
7931 unsigned long match = 0;
7932
a4559740 7933 /* If the bgp instance is being deleted or self peer is deleted
7934 * then do not create aggregate route
7935 */
7936 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7937 || (bgp->peer_self == NULL))
7938 return;
7939
fc968841
NT
7940 if (BGP_PATH_HOLDDOWN(pi))
7941 return;
7942
7943 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7944 return;
7945
4056a5f6
RZ
7946 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7947 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7948 match++;
fc968841 7949
365ab2e7 7950 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7951 && aggr_suppress_map_test(bgp, aggregate, pi))
7952 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7953 match++;
fc968841 7954
6aabb15d 7955 /*
365ab2e7 7956 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7957 * "unsuppressing" twice.
7958 */
7959 if (aggregate->match_med)
f66624f5 7960 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
6aabb15d 7961
fc968841
NT
7962 if (aggregate->count > 0)
7963 aggregate->count--;
7964
7965 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7966 aggregate->incomplete_origin_count--;
7967 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7968 aggregate->egp_origin_count--;
7969
7970 if (aggregate->as_set) {
7971 /* Remove as-path from aggregate.
7972 */
7973 bgp_remove_aspath_from_aggregate(aggregate,
7974 pi->attr->aspath);
7975
9a706b42 7976 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7977 /* Remove community from aggregate.
7978 */
7979 bgp_remove_community_from_aggregate(
9a706b42 7980 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7981
b53e67a3 7982 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7983 /* Remove ecommunity from aggregate.
7984 */
7985 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7986 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7987
1bcf3a96 7988 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7989 /* Remove lcommunity from aggregate.
7990 */
7991 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7992 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7993 }
7994
7995 /* If this node was suppressed, process the change. */
7996 if (match)
7997 bgp_process(bgp, pi->net, afi, safi);
7998
7999 origin = BGP_ORIGIN_IGP;
8000 if (aggregate->incomplete_origin_count > 0)
8001 origin = BGP_ORIGIN_INCOMPLETE;
8002 else if (aggregate->egp_origin_count > 0)
8003 origin = BGP_ORIGIN_EGP;
8004
229757f1
DA
8005 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
8006 origin = aggregate->origin;
8007
fc968841
NT
8008 if (aggregate->as_set) {
8009 /* Retrieve aggregate route's as-path.
8010 */
8011 if (aggregate->aspath)
8012 aspath = aspath_dup(aggregate->aspath);
8013
8014 /* Retrieve aggregate route's community.
8015 */
8016 if (aggregate->community)
8017 community = community_dup(aggregate->community);
8018
8019 /* Retrieve aggregate route's ecommunity.
8020 */
8021 if (aggregate->ecommunity)
8022 ecommunity = ecommunity_dup(aggregate->ecommunity);
8023
8024 /* Retrieve aggregate route's lcommunity.
8025 */
8026 if (aggregate->lcommunity)
8027 lcommunity = lcommunity_dup(aggregate->lcommunity);
8028 }
8029
8030 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8031 aspath, community, ecommunity,
8032 lcommunity, atomic_aggregate, aggregate);
8033}
8034
5a1ae2c2 8035void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8036 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8037{
9bcb3eef
DS
8038 struct bgp_dest *child;
8039 struct bgp_dest *dest;
d62a17ae 8040 struct bgp_aggregate *aggregate;
8041 struct bgp_table *table;
718e3744 8042
d62a17ae 8043 table = bgp->aggregate[afi][safi];
f018db83 8044
d62a17ae 8045 /* No aggregates configured. */
8046 if (bgp_table_top_nolock(table) == NULL)
8047 return;
f018db83 8048
d62a17ae 8049 if (p->prefixlen == 0)
8050 return;
718e3744 8051
40381db7 8052 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8053 return;
718e3744 8054
a77e2f4b
S
8055 /* If suppress fib is enabled and route not installed
8056 * in FIB, do not update the aggregate route
8057 */
8058 if (!bgp_check_advertise(bgp, pi->net))
8059 return;
8060
d62a17ae 8061 child = bgp_node_get(table, p);
718e3744 8062
d62a17ae 8063 /* Aggregate address configuration check. */
9bcb3eef
DS
8064 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8065 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8066
9bcb3eef
DS
8067 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8068 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8069 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8070 aggregate);
d62a17ae 8071 }
b1e62edd 8072 }
9bcb3eef 8073 bgp_dest_unlock_node(child);
718e3744 8074}
8075
5a1ae2c2 8076void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8077 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8078{
9bcb3eef
DS
8079 struct bgp_dest *child;
8080 struct bgp_dest *dest;
d62a17ae 8081 struct bgp_aggregate *aggregate;
8082 struct bgp_table *table;
718e3744 8083
d62a17ae 8084 table = bgp->aggregate[afi][safi];
718e3744 8085
d62a17ae 8086 /* No aggregates configured. */
8087 if (bgp_table_top_nolock(table) == NULL)
8088 return;
718e3744 8089
d62a17ae 8090 if (p->prefixlen == 0)
8091 return;
718e3744 8092
d62a17ae 8093 child = bgp_node_get(table, p);
718e3744 8094
d62a17ae 8095 /* Aggregate address configuration check. */
9bcb3eef
DS
8096 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8097 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8098
9bcb3eef
DS
8099 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8100 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8101 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8102 aggregate, dest_p);
d62a17ae 8103 }
b1e62edd 8104 }
9bcb3eef 8105 bgp_dest_unlock_node(child);
d62a17ae 8106}
718e3744 8107
718e3744 8108/* Aggregate route attribute. */
8109#define AGGREGATE_SUMMARY_ONLY 1
8110#define AGGREGATE_AS_SET 1
fb29348a 8111#define AGGREGATE_AS_UNSET 0
718e3744 8112
229757f1
DA
8113static const char *bgp_origin2str(uint8_t origin)
8114{
8115 switch (origin) {
8116 case BGP_ORIGIN_IGP:
8117 return "igp";
8118 case BGP_ORIGIN_EGP:
8119 return "egp";
8120 case BGP_ORIGIN_INCOMPLETE:
8121 return "incomplete";
8122 }
8123 return "n/a";
8124}
8125
fdeb5a81 8126static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8127{
8128 switch (v_state) {
fdeb5a81
DS
8129 case RPKI_NOT_BEING_USED:
8130 return "not used";
8131 case RPKI_VALID:
b5b99af8 8132 return "valid";
fdeb5a81 8133 case RPKI_NOTFOUND:
b5b99af8 8134 return "not found";
fdeb5a81 8135 case RPKI_INVALID:
b5b99af8 8136 return "invalid";
b5b99af8 8137 }
fdeb5a81
DS
8138
8139 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8140 return "ERROR";
8141}
8142
585f1adc
IR
8143static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8144 afi_t afi, safi_t safi)
718e3744 8145{
585f1adc
IR
8146 VTY_DECLVAR_CONTEXT(bgp, bgp);
8147 int ret;
8148 struct prefix p;
9bcb3eef 8149 struct bgp_dest *dest;
d62a17ae 8150 struct bgp_aggregate *aggregate;
718e3744 8151
585f1adc
IR
8152 /* Convert string to prefix structure. */
8153 ret = str2prefix(prefix_str, &p);
8154 if (!ret) {
8155 vty_out(vty, "Malformed prefix\n");
8156 return CMD_WARNING_CONFIG_FAILED;
8157 }
8158 apply_mask(&p);
a4559740 8159
d62a17ae 8160 /* Old configuration check. */
585f1adc 8161 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8162 if (!dest) {
585f1adc
IR
8163 vty_out(vty,
8164 "%% There is no aggregate-address configuration.\n");
8165 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8166 }
f6269b4f 8167
9bcb3eef 8168 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8169 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8170 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8171 NULL, NULL, 0, aggregate);
d62a17ae 8172
8173 /* Unlock aggregate address configuration. */
9bcb3eef 8174 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8175
8176 if (aggregate->community)
8177 community_free(&aggregate->community);
8178
8179 if (aggregate->community_hash) {
8180 /* Delete all communities in the hash.
8181 */
8182 hash_clean(aggregate->community_hash,
8183 bgp_aggr_community_remove);
8184 /* Free up the community_hash.
8185 */
8186 hash_free(aggregate->community_hash);
8187 }
8188
8189 if (aggregate->ecommunity)
8190 ecommunity_free(&aggregate->ecommunity);
8191
8192 if (aggregate->ecommunity_hash) {
8193 /* Delete all ecommunities in the hash.
8194 */
8195 hash_clean(aggregate->ecommunity_hash,
8196 bgp_aggr_ecommunity_remove);
8197 /* Free up the ecommunity_hash.
8198 */
8199 hash_free(aggregate->ecommunity_hash);
8200 }
8201
8202 if (aggregate->lcommunity)
8203 lcommunity_free(&aggregate->lcommunity);
8204
8205 if (aggregate->lcommunity_hash) {
8206 /* Delete all lcommunities in the hash.
8207 */
8208 hash_clean(aggregate->lcommunity_hash,
8209 bgp_aggr_lcommunity_remove);
8210 /* Free up the lcommunity_hash.
8211 */
8212 hash_free(aggregate->lcommunity_hash);
8213 }
8214
8215 if (aggregate->aspath)
8216 aspath_free(aggregate->aspath);
8217
8218 if (aggregate->aspath_hash) {
8219 /* Delete all as-paths in the hash.
8220 */
8221 hash_clean(aggregate->aspath_hash,
8222 bgp_aggr_aspath_remove);
8223 /* Free up the aspath_hash.
8224 */
8225 hash_free(aggregate->aspath_hash);
8226 }
8227
d62a17ae 8228 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8229 bgp_dest_unlock_node(dest);
8230 bgp_dest_unlock_node(dest);
d62a17ae 8231
585f1adc 8232 return CMD_SUCCESS;
d62a17ae 8233}
8234
585f1adc
IR
8235static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8236 safi_t safi, const char *rmap,
8237 uint8_t summary_only, uint8_t as_set,
8238 uint8_t origin, bool match_med,
8239 const char *suppress_map)
d62a17ae 8240{
585f1adc 8241 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8242 int ret;
585f1adc 8243 struct prefix p;
9bcb3eef 8244 struct bgp_dest *dest;
d62a17ae 8245 struct bgp_aggregate *aggregate;
fb29348a 8246 uint8_t as_set_new = as_set;
d62a17ae 8247
365ab2e7 8248 if (suppress_map && summary_only) {
585f1adc 8249 vty_out(vty,
365ab2e7 8250 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8251 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8252 }
8253
585f1adc
IR
8254 /* Convert string to prefix structure. */
8255 ret = str2prefix(prefix_str, &p);
8256 if (!ret) {
8257 vty_out(vty, "Malformed prefix\n");
8258 return CMD_WARNING_CONFIG_FAILED;
8259 }
8260 apply_mask(&p);
d62a17ae 8261
585f1adc
IR
8262 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8263 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8264 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8265 prefix_str);
8266 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8267 }
8268
d62a17ae 8269 /* Old configuration check. */
585f1adc 8270 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8271 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8272
20894f50 8273 if (aggregate) {
585f1adc 8274 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8275 /* try to remove the old entry */
585f1adc 8276 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8277 if (ret) {
585f1adc 8278 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8279 bgp_dest_unlock_node(dest);
585f1adc 8280 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8281 }
8282 }
718e3744 8283
d62a17ae 8284 /* Make aggregate address structure. */
8285 aggregate = bgp_aggregate_new();
8286 aggregate->summary_only = summary_only;
6aabb15d 8287 aggregate->match_med = match_med;
fb29348a
DA
8288
8289 /* Network operators MUST NOT locally generate any new
8290 * announcements containing AS_SET or AS_CONFED_SET. If they have
8291 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8292 * SHOULD withdraw those routes and re-announce routes for the
8293 * aggregate or component prefixes (i.e., the more-specific routes
8294 * subsumed by the previously aggregated route) without AS_SET
8295 * or AS_CONFED_SET in the updates.
8296 */
7f972cd8 8297 if (bgp->reject_as_sets) {
fb29348a
DA
8298 if (as_set == AGGREGATE_AS_SET) {
8299 as_set_new = AGGREGATE_AS_UNSET;
8300 zlog_warn(
63efca0e 8301 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8302 __func__);
585f1adc 8303 vty_out(vty,
fb29348a
DA
8304 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8305 }
8306 }
8307
8308 aggregate->as_set = as_set_new;
d62a17ae 8309 aggregate->safi = safi;
229757f1
DA
8310 /* Override ORIGIN attribute if defined.
8311 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8312 * to IGP which is not what rfc4271 says.
8313 * This enables the same behavior, optionally.
8314 */
8315 aggregate->origin = origin;
20894f50
DA
8316
8317 if (rmap) {
8318 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8319 route_map_counter_decrement(aggregate->rmap.map);
8320 aggregate->rmap.name =
8321 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8322 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8323 route_map_counter_increment(aggregate->rmap.map);
8324 }
365ab2e7
RZ
8325
8326 if (suppress_map) {
8327 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8328 route_map_counter_decrement(aggregate->suppress_map);
8329
8330 aggregate->suppress_map_name =
8331 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8332 aggregate->suppress_map =
8333 route_map_lookup_by_name(aggregate->suppress_map_name);
8334 route_map_counter_increment(aggregate->suppress_map);
8335 }
8336
9bcb3eef 8337 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8338
d62a17ae 8339 /* Aggregate address insert into BGP routing table. */
585f1adc 8340 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8341
585f1adc 8342 return CMD_SUCCESS;
718e3744 8343}
8344
585f1adc
IR
8345DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8346 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8347 "as-set$as_set_s"
8348 "|summary-only$summary_only"
cacba915 8349 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8350 "|origin <egp|igp|incomplete>$origin_s"
8351 "|matching-MED-only$match_med"
cacba915 8352 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8353 "}]",
8354 NO_STR
8355 "Configure BGP aggregate entries\n"
764402fe
DA
8356 "Aggregate prefix\n"
8357 "Aggregate address\n"
8358 "Aggregate mask\n"
585f1adc
IR
8359 "Generate AS set path information\n"
8360 "Filter more specific routes from updates\n"
8361 "Apply route map to aggregate network\n"
8362 "Route map name\n"
8363 "BGP origin code\n"
8364 "Remote EGP\n"
8365 "Local IGP\n"
8366 "Unknown heritage\n"
8367 "Only aggregate routes with matching MED\n"
8368 "Suppress the selected more specific routes\n"
8369 "Route map with the route selectors\n")
8370{
8371 const char *prefix_s = NULL;
554b3b10 8372 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8373 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8374 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8375 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8376
554b3b10 8377 if (addr_str) {
7533cad7
QY
8378 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8379 sizeof(prefix_buf))
554b3b10
RZ
8380 == 0) {
8381 vty_out(vty, "%% Inconsistent address and mask\n");
8382 return CMD_WARNING_CONFIG_FAILED;
8383 }
585f1adc
IR
8384 prefix_s = prefix_buf;
8385 } else
8386 prefix_s = prefix_str;
37a87b8f 8387
585f1adc
IR
8388 if (origin_s) {
8389 if (strcmp(origin_s, "egp") == 0)
8390 origin = BGP_ORIGIN_EGP;
8391 else if (strcmp(origin_s, "igp") == 0)
8392 origin = BGP_ORIGIN_IGP;
8393 else if (strcmp(origin_s, "incomplete") == 0)
8394 origin = BGP_ORIGIN_INCOMPLETE;
8395 }
90e21f35 8396
585f1adc
IR
8397 if (as_set_s)
8398 as_set = AGGREGATE_AS_SET;
554b3b10 8399
585f1adc 8400 /* Handle configuration removal, otherwise installation. */
554b3b10 8401 if (no)
585f1adc
IR
8402 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8403
8404 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8405 summary_only != NULL, as_set, origin,
8406 match_med != NULL, suppress_map);
8407}
8408
8409DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8410 "[no] aggregate-address X:X::X:X/M$prefix [{"
8411 "as-set$as_set_s"
8412 "|summary-only$summary_only"
cacba915 8413 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8414 "|origin <egp|igp|incomplete>$origin_s"
8415 "|matching-MED-only$match_med"
cacba915 8416 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8417 "}]",
8418 NO_STR
8419 "Configure BGP aggregate entries\n"
8420 "Aggregate prefix\n"
8421 "Generate AS set path information\n"
8422 "Filter more specific routes from updates\n"
8423 "Apply route map to aggregate network\n"
8424 "Route map name\n"
8425 "BGP origin code\n"
8426 "Remote EGP\n"
8427 "Local IGP\n"
8428 "Unknown heritage\n"
8429 "Only aggregate routes with matching MED\n"
8430 "Suppress the selected more specific routes\n"
8431 "Route map with the route selectors\n")
8432{
8433 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8434 int as_set = AGGREGATE_AS_UNSET;
8435
8436 if (origin_s) {
8437 if (strcmp(origin_s, "egp") == 0)
8438 origin = BGP_ORIGIN_EGP;
8439 else if (strcmp(origin_s, "igp") == 0)
8440 origin = BGP_ORIGIN_IGP;
8441 else if (strcmp(origin_s, "incomplete") == 0)
8442 origin = BGP_ORIGIN_INCOMPLETE;
8443 }
8444
8445 if (as_set_s)
8446 as_set = AGGREGATE_AS_SET;
8447
8448 /* Handle configuration removal, otherwise installation. */
554b3b10 8449 if (no)
585f1adc
IR
8450 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8451 SAFI_UNICAST);
554b3b10 8452
585f1adc
IR
8453 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8454 rmap_name, summary_only != NULL, as_set,
8455 origin, match_med != NULL, suppress_map);
718e3744 8456}
8457
718e3744 8458/* Redistribute route treatment. */
d62a17ae 8459void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8460 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8461 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8462 enum blackhole_type bhtype, uint32_t metric,
8463 uint8_t type, unsigned short instance,
8464 route_tag_t tag)
d62a17ae 8465{
4b7e6066 8466 struct bgp_path_info *new;
40381db7
DS
8467 struct bgp_path_info *bpi;
8468 struct bgp_path_info rmap_path;
9bcb3eef 8469 struct bgp_dest *bn;
d62a17ae 8470 struct attr attr;
8471 struct attr *new_attr;
8472 afi_t afi;
b68885f9 8473 route_map_result_t ret;
d62a17ae 8474 struct bgp_redist *red;
8475
8476 /* Make default attribute. */
0f05ea43 8477 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8478 /*
8479 * This must not be NULL to satisfy Coverity SA
8480 */
8481 assert(attr.aspath);
9de1f7ff 8482
a4d82a8a 8483 switch (nhtype) {
9de1f7ff 8484 case NEXTHOP_TYPE_IFINDEX:
6fc4929e
PG
8485 switch (p->family) {
8486 case AF_INET:
8487 attr.nexthop.s_addr = INADDR_ANY;
8488 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
8489 break;
8490 case AF_INET6:
8491 memset(&attr.mp_nexthop_global, 0,
8492 sizeof(attr.mp_nexthop_global));
8493 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8494 break;
8495 }
9de1f7ff
DS
8496 break;
8497 case NEXTHOP_TYPE_IPV4:
8498 case NEXTHOP_TYPE_IPV4_IFINDEX:
8499 attr.nexthop = nexthop->ipv4;
7226bc40 8500 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8501 break;
8502 case NEXTHOP_TYPE_IPV6:
8503 case NEXTHOP_TYPE_IPV6_IFINDEX:
8504 attr.mp_nexthop_global = nexthop->ipv6;
8505 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8506 break;
8507 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8508 switch (p->family) {
8509 case AF_INET:
9de1f7ff 8510 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8511 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8512 break;
8513 case AF_INET6:
9de1f7ff
DS
8514 memset(&attr.mp_nexthop_global, 0,
8515 sizeof(attr.mp_nexthop_global));
74489921 8516 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8517 break;
74489921 8518 }
0789eb69 8519 attr.bh_type = bhtype;
9de1f7ff 8520 break;
d62a17ae 8521 }
0789eb69 8522 attr.nh_type = nhtype;
74489921 8523 attr.nh_ifindex = ifindex;
f04a80a5 8524
d62a17ae 8525 attr.med = metric;
957f74c3 8526 attr.distance = distance;
d62a17ae 8527 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8528 attr.tag = tag;
718e3744 8529
d62a17ae 8530 afi = family2afi(p->family);
6aeb9e78 8531
d62a17ae 8532 red = bgp_redist_lookup(bgp, afi, type, instance);
8533 if (red) {
8534 struct attr attr_new;
718e3744 8535
d62a17ae 8536 /* Copy attribute for modification. */
6f4f49b2 8537 attr_new = attr;
718e3744 8538
d62a17ae 8539 if (red->redist_metric_flag)
8540 attr_new.med = red->redist_metric;
718e3744 8541
d62a17ae 8542 /* Apply route-map. */
8543 if (red->rmap.name) {
6006b807 8544 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8545 rmap_path.peer = bgp->peer_self;
8546 rmap_path.attr = &attr_new;
718e3744 8547
d62a17ae 8548 SET_FLAG(bgp->peer_self->rmap_type,
8549 PEER_RMAP_TYPE_REDISTRIBUTE);
8550
1782514f 8551 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8552
8553 bgp->peer_self->rmap_type = 0;
8554
8555 if (ret == RMAP_DENYMATCH) {
8556 /* Free uninterned attribute. */
8557 bgp_attr_flush(&attr_new);
8558
8559 /* Unintern original. */
8560 aspath_unintern(&attr.aspath);
8561 bgp_redistribute_delete(bgp, p, type, instance);
8562 return;
8563 }
8564 }
8565
637e5ba4 8566 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8567 bgp_attr_add_gshut_community(&attr_new);
8568
d62a17ae 8569 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8570 SAFI_UNICAST, p, NULL);
8571
8572 new_attr = bgp_attr_intern(&attr_new);
8573
9bcb3eef 8574 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8575 if (bpi->peer == bgp->peer_self
8576 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8577 break;
8578
40381db7 8579 if (bpi) {
d62a17ae 8580 /* Ensure the (source route) type is updated. */
40381db7
DS
8581 bpi->type = type;
8582 if (attrhash_cmp(bpi->attr, new_attr)
8583 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8584 bgp_attr_unintern(&new_attr);
8585 aspath_unintern(&attr.aspath);
9bcb3eef 8586 bgp_dest_unlock_node(bn);
d62a17ae 8587 return;
8588 } else {
8589 /* The attribute is changed. */
40381db7 8590 bgp_path_info_set_flag(bn, bpi,
18ee8310 8591 BGP_PATH_ATTR_CHANGED);
d62a17ae 8592
8593 /* Rewrite BGP route information. */
40381db7
DS
8594 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8595 bgp_path_info_restore(bn, bpi);
d62a17ae 8596 else
40381db7
DS
8597 bgp_aggregate_decrement(
8598 bgp, p, bpi, afi, SAFI_UNICAST);
8599 bgp_attr_unintern(&bpi->attr);
8600 bpi->attr = new_attr;
083ec940 8601 bpi->uptime = monotime(NULL);
d62a17ae 8602
8603 /* Process change. */
40381db7 8604 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8605 SAFI_UNICAST);
8606 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8607 bgp_dest_unlock_node(bn);
d62a17ae 8608 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8609
8610 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8611 || (bgp->inst_type
8612 == BGP_INSTANCE_TYPE_DEFAULT)) {
8613
8614 vpn_leak_from_vrf_update(
40381db7 8615 bgp_get_default(), bgp, bpi);
ddb5b488 8616 }
d62a17ae 8617 return;
8618 }
8619 }
8620
8621 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8622 bgp->peer_self, new_attr, bn);
1defdda8 8623 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8624
8625 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8626 bgp_path_info_add(bn, new);
9bcb3eef 8627 bgp_dest_unlock_node(bn);
be785e35 8628 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8629 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8630
8631 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8632 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8633
8634 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8635 }
d62a17ae 8636 }
8637
8638 /* Unintern original. */
8639 aspath_unintern(&attr.aspath);
718e3744 8640}
8641
d7c0a89a
QY
8642void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8643 unsigned short instance)
718e3744 8644{
d62a17ae 8645 afi_t afi;
9bcb3eef 8646 struct bgp_dest *dest;
40381db7 8647 struct bgp_path_info *pi;
d62a17ae 8648 struct bgp_redist *red;
718e3744 8649
d62a17ae 8650 afi = family2afi(p->family);
718e3744 8651
d62a17ae 8652 red = bgp_redist_lookup(bgp, afi, type, instance);
8653 if (red) {
9bcb3eef
DS
8654 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8655 SAFI_UNICAST, p, NULL);
d62a17ae 8656
9bcb3eef 8657 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8658 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8659 break;
8660
40381db7 8661 if (pi) {
ddb5b488
PZ
8662 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8663 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8664
8665 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8666 bgp, pi);
ddb5b488 8667 }
40381db7 8668 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8669 bgp_path_info_delete(dest, pi);
8670 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8671 }
9bcb3eef 8672 bgp_dest_unlock_node(dest);
d62a17ae 8673 }
8674}
8675
8676/* Withdraw specified route type's route. */
8677void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8678 unsigned short instance)
d62a17ae 8679{
9bcb3eef 8680 struct bgp_dest *dest;
40381db7 8681 struct bgp_path_info *pi;
d62a17ae 8682 struct bgp_table *table;
8683
8684 table = bgp->rib[afi][SAFI_UNICAST];
8685
9bcb3eef
DS
8686 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8687 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8688 if (pi->peer == bgp->peer_self && pi->type == type
8689 && pi->instance == instance)
d62a17ae 8690 break;
8691
40381db7 8692 if (pi) {
ddb5b488
PZ
8693 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8694 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8695
8696 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8697 bgp, pi);
ddb5b488 8698 }
9bcb3eef 8699 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8700 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8701 bgp_path_info_delete(dest, pi);
8702 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8703 }
718e3744 8704 }
718e3744 8705}
6b0655a2 8706
718e3744 8707/* Static function to display route. */
7d3cae70
DA
8708static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8709 struct vty *vty, json_object *json, bool wide)
718e3744 8710{
be054588 8711 int len = 0;
d62a17ae 8712 char buf[BUFSIZ];
718e3744 8713
d62a17ae 8714 if (p->family == AF_INET) {
c6462ff4 8715 if (!json) {
8228a9a7 8716 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8717 } else {
8718 json_object_string_add(json, "prefix",
8719 inet_ntop(p->family,
8720 &p->u.prefix, buf,
8721 BUFSIZ));
8722 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8723 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8724 json_object_int_add(json, "version", dest->version);
c6462ff4 8725 }
d62a17ae 8726 } else if (p->family == AF_ETHERNET) {
8228a9a7 8727 len = vty_out(vty, "%pFX", p);
b03b8898 8728 } else if (p->family == AF_EVPN) {
57f7feb6 8729 if (!json)
2dbe669b 8730 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8731 else
60466a63 8732 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8733 } else if (p->family == AF_FLOWSPEC) {
8734 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8735 json ?
8736 NLRI_STRING_FORMAT_JSON_SIMPLE :
8737 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8738 } else {
c6462ff4 8739 if (!json)
8228a9a7 8740 len = vty_out(vty, "%pFX", p);
50e05855
AD
8741 else {
8742 json_object_string_add(json, "prefix",
8743 inet_ntop(p->family,
8744 &p->u.prefix, buf,
8745 BUFSIZ));
8746 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8747 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8748 json_object_int_add(json, "version", dest->version);
37d4e0df 8749 }
9c92b5f7 8750 }
d62a17ae 8751
9c92b5f7 8752 if (!json) {
ae248832 8753 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8754 if (len < 1)
8755 vty_out(vty, "\n%*s", 20, " ");
8756 else
8757 vty_out(vty, "%*s", len, " ");
8758 }
718e3744 8759}
8760
d62a17ae 8761enum bgp_display_type {
8762 normal_list,
718e3744 8763};
8764
1d7260a1 8765const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8766{
8767 switch (reason) {
8768 case bgp_path_selection_none:
8769 return "Nothing to Select";
8770 case bgp_path_selection_first:
8771 return "First path received";
8772 case bgp_path_selection_evpn_sticky_mac:
8773 return "EVPN Sticky Mac";
8774 case bgp_path_selection_evpn_seq:
8775 return "EVPN sequence number";
8776 case bgp_path_selection_evpn_lower_ip:
8777 return "EVPN lower IP";
8778 case bgp_path_selection_evpn_local_path:
8779 return "EVPN local ES path";
8780 case bgp_path_selection_evpn_non_proxy:
8781 return "EVPN non proxy";
8782 case bgp_path_selection_weight:
8783 return "Weight";
8784 case bgp_path_selection_local_pref:
8785 return "Local Pref";
8786 case bgp_path_selection_local_route:
8787 return "Local Route";
8788 case bgp_path_selection_confed_as_path:
8789 return "Confederation based AS Path";
8790 case bgp_path_selection_as_path:
8791 return "AS Path";
8792 case bgp_path_selection_origin:
8793 return "Origin";
8794 case bgp_path_selection_med:
8795 return "MED";
8796 case bgp_path_selection_peer:
8797 return "Peer Type";
8798 case bgp_path_selection_confed:
8799 return "Confed Peer Type";
8800 case bgp_path_selection_igp_metric:
8801 return "IGP Metric";
8802 case bgp_path_selection_older:
8803 return "Older Path";
8804 case bgp_path_selection_router_id:
8805 return "Router ID";
8806 case bgp_path_selection_cluster_length:
bcab253c 8807 return "Cluster length";
bbb46eb5
DA
8808 case bgp_path_selection_stale:
8809 return "Path Staleness";
8810 case bgp_path_selection_local_configured:
8811 return "Locally configured route";
8812 case bgp_path_selection_neighbor_ip:
8813 return "Neighbor IP";
8814 case bgp_path_selection_default:
8815 return "Nothing left to compare";
8816 }
8817 return "Invalid (internal error)";
8818}
8819
18ee8310 8820/* Print the short form route status for a bgp_path_info */
4b7e6066 8821static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8822 struct bgp_path_info *path,
82c298be 8823 const struct prefix *p,
d62a17ae 8824 json_object *json_path)
718e3744 8825{
82c298be
DA
8826 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8827
d62a17ae 8828 if (json_path) {
b05a1c8b 8829
d62a17ae 8830 /* Route status display. */
9b6d8fcf 8831 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8832 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8833
9b6d8fcf 8834 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8835 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8836
4056a5f6 8837 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8838 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8839
9b6d8fcf
DS
8840 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8841 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8842 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8843
d62a17ae 8844 /* Selected */
9b6d8fcf 8845 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8846 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8847
9b6d8fcf 8848 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8849 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8850
bbb46eb5 8851 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8852 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8853 json_object_string_add(json_path, "selectionReason",
8854 bgp_path_selection_reason2str(
8855 path->net->reason));
8856 }
b05a1c8b 8857
9b6d8fcf 8858 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8859 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8860
d62a17ae 8861 /* Internal route. */
9b6d8fcf
DS
8862 if ((path->peer->as)
8863 && (path->peer->as == path->peer->local_as))
d62a17ae 8864 json_object_string_add(json_path, "pathFrom",
8865 "internal");
8866 else
8867 json_object_string_add(json_path, "pathFrom",
8868 "external");
b05a1c8b 8869
d62a17ae 8870 return;
8871 }
b05a1c8b 8872
82c298be
DA
8873 /* RPKI validation state */
8874 rpki_state =
8875 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8876
8877 if (rpki_state == RPKI_VALID)
8878 vty_out(vty, "V");
8879 else if (rpki_state == RPKI_INVALID)
8880 vty_out(vty, "I");
8881 else if (rpki_state == RPKI_NOTFOUND)
8882 vty_out(vty, "N");
8883
d62a17ae 8884 /* Route status display. */
9b6d8fcf 8885 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8886 vty_out(vty, "R");
9b6d8fcf 8887 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8888 vty_out(vty, "S");
4056a5f6 8889 else if (bgp_path_suppressed(path))
d62a17ae 8890 vty_out(vty, "s");
9b6d8fcf
DS
8891 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8892 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8893 vty_out(vty, "*");
8894 else
8895 vty_out(vty, " ");
8896
8897 /* Selected */
9b6d8fcf 8898 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8899 vty_out(vty, "h");
9b6d8fcf 8900 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8901 vty_out(vty, "d");
9b6d8fcf 8902 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8903 vty_out(vty, ">");
9b6d8fcf 8904 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8905 vty_out(vty, "=");
8906 else
8907 vty_out(vty, " ");
718e3744 8908
d62a17ae 8909 /* Internal route. */
9b6d8fcf
DS
8910 if (path->peer && (path->peer->as)
8911 && (path->peer->as == path->peer->local_as))
d62a17ae 8912 vty_out(vty, "i");
8913 else
8914 vty_out(vty, " ");
b40d939b 8915}
8916
2ba93fd6
DA
8917static char *bgp_nexthop_hostname(struct peer *peer,
8918 struct bgp_nexthop_cache *bnc)
25b5da8d 8919{
892fedb6 8920 if (peer->hostname
aef999a2 8921 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8922 return peer->hostname;
8923 return NULL;
8924}
8925
b40d939b 8926/* called from terminal list command */
bd494ec5 8927void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8928 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8929 json_object *json_paths, bool wide)
d62a17ae 8930{
aef999a2 8931 int len;
515c2602 8932 struct attr *attr = path->attr;
d62a17ae 8933 json_object *json_path = NULL;
8934 json_object *json_nexthops = NULL;
8935 json_object *json_nexthop_global = NULL;
8936 json_object *json_nexthop_ll = NULL;
6f214dd3 8937 json_object *json_ext_community = NULL;
9df8b37c 8938 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8939 bool nexthop_self =
9b6d8fcf 8940 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8941 bool nexthop_othervrf = false;
43089216 8942 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8943 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8944 char *nexthop_hostname =
8945 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8946 char esi_buf[ESI_STR_LEN];
d62a17ae 8947
8948 if (json_paths)
8949 json_path = json_object_new_object();
8950
8951 /* short status lead text */
82c298be 8952 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8953
8954 if (!json_paths) {
8955 /* print prefix and mask */
8956 if (!display)
7d3cae70 8957 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8958 else
ae248832 8959 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8960 } else {
7d3cae70 8961 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8962 }
47fc97cc 8963
9df8b37c
PZ
8964 /*
8965 * If vrf id of nexthop is different from that of prefix,
8966 * set up printable string to append
8967 */
9b6d8fcf 8968 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8969 const char *self = "";
8970
8971 if (nexthop_self)
8972 self = "<";
8973
8974 nexthop_othervrf = true;
9b6d8fcf 8975 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8976
9b6d8fcf 8977 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8978 snprintf(vrf_id_str, sizeof(vrf_id_str),
8979 "@%s%s", VRFID_NONE_STR, self);
8980 else
8981 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8982 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8983
9b6d8fcf
DS
8984 if (path->extra->bgp_orig->inst_type
8985 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8986
9b6d8fcf 8987 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8988 } else {
8989 const char *self = "";
8990
8991 if (nexthop_self)
8992 self = "<";
8993
8994 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8995 }
8996
445c2480
DS
8997 /*
8998 * For ENCAP and EVPN routes, nexthop address family is not
8999 * neccessarily the same as the prefix address family.
9000 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
9001 * EVPN routes are also exchanged with a MP nexthop. Currently,
9002 * this
9003 * is only IPv4, the value will be present in either
9004 * attr->nexthop or
9005 * attr->mp_nexthop_global_in
9006 */
9007 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
9008 char buf[BUFSIZ];
9009 char nexthop[128];
9010 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
9011
9012 switch (af) {
9013 case AF_INET:
772270f3
QY
9014 snprintf(nexthop, sizeof(nexthop), "%s",
9015 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
9016 BUFSIZ));
445c2480
DS
9017 break;
9018 case AF_INET6:
772270f3
QY
9019 snprintf(nexthop, sizeof(nexthop), "%s",
9020 inet_ntop(af, &attr->mp_nexthop_global, buf,
9021 BUFSIZ));
445c2480
DS
9022 break;
9023 default:
772270f3 9024 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 9025 break;
d62a17ae 9026 }
d62a17ae 9027
445c2480
DS
9028 if (json_paths) {
9029 json_nexthop_global = json_object_new_object();
9030
515c2602
DA
9031 json_object_string_add(json_nexthop_global, "ip",
9032 nexthop);
9033
939a97f4 9034 if (path->peer->hostname)
515c2602
DA
9035 json_object_string_add(json_nexthop_global,
9036 "hostname",
939a97f4 9037 path->peer->hostname);
515c2602
DA
9038
9039 json_object_string_add(json_nexthop_global, "afi",
9040 (af == AF_INET) ? "ipv4"
9041 : "ipv6");
445c2480
DS
9042 json_object_boolean_true_add(json_nexthop_global,
9043 "used");
aef999a2
DA
9044 } else {
9045 if (nexthop_hostname)
9046 len = vty_out(vty, "%s(%s)%s", nexthop,
9047 nexthop_hostname, vrf_id_str);
9048 else
9049 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9050
ae248832 9051 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9052 if (len < 1)
9053 vty_out(vty, "\n%*s", 36, " ");
9054 else
9055 vty_out(vty, "%*s", len, " ");
9056 }
445c2480
DS
9057 } else if (safi == SAFI_EVPN) {
9058 if (json_paths) {
9059 json_nexthop_global = json_object_new_object();
9060
c949c771 9061 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9062 "%pI4",
9063 &attr->mp_nexthop_global_in);
515c2602 9064
939a97f4 9065 if (path->peer->hostname)
515c2602
DA
9066 json_object_string_add(json_nexthop_global,
9067 "hostname",
939a97f4 9068 path->peer->hostname);
515c2602 9069
a4d82a8a
PZ
9070 json_object_string_add(json_nexthop_global, "afi",
9071 "ipv4");
445c2480
DS
9072 json_object_boolean_true_add(json_nexthop_global,
9073 "used");
aef999a2
DA
9074 } else {
9075 if (nexthop_hostname)
7226bc40
TA
9076 len = vty_out(vty, "%pI4(%s)%s",
9077 &attr->mp_nexthop_global_in,
aef999a2
DA
9078 nexthop_hostname, vrf_id_str);
9079 else
7226bc40
TA
9080 len = vty_out(vty, "%pI4%s",
9081 &attr->mp_nexthop_global_in,
aef999a2
DA
9082 vrf_id_str);
9083
ae248832 9084 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9085 if (len < 1)
9086 vty_out(vty, "\n%*s", 36, " ");
9087 else
9088 vty_out(vty, "%*s", len, " ");
9089 }
d33fc23b 9090 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9091 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9092 if (json_paths) {
9093 json_nexthop_global = json_object_new_object();
515c2602 9094
026b914a
PG
9095 json_object_string_add(json_nexthop_global,
9096 "afi", "ipv4");
c949c771
DA
9097 json_object_string_addf(json_nexthop_global,
9098 "ip", "%pI4",
9099 &attr->nexthop);
515c2602 9100
939a97f4 9101 if (path->peer->hostname)
515c2602
DA
9102 json_object_string_add(
9103 json_nexthop_global, "hostname",
939a97f4 9104 path->peer->hostname);
515c2602 9105
50e05855
AD
9106 json_object_boolean_true_add(
9107 json_nexthop_global,
026b914a
PG
9108 "used");
9109 } else {
aef999a2
DA
9110 if (nexthop_hostname)
9111 len = vty_out(vty, "%pI4(%s)%s",
9112 &attr->nexthop,
9113 nexthop_hostname,
9114 vrf_id_str);
9115 else
9116 len = vty_out(vty, "%pI4%s",
9117 &attr->nexthop,
9118 vrf_id_str);
9119
ae248832 9120 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9121 if (len < 1)
9122 vty_out(vty, "\n%*s", 36, " ");
9123 else
9124 vty_out(vty, "%*s", len, " ");
026b914a
PG
9125 }
9126 }
7226bc40 9127 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9128 if (json_paths) {
9129 json_nexthop_global = json_object_new_object();
d62a17ae 9130
c949c771
DA
9131 json_object_string_addf(json_nexthop_global, "ip",
9132 "%pI4", &attr->nexthop);
515c2602 9133
939a97f4 9134 if (path->peer->hostname)
515c2602
DA
9135 json_object_string_add(json_nexthop_global,
9136 "hostname",
939a97f4 9137 path->peer->hostname);
445c2480 9138
a4d82a8a
PZ
9139 json_object_string_add(json_nexthop_global, "afi",
9140 "ipv4");
445c2480
DS
9141 json_object_boolean_true_add(json_nexthop_global,
9142 "used");
9143 } else {
aef999a2
DA
9144 if (nexthop_hostname)
9145 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9146 nexthop_hostname, vrf_id_str);
9147 else
9148 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9149 vrf_id_str);
9df8b37c 9150
ae248832 9151 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9152 if (len < 1)
9153 vty_out(vty, "\n%*s", 36, " ");
9154 else
9155 vty_out(vty, "%*s", len, " ");
d62a17ae 9156 }
445c2480 9157 }
b05a1c8b 9158
445c2480 9159 /* IPv6 Next Hop */
7226bc40 9160 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9161 if (json_paths) {
9162 json_nexthop_global = json_object_new_object();
c949c771
DA
9163 json_object_string_addf(json_nexthop_global, "ip",
9164 "%pI6",
9165 &attr->mp_nexthop_global);
515c2602 9166
939a97f4 9167 if (path->peer->hostname)
515c2602
DA
9168 json_object_string_add(json_nexthop_global,
9169 "hostname",
939a97f4 9170 path->peer->hostname);
515c2602 9171
a4d82a8a
PZ
9172 json_object_string_add(json_nexthop_global, "afi",
9173 "ipv6");
9174 json_object_string_add(json_nexthop_global, "scope",
9175 "global");
445c2480
DS
9176
9177 /* We display both LL & GL if both have been
9178 * received */
0606039c
DA
9179 if ((attr->mp_nexthop_len
9180 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9181 || (path->peer->conf_if)) {
a4d82a8a 9182 json_nexthop_ll = json_object_new_object();
c949c771
DA
9183 json_object_string_addf(
9184 json_nexthop_ll, "ip", "%pI6",
9185 &attr->mp_nexthop_local);
515c2602 9186
939a97f4 9187 if (path->peer->hostname)
515c2602
DA
9188 json_object_string_add(
9189 json_nexthop_ll, "hostname",
939a97f4 9190 path->peer->hostname);
515c2602 9191
a4d82a8a
PZ
9192 json_object_string_add(json_nexthop_ll, "afi",
9193 "ipv6");
9194 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9195 "link-local");
d62a17ae 9196
a4d82a8a
PZ
9197 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9198 &attr->mp_nexthop_local)
445c2480
DS
9199 != 0)
9200 && !attr->mp_nexthop_prefer_global)
d62a17ae 9201 json_object_boolean_true_add(
a4d82a8a 9202 json_nexthop_ll, "used");
445c2480
DS
9203 else
9204 json_object_boolean_true_add(
a4d82a8a 9205 json_nexthop_global, "used");
445c2480
DS
9206 } else
9207 json_object_boolean_true_add(
9208 json_nexthop_global, "used");
9209 } else {
9210 /* Display LL if LL/Global both in table unless
9211 * prefer-global is set */
0606039c
DA
9212 if (((attr->mp_nexthop_len
9213 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9214 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9215 || (path->peer->conf_if)) {
9216 if (path->peer->conf_if) {
a4d82a8a 9217 len = vty_out(vty, "%s",
9b6d8fcf 9218 path->peer->conf_if);
ae248832
MK
9219 /* len of IPv6 addr + max len of def
9220 * ifname */
9221 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9222
9223 if (len < 1)
a4d82a8a 9224 vty_out(vty, "\n%*s", 36, " ");
445c2480 9225 else
a4d82a8a 9226 vty_out(vty, "%*s", len, " ");
d62a17ae 9227 } else {
aef999a2
DA
9228 if (nexthop_hostname)
9229 len = vty_out(
9230 vty, "%pI6(%s)%s",
9231 &attr->mp_nexthop_local,
9232 nexthop_hostname,
9233 vrf_id_str);
9234 else
9235 len = vty_out(
9236 vty, "%pI6%s",
9237 &attr->mp_nexthop_local,
9238 vrf_id_str);
9239
ae248832 9240 len = wide ? (41 - len) : (16 - len);
d62a17ae 9241
9242 if (len < 1)
a4d82a8a 9243 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9244 else
a4d82a8a 9245 vty_out(vty, "%*s", len, " ");
d62a17ae 9246 }
445c2480 9247 } else {
aef999a2
DA
9248 if (nexthop_hostname)
9249 len = vty_out(vty, "%pI6(%s)%s",
9250 &attr->mp_nexthop_global,
9251 nexthop_hostname,
9252 vrf_id_str);
9253 else
9254 len = vty_out(vty, "%pI6%s",
9255 &attr->mp_nexthop_global,
9256 vrf_id_str);
9257
ae248832 9258 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9259
9260 if (len < 1)
9261 vty_out(vty, "\n%*s", 36, " ");
9262 else
9263 vty_out(vty, "%*s", len, " ");
d62a17ae 9264 }
9265 }
445c2480 9266 }
718e3744 9267
445c2480
DS
9268 /* MED/Metric */
9269 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9270 if (json_paths)
50e05855 9271 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9272 else if (wide)
9273 vty_out(vty, "%7u", attr->med);
0fbac0b4 9274 else
445c2480 9275 vty_out(vty, "%10u", attr->med);
ae248832
MK
9276 else if (!json_paths) {
9277 if (wide)
9278 vty_out(vty, "%*s", 7, " ");
9279 else
9280 vty_out(vty, "%*s", 10, " ");
9281 }
d62a17ae 9282
445c2480
DS
9283 /* Local Pref */
9284 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9285 if (json_paths)
50e05855 9286 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9287 attr->local_pref);
9288 else
445c2480
DS
9289 vty_out(vty, "%7u", attr->local_pref);
9290 else if (!json_paths)
9291 vty_out(vty, " ");
d62a17ae 9292
445c2480
DS
9293 if (json_paths)
9294 json_object_int_add(json_path, "weight", attr->weight);
9295 else
9296 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9297
47e12884
DA
9298 if (json_paths)
9299 json_object_string_addf(json_path, "peerId", "%pSU",
9300 &path->peer->su);
b05a1c8b 9301
445c2480
DS
9302 /* Print aspath */
9303 if (attr->aspath) {
0fbac0b4 9304 if (json_paths)
50e05855 9305 json_object_string_add(json_path, "path",
0fbac0b4
DA
9306 attr->aspath->str);
9307 else
445c2480 9308 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9309 }
f1aa5d8a 9310
445c2480
DS
9311 /* Print origin */
9312 if (json_paths)
a4d82a8a
PZ
9313 json_object_string_add(json_path, "origin",
9314 bgp_origin_long_str[attr->origin]);
445c2480
DS
9315 else
9316 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9317
9df8b37c 9318 if (json_paths) {
d071f237 9319 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9320 json_object_string_add(json_path, "esi",
9321 esi_to_str(&attr->esi,
9322 esi_buf, sizeof(esi_buf)));
9323 }
6f214dd3
CS
9324 if (safi == SAFI_EVPN &&
9325 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9326 json_ext_community = json_object_new_object();
b53e67a3
DA
9327 json_object_string_add(
9328 json_ext_community, "string",
9329 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9330 json_object_object_add(json_path,
9331 "extendedCommunity",
9332 json_ext_community);
9333 }
9334
9df8b37c
PZ
9335 if (nexthop_self)
9336 json_object_boolean_true_add(json_path,
9337 "announceNexthopSelf");
9338 if (nexthop_othervrf) {
9339 json_object_string_add(json_path, "nhVrfName",
9340 nexthop_vrfname);
9341
9342 json_object_int_add(json_path, "nhVrfId",
9343 ((nexthop_vrfid == VRF_UNKNOWN)
9344 ? -1
9345 : (int)nexthop_vrfid));
9346 }
9347 }
9348
d62a17ae 9349 if (json_paths) {
9350 if (json_nexthop_global || json_nexthop_ll) {
9351 json_nexthops = json_object_new_array();
f1aa5d8a 9352
d62a17ae 9353 if (json_nexthop_global)
9354 json_object_array_add(json_nexthops,
9355 json_nexthop_global);
f1aa5d8a 9356
d62a17ae 9357 if (json_nexthop_ll)
9358 json_object_array_add(json_nexthops,
9359 json_nexthop_ll);
f1aa5d8a 9360
d62a17ae 9361 json_object_object_add(json_path, "nexthops",
9362 json_nexthops);
9363 }
9364
9365 json_object_array_add(json_paths, json_path);
9366 } else {
9367 vty_out(vty, "\n");
6f214dd3 9368
b5e140c8 9369 if (safi == SAFI_EVPN) {
d071f237 9370 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9371 /* XXX - add these params to the json out */
b5e140c8 9372 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9373 vty_out(vty, "ESI:%s",
9374 esi_to_str(&attr->esi, esi_buf,
9375 sizeof(esi_buf)));
60605cbc 9376
229587fb 9377 vty_out(vty, "\n");
b5e140c8
AK
9378 }
9379 if (attr->flag &
9380 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9381 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9382 vty_out(vty, "%s\n",
9383 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9384 }
6f214dd3
CS
9385 }
9386
49e5a4a0 9387#ifdef ENABLE_BGP_VNC
d62a17ae 9388 /* prints an additional line, indented, with VNC info, if
9389 * present */
9390 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9391 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9392#endif
d62a17ae 9393 }
9394}
718e3744 9395
9396/* called from terminal list command */
7d3cae70
DA
9397void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9398 const struct prefix *p, struct attr *attr, safi_t safi,
9399 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9400{
9401 json_object *json_status = NULL;
9402 json_object *json_net = NULL;
aef999a2 9403 int len;
d62a17ae 9404 char buff[BUFSIZ];
dc387b0f 9405
d62a17ae 9406 /* Route status display. */
9407 if (use_json) {
9408 json_status = json_object_new_object();
9409 json_net = json_object_new_object();
9410 } else {
9411 vty_out(vty, "*");
9412 vty_out(vty, ">");
9413 vty_out(vty, " ");
9414 }
718e3744 9415
d62a17ae 9416 /* print prefix and mask */
50e05855 9417 if (use_json) {
dc387b0f
LK
9418 if (safi == SAFI_EVPN)
9419 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9420 else if (p->family == AF_INET || p->family == AF_INET6) {
9421 json_object_string_add(
9422 json_net, "addrPrefix",
9423 inet_ntop(p->family, &p->u.prefix, buff,
9424 BUFSIZ));
9425 json_object_int_add(json_net, "prefixLen",
9426 p->prefixlen);
67d7e256 9427 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9428 }
50e05855 9429 } else
7d3cae70 9430 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9431
9432 /* Print attribute */
9433 if (attr) {
9434 if (use_json) {
7226bc40
TA
9435 if (p->family == AF_INET &&
9436 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9437 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9438 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9439 json_object_string_addf(
9440 json_net, "nextHop", "%pI4",
9441 &attr->mp_nexthop_global_in);
d62a17ae 9442 else
c949c771
DA
9443 json_object_string_addf(
9444 json_net, "nextHop", "%pI4",
9445 &attr->nexthop);
7226bc40
TA
9446 } else if (p->family == AF_INET6 ||
9447 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9448 json_object_string_addf(
9449 json_net, "nextHopGlobal", "%pI6",
9450 &attr->mp_nexthop_global);
7226bc40
TA
9451 } else if (p->family == AF_EVPN &&
9452 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9453 json_object_string_addf(
9454 json_net, "nextHop", "%pI4",
9455 &attr->mp_nexthop_global_in);
23d0a753 9456 }
d62a17ae 9457
9458 if (attr->flag
9459 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9460 json_object_int_add(json_net, "metric",
9461 attr->med);
9462
0fbac0b4 9463 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9464 json_object_int_add(json_net, "locPrf",
0fbac0b4 9465 attr->local_pref);
d62a17ae 9466
9467 json_object_int_add(json_net, "weight", attr->weight);
9468
9469 /* Print aspath */
0fbac0b4 9470 if (attr->aspath)
50e05855 9471 json_object_string_add(json_net, "path",
0fbac0b4 9472 attr->aspath->str);
d62a17ae 9473
9474 /* Print origin */
9475 json_object_string_add(json_net, "bgpOriginCode",
9476 bgp_origin_str[attr->origin]);
9477 } else {
7226bc40
TA
9478 if (p->family == AF_INET &&
9479 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9480 safi == SAFI_EVPN ||
9481 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9482 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9483 || safi == SAFI_EVPN)
23d0a753
DA
9484 vty_out(vty, "%-16pI4",
9485 &attr->mp_nexthop_global_in);
ae248832 9486 else if (wide)
23d0a753 9487 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9488 else
23d0a753 9489 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9490 } else if (p->family == AF_INET6 ||
9491 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9492 char buf[BUFSIZ];
9493
9494 len = vty_out(
9495 vty, "%s",
9496 inet_ntop(AF_INET6,
9497 &attr->mp_nexthop_global, buf,
9498 BUFSIZ));
ae248832 9499 len = wide ? (41 - len) : (16 - len);
d62a17ae 9500 if (len < 1)
9501 vty_out(vty, "\n%*s", 36, " ");
9502 else
9503 vty_out(vty, "%*s", len, " ");
9504 }
9505 if (attr->flag
9506 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9507 if (wide)
9508 vty_out(vty, "%7u", attr->med);
9509 else
9510 vty_out(vty, "%10u", attr->med);
9511 else if (wide)
9512 vty_out(vty, " ");
d62a17ae 9513 else
9514 vty_out(vty, " ");
718e3744 9515
d62a17ae 9516 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9517 vty_out(vty, "%7u", attr->local_pref);
9518 else
9519 vty_out(vty, " ");
9520
9521 vty_out(vty, "%7u ", attr->weight);
9522
9523 /* Print aspath */
9524 if (attr->aspath)
9525 aspath_print_vty(vty, "%s", attr->aspath, " ");
9526
9527 /* Print origin */
9528 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9529 }
9530 }
9531 if (use_json) {
9532 json_object_boolean_true_add(json_status, "*");
9533 json_object_boolean_true_add(json_status, ">");
9534 json_object_object_add(json_net, "appliedStatusSymbols",
9535 json_status);
511211bf 9536 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9537 } else
9538 vty_out(vty, "\n");
9539}
9540
bd494ec5 9541void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9542 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9543 json_object *json)
9544{
9545 json_object *json_out = NULL;
9546 struct attr *attr;
9547 mpls_label_t label = MPLS_INVALID_LABEL;
9548
9b6d8fcf 9549 if (!path->extra)
d62a17ae 9550 return;
9551
9552 if (json)
9553 json_out = json_object_new_object();
9554
9555 /* short status lead text */
82c298be 9556 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9557
9558 /* print prefix and mask */
9559 if (json == NULL) {
9560 if (!display)
7d3cae70 9561 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9562 else
9563 vty_out(vty, "%*s", 17, " ");
9564 }
9565
9566 /* Print attribute */
9b6d8fcf 9567 attr = path->attr;
7226bc40
TA
9568 if (((p->family == AF_INET) &&
9569 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9570 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9571 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9572 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9573 || safi == SAFI_EVPN) {
9574 if (json)
c949c771
DA
9575 json_object_string_addf(
9576 json_out, "mpNexthopGlobalIn", "%pI4",
9577 &attr->mp_nexthop_global_in);
05864da7 9578 else
23d0a753
DA
9579 vty_out(vty, "%-16pI4",
9580 &attr->mp_nexthop_global_in);
05864da7
DS
9581 } else {
9582 if (json)
c949c771
DA
9583 json_object_string_addf(json_out, "nexthop",
9584 "%pI4", &attr->nexthop);
05864da7 9585 else
23d0a753 9586 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9587 }
7226bc40
TA
9588 } else if (((p->family == AF_INET6) &&
9589 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9590 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9591 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9592 char buf_a[512];
9593
9594 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9595 if (json)
c949c771
DA
9596 json_object_string_addf(
9597 json_out, "mpNexthopGlobalIn", "%pI6",
9598 &attr->mp_nexthop_global);
05864da7
DS
9599 else
9600 vty_out(vty, "%s",
9601 inet_ntop(AF_INET6,
9602 &attr->mp_nexthop_global,
9603 buf_a, sizeof(buf_a)));
9604 } else if (attr->mp_nexthop_len
9605 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9606 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9607 &attr->mp_nexthop_global,
9608 &attr->mp_nexthop_local);
9609 if (json)
9610 json_object_string_add(json_out,
9611 "mpNexthopGlobalLocal",
9612 buf_a);
9613 else
9614 vty_out(vty, "%s", buf_a);
d62a17ae 9615 }
9616 }
9617
9b6d8fcf 9618 label = decode_label(&path->extra->label[0]);
d62a17ae 9619
9620 if (bgp_is_valid_label(&label)) {
9621 if (json) {
9622 json_object_int_add(json_out, "notag", label);
9623 json_object_array_add(json, json_out);
9624 } else {
9625 vty_out(vty, "notag/%d", label);
9626 vty_out(vty, "\n");
9627 }
700ddfed
PG
9628 } else if (!json)
9629 vty_out(vty, "\n");
d62a17ae 9630}
718e3744 9631
bd494ec5 9632void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9633 struct bgp_path_info *path, int display,
d62a17ae 9634 json_object *json_paths)
718e3744 9635{
d62a17ae 9636 struct attr *attr;
d62a17ae 9637 json_object *json_path = NULL;
14f51eba
LK
9638 json_object *json_nexthop = NULL;
9639 json_object *json_overlay = NULL;
856ca177 9640
9b6d8fcf 9641 if (!path->extra)
d62a17ae 9642 return;
718e3744 9643
14f51eba
LK
9644 if (json_paths) {
9645 json_path = json_object_new_object();
9646 json_overlay = json_object_new_object();
9647 json_nexthop = json_object_new_object();
9648 }
9649
d62a17ae 9650 /* short status lead text */
82c298be 9651 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9652
d62a17ae 9653 /* print prefix and mask */
9654 if (!display)
7d3cae70 9655 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9656 else
9657 vty_out(vty, "%*s", 17, " ");
9658
9659 /* Print attribute */
9b6d8fcf 9660 attr = path->attr;
05864da7 9661 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9662
05864da7
DS
9663 switch (af) {
9664 case AF_INET:
05864da7 9665 if (!json_path) {
db66cf7c 9666 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9667 } else {
db66cf7c
DA
9668 json_object_string_addf(json_nexthop, "ip", "%pI4",
9669 &attr->mp_nexthop_global_in);
14f51eba 9670
05864da7 9671 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9672
05864da7
DS
9673 json_object_object_add(json_path, "nexthop",
9674 json_nexthop);
9675 }
9676 break;
9677 case AF_INET6:
05864da7 9678 if (!json_path) {
db66cf7c
DA
9679 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9680 &attr->mp_nexthop_local);
05864da7 9681 } else {
db66cf7c
DA
9682 json_object_string_addf(json_nexthop, "ipv6Global",
9683 "%pI6",
9684 &attr->mp_nexthop_global);
14f51eba 9685
db66cf7c
DA
9686 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9687 "%pI6",
9688 &attr->mp_nexthop_local);
14f51eba 9689
05864da7 9690 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9691
05864da7
DS
9692 json_object_object_add(json_path, "nexthop",
9693 json_nexthop);
9694 }
9695 break;
9696 default:
9697 if (!json_path) {
9698 vty_out(vty, "?");
9699 } else {
9700 json_object_string_add(json_nexthop, "Error",
9701 "Unsupported address-family");
77a2f8e5
DA
9702 json_object_string_add(json_nexthop, "error",
9703 "Unsupported address-family");
d62a17ae 9704 }
05864da7 9705 }
988258b4 9706
6c924775
DS
9707 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9708
05864da7 9709 if (!json_path)
db66cf7c 9710 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9711 else
db66cf7c 9712 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9713
b53e67a3 9714 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9715 char *mac = NULL;
9716 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9717 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9718 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9719
9720 if (routermac)
9721 mac = ecom_mac2str((char *)routermac->val);
9722 if (mac) {
9723 if (!json_path) {
c4efd0f4 9724 vty_out(vty, "/%s", mac);
05864da7
DS
9725 } else {
9726 json_object_string_add(json_overlay, "rmac",
9727 mac);
988258b4 9728 }
05864da7 9729 XFREE(MTYPE_TMP, mac);
988258b4 9730 }
05864da7 9731 }
718e3744 9732
05864da7
DS
9733 if (!json_path) {
9734 vty_out(vty, "\n");
9735 } else {
9736 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9737
05864da7 9738 json_object_array_add(json_paths, json_path);
14f51eba 9739 }
d62a17ae 9740}
718e3744 9741
d62a17ae 9742/* dampening route */
5f040085
DS
9743static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9744 struct bgp_path_info *path, int display,
9745 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9746 json_object *json_paths)
d62a17ae 9747{
e5be8c1d 9748 struct attr *attr = path->attr;
d62a17ae 9749 int len;
9750 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9751 json_object *json_path = NULL;
9752
9753 if (use_json)
9754 json_path = json_object_new_object();
d62a17ae 9755
9756 /* short status lead text */
e5be8c1d 9757 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9758
9759 /* print prefix and mask */
9760 if (!use_json) {
9761 if (!display)
7d3cae70 9762 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9763 else
9764 vty_out(vty, "%*s", 17, " ");
d62a17ae 9765
e5be8c1d
DA
9766 len = vty_out(vty, "%s", path->peer->host);
9767 len = 17 - len;
9768
9769 if (len < 1)
d62a17ae 9770 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9771 else
9772 vty_out(vty, "%*s", len, " ");
d62a17ae 9773
9b6d8fcf
DS
9774 vty_out(vty, "%s ",
9775 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9776 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9777 use_json, NULL));
d62a17ae 9778
e5be8c1d 9779 if (attr->aspath)
05864da7 9780 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9781
05864da7
DS
9782 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9783
d62a17ae 9784 vty_out(vty, "\n");
e5be8c1d
DA
9785 } else {
9786 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9787 safi, use_json, json_path);
9788
9789 if (attr->aspath)
9790 json_object_string_add(json_path, "asPath",
9791 attr->aspath->str);
9792
9793 json_object_string_add(json_path, "origin",
9794 bgp_origin_str[attr->origin]);
9795 json_object_string_add(json_path, "peerHost", path->peer->host);
9796
9797 json_object_array_add(json_paths, json_path);
9798 }
d62a17ae 9799}
718e3744 9800
d62a17ae 9801/* flap route */
5f040085
DS
9802static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9803 struct bgp_path_info *path, int display,
9804 afi_t afi, safi_t safi, bool use_json,
31258046 9805 json_object *json_paths)
784d3a42 9806{
31258046 9807 struct attr *attr = path->attr;
d62a17ae 9808 struct bgp_damp_info *bdi;
9809 char timebuf[BGP_UPTIME_LEN];
9810 int len;
31258046 9811 json_object *json_path = NULL;
784d3a42 9812
9b6d8fcf 9813 if (!path->extra)
d62a17ae 9814 return;
784d3a42 9815
31258046
DA
9816 if (use_json)
9817 json_path = json_object_new_object();
9818
9b6d8fcf 9819 bdi = path->extra->damp_info;
784d3a42 9820
d62a17ae 9821 /* short status lead text */
31258046 9822 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9823
d62a17ae 9824 if (!use_json) {
9825 if (!display)
7d3cae70 9826 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9827 else
9828 vty_out(vty, "%*s", 17, " ");
784d3a42 9829
31258046
DA
9830 len = vty_out(vty, "%s", path->peer->host);
9831 len = 16 - len;
9832 if (len < 1)
d62a17ae 9833 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9834 else
9835 vty_out(vty, "%*s", len, " ");
784d3a42 9836
31258046
DA
9837 len = vty_out(vty, "%d", bdi->flap);
9838 len = 5 - len;
9839 if (len < 1)
d62a17ae 9840 vty_out(vty, " ");
d62a17ae 9841 else
9842 vty_out(vty, "%*s", len, " ");
d62a17ae 9843
996c9314
LB
9844 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9845 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9846
31258046
DA
9847 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9848 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9849 vty_out(vty, "%s ",
9b6d8fcf 9850 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9851 BGP_UPTIME_LEN, afi,
31258046
DA
9852 safi, use_json, NULL));
9853 else
d62a17ae 9854 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9855
31258046 9856 if (attr->aspath)
05864da7 9857 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9858
05864da7
DS
9859 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9860
d62a17ae 9861 vty_out(vty, "\n");
31258046
DA
9862 } else {
9863 json_object_string_add(json_path, "peerHost", path->peer->host);
9864 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9865
9866 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9867 json_path);
9868
9869 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9870 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9871 bgp_damp_reuse_time_vty(vty, path, timebuf,
9872 BGP_UPTIME_LEN, afi, safi,
9873 use_json, json_path);
9874
9875 if (attr->aspath)
9876 json_object_string_add(json_path, "asPath",
9877 attr->aspath->str);
9878
9879 json_object_string_add(json_path, "origin",
9880 bgp_origin_str[attr->origin]);
9881
9882 json_object_array_add(json_paths, json_path);
9883 }
d62a17ae 9884}
9885
9886static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9887 int *first, const char *header,
9888 json_object *json_adv_to)
9889{
d62a17ae 9890 json_object *json_peer = NULL;
9891
9892 if (json_adv_to) {
9893 /* 'advertised-to' is a dictionary of peers we have advertised
9894 * this
9895 * prefix too. The key is the peer's IP or swpX, the value is
9896 * the
9897 * hostname if we know it and "" if not.
9898 */
9899 json_peer = json_object_new_object();
9900
9901 if (peer->hostname)
9902 json_object_string_add(json_peer, "hostname",
9903 peer->hostname);
9904
9905 if (peer->conf_if)
9906 json_object_object_add(json_adv_to, peer->conf_if,
9907 json_peer);
9908 else
47e12884
DA
9909 json_object_object_addf(json_adv_to, json_peer, "%pSU",
9910 &peer->su);
d62a17ae 9911 } else {
9912 if (*first) {
9913 vty_out(vty, "%s", header);
9914 *first = 0;
9915 }
9916
9917 if (peer->hostname
892fedb6 9918 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9919 if (peer->conf_if)
9920 vty_out(vty, " %s(%s)", peer->hostname,
9921 peer->conf_if);
9922 else
47e12884
DA
9923 vty_out(vty, " %s(%pSU)", peer->hostname,
9924 &peer->su);
d62a17ae 9925 } else {
9926 if (peer->conf_if)
9927 vty_out(vty, " %s", peer->conf_if);
9928 else
47e12884 9929 vty_out(vty, " %pSU", &peer->su);
d62a17ae 9930 }
9931 }
784d3a42
PG
9932}
9933
dcc68b5e
MS
9934static void route_vty_out_tx_ids(struct vty *vty,
9935 struct bgp_addpath_info_data *d)
9936{
9937 int i;
9938
9939 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9940 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9941 d->addpath_tx_id[i],
9942 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9943 }
9944}
9945
5e4d4c8a 9946static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9947 struct bgp_path_info *pi,
9948 struct attr *attr,
9949 json_object *json_path)
5e4d4c8a
AK
9950{
9951 char esi_buf[ESI_STR_LEN];
9952 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9953 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9954 ATTR_ES_PEER_ROUTER);
9955 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9956 ATTR_ES_PEER_ACTIVE);
9957 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9958 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9959 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9960 if (json_path) {
9961 json_object *json_es_info = NULL;
9962
9963 json_object_string_add(
9964 json_path, "esi",
9965 esi_buf);
9966 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9967 json_es_info = json_object_new_object();
9968 if (es_local)
9969 json_object_boolean_true_add(
9970 json_es_info, "localEs");
9971 if (peer_active)
9972 json_object_boolean_true_add(
9973 json_es_info, "peerActive");
9974 if (peer_proxy)
9975 json_object_boolean_true_add(
9976 json_es_info, "peerProxy");
9977 if (peer_router)
9978 json_object_boolean_true_add(
9979 json_es_info, "peerRouter");
9980 if (attr->mm_sync_seqnum)
9981 json_object_int_add(
9982 json_es_info, "peerSeq",
9983 attr->mm_sync_seqnum);
9984 json_object_object_add(
9985 json_path, "es_info",
9986 json_es_info);
9987 }
9988 } else {
9989 if (bgp_evpn_attr_is_sync(attr))
9990 vty_out(vty,
9991 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9992 esi_buf,
9993 es_local ? "local-es":"",
9994 peer_proxy ? "proxy " : "",
9995 peer_active ? "active ":"",
9996 peer_router ? "router ":"",
9997 attr->mm_sync_seqnum);
9998 else
9999 vty_out(vty, " ESI %s %s\n",
10000 esi_buf,
10001 es_local ? "local-es":"");
10002 }
10003}
10004
4933eaaf
DS
10005void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
10006 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
10007 enum rpki_states rpki_curr_state,
10008 json_object *json_paths)
d62a17ae 10009{
10010 char buf[INET6_ADDRSTRLEN];
10011 char buf1[BUFSIZ];
515c2602 10012 struct attr *attr = path->attr;
d62a17ae 10013 time_t tbuf;
10014 json_object *json_bestpath = NULL;
10015 json_object *json_cluster_list = NULL;
10016 json_object *json_cluster_list_list = NULL;
10017 json_object *json_ext_community = NULL;
10018 json_object *json_last_update = NULL;
7fd077aa 10019 json_object *json_pmsi = NULL;
d62a17ae 10020 json_object *json_nexthop_global = NULL;
10021 json_object *json_nexthop_ll = NULL;
10022 json_object *json_nexthops = NULL;
10023 json_object *json_path = NULL;
10024 json_object *json_peer = NULL;
10025 json_object *json_string = NULL;
10026 json_object *json_adv_to = NULL;
10027 int first = 0;
10028 struct listnode *node, *nnode;
10029 struct peer *peer;
be92fc9f 10030 bool addpath_capable;
d62a17ae 10031 int has_adj;
10032 unsigned int first_as;
1defdda8 10033 bool nexthop_self =
9b6d8fcf 10034 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10035 int i;
2ba93fd6
DA
10036 char *nexthop_hostname =
10037 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10038 uint32_t ttl = 0;
10039 uint32_t bos = 0;
10040 uint32_t exp = 0;
10041 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 10042
10043 if (json_paths) {
10044 json_path = json_object_new_object();
10045 json_peer = json_object_new_object();
10046 json_nexthop_global = json_object_new_object();
10047 }
10048
8304dabf
AD
10049 if (safi == SAFI_EVPN) {
10050 if (!json_paths)
10051 vty_out(vty, " Route %pRN", bn);
10052 }
10053
44c69747 10054 if (path->extra) {
b57ba6d2 10055 char tag_buf[30];
d62a17ae 10056
d62a17ae 10057 tag_buf[0] = '\0';
9b6d8fcf
DS
10058 if (path->extra && path->extra->num_labels) {
10059 bgp_evpn_label2str(path->extra->label,
10060 path->extra->num_labels, tag_buf,
a4d82a8a 10061 sizeof(tag_buf));
d62a17ae 10062 }
d7325ee7 10063 if (safi == SAFI_EVPN) {
44c69747 10064 if (!json_paths) {
44c69747
LK
10065 if (tag_buf[0] != '\0')
10066 vty_out(vty, " VNI %s", tag_buf);
44c69747 10067 } else {
77a2f8e5 10068 if (tag_buf[0]) {
44c69747
LK
10069 json_object_string_add(json_path, "VNI",
10070 tag_buf);
77a2f8e5
DA
10071 json_object_string_add(json_path, "vni",
10072 tag_buf);
10073 }
44c69747 10074 }
d7325ee7
DD
10075 }
10076
44c69747 10077 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 10078 struct bgp_path_info *parent_ri;
9bcb3eef 10079 struct bgp_dest *dest, *pdest;
d62a17ae 10080
9b6d8fcf 10081 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
10082 dest = parent_ri->net;
10083 if (dest && dest->pdest) {
10084 pdest = dest->pdest;
d7325ee7 10085 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 10086 vty_out(vty,
c4f64ea9
DA
10087 " Imported from %pRD:%pFX, VNI %s",
10088 (struct prefix_rd *)
10089 bgp_dest_get_prefix(
10090 pdest),
2dbe669b
DA
10091 (struct prefix_evpn *)
10092 bgp_dest_get_prefix(
10093 dest),
10094 tag_buf);
58bff4d1
AK
10095 if (attr->es_flags & ATTR_ES_L3_NHG)
10096 vty_out(vty, ", L3NHG %s",
10097 (attr->es_flags
10098 & ATTR_ES_L3_NHG_ACTIVE)
10099 ? "active"
10100 : "inactive");
10101 vty_out(vty, "\n");
10102
d7325ee7 10103 } else
2dbe669b 10104 vty_out(vty,
c4f64ea9
DA
10105 " Imported from %pRD:%pFX\n",
10106 (struct prefix_rd *)
10107 bgp_dest_get_prefix(
10108 pdest),
2dbe669b
DA
10109 (struct prefix_evpn *)
10110 bgp_dest_get_prefix(
10111 dest));
d62a17ae 10112 }
10113 }
10114 }
d62a17ae 10115
8304dabf
AD
10116 if (safi == SAFI_EVPN
10117 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10118 char gwip_buf[INET6_ADDRSTRLEN];
10119
860e740b
IR
10120 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10121 sizeof(gwip_buf));
8304dabf
AD
10122
10123 if (json_paths)
10124 json_object_string_add(json_path, "gatewayIP",
10125 gwip_buf);
10126 else
10127 vty_out(vty, " Gateway IP %s", gwip_buf);
10128 }
10129
2bf9780b 10130 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10131 vty_out(vty, "\n");
10132
05864da7
DS
10133 /* Line1 display AS-path, Aggregator */
10134 if (attr->aspath) {
10135 if (json_paths) {
10136 if (!attr->aspath->json)
10137 aspath_str_update(attr->aspath, true);
10138 json_object_lock(attr->aspath->json);
10139 json_object_object_add(json_path, "aspath",
10140 attr->aspath->json);
10141 } else {
10142 if (attr->aspath->segments)
10143 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10144 else
05864da7 10145 vty_out(vty, " Local");
d62a17ae 10146 }
05864da7 10147 }
d62a17ae 10148
05864da7
DS
10149 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10150 if (json_paths)
10151 json_object_boolean_true_add(json_path, "removed");
10152 else
10153 vty_out(vty, ", (removed)");
10154 }
d62a17ae 10155
05864da7
DS
10156 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10157 if (json_paths)
10158 json_object_boolean_true_add(json_path, "stale");
10159 else
10160 vty_out(vty, ", (stale)");
10161 }
d62a17ae 10162
05864da7
DS
10163 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10164 if (json_paths) {
10165 json_object_int_add(json_path, "aggregatorAs",
10166 attr->aggregator_as);
c949c771
DA
10167 json_object_string_addf(json_path, "aggregatorId",
10168 "%pI4", &attr->aggregator_addr);
05864da7 10169 } else {
88d495a9
DA
10170 vty_out(vty, ", (aggregated by %u %pI4)",
10171 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10172 }
05864da7 10173 }
d62a17ae 10174
05864da7
DS
10175 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10176 PEER_FLAG_REFLECTOR_CLIENT)) {
10177 if (json_paths)
10178 json_object_boolean_true_add(json_path,
10179 "rxedFromRrClient");
10180 else
10181 vty_out(vty, ", (Received from a RR-client)");
10182 }
d62a17ae 10183
05864da7
DS
10184 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10185 PEER_FLAG_RSERVER_CLIENT)) {
10186 if (json_paths)
10187 json_object_boolean_true_add(json_path,
10188 "rxedFromRsClient");
10189 else
10190 vty_out(vty, ", (Received from a RS-client)");
10191 }
d62a17ae 10192
05864da7
DS
10193 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10194 if (json_paths)
10195 json_object_boolean_true_add(json_path,
10196 "dampeningHistoryEntry");
10197 else
10198 vty_out(vty, ", (history entry)");
10199 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10200 if (json_paths)
10201 json_object_boolean_true_add(json_path,
10202 "dampeningSuppressed");
10203 else
10204 vty_out(vty, ", (suppressed due to dampening)");
10205 }
d62a17ae 10206
05864da7
DS
10207 if (!json_paths)
10208 vty_out(vty, "\n");
d62a17ae 10209
05864da7
DS
10210 /* Line2 display Next-hop, Neighbor, Router-id */
10211 /* Display the nexthop */
9bcb3eef 10212 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0 10213
7226bc40
TA
10214 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
10215 bn_p->family == AF_EVPN) &&
10216 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10217 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10218 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10219 || safi == SAFI_EVPN) {
515c2602 10220 if (json_paths) {
c949c771
DA
10221 json_object_string_addf(
10222 json_nexthop_global, "ip", "%pI4",
10223 &attr->mp_nexthop_global_in);
515c2602 10224
939a97f4 10225 if (path->peer->hostname)
515c2602
DA
10226 json_object_string_add(
10227 json_nexthop_global, "hostname",
939a97f4 10228 path->peer->hostname);
aef999a2
DA
10229 } else {
10230 if (nexthop_hostname)
10231 vty_out(vty, " %pI4(%s)",
10232 &attr->mp_nexthop_global_in,
10233 nexthop_hostname);
10234 else
10235 vty_out(vty, " %pI4",
10236 &attr->mp_nexthop_global_in);
10237 }
d62a17ae 10238 } else {
515c2602 10239 if (json_paths) {
c949c771
DA
10240 json_object_string_addf(json_nexthop_global,
10241 "ip", "%pI4",
10242 &attr->nexthop);
515c2602 10243
939a97f4 10244 if (path->peer->hostname)
515c2602
DA
10245 json_object_string_add(
10246 json_nexthop_global, "hostname",
939a97f4 10247 path->peer->hostname);
aef999a2
DA
10248 } else {
10249 if (nexthop_hostname)
10250 vty_out(vty, " %pI4(%s)",
10251 &attr->nexthop,
10252 nexthop_hostname);
10253 else
10254 vty_out(vty, " %pI4",
10255 &attr->nexthop);
10256 }
d62a17ae 10257 }
10258
05864da7
DS
10259 if (json_paths)
10260 json_object_string_add(json_nexthop_global, "afi",
10261 "ipv4");
10262 } else {
10263 if (json_paths) {
c949c771
DA
10264 json_object_string_addf(json_nexthop_global, "ip",
10265 "%pI6",
10266 &attr->mp_nexthop_global);
515c2602 10267
939a97f4 10268 if (path->peer->hostname)
515c2602
DA
10269 json_object_string_add(json_nexthop_global,
10270 "hostname",
939a97f4 10271 path->peer->hostname);
515c2602 10272
05864da7
DS
10273 json_object_string_add(json_nexthop_global, "afi",
10274 "ipv6");
10275 json_object_string_add(json_nexthop_global, "scope",
10276 "global");
10277 } else {
aef999a2
DA
10278 if (nexthop_hostname)
10279 vty_out(vty, " %pI6(%s)",
10280 &attr->mp_nexthop_global,
10281 nexthop_hostname);
10282 else
10283 vty_out(vty, " %pI6",
10284 &attr->mp_nexthop_global);
d62a17ae 10285 }
05864da7 10286 }
d62a17ae 10287
05864da7
DS
10288 /* Display the IGP cost or 'inaccessible' */
10289 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
95ba22d5
DA
10290 bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
10291
10292 if (json_paths) {
05864da7
DS
10293 json_object_boolean_false_add(json_nexthop_global,
10294 "accessible");
95ba22d5
DA
10295 json_object_boolean_add(json_nexthop_global,
10296 "importCheckEnabled", import);
10297 } else {
10298 vty_out(vty, " (inaccessible%s)",
10299 import ? ", import-check enabled" : "");
10300 }
05864da7
DS
10301 } else {
10302 if (path->extra && path->extra->igpmetric) {
d62a17ae 10303 if (json_paths)
05864da7
DS
10304 json_object_int_add(json_nexthop_global,
10305 "metric",
10306 path->extra->igpmetric);
d62a17ae 10307 else
05864da7
DS
10308 vty_out(vty, " (metric %u)",
10309 path->extra->igpmetric);
d62a17ae 10310 }
10311
05864da7 10312 /* IGP cost is 0, display this only for json */
d62a17ae 10313 else {
d62a17ae 10314 if (json_paths)
05864da7
DS
10315 json_object_int_add(json_nexthop_global,
10316 "metric", 0);
d62a17ae 10317 }
d62a17ae 10318
05864da7
DS
10319 if (json_paths)
10320 json_object_boolean_true_add(json_nexthop_global,
10321 "accessible");
10322 }
d62a17ae 10323
05864da7
DS
10324 /* Display peer "from" output */
10325 /* This path was originated locally */
10326 if (path->peer == bgp->peer_self) {
d62a17ae 10327
7226bc40
TA
10328 if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
10329 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10330 if (json_paths)
05864da7
DS
10331 json_object_string_add(json_peer, "peerId",
10332 "0.0.0.0");
d62a17ae 10333 else
05864da7
DS
10334 vty_out(vty, " from 0.0.0.0 ");
10335 } else {
d62a17ae 10336 if (json_paths)
05864da7
DS
10337 json_object_string_add(json_peer, "peerId",
10338 "::");
d62a17ae 10339 else
05864da7 10340 vty_out(vty, " from :: ");
d62a17ae 10341 }
d62a17ae 10342
4e9a9863 10343 if (json_paths)
c949c771
DA
10344 json_object_string_addf(json_peer, "routerId", "%pI4",
10345 &bgp->router_id);
4e9a9863 10346 else
23d0a753 10347 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10348 }
d62a17ae 10349
05864da7
DS
10350 /* We RXed this path from one of our peers */
10351 else {
10352
10353 if (json_paths) {
47e12884
DA
10354 json_object_string_addf(json_peer, "peerId", "%pSU",
10355 &path->peer->su);
c949c771
DA
10356 json_object_string_addf(json_peer, "routerId", "%pI4",
10357 &path->peer->remote_id);
05864da7
DS
10358
10359 if (path->peer->hostname)
10360 json_object_string_add(json_peer, "hostname",
10361 path->peer->hostname);
10362
10363 if (path->peer->domainname)
10364 json_object_string_add(json_peer, "domainname",
10365 path->peer->domainname);
10366
10367 if (path->peer->conf_if)
10368 json_object_string_add(json_peer, "interface",
10369 path->peer->conf_if);
10370 } else {
10371 if (path->peer->conf_if) {
10372 if (path->peer->hostname
892fedb6
DA
10373 && CHECK_FLAG(path->peer->bgp->flags,
10374 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10375 vty_out(vty, " from %s(%s)",
10376 path->peer->hostname,
10377 path->peer->conf_if);
d62a17ae 10378 else
05864da7 10379 vty_out(vty, " from %s",
9b6d8fcf 10380 path->peer->conf_if);
d62a17ae 10381 } else {
05864da7 10382 if (path->peer->hostname
892fedb6
DA
10383 && CHECK_FLAG(path->peer->bgp->flags,
10384 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10385 vty_out(vty, " from %s(%s)",
10386 path->peer->hostname,
10387 path->peer->host);
d62a17ae 10388 else
47e12884
DA
10389 vty_out(vty, " from %pSU",
10390 &path->peer->su);
d62a17ae 10391 }
d62a17ae 10392
05864da7 10393 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10394 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10395 else
10396 vty_out(vty, " (%s)",
10397 inet_ntop(AF_INET,
10398 &path->peer->remote_id, buf1,
10399 sizeof(buf1)));
d62a17ae 10400 }
05864da7 10401 }
9df8b37c 10402
05864da7
DS
10403 /*
10404 * Note when vrfid of nexthop is different from that of prefix
10405 */
10406 if (path->extra && path->extra->bgp_orig) {
10407 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10408
05864da7
DS
10409 if (json_paths) {
10410 const char *vn;
9df8b37c 10411
05864da7
DS
10412 if (path->extra->bgp_orig->inst_type
10413 == BGP_INSTANCE_TYPE_DEFAULT)
10414 vn = VRF_DEFAULT_NAME;
10415 else
10416 vn = path->extra->bgp_orig->name;
9df8b37c 10417
05864da7 10418 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10419
05864da7
DS
10420 if (nexthop_vrfid == VRF_UNKNOWN) {
10421 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10422 } else {
05864da7
DS
10423 json_object_int_add(json_path, "nhVrfId",
10424 (int)nexthop_vrfid);
9df8b37c 10425 }
05864da7
DS
10426 } else {
10427 if (nexthop_vrfid == VRF_UNKNOWN)
10428 vty_out(vty, " vrf ?");
137147c6
DS
10429 else {
10430 struct vrf *vrf;
10431
10432 vrf = vrf_lookup_by_id(nexthop_vrfid);
10433 vty_out(vty, " vrf %s(%u)",
10434 VRF_LOGNAME(vrf), nexthop_vrfid);
10435 }
9df8b37c 10436 }
05864da7 10437 }
9df8b37c 10438
05864da7
DS
10439 if (nexthop_self) {
10440 if (json_paths) {
10441 json_object_boolean_true_add(json_path,
10442 "announceNexthopSelf");
10443 } else {
10444 vty_out(vty, " announce-nh-self");
9df8b37c 10445 }
05864da7 10446 }
9df8b37c 10447
05864da7
DS
10448 if (!json_paths)
10449 vty_out(vty, "\n");
d62a17ae 10450
05864da7
DS
10451 /* display the link-local nexthop */
10452 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10453 if (json_paths) {
10454 json_nexthop_ll = json_object_new_object();
c949c771
DA
10455 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10456 &attr->mp_nexthop_local);
515c2602 10457
939a97f4 10458 if (path->peer->hostname)
515c2602
DA
10459 json_object_string_add(json_nexthop_ll,
10460 "hostname",
939a97f4 10461 path->peer->hostname);
515c2602 10462
05864da7
DS
10463 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10464 json_object_string_add(json_nexthop_ll, "scope",
10465 "link-local");
d62a17ae 10466
05864da7
DS
10467 json_object_boolean_true_add(json_nexthop_ll,
10468 "accessible");
d62a17ae 10469
05864da7 10470 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10471 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10472 "used");
10473 else
10474 json_object_boolean_true_add(
10475 json_nexthop_global, "used");
10476 } else {
10477 vty_out(vty, " (%s) %s\n",
10478 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10479 buf, INET6_ADDRSTRLEN),
10480 attr->mp_nexthop_prefer_global
10481 ? "(prefer-global)"
10482 : "(used)");
d62a17ae 10483 }
05864da7
DS
10484 }
10485 /* If we do not have a link-local nexthop then we must flag the
10486 global as "used" */
10487 else {
10488 if (json_paths)
10489 json_object_boolean_true_add(json_nexthop_global,
10490 "used");
10491 }
d62a17ae 10492
b5e140c8 10493 if (safi == SAFI_EVPN &&
5e4d4c8a 10494 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10495 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10496 }
10497
05864da7
DS
10498 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10499 * Int/Ext/Local, Atomic, best */
10500 if (json_paths)
10501 json_object_string_add(json_path, "origin",
10502 bgp_origin_long_str[attr->origin]);
10503 else
10504 vty_out(vty, " Origin %s",
10505 bgp_origin_long_str[attr->origin]);
9df8b37c 10506
05864da7 10507 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10508 if (json_paths)
05864da7 10509 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10510 else
05864da7
DS
10511 vty_out(vty, ", metric %u", attr->med);
10512 }
9df8b37c 10513
05864da7
DS
10514 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10515 if (json_paths)
0fbac0b4 10516 json_object_int_add(json_path, "locPrf",
05864da7
DS
10517 attr->local_pref);
10518 else
10519 vty_out(vty, ", localpref %u", attr->local_pref);
10520 }
9df8b37c 10521
05864da7
DS
10522 if (attr->weight != 0) {
10523 if (json_paths)
10524 json_object_int_add(json_path, "weight", attr->weight);
10525 else
10526 vty_out(vty, ", weight %u", attr->weight);
10527 }
9df8b37c 10528
05864da7
DS
10529 if (attr->tag != 0) {
10530 if (json_paths)
10531 json_object_int_add(json_path, "tag", attr->tag);
10532 else
10533 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10534 }
9df8b37c 10535
05864da7
DS
10536 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10537 if (json_paths)
10538 json_object_boolean_false_add(json_path, "valid");
10539 else
10540 vty_out(vty, ", invalid");
10541 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10542 if (json_paths)
10543 json_object_boolean_true_add(json_path, "valid");
10544 else
10545 vty_out(vty, ", valid");
10546 }
9df8b37c 10547
7d3cae70
DA
10548 if (json_paths)
10549 json_object_int_add(json_path, "version", bn->version);
10550
05864da7
DS
10551 if (path->peer != bgp->peer_self) {
10552 if (path->peer->as == path->peer->local_as) {
10553 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10554 if (json_paths)
10555 json_object_string_add(
10556 json_peer, "type",
10557 "confed-internal");
d62a17ae 10558 else
05864da7 10559 vty_out(vty, ", confed-internal");
d62a17ae 10560 } else {
05864da7
DS
10561 if (json_paths)
10562 json_object_string_add(
10563 json_peer, "type", "internal");
10564 else
10565 vty_out(vty, ", internal");
9df8b37c 10566 }
05864da7
DS
10567 } else {
10568 if (bgp_confederation_peers_check(bgp,
10569 path->peer->as)) {
10570 if (json_paths)
10571 json_object_string_add(
10572 json_peer, "type",
10573 "confed-external");
d62a17ae 10574 else
05864da7 10575 vty_out(vty, ", confed-external");
d62a17ae 10576 } else {
05864da7
DS
10577 if (json_paths)
10578 json_object_string_add(
10579 json_peer, "type", "external");
10580 else
10581 vty_out(vty, ", external");
d62a17ae 10582 }
10583 }
05864da7
DS
10584 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10585 if (json_paths) {
10586 json_object_boolean_true_add(json_path, "aggregated");
10587 json_object_boolean_true_add(json_path, "local");
10588 } else {
10589 vty_out(vty, ", aggregated, local");
10590 }
10591 } else if (path->type != ZEBRA_ROUTE_BGP) {
10592 if (json_paths)
10593 json_object_boolean_true_add(json_path, "sourced");
10594 else
10595 vty_out(vty, ", sourced");
10596 } else {
10597 if (json_paths) {
10598 json_object_boolean_true_add(json_path, "sourced");
10599 json_object_boolean_true_add(json_path, "local");
10600 } else {
10601 vty_out(vty, ", sourced, local");
d62a17ae 10602 }
05864da7 10603 }
718e3744 10604
05864da7 10605 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10606 if (json_paths)
05864da7
DS
10607 json_object_boolean_true_add(json_path,
10608 "atomicAggregate");
d62a17ae 10609 else
05864da7
DS
10610 vty_out(vty, ", atomic-aggregate");
10611 }
d62a17ae 10612
d864dd9e
EB
10613 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10614 if (json_paths)
10615 json_object_int_add(json_path, "otc", attr->otc);
10616 else
10617 vty_out(vty, ", otc %u", attr->otc);
10618 }
10619
05864da7
DS
10620 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10621 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10622 && bgp_path_info_mpath_count(path))) {
10623 if (json_paths)
10624 json_object_boolean_true_add(json_path, "multipath");
10625 else
10626 vty_out(vty, ", multipath");
10627 }
50e05855 10628
05864da7
DS
10629 // Mark the bestpath(s)
10630 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10631 first_as = aspath_get_first_as(attr->aspath);
718e3744 10632
05864da7
DS
10633 if (json_paths) {
10634 if (!json_bestpath)
10635 json_bestpath = json_object_new_object();
10636 json_object_int_add(json_bestpath, "bestpathFromAs",
10637 first_as);
10638 } else {
10639 if (first_as)
10640 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10641 else
05864da7 10642 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10643 }
05864da7 10644 }
718e3744 10645
05864da7
DS
10646 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10647 if (json_paths) {
10648 if (!json_bestpath)
10649 json_bestpath = json_object_new_object();
10650 json_object_boolean_true_add(json_bestpath, "overall");
10651 json_object_string_add(
10652 json_bestpath, "selectionReason",
10653 bgp_path_selection_reason2str(bn->reason));
10654 } else {
10655 vty_out(vty, ", best");
10656 vty_out(vty, " (%s)",
10657 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10658 }
05864da7 10659 }
718e3744 10660
4027d19b 10661 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10662 if (json_paths)
10663 json_object_string_add(
10664 json_path, "rpkiValidationState",
4027d19b 10665 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10666 else
1d327209 10667 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10668 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10669 }
10670
05864da7
DS
10671 if (json_bestpath)
10672 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10673
05864da7
DS
10674 if (!json_paths)
10675 vty_out(vty, "\n");
10676
10677 /* Line 4 display Community */
29e72930 10678 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10679 if (json_paths) {
9a706b42
DA
10680 if (!bgp_attr_get_community(attr)->json)
10681 community_str(bgp_attr_get_community(attr),
c0945b78 10682 true, true);
9a706b42
DA
10683 json_object_lock(bgp_attr_get_community(attr)->json);
10684 json_object_object_add(
10685 json_path, "community",
10686 bgp_attr_get_community(attr)->json);
05864da7
DS
10687 } else {
10688 vty_out(vty, " Community: %s\n",
9a706b42 10689 bgp_attr_get_community(attr)->str);
d62a17ae 10690 }
05864da7 10691 }
718e3744 10692
05864da7
DS
10693 /* Line 5 display Extended-community */
10694 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10695 if (json_paths) {
10696 json_ext_community = json_object_new_object();
b53e67a3
DA
10697 json_object_string_add(
10698 json_ext_community, "string",
10699 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10700 json_object_object_add(json_path, "extendedCommunity",
10701 json_ext_community);
d62a17ae 10702 } else {
05864da7 10703 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10704 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10705 }
05864da7 10706 }
718e3744 10707
05864da7
DS
10708 /* Line 6 display Large community */
10709 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10710 if (json_paths) {
1bcf3a96
DA
10711 if (!bgp_attr_get_lcommunity(attr)->json)
10712 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10713 true, true);
1bcf3a96
DA
10714 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10715 json_object_object_add(
10716 json_path, "largeCommunity",
10717 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10718 } else {
10719 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10720 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10721 }
05864da7 10722 }
718e3744 10723
05864da7
DS
10724 /* Line 7 display Originator, Cluster-id */
10725 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10726 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10727 char buf[BUFSIZ] = {0};
10728
05864da7 10729 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10730 if (json_paths)
c949c771
DA
10731 json_object_string_addf(json_path,
10732 "originatorId", "%pI4",
10733 &attr->originator_id);
d62a17ae 10734 else
23d0a753
DA
10735 vty_out(vty, " Originator: %pI4",
10736 &attr->originator_id);
d62a17ae 10737 }
856ca177 10738
05864da7 10739 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10740 struct cluster_list *cluster =
10741 bgp_attr_get_cluster(attr);
05864da7 10742 int i;
d62a17ae 10743
10744 if (json_paths) {
05864da7
DS
10745 json_cluster_list = json_object_new_object();
10746 json_cluster_list_list =
10747 json_object_new_array();
10748
779fee93 10749 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10750 json_string = json_object_new_string(
779fee93
DS
10751 inet_ntop(AF_INET,
10752 &cluster->list[i],
10753 buf, sizeof(buf)));
05864da7
DS
10754 json_object_array_add(
10755 json_cluster_list_list,
10756 json_string);
10757 }
718e3744 10758
05864da7
DS
10759 /*
10760 * struct cluster_list does not have
10761 * "str" variable like aspath and community
10762 * do. Add this someday if someone asks
10763 * for it.
10764 * json_object_string_add(json_cluster_list,
779fee93 10765 * "string", cluster->str);
05864da7
DS
10766 */
10767 json_object_object_add(json_cluster_list,
10768 "list",
10769 json_cluster_list_list);
10770 json_object_object_add(json_path, "clusterList",
10771 json_cluster_list);
0dc8ee70 10772 } else {
05864da7
DS
10773 vty_out(vty, ", Cluster list: ");
10774
779fee93 10775 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10776 vty_out(vty, "%pI4 ",
779fee93 10777 &cluster->list[i]);
05864da7 10778 }
0dc8ee70 10779 }
d62a17ae 10780 }
718e3744 10781
d62a17ae 10782 if (!json_paths)
10783 vty_out(vty, "\n");
05864da7 10784 }
d62a17ae 10785
05864da7 10786 if (path->extra && path->extra->damp_info)
b4f7f45b 10787 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10788
05864da7
DS
10789 /* Remote Label */
10790 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10791 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10792 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10793 &bos);
d62a17ae 10794
05864da7
DS
10795 if (json_paths)
10796 json_object_int_add(json_path, "remoteLabel", label);
10797 else
10798 vty_out(vty, " Remote label: %d\n", label);
10799 }
d62a17ae 10800
e496b420
HS
10801 /* Remote SID */
10802 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10803 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10804 if (json_paths)
10805 json_object_string_add(json_path, "remoteSid", buf);
10806 else
10807 vty_out(vty, " Remote SID: %s\n", buf);
10808 }
10809
05864da7
DS
10810 /* Label Index */
10811 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10812 if (json_paths)
10813 json_object_int_add(json_path, "labelIndex",
10814 attr->label_index);
10815 else
10816 vty_out(vty, " Label Index: %d\n",
10817 attr->label_index);
10818 }
d62a17ae 10819
05864da7
DS
10820 /* Line 8 display Addpath IDs */
10821 if (path->addpath_rx_id
10822 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10823 if (json_paths) {
10824 json_object_int_add(json_path, "addpathRxId",
10825 path->addpath_rx_id);
d62a17ae 10826
05864da7
DS
10827 /* Keep backwards compatibility with the old API
10828 * by putting TX All's ID in the old field
10829 */
10830 json_object_int_add(
10831 json_path, "addpathTxId",
10832 path->tx_addpath
10833 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10834
05864da7
DS
10835 /* ... but create a specific field for each
10836 * strategy
10837 */
10838 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10839 json_object_int_add(
10840 json_path,
10841 bgp_addpath_names(i)->id_json_name,
10842 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10843 }
05864da7
DS
10844 } else {
10845 vty_out(vty, " AddPath ID: RX %u, ",
10846 path->addpath_rx_id);
d62a17ae 10847
05864da7 10848 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10849 }
05864da7 10850 }
520d5d76 10851
05864da7
DS
10852 /* If we used addpath to TX a non-bestpath we need to display
10853 * "Advertised to" on a path-by-path basis
10854 */
10855 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10856 first = 1;
dcc68b5e 10857
05864da7
DS
10858 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10859 addpath_capable =
10860 bgp_addpath_encode_tx(peer, afi, safi);
10861 has_adj = bgp_adj_out_lookup(
10862 peer, path->net,
10863 bgp_addpath_id_for_peer(peer, afi, safi,
10864 &path->tx_addpath));
10865
10866 if ((addpath_capable && has_adj)
10867 || (!addpath_capable && has_adj
10868 && CHECK_FLAG(path->flags,
10869 BGP_PATH_SELECTED))) {
10870 if (json_path && !json_adv_to)
10871 json_adv_to = json_object_new_object();
dcc68b5e 10872
05864da7
DS
10873 route_vty_out_advertised_to(
10874 vty, peer, &first,
10875 " Advertised to:", json_adv_to);
d62a17ae 10876 }
10877 }
718e3744 10878
05864da7
DS
10879 if (json_path) {
10880 if (json_adv_to) {
10881 json_object_object_add(
10882 json_path, "advertisedTo", json_adv_to);
d62a17ae 10883 }
05864da7
DS
10884 } else {
10885 if (!first) {
10886 vty_out(vty, "\n");
d62a17ae 10887 }
10888 }
05864da7 10889 }
b05a1c8b 10890
05864da7 10891 /* Line 9 display Uptime */
083ec940 10892 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
10893 if (json_paths) {
10894 json_last_update = json_object_new_object();
10895 json_object_int_add(json_last_update, "epoch", tbuf);
10896 json_object_string_add(json_last_update, "string",
10897 ctime(&tbuf));
10898 json_object_object_add(json_path, "lastUpdate",
10899 json_last_update);
10900 } else
10901 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10902
05864da7
DS
10903 /* Line 10 display PMSI tunnel attribute, if present */
10904 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10905 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10906 bgp_attr_get_pmsi_tnl_type(attr),
10907 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10908
05864da7
DS
10909 if (json_paths) {
10910 json_pmsi = json_object_new_object();
10911 json_object_string_add(json_pmsi, "tunnelType", str);
10912 json_object_int_add(json_pmsi, "label",
10913 label2vni(&attr->label));
10914 json_object_object_add(json_path, "pmsi", json_pmsi);
10915 } else
10916 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10917 str, label2vni(&attr->label));
d62a17ae 10918 }
f1aa5d8a 10919
848e8cf6
DA
10920 if (path->peer->t_gr_restart &&
10921 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10922 unsigned long gr_remaining =
10923 thread_timer_remain_second(path->peer->t_gr_restart);
10924
10925 if (json_paths) {
10926 json_object_int_add(json_path,
10927 "gracefulRestartSecondsRemaining",
10928 gr_remaining);
10929 } else
10930 vty_out(vty,
10931 " Time until Graceful Restart stale route deleted: %lu\n",
10932 gr_remaining);
10933 }
10934
9a706b42
DA
10935 if (path->peer->t_llgr_stale[afi][safi] &&
10936 bgp_attr_get_community(attr) &&
10937 community_include(bgp_attr_get_community(attr),
10938 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10939 unsigned long llgr_remaining = thread_timer_remain_second(
10940 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10941
48ebba04
DA
10942 if (json_paths) {
10943 json_object_int_add(json_path, "llgrSecondsRemaining",
10944 llgr_remaining);
10945 } else
10946 vty_out(vty,
10947 " Time until Long-lived stale route deleted: %lu\n",
10948 llgr_remaining);
10949 }
10950
92269aa2
DS
10951 /* Output some debug about internal state of the dest flags */
10952 if (json_paths) {
10953 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10954 json_object_boolean_true_add(json_path, "processScheduled");
10955 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10956 json_object_boolean_true_add(json_path, "userCleared");
10957 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10958 json_object_boolean_true_add(json_path, "labelChanged");
10959 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10960 json_object_boolean_true_add(json_path, "registeredForLabel");
10961 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10962 json_object_boolean_true_add(json_path, "selectDefered");
10963 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10964 json_object_boolean_true_add(json_path, "fibInstalled");
10965 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10966 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10967
d62a17ae 10968 if (json_nexthop_global || json_nexthop_ll) {
10969 json_nexthops = json_object_new_array();
f1aa5d8a 10970
d62a17ae 10971 if (json_nexthop_global)
10972 json_object_array_add(json_nexthops,
10973 json_nexthop_global);
f1aa5d8a 10974
d62a17ae 10975 if (json_nexthop_ll)
10976 json_object_array_add(json_nexthops,
10977 json_nexthop_ll);
f1aa5d8a 10978
d62a17ae 10979 json_object_object_add(json_path, "nexthops",
10980 json_nexthops);
10981 }
10982
10983 json_object_object_add(json_path, "peer", json_peer);
10984 json_object_array_add(json_paths, json_path);
05864da7 10985 }
b366b518
BB
10986}
10987
96ade3ed 10988#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10989#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10990#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10991
a4d82a8a 10992static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10993 afi_t afi, safi_t safi, enum bgp_show_type type,
10994 bool use_json);
7f323236
DW
10995static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10996 const char *comstr, int exact, afi_t afi,
96c81f66 10997 safi_t safi, uint16_t show_flags);
d62a17ae 10998
1ae44dfc 10999static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 11000 struct bgp_table *table, enum bgp_show_type type,
edfee30d 11001 void *output_arg, const char *rd, int is_last,
96f3485c 11002 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 11003 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 11004 enum rpki_states rpki_target_state)
d62a17ae 11005{
40381db7 11006 struct bgp_path_info *pi;
9bcb3eef 11007 struct bgp_dest *dest;
2aad8c42
MS
11008 bool header = true;
11009 bool json_detail_header = false;
d62a17ae 11010 int display;
1ae44dfc
LB
11011 unsigned long output_count = 0;
11012 unsigned long total_count = 0;
d62a17ae 11013 struct prefix *p;
d62a17ae 11014 json_object *json_paths = NULL;
11015 int first = 1;
96f3485c
MK
11016 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11017 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
11018 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 11019
1ae44dfc 11020 if (output_cum && *output_cum != 0)
2aad8c42 11021 header = false;
1ae44dfc 11022
9386b588 11023 if (use_json && !*json_header_depth) {
96f3485c
MK
11024 if (all)
11025 *json_header_depth = 1;
11026 else {
11027 vty_out(vty, "{\n");
11028 *json_header_depth = 2;
11029 }
11030
d62a17ae 11031 vty_out(vty,
23d0a753
DA
11032 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
11033 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11034 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11035 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11036 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11037 ? VRF_DEFAULT_NAME
11038 : bgp->name,
11039 table->version, &bgp->router_id,
01eced22 11040 bgp->default_local_pref, bgp->as);
9386b588 11041 if (rd) {
445c2480 11042 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11043 ++*json_header_depth;
11044 }
d62a17ae 11045 }
718e3744 11046
445c2480
DS
11047 if (use_json && rd) {
11048 vty_out(vty, " \"%s\" : { ", rd);
11049 }
11050
2aad8c42
MS
11051 /* Check for 'json detail', where we need header output once per dest */
11052 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11053 type != bgp_show_type_dampend_paths &&
11054 type != bgp_show_type_damp_neighbor &&
11055 type != bgp_show_type_flap_statistics &&
11056 type != bgp_show_type_flap_neighbor)
11057 json_detail_header = true;
11058
d62a17ae 11059 /* Start processing of routes. */
9bcb3eef
DS
11060 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11061 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11062 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11063 bool json_detail = json_detail_header;
b54892e0 11064
9bcb3eef 11065 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11066 if (pi == NULL)
98ce9a06 11067 continue;
d62a17ae 11068
98ce9a06 11069 display = 0;
98ce9a06
DS
11070 if (use_json)
11071 json_paths = json_object_new_array();
11072 else
11073 json_paths = NULL;
d62a17ae 11074
6f94b685 11075 for (; pi; pi = pi->next) {
9a706b42
DA
11076 struct community *picomm = NULL;
11077
11078 picomm = bgp_attr_get_community(pi->attr);
11079
98ce9a06 11080 total_count++;
1e2ce4f1 11081
7d3cae70
DA
11082 if (type == bgp_show_type_prefix_version) {
11083 uint32_t version =
11084 strtoul(output_arg, NULL, 10);
11085 if (dest->version < version)
11086 continue;
11087 }
11088
a70a28a5
DA
11089 if (type == bgp_show_type_community_alias) {
11090 char *alias = output_arg;
11091 char **communities;
11092 int num;
11093 bool found = false;
11094
9a706b42
DA
11095 if (picomm) {
11096 frrstr_split(picomm->str, " ",
11097 &communities, &num);
a70a28a5
DA
11098 for (int i = 0; i < num; i++) {
11099 const char *com2alias =
11100 bgp_community2alias(
11101 communities[i]);
cd9cc0e6
IR
11102 if (!found
11103 && strcmp(alias, com2alias)
11104 == 0)
a70a28a5 11105 found = true;
cd9cc0e6
IR
11106 XFREE(MTYPE_TMP,
11107 communities[i]);
a70a28a5 11108 }
cd9cc0e6 11109 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11110 }
11111
1bcf3a96
DA
11112 if (!found &&
11113 bgp_attr_get_lcommunity(pi->attr)) {
11114 frrstr_split(bgp_attr_get_lcommunity(
11115 pi->attr)
11116 ->str,
a70a28a5
DA
11117 " ", &communities, &num);
11118 for (int i = 0; i < num; i++) {
11119 const char *com2alias =
11120 bgp_community2alias(
11121 communities[i]);
cd9cc0e6
IR
11122 if (!found
11123 && strcmp(alias, com2alias)
11124 == 0)
a70a28a5 11125 found = true;
cd9cc0e6
IR
11126 XFREE(MTYPE_TMP,
11127 communities[i]);
a70a28a5 11128 }
cd9cc0e6 11129 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11130 }
11131
11132 if (!found)
11133 continue;
11134 }
11135
1e2ce4f1
DS
11136 if (type == bgp_show_type_rpki) {
11137 if (dest_p->family == AF_INET
11138 || dest_p->family == AF_INET6)
4027d19b 11139 rpki_curr_state = hook_call(
1e2ce4f1
DS
11140 bgp_rpki_prefix_status,
11141 pi->peer, pi->attr, dest_p);
4027d19b
DS
11142 if (rpki_target_state != RPKI_NOT_BEING_USED
11143 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11144 continue;
11145 }
11146
98ce9a06
DS
11147 if (type == bgp_show_type_flap_statistics
11148 || type == bgp_show_type_flap_neighbor
11149 || type == bgp_show_type_dampend_paths
11150 || type == bgp_show_type_damp_neighbor) {
40381db7 11151 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11152 continue;
11153 }
11154 if (type == bgp_show_type_regexp) {
11155 regex_t *regex = output_arg;
d62a17ae 11156
40381db7 11157 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11158 == REG_NOMATCH)
11159 continue;
11160 }
11161 if (type == bgp_show_type_prefix_list) {
11162 struct prefix_list *plist = output_arg;
d62a17ae 11163
9bcb3eef 11164 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11165 != PREFIX_PERMIT)
11166 continue;
11167 }
ed126382
DA
11168 if (type == bgp_show_type_access_list) {
11169 struct access_list *alist = output_arg;
11170
11171 if (access_list_apply(alist, dest_p) !=
11172 FILTER_PERMIT)
11173 continue;
11174 }
98ce9a06
DS
11175 if (type == bgp_show_type_filter_list) {
11176 struct as_list *as_list = output_arg;
d62a17ae 11177
40381db7 11178 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11179 != AS_FILTER_PERMIT)
11180 continue;
11181 }
11182 if (type == bgp_show_type_route_map) {
11183 struct route_map *rmap = output_arg;
9b6d8fcf 11184 struct bgp_path_info path;
636632c3
DA
11185 struct bgp_path_info_extra extra;
11186 struct attr dummy_attr = {};
b68885f9 11187 route_map_result_t ret;
d62a17ae 11188
6f4f49b2 11189 dummy_attr = *pi->attr;
d62a17ae 11190
636632c3
DA
11191 prep_for_rmap_apply(&path, &extra, dest, pi,
11192 pi->peer, &dummy_attr);
d62a17ae 11193
1782514f 11194 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11195 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11196 if (ret == RMAP_DENYMATCH)
11197 continue;
11198 }
11199 if (type == bgp_show_type_neighbor
11200 || type == bgp_show_type_flap_neighbor
11201 || type == bgp_show_type_damp_neighbor) {
11202 union sockunion *su = output_arg;
11203
40381db7
DS
11204 if (pi->peer == NULL
11205 || pi->peer->su_remote == NULL
11206 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11207 continue;
11208 }
11209 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11210 uint32_t destination;
d62a17ae 11211
9bcb3eef 11212 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11213 if (IN_CLASSC(destination)
9bcb3eef 11214 && dest_p->prefixlen == 24)
98ce9a06
DS
11215 continue;
11216 if (IN_CLASSB(destination)
9bcb3eef 11217 && dest_p->prefixlen == 16)
98ce9a06
DS
11218 continue;
11219 if (IN_CLASSA(destination)
9bcb3eef 11220 && dest_p->prefixlen == 8)
98ce9a06
DS
11221 continue;
11222 }
11223 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11224 p = output_arg;
9bcb3eef 11225 if (!prefix_match(p, dest_p))
98ce9a06
DS
11226 continue;
11227 }
11228 if (type == bgp_show_type_community_all) {
9a706b42 11229 if (!picomm)
98ce9a06
DS
11230 continue;
11231 }
11232 if (type == bgp_show_type_community) {
11233 struct community *com = output_arg;
d62a17ae 11234
9a706b42 11235 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11236 continue;
11237 }
11238 if (type == bgp_show_type_community_exact) {
11239 struct community *com = output_arg;
d62a17ae 11240
9a706b42 11241 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11242 continue;
11243 }
11244 if (type == bgp_show_type_community_list) {
11245 struct community_list *list = output_arg;
d62a17ae 11246
9a706b42 11247 if (!community_list_match(picomm, list))
98ce9a06
DS
11248 continue;
11249 }
a4d82a8a 11250 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11251 struct community_list *list = output_arg;
d62a17ae 11252
9a706b42 11253 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11254 continue;
11255 }
11256 if (type == bgp_show_type_lcommunity) {
11257 struct lcommunity *lcom = output_arg;
d62a17ae 11258
1bcf3a96
DA
11259 if (!bgp_attr_get_lcommunity(pi->attr) ||
11260 !lcommunity_match(
11261 bgp_attr_get_lcommunity(pi->attr),
11262 lcom))
98ce9a06
DS
11263 continue;
11264 }
36a206db 11265
11266 if (type == bgp_show_type_lcommunity_exact) {
11267 struct lcommunity *lcom = output_arg;
11268
1bcf3a96
DA
11269 if (!bgp_attr_get_lcommunity(pi->attr) ||
11270 !lcommunity_cmp(
11271 bgp_attr_get_lcommunity(pi->attr),
11272 lcom))
36a206db 11273 continue;
11274 }
98ce9a06
DS
11275 if (type == bgp_show_type_lcommunity_list) {
11276 struct community_list *list = output_arg;
d62a17ae 11277
1bcf3a96
DA
11278 if (!lcommunity_list_match(
11279 bgp_attr_get_lcommunity(pi->attr),
11280 list))
98ce9a06
DS
11281 continue;
11282 }
36a206db 11283 if (type
11284 == bgp_show_type_lcommunity_list_exact) {
11285 struct community_list *list = output_arg;
11286
11287 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11288 bgp_attr_get_lcommunity(pi->attr),
11289 list))
36a206db 11290 continue;
11291 }
98ce9a06 11292 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11293 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11294 continue;
11295 }
11296 if (type == bgp_show_type_dampend_paths
11297 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11298 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11299 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11300 continue;
11301 }
11302
11303 if (!use_json && header) {
23d0a753
DA
11304 vty_out(vty,
11305 "BGP table version is %" PRIu64
11306 ", local router ID is %pI4, vrf id ",
11307 table->version, &bgp->router_id);
9df8b37c
PZ
11308 if (bgp->vrf_id == VRF_UNKNOWN)
11309 vty_out(vty, "%s", VRFID_NONE_STR);
11310 else
11311 vty_out(vty, "%u", bgp->vrf_id);
11312 vty_out(vty, "\n");
01eced22
AD
11313 vty_out(vty, "Default local pref %u, ",
11314 bgp->default_local_pref);
11315 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11316 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11317 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11318 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11319 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11320 if (type == bgp_show_type_dampend_paths
11321 || type == bgp_show_type_damp_neighbor)
98ce9a06 11322 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11323 else if (type == bgp_show_type_flap_statistics
11324 || type == bgp_show_type_flap_neighbor)
98ce9a06 11325 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11326 else
ae248832
MK
11327 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11328 : BGP_SHOW_HEADER));
2aad8c42
MS
11329 header = false;
11330
11331 } else if (json_detail && json_paths != NULL) {
11332 const struct prefix_rd *prd;
11333 json_object *jtemp;
11334
11335 /* Use common detail header, for most types;
11336 * need a json 'object'.
11337 */
11338
11339 jtemp = json_object_new_object();
11340 prd = bgp_rd_from_dest(dest, safi);
11341
11342 route_vty_out_detail_header(
11343 vty, bgp, dest, prd, table->afi,
11344 safi, jtemp);
11345
11346 json_object_array_add(json_paths, jtemp);
11347
11348 json_detail = false;
d62a17ae 11349 }
2aad8c42 11350
98ce9a06
DS
11351 if (rd != NULL && !display && !output_count) {
11352 if (!use_json)
11353 vty_out(vty,
11354 "Route Distinguisher: %s\n",
11355 rd);
d62a17ae 11356 }
98ce9a06
DS
11357 if (type == bgp_show_type_dampend_paths
11358 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11359 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11360 AFI_IP, safi, use_json,
11361 json_paths);
98ce9a06
DS
11362 else if (type == bgp_show_type_flap_statistics
11363 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11364 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11365 AFI_IP, safi, use_json,
11366 json_paths);
f280c93b
DA
11367 else {
11368 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11369 route_vty_out_detail(
11370 vty, bgp, dest, pi,
11371 family2afi(dest_p->family),
11372 safi, RPKI_NOT_BEING_USED,
11373 json_paths);
11374 else
11375 route_vty_out(vty, dest_p, pi, display,
11376 safi, json_paths, wide);
11377 }
98ce9a06 11378 display++;
d62a17ae 11379 }
11380
98ce9a06
DS
11381 if (display) {
11382 output_count++;
11383 if (!use_json)
11384 continue;
11385
625d2931 11386 /* encode prefix */
9bcb3eef 11387 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11388 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11389
1840384b 11390
b54892e0
DS
11391 bgp_fs_nlri_get_string(
11392 (unsigned char *)
9bcb3eef
DS
11393 dest_p->u.prefix_flowspec.ptr,
11394 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11395 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11396 family2afi(dest_p->u
11397 .prefix_flowspec.family));
625d2931 11398 if (first)
b54892e0 11399 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11400 dest_p->u.prefix_flowspec
b54892e0 11401 .prefixlen);
625d2931 11402 else
b54892e0 11403 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11404 dest_p->u.prefix_flowspec
b54892e0 11405 .prefixlen);
625d2931 11406 } else {
625d2931 11407 if (first)
1b78780b 11408 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11409 else
1b78780b 11410 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11411 }
3757f964 11412 vty_json(vty, json_paths);
449feb8e 11413 json_paths = NULL;
98ce9a06 11414 first = 0;
1f83ed02
DS
11415 } else
11416 json_object_free(json_paths);
98ce9a06
DS
11417 }
11418
1ae44dfc
LB
11419 if (output_cum) {
11420 output_count += *output_cum;
11421 *output_cum = output_count;
11422 }
11423 if (total_cum) {
11424 total_count += *total_cum;
11425 *total_cum = total_count;
11426 }
d62a17ae 11427 if (use_json) {
9386b588 11428 if (rd) {
a4d82a8a 11429 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11430 }
11431 if (is_last) {
a4d82a8a
PZ
11432 unsigned long i;
11433 for (i = 0; i < *json_header_depth; ++i)
11434 vty_out(vty, " } ");
96f3485c
MK
11435 if (!all)
11436 vty_out(vty, "\n");
9386b588 11437 }
d62a17ae 11438 } else {
1ae44dfc
LB
11439 if (is_last) {
11440 /* No route is displayed */
11441 if (output_count == 0) {
11442 if (type == bgp_show_type_normal)
11443 vty_out(vty,
11444 "No BGP prefixes displayed, %ld exist\n",
11445 total_count);
11446 } else
d62a17ae 11447 vty_out(vty,
1ae44dfc
LB
11448 "\nDisplayed %ld routes and %ld total paths\n",
11449 output_count, total_count);
11450 }
d62a17ae 11451 }
718e3744 11452
d62a17ae 11453 return CMD_SUCCESS;
718e3744 11454}
11455
1ae44dfc
LB
11456int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11457 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11458 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11459{
9bcb3eef 11460 struct bgp_dest *dest, *next;
1ae44dfc
LB
11461 unsigned long output_cum = 0;
11462 unsigned long total_cum = 0;
9386b588 11463 unsigned long json_header_depth = 0;
67009e22 11464 struct bgp_table *itable;
0136788c 11465 bool show_msg;
96c81f66 11466 uint16_t show_flags = 0;
0136788c
LB
11467
11468 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11469
96f3485c
MK
11470 if (use_json)
11471 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11472
9bcb3eef
DS
11473 for (dest = bgp_table_top(table); dest; dest = next) {
11474 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11475
9bcb3eef
DS
11476 next = bgp_route_next(dest);
11477 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11478 continue;
67009e22 11479
9bcb3eef 11480 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11481 if (itable != NULL) {
1ae44dfc 11482 struct prefix_rd prd;
06b9f471 11483 char rd[RD_ADDRSTRLEN];
1ae44dfc 11484
9bcb3eef 11485 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11486 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11487 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11488 rd, next == NULL, &output_cum,
11489 &total_cum, &json_header_depth,
1e2ce4f1 11490 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11491 if (next == NULL)
11492 show_msg = false;
1ae44dfc
LB
11493 }
11494 }
0136788c
LB
11495 if (show_msg) {
11496 if (output_cum == 0)
11497 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11498 total_cum);
11499 else
11500 vty_out(vty,
11501 "\nDisplayed %ld routes and %ld total paths\n",
11502 output_cum, total_cum);
11503 }
1ae44dfc
LB
11504 return CMD_SUCCESS;
11505}
2aad8c42 11506
d62a17ae 11507static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11508 enum bgp_show_type type, void *output_arg,
96c81f66 11509 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11510{
d62a17ae 11511 struct bgp_table *table;
9386b588 11512 unsigned long json_header_depth = 0;
96f3485c 11513 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11514
d62a17ae 11515 if (bgp == NULL) {
11516 bgp = bgp_get_default();
11517 }
fee0f4c6 11518
d62a17ae 11519 if (bgp == NULL) {
11520 if (!use_json)
11521 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11522 else
11523 vty_out(vty, "{}\n");
d62a17ae 11524 return CMD_WARNING;
11525 }
4dd6177e 11526
cd8c2a27
MS
11527 /* Labeled-unicast routes live in the unicast table. */
11528 if (safi == SAFI_LABELED_UNICAST)
11529 safi = SAFI_UNICAST;
11530
1ae44dfc 11531 table = bgp->rib[afi][safi];
d62a17ae 11532 /* use MPLS and ENCAP specific shows until they are merged */
11533 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11534 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11535 output_arg, use_json);
d62a17ae 11536 }
dba3c1d3
PG
11537
11538 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11539 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11540 output_arg, use_json,
11541 1, NULL, NULL);
11542 }
fee0f4c6 11543
96f3485c 11544 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11545 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11546 rpki_target_state);
fee0f4c6 11547}
11548
d62a17ae 11549static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11550 safi_t safi, uint16_t show_flags)
f186de26 11551{
d62a17ae 11552 struct listnode *node, *nnode;
11553 struct bgp *bgp;
11554 int is_first = 1;
9f049418 11555 bool route_output = false;
96f3485c 11556 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11557
d62a17ae 11558 if (use_json)
11559 vty_out(vty, "{\n");
9f689658 11560
d62a17ae 11561 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11562 route_output = true;
d62a17ae 11563 if (use_json) {
11564 if (!is_first)
11565 vty_out(vty, ",\n");
11566 else
11567 is_first = 0;
11568
11569 vty_out(vty, "\"%s\":",
11570 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11571 ? VRF_DEFAULT_NAME
d62a17ae 11572 : bgp->name);
11573 } else {
11574 vty_out(vty, "\nInstance %s:\n",
11575 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11576 ? VRF_DEFAULT_NAME
d62a17ae 11577 : bgp->name);
11578 }
11579 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11580 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11581 }
9f689658 11582
d62a17ae 11583 if (use_json)
11584 vty_out(vty, "}\n");
9f049418
DS
11585 else if (!route_output)
11586 vty_out(vty, "%% BGP instance not found\n");
f186de26 11587}
11588
718e3744 11589/* Header of detailed BGP route information */
d62a17ae 11590void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11591 struct bgp_dest *dest,
11592 const struct prefix_rd *prd,
d62a17ae 11593 afi_t afi, safi_t safi, json_object *json)
11594{
40381db7 11595 struct bgp_path_info *pi;
b54892e0 11596 const struct prefix *p;
d62a17ae 11597 struct peer *peer;
11598 struct listnode *node, *nnode;
06b9f471 11599 char buf1[RD_ADDRSTRLEN];
d62a17ae 11600 int count = 0;
11601 int best = 0;
11602 int suppress = 0;
c5f1e1b2
C
11603 int accept_own = 0;
11604 int route_filter_translated_v4 = 0;
11605 int route_filter_v4 = 0;
11606 int route_filter_translated_v6 = 0;
11607 int route_filter_v6 = 0;
11608 int llgr_stale = 0;
11609 int no_llgr = 0;
11610 int accept_own_nexthop = 0;
11611 int blackhole = 0;
d62a17ae 11612 int no_export = 0;
11613 int no_advertise = 0;
11614 int local_as = 0;
c5f1e1b2 11615 int no_peer = 0;
d62a17ae 11616 int first = 1;
11617 int has_valid_label = 0;
11618 mpls_label_t label = 0;
11619 json_object *json_adv_to = NULL;
67f67ba4
DA
11620 uint32_t ttl = 0;
11621 uint32_t bos = 0;
11622 uint32_t exp = 0;
9bedbb1e 11623
67f67ba4 11624 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11625
67f67ba4
DA
11626 p = bgp_dest_get_prefix(dest);
11627 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11628
44c69747 11629 if (safi == SAFI_EVPN) {
44c69747 11630 if (!json) {
2dbe669b 11631 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11632 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11633 : "",
2dbe669b 11634 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11635 } else {
11636 json_object_string_add(json, "rd",
11637 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11638 "");
11639 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11640 }
11641 } else {
11642 if (!json) {
9119ef3a
DA
11643 vty_out(vty,
11644 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11645 "\n",
d62a17ae 11646 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11647 ? prefix_rd2str(prd, buf1,
11648 sizeof(buf1))
11649 : ""),
9119ef3a
DA
11650 safi == SAFI_MPLS_VPN ? ":" : "", p,
11651 dest->version);
cd1964ff 11652
9119ef3a 11653 } else {
67d7e256 11654 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11655 json_object_int_add(json, "version", dest->version);
11656
11657 }
44c69747
LK
11658 }
11659
11660 if (has_valid_label) {
11661 if (json)
11662 json_object_int_add(json, "localLabel", label);
11663 else
d62a17ae 11664 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11665 }
11666
11667 if (!json)
d62a17ae 11668 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11669 vty_out(vty, "not allocated\n");
718e3744 11670
9bcb3eef 11671 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11672 struct community *picomm = NULL;
11673
11674 picomm = bgp_attr_get_community(pi->attr);
11675
d62a17ae 11676 count++;
40381db7 11677 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11678 best = count;
4056a5f6 11679 if (bgp_path_suppressed(pi))
d62a17ae 11680 suppress = 1;
cee9c031 11681
9a706b42 11682 if (!picomm)
cee9c031
QY
11683 continue;
11684
11685 no_advertise += community_include(
9a706b42
DA
11686 picomm, COMMUNITY_NO_ADVERTISE);
11687 no_export +=
11688 community_include(picomm, COMMUNITY_NO_EXPORT);
11689 local_as +=
11690 community_include(picomm, COMMUNITY_LOCAL_AS);
11691 accept_own +=
11692 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11693 route_filter_translated_v4 += community_include(
9a706b42 11694 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11695 route_filter_translated_v6 += community_include(
9a706b42 11696 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11697 route_filter_v4 += community_include(
9a706b42 11698 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11699 route_filter_v6 += community_include(
9a706b42
DA
11700 picomm, COMMUNITY_ROUTE_FILTER_v6);
11701 llgr_stale +=
11702 community_include(picomm, COMMUNITY_LLGR_STALE);
11703 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11704 accept_own_nexthop += community_include(
11705 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11706 blackhole +=
11707 community_include(picomm, COMMUNITY_BLACKHOLE);
11708 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11709 }
718e3744 11710 }
718e3744 11711
d62a17ae 11712 if (!json) {
11713 vty_out(vty, "Paths: (%d available", count);
11714 if (best) {
11715 vty_out(vty, ", best #%d", best);
b84060bb
PG
11716 if (safi == SAFI_UNICAST) {
11717 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11718 vty_out(vty, ", table %s",
11719 VRF_DEFAULT_NAME);
11720 else
11721 vty_out(vty, ", vrf %s",
11722 bgp->name);
11723 }
d62a17ae 11724 } else
11725 vty_out(vty, ", no best path");
11726
c5f1e1b2
C
11727 if (accept_own)
11728 vty_out(vty,
11729 ", accept own local route exported and imported in different VRF");
11730 else if (route_filter_translated_v4)
11731 vty_out(vty,
11732 ", mark translated RTs for VPNv4 route filtering");
11733 else if (route_filter_v4)
11734 vty_out(vty,
11735 ", attach RT as-is for VPNv4 route filtering");
11736 else if (route_filter_translated_v6)
11737 vty_out(vty,
11738 ", mark translated RTs for VPNv6 route filtering");
11739 else if (route_filter_v6)
11740 vty_out(vty,
11741 ", attach RT as-is for VPNv6 route filtering");
11742 else if (llgr_stale)
11743 vty_out(vty,
1479ed2f 11744 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11745 else if (no_llgr)
11746 vty_out(vty,
11747 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11748 else if (accept_own_nexthop)
11749 vty_out(vty,
11750 ", accept local nexthop");
11751 else if (blackhole)
11752 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11753 else if (no_export)
11754 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11755 else if (no_advertise)
11756 vty_out(vty, ", not advertised to any peer");
d62a17ae 11757 else if (local_as)
11758 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11759 else if (no_peer)
11760 vty_out(vty,
11761 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11762
11763 if (suppress)
11764 vty_out(vty,
11765 ", Advertisements suppressed by an aggregate.");
11766 vty_out(vty, ")\n");
11767 }
718e3744 11768
d62a17ae 11769 /* If we are not using addpath then we can display Advertised to and
11770 * that will
11771 * show what peers we advertised the bestpath to. If we are using
11772 * addpath
11773 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11774 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11775 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11776 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11777 if (json && !json_adv_to)
11778 json_adv_to = json_object_new_object();
11779
11780 route_vty_out_advertised_to(
11781 vty, peer, &first,
11782 " Advertised to non peer-group peers:\n ",
11783 json_adv_to);
11784 }
11785 }
11786
11787 if (json) {
11788 if (json_adv_to) {
11789 json_object_object_add(json, "advertisedTo",
11790 json_adv_to);
11791 }
11792 } else {
11793 if (first)
11794 vty_out(vty, " Not advertised to any peer");
11795 vty_out(vty, "\n");
11796 }
11797 }
718e3744 11798}
11799
edfee30d 11800static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11801 struct bgp_dest *bgp_node, struct vty *vty,
11802 struct bgp *bgp, afi_t afi, safi_t safi,
11803 json_object *json, enum bgp_path_type pathtype,
4027d19b 11804 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11805{
11806 struct bgp_path_info *pi;
11807 int header = 1;
44c69747
LK
11808 json_object *json_header = NULL;
11809 json_object *json_paths = NULL;
4933eaaf 11810 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11811
9bcb3eef 11812 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11813 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11814
11815 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11816 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11817 pi->peer, pi->attr, p);
4933eaaf 11818
4027d19b
DS
11819 if (rpki_target_state != RPKI_NOT_BEING_USED
11820 && rpki_curr_state != rpki_target_state)
4933eaaf 11821 continue;
44c69747
LK
11822
11823 if (json && !json_paths) {
11824 /* Instantiate json_paths only if path is valid */
11825 json_paths = json_object_new_array();
c4f64ea9 11826 if (pfx_rd)
44c69747 11827 json_header = json_object_new_object();
c4f64ea9 11828 else
44c69747
LK
11829 json_header = json;
11830 }
11831
11832 if (header) {
11833 route_vty_out_detail_header(
11834 vty, bgp, bgp_node, pfx_rd,
11835 AFI_IP, safi, json_header);
11836 header = 0;
11837 }
11838 (*display)++;
11839
11840 if (pathtype == BGP_PATH_SHOW_ALL
11841 || (pathtype == BGP_PATH_SHOW_BESTPATH
11842 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11843 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11844 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11845 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11846 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11847 safi, rpki_curr_state, json_paths);
44c69747
LK
11848 }
11849
11850 if (json && json_paths) {
11851 json_object_object_add(json_header, "paths", json_paths);
11852
11853 if (pfx_rd)
c4f64ea9
DA
11854 json_object_object_addf(json, json_header, "%pRD",
11855 pfx_rd);
44c69747
LK
11856 }
11857}
11858
2aad8c42
MS
11859/*
11860 * Return rd based on safi
11861 */
11862static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11863 safi_t safi)
11864{
11865 switch (safi) {
11866 case SAFI_MPLS_VPN:
11867 case SAFI_ENCAP:
11868 case SAFI_EVPN:
11869 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11870 default:
11871 return NULL;
11872
11873 }
11874}
11875
718e3744 11876/* Display specified route of BGP table. */
d62a17ae 11877static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11878 struct bgp_table *rib, const char *ip_str,
11879 afi_t afi, safi_t safi,
4027d19b 11880 enum rpki_states rpki_target_state,
d62a17ae 11881 struct prefix_rd *prd, int prefix_check,
9f049418 11882 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11883{
11884 int ret;
d62a17ae 11885 int display = 0;
11886 struct prefix match;
9bcb3eef
DS
11887 struct bgp_dest *dest;
11888 struct bgp_dest *rm;
d62a17ae 11889 struct bgp_table *table;
11890 json_object *json = NULL;
11891 json_object *json_paths = NULL;
11892
11893 /* Check IP address argument. */
11894 ret = str2prefix(ip_str, &match);
11895 if (!ret) {
11896 vty_out(vty, "address is malformed\n");
11897 return CMD_WARNING;
11898 }
718e3744 11899
d62a17ae 11900 match.family = afi2family(afi);
b05a1c8b 11901
44c69747 11902 if (use_json)
d62a17ae 11903 json = json_object_new_object();
718e3744 11904
44c69747 11905 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11906 for (dest = bgp_table_top(rib); dest;
11907 dest = bgp_route_next(dest)) {
11908 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11909
9bcb3eef 11910 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11911 continue;
9bcb3eef 11912 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11913 if (!table)
ea47320b 11914 continue;
d62a17ae 11915
4953391b
DA
11916 rm = bgp_node_match(table, &match);
11917 if (rm == NULL)
ea47320b 11918 continue;
d62a17ae 11919
9bcb3eef 11920 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11921 if (prefix_check
b54892e0 11922 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11923 bgp_dest_unlock_node(rm);
ea47320b
DL
11924 continue;
11925 }
d62a17ae 11926
9bcb3eef 11927 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11928 bgp, afi, safi, json, pathtype,
4027d19b 11929 &display, rpki_target_state);
44c69747 11930
9bcb3eef 11931 bgp_dest_unlock_node(rm);
44c69747
LK
11932 }
11933 } else if (safi == SAFI_EVPN) {
9bcb3eef 11934 struct bgp_dest *longest_pfx;
cded3b72 11935 bool is_exact_pfxlen_match = false;
44c69747 11936
9bcb3eef
DS
11937 for (dest = bgp_table_top(rib); dest;
11938 dest = bgp_route_next(dest)) {
11939 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11940
9bcb3eef 11941 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11942 continue;
9bcb3eef 11943 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11944 if (!table)
11945 continue;
11946
11947 longest_pfx = NULL;
cded3b72 11948 is_exact_pfxlen_match = false;
44c69747
LK
11949 /*
11950 * Search through all the prefixes for a match. The
11951 * pfx's are enumerated in ascending order of pfxlens.
11952 * So, the last pfx match is the longest match. Set
11953 * is_exact_pfxlen_match when we get exact pfxlen match
11954 */
11955 for (rm = bgp_table_top(table); rm;
11956 rm = bgp_route_next(rm)) {
b54892e0 11957 const struct prefix *rm_p =
9bcb3eef 11958 bgp_dest_get_prefix(rm);
44c69747
LK
11959 /*
11960 * Get prefixlen of the ip-prefix within type5
11961 * evpn route
11962 */
b54892e0
DS
11963 if (evpn_type5_prefix_match(rm_p, &match)
11964 && rm->info) {
44c69747
LK
11965 longest_pfx = rm;
11966 int type5_pfxlen =
b54892e0
DS
11967 bgp_evpn_get_type5_prefixlen(
11968 rm_p);
44c69747 11969 if (type5_pfxlen == match.prefixlen) {
cded3b72 11970 is_exact_pfxlen_match = true;
9bcb3eef 11971 bgp_dest_unlock_node(rm);
44c69747
LK
11972 break;
11973 }
d62a17ae 11974 }
11975 }
ea47320b 11976
44c69747
LK
11977 if (!longest_pfx)
11978 continue;
11979
11980 if (prefix_check && !is_exact_pfxlen_match)
11981 continue;
11982
11983 rm = longest_pfx;
9bcb3eef 11984 bgp_dest_lock_node(rm);
44c69747 11985
9bcb3eef 11986 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11987 bgp, afi, safi, json, pathtype,
4027d19b 11988 &display, rpki_target_state);
44c69747 11989
9bcb3eef 11990 bgp_dest_unlock_node(rm);
d62a17ae 11991 }
98a9dbc7 11992 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11993 if (use_json)
11994 json_paths = json_object_new_array();
11995
63a0b7a9
PG
11996 display = bgp_flowspec_display_match_per_ip(afi, rib,
11997 &match, prefix_check,
11998 vty,
11999 use_json,
12000 json_paths);
d5f20468
SP
12001 if (use_json) {
12002 if (display)
12003 json_object_object_add(json, "paths",
12004 json_paths);
12005 else
12006 json_object_free(json_paths);
12007 }
d62a17ae 12008 } else {
4953391b
DA
12009 dest = bgp_node_match(rib, &match);
12010 if (dest != NULL) {
9bcb3eef 12011 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 12012 if (!prefix_check
9bcb3eef
DS
12013 || dest_p->prefixlen == match.prefixlen) {
12014 bgp_show_path_info(NULL, dest, vty, bgp, afi,
12015 safi, json, pathtype,
4027d19b 12016 &display, rpki_target_state);
d62a17ae 12017 }
12018
9bcb3eef 12019 bgp_dest_unlock_node(dest);
d62a17ae 12020 }
12021 }
e5eee9af 12022
d62a17ae 12023 if (use_json) {
75eeda93 12024 vty_json(vty, json);
d62a17ae 12025 } else {
12026 if (!display) {
12027 vty_out(vty, "%% Network not in table\n");
12028 return CMD_WARNING;
12029 }
12030 }
b05a1c8b 12031
d62a17ae 12032 return CMD_SUCCESS;
718e3744 12033}
12034
fee0f4c6 12035/* Display specified route of Main RIB */
d62a17ae 12036static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12037 afi_t afi, safi_t safi, struct prefix_rd *prd,
12038 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12039 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12040{
9b86009a 12041 if (!bgp) {
d62a17ae 12042 bgp = bgp_get_default();
9b86009a
RW
12043 if (!bgp) {
12044 if (!use_json)
12045 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12046 else
12047 vty_out(vty, "{}\n");
9b86009a
RW
12048 return CMD_WARNING;
12049 }
12050 }
d62a17ae 12051
12052 /* labeled-unicast routes live in the unicast table */
12053 if (safi == SAFI_LABELED_UNICAST)
12054 safi = SAFI_UNICAST;
12055
12056 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12057 afi, safi, rpki_target_state, prd,
8aa22bbb 12058 prefix_check, pathtype, use_json);
d62a17ae 12059}
12060
12061static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12062 struct cmd_token **argv, bool exact, afi_t afi,
12063 safi_t safi, bool uj)
d62a17ae 12064{
12065 struct lcommunity *lcom;
12066 struct buffer *b;
12067 int i;
12068 char *str;
12069 int first = 0;
96c81f66 12070 uint16_t show_flags = 0;
4f28b2b5 12071 int ret;
96f3485c
MK
12072
12073 if (uj)
12074 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12075
12076 b = buffer_new(1024);
12077 for (i = 0; i < argc; i++) {
12078 if (first)
12079 buffer_putc(b, ' ');
12080 else {
12081 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12082 first = 1;
12083 buffer_putstr(b, argv[i]->arg);
12084 }
12085 }
12086 }
12087 buffer_putc(b, '\0');
57d187bc 12088
d62a17ae 12089 str = buffer_getstr(b);
12090 buffer_free(b);
57d187bc 12091
d62a17ae 12092 lcom = lcommunity_str2com(str);
12093 XFREE(MTYPE_TMP, str);
12094 if (!lcom) {
12095 vty_out(vty, "%% Large-community malformed\n");
12096 return CMD_WARNING;
12097 }
57d187bc 12098
4f28b2b5 12099 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12100 (exact ? bgp_show_type_lcommunity_exact
12101 : bgp_show_type_lcommunity),
12102 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12103
12104 lcommunity_free(&lcom);
12105 return ret;
57d187bc
JS
12106}
12107
d62a17ae 12108static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12109 const char *lcom, bool exact, afi_t afi,
12110 safi_t safi, bool uj)
57d187bc 12111{
d62a17ae 12112 struct community_list *list;
96c81f66 12113 uint16_t show_flags = 0;
96f3485c
MK
12114
12115 if (uj)
12116 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12117
57d187bc 12118
e237b0d2 12119 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12120 LARGE_COMMUNITY_LIST_MASTER);
12121 if (list == NULL) {
12122 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12123 lcom);
12124 return CMD_WARNING;
12125 }
57d187bc 12126
36a206db 12127 return bgp_show(vty, bgp, afi, safi,
12128 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12129 : bgp_show_type_lcommunity_list),
1e2ce4f1 12130 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12131}
12132
52951b63
DS
12133DEFUN (show_ip_bgp_large_community_list,
12134 show_ip_bgp_large_community_list_cmd,
77a3a95e 12135 "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
12136 SHOW_STR
12137 IP_STR
12138 BGP_STR
12139 BGP_INSTANCE_HELP_STR
9bedbb1e 12140 BGP_AFI_HELP_STR
4dd6177e 12141 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12142 "Display routes matching the large-community-list\n"
12143 "large-community-list number\n"
12144 "large-community-list name\n"
36a206db 12145 "Exact match of the large-communities\n"
52951b63
DS
12146 JSON_STR)
12147{
d62a17ae 12148 afi_t afi = AFI_IP6;
12149 safi_t safi = SAFI_UNICAST;
12150 int idx = 0;
36a206db 12151 bool exact_match = 0;
4d678463 12152 struct bgp *bgp = NULL;
9f049418 12153 bool uj = use_json(argc, argv);
d62a17ae 12154
ef3364f0
DA
12155 if (uj)
12156 argc--;
4d678463 12157
ef3364f0
DA
12158 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12159 &bgp, uj);
12160 if (!idx)
12161 return CMD_WARNING;
d62a17ae 12162
12163 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12164
12165 const char *clist_number_or_name = argv[++idx]->arg;
12166
12167 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12168 exact_match = 1;
12169
12170 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12171 exact_match, afi, safi, uj);
52951b63
DS
12172}
12173DEFUN (show_ip_bgp_large_community,
12174 show_ip_bgp_large_community_cmd,
36a206db 12175 "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
12176 SHOW_STR
12177 IP_STR
12178 BGP_STR
12179 BGP_INSTANCE_HELP_STR
9bedbb1e 12180 BGP_AFI_HELP_STR
4dd6177e 12181 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12182 "Display routes matching the large-communities\n"
12183 "List of large-community numbers\n"
36a206db 12184 "Exact match of the large-communities\n"
52951b63
DS
12185 JSON_STR)
12186{
d62a17ae 12187 afi_t afi = AFI_IP6;
12188 safi_t safi = SAFI_UNICAST;
12189 int idx = 0;
36a206db 12190 bool exact_match = 0;
4d678463 12191 struct bgp *bgp = NULL;
9f049418 12192 bool uj = use_json(argc, argv);
96c81f66 12193 uint16_t show_flags = 0;
d62a17ae 12194
96f3485c
MK
12195 if (uj) {
12196 argc--;
12197 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12198 }
4d678463 12199
96f3485c
MK
12200 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12201 &bgp, uj);
12202 if (!idx)
12203 return CMD_WARNING;
d62a17ae 12204
36a206db 12205 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12206 if (argv_find(argv, argc, "exact-match", &idx))
12207 exact_match = 1;
12208 return bgp_show_lcommunity(vty, bgp, argc, argv,
12209 exact_match, afi, safi, uj);
12210 } else
d62a17ae 12211 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12212 bgp_show_type_lcommunity_all, NULL, show_flags,
12213 RPKI_NOT_BEING_USED);
52951b63
DS
12214}
12215
71f1613a
DA
12216static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12217 safi_t safi, struct json_object *json_array);
d62a17ae 12218static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12219 safi_t safi, struct json_object *json);
e01ca200 12220
7b2ff250 12221
9ab0cf58
PG
12222DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12223 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12224 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12225 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12226{
12227 bool uj = use_json(argc, argv);
12228 struct bgp *bgp = NULL;
ec76a1d1
DA
12229 safi_t safi = SAFI_UNICAST;
12230 afi_t afi = AFI_IP6;
4265b261 12231 int idx = 0;
6c9d22e2
PG
12232 struct json_object *json_all = NULL;
12233 struct json_object *json_afi_safi = NULL;
4265b261
PG
12234
12235 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12236 &bgp, false);
71f1613a 12237 if (!idx)
4265b261 12238 return CMD_WARNING;
6c9d22e2 12239
4265b261 12240 if (uj)
6c9d22e2 12241 json_all = json_object_new_object();
4265b261 12242
9ab0cf58
PG
12243 FOREACH_AFI_SAFI (afi, safi) {
12244 /*
12245 * So limit output to those afi/safi pairs that
12246 * actually have something interesting in them
12247 */
12248 if (strmatch(get_afi_safi_str(afi, safi, true),
12249 "Unknown")) {
12250 continue;
12251 }
12252 if (uj) {
12253 json_afi_safi = json_object_new_array();
12254 json_object_object_add(
12255 json_all,
12256 get_afi_safi_str(afi, safi, true),
12257 json_afi_safi);
12258 } else {
12259 json_afi_safi = NULL;
6c9d22e2 12260 }
9ab0cf58
PG
12261
12262 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12263 }
6c9d22e2 12264
3757f964
DA
12265 if (uj)
12266 vty_json(vty, json_all);
6c9d22e2 12267
4265b261
PG
12268 return CMD_SUCCESS;
12269}
12270
7b2ff250 12271/* BGP route print out function without JSON */
14718643
PG
12272DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12273 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12274 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12275 SHOW_STR
12276 IP_STR
12277 BGP_STR
12278 BGP_INSTANCE_HELP_STR
12279 L2VPN_HELP_STR
12280 EVPN_HELP_STR
12281 "BGP RIB advertisement statistics\n"
12282 JSON_STR)
12283{
ec76a1d1
DA
12284 afi_t afi = AFI_IP6;
12285 safi_t safi = SAFI_UNICAST;
14718643
PG
12286 struct bgp *bgp = NULL;
12287 int idx = 0, ret;
12288 bool uj = use_json(argc, argv);
12289 struct json_object *json_afi_safi = NULL, *json = NULL;
12290
12291 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12292 &bgp, false);
12293 if (!idx)
12294 return CMD_WARNING;
12295
12296 if (uj)
12297 json_afi_safi = json_object_new_array();
12298 else
12299 json_afi_safi = NULL;
12300
12301 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12302
12303 if (uj) {
12304 json = json_object_new_object();
12305 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12306 json_afi_safi);
3757f964 12307 vty_json(vty, json);
14718643
PG
12308 }
12309 return ret;
12310}
12311
893cccd0 12312/* BGP route print out function without JSON */
9ab0cf58
PG
12313DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12314 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12315 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12316 "]]\
893cccd0 12317 statistics [json]",
9ab0cf58
PG
12318 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12319 BGP_SAFI_WITH_LABEL_HELP_STR
12320 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12321{
ec76a1d1
DA
12322 afi_t afi = AFI_IP6;
12323 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12324 struct bgp *bgp = NULL;
12325 int idx = 0, ret;
12326 bool uj = use_json(argc, argv);
6c9d22e2 12327 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12328
12329 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12330 &bgp, false);
12331 if (!idx)
12332 return CMD_WARNING;
6c9d22e2 12333
893cccd0 12334 if (uj)
6c9d22e2
PG
12335 json_afi_safi = json_object_new_array();
12336 else
12337 json_afi_safi = NULL;
12338
12339 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12340
12341 if (uj) {
12342 json = json_object_new_object();
12343 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12344 json_afi_safi);
3757f964 12345 vty_json(vty, json);
893cccd0
PG
12346 }
12347 return ret;
893cccd0 12348}
7b2ff250 12349
fe0f234d 12350DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12351 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12352 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12353 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12354 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12355 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12356 "Display the entries for all address families\n"
9ab0cf58
PG
12357 "Display detailed information about dampening\n"
12358 "Display detail of configured dampening parameters\n"
fe0f234d 12359 JSON_STR)
718e3744 12360{
d62a17ae 12361 afi_t afi = AFI_IP6;
12362 safi_t safi = SAFI_UNICAST;
d62a17ae 12363 struct bgp *bgp = NULL;
12364 int idx = 0;
96c81f66 12365 uint16_t show_flags = 0;
fe0f234d
RW
12366 bool uj = use_json(argc, argv);
12367
12368 if (uj) {
12369 argc--;
12370 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12371 }
96f3485c
MK
12372
12373 /* [<ipv4|ipv6> [all]] */
12374 if (all) {
12375 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12376 if (argv_find(argv, argc, "ipv4", &idx))
12377 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12378
12379 if (argv_find(argv, argc, "ipv6", &idx))
12380 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12381 }
d62a17ae 12382
12383 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12384 &bgp, false);
d62a17ae 12385 if (!idx)
12386 return CMD_WARNING;
12387
fe0f234d 12388 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12389}
12390
fe0f234d
RW
12391/* BGP route print out function */
12392DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12393 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12394 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12395 "]]\
96f3485c 12396 [all$all]\
cf4898bc
QY
12397 [cidr-only\
12398 |dampening <flap-statistics|dampened-paths>\
12399 |community [AA:NN|local-AS|no-advertise|no-export\
12400 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12401 |accept-own|accept-own-nexthop|route-filter-v6\
12402 |route-filter-v4|route-filter-translated-v6\
12403 |route-filter-translated-v4] [exact-match]\
70799983 12404 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12405 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12406 |prefix-list WORD\
ed126382 12407 |access-list ACCESSLIST_NAME\
70dd370f 12408 |route-map RMAP_NAME\
1e2ce4f1 12409 |rpki <invalid|valid|notfound>\
7d3cae70 12410 |version (1-4294967295)\
b4ad2fae 12411 |alias ALIAS_NAME\
39c3c736
RW
12412 |A.B.C.D/M longer-prefixes\
12413 |X:X::X:X/M longer-prefixes\
f280c93b 12414 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12415 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12416 BGP_SAFI_WITH_LABEL_HELP_STR
12417 "Display the entries for all address families\n"
12418 "Display only routes with non-natural netmasks\n"
12419 "Display detailed information about dampening\n"
12420 "Display flap statistics of routes\n"
12421 "Display paths suppressed due to dampening\n"
12422 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12423 "Do not send outside local AS (well-known community)\n"
12424 "Do not advertise to any peer (well-known community)\n"
12425 "Do not export to next AS (well-known community)\n"
12426 "Graceful shutdown (well-known community)\n"
12427 "Do not export to any peer (well-known community)\n"
12428 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12429 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12430 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12431 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12432 "Should accept VPN route with local nexthop (well-known community)\n"
12433 "RT VPNv6 route filtering (well-known community)\n"
12434 "RT VPNv4 route filtering (well-known community)\n"
12435 "RT translated VPNv6 route filtering (well-known community)\n"
12436 "RT translated VPNv4 route filtering (well-known community)\n"
12437 "Exact match of the communities\n"
70799983
RW
12438 "Community-list number\n"
12439 "Community-list name\n"
12440 "Display routes matching the community-list\n"
12441 "Exact match of the communities\n"
a7129347
RW
12442 "Display routes conforming to the filter-list\n"
12443 "Regular expression access list name\n"
6deaf579
RW
12444 "Display routes conforming to the prefix-list\n"
12445 "Prefix-list name\n"
ed126382
DA
12446 "Display routes conforming to the access-list\n"
12447 "Access-list name\n"
bf1a944a
RW
12448 "Display routes matching the route-map\n"
12449 "A route-map to match on\n"
a70a28a5
DA
12450 "RPKI route types\n"
12451 "A valid path as determined by rpki\n"
12452 "A invalid path as determined by rpki\n"
12453 "A path that has no rpki data\n"
12454 "Display prefixes with matching version numbers\n"
12455 "Version number and above\n"
12456 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12457 "BGP community alias\n"
12458 "IPv4 prefix\n"
12459 "Display route and more specific routes\n"
12460 "IPv6 prefix\n"
12461 "Display route and more specific routes\n"
12462 JSON_STR
a70a28a5
DA
12463 "Display detailed version of JSON output\n"
12464 "Increase table width for longer prefixes\n")
7b2ff250
DW
12465{
12466 afi_t afi = AFI_IP6;
12467 safi_t safi = SAFI_UNICAST;
12468 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12469 void *output_arg = NULL;
7b2ff250
DW
12470 struct bgp *bgp = NULL;
12471 int idx = 0;
d0086e8e 12472 int exact_match = 0;
96f3485c
MK
12473 char *community = NULL;
12474 bool first = true;
96c81f66 12475 uint16_t show_flags = 0;
4027d19b 12476 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12477 struct prefix p;
96f3485c
MK
12478
12479 if (uj) {
9f049418 12480 argc--;
96f3485c
MK
12481 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12482 }
12483
f280c93b
DA
12484 if (detail)
12485 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12486
96f3485c
MK
12487 /* [<ipv4|ipv6> [all]] */
12488 if (all) {
12489 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12490
12491 if (argv_find(argv, argc, "ipv4", &idx))
12492 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12493
12494 if (argv_find(argv, argc, "ipv6", &idx))
12495 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12496 }
12497
12498 if (wide)
12499 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12500
12501 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12502 &bgp, uj);
7b2ff250
DW
12503 if (!idx)
12504 return CMD_WARNING;
12505
7b2ff250 12506 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12507 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12508
12509 if (argv_find(argv, argc, "dampening", &idx)) {
12510 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12511 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12512 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12513 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12514 }
12515
12516 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12517 char *maybecomm = NULL;
d0086e8e 12518
79bc257a
RW
12519 if (idx + 1 < argc) {
12520 if (argv[idx + 1]->type == VARIABLE_TKN)
12521 maybecomm = argv[idx + 1]->arg;
12522 else
12523 maybecomm = argv[idx + 1]->text;
12524 }
12525
cf4898bc
QY
12526 if (maybecomm && !strmatch(maybecomm, "json")
12527 && !strmatch(maybecomm, "exact-match"))
12528 community = maybecomm;
d0086e8e 12529
cf4898bc
QY
12530 if (argv_find(argv, argc, "exact-match", &idx))
12531 exact_match = 1;
d0086e8e 12532
96f3485c
MK
12533 if (!community)
12534 sh_type = bgp_show_type_community_all;
12535 }
12536
70799983
RW
12537 if (argv_find(argv, argc, "community-list", &idx)) {
12538 const char *clist_number_or_name = argv[++idx]->arg;
12539 struct community_list *list;
12540
12541 if (argv_find(argv, argc, "exact-match", &idx))
12542 exact_match = 1;
12543
12544 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12545 COMMUNITY_LIST_MASTER);
12546 if (list == NULL) {
606d49a4 12547 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12548 clist_number_or_name);
12549 return CMD_WARNING;
12550 }
12551
12552 if (exact_match)
12553 sh_type = bgp_show_type_community_list_exact;
12554 else
12555 sh_type = bgp_show_type_community_list;
12556 output_arg = list;
12557 }
12558
a7129347
RW
12559 if (argv_find(argv, argc, "filter-list", &idx)) {
12560 const char *filter = argv[++idx]->arg;
12561 struct as_list *as_list;
12562
12563 as_list = as_list_lookup(filter);
12564 if (as_list == NULL) {
606d49a4 12565 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12566 filter);
12567 return CMD_WARNING;
12568 }
12569
12570 sh_type = bgp_show_type_filter_list;
12571 output_arg = as_list;
12572 }
12573
6deaf579
RW
12574 if (argv_find(argv, argc, "prefix-list", &idx)) {
12575 const char *prefix_list_str = argv[++idx]->arg;
12576 struct prefix_list *plist;
12577
12578 plist = prefix_list_lookup(afi, prefix_list_str);
12579 if (plist == NULL) {
606d49a4 12580 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12581 prefix_list_str);
12582 return CMD_WARNING;
12583 }
12584
12585 sh_type = bgp_show_type_prefix_list;
12586 output_arg = plist;
12587 }
12588
ed126382
DA
12589 if (argv_find(argv, argc, "access-list", &idx)) {
12590 const char *access_list_str = argv[++idx]->arg;
12591 struct access_list *alist;
12592
12593 alist = access_list_lookup(afi, access_list_str);
12594 if (!alist) {
606d49a4 12595 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12596 access_list_str);
12597 return CMD_WARNING;
12598 }
12599
12600 sh_type = bgp_show_type_access_list;
12601 output_arg = alist;
12602 }
12603
bf1a944a
RW
12604 if (argv_find(argv, argc, "route-map", &idx)) {
12605 const char *rmap_str = argv[++idx]->arg;
12606 struct route_map *rmap;
12607
12608 rmap = route_map_lookup_by_name(rmap_str);
12609 if (!rmap) {
606d49a4 12610 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12611 return CMD_WARNING;
12612 }
12613
12614 sh_type = bgp_show_type_route_map;
12615 output_arg = rmap;
12616 }
12617
1e2ce4f1
DS
12618 if (argv_find(argv, argc, "rpki", &idx)) {
12619 sh_type = bgp_show_type_rpki;
12620 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12621 rpki_target_state = RPKI_VALID;
1e2ce4f1 12622 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12623 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12624 }
12625
7d3cae70
DA
12626 /* Display prefixes with matching version numbers */
12627 if (argv_find(argv, argc, "version", &idx)) {
12628 sh_type = bgp_show_type_prefix_version;
2391833e 12629 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12630 }
12631
a70a28a5
DA
12632 /* Display prefixes with matching BGP community alias */
12633 if (argv_find(argv, argc, "alias", &idx)) {
12634 sh_type = bgp_show_type_community_alias;
2391833e 12635 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12636 }
12637
39c3c736
RW
12638 /* prefix-longer */
12639 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12640 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12641 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12642
12643 if (!str2prefix(prefix_str, &p)) {
12644 vty_out(vty, "%% Malformed Prefix\n");
12645 return CMD_WARNING;
12646 }
12647
12648 sh_type = bgp_show_type_prefix_longer;
12649 output_arg = &p;
a70a28a5
DA
12650 }
12651
96f3485c
MK
12652 if (!all) {
12653 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12654 if (community)
12655 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12656 exact_match, afi, safi,
12657 show_flags);
2391833e 12658 else
a70a28a5 12659 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12660 output_arg, show_flags,
a70a28a5 12661 rpki_target_state);
96f3485c 12662 } else {
fa5ac378
DA
12663 struct listnode *node;
12664 struct bgp *abgp;
96f3485c
MK
12665 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12666 * AFI_IP6 */
12667
12668 if (uj)
12669 vty_out(vty, "{\n");
12670
12671 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12672 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12673 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12674 ? AFI_IP
12675 : AFI_IP6;
fa5ac378
DA
12676 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12677 FOREACH_SAFI (safi) {
12678 if (!bgp_afi_safi_peer_exists(abgp, afi,
12679 safi))
12680 continue;
96f3485c 12681
fa5ac378
DA
12682 if (uj) {
12683 if (first)
12684 first = false;
12685 else
12686 vty_out(vty, ",\n");
12687 vty_out(vty, "\"%s\":{\n",
12688 get_afi_safi_str(afi,
12689 safi,
12690 true));
12691 } else
12692 vty_out(vty,
12693 "\nFor address family: %s\n",
12694 get_afi_safi_str(
12695 afi, safi,
12696 false));
12697
12698 if (community)
12699 bgp_show_community(
12700 vty, abgp, community,
12701 exact_match, afi, safi,
12702 show_flags);
96f3485c 12703 else
fa5ac378
DA
12704 bgp_show(vty, abgp, afi, safi,
12705 sh_type, output_arg,
12706 show_flags,
12707 rpki_target_state);
12708 if (uj)
12709 vty_out(vty, "}\n");
12710 }
96f3485c
MK
12711 }
12712 } else {
12713 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12714 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12715 FOREACH_AFI_SAFI (afi, safi) {
12716 if (!bgp_afi_safi_peer_exists(abgp, afi,
12717 safi))
12718 continue;
96f3485c 12719
fa5ac378
DA
12720 if (uj) {
12721 if (first)
12722 first = false;
12723 else
12724 vty_out(vty, ",\n");
12725
12726 vty_out(vty, "\"%s\":{\n",
12727 get_afi_safi_str(afi,
12728 safi,
12729 true));
12730 } else
12731 vty_out(vty,
12732 "\nFor address family: %s\n",
12733 get_afi_safi_str(
12734 afi, safi,
12735 false));
12736
12737 if (community)
12738 bgp_show_community(
12739 vty, abgp, community,
12740 exact_match, afi, safi,
12741 show_flags);
96f3485c 12742 else
fa5ac378
DA
12743 bgp_show(vty, abgp, afi, safi,
12744 sh_type, output_arg,
12745 show_flags,
12746 rpki_target_state);
12747 if (uj)
12748 vty_out(vty, "}\n");
12749 }
96f3485c
MK
12750 }
12751 }
12752 if (uj)
12753 vty_out(vty, "}\n");
12754 }
12755 return CMD_SUCCESS;
a636c635 12756}
47fc97cc 12757
718e3744 12758DEFUN (show_ip_bgp_route,
12759 show_ip_bgp_route_cmd,
8aa22bbb 12760 "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 12761 SHOW_STR
12762 IP_STR
12763 BGP_STR
a636c635 12764 BGP_INSTANCE_HELP_STR
4f280b15 12765 BGP_AFI_HELP_STR
4dd6177e 12766 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12767 "Network in the BGP routing table to display\n"
0c7b1b01 12768 "IPv4 prefix\n"
8c3deaae 12769 "Network in the BGP routing table to display\n"
0c7b1b01 12770 "IPv6 prefix\n"
4092b06c 12771 "Display only the bestpath\n"
b05a1c8b 12772 "Display only multipaths\n"
8aa22bbb
DS
12773 "Display only paths that match the specified rpki state\n"
12774 "A valid path as determined by rpki\n"
12775 "A invalid path as determined by rpki\n"
12776 "A path that has no rpki data\n"
9973d184 12777 JSON_STR)
4092b06c 12778{
d62a17ae 12779 int prefix_check = 0;
ae19d7dd 12780
d62a17ae 12781 afi_t afi = AFI_IP6;
12782 safi_t safi = SAFI_UNICAST;
12783 char *prefix = NULL;
12784 struct bgp *bgp = NULL;
12785 enum bgp_path_type path_type;
9f049418 12786 bool uj = use_json(argc, argv);
b05a1c8b 12787
d62a17ae 12788 int idx = 0;
ae19d7dd 12789
d62a17ae 12790 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12791 &bgp, uj);
d62a17ae 12792 if (!idx)
12793 return CMD_WARNING;
c41247f5 12794
d62a17ae 12795 if (!bgp) {
12796 vty_out(vty,
12797 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12798 return CMD_WARNING;
12799 }
a636c635 12800
d62a17ae 12801 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12802 if (argv_find(argv, argc, "A.B.C.D", &idx)
12803 || argv_find(argv, argc, "X:X::X:X", &idx))
12804 prefix_check = 0;
12805 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12806 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12807 prefix_check = 1;
12808
12809 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12810 && afi != AFI_IP6) {
12811 vty_out(vty,
12812 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12813 return CMD_WARNING;
12814 }
12815 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12816 && afi != AFI_IP) {
12817 vty_out(vty,
12818 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12819 return CMD_WARNING;
12820 }
12821
12822 prefix = argv[idx]->arg;
12823
12824 /* [<bestpath|multipath>] */
12825 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12826 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12827 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12828 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12829 else
360660c6 12830 path_type = BGP_PATH_SHOW_ALL;
a636c635 12831
d62a17ae 12832 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12833 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12834}
12835
8c3deaae
QY
12836DEFUN (show_ip_bgp_regexp,
12837 show_ip_bgp_regexp_cmd,
3e5b31b3 12838 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12839 SHOW_STR
12840 IP_STR
12841 BGP_STR
b00b230a 12842 BGP_INSTANCE_HELP_STR
4f280b15 12843 BGP_AFI_HELP_STR
4dd6177e 12844 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12845 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12846 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12847 JSON_STR)
8c3deaae 12848{
d62a17ae 12849 afi_t afi = AFI_IP6;
12850 safi_t safi = SAFI_UNICAST;
12851 struct bgp *bgp = NULL;
3e5b31b3
DA
12852 bool uj = use_json(argc, argv);
12853 char *regstr = NULL;
8c3deaae 12854
d62a17ae 12855 int idx = 0;
12856 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12857 &bgp, false);
d62a17ae 12858 if (!idx)
12859 return CMD_WARNING;
8c3deaae 12860
d62a17ae 12861 // get index of regex
3e5b31b3
DA
12862 if (argv_find(argv, argc, "REGEX", &idx))
12863 regstr = argv[idx]->arg;
8c3deaae 12864
5f71d11c 12865 assert(regstr);
3e5b31b3
DA
12866 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12867 bgp_show_type_regexp, uj);
8c3deaae
QY
12868}
12869
ae248832 12870DEFPY (show_ip_bgp_instance_all,
a636c635 12871 show_ip_bgp_instance_all_cmd,
ae248832 12872 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12873 SHOW_STR
a636c635 12874 IP_STR
4092b06c 12875 BGP_STR
a636c635 12876 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12877 BGP_AFI_HELP_STR
4dd6177e 12878 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12879 JSON_STR
12880 "Increase table width for longer prefixes\n")
4092b06c 12881{
54d05dea 12882 afi_t afi = AFI_IP6;
d62a17ae 12883 safi_t safi = SAFI_UNICAST;
12884 struct bgp *bgp = NULL;
d62a17ae 12885 int idx = 0;
96c81f66 12886 uint16_t show_flags = 0;
ae19d7dd 12887
96f3485c 12888 if (uj) {
d62a17ae 12889 argc--;
96f3485c
MK
12890 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12891 }
12892
12893 if (wide)
12894 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12895
9f049418
DS
12896 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12897 &bgp, uj);
12898 if (!idx)
12899 return CMD_WARNING;
12900
96f3485c 12901 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12902 return CMD_SUCCESS;
e3e29b32
LB
12903}
12904
a4d82a8a 12905static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12906 afi_t afi, safi_t safi, enum bgp_show_type type,
12907 bool use_json)
718e3744 12908{
d62a17ae 12909 regex_t *regex;
12910 int rc;
96c81f66 12911 uint16_t show_flags = 0;
96f3485c
MK
12912
12913 if (use_json)
12914 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12915
c3900853 12916 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12917 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12918 regstr);
12919 return CMD_WARNING_CONFIG_FAILED;
12920 }
12921
d62a17ae 12922 regex = bgp_regcomp(regstr);
12923 if (!regex) {
12924 vty_out(vty, "Can't compile regexp %s\n", regstr);
12925 return CMD_WARNING;
12926 }
a636c635 12927
1e2ce4f1
DS
12928 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12929 RPKI_NOT_BEING_USED);
d62a17ae 12930 bgp_regex_free(regex);
12931 return rc;
e3e29b32
LB
12932}
12933
7f323236
DW
12934static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12935 const char *comstr, int exact, afi_t afi,
96c81f66 12936 safi_t safi, uint16_t show_flags)
d62a17ae 12937{
12938 struct community *com;
d62a17ae 12939 int ret = 0;
12940
7f323236 12941 com = community_str2com(comstr);
d62a17ae 12942 if (!com) {
7f323236 12943 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12944 return CMD_WARNING;
12945 }
12946
12947 ret = bgp_show(vty, bgp, afi, safi,
12948 (exact ? bgp_show_type_community_exact
12949 : bgp_show_type_community),
1e2ce4f1 12950 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12951 community_free(&com);
46c3ce83 12952
d62a17ae 12953 return ret;
718e3744 12954}
12955
d62a17ae 12956enum bgp_stats {
12957 BGP_STATS_MAXBITLEN = 0,
12958 BGP_STATS_RIB,
12959 BGP_STATS_PREFIXES,
12960 BGP_STATS_TOTPLEN,
12961 BGP_STATS_UNAGGREGATEABLE,
12962 BGP_STATS_MAX_AGGREGATEABLE,
12963 BGP_STATS_AGGREGATES,
12964 BGP_STATS_SPACE,
12965 BGP_STATS_ASPATH_COUNT,
12966 BGP_STATS_ASPATH_MAXHOPS,
12967 BGP_STATS_ASPATH_TOTHOPS,
12968 BGP_STATS_ASPATH_MAXSIZE,
12969 BGP_STATS_ASPATH_TOTSIZE,
12970 BGP_STATS_ASN_HIGHEST,
12971 BGP_STATS_MAX,
a636c635 12972};
2815e61f 12973
9ab0cf58 12974#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12975#define TABLE_STATS_IDX_JSON 1
12976
12977static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12978 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12979 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12980 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12981 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12982 "unaggregateablePrefixes"},
12983 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12984 "maximumAggregateablePrefixes"},
12985 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12986 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12987 [BGP_STATS_SPACE] = {"Address space advertised",
12988 "addressSpaceAdvertised"},
9ab0cf58
PG
12989 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12990 "advertisementsWithPaths"},
12991 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12992 "longestAsPath"},
12993 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12994 "largestAsPath"},
12995 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12996 "averageAsPathLengthHops"},
12997 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12998 "averageAsPathSizeBytes"},
12999 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 13000 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 13001};
2815e61f 13002
d62a17ae 13003struct bgp_table_stats {
13004 struct bgp_table *table;
13005 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
13006
13007 unsigned long long
13008 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
13009 1];
13010
8d0ab76d 13011 double total_space;
ff7924f6
PJ
13012};
13013
9bcb3eef 13014static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 13015 struct bgp_table_stats *ts, unsigned int space)
2815e61f 13016{
9bcb3eef 13017 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 13018 struct bgp_path_info *pi;
b54892e0 13019 const struct prefix *rn_p;
d62a17ae 13020
9bcb3eef 13021 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 13022 return;
d62a17ae 13023
9bcb3eef 13024 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 13025 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 13026 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 13027
0747643e 13028 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 13029 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
13030 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
13031 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 13032
9bcb3eef 13033 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13034 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13035 /* announced address space */
13036 if (space)
b54892e0 13037 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13038 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13039 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13040
9c14ec72 13041
9bcb3eef 13042 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13043 ts->counts[BGP_STATS_RIB]++;
13044
05864da7
DS
13045 if (CHECK_FLAG(pi->attr->flag,
13046 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13047 ts->counts[BGP_STATS_AGGREGATES]++;
13048
13049 /* as-path stats */
05864da7 13050 if (pi->attr->aspath) {
9c14ec72
RW
13051 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13052 unsigned int size = aspath_size(pi->attr->aspath);
13053 as_t highest = aspath_highest(pi->attr->aspath);
13054
13055 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13056
13057 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13058 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13059
13060 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13061 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13062
13063 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13064 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13065 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13066 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13067 }
13068 }
13069}
13070
cc9f21da 13071static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13072{
9bcb3eef
DS
13073 struct bgp_dest *dest, *ndest;
13074 struct bgp_dest *top;
9c14ec72
RW
13075 struct bgp_table_stats *ts = THREAD_ARG(t);
13076 unsigned int space = 0;
13077
13078 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13079 return;
9c14ec72
RW
13080
13081 switch (ts->table->afi) {
13082 case AFI_IP:
13083 space = IPV4_MAX_BITLEN;
13084 break;
13085 case AFI_IP6:
13086 space = IPV6_MAX_BITLEN;
13087 break;
3ba7b4af
TA
13088 case AFI_L2VPN:
13089 space = EVPN_ROUTE_PREFIXLEN;
13090 break;
9c14ec72 13091 default:
cc9f21da 13092 return;
9c14ec72
RW
13093 }
13094
13095 ts->counts[BGP_STATS_MAXBITLEN] = space;
13096
9bcb3eef 13097 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13098 if (ts->table->safi == SAFI_MPLS_VPN
13099 || ts->table->safi == SAFI_ENCAP
13100 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13101 struct bgp_table *table;
13102
9bcb3eef 13103 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13104 if (!table)
13105 continue;
13106
13107 top = bgp_table_top(table);
9bcb3eef
DS
13108 for (ndest = bgp_table_top(table); ndest;
13109 ndest = bgp_route_next(ndest))
13110 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13111 } else {
9bcb3eef 13112 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13113 }
13114 }
2815e61f 13115}
ff7924f6 13116
71f1613a
DA
13117static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13118 struct json_object *json_array)
13119{
13120 struct listnode *node, *nnode;
13121 struct bgp *bgp;
13122
13123 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13124 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13125}
13126
13127static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13128 safi_t safi, struct json_object *json_array)
2815e61f 13129{
d62a17ae 13130 struct bgp_table_stats ts;
13131 unsigned int i;
893cccd0
PG
13132 int ret = CMD_SUCCESS;
13133 char temp_buf[20];
6c9d22e2 13134 struct json_object *json = NULL;
0747643e
AQ
13135 uint32_t bitlen = 0;
13136 struct json_object *json_bitlen;
6c9d22e2
PG
13137
13138 if (json_array)
13139 json = json_object_new_object();
019386c2 13140
d62a17ae 13141 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13142 char warning_msg[50];
13143
13144 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13145 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13146 safi);
6c9d22e2
PG
13147
13148 if (!json)
893cccd0
PG
13149 vty_out(vty, "%s\n", warning_msg);
13150 else
9ab0cf58 13151 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13152
893cccd0
PG
13153 ret = CMD_WARNING;
13154 goto end_table_stats;
d62a17ae 13155 }
019386c2 13156
893cccd0 13157 if (!json)
5290ceab
DA
13158 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13159 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13160 else
13161 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13162
d62a17ae 13163 /* labeled-unicast routes live in the unicast table */
13164 if (safi == SAFI_LABELED_UNICAST)
13165 safi = SAFI_UNICAST;
019386c2 13166
d62a17ae 13167 memset(&ts, 0, sizeof(ts));
13168 ts.table = bgp->rib[afi][safi];
13169 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13170
d62a17ae 13171 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13172 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13173 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13174 continue;
13175
13176 switch (i) {
d62a17ae 13177 case BGP_STATS_ASPATH_TOTHOPS:
13178 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13179 if (!json) {
9ab0cf58
PG
13180 snprintf(
13181 temp_buf, sizeof(temp_buf), "%12.2f",
13182 ts.counts[i]
13183 ? (float)ts.counts[i]
13184 / (float)ts.counts
13185 [BGP_STATS_ASPATH_COUNT]
13186 : 0);
893cccd0 13187 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13188 table_stats_strs[i]
13189 [TABLE_STATS_IDX_VTY],
893cccd0 13190 temp_buf);
9ab0cf58
PG
13191 } else {
13192 json_object_double_add(
13193 json,
13194 table_stats_strs[i]
13195 [TABLE_STATS_IDX_JSON],
13196 ts.counts[i]
13197 ? (double)ts.counts[i]
13198 / (double)ts.counts
d62a17ae 13199 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13200 : 0);
13201 }
d62a17ae 13202 break;
13203 case BGP_STATS_TOTPLEN:
6c9d22e2 13204 if (!json) {
9ab0cf58
PG
13205 snprintf(
13206 temp_buf, sizeof(temp_buf), "%12.2f",
13207 ts.counts[i]
13208 ? (float)ts.counts[i]
13209 / (float)ts.counts
13210 [BGP_STATS_PREFIXES]
13211 : 0);
893cccd0 13212 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13213 table_stats_strs[i]
13214 [TABLE_STATS_IDX_VTY],
893cccd0 13215 temp_buf);
9ab0cf58
PG
13216 } else {
13217 json_object_double_add(
13218 json,
13219 table_stats_strs[i]
13220 [TABLE_STATS_IDX_JSON],
13221 ts.counts[i]
13222 ? (double)ts.counts[i]
13223 / (double)ts.counts
d62a17ae 13224 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13225 : 0);
13226 }
d62a17ae 13227 break;
13228 case BGP_STATS_SPACE:
6c9d22e2
PG
13229 if (!json) {
13230 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13231 ts.total_space);
893cccd0 13232 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13233 table_stats_strs[i]
13234 [TABLE_STATS_IDX_VTY],
893cccd0 13235 temp_buf);
9ab0cf58
PG
13236 } else {
13237 json_object_double_add(
13238 json,
13239 table_stats_strs[i]
13240 [TABLE_STATS_IDX_JSON],
13241 (double)ts.total_space);
13242 }
8d0ab76d 13243 if (afi == AFI_IP6) {
6c9d22e2
PG
13244 if (!json) {
13245 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13246 "%12g",
13247 ts.total_space
13248 * pow(2.0, -128 + 32));
6c9d22e2
PG
13249 vty_out(vty, "%30s: %s\n",
13250 "/32 equivalent %s\n",
13251 temp_buf);
9ab0cf58
PG
13252 } else {
13253 json_object_double_add(
13254 json, "/32equivalent",
13255 (double)(ts.total_space
13256 * pow(2.0,
13257 -128 + 32)));
13258 }
6c9d22e2
PG
13259 if (!json) {
13260 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13261 "%12g",
13262 ts.total_space
13263 * pow(2.0, -128 + 48));
6c9d22e2
PG
13264 vty_out(vty, "%30s: %s\n",
13265 "/48 equivalent %s\n",
13266 temp_buf);
9ab0cf58
PG
13267 } else {
13268 json_object_double_add(
13269 json, "/48equivalent",
13270 (double)(ts.total_space
13271 * pow(2.0,
13272 -128 + 48)));
13273 }
8d0ab76d 13274 } else {
6c9d22e2
PG
13275 if (!json) {
13276 snprintf(temp_buf, sizeof(temp_buf),
13277 "%12.2f",
9ab0cf58
PG
13278 ts.total_space * 100.
13279 * pow(2.0, -32));
6c9d22e2 13280 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13281 "% announced ", temp_buf);
13282 } else {
13283 json_object_double_add(
13284 json, "%announced",
13285 (double)(ts.total_space * 100.
13286 * pow(2.0, -32)));
13287 }
6c9d22e2
PG
13288 if (!json) {
13289 snprintf(temp_buf, sizeof(temp_buf),
13290 "%12.2f",
9ab0cf58
PG
13291 ts.total_space
13292 * pow(2.0, -32 + 8));
6c9d22e2
PG
13293 vty_out(vty, "%30s: %s\n",
13294 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13295 } else {
13296 json_object_double_add(
13297 json, "/8equivalent",
13298 (double)(ts.total_space
13299 * pow(2.0, -32 + 8)));
13300 }
6c9d22e2
PG
13301 if (!json) {
13302 snprintf(temp_buf, sizeof(temp_buf),
13303 "%12.2f",
9ab0cf58
PG
13304 ts.total_space
13305 * pow(2.0, -32 + 24));
6c9d22e2 13306 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13307 "/24 equivalent ", temp_buf);
13308 } else {
13309 json_object_double_add(
13310 json, "/24equivalent",
13311 (double)(ts.total_space
13312 * pow(2.0, -32 + 24)));
13313 }
8d0ab76d 13314 }
d62a17ae 13315 break;
13316 default:
6c9d22e2
PG
13317 if (!json) {
13318 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13319 ts.counts[i]);
893cccd0 13320 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13321 table_stats_strs[i]
13322 [TABLE_STATS_IDX_VTY],
13323 temp_buf);
13324 } else {
13325 json_object_int_add(
13326 json,
13327 table_stats_strs[i]
13328 [TABLE_STATS_IDX_JSON],
13329 ts.counts[i]);
13330 }
d62a17ae 13331 }
893cccd0
PG
13332 if (!json)
13333 vty_out(vty, "\n");
d62a17ae 13334 }
0747643e
AQ
13335
13336 switch (afi) {
13337 case AFI_IP:
13338 bitlen = IPV4_MAX_BITLEN;
13339 break;
13340 case AFI_IP6:
13341 bitlen = IPV6_MAX_BITLEN;
13342 break;
13343 case AFI_L2VPN:
13344 bitlen = EVPN_ROUTE_PREFIXLEN;
13345 break;
13346 default:
13347 break;
13348 }
13349
13350 if (json) {
13351 json_bitlen = json_object_new_array();
13352
13353 for (i = 0; i <= bitlen; i++) {
13354 struct json_object *ind_bit = json_object_new_object();
13355
13356 if (!ts.prefix_len_count[i])
13357 continue;
13358
13359 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13360 json_object_int_add(ind_bit, temp_buf,
13361 ts.prefix_len_count[i]);
13362 json_object_array_add(json_bitlen, ind_bit);
13363 }
13364 json_object_object_add(json, "prefixLength", json_bitlen);
13365 }
13366
9ab0cf58 13367end_table_stats:
6c9d22e2
PG
13368 if (json)
13369 json_object_array_add(json_array, json);
893cccd0 13370 return ret;
d62a17ae 13371}
13372
71f1613a
DA
13373static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13374 safi_t safi, struct json_object *json_array)
13375{
13376 if (!bgp) {
13377 bgp_table_stats_all(vty, afi, safi, json_array);
13378 return CMD_SUCCESS;
13379 }
13380
13381 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13382}
13383
d62a17ae 13384enum bgp_pcounts {
13385 PCOUNT_ADJ_IN = 0,
13386 PCOUNT_DAMPED,
13387 PCOUNT_REMOVED,
13388 PCOUNT_HISTORY,
13389 PCOUNT_STALE,
13390 PCOUNT_VALID,
13391 PCOUNT_ALL,
13392 PCOUNT_COUNTED,
7e3d9632 13393 PCOUNT_BPATH_SELECTED,
d62a17ae 13394 PCOUNT_PFCNT, /* the figure we display to users */
13395 PCOUNT_MAX,
a636c635 13396};
718e3744 13397
2b64873d 13398static const char *const pcount_strs[] = {
9d303b37
DL
13399 [PCOUNT_ADJ_IN] = "Adj-in",
13400 [PCOUNT_DAMPED] = "Damped",
13401 [PCOUNT_REMOVED] = "Removed",
13402 [PCOUNT_HISTORY] = "History",
13403 [PCOUNT_STALE] = "Stale",
13404 [PCOUNT_VALID] = "Valid",
13405 [PCOUNT_ALL] = "All RIB",
13406 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13407 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13408 [PCOUNT_PFCNT] = "Useable",
13409 [PCOUNT_MAX] = NULL,
a636c635 13410};
718e3744 13411
d62a17ae 13412struct peer_pcounts {
13413 unsigned int count[PCOUNT_MAX];
13414 const struct peer *peer;
13415 const struct bgp_table *table;
54317cba 13416 safi_t safi;
a636c635 13417};
47fc97cc 13418
9bcb3eef 13419static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13420{
54317cba
JW
13421 const struct bgp_adj_in *ain;
13422 const struct bgp_path_info *pi;
d62a17ae 13423 const struct peer *peer = pc->peer;
13424
54317cba
JW
13425 for (ain = rn->adj_in; ain; ain = ain->next)
13426 if (ain->peer == peer)
13427 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13428
9bcb3eef 13429 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13430
54317cba
JW
13431 if (pi->peer != peer)
13432 continue;
d62a17ae 13433
54317cba 13434 pc->count[PCOUNT_ALL]++;
d62a17ae 13435
54317cba
JW
13436 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13437 pc->count[PCOUNT_DAMPED]++;
13438 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13439 pc->count[PCOUNT_HISTORY]++;
13440 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13441 pc->count[PCOUNT_REMOVED]++;
13442 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13443 pc->count[PCOUNT_STALE]++;
13444 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13445 pc->count[PCOUNT_VALID]++;
13446 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13447 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13448 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13449 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13450
13451 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13452 pc->count[PCOUNT_COUNTED]++;
13453 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13454 flog_err(
13455 EC_LIB_DEVELOPMENT,
13456 "Attempting to count but flags say it is unusable");
13457 } else {
40381db7 13458 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13459 flog_err(
13460 EC_LIB_DEVELOPMENT,
13461 "Not counted but flags say we should");
d62a17ae 13462 }
13463 }
54317cba
JW
13464}
13465
cc9f21da 13466static void bgp_peer_count_walker(struct thread *t)
54317cba 13467{
9bcb3eef 13468 struct bgp_dest *rn, *rm;
54317cba
JW
13469 const struct bgp_table *table;
13470 struct peer_pcounts *pc = THREAD_ARG(t);
13471
13472 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13473 || pc->safi == SAFI_EVPN) {
13474 /* Special handling for 2-level routing tables. */
13475 for (rn = bgp_table_top(pc->table); rn;
13476 rn = bgp_route_next(rn)) {
9bcb3eef 13477 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13478 if (table != NULL)
13479 for (rm = bgp_table_top(table); rm;
13480 rm = bgp_route_next(rm))
13481 bgp_peer_count_proc(rm, pc);
13482 }
13483 } else
13484 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13485 bgp_peer_count_proc(rn, pc);
718e3744 13486}
13487
d62a17ae 13488static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13489 safi_t safi, bool use_json)
856ca177 13490{
d62a17ae 13491 struct peer_pcounts pcounts = {.peer = peer};
13492 unsigned int i;
13493 json_object *json = NULL;
13494 json_object *json_loop = NULL;
856ca177 13495
d62a17ae 13496 if (use_json) {
13497 json = json_object_new_object();
13498 json_loop = json_object_new_object();
13499 }
718e3744 13500
d62a17ae 13501 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13502 || !peer->bgp->rib[afi][safi]) {
13503 if (use_json) {
13504 json_object_string_add(
13505 json, "warning",
13506 "No such neighbor or address family");
13507 vty_out(vty, "%s\n", json_object_to_json_string(json));
13508 json_object_free(json);
d5f20468 13509 json_object_free(json_loop);
d62a17ae 13510 } else
13511 vty_out(vty, "%% No such neighbor or address family\n");
13512
13513 return CMD_WARNING;
13514 }
2a71e9ce 13515
d62a17ae 13516 memset(&pcounts, 0, sizeof(pcounts));
13517 pcounts.peer = peer;
13518 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13519 pcounts.safi = safi;
d62a17ae 13520
13521 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13522 * stats for the thread-walk (i.e. ensure this can't be blamed on
13523 * on just vty_read()).
13524 */
d62a17ae 13525 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13526
13527 if (use_json) {
13528 json_object_string_add(json, "prefixCountsFor", peer->host);
13529 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13530 get_afi_safi_str(afi, safi, true));
d62a17ae 13531 json_object_int_add(json, "pfxCounter",
13532 peer->pcount[afi][safi]);
13533
13534 for (i = 0; i < PCOUNT_MAX; i++)
13535 json_object_int_add(json_loop, pcount_strs[i],
13536 pcounts.count[i]);
13537
13538 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13539
13540 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13541 json_object_string_add(json, "pfxctDriftFor",
13542 peer->host);
13543 json_object_string_add(
13544 json, "recommended",
13545 "Please report this bug, with the above command output");
13546 }
75eeda93 13547 vty_json(vty, json);
d62a17ae 13548 } else {
13549
13550 if (peer->hostname
892fedb6 13551 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13552 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13553 peer->hostname, peer->host,
5cb5f4d0 13554 get_afi_safi_str(afi, safi, false));
d62a17ae 13555 } else {
13556 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13557 get_afi_safi_str(afi, safi, false));
d62a17ae 13558 }
13559
6cde4b45 13560 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13561 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13562
13563 for (i = 0; i < PCOUNT_MAX; i++)
13564 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13565 pcounts.count[i]);
13566
13567 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13568 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13569 vty_out(vty,
13570 "Please report this bug, with the above command output\n");
13571 }
13572 }
13573
13574 return CMD_SUCCESS;
718e3744 13575}
13576
a636c635
DW
13577DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13578 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13579 "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 13580 SHOW_STR
13581 IP_STR
13582 BGP_STR
8386ac43 13583 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13584 BGP_AFI_HELP_STR
13585 BGP_SAFI_HELP_STR
0b16f239
DS
13586 "Detailed information on TCP and BGP neighbor connections\n"
13587 "Neighbor to display information about\n"
13588 "Neighbor to display information about\n"
91d37724 13589 "Neighbor on BGP configured interface\n"
a636c635 13590 "Display detailed prefix count information\n"
9973d184 13591 JSON_STR)
0b16f239 13592{
d62a17ae 13593 afi_t afi = AFI_IP6;
13594 safi_t safi = SAFI_UNICAST;
13595 struct peer *peer;
13596 int idx = 0;
13597 struct bgp *bgp = NULL;
9f049418
DS
13598 bool uj = use_json(argc, argv);
13599
13600 if (uj)
13601 argc--;
856ca177 13602
d62a17ae 13603 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13604 &bgp, uj);
d62a17ae 13605 if (!idx)
13606 return CMD_WARNING;
0b16f239 13607
d62a17ae 13608 argv_find(argv, argc, "neighbors", &idx);
13609 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13610 if (!peer)
13611 return CMD_WARNING;
bb46e94f 13612
29c8d9da 13613 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13614}
0b16f239 13615
d6902373
PG
13616#ifdef KEEP_OLD_VPN_COMMANDS
13617DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13618 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13619 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13620 SHOW_STR
13621 IP_STR
13622 BGP_STR
d6902373 13623 BGP_VPNVX_HELP_STR
91d37724 13624 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13625 "Detailed information on TCP and BGP neighbor connections\n"
13626 "Neighbor to display information about\n"
13627 "Neighbor to display information about\n"
91d37724 13628 "Neighbor on BGP configured interface\n"
a636c635 13629 "Display detailed prefix count information\n"
9973d184 13630 JSON_STR)
a636c635 13631{
d62a17ae 13632 int idx_peer = 6;
13633 struct peer *peer;
9f049418 13634 bool uj = use_json(argc, argv);
a636c635 13635
d62a17ae 13636 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13637 if (!peer)
13638 return CMD_WARNING;
13639
13640 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13641}
13642
d6902373
PG
13643DEFUN (show_ip_bgp_vpn_all_route_prefix,
13644 show_ip_bgp_vpn_all_route_prefix_cmd,
13645 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13646 SHOW_STR
13647 IP_STR
13648 BGP_STR
d6902373 13649 BGP_VPNVX_HELP_STR
91d37724
QY
13650 "Display information about all VPNv4 NLRIs\n"
13651 "Network in the BGP routing table to display\n"
3a2d747c 13652 "Network in the BGP routing table to display\n"
9973d184 13653 JSON_STR)
91d37724 13654{
d62a17ae 13655 int idx = 0;
13656 char *network = NULL;
13657 struct bgp *bgp = bgp_get_default();
13658 if (!bgp) {
13659 vty_out(vty, "Can't find default instance\n");
13660 return CMD_WARNING;
13661 }
87e34b58 13662
d62a17ae 13663 if (argv_find(argv, argc, "A.B.C.D", &idx))
13664 network = argv[idx]->arg;
13665 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13666 network = argv[idx]->arg;
13667 else {
13668 vty_out(vty, "Unable to figure out Network\n");
13669 return CMD_WARNING;
13670 }
87e34b58 13671
d62a17ae 13672 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13673 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13674 use_json(argc, argv));
91d37724 13675}
d6902373 13676#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13677
44c69747
LK
13678DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13679 show_bgp_l2vpn_evpn_route_prefix_cmd,
13680 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13681 SHOW_STR
4c63a661
PG
13682 BGP_STR
13683 L2VPN_HELP_STR
13684 EVPN_HELP_STR
44c69747
LK
13685 "Network in the BGP routing table to display\n"
13686 "Network in the BGP routing table to display\n"
4c63a661
PG
13687 "Network in the BGP routing table to display\n"
13688 "Network in the BGP routing table to display\n"
13689 JSON_STR)
13690{
d62a17ae 13691 int idx = 0;
13692 char *network = NULL;
44c69747 13693 int prefix_check = 0;
a636c635 13694
44c69747
LK
13695 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13696 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13697 network = argv[idx]->arg;
44c69747 13698 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13699 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13700 network = argv[idx]->arg;
44c69747
LK
13701 prefix_check = 1;
13702 } else {
d62a17ae 13703 vty_out(vty, "Unable to figure out Network\n");
13704 return CMD_WARNING;
13705 }
44c69747
LK
13706 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13707 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13708 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13709}
13710
114fc229 13711static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13712 struct bgp_table *table, int *header1,
13713 int *header2, json_object *json,
13714 json_object *json_scode,
13715 json_object *json_ocode, bool wide)
13716{
13717 uint64_t version = table ? table->version : 0;
13718
13719 if (*header1) {
13720 if (json) {
13721 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13722 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13723 "%pI4", &peer->bgp->router_id);
2f9bc755 13724 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13725 peer->bgp->default_local_pref);
13726 json_object_int_add(json, "localAS",
13727 peer->change_local_as
13728 ? peer->change_local_as
13729 : peer->local_as);
2f9bc755
DS
13730 json_object_object_add(json, "bgpStatusCodes",
13731 json_scode);
13732 json_object_object_add(json, "bgpOriginCodes",
13733 json_ocode);
13734 } else {
13735 vty_out(vty,
23d0a753
DA
13736 "BGP table version is %" PRIu64
13737 ", local router ID is %pI4, vrf id ",
114fc229
DA
13738 version, &peer->bgp->router_id);
13739 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13740 vty_out(vty, "%s", VRFID_NONE_STR);
13741 else
114fc229 13742 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13743 vty_out(vty, "\n");
13744 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13745 peer->bgp->default_local_pref);
13746 vty_out(vty, "local AS %u\n",
13747 peer->change_local_as ? peer->change_local_as
13748 : peer->local_as);
2f9bc755
DS
13749 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13750 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13751 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13752 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13753 }
13754 *header1 = 0;
13755 }
13756 if (*header2) {
13757 if (!json)
13758 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13759 : BGP_SHOW_HEADER));
13760 *header2 = 0;
13761 }
13762}
13763
d9478df0
TA
13764static void
13765show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13766 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13767 const char *rmap_name, json_object *json, json_object *json_ar,
13768 json_object *json_scode, json_object *json_ocode,
96c81f66 13769 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13770 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13771{
d62a17ae 13772 struct bgp_adj_in *ain;
13773 struct bgp_adj_out *adj;
9bcb3eef 13774 struct bgp_dest *dest;
d62a17ae 13775 struct bgp *bgp;
d62a17ae 13776 struct attr attr;
13777 int ret;
13778 struct update_subgroup *subgrp;
d62a17ae 13779 struct peer_af *paf;
f99def61 13780 bool route_filtered;
96f3485c
MK
13781 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13782 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13783 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13784 || (safi == SAFI_EVPN))
13785 ? true
13786 : false;
a636c635 13787
d62a17ae 13788 bgp = peer->bgp;
a636c635 13789
d62a17ae 13790 subgrp = peer_subgroup(peer, afi, safi);
13791
6392aaa6 13792 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13793 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13794 if (use_json) {
13795 json_object_int_add(json, "bgpTableVersion",
13796 table->version);
c949c771
DA
13797 json_object_string_addf(json, "bgpLocalRouterId",
13798 "%pI4", &bgp->router_id);
01eced22
AD
13799 json_object_int_add(json, "defaultLocPrf",
13800 bgp->default_local_pref);
114fc229
DA
13801 json_object_int_add(json, "localAS",
13802 peer->change_local_as
13803 ? peer->change_local_as
13804 : peer->local_as);
d62a17ae 13805 json_object_object_add(json, "bgpStatusCodes",
13806 json_scode);
13807 json_object_object_add(json, "bgpOriginCodes",
13808 json_ocode);
07d0c4ed
DA
13809 json_object_string_add(
13810 json, "bgpOriginatingDefaultNetwork",
13811 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13812 } else {
23d0a753
DA
13813 vty_out(vty,
13814 "BGP table version is %" PRIu64
13815 ", local router ID is %pI4, vrf id ",
13816 table->version, &bgp->router_id);
9df8b37c
PZ
13817 if (bgp->vrf_id == VRF_UNKNOWN)
13818 vty_out(vty, "%s", VRFID_NONE_STR);
13819 else
13820 vty_out(vty, "%u", bgp->vrf_id);
13821 vty_out(vty, "\n");
01eced22
AD
13822 vty_out(vty, "Default local pref %u, ",
13823 bgp->default_local_pref);
114fc229
DA
13824 vty_out(vty, "local AS %u\n",
13825 peer->change_local_as ? peer->change_local_as
13826 : peer->local_as);
d62a17ae 13827 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13828 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13829 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13830 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13831
07d0c4ed
DA
13832 vty_out(vty, "Originating default network %s\n\n",
13833 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13834 }
d9478df0 13835 *header1 = 0;
d62a17ae 13836 }
a636c635 13837
9bcb3eef 13838 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13839 if (type == bgp_show_adj_route_received
13840 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13841 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13842 if (ain->peer != peer)
ea47320b 13843 continue;
6392aaa6 13844
114fc229 13845 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13846 header2, json, json_scode,
13847 json_ocode, wide);
13848
13849 if ((safi == SAFI_MPLS_VPN)
13850 || (safi == SAFI_ENCAP)
13851 || (safi == SAFI_EVPN)) {
13852 if (use_json)
13853 json_object_string_add(
13854 json_ar, "rd", rd_str);
13855 else if (show_rd && rd_str) {
13856 vty_out(vty,
13857 "Route Distinguisher: %s\n",
13858 rd_str);
13859 show_rd = false;
13860 }
13861 }
6392aaa6 13862
6f4f49b2 13863 attr = *ain->attr;
f99def61
AD
13864 route_filtered = false;
13865
13866 /* Filter prefix using distribute list,
13867 * filter list or prefix list
13868 */
b54892e0 13869 const struct prefix *rn_p =
9bcb3eef 13870 bgp_dest_get_prefix(dest);
b54892e0
DS
13871 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13872 safi))
13873 == FILTER_DENY)
f99def61
AD
13874 route_filtered = true;
13875
13876 /* Filter prefix using route-map */
b54892e0
DS
13877 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13878 safi, rmap_name, NULL,
13879 0, NULL);
6392aaa6 13880
13c8e163
AD
13881 if (type == bgp_show_adj_route_filtered &&
13882 !route_filtered && ret != RMAP_DENY) {
d498917e 13883 bgp_attr_flush(&attr);
6392aaa6 13884 continue;
d62a17ae 13885 }
6392aaa6 13886
d9478df0
TA
13887 if (type == bgp_show_adj_route_received
13888 && (route_filtered || ret == RMAP_DENY))
13889 (*filtered_count)++;
6392aaa6 13890
7d3cae70 13891 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13892 use_json, json_ar, wide);
d498917e 13893 bgp_attr_flush(&attr);
d9478df0 13894 (*output_count)++;
d62a17ae 13895 }
6392aaa6 13896 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13897 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13898 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13899 if (paf->peer != peer || !adj->attr)
924c3f6a 13900 continue;
d62a17ae 13901
114fc229 13902 show_adj_route_header(vty, peer, table,
d9478df0
TA
13903 header1, header2,
13904 json, json_scode,
13905 json_ocode, wide);
d62a17ae 13906
b54892e0 13907 const struct prefix *rn_p =
9bcb3eef 13908 bgp_dest_get_prefix(dest);
b54892e0 13909
6f4f49b2 13910 attr = *adj->attr;
b755861b 13911 ret = bgp_output_modifier(
b54892e0 13912 peer, rn_p, &attr, afi, safi,
b755861b 13913 rmap_name);
f46d8e1e 13914
b755861b 13915 if (ret != RMAP_DENY) {
d9478df0
TA
13916 if ((safi == SAFI_MPLS_VPN)
13917 || (safi == SAFI_ENCAP)
13918 || (safi == SAFI_EVPN)) {
13919 if (use_json)
13920 json_object_string_add(
13921 json_ar,
13922 "rd",
13923 rd_str);
13924 else if (show_rd
13925 && rd_str) {
13926 vty_out(vty,
13927 "Route Distinguisher: %s\n",
13928 rd_str);
13929 show_rd = false;
13930 }
13931 }
b54892e0 13932 route_vty_out_tmp(
7d3cae70
DA
13933 vty, dest, rn_p, &attr,
13934 safi, use_json, json_ar,
ae248832 13935 wide);
d9478df0 13936 (*output_count)++;
b755861b 13937 } else {
d9478df0 13938 (*filtered_count)++;
a2addae8 13939 }
b755861b 13940
d498917e 13941 bgp_attr_flush(&attr);
924c3f6a 13942 }
f20ce998
DS
13943 } else if (type == bgp_show_adj_route_bestpath) {
13944 struct bgp_path_info *pi;
13945
114fc229
DA
13946 show_adj_route_header(vty, peer, table, header1,
13947 header2, json, json_scode,
13948 json_ocode, wide);
f20ce998
DS
13949
13950 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13951 pi = pi->next) {
13952 if (pi->peer != peer)
13953 continue;
13954
13955 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13956 continue;
13957
7d3cae70 13958 route_vty_out_tmp(vty, dest,
f20ce998
DS
13959 bgp_dest_get_prefix(dest),
13960 pi->attr, safi, use_json,
13961 json_ar, wide);
d9478df0 13962 (*output_count)++;
f20ce998 13963 }
d62a17ae 13964 }
13965 }
a636c635 13966}
2a71e9ce 13967
d62a17ae 13968static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13969 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13970 const char *rmap_name, uint16_t show_flags)
0b16f239 13971{
d9478df0
TA
13972 struct bgp *bgp;
13973 struct bgp_table *table;
d62a17ae 13974 json_object *json = NULL;
d9478df0
TA
13975 json_object *json_scode = NULL;
13976 json_object *json_ocode = NULL;
13977 json_object *json_ar = NULL;
96f3485c 13978 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13979
d9478df0
TA
13980 /* Init BGP headers here so they're only displayed once
13981 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13982 */
13983 int header1 = 1;
13984 int header2 = 1;
13985
13986 /*
13987 * Initialize variables for each RD
13988 * All prefixes under an RD is aggregated within "json_routes"
13989 */
13990 char rd_str[BUFSIZ] = {0};
13991 json_object *json_routes = NULL;
13992
13993
13994 /* For 2-tier tables, prefix counts need to be
13995 * maintained across multiple runs of show_adj_route()
13996 */
13997 unsigned long output_count_per_rd;
13998 unsigned long filtered_count_per_rd;
13999 unsigned long output_count = 0;
14000 unsigned long filtered_count = 0;
14001
14002 if (use_json) {
d62a17ae 14003 json = json_object_new_object();
d9478df0
TA
14004 json_ar = json_object_new_object();
14005 json_scode = json_object_new_object();
14006 json_ocode = json_object_new_object();
14007
14008 json_object_string_add(json_scode, "suppressed", "s");
14009 json_object_string_add(json_scode, "damped", "d");
14010 json_object_string_add(json_scode, "history", "h");
14011 json_object_string_add(json_scode, "valid", "*");
14012 json_object_string_add(json_scode, "best", ">");
14013 json_object_string_add(json_scode, "multipath", "=");
14014 json_object_string_add(json_scode, "internal", "i");
14015 json_object_string_add(json_scode, "ribFailure", "r");
14016 json_object_string_add(json_scode, "stale", "S");
14017 json_object_string_add(json_scode, "removed", "R");
14018
14019 json_object_string_add(json_ocode, "igp", "i");
14020 json_object_string_add(json_ocode, "egp", "e");
14021 json_object_string_add(json_ocode, "incomplete", "?");
14022 }
0b16f239 14023
d62a17ae 14024 if (!peer || !peer->afc[afi][safi]) {
14025 if (use_json) {
14026 json_object_string_add(
14027 json, "warning",
14028 "No such neighbor or address family");
14029 vty_out(vty, "%s\n", json_object_to_json_string(json));
14030 json_object_free(json);
690c3134
MW
14031 json_object_free(json_ar);
14032 json_object_free(json_scode);
14033 json_object_free(json_ocode);
d62a17ae 14034 } else
14035 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14036
d62a17ae 14037 return CMD_WARNING;
14038 }
14039
6392aaa6
PM
14040 if ((type == bgp_show_adj_route_received
14041 || type == bgp_show_adj_route_filtered)
d62a17ae 14042 && !CHECK_FLAG(peer->af_flags[afi][safi],
14043 PEER_FLAG_SOFT_RECONFIG)) {
14044 if (use_json) {
14045 json_object_string_add(
14046 json, "warning",
14047 "Inbound soft reconfiguration not enabled");
14048 vty_out(vty, "%s\n", json_object_to_json_string(json));
14049 json_object_free(json);
690c3134
MW
14050 json_object_free(json_ar);
14051 json_object_free(json_scode);
14052 json_object_free(json_ocode);
d62a17ae 14053 } else
14054 vty_out(vty,
14055 "%% Inbound soft reconfiguration not enabled\n");
14056
14057 return CMD_WARNING;
14058 }
0b16f239 14059
d9478df0
TA
14060 bgp = peer->bgp;
14061
14062 /* labeled-unicast routes live in the unicast table */
14063 if (safi == SAFI_LABELED_UNICAST)
14064 table = bgp->rib[afi][SAFI_UNICAST];
14065 else
14066 table = bgp->rib[afi][safi];
14067
14068 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14069 || (safi == SAFI_EVPN)) {
14070
14071 struct bgp_dest *dest;
14072
14073 for (dest = bgp_table_top(table); dest;
14074 dest = bgp_route_next(dest)) {
14075 table = bgp_dest_get_bgp_table_info(dest);
14076 if (!table)
14077 continue;
14078
14079 output_count_per_rd = 0;
14080 filtered_count_per_rd = 0;
14081
14082 if (use_json)
14083 json_routes = json_object_new_object();
14084
14085 const struct prefix_rd *prd;
14086 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14087 dest);
14088
14089 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14090
14091 show_adj_route(vty, peer, table, afi, safi, type,
14092 rmap_name, json, json_routes, json_scode,
14093 json_ocode, show_flags, &header1,
14094 &header2, rd_str, &output_count_per_rd,
14095 &filtered_count_per_rd);
14096
14097 /* Don't include an empty RD in the output! */
14098 if (json_routes && (output_count_per_rd > 0))
14099 json_object_object_add(json_ar, rd_str,
14100 json_routes);
14101
14102 output_count += output_count_per_rd;
14103 filtered_count += filtered_count_per_rd;
14104 }
14105 } else
14106 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14107 json, json_ar, json_scode, json_ocode,
14108 show_flags, &header1, &header2, rd_str,
14109 &output_count, &filtered_count);
14110
14111 if (use_json) {
c1984955
TA
14112 if (type == bgp_show_adj_route_advertised)
14113 json_object_object_add(json, "advertisedRoutes",
14114 json_ar);
14115 else
14116 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14117 json_object_int_add(json, "totalPrefixCounter", output_count);
14118 json_object_int_add(json, "filteredPrefixCounter",
14119 filtered_count);
14120
690c3134
MW
14121 /*
14122 * These fields only give up ownership to `json` when `header1`
14123 * is used (set to zero). See code in `show_adj_route` and
14124 * `show_adj_route_header`.
14125 */
14126 if (header1 == 1) {
d9478df0
TA
14127 json_object_free(json_scode);
14128 json_object_free(json_ocode);
14129 }
14130
75eeda93 14131 vty_json(vty, json);
d9478df0
TA
14132 } else if (output_count > 0) {
14133 if (filtered_count > 0)
14134 vty_out(vty,
14135 "\nTotal number of prefixes %ld (%ld filtered)\n",
14136 output_count, filtered_count);
14137 else
14138 vty_out(vty, "\nTotal number of prefixes %ld\n",
14139 output_count);
14140 }
0b16f239 14141
d62a17ae 14142 return CMD_SUCCESS;
a636c635 14143}
50ef26d4 14144
f20ce998
DS
14145DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14146 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14147 "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]",
14148 SHOW_STR
14149 IP_STR
14150 BGP_STR
14151 BGP_INSTANCE_HELP_STR
14152 BGP_AFI_HELP_STR
14153 BGP_SAFI_WITH_LABEL_HELP_STR
14154 "Detailed information on TCP and BGP neighbor connections\n"
14155 "Neighbor to display information about\n"
14156 "Neighbor to display information about\n"
14157 "Neighbor on BGP configured interface\n"
14158 "Display the routes selected by best path\n"
14159 JSON_STR
14160 "Increase table width for longer prefixes\n")
14161{
14162 afi_t afi = AFI_IP6;
14163 safi_t safi = SAFI_UNICAST;
14164 char *rmap_name = NULL;
14165 char *peerstr = NULL;
14166 struct bgp *bgp = NULL;
14167 struct peer *peer;
14168 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14169 int idx = 0;
96c81f66 14170 uint16_t show_flags = 0;
96f3485c
MK
14171
14172 if (uj)
14173 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14174
14175 if (wide)
14176 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14177
14178 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14179 &bgp, uj);
14180
14181 if (!idx)
14182 return CMD_WARNING;
14183
14184 argv_find(argv, argc, "neighbors", &idx);
14185 peerstr = argv[++idx]->arg;
14186
14187 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14188 if (!peer)
14189 return CMD_WARNING;
14190
96f3485c
MK
14191 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14192 show_flags);
f20ce998
DS
14193}
14194
ae248832 14195DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14196 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14197 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [json$uj | wide$wide]",
718e3744 14198 SHOW_STR
14199 IP_STR
14200 BGP_STR
a636c635 14201 BGP_INSTANCE_HELP_STR
7395a2c9 14202 BGP_AFI_HELP_STR
4dd6177e 14203 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14204 "Display the entries for all address families\n"
718e3744 14205 "Detailed information on TCP and BGP neighbor connections\n"
14206 "Neighbor to display information about\n"
14207 "Neighbor to display information about\n"
91d37724 14208 "Neighbor on BGP configured interface\n"
a636c635 14209 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14210 "Display the received routes from neighbor\n"
14211 "Display the filtered routes received from neighbor\n"
a636c635
DW
14212 "Route-map to modify the attributes\n"
14213 "Name of the route map\n"
ae248832
MK
14214 JSON_STR
14215 "Increase table width for longer prefixes\n")
718e3744 14216{
d62a17ae 14217 afi_t afi = AFI_IP6;
14218 safi_t safi = SAFI_UNICAST;
d62a17ae 14219 char *peerstr = NULL;
d62a17ae 14220 struct bgp *bgp = NULL;
14221 struct peer *peer;
6392aaa6 14222 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14223 int idx = 0;
96f3485c 14224 bool first = true;
96c81f66 14225 uint16_t show_flags = 0;
75ce3b14
DA
14226 struct listnode *node;
14227 struct bgp *abgp;
6392aaa6 14228
96f3485c 14229 if (uj) {
d62a17ae 14230 argc--;
96f3485c
MK
14231 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14232 }
14233
14234 if (all) {
14235 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14236 if (argv_find(argv, argc, "ipv4", &idx))
14237 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14238
14239 if (argv_find(argv, argc, "ipv6", &idx))
14240 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14241 }
14242
14243 if (wide)
14244 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14245
9f049418
DS
14246 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14247 &bgp, uj);
14248 if (!idx)
14249 return CMD_WARNING;
14250
d62a17ae 14251 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14252 argv_find(argv, argc, "neighbors", &idx);
14253 peerstr = argv[++idx]->arg;
8c3deaae 14254
d62a17ae 14255 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14256 if (!peer)
14257 return CMD_WARNING;
856ca177 14258
d62a17ae 14259 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14260 type = bgp_show_adj_route_advertised;
14261 else if (argv_find(argv, argc, "received-routes", &idx))
14262 type = bgp_show_adj_route_received;
14263 else if (argv_find(argv, argc, "filtered-routes", &idx))
14264 type = bgp_show_adj_route_filtered;
14265
96f3485c 14266 if (!all)
70dd370f 14267 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14268 show_flags);
14269 if (uj)
14270 vty_out(vty, "{\n");
14271
14272 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14273 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14274 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14275 : AFI_IP6;
75ce3b14
DA
14276 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14277 FOREACH_SAFI (safi) {
14278 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14279 continue;
96f3485c 14280
75ce3b14
DA
14281 if (uj) {
14282 if (first)
14283 first = false;
14284 else
14285 vty_out(vty, ",\n");
14286 vty_out(vty, "\"%s\":",
14287 get_afi_safi_str(afi, safi,
14288 true));
14289 } else
14290 vty_out(vty,
14291 "\nFor address family: %s\n",
14292 get_afi_safi_str(afi, safi,
14293 false));
96f3485c 14294
75ce3b14 14295 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14296 route_map, show_flags);
75ce3b14 14297 }
96f3485c
MK
14298 }
14299 } else {
75ce3b14
DA
14300 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14301 FOREACH_AFI_SAFI (afi, safi) {
14302 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14303 continue;
96f3485c 14304
75ce3b14
DA
14305 if (uj) {
14306 if (first)
14307 first = false;
14308 else
14309 vty_out(vty, ",\n");
14310 vty_out(vty, "\"%s\":",
14311 get_afi_safi_str(afi, safi,
14312 true));
14313 } else
14314 vty_out(vty,
14315 "\nFor address family: %s\n",
14316 get_afi_safi_str(afi, safi,
14317 false));
96f3485c 14318
75ce3b14 14319 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14320 route_map, show_flags);
75ce3b14 14321 }
96f3485c
MK
14322 }
14323 }
14324 if (uj)
14325 vty_out(vty, "}\n");
14326
14327 return CMD_SUCCESS;
95cbbd2a
ML
14328}
14329
718e3744 14330DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14331 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14332 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14333 SHOW_STR
14334 IP_STR
14335 BGP_STR
d3120452 14336 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14337 BGP_AF_STR
14338 BGP_AF_STR
14339 BGP_AF_MODIFIER_STR
718e3744 14340 "Detailed information on TCP and BGP neighbor connections\n"
14341 "Neighbor to display information about\n"
14342 "Neighbor to display information about\n"
91d37724 14343 "Neighbor on BGP configured interface\n"
718e3744 14344 "Display information received from a BGP neighbor\n"
856ca177 14345 "Display the prefixlist filter\n"
9973d184 14346 JSON_STR)
718e3744 14347{
d62a17ae 14348 afi_t afi = AFI_IP6;
14349 safi_t safi = SAFI_UNICAST;
14350 char *peerstr = NULL;
d62a17ae 14351 char name[BUFSIZ];
d62a17ae 14352 struct peer *peer;
d3120452 14353 int count;
d62a17ae 14354 int idx = 0;
d3120452
IR
14355 struct bgp *bgp = NULL;
14356 bool uj = use_json(argc, argv);
14357
14358 if (uj)
14359 argc--;
14360
14361 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14362 &bgp, uj);
14363 if (!idx)
14364 return CMD_WARNING;
d62a17ae 14365
d62a17ae 14366 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14367 argv_find(argv, argc, "neighbors", &idx);
14368 peerstr = argv[++idx]->arg;
14369
d3120452
IR
14370 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14371 if (!peer)
14372 return CMD_WARNING;
718e3744 14373
4ced1a2c 14374 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14375 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14376 if (count) {
14377 if (!uj)
14378 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14379 get_afi_safi_str(afi, safi, false));
d62a17ae 14380 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14381 } else {
14382 if (uj)
14383 vty_out(vty, "{}\n");
14384 else
14385 vty_out(vty, "No functional output\n");
14386 }
718e3744 14387
d62a17ae 14388 return CMD_SUCCESS;
14389}
14390
14391static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14392 afi_t afi, safi_t safi,
9f049418 14393 enum bgp_show_type type, bool use_json)
d62a17ae 14394{
96c81f66 14395 uint16_t show_flags = 0;
96f3485c
MK
14396
14397 if (use_json)
14398 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14399
d62a17ae 14400 if (!peer || !peer->afc[afi][safi]) {
14401 if (use_json) {
14402 json_object *json_no = NULL;
14403 json_no = json_object_new_object();
14404 json_object_string_add(
14405 json_no, "warning",
14406 "No such neighbor or address family");
14407 vty_out(vty, "%s\n",
14408 json_object_to_json_string(json_no));
14409 json_object_free(json_no);
14410 } else
14411 vty_out(vty, "%% No such neighbor or address family\n");
14412 return CMD_WARNING;
14413 }
47fc97cc 14414
7daf25a3
TA
14415 /* labeled-unicast routes live in the unicast table */
14416 if (safi == SAFI_LABELED_UNICAST)
14417 safi = SAFI_UNICAST;
14418
1e2ce4f1
DS
14419 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14420 RPKI_NOT_BEING_USED);
718e3744 14421}
14422
dba3c1d3
PG
14423DEFUN (show_ip_bgp_flowspec_routes_detailed,
14424 show_ip_bgp_flowspec_routes_detailed_cmd,
14425 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14426 SHOW_STR
14427 IP_STR
14428 BGP_STR
14429 BGP_INSTANCE_HELP_STR
14430 BGP_AFI_HELP_STR
14431 "SAFI Flowspec\n"
14432 "Detailed information on flowspec entries\n"
14433 JSON_STR)
14434{
458c1475 14435 afi_t afi = AFI_IP6;
dba3c1d3
PG
14436 safi_t safi = SAFI_UNICAST;
14437 struct bgp *bgp = NULL;
14438 int idx = 0;
9f049418 14439 bool uj = use_json(argc, argv);
5be6fa9b 14440 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14441
96f3485c 14442 if (uj) {
9f049418 14443 argc--;
96f3485c
MK
14444 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14445 }
dba3c1d3
PG
14446
14447 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14448 &bgp, uj);
dba3c1d3
PG
14449 if (!idx)
14450 return CMD_WARNING;
14451
96f3485c 14452 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14453 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14454}
14455
718e3744 14456DEFUN (show_ip_bgp_neighbor_routes,
14457 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14458 "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 14459 SHOW_STR
14460 IP_STR
14461 BGP_STR
8386ac43 14462 BGP_INSTANCE_HELP_STR
4f280b15 14463 BGP_AFI_HELP_STR
4dd6177e 14464 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14465 "Detailed information on TCP and BGP neighbor connections\n"
14466 "Neighbor to display information about\n"
14467 "Neighbor to display information about\n"
91d37724 14468 "Neighbor on BGP configured interface\n"
2525cf39 14469 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14470 "Display the dampened routes received from neighbor\n"
14471 "Display routes learned from neighbor\n"
9973d184 14472 JSON_STR)
718e3744 14473{
d62a17ae 14474 char *peerstr = NULL;
14475 struct bgp *bgp = NULL;
14476 afi_t afi = AFI_IP6;
14477 safi_t safi = SAFI_UNICAST;
14478 struct peer *peer;
14479 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14480 int idx = 0;
9f049418
DS
14481 bool uj = use_json(argc, argv);
14482
14483 if (uj)
14484 argc--;
bb46e94f 14485
d62a17ae 14486 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14487 &bgp, uj);
d62a17ae 14488 if (!idx)
14489 return CMD_WARNING;
c493f2d8 14490
d62a17ae 14491 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14492 argv_find(argv, argc, "neighbors", &idx);
14493 peerstr = argv[++idx]->arg;
8c3deaae 14494
d62a17ae 14495 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14496 if (!peer)
d62a17ae 14497 return CMD_WARNING;
bb46e94f 14498
d62a17ae 14499 if (argv_find(argv, argc, "flap-statistics", &idx))
14500 sh_type = bgp_show_type_flap_neighbor;
14501 else if (argv_find(argv, argc, "dampened-routes", &idx))
14502 sh_type = bgp_show_type_damp_neighbor;
14503 else if (argv_find(argv, argc, "routes", &idx))
14504 sh_type = bgp_show_type_neighbor;
2525cf39 14505
d62a17ae 14506 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14507}
6b0655a2 14508
734b349e 14509struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14510
d62a17ae 14511struct bgp_distance {
14512 /* Distance value for the IP source prefix. */
d7c0a89a 14513 uint8_t distance;
718e3744 14514
d62a17ae 14515 /* Name of the access-list to be matched. */
14516 char *access_list;
718e3744 14517};
14518
4f280b15
LB
14519DEFUN (show_bgp_afi_vpn_rd_route,
14520 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14521 "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
14522 SHOW_STR
14523 BGP_STR
14524 BGP_AFI_HELP_STR
00e6edb9 14525 BGP_AF_MODIFIER_STR
4f280b15
LB
14526 "Display information for a route distinguisher\n"
14527 "Route Distinguisher\n"
a111dd97 14528 "All Route Distinguishers\n"
7395a2c9
DS
14529 "Network in the BGP routing table to display\n"
14530 "Network in the BGP routing table to display\n"
14531 JSON_STR)
4f280b15 14532{
d62a17ae 14533 int ret;
14534 struct prefix_rd prd;
14535 afi_t afi = AFI_MAX;
14536 int idx = 0;
4f280b15 14537
ff6566f3
DS
14538 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14539 vty_out(vty, "%% Malformed Address Family\n");
14540 return CMD_WARNING;
14541 }
14542
a111dd97
TA
14543 if (!strcmp(argv[5]->arg, "all"))
14544 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14545 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14546 RPKI_NOT_BEING_USED,
14547 use_json(argc, argv));
14548
d62a17ae 14549 ret = str2prefix_rd(argv[5]->arg, &prd);
14550 if (!ret) {
14551 vty_out(vty, "%% Malformed Route Distinguisher\n");
14552 return CMD_WARNING;
14553 }
ff6566f3 14554
d62a17ae 14555 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14556 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14557 use_json(argc, argv));
4f280b15
LB
14558}
14559
d62a17ae 14560static struct bgp_distance *bgp_distance_new(void)
718e3744 14561{
d62a17ae 14562 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14563}
14564
d62a17ae 14565static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14566{
d62a17ae 14567 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14568}
14569
585f1adc
IR
14570static int bgp_distance_set(struct vty *vty, const char *distance_str,
14571 const char *ip_str, const char *access_list_str)
718e3744 14572{
d62a17ae 14573 int ret;
585f1adc
IR
14574 afi_t afi;
14575 safi_t safi;
d62a17ae 14576 struct prefix p;
585f1adc 14577 uint8_t distance;
9bcb3eef 14578 struct bgp_dest *dest;
d62a17ae 14579 struct bgp_distance *bdistance;
718e3744 14580
585f1adc
IR
14581 afi = bgp_node_afi(vty);
14582 safi = bgp_node_safi(vty);
14583
d62a17ae 14584 ret = str2prefix(ip_str, &p);
14585 if (ret == 0) {
585f1adc 14586 vty_out(vty, "Malformed prefix\n");
d62a17ae 14587 return CMD_WARNING_CONFIG_FAILED;
14588 }
718e3744 14589
585f1adc
IR
14590 distance = atoi(distance_str);
14591
d62a17ae 14592 /* Get BGP distance node. */
9bcb3eef
DS
14593 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14594 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14595 if (bdistance)
9bcb3eef 14596 bgp_dest_unlock_node(dest);
ca2e160d 14597 else {
d62a17ae 14598 bdistance = bgp_distance_new();
9bcb3eef 14599 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14600 }
718e3744 14601
d62a17ae 14602 /* Set distance value. */
14603 bdistance->distance = distance;
718e3744 14604
d62a17ae 14605 /* Reset access-list configuration. */
e1b36e13 14606 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14607 if (access_list_str)
14608 bdistance->access_list =
14609 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14610
d62a17ae 14611 return CMD_SUCCESS;
718e3744 14612}
14613
585f1adc
IR
14614static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14615 const char *ip_str, const char *access_list_str)
718e3744 14616{
d62a17ae 14617 int ret;
585f1adc
IR
14618 afi_t afi;
14619 safi_t safi;
d62a17ae 14620 struct prefix p;
585f1adc 14621 int distance;
9bcb3eef 14622 struct bgp_dest *dest;
d62a17ae 14623 struct bgp_distance *bdistance;
718e3744 14624
585f1adc
IR
14625 afi = bgp_node_afi(vty);
14626 safi = bgp_node_safi(vty);
14627
d62a17ae 14628 ret = str2prefix(ip_str, &p);
14629 if (ret == 0) {
585f1adc 14630 vty_out(vty, "Malformed prefix\n");
d62a17ae 14631 return CMD_WARNING_CONFIG_FAILED;
14632 }
718e3744 14633
9bcb3eef
DS
14634 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14635 if (!dest) {
585f1adc 14636 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14637 return CMD_WARNING_CONFIG_FAILED;
14638 }
718e3744 14639
9bcb3eef 14640 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14641 distance = atoi(distance_str);
1f9a9fff 14642
d62a17ae 14643 if (bdistance->distance != distance) {
585f1adc 14644 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14645 bgp_dest_unlock_node(dest);
d62a17ae 14646 return CMD_WARNING_CONFIG_FAILED;
14647 }
718e3744 14648
0a22ddfb 14649 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14650 bgp_distance_free(bdistance);
718e3744 14651
9bcb3eef
DS
14652 bgp_dest_set_bgp_path_info(dest, NULL);
14653 bgp_dest_unlock_node(dest);
14654 bgp_dest_unlock_node(dest);
718e3744 14655
d62a17ae 14656 return CMD_SUCCESS;
718e3744 14657}
14658
718e3744 14659/* Apply BGP information to distance method. */
b8685f9b 14660uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14661 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14662{
9bcb3eef 14663 struct bgp_dest *dest;
801bb996 14664 struct prefix q = {0};
d62a17ae 14665 struct peer *peer;
14666 struct bgp_distance *bdistance;
14667 struct access_list *alist;
14668 struct bgp_static *bgp_static;
14669
14670 if (!bgp)
14671 return 0;
14672
40381db7 14673 peer = pinfo->peer;
d62a17ae 14674
7b7d48e5
DS
14675 if (pinfo->attr->distance)
14676 return pinfo->attr->distance;
14677
801bb996
CS
14678 /* Check source address.
14679 * Note: for aggregate route, peer can have unspec af type.
14680 */
14681 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14682 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14683 return 0;
14684
9bcb3eef
DS
14685 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14686 if (dest) {
14687 bdistance = bgp_dest_get_bgp_distance_info(dest);
14688 bgp_dest_unlock_node(dest);
d62a17ae 14689
14690 if (bdistance->access_list) {
14691 alist = access_list_lookup(afi, bdistance->access_list);
14692 if (alist
14693 && access_list_apply(alist, p) == FILTER_PERMIT)
14694 return bdistance->distance;
14695 } else
14696 return bdistance->distance;
718e3744 14697 }
718e3744 14698
d62a17ae 14699 /* Backdoor check. */
9bcb3eef
DS
14700 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14701 if (dest) {
14702 bgp_static = bgp_dest_get_bgp_static_info(dest);
14703 bgp_dest_unlock_node(dest);
718e3744 14704
d62a17ae 14705 if (bgp_static->backdoor) {
14706 if (bgp->distance_local[afi][safi])
14707 return bgp->distance_local[afi][safi];
14708 else
14709 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14710 }
718e3744 14711 }
718e3744 14712
d62a17ae 14713 if (peer->sort == BGP_PEER_EBGP) {
14714 if (bgp->distance_ebgp[afi][safi])
14715 return bgp->distance_ebgp[afi][safi];
14716 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14717 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14718 if (bgp->distance_ibgp[afi][safi])
14719 return bgp->distance_ibgp[afi][safi];
14720 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14721 } else {
14722 if (bgp->distance_local[afi][safi])
14723 return bgp->distance_local[afi][safi];
14724 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14725 }
718e3744 14726}
14727
a612fb77
DA
14728/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14729 * we should tell ZEBRA update the routes for a specific
14730 * AFI/SAFI to reflect changes in RIB.
14731 */
585f1adc
IR
14732static void bgp_announce_routes_distance_update(struct bgp *bgp,
14733 afi_t update_afi,
14734 safi_t update_safi)
a612fb77
DA
14735{
14736 afi_t afi;
14737 safi_t safi;
14738
14739 FOREACH_AFI_SAFI (afi, safi) {
14740 if (!bgp_fibupd_safi(safi))
14741 continue;
14742
8b54bc30
DA
14743 if (afi != update_afi && safi != update_safi)
14744 continue;
14745
14746 if (BGP_DEBUG(zebra, ZEBRA))
14747 zlog_debug(
14748 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14749 __func__, afi, safi);
14750 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14751 }
14752}
14753
585f1adc
IR
14754DEFUN (bgp_distance,
14755 bgp_distance_cmd,
14756 "distance bgp (1-255) (1-255) (1-255)",
14757 "Define an administrative distance\n"
14758 "BGP distance\n"
14759 "Distance for routes external to the AS\n"
14760 "Distance for routes internal to the AS\n"
14761 "Distance for local routes\n")
718e3744 14762{
585f1adc 14763 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14764 int idx_number = 2;
14765 int idx_number_2 = 3;
14766 int idx_number_3 = 4;
585f1adc
IR
14767 int distance_ebgp = atoi(argv[idx_number]->arg);
14768 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14769 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14770 afi_t afi;
14771 safi_t safi;
718e3744 14772
d62a17ae 14773 afi = bgp_node_afi(vty);
14774 safi = bgp_node_safi(vty);
718e3744 14775
585f1adc
IR
14776 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14777 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14778 || bgp->distance_local[afi][safi] != distance_local) {
14779 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14780 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14781 bgp->distance_local[afi][safi] = distance_local;
14782 bgp_announce_routes_distance_update(bgp, afi, safi);
14783 }
14784 return CMD_SUCCESS;
14785}
37a87b8f 14786
585f1adc
IR
14787DEFUN (no_bgp_distance,
14788 no_bgp_distance_cmd,
14789 "no distance bgp [(1-255) (1-255) (1-255)]",
14790 NO_STR
14791 "Define an administrative distance\n"
14792 "BGP distance\n"
14793 "Distance for routes external to the AS\n"
14794 "Distance for routes internal to the AS\n"
14795 "Distance for local routes\n")
718e3744 14796{
585f1adc 14797 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14798 afi_t afi;
14799 safi_t safi;
37a87b8f
CS
14800
14801 afi = bgp_node_afi(vty);
14802 safi = bgp_node_safi(vty);
14803
585f1adc
IR
14804 if (bgp->distance_ebgp[afi][safi] != 0
14805 || bgp->distance_ibgp[afi][safi] != 0
14806 || bgp->distance_local[afi][safi] != 0) {
14807 bgp->distance_ebgp[afi][safi] = 0;
14808 bgp->distance_ibgp[afi][safi] = 0;
14809 bgp->distance_local[afi][safi] = 0;
14810 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14811 }
585f1adc
IR
14812 return CMD_SUCCESS;
14813}
37a87b8f 14814
37a87b8f 14815
585f1adc
IR
14816DEFUN (bgp_distance_source,
14817 bgp_distance_source_cmd,
14818 "distance (1-255) A.B.C.D/M",
14819 "Define an administrative distance\n"
14820 "Administrative distance\n"
14821 "IP source prefix\n")
14822{
14823 int idx_number = 1;
14824 int idx_ipv4_prefixlen = 2;
14825 bgp_distance_set(vty, argv[idx_number]->arg,
14826 argv[idx_ipv4_prefixlen]->arg, NULL);
14827 return CMD_SUCCESS;
734b349e
MZ
14828}
14829
585f1adc
IR
14830DEFUN (no_bgp_distance_source,
14831 no_bgp_distance_source_cmd,
14832 "no distance (1-255) A.B.C.D/M",
14833 NO_STR
14834 "Define an administrative distance\n"
14835 "Administrative distance\n"
14836 "IP source prefix\n")
37a87b8f 14837{
585f1adc
IR
14838 int idx_number = 2;
14839 int idx_ipv4_prefixlen = 3;
14840 bgp_distance_unset(vty, argv[idx_number]->arg,
14841 argv[idx_ipv4_prefixlen]->arg, NULL);
14842 return CMD_SUCCESS;
37a87b8f
CS
14843}
14844
585f1adc
IR
14845DEFUN (bgp_distance_source_access_list,
14846 bgp_distance_source_access_list_cmd,
14847 "distance (1-255) A.B.C.D/M WORD",
14848 "Define an administrative distance\n"
14849 "Administrative distance\n"
14850 "IP source prefix\n"
14851 "Access list name\n")
37a87b8f 14852{
585f1adc
IR
14853 int idx_number = 1;
14854 int idx_ipv4_prefixlen = 2;
14855 int idx_word = 3;
14856 bgp_distance_set(vty, argv[idx_number]->arg,
14857 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14858 return CMD_SUCCESS;
14859}
718e3744 14860
585f1adc
IR
14861DEFUN (no_bgp_distance_source_access_list,
14862 no_bgp_distance_source_access_list_cmd,
14863 "no distance (1-255) A.B.C.D/M WORD",
14864 NO_STR
14865 "Define an administrative distance\n"
14866 "Administrative distance\n"
14867 "IP source prefix\n"
14868 "Access list name\n")
14869{
14870 int idx_number = 2;
14871 int idx_ipv4_prefixlen = 3;
14872 int idx_word = 4;
14873 bgp_distance_unset(vty, argv[idx_number]->arg,
14874 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14875 return CMD_SUCCESS;
14876}
37a87b8f 14877
585f1adc
IR
14878DEFUN (ipv6_bgp_distance_source,
14879 ipv6_bgp_distance_source_cmd,
14880 "distance (1-255) X:X::X:X/M",
14881 "Define an administrative distance\n"
14882 "Administrative distance\n"
14883 "IP source prefix\n")
14884{
14885 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14886 return CMD_SUCCESS;
14887}
7ebe9748 14888
585f1adc
IR
14889DEFUN (no_ipv6_bgp_distance_source,
14890 no_ipv6_bgp_distance_source_cmd,
14891 "no distance (1-255) X:X::X:X/M",
14892 NO_STR
14893 "Define an administrative distance\n"
14894 "Administrative distance\n"
14895 "IP source prefix\n")
14896{
14897 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14898 return CMD_SUCCESS;
14899}
37a87b8f 14900
585f1adc
IR
14901DEFUN (ipv6_bgp_distance_source_access_list,
14902 ipv6_bgp_distance_source_access_list_cmd,
14903 "distance (1-255) X:X::X:X/M WORD",
14904 "Define an administrative distance\n"
14905 "Administrative distance\n"
14906 "IP source prefix\n"
14907 "Access list name\n")
14908{
14909 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14910 return CMD_SUCCESS;
718e3744 14911}
14912
585f1adc
IR
14913DEFUN (no_ipv6_bgp_distance_source_access_list,
14914 no_ipv6_bgp_distance_source_access_list_cmd,
14915 "no distance (1-255) X:X::X:X/M WORD",
14916 NO_STR
14917 "Define an administrative distance\n"
14918 "Administrative distance\n"
14919 "IP source prefix\n"
14920 "Access list name\n")
718e3744 14921{
585f1adc
IR
14922 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14923 return CMD_SUCCESS;
14924}
37a87b8f 14925
585f1adc
IR
14926DEFUN (bgp_damp_set,
14927 bgp_damp_set_cmd,
a30fec23 14928 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14929 "BGP Specific commands\n"
14930 "Enable route-flap dampening\n"
14931 "Half-life time for the penalty\n"
14932 "Value to start reusing a route\n"
14933 "Value to start suppressing a route\n"
14934 "Maximum duration to suppress a stable route\n")
14935{
14936 VTY_DECLVAR_CONTEXT(bgp, bgp);
14937 int idx_half_life = 2;
14938 int idx_reuse = 3;
14939 int idx_suppress = 4;
14940 int idx_max_suppress = 5;
37a87b8f
CS
14941 int half = DEFAULT_HALF_LIFE * 60;
14942 int reuse = DEFAULT_REUSE;
14943 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14944 int max = 4 * half;
14945
14946 if (argc == 6) {
14947 half = atoi(argv[idx_half_life]->arg) * 60;
14948 reuse = atoi(argv[idx_reuse]->arg);
14949 suppress = atoi(argv[idx_suppress]->arg);
14950 max = atoi(argv[idx_max_suppress]->arg) * 60;
14951 } else if (argc == 3) {
14952 half = atoi(argv[idx_half_life]->arg) * 60;
14953 max = 4 * half;
14954 }
14955
14956 /*
14957 * These can't be 0 but our SA doesn't understand the
14958 * way our cli is constructed
14959 */
14960 assert(reuse);
14961 assert(half);
14962 if (suppress < reuse) {
14963 vty_out(vty,
14964 "Suppress value cannot be less than reuse value \n");
14965 return 0;
14966 }
14967
14968 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14969 reuse, suppress, max);
14970}
14971
14972DEFUN (bgp_damp_unset,
14973 bgp_damp_unset_cmd,
a30fec23 14974 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14975 NO_STR
14976 "BGP Specific commands\n"
14977 "Enable route-flap dampening\n"
14978 "Half-life time for the penalty\n"
14979 "Value to start reusing a route\n"
14980 "Value to start suppressing a route\n"
14981 "Maximum duration to suppress a stable route\n")
14982{
14983 VTY_DECLVAR_CONTEXT(bgp, bgp);
14984 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14985}
14986
718e3744 14987/* Display specified route of BGP table. */
d62a17ae 14988static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14989 const char *ip_str, afi_t afi, safi_t safi,
14990 struct prefix_rd *prd, int prefix_check)
14991{
14992 int ret;
14993 struct prefix match;
9bcb3eef
DS
14994 struct bgp_dest *dest;
14995 struct bgp_dest *rm;
40381db7
DS
14996 struct bgp_path_info *pi;
14997 struct bgp_path_info *pi_temp;
d62a17ae 14998 struct bgp *bgp;
14999 struct bgp_table *table;
15000
15001 /* BGP structure lookup. */
15002 if (view_name) {
15003 bgp = bgp_lookup_by_name(view_name);
15004 if (bgp == NULL) {
15005 vty_out(vty, "%% Can't find BGP instance %s\n",
15006 view_name);
15007 return CMD_WARNING;
15008 }
15009 } else {
15010 bgp = bgp_get_default();
15011 if (bgp == NULL) {
15012 vty_out(vty, "%% No BGP process is configured\n");
15013 return CMD_WARNING;
15014 }
718e3744 15015 }
718e3744 15016
d62a17ae 15017 /* Check IP address argument. */
15018 ret = str2prefix(ip_str, &match);
15019 if (!ret) {
15020 vty_out(vty, "%% address is malformed\n");
15021 return CMD_WARNING;
15022 }
718e3744 15023
d62a17ae 15024 match.family = afi2family(afi);
15025
15026 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
15027 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
15028 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
15029 dest = bgp_route_next(dest)) {
15030 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15031
9bcb3eef 15032 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 15033 continue;
9bcb3eef 15034 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15035 if (!table)
ea47320b 15036 continue;
4953391b
DA
15037 rm = bgp_node_match(table, &match);
15038 if (rm == NULL)
ea47320b 15039 continue;
d62a17ae 15040
9bcb3eef 15041 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15042
ea47320b 15043 if (!prefix_check
b54892e0 15044 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15045 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15046 while (pi) {
15047 if (pi->extra && pi->extra->damp_info) {
15048 pi_temp = pi->next;
ea47320b 15049 bgp_damp_info_free(
19971c9a 15050 pi->extra->damp_info,
5c8846f6 15051 1, afi, safi);
40381db7 15052 pi = pi_temp;
ea47320b 15053 } else
40381db7 15054 pi = pi->next;
d62a17ae 15055 }
ea47320b
DL
15056 }
15057
9bcb3eef 15058 bgp_dest_unlock_node(rm);
d62a17ae 15059 }
15060 } else {
4953391b
DA
15061 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15062 if (dest != NULL) {
9bcb3eef 15063 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15064
d62a17ae 15065 if (!prefix_check
9bcb3eef
DS
15066 || dest_p->prefixlen == match.prefixlen) {
15067 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15068 while (pi) {
15069 if (pi->extra && pi->extra->damp_info) {
15070 pi_temp = pi->next;
d62a17ae 15071 bgp_damp_info_free(
19971c9a 15072 pi->extra->damp_info,
5c8846f6 15073 1, afi, safi);
40381db7 15074 pi = pi_temp;
d62a17ae 15075 } else
40381db7 15076 pi = pi->next;
d62a17ae 15077 }
15078 }
15079
9bcb3eef 15080 bgp_dest_unlock_node(dest);
d62a17ae 15081 }
15082 }
718e3744 15083
d62a17ae 15084 return CMD_SUCCESS;
718e3744 15085}
15086
15087DEFUN (clear_ip_bgp_dampening,
15088 clear_ip_bgp_dampening_cmd,
15089 "clear ip bgp dampening",
15090 CLEAR_STR
15091 IP_STR
15092 BGP_STR
15093 "Clear route flap dampening information\n")
15094{
b4f7f45b 15095 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15096 return CMD_SUCCESS;
718e3744 15097}
15098
15099DEFUN (clear_ip_bgp_dampening_prefix,
15100 clear_ip_bgp_dampening_prefix_cmd,
15101 "clear ip bgp dampening A.B.C.D/M",
15102 CLEAR_STR
15103 IP_STR
15104 BGP_STR
15105 "Clear route flap dampening information\n"
0c7b1b01 15106 "IPv4 prefix\n")
718e3744 15107{
d62a17ae 15108 int idx_ipv4_prefixlen = 4;
15109 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15110 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15111}
15112
15113DEFUN (clear_ip_bgp_dampening_address,
15114 clear_ip_bgp_dampening_address_cmd,
15115 "clear ip bgp dampening A.B.C.D",
15116 CLEAR_STR
15117 IP_STR
15118 BGP_STR
15119 "Clear route flap dampening information\n"
15120 "Network to clear damping information\n")
15121{
d62a17ae 15122 int idx_ipv4 = 4;
15123 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15124 SAFI_UNICAST, NULL, 0);
718e3744 15125}
15126
15127DEFUN (clear_ip_bgp_dampening_address_mask,
15128 clear_ip_bgp_dampening_address_mask_cmd,
15129 "clear ip bgp dampening A.B.C.D A.B.C.D",
15130 CLEAR_STR
15131 IP_STR
15132 BGP_STR
15133 "Clear route flap dampening information\n"
15134 "Network to clear damping information\n"
15135 "Network mask\n")
15136{
d62a17ae 15137 int idx_ipv4 = 4;
15138 int idx_ipv4_2 = 5;
15139 int ret;
15140 char prefix_str[BUFSIZ];
718e3744 15141
d62a17ae 15142 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15143 prefix_str, sizeof(prefix_str));
d62a17ae 15144 if (!ret) {
15145 vty_out(vty, "%% Inconsistent address and mask\n");
15146 return CMD_WARNING;
15147 }
718e3744 15148
d62a17ae 15149 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15150 NULL, 0);
718e3744 15151}
6b0655a2 15152
e3b78da8 15153static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15154{
15155 struct vty *vty = arg;
e3b78da8 15156 struct peer *peer = bucket->data;
825d9834 15157
47e12884 15158 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15159}
15160
2a0e69ae
DS
15161DEFUN (show_bgp_listeners,
15162 show_bgp_listeners_cmd,
15163 "show bgp listeners",
15164 SHOW_STR
15165 BGP_STR
15166 "Display Listen Sockets and who created them\n")
15167{
15168 bgp_dump_listener_info(vty);
15169
15170 return CMD_SUCCESS;
15171}
15172
825d9834
DS
15173DEFUN (show_bgp_peerhash,
15174 show_bgp_peerhash_cmd,
15175 "show bgp peerhash",
15176 SHOW_STR
15177 BGP_STR
15178 "Display information about the BGP peerhash\n")
15179{
15180 struct list *instances = bm->bgp;
15181 struct listnode *node;
15182 struct bgp *bgp;
15183
15184 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15185 vty_out(vty, "BGP: %s\n", bgp->name);
15186 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15187 vty);
15188 }
15189
15190 return CMD_SUCCESS;
15191}
15192
587ff0fd 15193/* also used for encap safi */
2b791107
DL
15194static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15195 afi_t afi, safi_t safi)
d62a17ae 15196{
9bcb3eef
DS
15197 struct bgp_dest *pdest;
15198 struct bgp_dest *dest;
d62a17ae 15199 struct bgp_table *table;
b54892e0
DS
15200 const struct prefix *p;
15201 const struct prefix_rd *prd;
d62a17ae 15202 struct bgp_static *bgp_static;
15203 mpls_label_t label;
d62a17ae 15204
15205 /* Network configuration. */
9bcb3eef
DS
15206 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15207 pdest = bgp_route_next(pdest)) {
15208 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15209 if (!table)
ea47320b 15210 continue;
d62a17ae 15211
9bcb3eef
DS
15212 for (dest = bgp_table_top(table); dest;
15213 dest = bgp_route_next(dest)) {
15214 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15215 if (bgp_static == NULL)
ea47320b 15216 continue;
d62a17ae 15217
9bcb3eef
DS
15218 p = bgp_dest_get_prefix(dest);
15219 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15220 pdest);
d62a17ae 15221
ea47320b 15222 /* "network" configuration display. */
ea47320b
DL
15223 label = decode_label(&bgp_static->label);
15224
c4f64ea9 15225 vty_out(vty, " network %pFX rd %pRD", p, prd);
ea47320b
DL
15226 if (safi == SAFI_MPLS_VPN)
15227 vty_out(vty, " label %u", label);
15228
15229 if (bgp_static->rmap.name)
15230 vty_out(vty, " route-map %s",
15231 bgp_static->rmap.name);
e2a86ad9
DS
15232
15233 if (bgp_static->backdoor)
15234 vty_out(vty, " backdoor");
15235
ea47320b
DL
15236 vty_out(vty, "\n");
15237 }
15238 }
d62a17ae 15239}
15240
2b791107
DL
15241static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15242 afi_t afi, safi_t safi)
d62a17ae 15243{
9bcb3eef
DS
15244 struct bgp_dest *pdest;
15245 struct bgp_dest *dest;
d62a17ae 15246 struct bgp_table *table;
b54892e0
DS
15247 const struct prefix *p;
15248 const struct prefix_rd *prd;
d62a17ae 15249 struct bgp_static *bgp_static;
ff44f570 15250 char buf[PREFIX_STRLEN * 2];
d62a17ae 15251 char buf2[SU_ADDRSTRLEN];
5f933e1e 15252 char esi_buf[ESI_STR_LEN];
d62a17ae 15253
15254 /* Network configuration. */
9bcb3eef
DS
15255 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15256 pdest = bgp_route_next(pdest)) {
15257 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15258 if (!table)
ea47320b 15259 continue;
d62a17ae 15260
9bcb3eef
DS
15261 for (dest = bgp_table_top(table); dest;
15262 dest = bgp_route_next(dest)) {
15263 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15264 if (bgp_static == NULL)
ea47320b 15265 continue;
d62a17ae 15266
ea47320b 15267 char *macrouter = NULL;
d62a17ae 15268
ea47320b
DL
15269 if (bgp_static->router_mac)
15270 macrouter = prefix_mac2str(
15271 bgp_static->router_mac, NULL, 0);
15272 if (bgp_static->eth_s_id)
0a50c248
AK
15273 esi_to_str(bgp_static->eth_s_id,
15274 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15275 p = bgp_dest_get_prefix(dest);
15276 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15277
ea47320b 15278 /* "network" configuration display. */
197cb530
PG
15279 if (p->u.prefix_evpn.route_type == 5) {
15280 char local_buf[PREFIX_STRLEN];
3714a385 15281 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15282 struct prefix_evpn *)p)
15283 ? AF_INET
15284 : AF_INET6;
3714a385 15285 inet_ntop(family,
15286 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15287 local_buf, PREFIX_STRLEN);
772270f3
QY
15288 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15289 p->u.prefix_evpn.prefix_addr
15290 .ip_prefix_length);
197cb530
PG
15291 } else {
15292 prefix2str(p, buf, sizeof(buf));
15293 }
ea47320b 15294
a4d82a8a
PZ
15295 if (bgp_static->gatewayIp.family == AF_INET
15296 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15297 inet_ntop(bgp_static->gatewayIp.family,
15298 &bgp_static->gatewayIp.u.prefix, buf2,
15299 sizeof(buf2));
ea47320b 15300 vty_out(vty,
c4f64ea9
DA
15301 " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
15302 buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15303 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15304 macrouter);
15305
0a22ddfb 15306 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15307 }
15308 }
3da6fcd5
PG
15309}
15310
718e3744 15311/* Configuration of static route announcement and aggregate
15312 information. */
2b791107
DL
15313void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15314 safi_t safi)
d62a17ae 15315{
9bcb3eef 15316 struct bgp_dest *dest;
b54892e0 15317 const struct prefix *p;
d62a17ae 15318 struct bgp_static *bgp_static;
15319 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15320
2b791107
DL
15321 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15322 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15323 return;
15324 }
d62a17ae 15325
2b791107
DL
15326 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15327 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15328 return;
15329 }
d62a17ae 15330
15331 /* Network configuration. */
9bcb3eef
DS
15332 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15333 dest = bgp_route_next(dest)) {
15334 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15335 if (bgp_static == NULL)
ea47320b 15336 continue;
d62a17ae 15337
9bcb3eef 15338 p = bgp_dest_get_prefix(dest);
d62a17ae 15339
8228a9a7 15340 vty_out(vty, " network %pFX", p);
d62a17ae 15341
ea47320b
DL
15342 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15343 vty_out(vty, " label-index %u",
15344 bgp_static->label_index);
d62a17ae 15345
ea47320b
DL
15346 if (bgp_static->rmap.name)
15347 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15348
15349 if (bgp_static->backdoor)
15350 vty_out(vty, " backdoor");
718e3744 15351
ea47320b
DL
15352 vty_out(vty, "\n");
15353 }
15354
d62a17ae 15355 /* Aggregate-address configuration. */
9bcb3eef
DS
15356 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15357 dest = bgp_route_next(dest)) {
15358 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15359 if (bgp_aggregate == NULL)
ea47320b 15360 continue;
d62a17ae 15361
9bcb3eef 15362 p = bgp_dest_get_prefix(dest);
d62a17ae 15363
8228a9a7 15364 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15365
ea47320b
DL
15366 if (bgp_aggregate->as_set)
15367 vty_out(vty, " as-set");
d62a17ae 15368
ea47320b
DL
15369 if (bgp_aggregate->summary_only)
15370 vty_out(vty, " summary-only");
718e3744 15371
20894f50
DA
15372 if (bgp_aggregate->rmap.name)
15373 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15374
229757f1
DA
15375 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15376 vty_out(vty, " origin %s",
15377 bgp_origin2str(bgp_aggregate->origin));
15378
6aabb15d
RZ
15379 if (bgp_aggregate->match_med)
15380 vty_out(vty, " matching-MED-only");
15381
365ab2e7
RZ
15382 if (bgp_aggregate->suppress_map_name)
15383 vty_out(vty, " suppress-map %s",
15384 bgp_aggregate->suppress_map_name);
15385
ea47320b
DL
15386 vty_out(vty, "\n");
15387 }
d62a17ae 15388}
734b349e 15389
2b791107 15390void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15391 safi_t safi)
d62a17ae 15392{
9bcb3eef 15393 struct bgp_dest *dest;
d62a17ae 15394 struct bgp_distance *bdistance;
15395
15396 /* Distance configuration. */
15397 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15398 && bgp->distance_local[afi][safi]
15399 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15400 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15401 || bgp->distance_local[afi][safi]
15402 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15403 vty_out(vty, " distance bgp %d %d %d\n",
15404 bgp->distance_ebgp[afi][safi],
15405 bgp->distance_ibgp[afi][safi],
15406 bgp->distance_local[afi][safi]);
15407 }
734b349e 15408
9bcb3eef
DS
15409 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15410 dest = bgp_route_next(dest)) {
15411 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15412 if (bdistance != NULL)
56ca3b5b 15413 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15414 bdistance->distance, dest,
d62a17ae 15415 bdistance->access_list ? bdistance->access_list
15416 : "");
ca2e160d 15417 }
718e3744 15418}
15419
15420/* Allocate routing table structure and install commands. */
d62a17ae 15421void bgp_route_init(void)
15422{
15423 afi_t afi;
15424 safi_t safi;
15425
15426 /* Init BGP distance table. */
05c7a1cc 15427 FOREACH_AFI_SAFI (afi, safi)
960035b2 15428 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15429
15430 /* IPv4 BGP commands. */
15431 install_element(BGP_NODE, &bgp_table_map_cmd);
15432 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15433 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15434
554b3b10 15435 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15436
15437 /* IPv4 unicast configuration. */
15438 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15439 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15440 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15441
554b3b10 15442 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15443
15444 /* IPv4 multicast configuration. */
15445 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15446 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15447 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15448 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15449
15450 /* IPv4 labeled-unicast configuration. */
fb985e0c 15451 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15452 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15453
d62a17ae 15454 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15455 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15456 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15457 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15458 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15459 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15460 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15461 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15462
15463 install_element(VIEW_NODE,
15464 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15465 install_element(VIEW_NODE,
15466 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15467 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15468 install_element(VIEW_NODE,
15469 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15470#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15471 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15472#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15473 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15474 install_element(VIEW_NODE,
44c69747 15475 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15476
d62a17ae 15477 /* BGP dampening clear commands */
15478 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15479 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15480
d62a17ae 15481 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15482 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15483
15484 /* prefix count */
15485 install_element(ENABLE_NODE,
15486 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15487#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15488 install_element(ENABLE_NODE,
15489 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15490#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15491
d62a17ae 15492 /* New config IPv6 BGP commands. */
15493 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15494 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15495 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15496
554b3b10 15497 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15498
15499 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15500
fb985e0c
DA
15501 /* IPv6 labeled unicast address family. */
15502 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15503 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15504
d62a17ae 15505 install_element(BGP_NODE, &bgp_distance_cmd);
15506 install_element(BGP_NODE, &no_bgp_distance_cmd);
15507 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15508 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15509 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15510 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15511 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15512 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15513 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15514 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15515 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15516 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15517 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15518 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15519 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15520 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15521 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15522 install_element(BGP_IPV4M_NODE,
15523 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15524 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15525 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15526 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15527 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15528 install_element(BGP_IPV6_NODE,
15529 &ipv6_bgp_distance_source_access_list_cmd);
15530 install_element(BGP_IPV6_NODE,
15531 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15532 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15533 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15534 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15535 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15536 install_element(BGP_IPV6M_NODE,
15537 &ipv6_bgp_distance_source_access_list_cmd);
15538 install_element(BGP_IPV6M_NODE,
15539 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15540
ef5f4b23 15541 /* BGP dampening */
585f1adc
IR
15542 install_element(BGP_NODE, &bgp_damp_set_cmd);
15543 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15544 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15545 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15546 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15547 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15548 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15549 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15550 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15551 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15552 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15553 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15554 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15555 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15556
15557 /* Large Communities */
15558 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15559 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15560
15561 /* show bgp ipv4 flowspec detailed */
15562 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15563
2a0e69ae 15564 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15565 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15566}
15567
15568void bgp_route_finish(void)
15569{
15570 afi_t afi;
15571 safi_t safi;
15572
05c7a1cc
QY
15573 FOREACH_AFI_SAFI (afi, safi) {
15574 bgp_table_unlock(bgp_distance_table[afi][safi]);
15575 bgp_distance_table[afi][safi] = NULL;
15576 }
228da428 15577}