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