]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
topotests: add bgp_vpnv4_ebgp test with 'mpls bgp forwarding'
[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{
9bbdb457
DA
1779 if (peer->sort == BGP_PEER_EBGP &&
1780 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
1781 attr->aspath = aspath_replace_specific_asn(attr->aspath,
1782 peer->as, bgp->as);
d62a17ae 1783}
1784
1479ed2f
DA
1785void bgp_attr_add_llgr_community(struct attr *attr)
1786{
1787 struct community *old;
1788 struct community *new;
1789 struct community *merge;
1790 struct community *llgr;
1791
9a706b42 1792 old = bgp_attr_get_community(attr);
1479ed2f
DA
1793 llgr = community_str2com("llgr-stale");
1794
1795 assert(llgr);
1796
1797 if (old) {
1798 merge = community_merge(community_dup(old), llgr);
1799
1800 if (old->refcnt == 0)
1801 community_free(&old);
1802
1803 new = community_uniq_sort(merge);
1804 community_free(&merge);
1805 } else {
1806 new = community_dup(llgr);
1807 }
1808
1809 community_free(&llgr);
1810
9a706b42 1811 bgp_attr_set_community(attr, new);
1479ed2f
DA
1812}
1813
7f323236
DW
1814void bgp_attr_add_gshut_community(struct attr *attr)
1815{
1816 struct community *old;
1817 struct community *new;
1818 struct community *merge;
1819 struct community *gshut;
1820
9a706b42 1821 old = bgp_attr_get_community(attr);
7f323236
DW
1822 gshut = community_str2com("graceful-shutdown");
1823
990f4f91 1824 assert(gshut);
1825
7f323236
DW
1826 if (old) {
1827 merge = community_merge(community_dup(old), gshut);
1828
a4d82a8a 1829 if (old->refcnt == 0)
3c1f53de 1830 community_free(&old);
7f323236
DW
1831
1832 new = community_uniq_sort(merge);
3c1f53de 1833 community_free(&merge);
7f323236
DW
1834 } else {
1835 new = community_dup(gshut);
1836 }
1837
3c1f53de 1838 community_free(&gshut);
9a706b42 1839 bgp_attr_set_community(attr, new);
7f323236
DW
1840
1841 /* When we add the graceful-shutdown community we must also
1842 * lower the local-preference */
1843 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1844 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1845}
1846
1847
e73c112e
MK
1848/* Notify BGP Conditional advertisement scanner process. */
1849void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1850{
e73c112e 1851 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1852 afi_t afi = SUBGRP_AFI(subgrp);
1853 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1854 struct bgp_filter *filter = &peer->filter[afi][safi];
1855
1856 if (!ADVERTISE_MAP_NAME(filter))
1857 return;
1858
52979c3b
DS
1859 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1860 return;
e73c112e 1861
52979c3b 1862 peer->advmap_table_change = true;
e73c112e
MK
1863}
1864
1865
f2ee6d5c 1866void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1867{
960035b2 1868 if (family == AF_INET) {
975a328e
DA
1869 attr->nexthop.s_addr = INADDR_ANY;
1870 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1871 }
d62a17ae 1872 if (family == AF_INET6)
1873 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1874 if (family == AF_EVPN)
1875 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1876}
1877
9bcb3eef 1878bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1879 struct update_subgroup *subgrp,
7f7940e6 1880 const struct prefix *p, struct attr *attr,
51c3a7de 1881 struct attr *post_attr)
d62a17ae 1882{
1883 struct bgp_filter *filter;
1884 struct peer *from;
1885 struct peer *peer;
1886 struct peer *onlypeer;
1887 struct bgp *bgp;
40381db7 1888 struct attr *piattr;
b68885f9 1889 route_map_result_t ret;
d62a17ae 1890 int transparent;
1891 int reflect;
1892 afi_t afi;
1893 safi_t safi;
1894 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1895 bool nh_reset = false;
1896 uint64_t cum_bw;
d62a17ae 1897
1898 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1899 return false;
d62a17ae 1900
1901 afi = SUBGRP_AFI(subgrp);
1902 safi = SUBGRP_SAFI(subgrp);
1903 peer = SUBGRP_PEER(subgrp);
1904 onlypeer = NULL;
1905 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1906 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1907
40381db7 1908 from = pi->peer;
d62a17ae 1909 filter = &peer->filter[afi][safi];
1910 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1911 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1912 : pi->attr;
3f9c7369 1913
d0bf49ec
LS
1914 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1915 peer->pmax_out[afi][safi] != 0 &&
1916 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1917 if (BGP_DEBUG(update, UPDATE_OUT) ||
1918 BGP_DEBUG(update, UPDATE_PREFIX)) {
1919 zlog_debug("%s reached maximum prefix to be send (%u)",
1920 peer->host, peer->pmax_out[afi][safi]);
1921 }
1922 return false;
1923 }
1924
49e5a4a0 1925#ifdef ENABLE_BGP_VNC
d62a17ae 1926 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1927 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1928 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1929
1930 /*
1931 * direct and direct_ext type routes originate internally even
1932 * though they can have peer pointers that reference other
1933 * systems
1934 */
8228a9a7
DS
1935 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1936 __func__, p);
d62a17ae 1937 samepeer_safe = 1;
1938 }
65efcfce
LB
1939#endif
1940
ddb5b488
PZ
1941 if (((afi == AFI_IP) || (afi == AFI_IP6))
1942 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1943 && (pi->type == ZEBRA_ROUTE_BGP)
1944 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1945
1946 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1947
1948 samepeer_safe = 1;
1949 }
1950
d62a17ae 1951 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1952 * pi is valid */
1953 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1954 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1955 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1956 return false;
d62a17ae 1957 }
adbac85e 1958
d62a17ae 1959 /* If this is not the bestpath then check to see if there is an enabled
1960 * addpath
1961 * feature that requires us to advertise it */
40381db7 1962 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1963 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1964 return false;
d62a17ae 1965 }
1966 }
06370dac 1967
d62a17ae 1968 /* Aggregate-address suppress check. */
4056a5f6
RZ
1969 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1970 return false;
3f9c7369 1971
13b7e7f0
DS
1972 /*
1973 * If we are doing VRF 2 VRF leaking via the import
1974 * statement, we want to prevent the route going
1975 * off box as that the RT and RD created are localy
1976 * significant and globaly useless.
1977 */
40381db7
DS
1978 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1979 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1980 return false;
13b7e7f0 1981
d62a17ae 1982 /* If it's labeled safi, make sure the route has a valid label. */
1983 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1984 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1985 if (!bgp_is_valid_label(&label)) {
1986 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1987 zlog_debug("u%" PRIu64 ":s%" PRIu64
1988 " %pFX is filtered - no label (%p)",
d62a17ae 1989 subgrp->update_group->id, subgrp->id,
8228a9a7 1990 p, &label);
3dc339cd 1991 return false;
d62a17ae 1992 }
1993 }
cd1964ff 1994
d62a17ae 1995 /* Do not send back route to sender. */
1996 if (onlypeer && from == onlypeer) {
3dc339cd 1997 return false;
d62a17ae 1998 }
3f9c7369 1999
d62a17ae 2000 /* Do not send the default route in the BGP table if the neighbor is
2001 * configured for default-originate */
2002 if (CHECK_FLAG(peer->af_flags[afi][safi],
2003 PEER_FLAG_DEFAULT_ORIGINATE)) {
2004 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2005 return false;
d62a17ae 2006 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2007 return false;
d62a17ae 2008 }
4125bb67 2009
d62a17ae 2010 /* Transparency check. */
2011 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2012 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2013 transparent = 1;
2014 else
2015 transparent = 0;
2016
2017 /* If community is not disabled check the no-export and local. */
40381db7 2018 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2019 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2020 zlog_debug("%s: community filter check fail for %pFX",
2021 __func__, p);
3dc339cd 2022 return false;
d62a17ae 2023 }
3f9c7369 2024
d62a17ae 2025 /* If the attribute has originator-id and it is same as remote
2026 peer's id. */
40381db7
DS
2027 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2028 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2029 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2030 zlog_debug(
a9f3f4f5
DA
2031 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2032 onlypeer, p);
3dc339cd 2033 return false;
d62a17ae 2034 }
3f9c7369 2035
d62a17ae 2036 /* ORF prefix-list filter check */
2037 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2038 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2039 || CHECK_FLAG(peer->af_cap[afi][safi],
2040 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2041 if (peer->orf_plist[afi][safi]) {
2042 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2043 == PREFIX_DENY) {
2044 if (bgp_debug_update(NULL, p,
2045 subgrp->update_group, 0))
2046 zlog_debug(
a9f3f4f5
DA
2047 "%pBP [Update:SEND] %pFX is filtered via ORF",
2048 peer, p);
3dc339cd 2049 return false;
d62a17ae 2050 }
2051 }
2052
2053 /* Output filter check. */
40381db7 2054 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2055 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
a9f3f4f5
DA
2056 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2057 p);
3dc339cd 2058 return false;
d62a17ae 2059 }
3f9c7369 2060
d62a17ae 2061 /* AS path loop check. */
2b31007c
RZ
2062 if (onlypeer && onlypeer->as_path_loop_detection
2063 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2064 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2065 zlog_debug(
a9f3f4f5
DA
2066 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2067 onlypeer, onlypeer->as);
3dc339cd 2068 return false;
d62a17ae 2069 }
3f9c7369 2070
d62a17ae 2071 /* If we're a CONFED we need to loop check the CONFED ID too */
2072 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2073 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
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 is AS path.",
2077 peer, bgp->confed_id);
3dc339cd 2078 return false;
d62a17ae 2079 }
3f9c7369 2080 }
3f9c7369 2081
d62a17ae 2082 /* Route-Reflect check. */
2083 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2084 reflect = 1;
2085 else
2086 reflect = 0;
2087
2088 /* IBGP reflection check. */
2089 if (reflect && !samepeer_safe) {
2090 /* A route from a Client peer. */
2091 if (CHECK_FLAG(from->af_flags[afi][safi],
2092 PEER_FLAG_REFLECTOR_CLIENT)) {
2093 /* Reflect to all the Non-Client peers and also to the
2094 Client peers other than the originator. Originator
2095 check
2096 is already done. So there is noting to do. */
2097 /* no bgp client-to-client reflection check. */
892fedb6
DA
2098 if (CHECK_FLAG(bgp->flags,
2099 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2100 if (CHECK_FLAG(peer->af_flags[afi][safi],
2101 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2102 return false;
d62a17ae 2103 } else {
2104 /* A route from a Non-client peer. Reflect to all other
2105 clients. */
2106 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2107 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2108 return false;
d62a17ae 2109 }
2110 }
3f9c7369 2111
51c3a7de
DA
2112 /* For modify attribute, copy it to temporary structure.
2113 * post_attr comes from BGP conditional advertisements, where
2114 * attributes are already processed by advertise-map route-map,
2115 * and this needs to be saved instead of overwriting from the
2116 * path attributes.
2117 */
2118 if (post_attr)
2119 *attr = *post_attr;
2120 else
2121 *attr = *piattr;
d62a17ae 2122
2123 /* If local-preference is not set. */
2124 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2125 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2126 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2127 attr->local_pref = bgp->default_local_pref;
3f9c7369 2128 }
3f9c7369 2129
d62a17ae 2130 /* If originator-id is not set and the route is to be reflected,
2131 set the originator id */
2132 if (reflect
2133 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2134 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2135 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2136 }
3f9c7369 2137
d62a17ae 2138 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2139 */
2140 if (peer->sort == BGP_PEER_EBGP
2141 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2142 if (from != bgp->peer_self && !transparent
2143 && !CHECK_FLAG(peer->af_flags[afi][safi],
2144 PEER_FLAG_MED_UNCHANGED))
2145 attr->flag &=
2146 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2147 }
3f9c7369 2148
d62a17ae 2149 /* Since the nexthop attribute can vary per peer, it is not explicitly
2150 * set
2151 * in announce check, only certain flags and length (or number of
2152 * nexthops
2153 * -- for IPv6/MP_REACH) are set here in order to guide the update
2154 * formation
2155 * code in setting the nexthop(s) on a per peer basis in
2156 * reformat_peer().
2157 * Typically, the source nexthop in the attribute is preserved but in
2158 * the
2159 * scenarios where we know it will always be overwritten, we reset the
2160 * nexthop to "0" in an attempt to achieve better Update packing. An
2161 * example of this is when a prefix from each of 2 IBGP peers needs to
2162 * be
2163 * announced to an EBGP peer (and they have the same attributes barring
2164 * their nexthop).
2165 */
2166 if (reflect)
2167 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2168
2169#define NEXTHOP_IS_V6 \
2170 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2171 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2172 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2173 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2174
2175 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2176 * if
2177 * the peer (group) is configured to receive link-local nexthop
2178 * unchanged
c728d027
DA
2179 * and it is available in the prefix OR we're not reflecting the route,
2180 * link-local nexthop address is valid and
d62a17ae 2181 * the peer (group) to whom we're going to announce is on a shared
2182 * network
2183 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2184 * By checking if nexthop LL address is valid we are sure that
2185 * we do not announce LL address as `::`.
d62a17ae 2186 */
2187 if (NEXTHOP_IS_V6) {
2188 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2189 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2190 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2191 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2192 || (!reflect && !transparent
c728d027
DA
2193 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2194 && peer->shared_network
d62a17ae 2195 && (from == bgp->peer_self
2196 || peer->sort == BGP_PEER_EBGP))) {
2197 attr->mp_nexthop_len =
2198 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2199 }
3f9c7369 2200
d62a17ae 2201 /* Clear off link-local nexthop in source, whenever it is not
2202 * needed to
2203 * ensure more prefixes share the same attribute for
2204 * announcement.
2205 */
2206 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2207 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2208 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2209 }
3f9c7369 2210
5a78f2bc
EB
2211 if (bgp_check_role_applicability(afi, safi) &&
2212 bgp_otc_egress(peer, attr))
d864dd9e
EB
2213 return false;
2214
d62a17ae 2215 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2216 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2217
0655090c
QY
2218 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2219 filter->advmap.aname &&
2220 route_map_lookup_by_name(filter->advmap.aname)) {
2221 struct bgp_path_info rmap_path = {0};
2222 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2223 struct attr dummy_attr = *attr;
2224
2225 /* Fill temp path_info */
2226 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2227 pi, peer, &dummy_attr);
2228
2229 struct route_map *amap =
2230 route_map_lookup_by_name(filter->advmap.aname);
2231
2232 ret = route_map_apply(amap, p, &rmap_path);
2233
2234 bgp_attr_flush(&dummy_attr);
2235
2236 /*
2237 * The conditional advertisement mode is Withdraw and this
2238 * prefix is a conditional prefix. Don't advertise it
2239 */
2240 if (ret == RMAP_PERMITMATCH)
2241 return false;
2242 }
2243
d62a17ae 2244 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2245 if (!post_attr &&
2246 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2247 struct bgp_path_info rmap_path = {0};
2248 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2249 struct attr dummy_attr = {0};
d62a17ae 2250
e34291b8 2251 /* Fill temp path_info */
9bcb3eef
DS
2252 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2253 pi, peer, attr);
16f7ce2b 2254
d62a17ae 2255 /* don't confuse inbound and outbound setting */
2256 RESET_FLAG(attr->rmap_change_flags);
2257
2258 /*
2259 * The route reflector is not allowed to modify the attributes
2260 * of the reflected IBGP routes unless explicitly allowed.
2261 */
2262 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2263 && !CHECK_FLAG(bgp->flags,
2264 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2265 dummy_attr = *attr;
40381db7 2266 rmap_path.attr = &dummy_attr;
d62a17ae 2267 }
3f9c7369 2268
d62a17ae 2269 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2270
4056a5f6 2271 if (bgp_path_suppressed(pi))
d62a17ae 2272 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2273 &rmap_path);
d62a17ae 2274 else
2275 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2276 &rmap_path);
d62a17ae 2277
7e7639f5 2278 bgp_attr_flush(&dummy_attr);
d62a17ae 2279 peer->rmap_type = 0;
2280
2281 if (ret == RMAP_DENYMATCH) {
778048bf 2282 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2283 zlog_debug(
a9f3f4f5
DA
2284 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2285 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2286 bgp_attr_flush(rmap_path.attr);
3dc339cd 2287 return false;
d62a17ae 2288 }
3f9c7369 2289 }
3f9c7369 2290
9dac9fc8
DA
2291 /* RFC 8212 to prevent route leaks.
2292 * This specification intends to improve this situation by requiring the
2293 * explicit configuration of both BGP Import and Export Policies for any
2294 * External BGP (EBGP) session such as customers, peers, or
2295 * confederation boundaries for all enabled address families. Through
2296 * codification of the aforementioned requirement, operators will
2297 * benefit from consistent behavior across different BGP
2298 * implementations.
2299 */
1d3fdccf 2300 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2301 if (!bgp_outbound_policy_exists(peer, filter)) {
2302 if (monotime_since(&bgp->ebgprequirespolicywarning,
2303 NULL) > FIFTEENMINUTE2USEC ||
2304 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2305 zlog_warn(
2306 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2307 monotime(&bgp->ebgprequirespolicywarning);
2308 }
3dc339cd 2309 return false;
b17826b7 2310 }
9dac9fc8 2311
fb29348a
DA
2312 /* draft-ietf-idr-deprecate-as-set-confed-set
2313 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2314 * Eventually, This document (if approved) updates RFC 4271
2315 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2316 * and obsoletes RFC 6472.
2317 */
7f972cd8 2318 if (peer->bgp->reject_as_sets)
fb29348a 2319 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2320 return false;
fb29348a 2321
01da2d26
DA
2322 /* If neighbor sso is configured, then check if the route has
2323 * SoO extended community and validate against the configured
2324 * one. If they match, do not announce, to prevent routing
2325 * loops.
2326 */
2327 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
2328 peer->soo[afi][safi]) {
2329 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
2330 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
2331
2332 if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
2333 ECOMMUNITY_SITE_ORIGIN) ||
2334 ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
2335 ECOMMUNITY_SITE_ORIGIN)) &&
2336 ecommunity_include(ecomm, ecomm_soo)) {
2337 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2338 zlog_debug(
2339 "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
2340 peer, p, ecommunity_str(ecomm_soo));
2341 return false;
2342 }
2343 }
2344
33d022bc
DA
2345 /* Codification of AS 0 Processing */
2346 if (aspath_check_as_zero(attr->aspath))
e2369003 2347 return false;
33d022bc 2348
637e5ba4 2349 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2350 if (peer->sort == BGP_PEER_IBGP
2351 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2352 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2353 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2354 } else {
2355 bgp_attr_add_gshut_community(attr);
2356 }
2357 }
2358
1479ed2f
DA
2359 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2360 * Capability" to a neighbor MUST perform the following upon receiving
2361 * a route from that neighbor with the "LLGR_STALE" community, or upon
2362 * attaching the "LLGR_STALE" community itself per Section 4.2:
2363 *
2364 * The route SHOULD NOT be advertised to any neighbor from which the
2365 * Long-lived Graceful Restart Capability has not been received.
2366 */
9a706b42
DA
2367 if (bgp_attr_get_community(attr) &&
2368 community_include(bgp_attr_get_community(attr),
2369 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2370 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2371 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2372 return false;
2373
d62a17ae 2374 /* After route-map has been applied, we check to see if the nexthop to
2375 * be carried in the attribute (that is used for the announcement) can
2376 * be cleared off or not. We do this in all cases where we would be
2377 * setting the nexthop to "ourselves". For IPv6, we only need to
2378 * consider
2379 * the global nexthop here; the link-local nexthop would have been
2380 * cleared
2381 * already, and if not, it is required by the update formation code.
2382 * Also see earlier comments in this function.
2383 */
2384 /*
2385 * If route-map has performed some operation on the nexthop or the peer
2386 * configuration says to pass it unchanged, we cannot reset the nexthop
2387 * here, so only attempt to do it if these aren't true. Note that the
2388 * route-map handler itself might have cleared the nexthop, if for
2389 * example,
2390 * it is configured as 'peer-address'.
2391 */
2392 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2393 piattr->rmap_change_flags)
d62a17ae 2394 && !transparent
2395 && !CHECK_FLAG(peer->af_flags[afi][safi],
2396 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2397 /* We can reset the nexthop, if setting (or forcing) it to
2398 * 'self' */
2399 if (CHECK_FLAG(peer->af_flags[afi][safi],
2400 PEER_FLAG_NEXTHOP_SELF)
2401 || CHECK_FLAG(peer->af_flags[afi][safi],
2402 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2403 if (!reflect
2404 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2405 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2406 subgroup_announce_reset_nhop(
2407 (peer_cap_enhe(peer, afi, safi)
2408 ? AF_INET6
2409 : p->family),
2410 attr);
7b651a32 2411 nh_reset = true;
2412 }
d62a17ae 2413 } else if (peer->sort == BGP_PEER_EBGP) {
2414 /* Can also reset the nexthop if announcing to EBGP, but
2415 * only if
2416 * no peer in the subgroup is on a shared subnet.
2417 * Note: 3rd party nexthop currently implemented for
2418 * IPv4 only.
2419 */
737af885
BS
2420 if ((p->family == AF_INET) &&
2421 (!bgp_subgrp_multiaccess_check_v4(
2422 piattr->nexthop,
7b651a32 2423 subgrp, from))) {
d62a17ae 2424 subgroup_announce_reset_nhop(
2425 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2426 ? AF_INET6
2427 : p->family),
737af885 2428 attr);
7b651a32 2429 nh_reset = true;
2430 }
737af885
BS
2431
2432 if ((p->family == AF_INET6) &&
2433 (!bgp_subgrp_multiaccess_check_v6(
2434 piattr->mp_nexthop_global,
7b651a32 2435 subgrp, from))) {
737af885
BS
2436 subgroup_announce_reset_nhop(
2437 (peer_cap_enhe(peer, afi, safi)
2438 ? AF_INET6
2439 : p->family),
2440 attr);
7b651a32 2441 nh_reset = true;
2442 }
737af885
BS
2443
2444
2445
40381db7 2446 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2447 /*
2448 * This flag is used for leaked vpn-vrf routes
2449 */
2450 int family = p->family;
2451
2452 if (peer_cap_enhe(peer, afi, safi))
2453 family = AF_INET6;
2454
2455 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2456 zlog_debug(
1defdda8 2457 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2458 __func__, family2str(family));
2459 subgroup_announce_reset_nhop(family, attr);
7b651a32 2460 nh_reset = true;
d62a17ae 2461 }
63696f1d 2462 }
960035b2 2463
63696f1d 2464 /* If IPv6/MP and nexthop does not have any override and happens
2465 * to
2466 * be a link-local address, reset it so that we don't pass along
2467 * the
2468 * source's link-local IPv6 address to recipients who may not be
2469 * on
2470 * the same interface.
2471 */
2472 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2473 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2474 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2475 nh_reset = true;
2476 }
d62a17ae 2477 }
3f9c7369 2478
7b651a32 2479 /*
2480 * When the next hop is set to ourselves, if all multipaths have
2481 * link-bandwidth announce the cumulative bandwidth as that makes
2482 * the most sense. However, don't modify if the link-bandwidth has
2483 * been explicitly set by user policy.
2484 */
2485 if (nh_reset &&
f7e1c681 2486 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2487 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2488 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2489 bgp_attr_set_ecommunity(
2490 attr,
2491 ecommunity_replace_linkbw(
2492 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2493 CHECK_FLAG(
2494 peer->flags,
2495 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2496
3dc339cd 2497 return true;
3f9c7369
DS
2498}
2499
cc9f21da 2500static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2501{
2502 struct afi_safi_info *info;
2503 afi_t afi;
2504 safi_t safi;
2505 struct bgp *bgp;
2506
2507 info = THREAD_ARG(thread);
2508 afi = info->afi;
2509 safi = info->safi;
2510 bgp = info->bgp;
2511
2512 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2513 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2514 safi);
f009ff26 2515
2516 bgp->gr_info[afi][safi].t_route_select = NULL;
2517
2518 XFREE(MTYPE_TMP, info);
2519
2520 /* Best path selection */
cc9f21da 2521 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2522}
2523
9bcb3eef 2524void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2525 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2526 struct bgp_path_info_pair *result, afi_t afi,
2527 safi_t safi)
2528{
2529 struct bgp_path_info *new_select;
2530 struct bgp_path_info *old_select;
40381db7
DS
2531 struct bgp_path_info *pi;
2532 struct bgp_path_info *pi1;
2533 struct bgp_path_info *pi2;
2534 struct bgp_path_info *nextpi = NULL;
d62a17ae 2535 int paths_eq, do_mpath, debug;
2536 struct list mp_list;
2537 char pfx_buf[PREFIX2STR_BUFFER];
2538 char path_buf[PATH_ADDPATH_STR_BUFFER];
2539
2540 bgp_mp_list_init(&mp_list);
2541 do_mpath =
2542 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2543
9bcb3eef 2544 debug = bgp_debug_bestpath(dest);
d62a17ae 2545
2546 if (debug)
9bcb3eef 2547 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2548
9bcb3eef 2549 dest->reason = bgp_path_selection_none;
d62a17ae 2550 /* bgp deterministic-med */
2551 new_select = NULL;
892fedb6 2552 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2553
1defdda8 2554 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2555 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2556 pi1 = pi1->next)
9bcb3eef 2557 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2558 BGP_PATH_DMED_SELECTED);
d62a17ae 2559
9bcb3eef 2560 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2561 pi1 = pi1->next) {
40381db7 2562 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2563 continue;
40381db7 2564 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2565 continue;
ea8b2282 2566 if (pi1->peer != bgp->peer_self)
feb17238 2567 if (!peer_established(pi1->peer))
d62a17ae 2568 continue;
2569
40381db7
DS
2570 new_select = pi1;
2571 if (pi1->next) {
2572 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2573 if (CHECK_FLAG(pi2->flags,
1defdda8 2574 BGP_PATH_DMED_CHECK))
d62a17ae 2575 continue;
40381db7 2576 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2577 continue;
ea8b2282 2578 if (pi2->peer != bgp->peer_self
d62a17ae 2579 && !CHECK_FLAG(
ea8b2282
DS
2580 pi2->peer->sflags,
2581 PEER_STATUS_NSF_WAIT))
40381db7 2582 if (pi2->peer->status
d62a17ae 2583 != Established)
2584 continue;
2585
121e245d
DS
2586 if (!aspath_cmp_left(pi1->attr->aspath,
2587 pi2->attr->aspath)
2588 && !aspath_cmp_left_confed(
40381db7 2589 pi1->attr->aspath,
121e245d
DS
2590 pi2->attr->aspath))
2591 continue;
d62a17ae 2592
121e245d
DS
2593 if (bgp_path_info_cmp(
2594 bgp, pi2, new_select,
2595 &paths_eq, mpath_cfg, debug,
fdf81fa0 2596 pfx_buf, afi, safi,
9bcb3eef 2597 &dest->reason)) {
121e245d 2598 bgp_path_info_unset_flag(
9bcb3eef 2599 dest, new_select,
121e245d
DS
2600 BGP_PATH_DMED_SELECTED);
2601 new_select = pi2;
d62a17ae 2602 }
121e245d
DS
2603
2604 bgp_path_info_set_flag(
9bcb3eef 2605 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2606 }
2607 }
9bcb3eef 2608 bgp_path_info_set_flag(dest, new_select,
18ee8310 2609 BGP_PATH_DMED_CHECK);
9bcb3eef 2610 bgp_path_info_set_flag(dest, new_select,
18ee8310 2611 BGP_PATH_DMED_SELECTED);
d62a17ae 2612
2613 if (debug) {
18ee8310 2614 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2615 new_select, path_buf, sizeof(path_buf));
8228a9a7 2616 zlog_debug(
4378495a
DS
2617 "%pBD(%s): %s is the bestpath from AS %u",
2618 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2619 aspath_get_first_as(
2620 new_select->attr->aspath));
d62a17ae 2621 }
2622 }
2623 }
96450faf 2624
d62a17ae 2625 /* Check old selected route and new selected route. */
2626 old_select = NULL;
2627 new_select = NULL;
9bcb3eef 2628 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2629 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2630 enum bgp_path_selection_reason reason;
2631
40381db7
DS
2632 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2633 old_select = pi;
d62a17ae 2634
40381db7 2635 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2636 /* reap REMOVED routes, if needs be
2637 * selected route must stay for a while longer though
2638 */
40381db7
DS
2639 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2640 && (pi != old_select))
9bcb3eef 2641 bgp_path_info_reap(dest, pi);
d62a17ae 2642
ddb5b488 2643 if (debug)
40381db7
DS
2644 zlog_debug("%s: pi %p in holddown", __func__,
2645 pi);
ddb5b488 2646
d62a17ae 2647 continue;
2648 }
96450faf 2649
40381db7
DS
2650 if (pi->peer && pi->peer != bgp->peer_self
2651 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2652 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2653
2654 if (debug)
2655 zlog_debug(
40381db7
DS
2656 "%s: pi %p non self peer %s not estab state",
2657 __func__, pi, pi->peer->host);
ddb5b488 2658
d62a17ae 2659 continue;
ddb5b488 2660 }
9fbdd100 2661
892fedb6 2662 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2663 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2664 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2665 if (debug)
40381db7 2666 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2667 continue;
2668 }
9fbdd100 2669
9bcb3eef 2670 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2671
9bcb3eef 2672 reason = dest->reason;
40381db7 2673 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2674 debug, pfx_buf, afi, safi,
2675 &dest->reason)) {
19ea4cec
DS
2676 if (new_select == NULL &&
2677 reason != bgp_path_selection_none)
9bcb3eef 2678 dest->reason = reason;
40381db7 2679 new_select = pi;
d62a17ae 2680 }
2681 }
718e3744 2682
d62a17ae 2683 /* Now that we know which path is the bestpath see if any of the other
2684 * paths
2685 * qualify as multipaths
2686 */
2687 if (debug) {
2688 if (new_select)
7533cad7
QY
2689 bgp_path_info_path_with_addpath_rx_str(
2690 new_select, path_buf, sizeof(path_buf));
d62a17ae 2691 else
772270f3 2692 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2693 zlog_debug(
4378495a
DS
2694 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2695 dest, bgp->name_pretty, path_buf,
d62a17ae 2696 old_select ? old_select->peer->host : "NONE");
96450faf 2697 }
9fbdd100 2698
d62a17ae 2699 if (do_mpath && new_select) {
9bcb3eef 2700 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2701 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2702
2703 if (debug)
18ee8310 2704 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2705 pi, path_buf, sizeof(path_buf));
d62a17ae 2706
40381db7 2707 if (pi == new_select) {
d62a17ae 2708 if (debug)
2709 zlog_debug(
4378495a
DS
2710 "%pBD(%s): %s is the bestpath, add to the multipath list",
2711 dest, bgp->name_pretty,
2712 path_buf);
40381db7 2713 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2714 continue;
2715 }
2716
40381db7 2717 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2718 continue;
2719
40381db7
DS
2720 if (pi->peer && pi->peer != bgp->peer_self
2721 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2722 PEER_STATUS_NSF_WAIT))
feb17238 2723 if (!peer_established(pi->peer))
d62a17ae 2724 continue;
2725
40381db7 2726 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2727 if (debug)
2728 zlog_debug(
8228a9a7
DS
2729 "%pBD: %s has the same nexthop as the bestpath, skip it",
2730 dest, path_buf);
d62a17ae 2731 continue;
2732 }
2733
40381db7 2734 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2735 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2736 &dest->reason);
d62a17ae 2737
2738 if (paths_eq) {
2739 if (debug)
2740 zlog_debug(
8228a9a7
DS
2741 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2742 dest, path_buf);
40381db7 2743 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2744 }
2745 }
2746 }
fee0f4c6 2747
4378495a 2748 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2749 mpath_cfg);
2750 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2751 bgp_mp_list_clear(&mp_list);
96450faf 2752
9bcb3eef 2753 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2754
d62a17ae 2755 result->old = old_select;
2756 result->new = new_select;
96450faf 2757
d62a17ae 2758 return;
fee0f4c6 2759}
2760
3f9c7369
DS
2761/*
2762 * A new route/change in bestpath of an existing route. Evaluate the path
2763 * for advertisement to the subgroup.
2764 */
3dc339cd
DA
2765void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2766 struct bgp_path_info *selected,
9bcb3eef 2767 struct bgp_dest *dest,
3dc339cd 2768 uint32_t addpath_tx_id)
d62a17ae 2769{
b54892e0 2770 const struct prefix *p;
d62a17ae 2771 struct peer *onlypeer;
2772 struct attr attr;
2773 afi_t afi;
2774 safi_t safi;
a77e2f4b
S
2775 struct bgp *bgp;
2776 bool advertise;
adbac85e 2777
9bcb3eef 2778 p = bgp_dest_get_prefix(dest);
d62a17ae 2779 afi = SUBGRP_AFI(subgrp);
2780 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2781 bgp = SUBGRP_INST(subgrp);
d62a17ae 2782 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2783 : NULL);
2784
2dbe669b
DA
2785 if (BGP_DEBUG(update, UPDATE_OUT))
2786 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2787
d62a17ae 2788 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2789 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2790 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2791 return;
d62a17ae 2792
6006b807 2793 memset(&attr, 0, sizeof(attr));
d62a17ae 2794 /* It's initialized in bgp_announce_check() */
2795
a77e2f4b
S
2796 /* Announcement to the subgroup. If the route is filtered withdraw it.
2797 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2798 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2799 * route
d62a17ae 2800 */
a77e2f4b
S
2801 advertise = bgp_check_advertise(bgp, dest);
2802
d62a17ae 2803 if (selected) {
7f7940e6 2804 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2805 NULL)) {
a77e2f4b
S
2806 /* Route is selected, if the route is already installed
2807 * in FIB, then it is advertised
2808 */
be785e35
DS
2809 if (advertise) {
2810 if (!bgp_check_withdrawal(bgp, dest))
2811 bgp_adj_out_set_subgroup(
2812 dest, subgrp, &attr, selected);
2813 else
2814 bgp_adj_out_unset_subgroup(
2815 dest, subgrp, 1, addpath_tx_id);
2816 }
a77e2f4b 2817 } else
9bcb3eef 2818 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2819 addpath_tx_id);
d62a17ae 2820 }
2821
2822 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2823 else {
9bcb3eef 2824 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2825 }
200df115 2826}
fee0f4c6 2827
3064bf43 2828/*
e1072051 2829 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2830 * This is called at the end of route processing.
3064bf43 2831 */
9bcb3eef 2832void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2833{
40381db7 2834 struct bgp_path_info *pi;
3064bf43 2835
9bcb3eef 2836 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2837 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2838 continue;
40381db7
DS
2839 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2840 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2841 }
3064bf43 2842}
2843
2844/*
2845 * Has the route changed from the RIB's perspective? This is invoked only
2846 * if the route selection returns the same best route as earlier - to
2847 * determine if we need to update zebra or not.
2848 */
9bcb3eef 2849bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2850{
4b7e6066 2851 struct bgp_path_info *mpinfo;
d62a17ae 2852
2bb9eff4
DS
2853 /* If this is multipath, check all selected paths for any nexthop
2854 * change or attribute change. Some attribute changes (e.g., community)
2855 * aren't of relevance to the RIB, but we'll update zebra to ensure
2856 * we handle the case of BGP nexthop change. This is the behavior
2857 * when the best path has an attribute change anyway.
d62a17ae 2858 */
1defdda8 2859 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2860 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2861 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2862 return true;
d62a17ae 2863
2bb9eff4
DS
2864 /*
2865 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2866 */
18ee8310
DS
2867 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2868 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2869 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2870 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2871 return true;
d62a17ae 2872 }
3064bf43 2873
d62a17ae 2874 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2875 return false;
3064bf43 2876}
2877
d62a17ae 2878struct bgp_process_queue {
2879 struct bgp *bgp;
9bcb3eef 2880 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2881#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2882 unsigned int flags;
2883 unsigned int queued;
200df115 2884};
2885
3b0c17e1 2886static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2887 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2888 struct bgp_path_info *new_select,
2889 struct bgp_path_info *old_select)
2890{
9bcb3eef 2891 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2892
2893 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2894 return;
2895
2896 if (advertise_type5_routes(bgp, afi) && new_select
2897 && is_route_injectable_into_evpn(new_select)) {
2898
2899 /* apply the route-map */
2900 if (bgp->adv_cmd_rmap[afi][safi].map) {
2901 route_map_result_t ret;
2902 struct bgp_path_info rmap_path;
2903 struct bgp_path_info_extra rmap_path_extra;
2904 struct attr dummy_attr;
2905
2906 dummy_attr = *new_select->attr;
2907
2908 /* Fill temp path_info */
9bcb3eef 2909 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2910 new_select, new_select->peer,
2911 &dummy_attr);
2912
2913 RESET_FLAG(dummy_attr.rmap_change_flags);
2914
2915 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2916 p, &rmap_path);
3b0c17e1 2917
2918 if (ret == RMAP_DENYMATCH) {
2919 bgp_attr_flush(&dummy_attr);
2920 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2921 safi);
2922 } else
2923 bgp_evpn_advertise_type5_route(
2924 bgp, p, &dummy_attr, afi, safi);
2925 } else {
2926 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2927 afi, safi);
2928 }
2929 } else if (advertise_type5_routes(bgp, afi) && old_select
2930 && is_route_injectable_into_evpn(old_select))
2931 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2932}
2933
bb2ca692
MS
2934/*
2935 * Utility to determine whether a particular path_info should use
2936 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2937 * in a path where we basically _know_ this is a BGP-LU route.
2938 */
2939static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2940{
2941 /* Certain types get imp null; so do paths where the nexthop is
2942 * not labeled.
2943 */
2944 if (new_select->sub_type == BGP_ROUTE_STATIC
2945 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2946 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2947 return true;
2948 else if (new_select->extra == NULL ||
2949 !bgp_is_valid_label(&new_select->extra->label[0]))
2950 /* TODO -- should be configurable? */
2951 return true;
2952 else
2953 return false;
2954}
2955
3103e8d2
DS
2956/*
2957 * old_select = The old best path
2958 * new_select = the new best path
2959 *
2960 * if (!old_select && new_select)
2961 * We are sending new information on.
2962 *
2963 * if (old_select && new_select) {
2964 * if (new_select != old_select)
2965 * We have a new best path send a change
2966 * else
2967 * We've received a update with new attributes that needs
2968 * to be passed on.
2969 * }
2970 *
2971 * if (old_select && !new_select)
2972 * We have no eligible route that we can announce or the rn
2973 * is being removed.
2974 */
9bcb3eef 2975static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2976 afi_t afi, safi_t safi)
d62a17ae 2977{
4b7e6066
DS
2978 struct bgp_path_info *new_select;
2979 struct bgp_path_info *old_select;
2980 struct bgp_path_info_pair old_and_new;
ddb5b488 2981 int debug = 0;
d62a17ae 2982
892fedb6 2983 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2984 if (dest)
2985 debug = bgp_debug_bestpath(dest);
b54892e0 2986 if (debug)
f4c713ae 2987 zlog_debug(
56ca3b5b 2988 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2989 __func__, dest);
f4c713ae
LB
2990 return;
2991 }
d62a17ae 2992 /* Is it end of initial update? (after startup) */
9bcb3eef 2993 if (!dest) {
e36f61b5
DS
2994 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2995 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2996
2997 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2998 FOREACH_AFI_SAFI (afi, safi) {
2999 if (bgp_fibupd_safi(safi))
3000 bgp_zebra_announce_table(bgp, afi, safi);
3001 }
d62a17ae 3002 bgp->main_peers_update_hold = 0;
3003
3004 bgp_start_routeadv(bgp);
aac24838 3005 return;
d62a17ae 3006 }
cb1faec9 3007
9bcb3eef 3008 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 3009
9bcb3eef 3010 debug = bgp_debug_bestpath(dest);
b54892e0 3011 if (debug)
4378495a
DS
3012 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
3013 dest, bgp->name_pretty, afi2str(afi),
3014 safi2str(safi));
ddb5b488 3015
f009ff26 3016 /* The best path calculation for the route is deferred if
3017 * BGP_NODE_SELECT_DEFER is set
3018 */
9bcb3eef 3019 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3020 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 3021 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 3022 return;
3023 }
3024
d62a17ae 3025 /* Best path selection. */
9bcb3eef 3026 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3027 afi, safi);
3028 old_select = old_and_new.old;
3029 new_select = old_and_new.new;
3030
3031 /* Do we need to allocate or free labels?
3032 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3033 * necessary to do this upon changes to best path. Exceptions:
3034 * - label index has changed -> recalculate resulting label
3035 * - path_info sub_type changed -> switch to/from implicit-null
3036 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3037 */
318cac96 3038 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3039 if (new_select) {
3040 if (!old_select
3041 || bgp_label_index_differs(new_select, old_select)
57592a53 3042 || new_select->sub_type != old_select->sub_type
9bcb3eef 3043 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3044 /* Enforced penultimate hop popping:
3045 * implicit-null for local routes, aggregate
3046 * and redistributed routes
3047 */
bb2ca692 3048 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3049 if (CHECK_FLAG(
9bcb3eef 3050 dest->flags,
992dd67e
PR
3051 BGP_NODE_REGISTERED_FOR_LABEL)
3052 || CHECK_FLAG(
3053 dest->flags,
3054 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3055 bgp_unregister_for_label(dest);
67f67ba4
DA
3056 dest->local_label = mpls_lse_encode(
3057 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3058 1);
9bcb3eef 3059 bgp_set_valid_label(&dest->local_label);
d62a17ae 3060 } else
9bcb3eef
DS
3061 bgp_register_for_label(dest,
3062 new_select);
d62a17ae 3063 }
9bcb3eef 3064 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3065 BGP_NODE_REGISTERED_FOR_LABEL)
3066 || CHECK_FLAG(dest->flags,
3067 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3068 bgp_unregister_for_label(dest);
318cac96 3069 }
992dd67e
PR
3070 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3071 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3072 bgp_unregister_for_label(dest);
d62a17ae 3073 }
cd1964ff 3074
b54892e0 3075 if (debug)
ddb5b488 3076 zlog_debug(
4378495a
DS
3077 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3078 __func__, dest, bgp->name_pretty, afi2str(afi),
3079 safi2str(safi), old_select, new_select);
ddb5b488 3080
d62a17ae 3081 /* If best route remains the same and this is not due to user-initiated
3082 * clear, see exactly what needs to be done.
3083 */
d62a17ae 3084 if (old_select && old_select == new_select
9bcb3eef 3085 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3086 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3087 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3088 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3089#ifdef ENABLE_BGP_VNC
d62a17ae 3090 vnc_import_bgp_add_route(bgp, p, old_select);
3091 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3092#endif
bb744275 3093 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3094 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3095
be785e35
DS
3096 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3097 && new_select->sub_type == BGP_ROUTE_NORMAL)
3098 SET_FLAG(dest->flags,
3099 BGP_NODE_FIB_INSTALL_PENDING);
3100
ddb5b488
PZ
3101 if (new_select->type == ZEBRA_ROUTE_BGP
3102 && (new_select->sub_type == BGP_ROUTE_NORMAL
3103 || new_select->sub_type
3104 == BGP_ROUTE_IMPORTED))
3105
9bcb3eef 3106 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3107 bgp, afi, safi);
3108 }
d62a17ae 3109 }
d62a17ae 3110
3111 /* If there is a change of interest to peers, reannounce the
3112 * route. */
1defdda8 3113 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3114 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3115 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3116 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3117
3118 /* unicast routes must also be annouced to
3119 * labeled-unicast update-groups */
3120 if (safi == SAFI_UNICAST)
3121 group_announce_route(bgp, afi,
9bcb3eef 3122 SAFI_LABELED_UNICAST, dest,
d62a17ae 3123 new_select);
3124
1defdda8 3125 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3126 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3127 }
fee0f4c6 3128
3b0c17e1 3129 /* advertise/withdraw type-5 routes */
3130 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3131 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3132 bgp_process_evpn_route_injection(
9bcb3eef 3133 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3134
b1875e65 3135 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3136 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3137 bgp_zebra_clear_route_change_flags(dest);
3138 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3139 return;
d62a17ae 3140 }
8ad7271d 3141
d62a17ae 3142 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3143 */
9bcb3eef 3144 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3145
3146 /* bestpath has changed; bump version */
3147 if (old_select || new_select) {
9bcb3eef 3148 bgp_bump_version(dest);
d62a17ae 3149
3150 if (!bgp->t_rmap_def_originate_eval) {
3151 bgp_lock(bgp);
3152 thread_add_timer(
3153 bm->master,
3154 update_group_refresh_default_originate_route_map,
3155 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3156 &bgp->t_rmap_def_originate_eval);
3157 }
3158 }
3f9c7369 3159
d62a17ae 3160 if (old_select)
9bcb3eef 3161 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3162 if (new_select) {
ddb5b488
PZ
3163 if (debug)
3164 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3165 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3166 bgp_path_info_unset_flag(dest, new_select,
3167 BGP_PATH_ATTR_CHANGED);
1defdda8 3168 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3169 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3170 }
338b3424 3171
49e5a4a0 3172#ifdef ENABLE_BGP_VNC
d62a17ae 3173 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3174 if (old_select != new_select) {
3175 if (old_select) {
3176 vnc_import_bgp_exterior_del_route(bgp, p,
3177 old_select);
3178 vnc_import_bgp_del_route(bgp, p, old_select);
3179 }
3180 if (new_select) {
3181 vnc_import_bgp_exterior_add_route(bgp, p,
3182 new_select);
3183 vnc_import_bgp_add_route(bgp, p, new_select);
3184 }
3185 }
3186 }
65efcfce
LB
3187#endif
3188
9bcb3eef 3189 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3190
3191 /* unicast routes must also be annouced to labeled-unicast update-groups
3192 */
3193 if (safi == SAFI_UNICAST)
9bcb3eef 3194 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3195 new_select);
3196
3197 /* FIB update. */
3198 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3199 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3200
d62a17ae 3201 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3202 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3203 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3204 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3205
be785e35
DS
3206 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3207 SET_FLAG(dest->flags,
3208 BGP_NODE_FIB_INSTALL_PENDING);
3209
2b659f33
MK
3210 /* if this is an evpn imported type-5 prefix,
3211 * we need to withdraw the route first to clear
3212 * the nh neigh and the RMAC entry.
3213 */
3214 if (old_select &&
3215 is_route_parent_evpn(old_select))
3216 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3217
9bcb3eef 3218 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3219 } else {
d62a17ae 3220 /* Withdraw the route from the kernel. */
3221 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3222 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3223 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3224 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3225
568e10ca 3226 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3227 }
718e3744 3228 }
3064bf43 3229
9bcb3eef 3230 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3231 old_select);
5424b7ba 3232
d62a17ae 3233 /* Clear any route change flags. */
9bcb3eef 3234 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3235
18ee8310 3236 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3237 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3238 bgp_path_info_reap(dest, old_select);
d62a17ae 3239
9bcb3eef 3240 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3241 return;
718e3744 3242}
3243
f009ff26 3244/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3245void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3246{
9bcb3eef 3247 struct bgp_dest *dest;
f009ff26 3248 int cnt = 0;
3249 struct afi_safi_info *thread_info;
f009ff26 3250
56c226e7
DS
3251 if (bgp->gr_info[afi][safi].t_route_select) {
3252 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3253
3254 thread_info = THREAD_ARG(t);
3255 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3256 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3257 }
f009ff26 3258
3259 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3260 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3261 get_afi_safi_str(afi, safi, false),
26742171 3262 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3263 }
3264
3265 /* Process the route list */
6338d242 3266 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3267 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3268 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3269 dest = bgp_route_next(dest)) {
3270 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3271 continue;
3272
3273 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3274 bgp->gr_info[afi][safi].gr_deferred--;
3275 bgp_process_main_one(bgp, dest, afi, safi);
3276 cnt++;
067ea165
CB
3277 }
3278 /* If iteration stopped before the entire table was traversed then the
3279 * node needs to be unlocked.
3280 */
3281 if (dest) {
3282 bgp_dest_unlock_node(dest);
3283 dest = NULL;
f009ff26 3284 }
3285
9e3b51a7 3286 /* Send EOR message when all routes are processed */
6338d242 3287 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3288 bgp_send_delayed_eor(bgp);
8c48b3b6 3289 /* Send route processing complete message to RIB */
3290 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3291 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3292 return;
9e3b51a7 3293 }
f009ff26 3294
3295 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3296
3297 thread_info->afi = afi;
3298 thread_info->safi = safi;
3299 thread_info->bgp = bgp;
3300
3301 /* If there are more routes to be processed, start the
3302 * selection timer
3303 */
3304 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3305 BGP_ROUTE_SELECT_DELAY,
3306 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3307}
3308
aac24838 3309static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3310{
aac24838
JB
3311 struct bgp_process_queue *pqnode = data;
3312 struct bgp *bgp = pqnode->bgp;
d62a17ae 3313 struct bgp_table *table;
9bcb3eef 3314 struct bgp_dest *dest;
aac24838
JB
3315
3316 /* eoiu marker */
3317 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3318 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3319 /* should always have dedicated wq call */
3320 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3321 return WQ_SUCCESS;
3322 }
3323
ac021f40 3324 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3325 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3326 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3327 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3328 table = bgp_dest_table(dest);
3329 /* note, new DESTs may be added as part of processing */
3330 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3331
9bcb3eef 3332 bgp_dest_unlock_node(dest);
d62a17ae 3333 bgp_table_unlock(table);
3334 }
aac24838
JB
3335
3336 return WQ_SUCCESS;
3337}
3338
3339static void bgp_processq_del(struct work_queue *wq, void *data)
3340{
3341 struct bgp_process_queue *pqnode = data;
3342
3343 bgp_unlock(pqnode->bgp);
3344
3345 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3346}
3347
b6c386bb 3348void bgp_process_queue_init(struct bgp *bgp)
200df115 3349{
b6c386bb
DS
3350 if (!bgp->process_queue) {
3351 char name[BUFSIZ];
3352
3353 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3354 bgp->process_queue = work_queue_new(bm->master, name);
3355 }
3356
3357 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3358 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3359 bgp->process_queue->spec.max_retries = 0;
3360 bgp->process_queue->spec.hold = 50;
d62a17ae 3361 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3362 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3363}
3364
cfe8d15a 3365static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3366{
3367 struct bgp_process_queue *pqnode;
3368
a4d82a8a
PZ
3369 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3370 sizeof(struct bgp_process_queue));
aac24838
JB
3371
3372 /* unlocked in bgp_processq_del */
3373 pqnode->bgp = bgp_lock(bgp);
3374 STAILQ_INIT(&pqnode->pqueue);
3375
aac24838
JB
3376 return pqnode;
3377}
3378
9bcb3eef 3379void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3380{
aac24838 3381#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3382 struct work_queue *wq = bgp->process_queue;
d62a17ae 3383 struct bgp_process_queue *pqnode;
cfe8d15a 3384 int pqnode_reuse = 0;
495f0b13 3385
d62a17ae 3386 /* already scheduled for processing? */
9bcb3eef 3387 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3388 return;
2e02b9b2 3389
f009ff26 3390 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3391 * the workqueue
3392 */
9bcb3eef 3393 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3394 if (BGP_DEBUG(update, UPDATE_OUT))
3395 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3396 dest);
f009ff26 3397 return;
3398 }
3399
46aeabed
LS
3400 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3401 if (BGP_DEBUG(update, UPDATE_OUT))
3402 zlog_debug(
3403 "Soft reconfigure table in progress for route %p",
3404 dest);
3405 return;
3406 }
3407
aac24838 3408 if (wq == NULL)
d62a17ae 3409 return;
3410
aac24838 3411 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3412 limit only if is from the same BGP view and it's not an EOIU marker
3413 */
aac24838
JB
3414 if (work_queue_item_count(wq)) {
3415 struct work_queue_item *item = work_queue_last_item(wq);
3416 pqnode = item->data;
228da428 3417
a4d82a8a
PZ
3418 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3419 || pqnode->bgp != bgp
3420 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3421 pqnode = bgp_processq_alloc(bgp);
3422 else
3423 pqnode_reuse = 1;
aac24838 3424 } else
cfe8d15a 3425 pqnode = bgp_processq_alloc(bgp);
aac24838 3426 /* all unlocked in bgp_process_wq */
9bcb3eef 3427 bgp_table_lock(bgp_dest_table(dest));
aac24838 3428
9bcb3eef
DS
3429 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3430 bgp_dest_lock_node(dest);
aac24838 3431
60466a63 3432 /* can't be enqueued twice */
9bcb3eef
DS
3433 assert(STAILQ_NEXT(dest, pq) == NULL);
3434 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3435 pqnode->queued++;
3436
cfe8d15a
LB
3437 if (!pqnode_reuse)
3438 work_queue_add(wq, pqnode);
3439
d62a17ae 3440 return;
fee0f4c6 3441}
0a486e5f 3442
d62a17ae 3443void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3444{
d62a17ae 3445 struct bgp_process_queue *pqnode;
cb1faec9 3446
b6c386bb 3447 if (bgp->process_queue == NULL)
d62a17ae 3448 return;
2e02b9b2 3449
cfe8d15a 3450 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3451
aac24838 3452 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3453 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3454}
3455
cc9f21da 3456static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3457{
d62a17ae 3458 struct peer *peer;
0a486e5f 3459
d62a17ae 3460 peer = THREAD_ARG(thread);
3461 peer->t_pmax_restart = NULL;
0a486e5f 3462
d62a17ae 3463 if (bgp_debug_neighbor_events(peer))
3464 zlog_debug(
3465 "%s Maximum-prefix restart timer expired, restore peering",
3466 peer->host);
0a486e5f 3467
a9bafa95 3468 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3469 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3470}
3471
9cbd06e0
DA
3472static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3473 safi_t safi)
3474{
3475 uint32_t count = 0;
f41b0459 3476 bool filtered = false;
9cbd06e0
DA
3477 struct bgp_dest *dest;
3478 struct bgp_adj_in *ain;
40bb2ccf 3479 struct attr attr = {};
9cbd06e0
DA
3480 struct bgp_table *table = peer->bgp->rib[afi][safi];
3481
3482 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3483 for (ain = dest->adj_in; ain; ain = ain->next) {
3484 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3485
3486 attr = *ain->attr;
9cbd06e0
DA
3487
3488 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3489 == FILTER_DENY)
f41b0459
DA
3490 filtered = true;
3491
3492 if (bgp_input_modifier(
3493 peer, rn_p, &attr, afi, safi,
3494 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3495 NULL, 0, NULL)
3496 == RMAP_DENY)
3497 filtered = true;
3498
3499 if (filtered)
9cbd06e0 3500 count++;
f41b0459 3501
d498917e 3502 bgp_attr_flush(&attr);
9cbd06e0
DA
3503 }
3504 }
3505
3506 return count;
3507}
3508
3dc339cd
DA
3509bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3510 int always)
718e3744 3511{
d62a17ae 3512 iana_afi_t pkt_afi;
5c525538 3513 iana_safi_t pkt_safi;
9cbd06e0
DA
3514 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3515 PEER_FLAG_MAX_PREFIX_FORCE))
3516 ? bgp_filtered_routes_count(peer, afi, safi)
3517 + peer->pcount[afi][safi]
3518 : peer->pcount[afi][safi];
9cabb64b 3519
d62a17ae 3520 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3521 return false;
e0701b79 3522
9cbd06e0 3523 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3524 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3525 PEER_STATUS_PREFIX_LIMIT)
3526 && !always)
3dc339cd 3527 return false;
e0701b79 3528
d62a17ae 3529 zlog_info(
f70c91dc
DA
3530 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3531 get_afi_safi_str(afi, safi, false), peer, pcount,
3532 peer->pmax[afi][safi]);
d62a17ae 3533 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3534
3535 if (CHECK_FLAG(peer->af_flags[afi][safi],
3536 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3537 return false;
d62a17ae 3538
3539 /* Convert AFI, SAFI to values for packet. */
3540 pkt_afi = afi_int2iana(afi);
3541 pkt_safi = safi_int2iana(safi);
3542 {
d7c0a89a 3543 uint8_t ndata[7];
d62a17ae 3544
3545 ndata[0] = (pkt_afi >> 8);
3546 ndata[1] = pkt_afi;
3547 ndata[2] = pkt_safi;
3548 ndata[3] = (peer->pmax[afi][safi] >> 24);
3549 ndata[4] = (peer->pmax[afi][safi] >> 16);
3550 ndata[5] = (peer->pmax[afi][safi] >> 8);
3551 ndata[6] = (peer->pmax[afi][safi]);
3552
3553 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3554 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3555 BGP_NOTIFY_CEASE_MAX_PREFIX,
3556 ndata, 7);
3557 }
3558
3559 /* Dynamic peers will just close their connection. */
3560 if (peer_dynamic_neighbor(peer))
3dc339cd 3561 return true;
d62a17ae 3562
3563 /* restart timer start */
3564 if (peer->pmax_restart[afi][safi]) {
3565 peer->v_pmax_restart =
3566 peer->pmax_restart[afi][safi] * 60;
3567
3568 if (bgp_debug_neighbor_events(peer))
3569 zlog_debug(
f70c91dc
DA
3570 "%pBP Maximum-prefix restart timer started for %d secs",
3571 peer, peer->v_pmax_restart);
d62a17ae 3572
3573 BGP_TIMER_ON(peer->t_pmax_restart,
3574 bgp_maximum_prefix_restart_timer,
3575 peer->v_pmax_restart);
3576 }
3577
3dc339cd 3578 return true;
d62a17ae 3579 } else
3580 UNSET_FLAG(peer->af_sflags[afi][safi],
3581 PEER_STATUS_PREFIX_LIMIT);
3582
b1823b69
DS
3583 if (pcount
3584 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3585 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3586 PEER_STATUS_PREFIX_THRESHOLD)
3587 && !always)
3dc339cd 3588 return false;
d62a17ae 3589
3590 zlog_info(
f70c91dc
DA
3591 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3592 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3593 peer->pmax[afi][safi]);
d62a17ae 3594 SET_FLAG(peer->af_sflags[afi][safi],
3595 PEER_STATUS_PREFIX_THRESHOLD);
3596 } else
3597 UNSET_FLAG(peer->af_sflags[afi][safi],
3598 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3599 return false;
718e3744 3600}
3601
b40d939b 3602/* Unconditionally remove the route from the RIB, without taking
3603 * damping into consideration (eg, because the session went down)
3604 */
9bcb3eef 3605void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3606 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3607{
f009ff26 3608
3609 struct bgp *bgp = NULL;
3610 bool delete_route = false;
3611
9bcb3eef
DS
3612 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3613 safi);
d62a17ae 3614
f009ff26 3615 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3616 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3617
f009ff26 3618 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3619 * flag
3620 */
3621 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3622 delete_route = true;
9bcb3eef 3623 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3624 delete_route = true;
f009ff26 3625 if (delete_route) {
9bcb3eef
DS
3626 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3627 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3628 bgp = pi->peer->bgp;
26742171 3629 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3630 }
3631 }
3632 }
4a11bf2c 3633
9bcb3eef
DS
3634 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3635 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3636}
3637
9bcb3eef 3638static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3639 struct peer *peer, afi_t afi, safi_t safi,
3640 struct prefix_rd *prd)
3641{
9bcb3eef 3642 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3643
d62a17ae 3644 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3645 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3646 */
b4f7f45b
IR
3647 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3648 && peer->sort == BGP_PEER_EBGP)
3649 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3650 == BGP_DAMP_SUPPRESSED) {
3651 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3652 safi);
3653 return;
d62a17ae 3654 }
3655
49e5a4a0 3656#ifdef ENABLE_BGP_VNC
d62a17ae 3657 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3658 struct bgp_dest *pdest = NULL;
d62a17ae 3659 struct bgp_table *table = NULL;
3660
9bcb3eef
DS
3661 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3662 (struct prefix *)prd);
3663 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3664 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3665
3666 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3667 peer->bgp, prd, table, p, pi);
d62a17ae 3668 }
9bcb3eef 3669 bgp_dest_unlock_node(pdest);
d62a17ae 3670 }
3671 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3672 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3673
b54892e0
DS
3674 vnc_import_bgp_del_route(peer->bgp, p, pi);
3675 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3676 }
65efcfce 3677 }
d62a17ae 3678#endif
128ea8ab 3679
d62a17ae 3680 /* If this is an EVPN route, process for un-import. */
3681 if (safi == SAFI_EVPN)
b54892e0 3682 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3683
9bcb3eef 3684 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3685}
3686
4b7e6066
DS
3687struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3688 struct peer *peer, struct attr *attr,
9bcb3eef 3689 struct bgp_dest *dest)
fb018d25 3690{
4b7e6066 3691 struct bgp_path_info *new;
fb018d25 3692
d62a17ae 3693 /* Make new BGP info. */
4b7e6066 3694 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3695 new->type = type;
3696 new->instance = instance;
3697 new->sub_type = sub_type;
3698 new->peer = peer;
3699 new->attr = attr;
083ec940 3700 new->uptime = monotime(NULL);
9bcb3eef 3701 new->net = dest;
d62a17ae 3702 return new;
fb018d25
DS
3703}
3704
c265ee22 3705/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3706bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3707 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3708 struct bgp_dest *dest)
d62a17ae 3709{
2dbe3fa9 3710 bool ret = false;
b099a5c8
DA
3711 bool is_bgp_static_route =
3712 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3713 : false;
d62a17ae 3714
e8442016
DS
3715 /*
3716 * Only validated for unicast and multicast currently.
3717 * Also valid for EVPN where the nexthop is an IP address.
3718 * If we are a bgp static route being checked then there is
3719 * no need to check to see if the nexthop is martian as
3720 * that it should be ok.
3721 */
3722 if (is_bgp_static_route ||
3723 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3724 return false;
d62a17ae 3725
3726 /* If NEXT_HOP is present, validate it. */
3727 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3728 if (attr->nexthop.s_addr == INADDR_ANY ||
3729 !ipv4_unicast_valid(&attr->nexthop) ||
3730 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3731 return true;
d62a17ae 3732 }
c265ee22 3733
d62a17ae 3734 /* If MP_NEXTHOP is present, validate it. */
3735 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3736 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3737 * it is not an IPv6 link-local address.
0355b41d
DA
3738 *
3739 * If we receive an UPDATE with nexthop length set to 32 bytes
3740 * we shouldn't discard an UPDATE if it's set to (::).
3741 * The link-local (2st) is validated along the code path later.
d62a17ae 3742 */
3743 if (attr->mp_nexthop_len) {
3744 switch (attr->mp_nexthop_len) {
3745 case BGP_ATTR_NHLEN_IPV4:
3746 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3747 ret = (attr->mp_nexthop_global_in.s_addr ==
3748 INADDR_ANY ||
3749 !ipv4_unicast_valid(
3750 &attr->mp_nexthop_global_in) ||
3751 bgp_nexthop_self(bgp, afi, type, stype, attr,
3752 dest));
d62a17ae 3753 break;
3754
3755 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3756 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3757 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3758 &attr->mp_nexthop_global)
d62a17ae 3759 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3760 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3761 &attr->mp_nexthop_global)
3762 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3763 dest));
d62a17ae 3764 break;
0355b41d
DA
3765 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3766 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3767 || IN6_IS_ADDR_MULTICAST(
3768 &attr->mp_nexthop_global)
3769 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3770 dest));
0355b41d 3771 break;
d62a17ae 3772
3773 default:
3dc339cd 3774 ret = true;
d62a17ae 3775 break;
3776 }
3777 }
c265ee22 3778
d62a17ae 3779 return ret;
3780}
3781
aade37d7 3782static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3783{
3784 struct community *old;
3785 struct community *new;
3786 struct community *merge;
aade37d7 3787 struct community *no_export;
2721dd61 3788
9a706b42 3789 old = bgp_attr_get_community(attr);
aade37d7 3790 no_export = community_str2com("no-export");
2721dd61 3791
b4efa101
DA
3792 assert(no_export);
3793
2721dd61 3794 if (old) {
aade37d7 3795 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3796
3797 if (!old->refcnt)
3798 community_free(&old);
3799
3800 new = community_uniq_sort(merge);
3801 community_free(&merge);
3802 } else {
aade37d7 3803 new = community_dup(no_export);
2721dd61
DA
3804 }
3805
aade37d7 3806 community_free(&no_export);
2721dd61 3807
9a706b42 3808 bgp_attr_set_community(attr, new);
2721dd61
DA
3809}
3810
5a1ae2c2 3811int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3812 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3813 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3814 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3815 struct bgp_route_evpn *evpn)
d62a17ae 3816{
3817 int ret;
3818 int aspath_loop_count = 0;
9bcb3eef 3819 struct bgp_dest *dest;
d62a17ae 3820 struct bgp *bgp;
3821 struct attr new_attr;
3822 struct attr *attr_new;
40381db7 3823 struct bgp_path_info *pi;
4b7e6066
DS
3824 struct bgp_path_info *new;
3825 struct bgp_path_info_extra *extra;
d62a17ae 3826 const char *reason;
3827 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3828 int connected = 0;
3829 int do_loop_check = 1;
3830 int has_valid_label = 0;
7c312383 3831 afi_t nh_afi;
949b0f24 3832 uint8_t pi_type = 0;
3833 uint8_t pi_sub_type = 0;
9146341f 3834 bool force_evpn_import = false;
907707db 3835 safi_t orig_safi = safi;
a486300b 3836 bool leak_success = true;
949b0f24 3837
c7bb4f00 3838 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3839 char pfxprint[PREFIX2STR_BUFFER];
3840
3841 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3842 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3843 afi, safi, attr);
6401252f
QY
3844 }
3845
49e5a4a0 3846#ifdef ENABLE_BGP_VNC
d62a17ae 3847 int vnc_implicit_withdraw = 0;
65efcfce 3848#endif
d62a17ae 3849 int same_attr = 0;
718e3744 3850
907707db
MS
3851 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3852 if (orig_safi == SAFI_LABELED_UNICAST)
3853 safi = SAFI_UNICAST;
3854
6006b807 3855 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3856 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3857 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3858
d62a17ae 3859 bgp = peer->bgp;
9bcb3eef 3860 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3861 /* TODO: Check to see if we can get rid of "is_valid_label" */
3862 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3863 has_valid_label = (num_labels > 0) ? 1 : 0;
3864 else
3865 has_valid_label = bgp_is_valid_label(label);
718e3744 3866
28f66de2
MS
3867 if (has_valid_label)
3868 assert(label != NULL);
3869
66ff6089
AD
3870 /* Update overlay index of the attribute */
3871 if (afi == AFI_L2VPN && evpn)
3872 memcpy(&attr->evpn_overlay, evpn,
3873 sizeof(struct bgp_route_evpn));
3874
d62a17ae 3875 /* When peer's soft reconfiguration enabled. Record input packet in
3876 Adj-RIBs-In. */
3877 if (!soft_reconfig
3878 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3879 && peer != bgp->peer_self)
9bcb3eef 3880 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3881
3882 /* Check previously received route. */
9bcb3eef 3883 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3884 if (pi->peer == peer && pi->type == type
3885 && pi->sub_type == sub_type
3886 && pi->addpath_rx_id == addpath_id)
d62a17ae 3887 break;
3888
3889 /* AS path local-as loop check. */
3890 if (peer->change_local_as) {
c4368918
DW
3891 if (peer->allowas_in[afi][safi])
3892 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3893 else if (!CHECK_FLAG(peer->flags,
3894 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3895 aspath_loop_count = 1;
3896
3897 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3898 > aspath_loop_count) {
b4d46cc9 3899 peer->stat_pfx_aspath_loop++;
692174a1 3900 reason = "as-path contains our own AS;";
d62a17ae 3901 goto filtered;
3902 }
718e3744 3903 }
718e3744 3904
d62a17ae 3905 /* If the peer is configured for "allowas-in origin" and the last ASN in
3906 * the
3907 * as-path is our ASN then we do not need to call aspath_loop_check
3908 */
3909 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3910 if (aspath_get_last_as(attr->aspath) == bgp->as)
3911 do_loop_check = 0;
3912
3913 /* AS path loop check. */
3914 if (do_loop_check) {
3915 if (aspath_loop_check(attr->aspath, bgp->as)
3916 > peer->allowas_in[afi][safi]
3917 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3918 && aspath_loop_check(attr->aspath, bgp->confed_id)
3919 > peer->allowas_in[afi][safi])) {
b4d46cc9 3920 peer->stat_pfx_aspath_loop++;
d62a17ae 3921 reason = "as-path contains our own AS;";
3922 goto filtered;
3923 }
3924 }
aac9ef6c 3925
d62a17ae 3926 /* Route reflector originator ID check. */
3927 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3928 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3929 peer->stat_pfx_originator_loop++;
d62a17ae 3930 reason = "originator is us;";
3931 goto filtered;
3932 }
718e3744 3933
d62a17ae 3934 /* Route reflector cluster ID check. */
3935 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3936 peer->stat_pfx_cluster_loop++;
d62a17ae 3937 reason = "reflected from the same cluster;";
3938 goto filtered;
3939 }
718e3744 3940
d62a17ae 3941 /* Apply incoming filter. */
907707db 3942 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3943 peer->stat_pfx_filter++;
d62a17ae 3944 reason = "filter;";
3945 goto filtered;
3946 }
718e3744 3947
a8b72dc6
DA
3948 /* RFC 8212 to prevent route leaks.
3949 * This specification intends to improve this situation by requiring the
3950 * explicit configuration of both BGP Import and Export Policies for any
3951 * External BGP (EBGP) session such as customers, peers, or
3952 * confederation boundaries for all enabled address families. Through
3953 * codification of the aforementioned requirement, operators will
3954 * benefit from consistent behavior across different BGP
3955 * implementations.
3956 */
1d3fdccf 3957 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3958 if (!bgp_inbound_policy_exists(peer,
3959 &peer->filter[afi][safi])) {
3960 reason = "inbound policy missing";
b17826b7
DS
3961 if (monotime_since(&bgp->ebgprequirespolicywarning,
3962 NULL) > FIFTEENMINUTE2USEC ||
3963 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3964 zlog_warn(
3965 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3966 monotime(&bgp->ebgprequirespolicywarning);
3967 }
a8b72dc6
DA
3968 goto filtered;
3969 }
3970
fb29348a
DA
3971 /* draft-ietf-idr-deprecate-as-set-confed-set
3972 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3973 * Eventually, This document (if approved) updates RFC 4271
3974 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3975 * and obsoletes RFC 6472.
3976 */
7f972cd8 3977 if (peer->bgp->reject_as_sets)
fb29348a
DA
3978 if (aspath_check_as_sets(attr->aspath)) {
3979 reason =
3980 "as-path contains AS_SET or AS_CONFED_SET type;";
3981 goto filtered;
3982 }
3983
6f4f49b2 3984 new_attr = *attr;
d62a17ae 3985
3986 /* Apply incoming route-map.
3987 * NB: new_attr may now contain newly allocated values from route-map
3988 * "set"
3989 * commands, so we need bgp_attr_flush in the error paths, until we
3990 * intern
3991 * the attr (which takes over the memory references) */
907707db 3992 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3993 num_labels, dest)
3994 == RMAP_DENY) {
b4d46cc9 3995 peer->stat_pfx_filter++;
d62a17ae 3996 reason = "route-map;";
3997 bgp_attr_flush(&new_attr);
3998 goto filtered;
3999 }
718e3744 4000
05864da7 4001 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
4002 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
4003 /* remove from RIB previous entry */
4004 bgp_zebra_withdraw(p, pi, bgp, safi);
4005 }
4006
7f323236
DW
4007 if (peer->sort == BGP_PEER_EBGP) {
4008
2721dd61
DA
4009 /* rfc7999:
4010 * A BGP speaker receiving an announcement tagged with the
4011 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
4012 * NO_EXPORT community as defined in RFC1997, or a
4013 * similar community, to prevent propagation of the
4014 * prefix outside the local AS. The community to prevent
4015 * propagation SHOULD be chosen according to the operator's
4016 * routing policy.
4017 */
9a706b42
DA
4018 if (bgp_attr_get_community(&new_attr) &&
4019 community_include(bgp_attr_get_community(&new_attr),
4020 COMMUNITY_BLACKHOLE))
aade37d7 4021 bgp_attr_add_no_export_community(&new_attr);
2721dd61 4022
a4d82a8a
PZ
4023 /* If we receive the graceful-shutdown community from an eBGP
4024 * peer we must lower local-preference */
9a706b42
DA
4025 if (bgp_attr_get_community(&new_attr) &&
4026 community_include(bgp_attr_get_community(&new_attr),
4027 COMMUNITY_GSHUT)) {
7f323236
DW
4028 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4029 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4030
a4d82a8a
PZ
4031 /* If graceful-shutdown is configured then add the GSHUT
4032 * community to all paths received from eBGP peers */
637e5ba4 4033 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4034 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4035 }
4036
949b0f24 4037 if (pi) {
4038 pi_type = pi->type;
4039 pi_sub_type = pi->sub_type;
4040 }
4041
d62a17ae 4042 /* next hop check. */
a4d82a8a 4043 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
4044 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
4045 &new_attr, dest)) {
b4d46cc9 4046 peer->stat_pfx_nh_invalid++;
d62a17ae 4047 reason = "martian or self next-hop;";
4048 bgp_attr_flush(&new_attr);
4049 goto filtered;
4050 }
718e3744 4051
5c14a191 4052 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4053 peer->stat_pfx_nh_invalid++;
4e802e66 4054 reason = "self mac;";
4dbf2038 4055 bgp_attr_flush(&new_attr);
4e802e66
DS
4056 goto filtered;
4057 }
4058
5a78f2bc
EB
4059 if (bgp_check_role_applicability(afi, safi) &&
4060 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4061 reason = "failing otc validation";
4062 bgp_attr_flush(&new_attr);
4063 goto filtered;
4064 }
a1b773e2
DS
4065 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4066 * condition :
4067 * Suppress fib is enabled
4068 * BGP_OPT_NO_FIB is not enabled
4069 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4070 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4071 */
4072 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4073 && (sub_type == BGP_ROUTE_NORMAL)
4074 && (!bgp_option_check(BGP_OPT_NO_FIB))
4075 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4076 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4077
9cbd06e0
DA
4078 /* If maximum prefix count is configured and current prefix
4079 * count exeed it.
4080 */
4dbf2038
IR
4081 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4082 bgp_attr_flush(&new_attr);
9cbd06e0 4083 return -1;
4dbf2038
IR
4084 }
4085
01da2d26
DA
4086 /* If neighbor soo is configured, tag all incoming routes with
4087 * this SoO tag and then filter out advertisements in
4088 * subgroup_announce_check() if it matches the configured SoO
4089 * on the other peer.
4090 */
4091 if (peer->soo[afi][safi]) {
4092 struct ecommunity *old_ecomm =
4093 bgp_attr_get_ecommunity(&new_attr);
4094 struct ecommunity *ecomm_soo = peer->soo[afi][safi];
4095 struct ecommunity *new_ecomm;
4096
4097 if (old_ecomm) {
4098 new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
4099 ecomm_soo);
4100
4101 if (!old_ecomm->refcnt)
4102 ecommunity_free(&old_ecomm);
4103 } else {
4104 new_ecomm = ecommunity_dup(ecomm_soo);
4105 }
4106
4107 bgp_attr_set_ecommunity(&new_attr, new_ecomm);
4108 }
4109
4dbf2038 4110 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4111
d62a17ae 4112 /* If the update is implicit withdraw. */
40381db7 4113 if (pi) {
083ec940 4114 pi->uptime = monotime(NULL);
40381db7 4115 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4116
9bcb3eef 4117 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4118
d62a17ae 4119 /* Same attribute comes in. */
40381db7 4120 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4121 && same_attr
d62a17ae 4122 && (!has_valid_label
40381db7 4123 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4124 num_labels * sizeof(mpls_label_t))
66ff6089 4125 == 0)) {
b4f7f45b
IR
4126 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4127 BGP_CONFIG_DAMPENING)
d62a17ae 4128 && peer->sort == BGP_PEER_EBGP
40381db7 4129 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4130 if (bgp_debug_update(peer, p, NULL, 1)) {
4131 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4132 afi, safi, prd, p, label,
4133 num_labels, addpath_id ? 1 : 0,
66ff6089 4134 addpath_id, evpn, pfx_buf,
a4d82a8a 4135 sizeof(pfx_buf));
f70c91dc 4136 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4137 pfx_buf);
4138 }
4139
9bcb3eef 4140 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4141 != BGP_DAMP_SUPPRESSED) {
40381db7 4142 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4143 safi);
9bcb3eef 4144 bgp_process(bgp, dest, afi, safi);
d62a17ae 4145 }
4146 } else /* Duplicate - odd */
4147 {
4148 if (bgp_debug_update(peer, p, NULL, 1)) {
4149 if (!peer->rcvd_attr_printed) {
4150 zlog_debug(
f70c91dc
DA
4151 "%pBP rcvd UPDATE w/ attr: %s",
4152 peer,
d62a17ae 4153 peer->rcvd_attr_str);
4154 peer->rcvd_attr_printed = 1;
4155 }
4156
4157 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4158 afi, safi, prd, p, label,
4159 num_labels, addpath_id ? 1 : 0,
66ff6089 4160 addpath_id, evpn, pfx_buf,
a4d82a8a 4161 sizeof(pfx_buf));
d62a17ae 4162 zlog_debug(
f70c91dc
DA
4163 "%pBP rcvd %s...duplicate ignored",
4164 peer, pfx_buf);
d62a17ae 4165 }
4166
4167 /* graceful restart STALE flag unset. */
40381db7 4168 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4169 bgp_path_info_unset_flag(
9bcb3eef
DS
4170 dest, pi, BGP_PATH_STALE);
4171 bgp_dest_set_defer_flag(dest, false);
4172 bgp_process(bgp, dest, afi, safi);
d62a17ae 4173 }
4174 }
4175
9bcb3eef 4176 bgp_dest_unlock_node(dest);
d62a17ae 4177 bgp_attr_unintern(&attr_new);
4178
4179 return 0;
4180 }
718e3744 4181
d62a17ae 4182 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4183 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4184 if (bgp_debug_update(peer, p, NULL, 1)) {
4185 bgp_debug_rdpfxpath2str(
a4d82a8a 4186 afi, safi, prd, p, label, num_labels,
66ff6089 4187 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4188 pfx_buf, sizeof(pfx_buf));
d62a17ae 4189 zlog_debug(
f70c91dc
DA
4190 "%pBP rcvd %s, flapped quicker than processing",
4191 peer, pfx_buf);
d62a17ae 4192 }
4193
9bcb3eef 4194 bgp_path_info_restore(dest, pi);
9146341f 4195
4196 /*
4197 * If the BGP_PATH_REMOVED flag is set, then EVPN
4198 * routes would have been unimported already when a
4199 * prior BGP withdraw processing happened. Such routes
4200 * need to be imported again, so flag accordingly.
4201 */
4202 force_evpn_import = true;
d62a17ae 4203 }
718e3744 4204
d62a17ae 4205 /* Received Logging. */
4206 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4207 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4208 num_labels, addpath_id ? 1 : 0,
66ff6089 4209 addpath_id, evpn, pfx_buf,
a4d82a8a 4210 sizeof(pfx_buf));
f70c91dc 4211 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4212 }
718e3744 4213
d62a17ae 4214 /* graceful restart STALE flag unset. */
f009ff26 4215 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4216 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4217 bgp_dest_set_defer_flag(dest, false);
f009ff26 4218 }
d62a17ae 4219
4220 /* The attribute is changed. */
9bcb3eef 4221 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4222
4223 /* implicit withdraw, decrement aggregate and pcount here.
4224 * only if update is accepted, they'll increment below.
4225 */
40381db7 4226 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4227
4228 /* Update bgp route dampening information. */
b4f7f45b 4229 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4230 && peer->sort == BGP_PEER_EBGP) {
4231 /* This is implicit withdraw so we should update
b4f7f45b
IR
4232 dampening
4233 information. */
40381db7 4234 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4235 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4236 }
49e5a4a0 4237#ifdef ENABLE_BGP_VNC
d62a17ae 4238 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4239 struct bgp_dest *pdest = NULL;
d62a17ae 4240 struct bgp_table *table = NULL;
4241
9bcb3eef
DS
4242 pdest = bgp_node_get(bgp->rib[afi][safi],
4243 (struct prefix *)prd);
4244 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4245 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4246
4247 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4248 bgp, prd, table, p, pi);
d62a17ae 4249 }
9bcb3eef 4250 bgp_dest_unlock_node(pdest);
d62a17ae 4251 }
4252 if ((afi == AFI_IP || afi == AFI_IP6)
4253 && (safi == SAFI_UNICAST)) {
40381db7 4254 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4255 /*
4256 * Implicit withdraw case.
4257 */
4258 ++vnc_implicit_withdraw;
40381db7
DS
4259 vnc_import_bgp_del_route(bgp, p, pi);
4260 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4261 }
4262 }
65efcfce 4263#endif
128ea8ab 4264
d62a17ae 4265 /* Special handling for EVPN update of an existing route. If the
4266 * extended community attribute has changed, we need to
4267 * un-import
4268 * the route using its existing extended community. It will be
4269 * subsequently processed for import with the new extended
4270 * community.
4271 */
6f8c9c11
PR
4272 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4273 && !same_attr) {
40381db7 4274 if ((pi->attr->flag
d62a17ae 4275 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4276 && (attr_new->flag
4277 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4278 int cmp;
4279
b53e67a3
DA
4280 cmp = ecommunity_cmp(
4281 bgp_attr_get_ecommunity(pi->attr),
4282 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4283 if (!cmp) {
4284 if (bgp_debug_update(peer, p, NULL, 1))
4285 zlog_debug(
4286 "Change in EXT-COMM, existing %s new %s",
4287 ecommunity_str(
b53e67a3
DA
4288 bgp_attr_get_ecommunity(
4289 pi->attr)),
d62a17ae 4290 ecommunity_str(
b53e67a3
DA
4291 bgp_attr_get_ecommunity(
4292 attr_new)));
6f8c9c11
PR
4293 if (safi == SAFI_EVPN)
4294 bgp_evpn_unimport_route(
4295 bgp, afi, safi, p, pi);
4296 else /* SAFI_MPLS_VPN */
4297 vpn_leak_to_vrf_withdraw(bgp,
4298 pi);
d62a17ae 4299 }
4300 }
4301 }
718e3744 4302
d62a17ae 4303 /* Update to new attribute. */
40381db7
DS
4304 bgp_attr_unintern(&pi->attr);
4305 pi->attr = attr_new;
d62a17ae 4306
4307 /* Update MPLS label */
4308 if (has_valid_label) {
40381db7 4309 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4310 if (extra->label != label) {
4311 memcpy(&extra->label, label,
dbd587da 4312 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4313 extra->num_labels = num_labels;
4314 }
b57ba6d2
MK
4315 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4316 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4317 }
718e3744 4318
e496b420
HS
4319 /* Update SRv6 SID */
4320 if (attr->srv6_l3vpn) {
4321 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4322 if (sid_diff(&extra->sid[0].sid,
4323 &attr->srv6_l3vpn->sid)) {
4324 sid_copy(&extra->sid[0].sid,
e496b420
HS
4325 &attr->srv6_l3vpn->sid);
4326 extra->num_sids = 1;
cc8f05df 4327
16f3db2d
RS
4328 extra->sid[0].loc_block_len = 0;
4329 extra->sid[0].loc_node_len = 0;
4330 extra->sid[0].func_len = 0;
4331 extra->sid[0].arg_len = 0;
ea7cd161
RS
4332 extra->sid[0].transposition_len = 0;
4333 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4334
4335 if (attr->srv6_l3vpn->loc_block_len != 0) {
4336 extra->sid[0].loc_block_len =
4337 attr->srv6_l3vpn->loc_block_len;
4338 extra->sid[0].loc_node_len =
4339 attr->srv6_l3vpn->loc_node_len;
4340 extra->sid[0].func_len =
4341 attr->srv6_l3vpn->func_len;
4342 extra->sid[0].arg_len =
4343 attr->srv6_l3vpn->arg_len;
ea7cd161 4344 extra->sid[0].transposition_len =
cc8f05df 4345 attr->srv6_l3vpn
ea7cd161
RS
4346 ->transposition_len;
4347 extra->sid[0].transposition_offset =
cc8f05df 4348 attr->srv6_l3vpn
ea7cd161
RS
4349 ->transposition_offset;
4350 }
e496b420
HS
4351 }
4352 } else if (attr->srv6_vpn) {
4353 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4354 if (sid_diff(&extra->sid[0].sid,
4355 &attr->srv6_vpn->sid)) {
4356 sid_copy(&extra->sid[0].sid,
4357 &attr->srv6_vpn->sid);
e496b420
HS
4358 extra->num_sids = 1;
4359 }
4360 }
4361
49e5a4a0 4362#ifdef ENABLE_BGP_VNC
d62a17ae 4363 if ((afi == AFI_IP || afi == AFI_IP6)
4364 && (safi == SAFI_UNICAST)) {
4365 if (vnc_implicit_withdraw) {
4366 /*
4367 * Add back the route with its new attributes
4368 * (e.g., nexthop).
4369 * The route is still selected, until the route
4370 * selection
4371 * queued by bgp_process actually runs. We have
4372 * to make this
4373 * update to the VNC side immediately to avoid
4374 * racing against
4375 * configuration changes (e.g., route-map
4376 * changes) which
4377 * trigger re-importation of the entire RIB.
4378 */
40381db7
DS
4379 vnc_import_bgp_add_route(bgp, p, pi);
4380 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4381 }
4382 }
65efcfce
LB
4383#endif
4384
d62a17ae 4385 /* Update bgp route dampening information. */
b4f7f45b 4386 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4387 && peer->sort == BGP_PEER_EBGP) {
4388 /* Now we do normal update dampening. */
9bcb3eef 4389 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4390 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4391 bgp_dest_unlock_node(dest);
d62a17ae 4392 return 0;
4393 }
4394 }
128ea8ab 4395
d62a17ae 4396 /* Nexthop reachability check - for unicast and
4397 * labeled-unicast.. */
7c312383
AD
4398 if (((afi == AFI_IP || afi == AFI_IP6)
4399 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4400 || (safi == SAFI_EVPN &&
4401 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4402 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4403 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4404 && !CHECK_FLAG(peer->flags,
4405 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4406 && !CHECK_FLAG(bgp->flags,
4407 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4408 connected = 1;
4409 else
4410 connected = 0;
4411
960035b2
PZ
4412 struct bgp *bgp_nexthop = bgp;
4413
40381db7
DS
4414 if (pi->extra && pi->extra->bgp_orig)
4415 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4416
7c312383
AD
4417 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4418
4419 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4420 safi, pi, NULL, connected,
4421 p)
a4d82a8a 4422 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4423 bgp_path_info_set_flag(dest, pi,
4424 BGP_PATH_VALID);
d62a17ae 4425 else {
4426 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4427 zlog_debug("%s(%pI4): NH unresolved",
4428 __func__,
4429 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4430 }
9bcb3eef 4431 bgp_path_info_unset_flag(dest, pi,
18ee8310 4432 BGP_PATH_VALID);
d62a17ae 4433 }
4434 } else
9bcb3eef 4435 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4436
49e5a4a0 4437#ifdef ENABLE_BGP_VNC
d62a17ae 4438 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4439 struct bgp_dest *pdest = NULL;
d62a17ae 4440 struct bgp_table *table = NULL;
4441
9bcb3eef
DS
4442 pdest = bgp_node_get(bgp->rib[afi][safi],
4443 (struct prefix *)prd);
4444 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4445 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4446
4447 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4448 bgp, prd, table, p, pi);
d62a17ae 4449 }
9bcb3eef 4450 bgp_dest_unlock_node(pdest);
d62a17ae 4451 }
4452#endif
718e3744 4453
d62a17ae 4454 /* If this is an EVPN route and some attribute has changed,
9146341f 4455 * or we are explicitly told to perform a route import, process
d62a17ae 4456 * route for import. If the extended community has changed, we
4457 * would
4458 * have done the un-import earlier and the import would result
4459 * in the
4460 * route getting injected into appropriate L2 VNIs. If it is
4461 * just
4462 * some other attribute change, the import will result in
4463 * updating
4464 * the attributes for the route in the VNI(s).
4465 */
9146341f 4466 if (safi == SAFI_EVPN &&
4467 (!same_attr || force_evpn_import) &&
7c312383 4468 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4469 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4470
4471 /* Process change. */
40381db7 4472 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4473
9bcb3eef
DS
4474 bgp_process(bgp, dest, afi, safi);
4475 bgp_dest_unlock_node(dest);
558d1fec 4476
ddb5b488
PZ
4477 if (SAFI_UNICAST == safi
4478 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4479 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4480
40381db7 4481 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4482 }
4483 if ((SAFI_MPLS_VPN == safi)
4484 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4485
a486300b 4486 leak_success = vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4487 }
4488
49e5a4a0 4489#ifdef ENABLE_BGP_VNC
d62a17ae 4490 if (SAFI_MPLS_VPN == safi) {
4491 mpls_label_t label_decoded = decode_label(label);
28070ee3 4492
d62a17ae 4493 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4494 type, sub_type, &label_decoded);
4495 }
4496 if (SAFI_ENCAP == safi) {
4497 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4498 type, sub_type, NULL);
4499 }
28070ee3 4500#endif
a486300b
PG
4501 if ((safi == SAFI_MPLS_VPN) &&
4502 !CHECK_FLAG(bgp->af_flags[afi][safi],
4503 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4504 !leak_success) {
4505 bgp_unlink_nexthop(pi);
4506 bgp_path_info_delete(dest, pi);
4507 }
d62a17ae 4508 return 0;
4509 } // End of implicit withdraw
718e3744 4510
d62a17ae 4511 /* Received Logging. */
4512 if (bgp_debug_update(peer, p, NULL, 1)) {
4513 if (!peer->rcvd_attr_printed) {
f70c91dc 4514 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4515 peer->rcvd_attr_str);
4516 peer->rcvd_attr_printed = 1;
4517 }
718e3744 4518
a4d82a8a 4519 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4520 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4521 pfx_buf, sizeof(pfx_buf));
f70c91dc 4522 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4523 }
718e3744 4524
d62a17ae 4525 /* Make new BGP info. */
9bcb3eef 4526 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4527
d62a17ae 4528 /* Update MPLS label */
4529 if (has_valid_label) {
18ee8310 4530 extra = bgp_path_info_extra_get(new);
8ba71050 4531 if (extra->label != label) {
dbd587da
QY
4532 memcpy(&extra->label, label,
4533 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4534 extra->num_labels = num_labels;
4535 }
b57ba6d2
MK
4536 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4537 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4538 }
718e3744 4539
e496b420
HS
4540 /* Update SRv6 SID */
4541 if (safi == SAFI_MPLS_VPN) {
4542 extra = bgp_path_info_extra_get(new);
4543 if (attr->srv6_l3vpn) {
16f3db2d 4544 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4545 extra->num_sids = 1;
cc8f05df 4546
16f3db2d
RS
4547 extra->sid[0].loc_block_len =
4548 attr->srv6_l3vpn->loc_block_len;
4549 extra->sid[0].loc_node_len =
4550 attr->srv6_l3vpn->loc_node_len;
4551 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4552 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4553 extra->sid[0].transposition_len =
4554 attr->srv6_l3vpn->transposition_len;
4555 extra->sid[0].transposition_offset =
4556 attr->srv6_l3vpn->transposition_offset;
e496b420 4557 } else if (attr->srv6_vpn) {
16f3db2d 4558 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4559 extra->num_sids = 1;
4560 }
4561 }
4562
d62a17ae 4563 /* Nexthop reachability check. */
7c312383
AD
4564 if (((afi == AFI_IP || afi == AFI_IP6)
4565 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4566 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4567 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4568 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4569 && !CHECK_FLAG(peer->flags,
4570 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4571 && !CHECK_FLAG(bgp->flags,
4572 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4573 connected = 1;
4574 else
4575 connected = 0;
4576
7c312383
AD
4577 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4578
4053e952 4579 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4580 connected, p)
a4d82a8a 4581 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4582 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4583 else {
4584 if (BGP_DEBUG(nht, NHT)) {
4585 char buf1[INET6_ADDRSTRLEN];
4586 inet_ntop(AF_INET,
4587 (const void *)&attr_new->nexthop,
4588 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4589 zlog_debug("%s(%s): NH unresolved", __func__,
4590 buf1);
d62a17ae 4591 }
9bcb3eef 4592 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4593 }
4594 } else
9bcb3eef 4595 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4596
d62a17ae 4597 /* Addpath ID */
4598 new->addpath_rx_id = addpath_id;
4599
4600 /* Increment prefix */
4601 bgp_aggregate_increment(bgp, p, new, afi, safi);
4602
4603 /* Register new BGP information. */
9bcb3eef 4604 bgp_path_info_add(dest, new);
d62a17ae 4605
4606 /* route_node_get lock */
9bcb3eef 4607 bgp_dest_unlock_node(dest);
558d1fec 4608
49e5a4a0 4609#ifdef ENABLE_BGP_VNC
d62a17ae 4610 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4611 struct bgp_dest *pdest = NULL;
d62a17ae 4612 struct bgp_table *table = NULL;
4613
9bcb3eef
DS
4614 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4615 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4616 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4617
4618 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4619 bgp, prd, table, p, new);
4620 }
9bcb3eef 4621 bgp_dest_unlock_node(pdest);
d62a17ae 4622 }
65efcfce
LB
4623#endif
4624
d62a17ae 4625 /* If this is an EVPN route, process for import. */
7c312383 4626 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4627 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4628
9bcb3eef 4629 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4630
d62a17ae 4631 /* Process change. */
9bcb3eef 4632 bgp_process(bgp, dest, afi, safi);
718e3744 4633
ddb5b488
PZ
4634 if (SAFI_UNICAST == safi
4635 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4636 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4637 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4638 }
4639 if ((SAFI_MPLS_VPN == safi)
4640 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
a486300b 4641 leak_success = vpn_leak_to_vrf_update(bgp, new);
ddb5b488 4642 }
49e5a4a0 4643#ifdef ENABLE_BGP_VNC
d62a17ae 4644 if (SAFI_MPLS_VPN == safi) {
4645 mpls_label_t label_decoded = decode_label(label);
28070ee3 4646
d62a17ae 4647 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4648 sub_type, &label_decoded);
4649 }
4650 if (SAFI_ENCAP == safi) {
4651 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4652 sub_type, NULL);
4653 }
28070ee3 4654#endif
a486300b
PG
4655 if ((safi == SAFI_MPLS_VPN) &&
4656 !CHECK_FLAG(bgp->af_flags[afi][safi],
4657 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4658 !leak_success) {
4659 bgp_unlink_nexthop(new);
4660 bgp_path_info_delete(dest, new);
4661 }
28070ee3 4662
d62a17ae 4663 return 0;
718e3744 4664
d62a17ae 4665/* This BGP update is filtered. Log the reason then update BGP
4666 entry. */
4667filtered:
9bcb3eef 4668 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4669
d62a17ae 4670 if (bgp_debug_update(peer, p, NULL, 1)) {
4671 if (!peer->rcvd_attr_printed) {
f70c91dc 4672 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4673 peer->rcvd_attr_str);
4674 peer->rcvd_attr_printed = 1;
4675 }
718e3744 4676
a4d82a8a 4677 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4678 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4679 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4680 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4681 peer, pfx_buf, reason);
d62a17ae 4682 }
128ea8ab 4683
40381db7 4684 if (pi) {
d62a17ae 4685 /* If this is an EVPN route, un-import it as it is now filtered.
4686 */
4687 if (safi == SAFI_EVPN)
40381db7 4688 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4689
ddb5b488
PZ
4690 if (SAFI_UNICAST == safi
4691 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4692 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4693
40381db7 4694 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4695 }
4696 if ((SAFI_MPLS_VPN == safi)
4697 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4698
40381db7 4699 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4700 }
4701
9bcb3eef 4702 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4703 }
4704
9bcb3eef 4705 bgp_dest_unlock_node(dest);
558d1fec 4706
49e5a4a0 4707#ifdef ENABLE_BGP_VNC
d62a17ae 4708 /*
4709 * Filtered update is treated as an implicit withdrawal (see
4710 * bgp_rib_remove()
4711 * a few lines above)
4712 */
4713 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4714 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4715 0);
4716 }
97736e32
PZ
4717#endif
4718
d62a17ae 4719 return 0;
718e3744 4720}
4721
26a3ffd6 4722int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4723 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4724 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4725 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4726{
d62a17ae 4727 struct bgp *bgp;
4728 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4729 struct bgp_dest *dest;
40381db7 4730 struct bgp_path_info *pi;
718e3744 4731
49e5a4a0 4732#ifdef ENABLE_BGP_VNC
d62a17ae 4733 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4734 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4735 0);
4736 }
28070ee3
PZ
4737#endif
4738
d62a17ae 4739 bgp = peer->bgp;
4740
4741 /* Lookup node. */
9bcb3eef 4742 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4743
4744 /* If peer is soft reconfiguration enabled. Record input packet for
4745 * further calculation.
4746 *
4747 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4748 * routes that are filtered. This tanks out Quagga RS pretty badly due
4749 * to
4750 * the iteration over all RS clients.
4751 * Since we need to remove the entry from adj_in anyway, do that first
4752 * and
4753 * if there was no entry, we don't need to do anything more.
4754 */
4755 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4756 && peer != bgp->peer_self)
9bcb3eef 4757 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4758 peer->stat_pfx_dup_withdraw++;
4759
d62a17ae 4760 if (bgp_debug_update(peer, p, NULL, 1)) {
4761 bgp_debug_rdpfxpath2str(
a4d82a8a 4762 afi, safi, prd, p, label, num_labels,
6c995628
AD
4763 addpath_id ? 1 : 0, addpath_id, NULL,
4764 pfx_buf, sizeof(pfx_buf));
d62a17ae 4765 zlog_debug(
4766 "%s withdrawing route %s not in adj-in",
4767 peer->host, pfx_buf);
4768 }
9bcb3eef 4769 bgp_dest_unlock_node(dest);
d62a17ae 4770 return 0;
4771 }
cd808e74 4772
d62a17ae 4773 /* Lookup withdrawn route. */
9bcb3eef 4774 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4775 if (pi->peer == peer && pi->type == type
4776 && pi->sub_type == sub_type
4777 && pi->addpath_rx_id == addpath_id)
d62a17ae 4778 break;
4779
4780 /* Logging. */
4781 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4782 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4783 addpath_id ? 1 : 0, addpath_id, NULL,
4784 pfx_buf, sizeof(pfx_buf));
f70c91dc 4785 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4786 pfx_buf);
4787 }
718e3744 4788
d62a17ae 4789 /* Withdraw specified route from routing table. */
40381db7 4790 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4791 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4792 if (SAFI_UNICAST == safi
4793 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4794 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4795 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4796 }
4797 if ((SAFI_MPLS_VPN == safi)
4798 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4799
40381db7 4800 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4801 }
4802 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4803 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4804 addpath_id ? 1 : 0, addpath_id, NULL,
4805 pfx_buf, sizeof(pfx_buf));
d62a17ae 4806 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4807 }
718e3744 4808
d62a17ae 4809 /* Unlock bgp_node_get() lock. */
9bcb3eef 4810 bgp_dest_unlock_node(dest);
d62a17ae 4811
4812 return 0;
718e3744 4813}
6b0655a2 4814
d62a17ae 4815void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4816 int withdraw)
718e3744 4817{
d62a17ae 4818 struct update_subgroup *subgrp;
4819 subgrp = peer_subgroup(peer, afi, safi);
4820 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4821}
6182d65b 4822
718e3744 4823
3f9c7369
DS
4824/*
4825 * bgp_stop_announce_route_timer
4826 */
d62a17ae 4827void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4828{
d62a17ae 4829 if (!paf->t_announce_route)
4830 return;
4831
c3aaa89a 4832 THREAD_OFF(paf->t_announce_route);
718e3744 4833}
6b0655a2 4834
3f9c7369
DS
4835/*
4836 * bgp_announce_route_timer_expired
4837 *
4838 * Callback that is invoked when the route announcement timer for a
4839 * peer_af expires.
4840 */
cc9f21da 4841static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4842{
d62a17ae 4843 struct peer_af *paf;
4844 struct peer *peer;
558d1fec 4845
d62a17ae 4846 paf = THREAD_ARG(t);
4847 peer = paf->peer;
718e3744 4848
feb17238 4849 if (!peer_established(peer))
cc9f21da 4850 return;
3f9c7369 4851
d62a17ae 4852 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4853 return;
3f9c7369 4854
d62a17ae 4855 peer_af_announce_route(paf, 1);
c5aec50b
MK
4856
4857 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4858 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4859}
4860
3f9c7369
DS
4861/*
4862 * bgp_announce_route
4863 *
4864 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4865 *
4866 * if force is true we will force an update even if the update
4867 * limiting code is attempted to kick in.
3f9c7369 4868 */
e1a32ec1 4869void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4870{
4871 struct peer_af *paf;
4872 struct update_subgroup *subgrp;
4873
4874 paf = peer_af_find(peer, afi, safi);
4875 if (!paf)
4876 return;
4877 subgrp = PAF_SUBGRP(paf);
4878
4879 /*
4880 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4881 * or a refresh has already been triggered.
4882 */
4883 if (!subgrp || paf->t_announce_route)
4884 return;
4885
e1a32ec1
DS
4886 if (force)
4887 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4888
d62a17ae 4889 /*
4890 * Start a timer to stagger/delay the announce. This serves
4891 * two purposes - announcement can potentially be combined for
4892 * multiple peers and the announcement doesn't happen in the
4893 * vty context.
4894 */
4895 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4896 (subgrp->peer_count == 1)
4897 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4898 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4899 &paf->t_announce_route);
3f9c7369
DS
4900}
4901
4902/*
4903 * Announce routes from all AF tables to a peer.
4904 *
4905 * This should ONLY be called when there is a need to refresh the
4906 * routes to the peer based on a policy change for this peer alone
4907 * or a route refresh request received from the peer.
4908 * The operation will result in splitting the peer from its existing
4909 * subgroups and putting it in new subgroups.
4910 */
d62a17ae 4911void bgp_announce_route_all(struct peer *peer)
718e3744 4912{
d62a17ae 4913 afi_t afi;
4914 safi_t safi;
4915
05c7a1cc 4916 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4917 bgp_announce_route(peer, afi, safi, false);
718e3744 4918}
6b0655a2 4919
46aeabed
LS
4920/* Flag or unflag bgp_dest to determine whether it should be treated by
4921 * bgp_soft_reconfig_table_task.
4922 * Flag if flag is true. Unflag if flag is false.
4923 */
4924static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4925{
4926 struct bgp_dest *dest;
4927 struct bgp_adj_in *ain;
4928
4929 if (!table)
4930 return;
4931
4932 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4933 for (ain = dest->adj_in; ain; ain = ain->next) {
4934 if (ain->peer != NULL)
4935 break;
4936 }
4937 if (flag && ain != NULL && ain->peer != NULL)
4938 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4939 else
4940 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4941 }
4942}
4943
4944static int bgp_soft_reconfig_table_update(struct peer *peer,
4945 struct bgp_dest *dest,
4946 struct bgp_adj_in *ain, afi_t afi,
4947 safi_t safi, struct prefix_rd *prd)
4948{
4949 struct bgp_path_info *pi;
4950 uint32_t num_labels = 0;
4951 mpls_label_t *label_pnt = NULL;
4952 struct bgp_route_evpn evpn;
4953
4954 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4955 if (pi->peer == peer)
4956 break;
4957
4958 if (pi && pi->extra)
4959 num_labels = pi->extra->num_labels;
4960 if (num_labels)
4961 label_pnt = &pi->extra->label[0];
4962 if (pi)
4963 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4964 sizeof(evpn));
4965 else
4966 memset(&evpn, 0, sizeof(evpn));
4967
4968 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4969 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4970 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4971 &evpn);
4972}
4973
d62a17ae 4974static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4975 struct bgp_table *table,
4976 struct prefix_rd *prd)
718e3744 4977{
d62a17ae 4978 int ret;
9bcb3eef 4979 struct bgp_dest *dest;
d62a17ae 4980 struct bgp_adj_in *ain;
718e3744 4981
d62a17ae 4982 if (!table)
4983 table = peer->bgp->rib[afi][safi];
718e3744 4984
9bcb3eef
DS
4985 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4986 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4987 if (ain->peer != peer)
4988 continue;
8692c506 4989
46aeabed
LS
4990 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4991 afi, safi, prd);
ea47320b
DL
4992
4993 if (ret < 0) {
9bcb3eef 4994 bgp_dest_unlock_node(dest);
ea47320b 4995 return;
d62a17ae 4996 }
4997 }
718e3744 4998}
4999
46aeabed
LS
5000/* Do soft reconfig table per bgp table.
5001 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
5002 * when BGP_NODE_SOFT_RECONFIG is set,
5003 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
5004 * Schedule a new thread to continue the job.
5005 * Without splitting the full job into several part,
5006 * vtysh waits for the job to finish before responding to a BGP command
5007 */
cc9f21da 5008static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
5009{
5010 uint32_t iter, max_iter;
5011 int ret;
5012 struct bgp_dest *dest;
5013 struct bgp_adj_in *ain;
5014 struct peer *peer;
5015 struct bgp_table *table;
5016 struct prefix_rd *prd;
5017 struct listnode *node, *nnode;
5018
5019 table = THREAD_ARG(thread);
5020 prd = NULL;
5021
5022 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
5023 if (table->soft_reconfig_init) {
5024 /* first call of the function with a new srta structure.
5025 * Don't do any treatment this time on nodes
5026 * in order vtysh to respond quickly
5027 */
5028 max_iter = 0;
5029 }
5030
5031 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
5032 dest = bgp_route_next(dest)) {
5033 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
5034 continue;
5035
5036 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
5037
5038 for (ain = dest->adj_in; ain; ain = ain->next) {
5039 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
5040 nnode, peer)) {
5041 if (ain->peer != peer)
5042 continue;
5043
5044 ret = bgp_soft_reconfig_table_update(
5045 peer, dest, ain, table->afi,
5046 table->safi, prd);
5047 iter++;
5048
5049 if (ret < 0) {
5050 bgp_dest_unlock_node(dest);
5051 listnode_delete(
5052 table->soft_reconfig_peers,
5053 peer);
5054 bgp_announce_route(peer, table->afi,
e1a32ec1 5055 table->safi, false);
46aeabed
LS
5056 if (list_isempty(
5057 table->soft_reconfig_peers)) {
5058 list_delete(
5059 &table->soft_reconfig_peers);
5060 bgp_soft_reconfig_table_flag(
5061 table, false);
cc9f21da 5062 return;
46aeabed
LS
5063 }
5064 }
5065 }
5066 }
5067 }
5068
5069 /* we're either starting the initial iteration,
5070 * or we're going to continue an ongoing iteration
5071 */
5072 if (dest || table->soft_reconfig_init) {
5073 table->soft_reconfig_init = false;
5074 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5075 table, 0, &table->soft_reconfig_thread);
cc9f21da 5076 return;
46aeabed
LS
5077 }
5078 /* we're done, clean up the background iteration context info and
5079 schedule route annoucement
5080 */
5081 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5082 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5083 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5084 }
5085
5086 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5087}
5088
5089
5090/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5091 * and peer.
5092 * - bgp cannot be NULL
5093 * - if table and peer are NULL, cancel all threads within the bgp instance
5094 * - if table is NULL and peer is not,
5095 * remove peer in all threads within the bgp instance
5096 * - if peer is NULL, cancel all threads matching table within the bgp instance
5097 */
5098void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5099 const struct bgp_table *table,
5100 const struct peer *peer)
5101{
5102 struct peer *npeer;
5103 struct listnode *node, *nnode;
5104 int afi, safi;
5105 struct bgp_table *ntable;
5106
5107 if (!bgp)
5108 return;
5109
5110 FOREACH_AFI_SAFI (afi, safi) {
5111 ntable = bgp->rib[afi][safi];
5112 if (!ntable)
5113 continue;
5114 if (table && table != ntable)
5115 continue;
5116
5117 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5118 npeer)) {
5119 if (peer && peer != npeer)
5120 continue;
5121 listnode_delete(ntable->soft_reconfig_peers, npeer);
5122 }
5123
5124 if (!ntable->soft_reconfig_peers
5125 || !list_isempty(ntable->soft_reconfig_peers))
5126 continue;
5127
5128 list_delete(&ntable->soft_reconfig_peers);
5129 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5130 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5131 }
5132}
5133
d62a17ae 5134void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5135{
9bcb3eef 5136 struct bgp_dest *dest;
d62a17ae 5137 struct bgp_table *table;
46aeabed
LS
5138 struct listnode *node, *nnode;
5139 struct peer *npeer;
5140 struct peer_af *paf;
718e3744 5141
feb17238 5142 if (!peer_established(peer))
d62a17ae 5143 return;
718e3744 5144
d62a17ae 5145 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5146 && (safi != SAFI_EVPN)) {
5147 table = peer->bgp->rib[afi][safi];
5148 if (!table)
5149 return;
5150
5151 table->soft_reconfig_init = true;
5152
5153 if (!table->soft_reconfig_peers)
5154 table->soft_reconfig_peers = list_new();
5155 npeer = NULL;
5156 /* add peer to the table soft_reconfig_peers if not already
5157 * there
5158 */
5159 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5160 npeer)) {
5161 if (peer == npeer)
5162 break;
5163 }
5164 if (peer != npeer)
5165 listnode_add(table->soft_reconfig_peers, peer);
5166
5167 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5168 * on table would start back at the beginning.
5169 */
5170 bgp_soft_reconfig_table_flag(table, true);
5171
5172 if (!table->soft_reconfig_thread)
5173 thread_add_event(bm->master,
5174 bgp_soft_reconfig_table_task, table, 0,
5175 &table->soft_reconfig_thread);
5176 /* Cancel bgp_announce_route_timer_expired threads.
5177 * bgp_announce_route_timer_expired threads have been scheduled
5178 * to announce routes as soon as the soft_reconfigure process
5179 * finishes.
5180 * In this case, soft_reconfigure is also scheduled by using
5181 * a thread but is planned after the
5182 * bgp_announce_route_timer_expired threads. It means that,
5183 * without cancelling the threads, the route announcement task
5184 * would run before the soft reconfiguration one. That would
5185 * useless and would block vtysh during several seconds. Route
5186 * announcements are rescheduled as soon as the soft_reconfigure
5187 * process finishes.
5188 */
5189 paf = peer_af_find(peer, afi, safi);
5190 if (paf)
5191 bgp_stop_announce_route_timer(paf);
5192 } else
9bcb3eef
DS
5193 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5194 dest = bgp_route_next(dest)) {
5195 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5196
b54892e0
DS
5197 if (table == NULL)
5198 continue;
8692c506 5199
9bcb3eef 5200 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5201 struct prefix_rd prd;
5202
5203 prd.family = AF_UNSPEC;
5204 prd.prefixlen = 64;
5205 memcpy(&prd.val, p->u.val, 8);
5206
5207 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5208 }
718e3744 5209}
6b0655a2 5210
228da428 5211
d62a17ae 5212struct bgp_clear_node_queue {
9bcb3eef 5213 struct bgp_dest *dest;
228da428
CC
5214};
5215
d62a17ae 5216static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5217{
d62a17ae 5218 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5219 struct bgp_dest *dest = cnq->dest;
d62a17ae 5220 struct peer *peer = wq->spec.data;
40381db7 5221 struct bgp_path_info *pi;
3103e8d2 5222 struct bgp *bgp;
9bcb3eef
DS
5223 afi_t afi = bgp_dest_table(dest)->afi;
5224 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5225
9bcb3eef 5226 assert(dest && peer);
3103e8d2 5227 bgp = peer->bgp;
d62a17ae 5228
5229 /* It is possible that we have multiple paths for a prefix from a peer
5230 * if that peer is using AddPath.
5231 */
9bcb3eef 5232 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5233 if (pi->peer != peer)
ea47320b
DL
5234 continue;
5235
5236 /* graceful restart STALE flag set. */
9af52ccf
DA
5237 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5238 && peer->nsf[afi][safi])
5239 || CHECK_FLAG(peer->af_sflags[afi][safi],
5240 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5241 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5242 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5243 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5244 else {
5245 /* If this is an EVPN route, process for
5246 * un-import. */
5247 if (safi == SAFI_EVPN)
9bcb3eef
DS
5248 bgp_evpn_unimport_route(
5249 bgp, afi, safi,
5250 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5251 /* Handle withdraw for VRF route-leaking and L3VPN */
5252 if (SAFI_UNICAST == safi
5253 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5254 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5255 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5256 bgp, pi);
960035b2 5257 }
3103e8d2 5258 if (SAFI_MPLS_VPN == safi &&
960035b2 5259 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5260 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5261 }
3103e8d2 5262
9bcb3eef 5263 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5264 }
ea47320b 5265 }
d62a17ae 5266 return WQ_SUCCESS;
200df115 5267}
5268
d62a17ae 5269static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5270{
d62a17ae 5271 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5272 struct bgp_dest *dest = cnq->dest;
5273 struct bgp_table *table = bgp_dest_table(dest);
228da428 5274
9bcb3eef 5275 bgp_dest_unlock_node(dest);
d62a17ae 5276 bgp_table_unlock(table);
5277 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5278}
5279
d62a17ae 5280static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5281{
d62a17ae 5282 struct peer *peer = wq->spec.data;
64e580a7 5283
d62a17ae 5284 /* Tickle FSM to start moving again */
5285 BGP_EVENT_ADD(peer, Clearing_Completed);
5286
5287 peer_unlock(peer); /* bgp_clear_route */
200df115 5288}
718e3744 5289
d62a17ae 5290static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5291{
d62a17ae 5292 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5293
5294 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5295#undef CLEAR_QUEUE_NAME_LEN
5296
0ce1ca80 5297 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5298 peer->clear_node_queue->spec.hold = 10;
5299 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5300 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5301 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5302 peer->clear_node_queue->spec.max_retries = 0;
5303
5304 /* we only 'lock' this peer reference when the queue is actually active
5305 */
5306 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5307}
5308
d62a17ae 5309static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5310 struct bgp_table *table)
65ca75e0 5311{
9bcb3eef 5312 struct bgp_dest *dest;
b6c386bb 5313 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5314
d62a17ae 5315 if (!table)
5316 table = peer->bgp->rib[afi][safi];
dc83d712 5317
d62a17ae 5318 /* If still no table => afi/safi isn't configured at all or smth. */
5319 if (!table)
5320 return;
dc83d712 5321
9bcb3eef 5322 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5323 struct bgp_path_info *pi, *next;
d62a17ae 5324 struct bgp_adj_in *ain;
5325 struct bgp_adj_in *ain_next;
5326
5327 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5328 * queued for every clearing peer, regardless of whether it is
5329 * relevant to the peer at hand.
5330 *
5331 * Overview: There are 3 different indices which need to be
5332 * scrubbed, potentially, when a peer is removed:
5333 *
5334 * 1 peer's routes visible via the RIB (ie accepted routes)
5335 * 2 peer's routes visible by the (optional) peer's adj-in index
5336 * 3 other routes visible by the peer's adj-out index
5337 *
5338 * 3 there is no hurry in scrubbing, once the struct peer is
5339 * removed from bgp->peer, we could just GC such deleted peer's
5340 * adj-outs at our leisure.
5341 *
5342 * 1 and 2 must be 'scrubbed' in some way, at least made
5343 * invisible via RIB index before peer session is allowed to be
5344 * brought back up. So one needs to know when such a 'search' is
5345 * complete.
5346 *
5347 * Ideally:
5348 *
5349 * - there'd be a single global queue or a single RIB walker
5350 * - rather than tracking which route_nodes still need to be
5351 * examined on a peer basis, we'd track which peers still
5352 * aren't cleared
5353 *
5354 * Given that our per-peer prefix-counts now should be reliable,
5355 * this may actually be achievable. It doesn't seem to be a huge
5356 * problem at this time,
5357 *
5358 * It is possible that we have multiple paths for a prefix from
5359 * a peer
5360 * if that peer is using AddPath.
5361 */
9bcb3eef 5362 ain = dest->adj_in;
d62a17ae 5363 while (ain) {
5364 ain_next = ain->next;
5365
6a840fd9 5366 if (ain->peer == peer)
9bcb3eef 5367 bgp_adj_in_remove(dest, ain);
d62a17ae 5368
5369 ain = ain_next;
5370 }
5371
9bcb3eef 5372 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5373 next = pi->next;
5374 if (pi->peer != peer)
d62a17ae 5375 continue;
5376
5377 if (force)
9bcb3eef 5378 bgp_path_info_reap(dest, pi);
d62a17ae 5379 else {
5380 struct bgp_clear_node_queue *cnq;
5381
5382 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5383 bgp_table_lock(bgp_dest_table(dest));
5384 bgp_dest_lock_node(dest);
d62a17ae 5385 cnq = XCALLOC(
5386 MTYPE_BGP_CLEAR_NODE_QUEUE,
5387 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5388 cnq->dest = dest;
d62a17ae 5389 work_queue_add(peer->clear_node_queue, cnq);
5390 break;
5391 }
5392 }
5393 }
5394 return;
5395}
5396
5397void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5398{
9bcb3eef 5399 struct bgp_dest *dest;
d62a17ae 5400 struct bgp_table *table;
5401
5402 if (peer->clear_node_queue == NULL)
5403 bgp_clear_node_queue_init(peer);
5404
5405 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5406 * Idle until it receives a Clearing_Completed event. This protects
5407 * against peers which flap faster than we can we clear, which could
5408 * lead to:
5409 *
5410 * a) race with routes from the new session being installed before
5411 * clear_route_node visits the node (to delete the route of that
5412 * peer)
5413 * b) resource exhaustion, clear_route_node likely leads to an entry
5414 * on the process_main queue. Fast-flapping could cause that queue
5415 * to grow and grow.
5416 */
5417
5418 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5419 * the unlock will happen upon work-queue completion; other wise, the
5420 * unlock happens at the end of this function.
5421 */
5422 if (!peer->clear_node_queue->thread)
5423 peer_lock(peer);
5424
5425 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5426 bgp_clear_route_table(peer, afi, safi, NULL);
5427 else
9bcb3eef
DS
5428 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5429 dest = bgp_route_next(dest)) {
5430 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5431 if (!table)
5432 continue;
5433
5434 bgp_clear_route_table(peer, afi, safi, table);
5435 }
d62a17ae 5436
5437 /* unlock if no nodes got added to the clear-node-queue. */
5438 if (!peer->clear_node_queue->thread)
5439 peer_unlock(peer);
718e3744 5440}
d62a17ae 5441
5442void bgp_clear_route_all(struct peer *peer)
718e3744 5443{
d62a17ae 5444 afi_t afi;
5445 safi_t safi;
718e3744 5446
05c7a1cc
QY
5447 FOREACH_AFI_SAFI (afi, safi)
5448 bgp_clear_route(peer, afi, safi);
65efcfce 5449
49e5a4a0 5450#ifdef ENABLE_BGP_VNC
d62a17ae 5451 rfapiProcessPeerDown(peer);
65efcfce 5452#endif
718e3744 5453}
5454
d62a17ae 5455void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5456{
d62a17ae 5457 struct bgp_table *table;
9bcb3eef 5458 struct bgp_dest *dest;
d62a17ae 5459 struct bgp_adj_in *ain;
5460 struct bgp_adj_in *ain_next;
718e3744 5461
d62a17ae 5462 table = peer->bgp->rib[afi][safi];
718e3744 5463
d62a17ae 5464 /* It is possible that we have multiple paths for a prefix from a peer
5465 * if that peer is using AddPath.
5466 */
9bcb3eef
DS
5467 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5468 ain = dest->adj_in;
43143c8f 5469
d62a17ae 5470 while (ain) {
5471 ain_next = ain->next;
43143c8f 5472
6a840fd9 5473 if (ain->peer == peer)
9bcb3eef 5474 bgp_adj_in_remove(dest, ain);
43143c8f 5475
d62a17ae 5476 ain = ain_next;
5477 }
5478 }
718e3744 5479}
93406d87 5480
1479ed2f
DA
5481/* If any of the routes from the peer have been marked with the NO_LLGR
5482 * community, either as sent by the peer, or as the result of a configured
5483 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5484 * operation of [RFC4271].
5485 */
d62a17ae 5486void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5487{
9bcb3eef 5488 struct bgp_dest *dest;
40381db7 5489 struct bgp_path_info *pi;
d62a17ae 5490 struct bgp_table *table;
5491
9af52ccf 5492 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5493 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5494 dest = bgp_route_next(dest)) {
5495 struct bgp_dest *rm;
d62a17ae 5496
5497 /* look for neighbor in tables */
9bcb3eef 5498 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5499 if (!table)
ea47320b
DL
5500 continue;
5501
5502 for (rm = bgp_table_top(table); rm;
5503 rm = bgp_route_next(rm))
9bcb3eef 5504 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5505 pi = pi->next) {
40381db7 5506 if (pi->peer != peer)
ea47320b 5507 continue;
1479ed2f
DA
5508 if (CHECK_FLAG(
5509 peer->af_sflags[afi][safi],
5510 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5511 bgp_attr_get_community(pi->attr) &&
1479ed2f 5512 !community_include(
9a706b42
DA
5513 bgp_attr_get_community(
5514 pi->attr),
1479ed2f 5515 COMMUNITY_NO_LLGR))
e3015d91 5516 continue;
40381db7 5517 if (!CHECK_FLAG(pi->flags,
1defdda8 5518 BGP_PATH_STALE))
e3015d91 5519 continue;
ea47320b 5520
641065d4
KM
5521 /*
5522 * If this is VRF leaked route
5523 * process for withdraw.
5524 */
5525 if (pi->sub_type ==
5526 BGP_ROUTE_IMPORTED &&
5527 peer->bgp->inst_type ==
5528 BGP_INSTANCE_TYPE_DEFAULT)
5529 vpn_leak_to_vrf_withdraw(
5530 peer->bgp, pi);
5531
40381db7 5532 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5533 break;
5534 }
d62a17ae 5535 }
5536 } else {
9bcb3eef
DS
5537 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5538 dest = bgp_route_next(dest))
5539 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5540 pi = pi->next) {
40381db7 5541 if (pi->peer != peer)
ea47320b 5542 continue;
1479ed2f
DA
5543 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5544 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5545 bgp_attr_get_community(pi->attr) &&
5546 !community_include(
5547 bgp_attr_get_community(pi->attr),
5548 COMMUNITY_NO_LLGR))
e3015d91 5549 continue;
40381db7 5550 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5551 continue;
641065d4
KM
5552 if (safi == SAFI_UNICAST &&
5553 (peer->bgp->inst_type ==
5554 BGP_INSTANCE_TYPE_VRF ||
5555 peer->bgp->inst_type ==
5556 BGP_INSTANCE_TYPE_DEFAULT))
5557 vpn_leak_from_vrf_withdraw(
5558 bgp_get_default(), peer->bgp,
5559 pi);
5560
9bcb3eef 5561 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5562 break;
5563 }
d62a17ae 5564 }
93406d87 5565}
6b0655a2 5566
9af52ccf
DA
5567void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5568{
5569 struct bgp_dest *dest, *ndest;
5570 struct bgp_path_info *pi;
5571 struct bgp_table *table;
5572
5573 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5574 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5575 dest = bgp_route_next(dest)) {
5576 table = bgp_dest_get_bgp_table_info(dest);
5577 if (!table)
5578 continue;
5579
5580 for (ndest = bgp_table_top(table); ndest;
5581 ndest = bgp_route_next(ndest)) {
5582 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5583 pi = pi->next) {
5584 if (pi->peer != peer)
5585 continue;
5586
5587 if ((CHECK_FLAG(
5588 peer->af_sflags[afi][safi],
5589 PEER_STATUS_ENHANCED_REFRESH))
5590 && !CHECK_FLAG(pi->flags,
5591 BGP_PATH_STALE)
5592 && !CHECK_FLAG(
5593 pi->flags,
5594 BGP_PATH_UNUSEABLE)) {
5595 if (bgp_debug_neighbor_events(
5596 peer))
5597 zlog_debug(
5598 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5599 peer->host,
5600 afi2str(afi),
5601 safi2str(safi),
5602 bgp_dest_get_prefix(
5603 ndest));
5604
5605 bgp_path_info_set_flag(
5606 ndest, pi,
5607 BGP_PATH_STALE);
5608 }
5609 }
5610 }
5611 }
5612 } else {
5613 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5614 dest = bgp_route_next(dest)) {
5615 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5616 pi = pi->next) {
5617 if (pi->peer != peer)
5618 continue;
5619
5620 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5621 PEER_STATUS_ENHANCED_REFRESH))
5622 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5623 && !CHECK_FLAG(pi->flags,
5624 BGP_PATH_UNUSEABLE)) {
5625 if (bgp_debug_neighbor_events(peer))
5626 zlog_debug(
5627 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5628 peer->host,
5629 afi2str(afi),
5630 safi2str(safi),
5631 bgp_dest_get_prefix(
5632 dest));
5633
5634 bgp_path_info_set_flag(dest, pi,
5635 BGP_PATH_STALE);
5636 }
5637 }
5638 }
5639 }
5640}
5641
3dc339cd 5642bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5643{
e0df4c04 5644 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5645 return true;
e0df4c04 5646
9dac9fc8
DA
5647 if (peer->sort == BGP_PEER_EBGP
5648 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5649 || FILTER_LIST_OUT_NAME(filter)
5650 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5651 return true;
5652 return false;
9dac9fc8
DA
5653}
5654
3dc339cd 5655bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5656{
e0df4c04 5657 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5658 return true;
e0df4c04 5659
9dac9fc8
DA
5660 if (peer->sort == BGP_PEER_EBGP
5661 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5662 || FILTER_LIST_IN_NAME(filter)
5663 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5664 return true;
5665 return false;
9dac9fc8
DA
5666}
5667
568e10ca 5668static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5669 safi_t safi)
bb86c601 5670{
9bcb3eef 5671 struct bgp_dest *dest;
40381db7 5672 struct bgp_path_info *pi;
4b7e6066 5673 struct bgp_path_info *next;
bb86c601 5674
9bcb3eef
DS
5675 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5676 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5677 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5678
40381db7 5679 next = pi->next;
1b7bb747
CS
5680
5681 /* Unimport EVPN routes from VRFs */
5682 if (safi == SAFI_EVPN)
5683 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5684 SAFI_EVPN, p, pi);
1b7bb747 5685
40381db7
DS
5686 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5687 && pi->type == ZEBRA_ROUTE_BGP
5688 && (pi->sub_type == BGP_ROUTE_NORMAL
5689 || pi->sub_type == BGP_ROUTE_AGGREGATE
5690 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5691
d62a17ae 5692 if (bgp_fibupd_safi(safi))
b54892e0 5693 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5694 }
9514b37d 5695
9bcb3eef 5696 bgp_path_info_reap(dest, pi);
d62a17ae 5697 }
bb86c601
LB
5698}
5699
718e3744 5700/* Delete all kernel routes. */
d62a17ae 5701void bgp_cleanup_routes(struct bgp *bgp)
5702{
5703 afi_t afi;
9bcb3eef 5704 struct bgp_dest *dest;
67009e22 5705 struct bgp_table *table;
d62a17ae 5706
5707 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5708 if (afi == AFI_L2VPN)
5709 continue;
568e10ca 5710 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5711 SAFI_UNICAST);
d62a17ae 5712 /*
5713 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5714 */
5715 if (afi != AFI_L2VPN) {
5716 safi_t safi;
5717 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5718 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5719 dest = bgp_route_next(dest)) {
5720 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5721 if (table != NULL) {
5722 bgp_cleanup_table(bgp, table, safi);
5723 bgp_table_finish(&table);
9bcb3eef
DS
5724 bgp_dest_set_bgp_table_info(dest, NULL);
5725 bgp_dest_unlock_node(dest);
d62a17ae 5726 }
5727 }
5728 safi = SAFI_ENCAP;
9bcb3eef
DS
5729 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5730 dest = bgp_route_next(dest)) {
5731 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5732 if (table != NULL) {
5733 bgp_cleanup_table(bgp, table, safi);
5734 bgp_table_finish(&table);
9bcb3eef
DS
5735 bgp_dest_set_bgp_table_info(dest, NULL);
5736 bgp_dest_unlock_node(dest);
d62a17ae 5737 }
5738 }
5739 }
5740 }
9bcb3eef
DS
5741 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5742 dest = bgp_route_next(dest)) {
5743 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5744 if (table != NULL) {
5745 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5746 bgp_table_finish(&table);
9bcb3eef
DS
5747 bgp_dest_set_bgp_table_info(dest, NULL);
5748 bgp_dest_unlock_node(dest);
d62a17ae 5749 }
bb86c601 5750 }
718e3744 5751}
5752
d62a17ae 5753void bgp_reset(void)
718e3744 5754{
d62a17ae 5755 vty_reset();
5756 bgp_zclient_reset();
5757 access_list_reset();
5758 prefix_list_reset();
718e3744 5759}
6b0655a2 5760
be92fc9f 5761bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5762{
d62a17ae 5763 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5764 && CHECK_FLAG(peer->af_cap[afi][safi],
5765 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5766}
5767
718e3744 5768/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5769 value. */
d62a17ae 5770int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5771 struct bgp_nlri *packet)
5772{
d7c0a89a
QY
5773 uint8_t *pnt;
5774 uint8_t *lim;
d62a17ae 5775 struct prefix p;
5776 int psize;
5777 int ret;
5778 afi_t afi;
5779 safi_t safi;
be92fc9f 5780 bool addpath_capable;
d7c0a89a 5781 uint32_t addpath_id;
d62a17ae 5782
d62a17ae 5783 pnt = packet->nlri;
5784 lim = pnt + packet->length;
5785 afi = packet->afi;
5786 safi = packet->safi;
5787 addpath_id = 0;
be92fc9f 5788 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5789
5790 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5791 syntactic validity. If the field is syntactically incorrect,
5792 then the Error Subcode is set to Invalid Network Field. */
5793 for (; pnt < lim; pnt += psize) {
5794 /* Clear prefix structure. */
6006b807 5795 memset(&p, 0, sizeof(p));
d62a17ae 5796
be92fc9f 5797 if (addpath_capable) {
d62a17ae 5798
5799 /* When packet overflow occurs return immediately. */
761ed665 5800 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5801 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5802
a3a850a1 5803 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5804 addpath_id = ntohl(addpath_id);
d62a17ae 5805 pnt += BGP_ADDPATH_ID_LEN;
5806 }
718e3744 5807
d62a17ae 5808 /* Fetch prefix length. */
5809 p.prefixlen = *pnt++;
5810 /* afi/safi validity already verified by caller,
5811 * bgp_update_receive */
5812 p.family = afi2family(afi);
5813
5814 /* Prefix length check. */
5815 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5816 flog_err(
e50f7cfd 5817 EC_BGP_UPDATE_RCV,
14454c9f 5818 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5819 peer->host, p.prefixlen, packet->afi);
513386b5 5820 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5821 }
6b0655a2 5822
d62a17ae 5823 /* Packet size overflow check. */
5824 psize = PSIZE(p.prefixlen);
5825
5826 /* When packet overflow occur return immediately. */
5827 if (pnt + psize > lim) {
af4c2728 5828 flog_err(
e50f7cfd 5829 EC_BGP_UPDATE_RCV,
d62a17ae 5830 "%s [Error] Update packet error (prefix length %d overflows packet)",
5831 peer->host, p.prefixlen);
513386b5 5832 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5833 }
5834
5835 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5836 * prefix for the v4 and v6 afi's and unicast/multicast */
5837 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5838 flog_err(
e50f7cfd 5839 EC_BGP_UPDATE_RCV,
d62a17ae 5840 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5841 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5842 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5843 }
5844
5845 /* Fetch prefix from NLRI packet. */
a85297a7 5846 memcpy(p.u.val, pnt, psize);
d62a17ae 5847
5848 /* Check address. */
5849 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5850 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5851 /* From RFC4271 Section 6.3:
5852 *
5853 * If a prefix in the NLRI field is semantically
5854 * incorrect
5855 * (e.g., an unexpected multicast IP address),
5856 * an error SHOULD
5857 * be logged locally, and the prefix SHOULD be
5858 * ignored.
a4d82a8a 5859 */
af4c2728 5860 flog_err(
e50f7cfd 5861 EC_BGP_UPDATE_RCV,
23d0a753
DA
5862 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5863 peer->host, &p.u.prefix4);
d62a17ae 5864 continue;
5865 }
5866 }
5867
5868 /* Check address. */
5869 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5870 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5871 flog_err(
e50f7cfd 5872 EC_BGP_UPDATE_RCV,
c0d72166
DS
5873 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5874 peer->host, &p.u.prefix6);
d62a17ae 5875
5876 continue;
5877 }
5878 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5879 flog_err(
e50f7cfd 5880 EC_BGP_UPDATE_RCV,
c0d72166
DS
5881 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5882 peer->host, &p.u.prefix6);
d62a17ae 5883
5884 continue;
5885 }
5886 }
5887
5888 /* Normal process. */
5889 if (attr)
5890 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5891 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5892 NULL, NULL, 0, 0, NULL);
d62a17ae 5893 else
5894 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5895 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5896 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5897 NULL);
d62a17ae 5898
513386b5
DA
5899 /* Do not send BGP notification twice when maximum-prefix count
5900 * overflow. */
5901 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5902 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5903
5904 /* Address family configuration mismatch. */
d62a17ae 5905 if (ret < 0)
513386b5 5906 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5907 }
5908
5909 /* Packet length consistency check. */
5910 if (pnt != lim) {
af4c2728 5911 flog_err(
e50f7cfd 5912 EC_BGP_UPDATE_RCV,
d62a17ae 5913 "%s [Error] Update packet error (prefix length mismatch with total length)",
5914 peer->host);
513386b5 5915 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5916 }
6b0655a2 5917
513386b5 5918 return BGP_NLRI_PARSE_OK;
718e3744 5919}
5920
d62a17ae 5921static struct bgp_static *bgp_static_new(void)
718e3744 5922{
d62a17ae 5923 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5924}
5925
d62a17ae 5926static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5927{
0a22ddfb 5928 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5929 route_map_counter_decrement(bgp_static->rmap.map);
5930
0a22ddfb 5931 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5932 XFREE(MTYPE_BGP_STATIC, bgp_static);
5933}
5934
5f040085 5935void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5936 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5937{
9bcb3eef 5938 struct bgp_dest *dest;
40381db7 5939 struct bgp_path_info *pi;
4b7e6066 5940 struct bgp_path_info *new;
40381db7 5941 struct bgp_path_info rmap_path;
d62a17ae 5942 struct attr attr;
5943 struct attr *attr_new;
b68885f9 5944 route_map_result_t ret;
49e5a4a0 5945#ifdef ENABLE_BGP_VNC
d62a17ae 5946 int vnc_implicit_withdraw = 0;
65efcfce 5947#endif
fee0f4c6 5948
d62a17ae 5949 assert(bgp_static);
dd8103a9 5950
9bcb3eef 5951 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5952
0f05ea43 5953 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5954
d62a17ae 5955 attr.nexthop = bgp_static->igpnexthop;
5956 attr.med = bgp_static->igpmetric;
5957 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5958
7226bc40
TA
5959 if (afi == AFI_IP)
5960 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5961
d62a17ae 5962 if (bgp_static->atomic)
5963 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5964
d62a17ae 5965 /* Store label index, if required. */
5966 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5967 attr.label_index = bgp_static->label_index;
5968 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5969 }
718e3744 5970
d62a17ae 5971 /* Apply route-map. */
5972 if (bgp_static->rmap.name) {
5973 struct attr attr_tmp = attr;
80ced710 5974
6006b807 5975 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5976 rmap_path.peer = bgp->peer_self;
5977 rmap_path.attr = &attr_tmp;
fee0f4c6 5978
d62a17ae 5979 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5980
1782514f 5981 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5982
d62a17ae 5983 bgp->peer_self->rmap_type = 0;
718e3744 5984
d62a17ae 5985 if (ret == RMAP_DENYMATCH) {
5986 /* Free uninterned attribute. */
5987 bgp_attr_flush(&attr_tmp);
718e3744 5988
d62a17ae 5989 /* Unintern original. */
5990 aspath_unintern(&attr.aspath);
5991 bgp_static_withdraw(bgp, p, afi, safi);
5992 return;
5993 }
7f323236 5994
637e5ba4 5995 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5996 bgp_attr_add_gshut_community(&attr_tmp);
5997
d62a17ae 5998 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5999 } else {
6000
637e5ba4 6001 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
6002 bgp_attr_add_gshut_community(&attr);
6003
d62a17ae 6004 attr_new = bgp_attr_intern(&attr);
7f323236 6005 }
718e3744 6006
9bcb3eef 6007 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6008 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6009 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6010 break;
6011
40381db7
DS
6012 if (pi) {
6013 if (attrhash_cmp(pi->attr, attr_new)
6014 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 6015 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 6016 bgp_dest_unlock_node(dest);
d62a17ae 6017 bgp_attr_unintern(&attr_new);
6018 aspath_unintern(&attr.aspath);
6019 return;
6020 } else {
6021 /* The attribute is changed. */
9bcb3eef 6022 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6023
6024 /* Rewrite BGP route information. */
40381db7 6025 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6026 bgp_path_info_restore(dest, pi);
d62a17ae 6027 else
40381db7 6028 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 6029#ifdef ENABLE_BGP_VNC
d62a17ae 6030 if ((afi == AFI_IP || afi == AFI_IP6)
6031 && (safi == SAFI_UNICAST)) {
40381db7 6032 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 6033 /*
6034 * Implicit withdraw case.
40381db7 6035 * We have to do this before pi is
d62a17ae 6036 * changed
6037 */
6038 ++vnc_implicit_withdraw;
40381db7 6039 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 6040 vnc_import_bgp_exterior_del_route(
40381db7 6041 bgp, p, pi);
d62a17ae 6042 }
6043 }
65efcfce 6044#endif
40381db7
DS
6045 bgp_attr_unintern(&pi->attr);
6046 pi->attr = attr_new;
083ec940 6047 pi->uptime = monotime(NULL);
49e5a4a0 6048#ifdef ENABLE_BGP_VNC
d62a17ae 6049 if ((afi == AFI_IP || afi == AFI_IP6)
6050 && (safi == SAFI_UNICAST)) {
6051 if (vnc_implicit_withdraw) {
40381db7 6052 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6053 vnc_import_bgp_exterior_add_route(
40381db7 6054 bgp, p, pi);
d62a17ae 6055 }
6056 }
65efcfce 6057#endif
718e3744 6058
d62a17ae 6059 /* Nexthop reachability check. */
892fedb6 6060 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6061 && (safi == SAFI_UNICAST
6062 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6063
6064 struct bgp *bgp_nexthop = bgp;
6065
40381db7
DS
6066 if (pi->extra && pi->extra->bgp_orig)
6067 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6068
6069 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6070 afi, safi, pi, NULL,
654a5978 6071 0, p))
9bcb3eef 6072 bgp_path_info_set_flag(dest, pi,
18ee8310 6073 BGP_PATH_VALID);
d62a17ae 6074 else {
6075 if (BGP_DEBUG(nht, NHT)) {
6076 char buf1[INET6_ADDRSTRLEN];
6077 inet_ntop(p->family,
6078 &p->u.prefix, buf1,
6079 INET6_ADDRSTRLEN);
6080 zlog_debug(
6081 "%s(%s): Route not in table, not advertising",
15569c58 6082 __func__, buf1);
d62a17ae 6083 }
18ee8310 6084 bgp_path_info_unset_flag(
9bcb3eef 6085 dest, pi, BGP_PATH_VALID);
d62a17ae 6086 }
6087 } else {
6088 /* Delete the NHT structure if any, if we're
6089 * toggling between
6090 * enabling/disabling import check. We
6091 * deregister the route
6092 * from NHT to avoid overloading NHT and the
6093 * process interaction
6094 */
40381db7 6095 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6096 bgp_path_info_set_flag(dest, pi,
6097 BGP_PATH_VALID);
d62a17ae 6098 }
6099 /* Process change. */
40381db7 6100 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6101 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6102
6103 if (SAFI_UNICAST == safi
6104 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6105 || bgp->inst_type
6106 == BGP_INSTANCE_TYPE_DEFAULT)) {
6107 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6108 pi);
ddb5b488
PZ
6109 }
6110
9bcb3eef 6111 bgp_dest_unlock_node(dest);
d62a17ae 6112 aspath_unintern(&attr.aspath);
6113 return;
6114 }
718e3744 6115 }
718e3744 6116
d62a17ae 6117 /* Make new BGP info. */
6118 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6119 attr_new, dest);
d62a17ae 6120 /* Nexthop reachability check. */
892fedb6 6121 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6122 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6123 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6124 p))
9bcb3eef 6125 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6126 else {
6127 if (BGP_DEBUG(nht, NHT)) {
6128 char buf1[INET6_ADDRSTRLEN];
6129 inet_ntop(p->family, &p->u.prefix, buf1,
6130 INET6_ADDRSTRLEN);
6131 zlog_debug(
6132 "%s(%s): Route not in table, not advertising",
15569c58 6133 __func__, buf1);
d62a17ae 6134 }
9bcb3eef 6135 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6136 }
6137 } else {
6138 /* Delete the NHT structure if any, if we're toggling between
6139 * enabling/disabling import check. We deregister the route
6140 * from NHT to avoid overloading NHT and the process interaction
6141 */
6142 bgp_unlink_nexthop(new);
6143
9bcb3eef 6144 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6145 }
078430f6 6146
d62a17ae 6147 /* Aggregate address increment. */
6148 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6149
d62a17ae 6150 /* Register new BGP information. */
9bcb3eef 6151 bgp_path_info_add(dest, new);
718e3744 6152
d62a17ae 6153 /* route_node_get lock */
9bcb3eef 6154 bgp_dest_unlock_node(dest);
d62a17ae 6155
6156 /* Process change. */
9bcb3eef 6157 bgp_process(bgp, dest, afi, safi);
d62a17ae 6158
ddb5b488
PZ
6159 if (SAFI_UNICAST == safi
6160 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6161 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6162 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6163 }
6164
d62a17ae 6165 /* Unintern original. */
6166 aspath_unintern(&attr.aspath);
718e3744 6167}
6168
5f040085 6169void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6170 safi_t safi)
718e3744 6171{
9bcb3eef 6172 struct bgp_dest *dest;
40381db7 6173 struct bgp_path_info *pi;
718e3744 6174
9bcb3eef 6175 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6176
d62a17ae 6177 /* Check selected route and self inserted route. */
9bcb3eef 6178 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6179 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6180 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6181 break;
6182
6183 /* Withdraw static BGP route from routing table. */
40381db7 6184 if (pi) {
ddb5b488
PZ
6185 if (SAFI_UNICAST == safi
6186 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6187 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6188 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6189 }
40381db7
DS
6190 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6191 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6192 bgp_path_info_delete(dest, pi);
6193 bgp_process(bgp, dest, afi, safi);
d62a17ae 6194 }
718e3744 6195
d62a17ae 6196 /* Unlock bgp_node_lookup. */
9bcb3eef 6197 bgp_dest_unlock_node(dest);
718e3744 6198}
6199
137446f9
LB
6200/*
6201 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6202 */
5f040085 6203static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6204 afi_t afi, safi_t safi,
6205 struct prefix_rd *prd)
718e3744 6206{
9bcb3eef 6207 struct bgp_dest *dest;
40381db7 6208 struct bgp_path_info *pi;
718e3744 6209
9bcb3eef 6210 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6211
d62a17ae 6212 /* Check selected route and self inserted route. */
9bcb3eef 6213 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6214 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6215 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6216 break;
718e3744 6217
d62a17ae 6218 /* Withdraw static BGP route from routing table. */
40381db7 6219 if (pi) {
49e5a4a0 6220#ifdef ENABLE_BGP_VNC
d62a17ae 6221 rfapiProcessWithdraw(
40381db7 6222 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6223 1); /* Kill, since it is an administrative change */
65efcfce 6224#endif
ddb5b488
PZ
6225 if (SAFI_MPLS_VPN == safi
6226 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6227 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6228 }
40381db7 6229 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6230 bgp_path_info_delete(dest, pi);
6231 bgp_process(bgp, dest, afi, safi);
d62a17ae 6232 }
718e3744 6233
d62a17ae 6234 /* Unlock bgp_node_lookup. */
9bcb3eef 6235 bgp_dest_unlock_node(dest);
718e3744 6236}
6237
5f040085 6238static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6239 struct bgp_static *bgp_static, afi_t afi,
6240 safi_t safi)
137446f9 6241{
9bcb3eef 6242 struct bgp_dest *dest;
4b7e6066 6243 struct bgp_path_info *new;
d62a17ae 6244 struct attr *attr_new;
6245 struct attr attr = {0};
40381db7 6246 struct bgp_path_info *pi;
49e5a4a0 6247#ifdef ENABLE_BGP_VNC
d62a17ae 6248 mpls_label_t label = 0;
65efcfce 6249#endif
d7c0a89a 6250 uint32_t num_labels = 0;
137446f9 6251
d62a17ae 6252 assert(bgp_static);
137446f9 6253
b57ba6d2
MK
6254 if (bgp_static->label != MPLS_INVALID_LABEL)
6255 num_labels = 1;
9bcb3eef
DS
6256 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6257 &bgp_static->prd);
137446f9 6258
0f05ea43 6259 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6260
d62a17ae 6261 attr.nexthop = bgp_static->igpnexthop;
6262 attr.med = bgp_static->igpmetric;
6263 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6264
d62a17ae 6265 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6266 || (safi == SAFI_ENCAP)) {
6267 if (afi == AFI_IP) {
6268 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6269 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6270 }
6271 }
6272 if (afi == AFI_L2VPN) {
b04c1e99
IR
6273 if (bgp_static->gatewayIp.family == AF_INET) {
6274 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6275 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6276 &bgp_static->gatewayIp.u.prefix4,
6277 IPV4_MAX_BYTELEN);
b04c1e99
IR
6278 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6279 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6280 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6281 &bgp_static->gatewayIp.u.prefix6,
6282 IPV6_MAX_BYTELEN);
b04c1e99 6283 }
0a50c248 6284 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6285 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6286 struct bgp_encap_type_vxlan bet;
6006b807 6287 memset(&bet, 0, sizeof(bet));
3714a385 6288 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6289 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6290 }
6291 if (bgp_static->router_mac) {
6292 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6293 }
6294 }
6295 /* Apply route-map. */
6296 if (bgp_static->rmap.name) {
6297 struct attr attr_tmp = attr;
40381db7 6298 struct bgp_path_info rmap_path;
b68885f9 6299 route_map_result_t ret;
137446f9 6300
40381db7
DS
6301 rmap_path.peer = bgp->peer_self;
6302 rmap_path.attr = &attr_tmp;
137446f9 6303
d62a17ae 6304 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6305
1782514f 6306 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6307
d62a17ae 6308 bgp->peer_self->rmap_type = 0;
137446f9 6309
d62a17ae 6310 if (ret == RMAP_DENYMATCH) {
6311 /* Free uninterned attribute. */
6312 bgp_attr_flush(&attr_tmp);
137446f9 6313
d62a17ae 6314 /* Unintern original. */
6315 aspath_unintern(&attr.aspath);
6316 bgp_static_withdraw_safi(bgp, p, afi, safi,
6317 &bgp_static->prd);
6318 return;
6319 }
137446f9 6320
d62a17ae 6321 attr_new = bgp_attr_intern(&attr_tmp);
6322 } else {
6323 attr_new = bgp_attr_intern(&attr);
6324 }
137446f9 6325
9bcb3eef 6326 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6327 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6328 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6329 break;
6330
40381db7 6331 if (pi) {
40381db7 6332 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6333 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6334 bgp_dest_unlock_node(dest);
d62a17ae 6335 bgp_attr_unintern(&attr_new);
6336 aspath_unintern(&attr.aspath);
6337 return;
6338 } else {
6339 /* The attribute is changed. */
9bcb3eef 6340 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6341
6342 /* Rewrite BGP route information. */
40381db7 6343 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6344 bgp_path_info_restore(dest, pi);
d62a17ae 6345 else
40381db7
DS
6346 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6347 bgp_attr_unintern(&pi->attr);
6348 pi->attr = attr_new;
083ec940 6349 pi->uptime = monotime(NULL);
49e5a4a0 6350#ifdef ENABLE_BGP_VNC
40381db7
DS
6351 if (pi->extra)
6352 label = decode_label(&pi->extra->label[0]);
65efcfce 6353#endif
137446f9 6354
d62a17ae 6355 /* Process change. */
40381db7 6356 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6357 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6358
6359 if (SAFI_MPLS_VPN == safi
6360 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6361 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6362 }
49e5a4a0 6363#ifdef ENABLE_BGP_VNC
40381db7
DS
6364 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6365 pi->attr, afi, safi, pi->type,
6366 pi->sub_type, &label);
65efcfce 6367#endif
9bcb3eef 6368 bgp_dest_unlock_node(dest);
d62a17ae 6369 aspath_unintern(&attr.aspath);
6370 return;
6371 }
6372 }
137446f9
LB
6373
6374
d62a17ae 6375 /* Make new BGP info. */
6376 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6377 attr_new, dest);
1defdda8 6378 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6379 bgp_path_info_extra_get(new);
b57ba6d2
MK
6380 if (num_labels) {
6381 new->extra->label[0] = bgp_static->label;
6382 new->extra->num_labels = num_labels;
6383 }
49e5a4a0 6384#ifdef ENABLE_BGP_VNC
d62a17ae 6385 label = decode_label(&bgp_static->label);
65efcfce 6386#endif
137446f9 6387
d62a17ae 6388 /* Aggregate address increment. */
6389 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6390
d62a17ae 6391 /* Register new BGP information. */
9bcb3eef 6392 bgp_path_info_add(dest, new);
d62a17ae 6393 /* route_node_get lock */
9bcb3eef 6394 bgp_dest_unlock_node(dest);
137446f9 6395
d62a17ae 6396 /* Process change. */
9bcb3eef 6397 bgp_process(bgp, dest, afi, safi);
137446f9 6398
ddb5b488
PZ
6399 if (SAFI_MPLS_VPN == safi
6400 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6401 vpn_leak_to_vrf_update(bgp, new);
6402 }
49e5a4a0 6403#ifdef ENABLE_BGP_VNC
d62a17ae 6404 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6405 safi, new->type, new->sub_type, &label);
65efcfce
LB
6406#endif
6407
d62a17ae 6408 /* Unintern original. */
6409 aspath_unintern(&attr.aspath);
137446f9
LB
6410}
6411
718e3744 6412/* Configure static BGP network. When user don't run zebra, static
6413 route should be installed as valid. */
585f1adc
IR
6414static int bgp_static_set(struct vty *vty, const char *negate,
6415 const char *ip_str, afi_t afi, safi_t safi,
6416 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6417{
585f1adc
IR
6418 VTY_DECLVAR_CONTEXT(bgp, bgp);
6419 int ret;
d62a17ae 6420 struct prefix p;
6421 struct bgp_static *bgp_static;
9bcb3eef 6422 struct bgp_dest *dest;
d7c0a89a 6423 uint8_t need_update = 0;
d62a17ae 6424
585f1adc
IR
6425 /* Convert IP prefix string to struct prefix. */
6426 ret = str2prefix(ip_str, &p);
6427 if (!ret) {
6428 vty_out(vty, "%% Malformed prefix\n");
6429 return CMD_WARNING_CONFIG_FAILED;
6430 }
6431 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6432 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6433 return CMD_WARNING_CONFIG_FAILED;
6434 }
6435
d62a17ae 6436 apply_mask(&p);
718e3744 6437
e2a86ad9 6438 if (negate) {
718e3744 6439
e2a86ad9 6440 /* Set BGP static route configuration. */
9bcb3eef 6441 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6442
9bcb3eef 6443 if (!dest) {
585f1adc
IR
6444 vty_out(vty, "%% Can't find static route specified\n");
6445 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6446 }
6447
9bcb3eef 6448 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6449
e2a86ad9
DS
6450 if ((label_index != BGP_INVALID_LABEL_INDEX)
6451 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6452 vty_out(vty,
6453 "%% label-index doesn't match static route\n");
70d9b134 6454 bgp_dest_unlock_node(dest);
585f1adc 6455 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6456 }
d62a17ae 6457
e2a86ad9
DS
6458 if ((rmap && bgp_static->rmap.name)
6459 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6460 vty_out(vty,
6461 "%% route-map name doesn't match static route\n");
70d9b134 6462 bgp_dest_unlock_node(dest);
585f1adc 6463 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6464 }
718e3744 6465
e2a86ad9
DS
6466 /* Update BGP RIB. */
6467 if (!bgp_static->backdoor)
6468 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6469
e2a86ad9
DS
6470 /* Clear configuration. */
6471 bgp_static_free(bgp_static);
9bcb3eef
DS
6472 bgp_dest_set_bgp_static_info(dest, NULL);
6473 bgp_dest_unlock_node(dest);
6474 bgp_dest_unlock_node(dest);
e2a86ad9 6475 } else {
718e3744 6476
e2a86ad9 6477 /* Set BGP static route configuration. */
9bcb3eef
DS
6478 dest = bgp_node_get(bgp->route[afi][safi], &p);
6479 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6480 if (bgp_static) {
e2a86ad9 6481 /* Configuration change. */
e2a86ad9
DS
6482 /* Label index cannot be changed. */
6483 if (bgp_static->label_index != label_index) {
585f1adc
IR
6484 vty_out(vty, "%% cannot change label-index\n");
6485 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6486 }
d62a17ae 6487
e2a86ad9 6488 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6489 if (bgp_static->valid
6490 && bgp_static->backdoor != backdoor)
e2a86ad9 6491 need_update = 1;
718e3744 6492
e2a86ad9 6493 bgp_static->backdoor = backdoor;
718e3744 6494
e2a86ad9 6495 if (rmap) {
0a22ddfb
QY
6496 XFREE(MTYPE_ROUTE_MAP_NAME,
6497 bgp_static->rmap.name);
b4897fa5 6498 route_map_counter_decrement(
6499 bgp_static->rmap.map);
e2a86ad9
DS
6500 bgp_static->rmap.name =
6501 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6502 bgp_static->rmap.map =
6503 route_map_lookup_by_name(rmap);
b4897fa5 6504 route_map_counter_increment(
6505 bgp_static->rmap.map);
e2a86ad9 6506 } else {
0a22ddfb
QY
6507 XFREE(MTYPE_ROUTE_MAP_NAME,
6508 bgp_static->rmap.name);
b4897fa5 6509 route_map_counter_decrement(
6510 bgp_static->rmap.map);
e2a86ad9
DS
6511 bgp_static->rmap.map = NULL;
6512 bgp_static->valid = 0;
6513 }
9bcb3eef 6514 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6515 } else {
6516 /* New configuration. */
6517 bgp_static = bgp_static_new();
6518 bgp_static->backdoor = backdoor;
6519 bgp_static->valid = 0;
6520 bgp_static->igpmetric = 0;
975a328e 6521 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6522 bgp_static->label_index = label_index;
718e3744 6523
e2a86ad9 6524 if (rmap) {
0a22ddfb
QY
6525 XFREE(MTYPE_ROUTE_MAP_NAME,
6526 bgp_static->rmap.name);
b4897fa5 6527 route_map_counter_decrement(
6528 bgp_static->rmap.map);
e2a86ad9
DS
6529 bgp_static->rmap.name =
6530 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6531 bgp_static->rmap.map =
6532 route_map_lookup_by_name(rmap);
b4897fa5 6533 route_map_counter_increment(
6534 bgp_static->rmap.map);
e2a86ad9 6535 }
9bcb3eef 6536 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6537 }
d62a17ae 6538
e2a86ad9
DS
6539 bgp_static->valid = 1;
6540 if (need_update)
6541 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6542
e2a86ad9
DS
6543 if (!bgp_static->backdoor)
6544 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6545 }
d62a17ae 6546
585f1adc 6547 return CMD_SUCCESS;
d62a17ae 6548}
6549
6550void bgp_static_add(struct bgp *bgp)
6551{
6552 afi_t afi;
6553 safi_t safi;
9bcb3eef
DS
6554 struct bgp_dest *dest;
6555 struct bgp_dest *rm;
d62a17ae 6556 struct bgp_table *table;
6557 struct bgp_static *bgp_static;
6558
47fc6261 6559 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6560 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6561 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6562 dest = bgp_route_next(dest)) {
6563 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6564 continue;
ea47320b 6565
05c7a1cc
QY
6566 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6567 || (safi == SAFI_EVPN)) {
9bcb3eef 6568 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6569
6570 for (rm = bgp_table_top(table); rm;
6571 rm = bgp_route_next(rm)) {
a78beeb5 6572 bgp_static =
9bcb3eef 6573 bgp_dest_get_bgp_static_info(
5a8ba9fc 6574 rm);
9bcb3eef
DS
6575 bgp_static_update_safi(
6576 bgp, bgp_dest_get_prefix(rm),
6577 bgp_static, afi, safi);
d62a17ae 6578 }
05c7a1cc 6579 } else {
5a8ba9fc 6580 bgp_static_update(
9bcb3eef
DS
6581 bgp, bgp_dest_get_prefix(dest),
6582 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6583 safi);
ea47320b 6584 }
05c7a1cc 6585 }
47fc6261 6586 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6587}
6588
718e3744 6589/* Called from bgp_delete(). Delete all static routes from the BGP
6590 instance. */
d62a17ae 6591void bgp_static_delete(struct bgp *bgp)
6592{
6593 afi_t afi;
6594 safi_t safi;
9bcb3eef
DS
6595 struct bgp_dest *dest;
6596 struct bgp_dest *rm;
d62a17ae 6597 struct bgp_table *table;
6598 struct bgp_static *bgp_static;
6599
05c7a1cc 6600 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6601 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6602 dest = bgp_route_next(dest)) {
6603 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6604 continue;
ea47320b 6605
05c7a1cc
QY
6606 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6607 || (safi == SAFI_EVPN)) {
9bcb3eef 6608 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6609
6610 for (rm = bgp_table_top(table); rm;
6611 rm = bgp_route_next(rm)) {
a78beeb5 6612 bgp_static =
9bcb3eef 6613 bgp_dest_get_bgp_static_info(
5a8ba9fc 6614 rm);
c7d14ba6
PG
6615 if (!bgp_static)
6616 continue;
6617
05c7a1cc 6618 bgp_static_withdraw_safi(
9bcb3eef 6619 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6620 AFI_IP, safi,
6621 (struct prefix_rd *)
9bcb3eef
DS
6622 bgp_dest_get_prefix(
6623 dest));
ea47320b 6624 bgp_static_free(bgp_static);
811c6797 6625 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6626 NULL);
811c6797 6627 bgp_dest_unlock_node(rm);
d62a17ae 6628 }
05c7a1cc 6629 } else {
9bcb3eef 6630 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6631 bgp_static_withdraw(bgp,
9bcb3eef 6632 bgp_dest_get_prefix(dest),
b54892e0 6633 afi, safi);
05c7a1cc 6634 bgp_static_free(bgp_static);
9bcb3eef
DS
6635 bgp_dest_set_bgp_static_info(dest, NULL);
6636 bgp_dest_unlock_node(dest);
ea47320b 6637 }
05c7a1cc 6638 }
d62a17ae 6639}
6640
6641void bgp_static_redo_import_check(struct bgp *bgp)
6642{
6643 afi_t afi;
6644 safi_t safi;
9bcb3eef
DS
6645 struct bgp_dest *dest;
6646 struct bgp_dest *rm;
d62a17ae 6647 struct bgp_table *table;
6648 struct bgp_static *bgp_static;
6649
6650 /* Use this flag to force reprocessing of the route */
892fedb6 6651 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6652 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6653 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6654 dest = bgp_route_next(dest)) {
6655 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6656 continue;
ea47320b 6657
05c7a1cc
QY
6658 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6659 || (safi == SAFI_EVPN)) {
9bcb3eef 6660 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6661
6662 for (rm = bgp_table_top(table); rm;
6663 rm = bgp_route_next(rm)) {
a78beeb5 6664 bgp_static =
9bcb3eef 6665 bgp_dest_get_bgp_static_info(
5a8ba9fc 6666 rm);
9bcb3eef
DS
6667 bgp_static_update_safi(
6668 bgp, bgp_dest_get_prefix(rm),
6669 bgp_static, afi, safi);
d62a17ae 6670 }
05c7a1cc 6671 } else {
9bcb3eef
DS
6672 bgp_static = bgp_dest_get_bgp_static_info(dest);
6673 bgp_static_update(bgp,
6674 bgp_dest_get_prefix(dest),
6675 bgp_static, afi, safi);
ea47320b 6676 }
05c7a1cc
QY
6677 }
6678 }
892fedb6 6679 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6680}
6681
6682static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6683 safi_t safi)
6684{
6685 struct bgp_table *table;
9bcb3eef 6686 struct bgp_dest *dest;
40381db7 6687 struct bgp_path_info *pi;
d62a17ae 6688
dfb6fd1d
NT
6689 /* Do not install the aggregate route if BGP is in the
6690 * process of termination.
6691 */
892fedb6
DA
6692 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6693 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6694 return;
6695
d62a17ae 6696 table = bgp->rib[afi][safi];
9bcb3eef
DS
6697 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6698 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6699 if (pi->peer == bgp->peer_self
6700 && ((pi->type == ZEBRA_ROUTE_BGP
6701 && pi->sub_type == BGP_ROUTE_STATIC)
6702 || (pi->type != ZEBRA_ROUTE_BGP
6703 && pi->sub_type
d62a17ae 6704 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6705 bgp_aggregate_decrement(
6706 bgp, bgp_dest_get_prefix(dest), pi, afi,
6707 safi);
40381db7 6708 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6709 bgp_path_info_delete(dest, pi);
6710 bgp_process(bgp, dest, afi, safi);
d62a17ae 6711 }
6712 }
6713 }
ad4cbda1 6714}
6715
6716/*
6717 * Purge all networks and redistributed routes from routing table.
6718 * Invoked upon the instance going down.
6719 */
d62a17ae 6720void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6721{
d62a17ae 6722 afi_t afi;
6723 safi_t safi;
ad4cbda1 6724
05c7a1cc
QY
6725 FOREACH_AFI_SAFI (afi, safi)
6726 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6727}
6728
137446f9
LB
6729/*
6730 * gpz 110624
6731 * Currently this is used to set static routes for VPN and ENCAP.
6732 * I think it can probably be factored with bgp_static_set.
6733 */
d62a17ae 6734int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6735 const char *ip_str, const char *rd_str,
6736 const char *label_str, const char *rmap_str,
6737 int evpn_type, const char *esi, const char *gwip,
6738 const char *ethtag, const char *routermac)
6739{
6740 VTY_DECLVAR_CONTEXT(bgp, bgp);
6741 int ret;
6742 struct prefix p;
6743 struct prefix_rd prd;
9bcb3eef
DS
6744 struct bgp_dest *pdest;
6745 struct bgp_dest *dest;
d62a17ae 6746 struct bgp_table *table;
6747 struct bgp_static *bgp_static;
6748 mpls_label_t label = MPLS_INVALID_LABEL;
6749 struct prefix gw_ip;
6750
6751 /* validate ip prefix */
6752 ret = str2prefix(ip_str, &p);
6753 if (!ret) {
6754 vty_out(vty, "%% Malformed prefix\n");
6755 return CMD_WARNING_CONFIG_FAILED;
6756 }
6757 apply_mask(&p);
6758 if ((afi == AFI_L2VPN)
6759 && (bgp_build_evpn_prefix(evpn_type,
6760 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6761 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6762 return CMD_WARNING_CONFIG_FAILED;
6763 }
718e3744 6764
d62a17ae 6765 ret = str2prefix_rd(rd_str, &prd);
6766 if (!ret) {
6767 vty_out(vty, "%% Malformed rd\n");
6768 return CMD_WARNING_CONFIG_FAILED;
6769 }
718e3744 6770
d62a17ae 6771 if (label_str) {
6772 unsigned long label_val;
6773 label_val = strtoul(label_str, NULL, 10);
6774 encode_label(label_val, &label);
6775 }
9bedbb1e 6776
d62a17ae 6777 if (safi == SAFI_EVPN) {
6778 if (esi && str2esi(esi, NULL) == 0) {
6779 vty_out(vty, "%% Malformed ESI\n");
6780 return CMD_WARNING_CONFIG_FAILED;
6781 }
6782 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6783 vty_out(vty, "%% Malformed Router MAC\n");
6784 return CMD_WARNING_CONFIG_FAILED;
6785 }
6786 if (gwip) {
6006b807 6787 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6788 ret = str2prefix(gwip, &gw_ip);
6789 if (!ret) {
6790 vty_out(vty, "%% Malformed GatewayIp\n");
6791 return CMD_WARNING_CONFIG_FAILED;
6792 }
6793 if ((gw_ip.family == AF_INET
3714a385 6794 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6795 (struct prefix_evpn *)&p))
6796 || (gw_ip.family == AF_INET6
3714a385 6797 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6798 (struct prefix_evpn *)&p))) {
6799 vty_out(vty,
6800 "%% GatewayIp family differs with IP prefix\n");
6801 return CMD_WARNING_CONFIG_FAILED;
6802 }
6803 }
6804 }
9bcb3eef
DS
6805 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6806 if (!bgp_dest_has_bgp_path_info_data(pdest))
6807 bgp_dest_set_bgp_table_info(pdest,
67009e22 6808 bgp_table_init(bgp, afi, safi));
9bcb3eef 6809 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6810
9bcb3eef 6811 dest = bgp_node_get(table, &p);
d62a17ae 6812
9bcb3eef 6813 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6814 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6815 bgp_dest_unlock_node(dest);
d62a17ae 6816 } else {
6817 /* New configuration. */
6818 bgp_static = bgp_static_new();
6819 bgp_static->backdoor = 0;
6820 bgp_static->valid = 0;
6821 bgp_static->igpmetric = 0;
975a328e 6822 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6823 bgp_static->label = label;
6824 bgp_static->prd = prd;
6825
6826 if (rmap_str) {
0a22ddfb 6827 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6828 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6829 bgp_static->rmap.name =
6830 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6831 bgp_static->rmap.map =
6832 route_map_lookup_by_name(rmap_str);
b4897fa5 6833 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6834 }
718e3744 6835
d62a17ae 6836 if (safi == SAFI_EVPN) {
6837 if (esi) {
6838 bgp_static->eth_s_id =
6839 XCALLOC(MTYPE_ATTR,
0a50c248 6840 sizeof(esi_t));
d62a17ae 6841 str2esi(esi, bgp_static->eth_s_id);
6842 }
6843 if (routermac) {
6844 bgp_static->router_mac =
28328ea9 6845 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6846 (void)prefix_str2mac(routermac,
6847 bgp_static->router_mac);
d62a17ae 6848 }
6849 if (gwip)
6850 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6851 }
9bcb3eef 6852 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6853
d62a17ae 6854 bgp_static->valid = 1;
6855 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6856 }
718e3744 6857
d62a17ae 6858 return CMD_SUCCESS;
718e3744 6859}
6860
6861/* Configure static BGP network. */
d62a17ae 6862int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6863 const char *ip_str, const char *rd_str,
6864 const char *label_str, int evpn_type, const char *esi,
6865 const char *gwip, const char *ethtag)
6866{
6867 VTY_DECLVAR_CONTEXT(bgp, bgp);
6868 int ret;
6869 struct prefix p;
6870 struct prefix_rd prd;
9bcb3eef
DS
6871 struct bgp_dest *pdest;
6872 struct bgp_dest *dest;
d62a17ae 6873 struct bgp_table *table;
6874 struct bgp_static *bgp_static;
6875 mpls_label_t label = MPLS_INVALID_LABEL;
6876
6877 /* Convert IP prefix string to struct prefix. */
6878 ret = str2prefix(ip_str, &p);
6879 if (!ret) {
6880 vty_out(vty, "%% Malformed prefix\n");
6881 return CMD_WARNING_CONFIG_FAILED;
6882 }
6883 apply_mask(&p);
6884 if ((afi == AFI_L2VPN)
6885 && (bgp_build_evpn_prefix(evpn_type,
6886 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6887 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6888 return CMD_WARNING_CONFIG_FAILED;
6889 }
6890 ret = str2prefix_rd(rd_str, &prd);
6891 if (!ret) {
6892 vty_out(vty, "%% Malformed rd\n");
6893 return CMD_WARNING_CONFIG_FAILED;
6894 }
718e3744 6895
d62a17ae 6896 if (label_str) {
6897 unsigned long label_val;
6898 label_val = strtoul(label_str, NULL, 10);
6899 encode_label(label_val, &label);
6900 }
718e3744 6901
9bcb3eef
DS
6902 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6903 if (!bgp_dest_has_bgp_path_info_data(pdest))
6904 bgp_dest_set_bgp_table_info(pdest,
67009e22 6905 bgp_table_init(bgp, afi, safi));
d62a17ae 6906 else
9bcb3eef
DS
6907 bgp_dest_unlock_node(pdest);
6908 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6909
9bcb3eef 6910 dest = bgp_node_lookup(table, &p);
6b0655a2 6911
9bcb3eef 6912 if (dest) {
d62a17ae 6913 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6914
9bcb3eef 6915 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6916 bgp_static_free(bgp_static);
9bcb3eef
DS
6917 bgp_dest_set_bgp_static_info(dest, NULL);
6918 bgp_dest_unlock_node(dest);
6919 bgp_dest_unlock_node(dest);
d62a17ae 6920 } else
6921 vty_out(vty, "%% Can't find the route\n");
6922
6923 return CMD_SUCCESS;
6924}
6925
6926static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6927 const char *rmap_name)
6928{
6929 VTY_DECLVAR_CONTEXT(bgp, bgp);
6930 struct bgp_rmap *rmap;
6931
6932 rmap = &bgp->table_map[afi][safi];
6933 if (rmap_name) {
0a22ddfb 6934 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6935 route_map_counter_decrement(rmap->map);
d62a17ae 6936 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6937 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6938 route_map_counter_increment(rmap->map);
d62a17ae 6939 } else {
0a22ddfb 6940 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6941 route_map_counter_decrement(rmap->map);
d62a17ae 6942 rmap->map = NULL;
6943 }
73ac8160 6944
d62a17ae 6945 if (bgp_fibupd_safi(safi))
6946 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6947
d62a17ae 6948 return CMD_SUCCESS;
73ac8160
DS
6949}
6950
d62a17ae 6951static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6952 const char *rmap_name)
73ac8160 6953{
d62a17ae 6954 VTY_DECLVAR_CONTEXT(bgp, bgp);
6955 struct bgp_rmap *rmap;
73ac8160 6956
d62a17ae 6957 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6958 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6959 route_map_counter_decrement(rmap->map);
d62a17ae 6960 rmap->map = NULL;
73ac8160 6961
d62a17ae 6962 if (bgp_fibupd_safi(safi))
6963 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6964
d62a17ae 6965 return CMD_SUCCESS;
73ac8160
DS
6966}
6967
2b791107 6968void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6969 safi_t safi)
73ac8160 6970{
d62a17ae 6971 if (bgp->table_map[afi][safi].name) {
d62a17ae 6972 vty_out(vty, " table-map %s\n",
6973 bgp->table_map[afi][safi].name);
6974 }
73ac8160
DS
6975}
6976
73ac8160
DS
6977DEFUN (bgp_table_map,
6978 bgp_table_map_cmd,
6979 "table-map WORD",
6980 "BGP table to RIB route download filter\n"
6981 "Name of the route map\n")
6982{
d62a17ae 6983 int idx_word = 1;
6984 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6985 argv[idx_word]->arg);
73ac8160
DS
6986}
6987DEFUN (no_bgp_table_map,
6988 no_bgp_table_map_cmd,
6989 "no table-map WORD",
3a2d747c 6990 NO_STR
73ac8160
DS
6991 "BGP table to RIB route download filter\n"
6992 "Name of the route map\n")
6993{
d62a17ae 6994 int idx_word = 2;
6995 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6996 argv[idx_word]->arg);
73ac8160
DS
6997}
6998
585f1adc
IR
6999DEFPY(bgp_network,
7000 bgp_network_cmd,
7001 "[no] network \
7002 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 7003 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
7004 backdoor$backdoor}]",
7005 NO_STR
7006 "Specify a network to announce via BGP\n"
7007 "IPv4 prefix\n"
7008 "Network number\n"
7009 "Network mask\n"
7010 "Network mask\n"
7011 "Route-map to modify the attributes\n"
7012 "Name of the route map\n"
7013 "Label index to associate with the prefix\n"
7014 "Label index value\n"
7015 "Specify a BGP backdoor route\n")
7016{
7017 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
7018
7019 if (address_str) {
7020 int ret;
718e3744 7021
e2a86ad9 7022 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
7023 addr_prefix_str,
7024 sizeof(addr_prefix_str));
e2a86ad9
DS
7025 if (!ret) {
7026 vty_out(vty, "%% Inconsistent address and mask\n");
7027 return CMD_WARNING_CONFIG_FAILED;
7028 }
d62a17ae 7029 }
718e3744 7030
585f1adc
IR
7031 return bgp_static_set(
7032 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
7033 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
7034 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 7035}
7036
585f1adc
IR
7037DEFPY(ipv6_bgp_network,
7038 ipv6_bgp_network_cmd,
7039 "[no] network X:X::X:X/M$prefix \
70dd370f 7040 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
7041 NO_STR
7042 "Specify a network to announce via BGP\n"
7043 "IPv6 prefix\n"
7044 "Route-map to modify the attributes\n"
7045 "Name of the route map\n"
7046 "Label index to associate with the prefix\n"
7047 "Label index value\n")
37a87b8f 7048{
585f1adc
IR
7049 return bgp_static_set(
7050 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7051 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7052}
7053
d62a17ae 7054static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7055{
d62a17ae 7056 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7057}
7058
d62a17ae 7059static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7060{
365ab2e7
RZ
7061 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7062 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7063 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7064 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7065 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7066}
718e3744 7067
365ab2e7
RZ
7068/**
7069 * Helper function to avoid repeated code: prepare variables for a
7070 * `route_map_apply` call.
7071 *
7072 * \returns `true` on route map match, otherwise `false`.
7073 */
7074static bool aggr_suppress_map_test(struct bgp *bgp,
7075 struct bgp_aggregate *aggregate,
7076 struct bgp_path_info *pi)
7077{
7078 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7079 route_map_result_t rmr = RMAP_DENYMATCH;
7080 struct bgp_path_info rmap_path = {};
7081 struct attr attr = {};
7082
7083 /* No route map entries created, just don't match. */
7084 if (aggregate->suppress_map == NULL)
7085 return false;
7086
7087 /* Call route map matching and return result. */
7088 attr.aspath = aspath_empty();
7089 rmap_path.peer = bgp->peer_self;
7090 rmap_path.attr = &attr;
7091
7092 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7093 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7094 bgp->peer_self->rmap_type = 0;
7095
7096 bgp_attr_flush(&attr);
afb254d7 7097 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7098
7099 return rmr == RMAP_PERMITMATCH;
7100}
7101
4056a5f6
RZ
7102/** Test whether the aggregation has suppressed this path or not. */
7103static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7104 struct bgp_path_info *pi)
7105{
7106 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7107 return false;
7108
7109 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7110}
7111
7112/**
7113 * Suppress this path and keep the reference.
7114 *
7115 * \returns `true` if needs processing otherwise `false`.
7116 */
7117static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7118 struct bgp_path_info *pi)
7119{
7120 struct bgp_path_info_extra *pie;
7121
7122 /* Path is already suppressed by this aggregation. */
7123 if (aggr_suppress_exists(aggregate, pi))
7124 return false;
7125
7126 pie = bgp_path_info_extra_get(pi);
7127
7128 /* This is the first suppression, allocate memory and list it. */
7129 if (pie->aggr_suppressors == NULL)
7130 pie->aggr_suppressors = list_new();
7131
7132 listnode_add(pie->aggr_suppressors, aggregate);
7133
7134 /* Only mark for processing if suppressed. */
7135 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7136 if (BGP_DEBUG(update, UPDATE_OUT))
7137 zlog_debug("aggregate-address suppressing: %pFX",
7138 bgp_dest_get_prefix(pi->net));
7139
4056a5f6
RZ
7140 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7141 return true;
7142 }
7143
7144 return false;
7145}
7146
7147/**
7148 * Unsuppress this path and remove the reference.
7149 *
7150 * \returns `true` if needs processing otherwise `false`.
7151 */
7152static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7153 struct bgp_path_info *pi)
7154{
7155 /* Path wasn't suppressed. */
7156 if (!aggr_suppress_exists(aggregate, pi))
7157 return false;
7158
7159 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7160
7161 /* Unsuppress and free extra memory if last item. */
7162 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7163 if (BGP_DEBUG(update, UPDATE_OUT))
7164 zlog_debug("aggregate-address unsuppressing: %pFX",
7165 bgp_dest_get_prefix(pi->net));
7166
4056a5f6
RZ
7167 list_delete(&pi->extra->aggr_suppressors);
7168 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7169 return true;
7170 }
7171
7172 return false;
7173}
7174
3dc339cd
DA
7175static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7176 struct aspath *aspath,
7177 struct community *comm,
7178 struct ecommunity *ecomm,
7179 struct lcommunity *lcomm)
eaaf8adb
DS
7180{
7181 static struct aspath *ae = NULL;
7182
7183 if (!ae)
7184 ae = aspath_empty();
7185
40381db7 7186 if (!pi)
3dc339cd 7187 return false;
eaaf8adb 7188
40381db7 7189 if (origin != pi->attr->origin)
3dc339cd 7190 return false;
eaaf8adb 7191
40381db7 7192 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7193 return false;
29f7d023 7194
9a706b42 7195 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7196 return false;
eaaf8adb 7197
b53e67a3 7198 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7199 return false;
eaaf8adb 7200
1bcf3a96 7201 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7202 return false;
dd18c5a9 7203
40381db7 7204 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7205 return false;
7ce8a8e0 7206
3dc339cd 7207 return true;
eaaf8adb
DS
7208}
7209
5f040085
DS
7210static void bgp_aggregate_install(
7211 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7212 uint8_t origin, struct aspath *aspath, struct community *community,
7213 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7214 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7215{
9bcb3eef 7216 struct bgp_dest *dest;
c701010e 7217 struct bgp_table *table;
6f94b685 7218 struct bgp_path_info *pi, *orig, *new;
20894f50 7219 struct attr *attr;
c701010e
DS
7220
7221 table = bgp->rib[afi][safi];
7222
9bcb3eef 7223 dest = bgp_node_get(table, p);
eaaf8adb 7224
9bcb3eef 7225 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7226 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7227 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7228 break;
7229
6aabb15d
RZ
7230 /*
7231 * If we have paths with different MEDs, then don't install
7232 * (or uninstall) the aggregate route.
7233 */
7234 if (aggregate->match_med && aggregate->med_mismatched)
7235 goto uninstall_aggregate_route;
7236
c701010e 7237 if (aggregate->count > 0) {
eaaf8adb
DS
7238 /*
7239 * If the aggregate information has not changed
7240 * no need to re-install it again.
7241 */
6f94b685 7242 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7243 ecommunity, lcommunity)) {
9bcb3eef 7244 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7245
7246 if (aspath)
7247 aspath_free(aspath);
7248 if (community)
3c1f53de 7249 community_free(&community);
3da2cc32
DS
7250 if (ecommunity)
7251 ecommunity_free(&ecommunity);
dd18c5a9
DS
7252 if (lcommunity)
7253 lcommunity_free(&lcommunity);
eaaf8adb
DS
7254
7255 return;
7256 }
7257
7258 /*
7259 * Mark the old as unusable
7260 */
40381db7 7261 if (pi)
9bcb3eef 7262 bgp_path_info_delete(dest, pi);
eaaf8adb 7263
20894f50
DA
7264 attr = bgp_attr_aggregate_intern(
7265 bgp, origin, aspath, community, ecommunity, lcommunity,
7266 aggregate, atomic_aggregate, p);
7267
7268 if (!attr) {
7269 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7270 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7271 zlog_debug("%s: %pFX null attribute", __func__,
7272 p);
20894f50
DA
7273 return;
7274 }
7275
3da2cc32 7276 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7277 bgp->peer_self, attr, dest);
20894f50 7278
1defdda8 7279 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7280
9bcb3eef
DS
7281 bgp_path_info_add(dest, new);
7282 bgp_process(bgp, dest, afi, safi);
c701010e 7283 } else {
6aabb15d 7284 uninstall_aggregate_route:
6f94b685 7285 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7286 if (pi->peer == bgp->peer_self
7287 && pi->type == ZEBRA_ROUTE_BGP
7288 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7289 break;
7290
7291 /* Withdraw static BGP route from routing table. */
40381db7 7292 if (pi) {
9bcb3eef
DS
7293 bgp_path_info_delete(dest, pi);
7294 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7295 }
7296 }
7297
9bcb3eef 7298 bgp_dest_unlock_node(dest);
c701010e
DS
7299}
7300
6aabb15d
RZ
7301/**
7302 * Check if the current path has different MED than other known paths.
7303 *
7304 * \returns `true` if the MED matched the others else `false`.
7305 */
7306static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7307 struct bgp *bgp, struct bgp_path_info *pi)
7308{
7309 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7310
7311 /* This is the first route being analyzed. */
7312 if (!aggregate->med_initialized) {
7313 aggregate->med_initialized = true;
7314 aggregate->med_mismatched = false;
7315 aggregate->med_matched_value = cur_med;
7316 } else {
7317 /* Check if routes with different MED showed up. */
7318 if (cur_med != aggregate->med_matched_value)
7319 aggregate->med_mismatched = true;
7320 }
7321
7322 return !aggregate->med_mismatched;
7323}
7324
7325/**
7326 * Initializes and tests all routes in the aggregate address path for MED
7327 * values.
7328 *
7329 * \returns `true` if all MEDs are the same otherwise `false`.
7330 */
7331static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7332 struct bgp *bgp, const struct prefix *p,
7333 afi_t afi, safi_t safi)
7334{
7335 struct bgp_table *table = bgp->rib[afi][safi];
7336 const struct prefix *dest_p;
7337 struct bgp_dest *dest, *top;
7338 struct bgp_path_info *pi;
7339 bool med_matched = true;
7340
7341 aggregate->med_initialized = false;
7342
7343 top = bgp_node_get(table, p);
7344 for (dest = bgp_node_get(table, p); dest;
7345 dest = bgp_route_next_until(dest, top)) {
7346 dest_p = bgp_dest_get_prefix(dest);
7347 if (dest_p->prefixlen <= p->prefixlen)
7348 continue;
7349
7350 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7351 if (BGP_PATH_HOLDDOWN(pi))
7352 continue;
7353 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7354 continue;
7355 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7356 med_matched = false;
7357 break;
7358 }
7359 }
7360 if (!med_matched)
7361 break;
7362 }
7363 bgp_dest_unlock_node(top);
7364
7365 return med_matched;
7366}
7367
7368/**
7369 * Toggles the route suppression status for this aggregate address
7370 * configuration.
7371 */
4056a5f6
RZ
7372void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7373 struct bgp *bgp, const struct prefix *p,
7374 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7375{
7376 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7377 const struct prefix *dest_p;
7378 struct bgp_dest *dest, *top;
7379 struct bgp_path_info *pi;
7380 bool toggle_suppression;
7381
7382 /* We've found a different MED we must revert any suppressed routes. */
7383 top = bgp_node_get(table, p);
7384 for (dest = bgp_node_get(table, p); dest;
7385 dest = bgp_route_next_until(dest, top)) {
7386 dest_p = bgp_dest_get_prefix(dest);
7387 if (dest_p->prefixlen <= p->prefixlen)
7388 continue;
7389
7390 toggle_suppression = false;
7391 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7392 if (BGP_PATH_HOLDDOWN(pi))
7393 continue;
7394 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7395 continue;
7396
6aabb15d
RZ
7397 /* We are toggling suppression back. */
7398 if (suppress) {
6aabb15d 7399 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7400 if (aggr_suppress_path(aggregate, pi))
7401 toggle_suppression = true;
6aabb15d
RZ
7402 continue;
7403 }
7404
6aabb15d 7405 /* Install route if there is no more suppression. */
4056a5f6 7406 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7407 toggle_suppression = true;
6aabb15d
RZ
7408 }
7409
7410 if (toggle_suppression)
7411 bgp_process(bgp, dest, afi, safi);
7412 }
7413 bgp_dest_unlock_node(top);
7414}
7415
7416/**
7417 * Aggregate address MED matching incremental test: this function is called
7418 * when the initial aggregation occurred and we are only testing a single
7419 * new path.
7420 *
7421 * In addition to testing and setting the MED validity it also installs back
7422 * suppressed routes (if summary is configured).
7423 *
7424 * Must not be called in `bgp_aggregate_route`.
7425 */
7426static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7427 struct bgp *bgp, const struct prefix *p,
7428 afi_t afi, safi_t safi,
7429 struct bgp_path_info *pi, bool is_adding)
7430{
7431 /* MED matching disabled. */
7432 if (!aggregate->match_med)
7433 return;
7434
7435 /* Aggregation with different MED, nothing to do. */
7436 if (aggregate->med_mismatched)
7437 return;
7438
7439 /*
7440 * Test the current entry:
7441 *
7442 * is_adding == true: if the new entry doesn't match then we must
7443 * install all suppressed routes.
7444 *
7445 * is_adding == false: if the entry being removed was the last
7446 * unmatching entry then we can suppress all routes.
7447 */
7448 if (!is_adding) {
7449 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7450 && aggregate->summary_only)
7451 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7452 safi, true);
7453 } else
7454 bgp_aggregate_med_match(aggregate, bgp, pi);
7455
7456 /* No mismatches, just quit. */
7457 if (!aggregate->med_mismatched)
7458 return;
7459
7460 /* Route summarization is disabled. */
7461 if (!aggregate->summary_only)
7462 return;
7463
7464 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7465}
7466
b5d58c32 7467/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7468void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7469 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7470{
7471 struct bgp_table *table;
9bcb3eef
DS
7472 struct bgp_dest *top;
7473 struct bgp_dest *dest;
d7c0a89a 7474 uint8_t origin;
d62a17ae 7475 struct aspath *aspath = NULL;
d62a17ae 7476 struct community *community = NULL;
3da2cc32 7477 struct ecommunity *ecommunity = NULL;
dd18c5a9 7478 struct lcommunity *lcommunity = NULL;
40381db7 7479 struct bgp_path_info *pi;
d62a17ae 7480 unsigned long match = 0;
d7c0a89a 7481 uint8_t atomic_aggregate = 0;
d62a17ae 7482
9f822fa2
S
7483 /* If the bgp instance is being deleted or self peer is deleted
7484 * then do not create aggregate route
7485 */
892fedb6
DA
7486 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7487 || (bgp->peer_self == NULL))
9f822fa2
S
7488 return;
7489
6aabb15d
RZ
7490 /* Initialize and test routes for MED difference. */
7491 if (aggregate->match_med)
7492 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7493
4056a5f6
RZ
7494 /*
7495 * Reset aggregate count: we might've been called from route map
7496 * update so in that case we must retest all more specific routes.
7497 *
7498 * \see `bgp_route_map_process_update`.
7499 */
7500 aggregate->count = 0;
7501 aggregate->incomplete_origin_count = 0;
7502 aggregate->incomplete_origin_count = 0;
7503 aggregate->egp_origin_count = 0;
7504
d62a17ae 7505 /* ORIGIN attribute: If at least one route among routes that are
7506 aggregated has ORIGIN with the value INCOMPLETE, then the
7507 aggregated route must have the ORIGIN attribute with the value
7508 INCOMPLETE. Otherwise, if at least one route among routes that
7509 are aggregated has ORIGIN with the value EGP, then the aggregated
7510 route must have the origin attribute with the value EGP. In all
7511 other case the value of the ORIGIN attribute of the aggregated
7512 route is INTERNAL. */
7513 origin = BGP_ORIGIN_IGP;
718e3744 7514
d62a17ae 7515 table = bgp->rib[afi][safi];
718e3744 7516
d62a17ae 7517 top = bgp_node_get(table, p);
9bcb3eef
DS
7518 for (dest = bgp_node_get(table, p); dest;
7519 dest = bgp_route_next_until(dest, top)) {
7520 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7521
9bcb3eef 7522 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7523 continue;
d62a17ae 7524
a77e2f4b
S
7525 /* If suppress fib is enabled and route not installed
7526 * in FIB, skip the route
7527 */
7528 if (!bgp_check_advertise(bgp, dest))
7529 continue;
7530
c2ff8b3e 7531 match = 0;
d62a17ae 7532
9bcb3eef 7533 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7534 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7535 continue;
718e3744 7536
40381db7 7537 if (pi->attr->flag
c2ff8b3e
DS
7538 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7539 atomic_aggregate = 1;
d62a17ae 7540
40381db7 7541 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7542 continue;
d62a17ae 7543
f273fef1
DS
7544 /*
7545 * summary-only aggregate route suppress
7546 * aggregated route announcements.
6aabb15d
RZ
7547 *
7548 * MED matching:
7549 * Don't create summaries if MED didn't match
7550 * otherwise neither the specific routes and the
7551 * aggregation will be announced.
f273fef1 7552 */
6aabb15d
RZ
7553 if (aggregate->summary_only
7554 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7555 if (aggr_suppress_path(aggregate, pi))
7556 match++;
d62a17ae 7557 }
c2ff8b3e 7558
365ab2e7
RZ
7559 /*
7560 * Suppress more specific routes that match the route
7561 * map results.
7562 *
7563 * MED matching:
7564 * Don't suppress routes if MED matching is enabled and
7565 * it mismatched otherwise we might end up with no
7566 * routes for this path.
7567 */
7568 if (aggregate->suppress_map_name
7569 && AGGREGATE_MED_VALID(aggregate)
7570 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7571 if (aggr_suppress_path(aggregate, pi))
7572 match++;
d62a17ae 7573 }
c2ff8b3e
DS
7574
7575 aggregate->count++;
7576
f273fef1
DS
7577 /*
7578 * If at least one route among routes that are
7579 * aggregated has ORIGIN with the value INCOMPLETE,
7580 * then the aggregated route MUST have the ORIGIN
7581 * attribute with the value INCOMPLETE. Otherwise, if
7582 * at least one route among routes that are aggregated
7583 * has ORIGIN with the value EGP, then the aggregated
7584 * route MUST have the ORIGIN attribute with the value
7585 * EGP.
7586 */
fc968841
NT
7587 switch (pi->attr->origin) {
7588 case BGP_ORIGIN_INCOMPLETE:
7589 aggregate->incomplete_origin_count++;
7590 break;
7591 case BGP_ORIGIN_EGP:
7592 aggregate->egp_origin_count++;
7593 break;
7594 default:
7595 /*Do nothing.
7596 */
7597 break;
7598 }
c2ff8b3e
DS
7599
7600 if (!aggregate->as_set)
7601 continue;
7602
f273fef1
DS
7603 /*
7604 * as-set aggregate route generate origin, as path,
7605 * and community aggregation.
7606 */
fc968841
NT
7607 /* Compute aggregate route's as-path.
7608 */
ef51a7d8 7609 bgp_compute_aggregate_aspath_hash(aggregate,
7610 pi->attr->aspath);
c2ff8b3e 7611
fc968841
NT
7612 /* Compute aggregate route's community.
7613 */
9a706b42 7614 if (bgp_attr_get_community(pi->attr))
21fec674 7615 bgp_compute_aggregate_community_hash(
9a706b42
DA
7616 aggregate,
7617 bgp_attr_get_community(pi->attr));
dd18c5a9 7618
fc968841
NT
7619 /* Compute aggregate route's extended community.
7620 */
b53e67a3 7621 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7622 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7623 aggregate,
7624 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7625
7626 /* Compute aggregate route's large community.
7627 */
1bcf3a96 7628 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7629 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7630 aggregate,
7631 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7632 }
c2ff8b3e 7633 if (match)
9bcb3eef 7634 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7635 }
21fec674 7636 if (aggregate->as_set) {
ef51a7d8 7637 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7638 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7639 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7640 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7641 }
7642
f1eb1f05 7643
9bcb3eef 7644 bgp_dest_unlock_node(top);
718e3744 7645
718e3744 7646
fc968841
NT
7647 if (aggregate->incomplete_origin_count > 0)
7648 origin = BGP_ORIGIN_INCOMPLETE;
7649 else if (aggregate->egp_origin_count > 0)
7650 origin = BGP_ORIGIN_EGP;
d62a17ae 7651
229757f1
DA
7652 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7653 origin = aggregate->origin;
7654
fc968841
NT
7655 if (aggregate->as_set) {
7656 if (aggregate->aspath)
7657 /* Retrieve aggregate route's as-path.
7658 */
7659 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7660
fc968841
NT
7661 if (aggregate->community)
7662 /* Retrieve aggregate route's community.
7663 */
7664 community = community_dup(aggregate->community);
3da2cc32 7665
fc968841
NT
7666 if (aggregate->ecommunity)
7667 /* Retrieve aggregate route's ecommunity.
7668 */
7669 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7670
fc968841
NT
7671 if (aggregate->lcommunity)
7672 /* Retrieve aggregate route's lcommunity.
7673 */
7674 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7675 }
718e3744 7676
c701010e 7677 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7678 ecommunity, lcommunity, atomic_aggregate,
7679 aggregate);
718e3744 7680}
7681
5f040085
DS
7682void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7683 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7684{
7685 struct bgp_table *table;
9bcb3eef
DS
7686 struct bgp_dest *top;
7687 struct bgp_dest *dest;
40381db7 7688 struct bgp_path_info *pi;
3b7db173
DS
7689 unsigned long match;
7690
7691 table = bgp->rib[afi][safi];
7692
7693 /* If routes exists below this node, generate aggregate routes. */
7694 top = bgp_node_get(table, p);
9bcb3eef
DS
7695 for (dest = bgp_node_get(table, p); dest;
7696 dest = bgp_route_next_until(dest, top)) {
7697 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7698
9bcb3eef 7699 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7700 continue;
7701 match = 0;
7702
9bcb3eef 7703 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7704 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7705 continue;
7706
40381db7 7707 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7708 continue;
7709
92b175bd
RZ
7710 /*
7711 * This route is suppressed: attempt to unsuppress it.
7712 *
7713 * `aggr_unsuppress_path` will fail if this particular
7714 * aggregate route was not the suppressor.
7715 */
7716 if (pi->extra && pi->extra->aggr_suppressors &&
7717 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7718 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7719 match++;
3b7db173 7720 }
365ab2e7 7721
3b7db173 7722 aggregate->count--;
fc968841
NT
7723
7724 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7725 aggregate->incomplete_origin_count--;
7726 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7727 aggregate->egp_origin_count--;
7728
7729 if (aggregate->as_set) {
7730 /* Remove as-path from aggregate.
7731 */
ef51a7d8 7732 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7733 aggregate,
7734 pi->attr->aspath);
7735
9a706b42 7736 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7737 /* Remove community from aggregate.
7738 */
21fec674 7739 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7740 aggregate,
7741 bgp_attr_get_community(
7742 pi->attr));
fc968841 7743
b53e67a3 7744 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7745 /* Remove ecommunity from aggregate.
7746 */
4edd83f9 7747 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7748 aggregate,
7749 bgp_attr_get_ecommunity(
7750 pi->attr));
fc968841 7751
1bcf3a96 7752 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7753 /* Remove lcommunity from aggregate.
7754 */
f1eb1f05 7755 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7756 aggregate,
7757 bgp_attr_get_lcommunity(
7758 pi->attr));
fc968841 7759 }
3b7db173
DS
7760 }
7761
7762 /* If this node was suppressed, process the change. */
7763 if (match)
9bcb3eef 7764 bgp_process(bgp, dest, afi, safi);
3b7db173 7765 }
f1eb1f05 7766 if (aggregate->as_set) {
ef51a7d8 7767 aspath_free(aggregate->aspath);
7768 aggregate->aspath = NULL;
21fec674 7769 if (aggregate->community)
7770 community_free(&aggregate->community);
4edd83f9 7771 if (aggregate->ecommunity)
7772 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7773 if (aggregate->lcommunity)
7774 lcommunity_free(&aggregate->lcommunity);
7775 }
7776
9bcb3eef 7777 bgp_dest_unlock_node(top);
3b7db173 7778}
718e3744 7779
5f040085
DS
7780static void bgp_add_route_to_aggregate(struct bgp *bgp,
7781 const struct prefix *aggr_p,
fc968841
NT
7782 struct bgp_path_info *pinew, afi_t afi,
7783 safi_t safi,
7784 struct bgp_aggregate *aggregate)
7785{
7786 uint8_t origin;
7787 struct aspath *aspath = NULL;
7788 uint8_t atomic_aggregate = 0;
7789 struct community *community = NULL;
7790 struct ecommunity *ecommunity = NULL;
7791 struct lcommunity *lcommunity = NULL;
7792
a4559740 7793 /* If the bgp instance is being deleted or self peer is deleted
7794 * then do not create aggregate route
7795 */
7796 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7797 || (bgp->peer_self == NULL))
7798 return;
7799
fc968841
NT
7800 /* ORIGIN attribute: If at least one route among routes that are
7801 * aggregated has ORIGIN with the value INCOMPLETE, then the
7802 * aggregated route must have the ORIGIN attribute with the value
7803 * INCOMPLETE. Otherwise, if at least one route among routes that
7804 * are aggregated has ORIGIN with the value EGP, then the aggregated
7805 * route must have the origin attribute with the value EGP. In all
7806 * other case the value of the ORIGIN attribute of the aggregated
7807 * route is INTERNAL.
7808 */
7809 origin = BGP_ORIGIN_IGP;
7810
7811 aggregate->count++;
7812
6aabb15d
RZ
7813 /*
7814 * This must be called before `summary` check to avoid
7815 * "suppressing" twice.
7816 */
7817 if (aggregate->match_med)
7818 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7819 pinew, true);
7820
7821 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7822 aggr_suppress_path(aggregate, pinew);
fc968841 7823
365ab2e7
RZ
7824 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7825 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7826 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7827
7828 switch (pinew->attr->origin) {
7829 case BGP_ORIGIN_INCOMPLETE:
7830 aggregate->incomplete_origin_count++;
7831 break;
7832 case BGP_ORIGIN_EGP:
7833 aggregate->egp_origin_count++;
7834 break;
7835 default:
7836 /* Do nothing.
7837 */
7838 break;
7839 }
7840
7841 if (aggregate->incomplete_origin_count > 0)
7842 origin = BGP_ORIGIN_INCOMPLETE;
7843 else if (aggregate->egp_origin_count > 0)
7844 origin = BGP_ORIGIN_EGP;
7845
229757f1
DA
7846 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7847 origin = aggregate->origin;
7848
fc968841
NT
7849 if (aggregate->as_set) {
7850 /* Compute aggregate route's as-path.
7851 */
7852 bgp_compute_aggregate_aspath(aggregate,
7853 pinew->attr->aspath);
7854
7855 /* Compute aggregate route's community.
7856 */
9a706b42 7857 if (bgp_attr_get_community(pinew->attr))
fc968841 7858 bgp_compute_aggregate_community(
9a706b42 7859 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7860
7861 /* Compute aggregate route's extended community.
7862 */
b53e67a3 7863 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7864 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7865 aggregate,
7866 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7867
7868 /* Compute aggregate route's large community.
7869 */
1bcf3a96 7870 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7871 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7872 aggregate,
7873 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7874
7875 /* Retrieve aggregate route's as-path.
7876 */
7877 if (aggregate->aspath)
7878 aspath = aspath_dup(aggregate->aspath);
7879
7880 /* Retrieve aggregate route's community.
7881 */
7882 if (aggregate->community)
7883 community = community_dup(aggregate->community);
7884
7885 /* Retrieve aggregate route's ecommunity.
7886 */
7887 if (aggregate->ecommunity)
7888 ecommunity = ecommunity_dup(aggregate->ecommunity);
7889
7890 /* Retrieve aggregate route's lcommunity.
7891 */
7892 if (aggregate->lcommunity)
7893 lcommunity = lcommunity_dup(aggregate->lcommunity);
7894 }
7895
7896 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7897 aspath, community, ecommunity,
7898 lcommunity, atomic_aggregate, aggregate);
7899}
7900
7901static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7902 safi_t safi,
7903 struct bgp_path_info *pi,
7904 struct bgp_aggregate *aggregate,
5f040085 7905 const struct prefix *aggr_p)
fc968841
NT
7906{
7907 uint8_t origin;
7908 struct aspath *aspath = NULL;
7909 uint8_t atomic_aggregate = 0;
7910 struct community *community = NULL;
7911 struct ecommunity *ecommunity = NULL;
7912 struct lcommunity *lcommunity = NULL;
7913 unsigned long match = 0;
7914
a4559740 7915 /* If the bgp instance is being deleted or self peer is deleted
7916 * then do not create aggregate route
7917 */
7918 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7919 || (bgp->peer_self == NULL))
7920 return;
7921
fc968841
NT
7922 if (BGP_PATH_HOLDDOWN(pi))
7923 return;
7924
7925 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7926 return;
7927
4056a5f6
RZ
7928 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7929 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7930 match++;
fc968841 7931
365ab2e7 7932 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7933 && aggr_suppress_map_test(bgp, aggregate, pi))
7934 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7935 match++;
fc968841 7936
6aabb15d 7937 /*
365ab2e7 7938 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7939 * "unsuppressing" twice.
7940 */
7941 if (aggregate->match_med)
7942 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7943 true);
7944
fc968841
NT
7945 if (aggregate->count > 0)
7946 aggregate->count--;
7947
7948 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7949 aggregate->incomplete_origin_count--;
7950 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7951 aggregate->egp_origin_count--;
7952
7953 if (aggregate->as_set) {
7954 /* Remove as-path from aggregate.
7955 */
7956 bgp_remove_aspath_from_aggregate(aggregate,
7957 pi->attr->aspath);
7958
9a706b42 7959 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7960 /* Remove community from aggregate.
7961 */
7962 bgp_remove_community_from_aggregate(
9a706b42 7963 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7964
b53e67a3 7965 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7966 /* Remove ecommunity from aggregate.
7967 */
7968 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7969 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7970
1bcf3a96 7971 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7972 /* Remove lcommunity from aggregate.
7973 */
7974 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7975 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7976 }
7977
7978 /* If this node was suppressed, process the change. */
7979 if (match)
7980 bgp_process(bgp, pi->net, afi, safi);
7981
7982 origin = BGP_ORIGIN_IGP;
7983 if (aggregate->incomplete_origin_count > 0)
7984 origin = BGP_ORIGIN_INCOMPLETE;
7985 else if (aggregate->egp_origin_count > 0)
7986 origin = BGP_ORIGIN_EGP;
7987
229757f1
DA
7988 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7989 origin = aggregate->origin;
7990
fc968841
NT
7991 if (aggregate->as_set) {
7992 /* Retrieve aggregate route's as-path.
7993 */
7994 if (aggregate->aspath)
7995 aspath = aspath_dup(aggregate->aspath);
7996
7997 /* Retrieve aggregate route's community.
7998 */
7999 if (aggregate->community)
8000 community = community_dup(aggregate->community);
8001
8002 /* Retrieve aggregate route's ecommunity.
8003 */
8004 if (aggregate->ecommunity)
8005 ecommunity = ecommunity_dup(aggregate->ecommunity);
8006
8007 /* Retrieve aggregate route's lcommunity.
8008 */
8009 if (aggregate->lcommunity)
8010 lcommunity = lcommunity_dup(aggregate->lcommunity);
8011 }
8012
8013 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
8014 aspath, community, ecommunity,
8015 lcommunity, atomic_aggregate, aggregate);
8016}
8017
5a1ae2c2 8018void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 8019 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 8020{
9bcb3eef
DS
8021 struct bgp_dest *child;
8022 struct bgp_dest *dest;
d62a17ae 8023 struct bgp_aggregate *aggregate;
8024 struct bgp_table *table;
718e3744 8025
d62a17ae 8026 table = bgp->aggregate[afi][safi];
f018db83 8027
d62a17ae 8028 /* No aggregates configured. */
8029 if (bgp_table_top_nolock(table) == NULL)
8030 return;
f018db83 8031
d62a17ae 8032 if (p->prefixlen == 0)
8033 return;
718e3744 8034
40381db7 8035 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 8036 return;
718e3744 8037
a77e2f4b
S
8038 /* If suppress fib is enabled and route not installed
8039 * in FIB, do not update the aggregate route
8040 */
8041 if (!bgp_check_advertise(bgp, pi->net))
8042 return;
8043
d62a17ae 8044 child = bgp_node_get(table, p);
718e3744 8045
d62a17ae 8046 /* Aggregate address configuration check. */
9bcb3eef
DS
8047 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8048 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8049
9bcb3eef
DS
8050 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8051 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8052 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8053 aggregate);
d62a17ae 8054 }
b1e62edd 8055 }
9bcb3eef 8056 bgp_dest_unlock_node(child);
718e3744 8057}
8058
5a1ae2c2 8059void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8060 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8061{
9bcb3eef
DS
8062 struct bgp_dest *child;
8063 struct bgp_dest *dest;
d62a17ae 8064 struct bgp_aggregate *aggregate;
8065 struct bgp_table *table;
718e3744 8066
d62a17ae 8067 table = bgp->aggregate[afi][safi];
718e3744 8068
d62a17ae 8069 /* No aggregates configured. */
8070 if (bgp_table_top_nolock(table) == NULL)
8071 return;
718e3744 8072
d62a17ae 8073 if (p->prefixlen == 0)
8074 return;
718e3744 8075
d62a17ae 8076 child = bgp_node_get(table, p);
718e3744 8077
d62a17ae 8078 /* Aggregate address configuration check. */
9bcb3eef
DS
8079 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8080 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8081
9bcb3eef
DS
8082 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8083 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8084 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8085 aggregate, dest_p);
d62a17ae 8086 }
b1e62edd 8087 }
9bcb3eef 8088 bgp_dest_unlock_node(child);
d62a17ae 8089}
718e3744 8090
718e3744 8091/* Aggregate route attribute. */
8092#define AGGREGATE_SUMMARY_ONLY 1
8093#define AGGREGATE_AS_SET 1
fb29348a 8094#define AGGREGATE_AS_UNSET 0
718e3744 8095
229757f1
DA
8096static const char *bgp_origin2str(uint8_t origin)
8097{
8098 switch (origin) {
8099 case BGP_ORIGIN_IGP:
8100 return "igp";
8101 case BGP_ORIGIN_EGP:
8102 return "egp";
8103 case BGP_ORIGIN_INCOMPLETE:
8104 return "incomplete";
8105 }
8106 return "n/a";
8107}
8108
fdeb5a81 8109static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8110{
8111 switch (v_state) {
fdeb5a81
DS
8112 case RPKI_NOT_BEING_USED:
8113 return "not used";
8114 case RPKI_VALID:
b5b99af8 8115 return "valid";
fdeb5a81 8116 case RPKI_NOTFOUND:
b5b99af8 8117 return "not found";
fdeb5a81 8118 case RPKI_INVALID:
b5b99af8 8119 return "invalid";
b5b99af8 8120 }
fdeb5a81
DS
8121
8122 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8123 return "ERROR";
8124}
8125
585f1adc
IR
8126static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8127 afi_t afi, safi_t safi)
718e3744 8128{
585f1adc
IR
8129 VTY_DECLVAR_CONTEXT(bgp, bgp);
8130 int ret;
8131 struct prefix p;
9bcb3eef 8132 struct bgp_dest *dest;
d62a17ae 8133 struct bgp_aggregate *aggregate;
718e3744 8134
585f1adc
IR
8135 /* Convert string to prefix structure. */
8136 ret = str2prefix(prefix_str, &p);
8137 if (!ret) {
8138 vty_out(vty, "Malformed prefix\n");
8139 return CMD_WARNING_CONFIG_FAILED;
8140 }
8141 apply_mask(&p);
a4559740 8142
d62a17ae 8143 /* Old configuration check. */
585f1adc 8144 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8145 if (!dest) {
585f1adc
IR
8146 vty_out(vty,
8147 "%% There is no aggregate-address configuration.\n");
8148 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8149 }
f6269b4f 8150
9bcb3eef 8151 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8152 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8153 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8154 NULL, NULL, 0, aggregate);
d62a17ae 8155
8156 /* Unlock aggregate address configuration. */
9bcb3eef 8157 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8158
8159 if (aggregate->community)
8160 community_free(&aggregate->community);
8161
8162 if (aggregate->community_hash) {
8163 /* Delete all communities in the hash.
8164 */
8165 hash_clean(aggregate->community_hash,
8166 bgp_aggr_community_remove);
8167 /* Free up the community_hash.
8168 */
8169 hash_free(aggregate->community_hash);
8170 }
8171
8172 if (aggregate->ecommunity)
8173 ecommunity_free(&aggregate->ecommunity);
8174
8175 if (aggregate->ecommunity_hash) {
8176 /* Delete all ecommunities in the hash.
8177 */
8178 hash_clean(aggregate->ecommunity_hash,
8179 bgp_aggr_ecommunity_remove);
8180 /* Free up the ecommunity_hash.
8181 */
8182 hash_free(aggregate->ecommunity_hash);
8183 }
8184
8185 if (aggregate->lcommunity)
8186 lcommunity_free(&aggregate->lcommunity);
8187
8188 if (aggregate->lcommunity_hash) {
8189 /* Delete all lcommunities in the hash.
8190 */
8191 hash_clean(aggregate->lcommunity_hash,
8192 bgp_aggr_lcommunity_remove);
8193 /* Free up the lcommunity_hash.
8194 */
8195 hash_free(aggregate->lcommunity_hash);
8196 }
8197
8198 if (aggregate->aspath)
8199 aspath_free(aggregate->aspath);
8200
8201 if (aggregate->aspath_hash) {
8202 /* Delete all as-paths in the hash.
8203 */
8204 hash_clean(aggregate->aspath_hash,
8205 bgp_aggr_aspath_remove);
8206 /* Free up the aspath_hash.
8207 */
8208 hash_free(aggregate->aspath_hash);
8209 }
8210
d62a17ae 8211 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8212 bgp_dest_unlock_node(dest);
8213 bgp_dest_unlock_node(dest);
d62a17ae 8214
585f1adc 8215 return CMD_SUCCESS;
d62a17ae 8216}
8217
585f1adc
IR
8218static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8219 safi_t safi, const char *rmap,
8220 uint8_t summary_only, uint8_t as_set,
8221 uint8_t origin, bool match_med,
8222 const char *suppress_map)
d62a17ae 8223{
585f1adc 8224 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8225 int ret;
585f1adc 8226 struct prefix p;
9bcb3eef 8227 struct bgp_dest *dest;
d62a17ae 8228 struct bgp_aggregate *aggregate;
fb29348a 8229 uint8_t as_set_new = as_set;
d62a17ae 8230
365ab2e7 8231 if (suppress_map && summary_only) {
585f1adc 8232 vty_out(vty,
365ab2e7 8233 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8234 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8235 }
8236
585f1adc
IR
8237 /* Convert string to prefix structure. */
8238 ret = str2prefix(prefix_str, &p);
8239 if (!ret) {
8240 vty_out(vty, "Malformed prefix\n");
8241 return CMD_WARNING_CONFIG_FAILED;
8242 }
8243 apply_mask(&p);
d62a17ae 8244
585f1adc
IR
8245 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8246 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8247 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8248 prefix_str);
8249 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8250 }
8251
d62a17ae 8252 /* Old configuration check. */
585f1adc 8253 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8254 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8255
20894f50 8256 if (aggregate) {
585f1adc 8257 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8258 /* try to remove the old entry */
585f1adc 8259 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8260 if (ret) {
585f1adc 8261 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8262 bgp_dest_unlock_node(dest);
585f1adc 8263 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8264 }
8265 }
718e3744 8266
d62a17ae 8267 /* Make aggregate address structure. */
8268 aggregate = bgp_aggregate_new();
8269 aggregate->summary_only = summary_only;
6aabb15d 8270 aggregate->match_med = match_med;
fb29348a
DA
8271
8272 /* Network operators MUST NOT locally generate any new
8273 * announcements containing AS_SET or AS_CONFED_SET. If they have
8274 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8275 * SHOULD withdraw those routes and re-announce routes for the
8276 * aggregate or component prefixes (i.e., the more-specific routes
8277 * subsumed by the previously aggregated route) without AS_SET
8278 * or AS_CONFED_SET in the updates.
8279 */
7f972cd8 8280 if (bgp->reject_as_sets) {
fb29348a
DA
8281 if (as_set == AGGREGATE_AS_SET) {
8282 as_set_new = AGGREGATE_AS_UNSET;
8283 zlog_warn(
63efca0e 8284 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8285 __func__);
585f1adc 8286 vty_out(vty,
fb29348a
DA
8287 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8288 }
8289 }
8290
8291 aggregate->as_set = as_set_new;
d62a17ae 8292 aggregate->safi = safi;
229757f1
DA
8293 /* Override ORIGIN attribute if defined.
8294 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8295 * to IGP which is not what rfc4271 says.
8296 * This enables the same behavior, optionally.
8297 */
8298 aggregate->origin = origin;
20894f50
DA
8299
8300 if (rmap) {
8301 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8302 route_map_counter_decrement(aggregate->rmap.map);
8303 aggregate->rmap.name =
8304 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8305 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8306 route_map_counter_increment(aggregate->rmap.map);
8307 }
365ab2e7
RZ
8308
8309 if (suppress_map) {
8310 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8311 route_map_counter_decrement(aggregate->suppress_map);
8312
8313 aggregate->suppress_map_name =
8314 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8315 aggregate->suppress_map =
8316 route_map_lookup_by_name(aggregate->suppress_map_name);
8317 route_map_counter_increment(aggregate->suppress_map);
8318 }
8319
9bcb3eef 8320 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8321
d62a17ae 8322 /* Aggregate address insert into BGP routing table. */
585f1adc 8323 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8324
585f1adc 8325 return CMD_SUCCESS;
718e3744 8326}
8327
585f1adc
IR
8328DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8329 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8330 "as-set$as_set_s"
8331 "|summary-only$summary_only"
cacba915 8332 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8333 "|origin <egp|igp|incomplete>$origin_s"
8334 "|matching-MED-only$match_med"
cacba915 8335 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8336 "}]",
8337 NO_STR
8338 "Configure BGP aggregate entries\n"
764402fe
DA
8339 "Aggregate prefix\n"
8340 "Aggregate address\n"
8341 "Aggregate mask\n"
585f1adc
IR
8342 "Generate AS set path information\n"
8343 "Filter more specific routes from updates\n"
8344 "Apply route map to aggregate network\n"
8345 "Route map name\n"
8346 "BGP origin code\n"
8347 "Remote EGP\n"
8348 "Local IGP\n"
8349 "Unknown heritage\n"
8350 "Only aggregate routes with matching MED\n"
8351 "Suppress the selected more specific routes\n"
8352 "Route map with the route selectors\n")
8353{
8354 const char *prefix_s = NULL;
554b3b10 8355 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8356 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8357 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8358 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8359
554b3b10 8360 if (addr_str) {
7533cad7
QY
8361 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8362 sizeof(prefix_buf))
554b3b10
RZ
8363 == 0) {
8364 vty_out(vty, "%% Inconsistent address and mask\n");
8365 return CMD_WARNING_CONFIG_FAILED;
8366 }
585f1adc
IR
8367 prefix_s = prefix_buf;
8368 } else
8369 prefix_s = prefix_str;
37a87b8f 8370
585f1adc
IR
8371 if (origin_s) {
8372 if (strcmp(origin_s, "egp") == 0)
8373 origin = BGP_ORIGIN_EGP;
8374 else if (strcmp(origin_s, "igp") == 0)
8375 origin = BGP_ORIGIN_IGP;
8376 else if (strcmp(origin_s, "incomplete") == 0)
8377 origin = BGP_ORIGIN_INCOMPLETE;
8378 }
90e21f35 8379
585f1adc
IR
8380 if (as_set_s)
8381 as_set = AGGREGATE_AS_SET;
554b3b10 8382
585f1adc 8383 /* Handle configuration removal, otherwise installation. */
554b3b10 8384 if (no)
585f1adc
IR
8385 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8386
8387 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8388 summary_only != NULL, as_set, origin,
8389 match_med != NULL, suppress_map);
8390}
8391
8392DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8393 "[no] aggregate-address X:X::X:X/M$prefix [{"
8394 "as-set$as_set_s"
8395 "|summary-only$summary_only"
cacba915 8396 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8397 "|origin <egp|igp|incomplete>$origin_s"
8398 "|matching-MED-only$match_med"
cacba915 8399 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8400 "}]",
8401 NO_STR
8402 "Configure BGP aggregate entries\n"
8403 "Aggregate prefix\n"
8404 "Generate AS set path information\n"
8405 "Filter more specific routes from updates\n"
8406 "Apply route map to aggregate network\n"
8407 "Route map name\n"
8408 "BGP origin code\n"
8409 "Remote EGP\n"
8410 "Local IGP\n"
8411 "Unknown heritage\n"
8412 "Only aggregate routes with matching MED\n"
8413 "Suppress the selected more specific routes\n"
8414 "Route map with the route selectors\n")
8415{
8416 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8417 int as_set = AGGREGATE_AS_UNSET;
8418
8419 if (origin_s) {
8420 if (strcmp(origin_s, "egp") == 0)
8421 origin = BGP_ORIGIN_EGP;
8422 else if (strcmp(origin_s, "igp") == 0)
8423 origin = BGP_ORIGIN_IGP;
8424 else if (strcmp(origin_s, "incomplete") == 0)
8425 origin = BGP_ORIGIN_INCOMPLETE;
8426 }
8427
8428 if (as_set_s)
8429 as_set = AGGREGATE_AS_SET;
8430
8431 /* Handle configuration removal, otherwise installation. */
554b3b10 8432 if (no)
585f1adc
IR
8433 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8434 SAFI_UNICAST);
554b3b10 8435
585f1adc
IR
8436 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8437 rmap_name, summary_only != NULL, as_set,
8438 origin, match_med != NULL, suppress_map);
718e3744 8439}
8440
718e3744 8441/* Redistribute route treatment. */
d62a17ae 8442void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8443 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8444 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8445 enum blackhole_type bhtype, uint32_t metric,
8446 uint8_t type, unsigned short instance,
8447 route_tag_t tag)
d62a17ae 8448{
4b7e6066 8449 struct bgp_path_info *new;
40381db7
DS
8450 struct bgp_path_info *bpi;
8451 struct bgp_path_info rmap_path;
9bcb3eef 8452 struct bgp_dest *bn;
d62a17ae 8453 struct attr attr;
8454 struct attr *new_attr;
8455 afi_t afi;
b68885f9 8456 route_map_result_t ret;
d62a17ae 8457 struct bgp_redist *red;
8458
8459 /* Make default attribute. */
0f05ea43 8460 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8461 /*
8462 * This must not be NULL to satisfy Coverity SA
8463 */
8464 assert(attr.aspath);
9de1f7ff 8465
a4d82a8a 8466 switch (nhtype) {
9de1f7ff
DS
8467 case NEXTHOP_TYPE_IFINDEX:
8468 break;
8469 case NEXTHOP_TYPE_IPV4:
8470 case NEXTHOP_TYPE_IPV4_IFINDEX:
8471 attr.nexthop = nexthop->ipv4;
7226bc40 8472 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8473 break;
8474 case NEXTHOP_TYPE_IPV6:
8475 case NEXTHOP_TYPE_IPV6_IFINDEX:
8476 attr.mp_nexthop_global = nexthop->ipv6;
8477 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8478 break;
8479 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8480 switch (p->family) {
8481 case AF_INET:
9de1f7ff 8482 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8483 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8484 break;
8485 case AF_INET6:
9de1f7ff
DS
8486 memset(&attr.mp_nexthop_global, 0,
8487 sizeof(attr.mp_nexthop_global));
74489921 8488 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8489 break;
74489921 8490 }
0789eb69 8491 attr.bh_type = bhtype;
9de1f7ff 8492 break;
d62a17ae 8493 }
0789eb69 8494 attr.nh_type = nhtype;
74489921 8495 attr.nh_ifindex = ifindex;
f04a80a5 8496
d62a17ae 8497 attr.med = metric;
957f74c3 8498 attr.distance = distance;
d62a17ae 8499 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8500 attr.tag = tag;
718e3744 8501
d62a17ae 8502 afi = family2afi(p->family);
6aeb9e78 8503
d62a17ae 8504 red = bgp_redist_lookup(bgp, afi, type, instance);
8505 if (red) {
8506 struct attr attr_new;
718e3744 8507
d62a17ae 8508 /* Copy attribute for modification. */
6f4f49b2 8509 attr_new = attr;
718e3744 8510
d62a17ae 8511 if (red->redist_metric_flag)
8512 attr_new.med = red->redist_metric;
718e3744 8513
d62a17ae 8514 /* Apply route-map. */
8515 if (red->rmap.name) {
6006b807 8516 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8517 rmap_path.peer = bgp->peer_self;
8518 rmap_path.attr = &attr_new;
718e3744 8519
d62a17ae 8520 SET_FLAG(bgp->peer_self->rmap_type,
8521 PEER_RMAP_TYPE_REDISTRIBUTE);
8522
1782514f 8523 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8524
8525 bgp->peer_self->rmap_type = 0;
8526
8527 if (ret == RMAP_DENYMATCH) {
8528 /* Free uninterned attribute. */
8529 bgp_attr_flush(&attr_new);
8530
8531 /* Unintern original. */
8532 aspath_unintern(&attr.aspath);
8533 bgp_redistribute_delete(bgp, p, type, instance);
8534 return;
8535 }
8536 }
8537
637e5ba4 8538 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8539 bgp_attr_add_gshut_community(&attr_new);
8540
d62a17ae 8541 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8542 SAFI_UNICAST, p, NULL);
8543
8544 new_attr = bgp_attr_intern(&attr_new);
8545
9bcb3eef 8546 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8547 if (bpi->peer == bgp->peer_self
8548 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8549 break;
8550
40381db7 8551 if (bpi) {
d62a17ae 8552 /* Ensure the (source route) type is updated. */
40381db7
DS
8553 bpi->type = type;
8554 if (attrhash_cmp(bpi->attr, new_attr)
8555 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8556 bgp_attr_unintern(&new_attr);
8557 aspath_unintern(&attr.aspath);
9bcb3eef 8558 bgp_dest_unlock_node(bn);
d62a17ae 8559 return;
8560 } else {
8561 /* The attribute is changed. */
40381db7 8562 bgp_path_info_set_flag(bn, bpi,
18ee8310 8563 BGP_PATH_ATTR_CHANGED);
d62a17ae 8564
8565 /* Rewrite BGP route information. */
40381db7
DS
8566 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8567 bgp_path_info_restore(bn, bpi);
d62a17ae 8568 else
40381db7
DS
8569 bgp_aggregate_decrement(
8570 bgp, p, bpi, afi, SAFI_UNICAST);
8571 bgp_attr_unintern(&bpi->attr);
8572 bpi->attr = new_attr;
083ec940 8573 bpi->uptime = monotime(NULL);
d62a17ae 8574
8575 /* Process change. */
40381db7 8576 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8577 SAFI_UNICAST);
8578 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8579 bgp_dest_unlock_node(bn);
d62a17ae 8580 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8581
8582 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8583 || (bgp->inst_type
8584 == BGP_INSTANCE_TYPE_DEFAULT)) {
8585
8586 vpn_leak_from_vrf_update(
40381db7 8587 bgp_get_default(), bgp, bpi);
ddb5b488 8588 }
d62a17ae 8589 return;
8590 }
8591 }
8592
8593 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8594 bgp->peer_self, new_attr, bn);
1defdda8 8595 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8596
8597 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8598 bgp_path_info_add(bn, new);
9bcb3eef 8599 bgp_dest_unlock_node(bn);
be785e35 8600 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8601 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8602
8603 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8604 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8605
8606 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8607 }
d62a17ae 8608 }
8609
8610 /* Unintern original. */
8611 aspath_unintern(&attr.aspath);
718e3744 8612}
8613
d7c0a89a
QY
8614void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8615 unsigned short instance)
718e3744 8616{
d62a17ae 8617 afi_t afi;
9bcb3eef 8618 struct bgp_dest *dest;
40381db7 8619 struct bgp_path_info *pi;
d62a17ae 8620 struct bgp_redist *red;
718e3744 8621
d62a17ae 8622 afi = family2afi(p->family);
718e3744 8623
d62a17ae 8624 red = bgp_redist_lookup(bgp, afi, type, instance);
8625 if (red) {
9bcb3eef
DS
8626 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8627 SAFI_UNICAST, p, NULL);
d62a17ae 8628
9bcb3eef 8629 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8630 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8631 break;
8632
40381db7 8633 if (pi) {
ddb5b488
PZ
8634 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8635 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8636
8637 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8638 bgp, pi);
ddb5b488 8639 }
40381db7 8640 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8641 bgp_path_info_delete(dest, pi);
8642 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8643 }
9bcb3eef 8644 bgp_dest_unlock_node(dest);
d62a17ae 8645 }
8646}
8647
8648/* Withdraw specified route type's route. */
8649void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8650 unsigned short instance)
d62a17ae 8651{
9bcb3eef 8652 struct bgp_dest *dest;
40381db7 8653 struct bgp_path_info *pi;
d62a17ae 8654 struct bgp_table *table;
8655
8656 table = bgp->rib[afi][SAFI_UNICAST];
8657
9bcb3eef
DS
8658 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8659 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8660 if (pi->peer == bgp->peer_self && pi->type == type
8661 && pi->instance == instance)
d62a17ae 8662 break;
8663
40381db7 8664 if (pi) {
ddb5b488
PZ
8665 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8666 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8667
8668 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8669 bgp, pi);
ddb5b488 8670 }
9bcb3eef 8671 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8672 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8673 bgp_path_info_delete(dest, pi);
8674 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8675 }
718e3744 8676 }
718e3744 8677}
6b0655a2 8678
718e3744 8679/* Static function to display route. */
7d3cae70
DA
8680static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8681 struct vty *vty, json_object *json, bool wide)
718e3744 8682{
be054588 8683 int len = 0;
d62a17ae 8684 char buf[BUFSIZ];
718e3744 8685
d62a17ae 8686 if (p->family == AF_INET) {
c6462ff4 8687 if (!json) {
8228a9a7 8688 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8689 } else {
8690 json_object_string_add(json, "prefix",
8691 inet_ntop(p->family,
8692 &p->u.prefix, buf,
8693 BUFSIZ));
8694 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8695 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8696 json_object_int_add(json, "version", dest->version);
c6462ff4 8697 }
d62a17ae 8698 } else if (p->family == AF_ETHERNET) {
8228a9a7 8699 len = vty_out(vty, "%pFX", p);
b03b8898 8700 } else if (p->family == AF_EVPN) {
57f7feb6 8701 if (!json)
2dbe669b 8702 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8703 else
60466a63 8704 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8705 } else if (p->family == AF_FLOWSPEC) {
8706 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8707 json ?
8708 NLRI_STRING_FORMAT_JSON_SIMPLE :
8709 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8710 } else {
c6462ff4 8711 if (!json)
8228a9a7 8712 len = vty_out(vty, "%pFX", p);
50e05855
AD
8713 else {
8714 json_object_string_add(json, "prefix",
8715 inet_ntop(p->family,
8716 &p->u.prefix, buf,
8717 BUFSIZ));
8718 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8719 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8720 json_object_int_add(json, "version", dest->version);
37d4e0df 8721 }
9c92b5f7 8722 }
d62a17ae 8723
9c92b5f7 8724 if (!json) {
ae248832 8725 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8726 if (len < 1)
8727 vty_out(vty, "\n%*s", 20, " ");
8728 else
8729 vty_out(vty, "%*s", len, " ");
8730 }
718e3744 8731}
8732
d62a17ae 8733enum bgp_display_type {
8734 normal_list,
718e3744 8735};
8736
1d7260a1 8737const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8738{
8739 switch (reason) {
8740 case bgp_path_selection_none:
8741 return "Nothing to Select";
8742 case bgp_path_selection_first:
8743 return "First path received";
8744 case bgp_path_selection_evpn_sticky_mac:
8745 return "EVPN Sticky Mac";
8746 case bgp_path_selection_evpn_seq:
8747 return "EVPN sequence number";
8748 case bgp_path_selection_evpn_lower_ip:
8749 return "EVPN lower IP";
8750 case bgp_path_selection_evpn_local_path:
8751 return "EVPN local ES path";
8752 case bgp_path_selection_evpn_non_proxy:
8753 return "EVPN non proxy";
8754 case bgp_path_selection_weight:
8755 return "Weight";
8756 case bgp_path_selection_local_pref:
8757 return "Local Pref";
8758 case bgp_path_selection_local_route:
8759 return "Local Route";
8760 case bgp_path_selection_confed_as_path:
8761 return "Confederation based AS Path";
8762 case bgp_path_selection_as_path:
8763 return "AS Path";
8764 case bgp_path_selection_origin:
8765 return "Origin";
8766 case bgp_path_selection_med:
8767 return "MED";
8768 case bgp_path_selection_peer:
8769 return "Peer Type";
8770 case bgp_path_selection_confed:
8771 return "Confed Peer Type";
8772 case bgp_path_selection_igp_metric:
8773 return "IGP Metric";
8774 case bgp_path_selection_older:
8775 return "Older Path";
8776 case bgp_path_selection_router_id:
8777 return "Router ID";
8778 case bgp_path_selection_cluster_length:
bcab253c 8779 return "Cluster length";
bbb46eb5
DA
8780 case bgp_path_selection_stale:
8781 return "Path Staleness";
8782 case bgp_path_selection_local_configured:
8783 return "Locally configured route";
8784 case bgp_path_selection_neighbor_ip:
8785 return "Neighbor IP";
8786 case bgp_path_selection_default:
8787 return "Nothing left to compare";
8788 }
8789 return "Invalid (internal error)";
8790}
8791
18ee8310 8792/* Print the short form route status for a bgp_path_info */
4b7e6066 8793static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8794 struct bgp_path_info *path,
82c298be 8795 const struct prefix *p,
d62a17ae 8796 json_object *json_path)
718e3744 8797{
82c298be
DA
8798 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8799
d62a17ae 8800 if (json_path) {
b05a1c8b 8801
d62a17ae 8802 /* Route status display. */
9b6d8fcf 8803 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8804 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8805
9b6d8fcf 8806 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8807 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8808
4056a5f6 8809 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8810 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8811
9b6d8fcf
DS
8812 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8813 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8814 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8815
d62a17ae 8816 /* Selected */
9b6d8fcf 8817 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8818 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8819
9b6d8fcf 8820 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8821 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8822
bbb46eb5 8823 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8824 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8825 json_object_string_add(json_path, "selectionReason",
8826 bgp_path_selection_reason2str(
8827 path->net->reason));
8828 }
b05a1c8b 8829
9b6d8fcf 8830 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8831 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8832
d62a17ae 8833 /* Internal route. */
9b6d8fcf
DS
8834 if ((path->peer->as)
8835 && (path->peer->as == path->peer->local_as))
d62a17ae 8836 json_object_string_add(json_path, "pathFrom",
8837 "internal");
8838 else
8839 json_object_string_add(json_path, "pathFrom",
8840 "external");
b05a1c8b 8841
d62a17ae 8842 return;
8843 }
b05a1c8b 8844
82c298be
DA
8845 /* RPKI validation state */
8846 rpki_state =
8847 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8848
8849 if (rpki_state == RPKI_VALID)
8850 vty_out(vty, "V");
8851 else if (rpki_state == RPKI_INVALID)
8852 vty_out(vty, "I");
8853 else if (rpki_state == RPKI_NOTFOUND)
8854 vty_out(vty, "N");
8855
d62a17ae 8856 /* Route status display. */
9b6d8fcf 8857 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8858 vty_out(vty, "R");
9b6d8fcf 8859 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8860 vty_out(vty, "S");
4056a5f6 8861 else if (bgp_path_suppressed(path))
d62a17ae 8862 vty_out(vty, "s");
9b6d8fcf
DS
8863 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8864 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8865 vty_out(vty, "*");
8866 else
8867 vty_out(vty, " ");
8868
8869 /* Selected */
9b6d8fcf 8870 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8871 vty_out(vty, "h");
9b6d8fcf 8872 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8873 vty_out(vty, "d");
9b6d8fcf 8874 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8875 vty_out(vty, ">");
9b6d8fcf 8876 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8877 vty_out(vty, "=");
8878 else
8879 vty_out(vty, " ");
718e3744 8880
d62a17ae 8881 /* Internal route. */
9b6d8fcf
DS
8882 if (path->peer && (path->peer->as)
8883 && (path->peer->as == path->peer->local_as))
d62a17ae 8884 vty_out(vty, "i");
8885 else
8886 vty_out(vty, " ");
b40d939b 8887}
8888
2ba93fd6
DA
8889static char *bgp_nexthop_hostname(struct peer *peer,
8890 struct bgp_nexthop_cache *bnc)
25b5da8d 8891{
892fedb6 8892 if (peer->hostname
aef999a2 8893 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8894 return peer->hostname;
8895 return NULL;
8896}
8897
b40d939b 8898/* called from terminal list command */
bd494ec5 8899void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8900 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8901 json_object *json_paths, bool wide)
d62a17ae 8902{
aef999a2 8903 int len;
515c2602 8904 struct attr *attr = path->attr;
d62a17ae 8905 json_object *json_path = NULL;
8906 json_object *json_nexthops = NULL;
8907 json_object *json_nexthop_global = NULL;
8908 json_object *json_nexthop_ll = NULL;
6f214dd3 8909 json_object *json_ext_community = NULL;
9df8b37c 8910 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8911 bool nexthop_self =
9b6d8fcf 8912 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8913 bool nexthop_othervrf = false;
43089216 8914 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8915 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8916 char *nexthop_hostname =
8917 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8918 char esi_buf[ESI_STR_LEN];
d62a17ae 8919
8920 if (json_paths)
8921 json_path = json_object_new_object();
8922
8923 /* short status lead text */
82c298be 8924 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8925
8926 if (!json_paths) {
8927 /* print prefix and mask */
8928 if (!display)
7d3cae70 8929 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8930 else
ae248832 8931 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8932 } else {
7d3cae70 8933 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8934 }
47fc97cc 8935
9df8b37c
PZ
8936 /*
8937 * If vrf id of nexthop is different from that of prefix,
8938 * set up printable string to append
8939 */
9b6d8fcf 8940 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8941 const char *self = "";
8942
8943 if (nexthop_self)
8944 self = "<";
8945
8946 nexthop_othervrf = true;
9b6d8fcf 8947 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8948
9b6d8fcf 8949 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8950 snprintf(vrf_id_str, sizeof(vrf_id_str),
8951 "@%s%s", VRFID_NONE_STR, self);
8952 else
8953 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8954 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8955
9b6d8fcf
DS
8956 if (path->extra->bgp_orig->inst_type
8957 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8958
9b6d8fcf 8959 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8960 } else {
8961 const char *self = "";
8962
8963 if (nexthop_self)
8964 self = "<";
8965
8966 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8967 }
8968
445c2480
DS
8969 /*
8970 * For ENCAP and EVPN routes, nexthop address family is not
8971 * neccessarily the same as the prefix address family.
8972 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8973 * EVPN routes are also exchanged with a MP nexthop. Currently,
8974 * this
8975 * is only IPv4, the value will be present in either
8976 * attr->nexthop or
8977 * attr->mp_nexthop_global_in
8978 */
8979 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8980 char buf[BUFSIZ];
8981 char nexthop[128];
8982 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8983
8984 switch (af) {
8985 case AF_INET:
772270f3
QY
8986 snprintf(nexthop, sizeof(nexthop), "%s",
8987 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8988 BUFSIZ));
445c2480
DS
8989 break;
8990 case AF_INET6:
772270f3
QY
8991 snprintf(nexthop, sizeof(nexthop), "%s",
8992 inet_ntop(af, &attr->mp_nexthop_global, buf,
8993 BUFSIZ));
445c2480
DS
8994 break;
8995 default:
772270f3 8996 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8997 break;
d62a17ae 8998 }
d62a17ae 8999
445c2480
DS
9000 if (json_paths) {
9001 json_nexthop_global = json_object_new_object();
9002
515c2602
DA
9003 json_object_string_add(json_nexthop_global, "ip",
9004 nexthop);
9005
939a97f4 9006 if (path->peer->hostname)
515c2602
DA
9007 json_object_string_add(json_nexthop_global,
9008 "hostname",
939a97f4 9009 path->peer->hostname);
515c2602
DA
9010
9011 json_object_string_add(json_nexthop_global, "afi",
9012 (af == AF_INET) ? "ipv4"
9013 : "ipv6");
445c2480
DS
9014 json_object_boolean_true_add(json_nexthop_global,
9015 "used");
aef999a2
DA
9016 } else {
9017 if (nexthop_hostname)
9018 len = vty_out(vty, "%s(%s)%s", nexthop,
9019 nexthop_hostname, vrf_id_str);
9020 else
9021 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
9022
ae248832 9023 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9024 if (len < 1)
9025 vty_out(vty, "\n%*s", 36, " ");
9026 else
9027 vty_out(vty, "%*s", len, " ");
9028 }
445c2480
DS
9029 } else if (safi == SAFI_EVPN) {
9030 if (json_paths) {
9031 json_nexthop_global = json_object_new_object();
9032
c949c771 9033 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
9034 "%pI4",
9035 &attr->mp_nexthop_global_in);
515c2602 9036
939a97f4 9037 if (path->peer->hostname)
515c2602
DA
9038 json_object_string_add(json_nexthop_global,
9039 "hostname",
939a97f4 9040 path->peer->hostname);
515c2602 9041
a4d82a8a
PZ
9042 json_object_string_add(json_nexthop_global, "afi",
9043 "ipv4");
445c2480
DS
9044 json_object_boolean_true_add(json_nexthop_global,
9045 "used");
aef999a2
DA
9046 } else {
9047 if (nexthop_hostname)
7226bc40
TA
9048 len = vty_out(vty, "%pI4(%s)%s",
9049 &attr->mp_nexthop_global_in,
aef999a2
DA
9050 nexthop_hostname, vrf_id_str);
9051 else
7226bc40
TA
9052 len = vty_out(vty, "%pI4%s",
9053 &attr->mp_nexthop_global_in,
aef999a2
DA
9054 vrf_id_str);
9055
ae248832 9056 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9057 if (len < 1)
9058 vty_out(vty, "\n%*s", 36, " ");
9059 else
9060 vty_out(vty, "%*s", len, " ");
9061 }
d33fc23b 9062 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9063 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9064 if (json_paths) {
9065 json_nexthop_global = json_object_new_object();
515c2602 9066
026b914a
PG
9067 json_object_string_add(json_nexthop_global,
9068 "afi", "ipv4");
c949c771
DA
9069 json_object_string_addf(json_nexthop_global,
9070 "ip", "%pI4",
9071 &attr->nexthop);
515c2602 9072
939a97f4 9073 if (path->peer->hostname)
515c2602
DA
9074 json_object_string_add(
9075 json_nexthop_global, "hostname",
939a97f4 9076 path->peer->hostname);
515c2602 9077
50e05855
AD
9078 json_object_boolean_true_add(
9079 json_nexthop_global,
026b914a
PG
9080 "used");
9081 } else {
aef999a2
DA
9082 if (nexthop_hostname)
9083 len = vty_out(vty, "%pI4(%s)%s",
9084 &attr->nexthop,
9085 nexthop_hostname,
9086 vrf_id_str);
9087 else
9088 len = vty_out(vty, "%pI4%s",
9089 &attr->nexthop,
9090 vrf_id_str);
9091
ae248832 9092 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9093 if (len < 1)
9094 vty_out(vty, "\n%*s", 36, " ");
9095 else
9096 vty_out(vty, "%*s", len, " ");
026b914a
PG
9097 }
9098 }
7226bc40 9099 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9100 if (json_paths) {
9101 json_nexthop_global = json_object_new_object();
d62a17ae 9102
c949c771
DA
9103 json_object_string_addf(json_nexthop_global, "ip",
9104 "%pI4", &attr->nexthop);
515c2602 9105
939a97f4 9106 if (path->peer->hostname)
515c2602
DA
9107 json_object_string_add(json_nexthop_global,
9108 "hostname",
939a97f4 9109 path->peer->hostname);
445c2480 9110
a4d82a8a
PZ
9111 json_object_string_add(json_nexthop_global, "afi",
9112 "ipv4");
445c2480
DS
9113 json_object_boolean_true_add(json_nexthop_global,
9114 "used");
9115 } else {
aef999a2
DA
9116 if (nexthop_hostname)
9117 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9118 nexthop_hostname, vrf_id_str);
9119 else
9120 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9121 vrf_id_str);
9df8b37c 9122
ae248832 9123 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9124 if (len < 1)
9125 vty_out(vty, "\n%*s", 36, " ");
9126 else
9127 vty_out(vty, "%*s", len, " ");
d62a17ae 9128 }
445c2480 9129 }
b05a1c8b 9130
445c2480 9131 /* IPv6 Next Hop */
7226bc40 9132 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9133 if (json_paths) {
9134 json_nexthop_global = json_object_new_object();
c949c771
DA
9135 json_object_string_addf(json_nexthop_global, "ip",
9136 "%pI6",
9137 &attr->mp_nexthop_global);
515c2602 9138
939a97f4 9139 if (path->peer->hostname)
515c2602
DA
9140 json_object_string_add(json_nexthop_global,
9141 "hostname",
939a97f4 9142 path->peer->hostname);
515c2602 9143
a4d82a8a
PZ
9144 json_object_string_add(json_nexthop_global, "afi",
9145 "ipv6");
9146 json_object_string_add(json_nexthop_global, "scope",
9147 "global");
445c2480
DS
9148
9149 /* We display both LL & GL if both have been
9150 * received */
0606039c
DA
9151 if ((attr->mp_nexthop_len
9152 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9153 || (path->peer->conf_if)) {
a4d82a8a 9154 json_nexthop_ll = json_object_new_object();
c949c771
DA
9155 json_object_string_addf(
9156 json_nexthop_ll, "ip", "%pI6",
9157 &attr->mp_nexthop_local);
515c2602 9158
939a97f4 9159 if (path->peer->hostname)
515c2602
DA
9160 json_object_string_add(
9161 json_nexthop_ll, "hostname",
939a97f4 9162 path->peer->hostname);
515c2602 9163
a4d82a8a
PZ
9164 json_object_string_add(json_nexthop_ll, "afi",
9165 "ipv6");
9166 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9167 "link-local");
d62a17ae 9168
a4d82a8a
PZ
9169 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9170 &attr->mp_nexthop_local)
445c2480
DS
9171 != 0)
9172 && !attr->mp_nexthop_prefer_global)
d62a17ae 9173 json_object_boolean_true_add(
a4d82a8a 9174 json_nexthop_ll, "used");
445c2480
DS
9175 else
9176 json_object_boolean_true_add(
a4d82a8a 9177 json_nexthop_global, "used");
445c2480
DS
9178 } else
9179 json_object_boolean_true_add(
9180 json_nexthop_global, "used");
9181 } else {
9182 /* Display LL if LL/Global both in table unless
9183 * prefer-global is set */
0606039c
DA
9184 if (((attr->mp_nexthop_len
9185 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9186 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9187 || (path->peer->conf_if)) {
9188 if (path->peer->conf_if) {
a4d82a8a 9189 len = vty_out(vty, "%s",
9b6d8fcf 9190 path->peer->conf_if);
ae248832
MK
9191 /* len of IPv6 addr + max len of def
9192 * ifname */
9193 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9194
9195 if (len < 1)
a4d82a8a 9196 vty_out(vty, "\n%*s", 36, " ");
445c2480 9197 else
a4d82a8a 9198 vty_out(vty, "%*s", len, " ");
d62a17ae 9199 } else {
aef999a2
DA
9200 if (nexthop_hostname)
9201 len = vty_out(
9202 vty, "%pI6(%s)%s",
9203 &attr->mp_nexthop_local,
9204 nexthop_hostname,
9205 vrf_id_str);
9206 else
9207 len = vty_out(
9208 vty, "%pI6%s",
9209 &attr->mp_nexthop_local,
9210 vrf_id_str);
9211
ae248832 9212 len = wide ? (41 - len) : (16 - len);
d62a17ae 9213
9214 if (len < 1)
a4d82a8a 9215 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9216 else
a4d82a8a 9217 vty_out(vty, "%*s", len, " ");
d62a17ae 9218 }
445c2480 9219 } else {
aef999a2
DA
9220 if (nexthop_hostname)
9221 len = vty_out(vty, "%pI6(%s)%s",
9222 &attr->mp_nexthop_global,
9223 nexthop_hostname,
9224 vrf_id_str);
9225 else
9226 len = vty_out(vty, "%pI6%s",
9227 &attr->mp_nexthop_global,
9228 vrf_id_str);
9229
ae248832 9230 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9231
9232 if (len < 1)
9233 vty_out(vty, "\n%*s", 36, " ");
9234 else
9235 vty_out(vty, "%*s", len, " ");
d62a17ae 9236 }
9237 }
445c2480 9238 }
718e3744 9239
445c2480
DS
9240 /* MED/Metric */
9241 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9242 if (json_paths)
50e05855 9243 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9244 else if (wide)
9245 vty_out(vty, "%7u", attr->med);
0fbac0b4 9246 else
445c2480 9247 vty_out(vty, "%10u", attr->med);
ae248832
MK
9248 else if (!json_paths) {
9249 if (wide)
9250 vty_out(vty, "%*s", 7, " ");
9251 else
9252 vty_out(vty, "%*s", 10, " ");
9253 }
d62a17ae 9254
445c2480
DS
9255 /* Local Pref */
9256 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9257 if (json_paths)
50e05855 9258 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9259 attr->local_pref);
9260 else
445c2480
DS
9261 vty_out(vty, "%7u", attr->local_pref);
9262 else if (!json_paths)
9263 vty_out(vty, " ");
d62a17ae 9264
445c2480
DS
9265 if (json_paths)
9266 json_object_int_add(json_path, "weight", attr->weight);
9267 else
9268 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9269
47e12884
DA
9270 if (json_paths)
9271 json_object_string_addf(json_path, "peerId", "%pSU",
9272 &path->peer->su);
b05a1c8b 9273
445c2480
DS
9274 /* Print aspath */
9275 if (attr->aspath) {
0fbac0b4 9276 if (json_paths)
50e05855 9277 json_object_string_add(json_path, "path",
0fbac0b4
DA
9278 attr->aspath->str);
9279 else
445c2480 9280 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9281 }
f1aa5d8a 9282
445c2480
DS
9283 /* Print origin */
9284 if (json_paths)
a4d82a8a
PZ
9285 json_object_string_add(json_path, "origin",
9286 bgp_origin_long_str[attr->origin]);
445c2480
DS
9287 else
9288 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9289
9df8b37c 9290 if (json_paths) {
d071f237 9291 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9292 json_object_string_add(json_path, "esi",
9293 esi_to_str(&attr->esi,
9294 esi_buf, sizeof(esi_buf)));
9295 }
6f214dd3
CS
9296 if (safi == SAFI_EVPN &&
9297 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9298 json_ext_community = json_object_new_object();
b53e67a3
DA
9299 json_object_string_add(
9300 json_ext_community, "string",
9301 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9302 json_object_object_add(json_path,
9303 "extendedCommunity",
9304 json_ext_community);
9305 }
9306
9df8b37c
PZ
9307 if (nexthop_self)
9308 json_object_boolean_true_add(json_path,
9309 "announceNexthopSelf");
9310 if (nexthop_othervrf) {
9311 json_object_string_add(json_path, "nhVrfName",
9312 nexthop_vrfname);
9313
9314 json_object_int_add(json_path, "nhVrfId",
9315 ((nexthop_vrfid == VRF_UNKNOWN)
9316 ? -1
9317 : (int)nexthop_vrfid));
9318 }
9319 }
9320
d62a17ae 9321 if (json_paths) {
9322 if (json_nexthop_global || json_nexthop_ll) {
9323 json_nexthops = json_object_new_array();
f1aa5d8a 9324
d62a17ae 9325 if (json_nexthop_global)
9326 json_object_array_add(json_nexthops,
9327 json_nexthop_global);
f1aa5d8a 9328
d62a17ae 9329 if (json_nexthop_ll)
9330 json_object_array_add(json_nexthops,
9331 json_nexthop_ll);
f1aa5d8a 9332
d62a17ae 9333 json_object_object_add(json_path, "nexthops",
9334 json_nexthops);
9335 }
9336
9337 json_object_array_add(json_paths, json_path);
9338 } else {
9339 vty_out(vty, "\n");
6f214dd3 9340
b5e140c8 9341 if (safi == SAFI_EVPN) {
d071f237 9342 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9343 /* XXX - add these params to the json out */
b5e140c8 9344 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9345 vty_out(vty, "ESI:%s",
9346 esi_to_str(&attr->esi, esi_buf,
9347 sizeof(esi_buf)));
60605cbc 9348
229587fb 9349 vty_out(vty, "\n");
b5e140c8
AK
9350 }
9351 if (attr->flag &
9352 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9353 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9354 vty_out(vty, "%s\n",
9355 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9356 }
6f214dd3
CS
9357 }
9358
49e5a4a0 9359#ifdef ENABLE_BGP_VNC
d62a17ae 9360 /* prints an additional line, indented, with VNC info, if
9361 * present */
9362 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9363 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9364#endif
d62a17ae 9365 }
9366}
718e3744 9367
9368/* called from terminal list command */
7d3cae70
DA
9369void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9370 const struct prefix *p, struct attr *attr, safi_t safi,
9371 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9372{
9373 json_object *json_status = NULL;
9374 json_object *json_net = NULL;
aef999a2 9375 int len;
d62a17ae 9376 char buff[BUFSIZ];
dc387b0f 9377
d62a17ae 9378 /* Route status display. */
9379 if (use_json) {
9380 json_status = json_object_new_object();
9381 json_net = json_object_new_object();
9382 } else {
9383 vty_out(vty, "*");
9384 vty_out(vty, ">");
9385 vty_out(vty, " ");
9386 }
718e3744 9387
d62a17ae 9388 /* print prefix and mask */
50e05855 9389 if (use_json) {
dc387b0f
LK
9390 if (safi == SAFI_EVPN)
9391 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9392 else if (p->family == AF_INET || p->family == AF_INET6) {
9393 json_object_string_add(
9394 json_net, "addrPrefix",
9395 inet_ntop(p->family, &p->u.prefix, buff,
9396 BUFSIZ));
9397 json_object_int_add(json_net, "prefixLen",
9398 p->prefixlen);
67d7e256 9399 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9400 }
50e05855 9401 } else
7d3cae70 9402 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9403
9404 /* Print attribute */
9405 if (attr) {
9406 if (use_json) {
7226bc40
TA
9407 if (p->family == AF_INET &&
9408 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9409 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9410 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9411 json_object_string_addf(
9412 json_net, "nextHop", "%pI4",
9413 &attr->mp_nexthop_global_in);
d62a17ae 9414 else
c949c771
DA
9415 json_object_string_addf(
9416 json_net, "nextHop", "%pI4",
9417 &attr->nexthop);
7226bc40
TA
9418 } else if (p->family == AF_INET6 ||
9419 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9420 json_object_string_addf(
9421 json_net, "nextHopGlobal", "%pI6",
9422 &attr->mp_nexthop_global);
7226bc40
TA
9423 } else if (p->family == AF_EVPN &&
9424 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9425 json_object_string_addf(
9426 json_net, "nextHop", "%pI4",
9427 &attr->mp_nexthop_global_in);
23d0a753 9428 }
d62a17ae 9429
9430 if (attr->flag
9431 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9432 json_object_int_add(json_net, "metric",
9433 attr->med);
9434
0fbac0b4 9435 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9436 json_object_int_add(json_net, "locPrf",
0fbac0b4 9437 attr->local_pref);
d62a17ae 9438
9439 json_object_int_add(json_net, "weight", attr->weight);
9440
9441 /* Print aspath */
0fbac0b4 9442 if (attr->aspath)
50e05855 9443 json_object_string_add(json_net, "path",
0fbac0b4 9444 attr->aspath->str);
d62a17ae 9445
9446 /* Print origin */
9447 json_object_string_add(json_net, "bgpOriginCode",
9448 bgp_origin_str[attr->origin]);
9449 } else {
7226bc40
TA
9450 if (p->family == AF_INET &&
9451 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9452 safi == SAFI_EVPN ||
9453 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9454 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9455 || safi == SAFI_EVPN)
23d0a753
DA
9456 vty_out(vty, "%-16pI4",
9457 &attr->mp_nexthop_global_in);
ae248832 9458 else if (wide)
23d0a753 9459 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9460 else
23d0a753 9461 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9462 } else if (p->family == AF_INET6 ||
9463 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9464 char buf[BUFSIZ];
9465
9466 len = vty_out(
9467 vty, "%s",
9468 inet_ntop(AF_INET6,
9469 &attr->mp_nexthop_global, buf,
9470 BUFSIZ));
ae248832 9471 len = wide ? (41 - len) : (16 - len);
d62a17ae 9472 if (len < 1)
9473 vty_out(vty, "\n%*s", 36, " ");
9474 else
9475 vty_out(vty, "%*s", len, " ");
9476 }
9477 if (attr->flag
9478 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9479 if (wide)
9480 vty_out(vty, "%7u", attr->med);
9481 else
9482 vty_out(vty, "%10u", attr->med);
9483 else if (wide)
9484 vty_out(vty, " ");
d62a17ae 9485 else
9486 vty_out(vty, " ");
718e3744 9487
d62a17ae 9488 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9489 vty_out(vty, "%7u", attr->local_pref);
9490 else
9491 vty_out(vty, " ");
9492
9493 vty_out(vty, "%7u ", attr->weight);
9494
9495 /* Print aspath */
9496 if (attr->aspath)
9497 aspath_print_vty(vty, "%s", attr->aspath, " ");
9498
9499 /* Print origin */
9500 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9501 }
9502 }
9503 if (use_json) {
9504 json_object_boolean_true_add(json_status, "*");
9505 json_object_boolean_true_add(json_status, ">");
9506 json_object_object_add(json_net, "appliedStatusSymbols",
9507 json_status);
511211bf 9508 json_object_object_addf(json_ar, json_net, "%pFX", p);
d62a17ae 9509 } else
9510 vty_out(vty, "\n");
9511}
9512
bd494ec5 9513void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9514 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9515 json_object *json)
9516{
9517 json_object *json_out = NULL;
9518 struct attr *attr;
9519 mpls_label_t label = MPLS_INVALID_LABEL;
9520
9b6d8fcf 9521 if (!path->extra)
d62a17ae 9522 return;
9523
9524 if (json)
9525 json_out = json_object_new_object();
9526
9527 /* short status lead text */
82c298be 9528 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9529
9530 /* print prefix and mask */
9531 if (json == NULL) {
9532 if (!display)
7d3cae70 9533 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9534 else
9535 vty_out(vty, "%*s", 17, " ");
9536 }
9537
9538 /* Print attribute */
9b6d8fcf 9539 attr = path->attr;
7226bc40
TA
9540 if (((p->family == AF_INET) &&
9541 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9542 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9543 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9544 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9545 || safi == SAFI_EVPN) {
9546 if (json)
c949c771
DA
9547 json_object_string_addf(
9548 json_out, "mpNexthopGlobalIn", "%pI4",
9549 &attr->mp_nexthop_global_in);
05864da7 9550 else
23d0a753
DA
9551 vty_out(vty, "%-16pI4",
9552 &attr->mp_nexthop_global_in);
05864da7
DS
9553 } else {
9554 if (json)
c949c771
DA
9555 json_object_string_addf(json_out, "nexthop",
9556 "%pI4", &attr->nexthop);
05864da7 9557 else
23d0a753 9558 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9559 }
7226bc40
TA
9560 } else if (((p->family == AF_INET6) &&
9561 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9562 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9563 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9564 char buf_a[512];
9565
9566 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9567 if (json)
c949c771
DA
9568 json_object_string_addf(
9569 json_out, "mpNexthopGlobalIn", "%pI6",
9570 &attr->mp_nexthop_global);
05864da7
DS
9571 else
9572 vty_out(vty, "%s",
9573 inet_ntop(AF_INET6,
9574 &attr->mp_nexthop_global,
9575 buf_a, sizeof(buf_a)));
9576 } else if (attr->mp_nexthop_len
9577 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9578 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9579 &attr->mp_nexthop_global,
9580 &attr->mp_nexthop_local);
9581 if (json)
9582 json_object_string_add(json_out,
9583 "mpNexthopGlobalLocal",
9584 buf_a);
9585 else
9586 vty_out(vty, "%s", buf_a);
d62a17ae 9587 }
9588 }
9589
9b6d8fcf 9590 label = decode_label(&path->extra->label[0]);
d62a17ae 9591
9592 if (bgp_is_valid_label(&label)) {
9593 if (json) {
9594 json_object_int_add(json_out, "notag", label);
9595 json_object_array_add(json, json_out);
9596 } else {
9597 vty_out(vty, "notag/%d", label);
9598 vty_out(vty, "\n");
9599 }
700ddfed
PG
9600 } else if (!json)
9601 vty_out(vty, "\n");
d62a17ae 9602}
718e3744 9603
bd494ec5 9604void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9605 struct bgp_path_info *path, int display,
d62a17ae 9606 json_object *json_paths)
718e3744 9607{
d62a17ae 9608 struct attr *attr;
d62a17ae 9609 json_object *json_path = NULL;
14f51eba
LK
9610 json_object *json_nexthop = NULL;
9611 json_object *json_overlay = NULL;
856ca177 9612
9b6d8fcf 9613 if (!path->extra)
d62a17ae 9614 return;
718e3744 9615
14f51eba
LK
9616 if (json_paths) {
9617 json_path = json_object_new_object();
9618 json_overlay = json_object_new_object();
9619 json_nexthop = json_object_new_object();
9620 }
9621
d62a17ae 9622 /* short status lead text */
82c298be 9623 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9624
d62a17ae 9625 /* print prefix and mask */
9626 if (!display)
7d3cae70 9627 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9628 else
9629 vty_out(vty, "%*s", 17, " ");
9630
9631 /* Print attribute */
9b6d8fcf 9632 attr = path->attr;
05864da7 9633 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9634
05864da7
DS
9635 switch (af) {
9636 case AF_INET:
05864da7 9637 if (!json_path) {
db66cf7c 9638 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9639 } else {
db66cf7c
DA
9640 json_object_string_addf(json_nexthop, "ip", "%pI4",
9641 &attr->mp_nexthop_global_in);
14f51eba 9642
05864da7 9643 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9644
05864da7
DS
9645 json_object_object_add(json_path, "nexthop",
9646 json_nexthop);
9647 }
9648 break;
9649 case AF_INET6:
05864da7 9650 if (!json_path) {
db66cf7c
DA
9651 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9652 &attr->mp_nexthop_local);
05864da7 9653 } else {
db66cf7c
DA
9654 json_object_string_addf(json_nexthop, "ipv6Global",
9655 "%pI6",
9656 &attr->mp_nexthop_global);
14f51eba 9657
db66cf7c
DA
9658 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9659 "%pI6",
9660 &attr->mp_nexthop_local);
14f51eba 9661
05864da7 9662 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9663
05864da7
DS
9664 json_object_object_add(json_path, "nexthop",
9665 json_nexthop);
9666 }
9667 break;
9668 default:
9669 if (!json_path) {
9670 vty_out(vty, "?");
9671 } else {
9672 json_object_string_add(json_nexthop, "Error",
9673 "Unsupported address-family");
77a2f8e5
DA
9674 json_object_string_add(json_nexthop, "error",
9675 "Unsupported address-family");
d62a17ae 9676 }
05864da7 9677 }
988258b4 9678
6c924775
DS
9679 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9680
05864da7 9681 if (!json_path)
db66cf7c 9682 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9683 else
db66cf7c 9684 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9685
b53e67a3 9686 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9687 char *mac = NULL;
9688 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9689 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9690 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9691
9692 if (routermac)
9693 mac = ecom_mac2str((char *)routermac->val);
9694 if (mac) {
9695 if (!json_path) {
c4efd0f4 9696 vty_out(vty, "/%s", mac);
05864da7
DS
9697 } else {
9698 json_object_string_add(json_overlay, "rmac",
9699 mac);
988258b4 9700 }
05864da7 9701 XFREE(MTYPE_TMP, mac);
988258b4 9702 }
05864da7 9703 }
718e3744 9704
05864da7
DS
9705 if (!json_path) {
9706 vty_out(vty, "\n");
9707 } else {
9708 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9709
05864da7 9710 json_object_array_add(json_paths, json_path);
14f51eba 9711 }
d62a17ae 9712}
718e3744 9713
d62a17ae 9714/* dampening route */
5f040085
DS
9715static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9716 struct bgp_path_info *path, int display,
9717 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9718 json_object *json_paths)
d62a17ae 9719{
e5be8c1d 9720 struct attr *attr = path->attr;
d62a17ae 9721 int len;
9722 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9723 json_object *json_path = NULL;
9724
9725 if (use_json)
9726 json_path = json_object_new_object();
d62a17ae 9727
9728 /* short status lead text */
e5be8c1d 9729 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9730
9731 /* print prefix and mask */
9732 if (!use_json) {
9733 if (!display)
7d3cae70 9734 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9735 else
9736 vty_out(vty, "%*s", 17, " ");
d62a17ae 9737
e5be8c1d
DA
9738 len = vty_out(vty, "%s", path->peer->host);
9739 len = 17 - len;
9740
9741 if (len < 1)
d62a17ae 9742 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9743 else
9744 vty_out(vty, "%*s", len, " ");
d62a17ae 9745
9b6d8fcf
DS
9746 vty_out(vty, "%s ",
9747 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9748 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9749 use_json, NULL));
d62a17ae 9750
e5be8c1d 9751 if (attr->aspath)
05864da7 9752 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9753
05864da7
DS
9754 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9755
d62a17ae 9756 vty_out(vty, "\n");
e5be8c1d
DA
9757 } else {
9758 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9759 safi, use_json, json_path);
9760
9761 if (attr->aspath)
9762 json_object_string_add(json_path, "asPath",
9763 attr->aspath->str);
9764
9765 json_object_string_add(json_path, "origin",
9766 bgp_origin_str[attr->origin]);
9767 json_object_string_add(json_path, "peerHost", path->peer->host);
9768
9769 json_object_array_add(json_paths, json_path);
9770 }
d62a17ae 9771}
718e3744 9772
d62a17ae 9773/* flap route */
5f040085
DS
9774static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9775 struct bgp_path_info *path, int display,
9776 afi_t afi, safi_t safi, bool use_json,
31258046 9777 json_object *json_paths)
784d3a42 9778{
31258046 9779 struct attr *attr = path->attr;
d62a17ae 9780 struct bgp_damp_info *bdi;
9781 char timebuf[BGP_UPTIME_LEN];
9782 int len;
31258046 9783 json_object *json_path = NULL;
784d3a42 9784
9b6d8fcf 9785 if (!path->extra)
d62a17ae 9786 return;
784d3a42 9787
31258046
DA
9788 if (use_json)
9789 json_path = json_object_new_object();
9790
9b6d8fcf 9791 bdi = path->extra->damp_info;
784d3a42 9792
d62a17ae 9793 /* short status lead text */
31258046 9794 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9795
d62a17ae 9796 if (!use_json) {
9797 if (!display)
7d3cae70 9798 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9799 else
9800 vty_out(vty, "%*s", 17, " ");
784d3a42 9801
31258046
DA
9802 len = vty_out(vty, "%s", path->peer->host);
9803 len = 16 - len;
9804 if (len < 1)
d62a17ae 9805 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9806 else
9807 vty_out(vty, "%*s", len, " ");
784d3a42 9808
31258046
DA
9809 len = vty_out(vty, "%d", bdi->flap);
9810 len = 5 - len;
9811 if (len < 1)
d62a17ae 9812 vty_out(vty, " ");
d62a17ae 9813 else
9814 vty_out(vty, "%*s", len, " ");
d62a17ae 9815
996c9314
LB
9816 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9817 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9818
31258046
DA
9819 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9820 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9821 vty_out(vty, "%s ",
9b6d8fcf 9822 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9823 BGP_UPTIME_LEN, afi,
31258046
DA
9824 safi, use_json, NULL));
9825 else
d62a17ae 9826 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9827
31258046 9828 if (attr->aspath)
05864da7 9829 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9830
05864da7
DS
9831 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9832
d62a17ae 9833 vty_out(vty, "\n");
31258046
DA
9834 } else {
9835 json_object_string_add(json_path, "peerHost", path->peer->host);
9836 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9837
9838 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9839 json_path);
9840
9841 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9842 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9843 bgp_damp_reuse_time_vty(vty, path, timebuf,
9844 BGP_UPTIME_LEN, afi, safi,
9845 use_json, json_path);
9846
9847 if (attr->aspath)
9848 json_object_string_add(json_path, "asPath",
9849 attr->aspath->str);
9850
9851 json_object_string_add(json_path, "origin",
9852 bgp_origin_str[attr->origin]);
9853
9854 json_object_array_add(json_paths, json_path);
9855 }
d62a17ae 9856}
9857
9858static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9859 int *first, const char *header,
9860 json_object *json_adv_to)
9861{
d62a17ae 9862 json_object *json_peer = NULL;
9863
9864 if (json_adv_to) {
9865 /* 'advertised-to' is a dictionary of peers we have advertised
9866 * this
9867 * prefix too. The key is the peer's IP or swpX, the value is
9868 * the
9869 * hostname if we know it and "" if not.
9870 */
9871 json_peer = json_object_new_object();
9872
9873 if (peer->hostname)
9874 json_object_string_add(json_peer, "hostname",
9875 peer->hostname);
9876
9877 if (peer->conf_if)
9878 json_object_object_add(json_adv_to, peer->conf_if,
9879 json_peer);
9880 else
47e12884
DA
9881 json_object_object_addf(json_adv_to, json_peer, "%pSU",
9882 &peer->su);
d62a17ae 9883 } else {
9884 if (*first) {
9885 vty_out(vty, "%s", header);
9886 *first = 0;
9887 }
9888
9889 if (peer->hostname
892fedb6 9890 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9891 if (peer->conf_if)
9892 vty_out(vty, " %s(%s)", peer->hostname,
9893 peer->conf_if);
9894 else
47e12884
DA
9895 vty_out(vty, " %s(%pSU)", peer->hostname,
9896 &peer->su);
d62a17ae 9897 } else {
9898 if (peer->conf_if)
9899 vty_out(vty, " %s", peer->conf_if);
9900 else
47e12884 9901 vty_out(vty, " %pSU", &peer->su);
d62a17ae 9902 }
9903 }
784d3a42
PG
9904}
9905
dcc68b5e
MS
9906static void route_vty_out_tx_ids(struct vty *vty,
9907 struct bgp_addpath_info_data *d)
9908{
9909 int i;
9910
9911 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9912 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9913 d->addpath_tx_id[i],
9914 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9915 }
9916}
9917
5e4d4c8a 9918static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9919 struct bgp_path_info *pi,
9920 struct attr *attr,
9921 json_object *json_path)
5e4d4c8a
AK
9922{
9923 char esi_buf[ESI_STR_LEN];
9924 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9925 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9926 ATTR_ES_PEER_ROUTER);
9927 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9928 ATTR_ES_PEER_ACTIVE);
9929 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9930 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9931 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9932 if (json_path) {
9933 json_object *json_es_info = NULL;
9934
9935 json_object_string_add(
9936 json_path, "esi",
9937 esi_buf);
9938 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9939 json_es_info = json_object_new_object();
9940 if (es_local)
9941 json_object_boolean_true_add(
9942 json_es_info, "localEs");
9943 if (peer_active)
9944 json_object_boolean_true_add(
9945 json_es_info, "peerActive");
9946 if (peer_proxy)
9947 json_object_boolean_true_add(
9948 json_es_info, "peerProxy");
9949 if (peer_router)
9950 json_object_boolean_true_add(
9951 json_es_info, "peerRouter");
9952 if (attr->mm_sync_seqnum)
9953 json_object_int_add(
9954 json_es_info, "peerSeq",
9955 attr->mm_sync_seqnum);
9956 json_object_object_add(
9957 json_path, "es_info",
9958 json_es_info);
9959 }
9960 } else {
9961 if (bgp_evpn_attr_is_sync(attr))
9962 vty_out(vty,
9963 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9964 esi_buf,
9965 es_local ? "local-es":"",
9966 peer_proxy ? "proxy " : "",
9967 peer_active ? "active ":"",
9968 peer_router ? "router ":"",
9969 attr->mm_sync_seqnum);
9970 else
9971 vty_out(vty, " ESI %s %s\n",
9972 esi_buf,
9973 es_local ? "local-es":"");
9974 }
9975}
9976
4933eaaf
DS
9977void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9978 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9979 enum rpki_states rpki_curr_state,
9980 json_object *json_paths)
d62a17ae 9981{
9982 char buf[INET6_ADDRSTRLEN];
9983 char buf1[BUFSIZ];
515c2602 9984 struct attr *attr = path->attr;
d62a17ae 9985 time_t tbuf;
9986 json_object *json_bestpath = NULL;
9987 json_object *json_cluster_list = NULL;
9988 json_object *json_cluster_list_list = NULL;
9989 json_object *json_ext_community = NULL;
9990 json_object *json_last_update = NULL;
7fd077aa 9991 json_object *json_pmsi = NULL;
d62a17ae 9992 json_object *json_nexthop_global = NULL;
9993 json_object *json_nexthop_ll = NULL;
9994 json_object *json_nexthops = NULL;
9995 json_object *json_path = NULL;
9996 json_object *json_peer = NULL;
9997 json_object *json_string = NULL;
9998 json_object *json_adv_to = NULL;
9999 int first = 0;
10000 struct listnode *node, *nnode;
10001 struct peer *peer;
be92fc9f 10002 bool addpath_capable;
d62a17ae 10003 int has_adj;
10004 unsigned int first_as;
1defdda8 10005 bool nexthop_self =
9b6d8fcf 10006 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 10007 int i;
2ba93fd6
DA
10008 char *nexthop_hostname =
10009 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
10010 uint32_t ttl = 0;
10011 uint32_t bos = 0;
10012 uint32_t exp = 0;
10013 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 10014
10015 if (json_paths) {
10016 json_path = json_object_new_object();
10017 json_peer = json_object_new_object();
10018 json_nexthop_global = json_object_new_object();
10019 }
10020
8304dabf
AD
10021 if (safi == SAFI_EVPN) {
10022 if (!json_paths)
10023 vty_out(vty, " Route %pRN", bn);
10024 }
10025
44c69747 10026 if (path->extra) {
b57ba6d2 10027 char tag_buf[30];
d62a17ae 10028
d62a17ae 10029 tag_buf[0] = '\0';
9b6d8fcf
DS
10030 if (path->extra && path->extra->num_labels) {
10031 bgp_evpn_label2str(path->extra->label,
10032 path->extra->num_labels, tag_buf,
a4d82a8a 10033 sizeof(tag_buf));
d62a17ae 10034 }
d7325ee7 10035 if (safi == SAFI_EVPN) {
44c69747 10036 if (!json_paths) {
44c69747
LK
10037 if (tag_buf[0] != '\0')
10038 vty_out(vty, " VNI %s", tag_buf);
44c69747 10039 } else {
77a2f8e5 10040 if (tag_buf[0]) {
44c69747
LK
10041 json_object_string_add(json_path, "VNI",
10042 tag_buf);
77a2f8e5
DA
10043 json_object_string_add(json_path, "vni",
10044 tag_buf);
10045 }
44c69747 10046 }
d7325ee7
DD
10047 }
10048
44c69747 10049 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 10050 struct bgp_path_info *parent_ri;
9bcb3eef 10051 struct bgp_dest *dest, *pdest;
d62a17ae 10052
9b6d8fcf 10053 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
10054 dest = parent_ri->net;
10055 if (dest && dest->pdest) {
10056 pdest = dest->pdest;
10057 prefix_rd2str(
10058 (struct prefix_rd *)bgp_dest_get_prefix(
10059 pdest),
10060 buf1, sizeof(buf1));
d7325ee7 10061 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 10062 vty_out(vty,
58bff4d1 10063 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
10064 buf1,
10065 (struct prefix_evpn *)
10066 bgp_dest_get_prefix(
10067 dest),
10068 tag_buf);
58bff4d1
AK
10069 if (attr->es_flags & ATTR_ES_L3_NHG)
10070 vty_out(vty, ", L3NHG %s",
10071 (attr->es_flags
10072 & ATTR_ES_L3_NHG_ACTIVE)
10073 ? "active"
10074 : "inactive");
10075 vty_out(vty, "\n");
10076
d7325ee7 10077 } else
2dbe669b
DA
10078 vty_out(vty,
10079 " Imported from %s:%pFX\n",
10080 buf1,
10081 (struct prefix_evpn *)
10082 bgp_dest_get_prefix(
10083 dest));
d62a17ae 10084 }
10085 }
10086 }
d62a17ae 10087
8304dabf
AD
10088 if (safi == SAFI_EVPN
10089 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10090 char gwip_buf[INET6_ADDRSTRLEN];
10091
860e740b
IR
10092 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10093 sizeof(gwip_buf));
8304dabf
AD
10094
10095 if (json_paths)
10096 json_object_string_add(json_path, "gatewayIP",
10097 gwip_buf);
10098 else
10099 vty_out(vty, " Gateway IP %s", gwip_buf);
10100 }
10101
2bf9780b 10102 if (safi == SAFI_EVPN && !json_path)
8304dabf
AD
10103 vty_out(vty, "\n");
10104
05864da7
DS
10105 /* Line1 display AS-path, Aggregator */
10106 if (attr->aspath) {
10107 if (json_paths) {
10108 if (!attr->aspath->json)
10109 aspath_str_update(attr->aspath, true);
10110 json_object_lock(attr->aspath->json);
10111 json_object_object_add(json_path, "aspath",
10112 attr->aspath->json);
10113 } else {
10114 if (attr->aspath->segments)
10115 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10116 else
05864da7 10117 vty_out(vty, " Local");
d62a17ae 10118 }
05864da7 10119 }
d62a17ae 10120
05864da7
DS
10121 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10122 if (json_paths)
10123 json_object_boolean_true_add(json_path, "removed");
10124 else
10125 vty_out(vty, ", (removed)");
10126 }
d62a17ae 10127
05864da7
DS
10128 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10129 if (json_paths)
10130 json_object_boolean_true_add(json_path, "stale");
10131 else
10132 vty_out(vty, ", (stale)");
10133 }
d62a17ae 10134
05864da7
DS
10135 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10136 if (json_paths) {
10137 json_object_int_add(json_path, "aggregatorAs",
10138 attr->aggregator_as);
c949c771
DA
10139 json_object_string_addf(json_path, "aggregatorId",
10140 "%pI4", &attr->aggregator_addr);
05864da7 10141 } else {
88d495a9
DA
10142 vty_out(vty, ", (aggregated by %u %pI4)",
10143 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10144 }
05864da7 10145 }
d62a17ae 10146
05864da7
DS
10147 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10148 PEER_FLAG_REFLECTOR_CLIENT)) {
10149 if (json_paths)
10150 json_object_boolean_true_add(json_path,
10151 "rxedFromRrClient");
10152 else
10153 vty_out(vty, ", (Received from a RR-client)");
10154 }
d62a17ae 10155
05864da7
DS
10156 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10157 PEER_FLAG_RSERVER_CLIENT)) {
10158 if (json_paths)
10159 json_object_boolean_true_add(json_path,
10160 "rxedFromRsClient");
10161 else
10162 vty_out(vty, ", (Received from a RS-client)");
10163 }
d62a17ae 10164
05864da7
DS
10165 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10166 if (json_paths)
10167 json_object_boolean_true_add(json_path,
10168 "dampeningHistoryEntry");
10169 else
10170 vty_out(vty, ", (history entry)");
10171 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10172 if (json_paths)
10173 json_object_boolean_true_add(json_path,
10174 "dampeningSuppressed");
10175 else
10176 vty_out(vty, ", (suppressed due to dampening)");
10177 }
d62a17ae 10178
05864da7
DS
10179 if (!json_paths)
10180 vty_out(vty, "\n");
d62a17ae 10181
05864da7
DS
10182 /* Line2 display Next-hop, Neighbor, Router-id */
10183 /* Display the nexthop */
9bcb3eef 10184 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0 10185
7226bc40
TA
10186 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
10187 bn_p->family == AF_EVPN) &&
10188 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10189 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10190 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10191 || safi == SAFI_EVPN) {
515c2602 10192 if (json_paths) {
c949c771
DA
10193 json_object_string_addf(
10194 json_nexthop_global, "ip", "%pI4",
10195 &attr->mp_nexthop_global_in);
515c2602 10196
939a97f4 10197 if (path->peer->hostname)
515c2602
DA
10198 json_object_string_add(
10199 json_nexthop_global, "hostname",
939a97f4 10200 path->peer->hostname);
aef999a2
DA
10201 } else {
10202 if (nexthop_hostname)
10203 vty_out(vty, " %pI4(%s)",
10204 &attr->mp_nexthop_global_in,
10205 nexthop_hostname);
10206 else
10207 vty_out(vty, " %pI4",
10208 &attr->mp_nexthop_global_in);
10209 }
d62a17ae 10210 } else {
515c2602 10211 if (json_paths) {
c949c771
DA
10212 json_object_string_addf(json_nexthop_global,
10213 "ip", "%pI4",
10214 &attr->nexthop);
515c2602 10215
939a97f4 10216 if (path->peer->hostname)
515c2602
DA
10217 json_object_string_add(
10218 json_nexthop_global, "hostname",
939a97f4 10219 path->peer->hostname);
aef999a2
DA
10220 } else {
10221 if (nexthop_hostname)
10222 vty_out(vty, " %pI4(%s)",
10223 &attr->nexthop,
10224 nexthop_hostname);
10225 else
10226 vty_out(vty, " %pI4",
10227 &attr->nexthop);
10228 }
d62a17ae 10229 }
10230
05864da7
DS
10231 if (json_paths)
10232 json_object_string_add(json_nexthop_global, "afi",
10233 "ipv4");
10234 } else {
10235 if (json_paths) {
c949c771
DA
10236 json_object_string_addf(json_nexthop_global, "ip",
10237 "%pI6",
10238 &attr->mp_nexthop_global);
515c2602 10239
939a97f4 10240 if (path->peer->hostname)
515c2602
DA
10241 json_object_string_add(json_nexthop_global,
10242 "hostname",
939a97f4 10243 path->peer->hostname);
515c2602 10244
05864da7
DS
10245 json_object_string_add(json_nexthop_global, "afi",
10246 "ipv6");
10247 json_object_string_add(json_nexthop_global, "scope",
10248 "global");
10249 } else {
aef999a2
DA
10250 if (nexthop_hostname)
10251 vty_out(vty, " %pI6(%s)",
10252 &attr->mp_nexthop_global,
10253 nexthop_hostname);
10254 else
10255 vty_out(vty, " %pI6",
10256 &attr->mp_nexthop_global);
d62a17ae 10257 }
05864da7 10258 }
d62a17ae 10259
05864da7
DS
10260 /* Display the IGP cost or 'inaccessible' */
10261 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10262 if (json_paths)
10263 json_object_boolean_false_add(json_nexthop_global,
10264 "accessible");
10265 else
10266 vty_out(vty, " (inaccessible)");
10267 } else {
10268 if (path->extra && path->extra->igpmetric) {
d62a17ae 10269 if (json_paths)
05864da7
DS
10270 json_object_int_add(json_nexthop_global,
10271 "metric",
10272 path->extra->igpmetric);
d62a17ae 10273 else
05864da7
DS
10274 vty_out(vty, " (metric %u)",
10275 path->extra->igpmetric);
d62a17ae 10276 }
10277
05864da7 10278 /* IGP cost is 0, display this only for json */
d62a17ae 10279 else {
d62a17ae 10280 if (json_paths)
05864da7
DS
10281 json_object_int_add(json_nexthop_global,
10282 "metric", 0);
d62a17ae 10283 }
d62a17ae 10284
05864da7
DS
10285 if (json_paths)
10286 json_object_boolean_true_add(json_nexthop_global,
10287 "accessible");
10288 }
d62a17ae 10289
05864da7
DS
10290 /* Display peer "from" output */
10291 /* This path was originated locally */
10292 if (path->peer == bgp->peer_self) {
d62a17ae 10293
7226bc40
TA
10294 if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
10295 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10296 if (json_paths)
05864da7
DS
10297 json_object_string_add(json_peer, "peerId",
10298 "0.0.0.0");
d62a17ae 10299 else
05864da7
DS
10300 vty_out(vty, " from 0.0.0.0 ");
10301 } else {
d62a17ae 10302 if (json_paths)
05864da7
DS
10303 json_object_string_add(json_peer, "peerId",
10304 "::");
d62a17ae 10305 else
05864da7 10306 vty_out(vty, " from :: ");
d62a17ae 10307 }
d62a17ae 10308
4e9a9863 10309 if (json_paths)
c949c771
DA
10310 json_object_string_addf(json_peer, "routerId", "%pI4",
10311 &bgp->router_id);
4e9a9863 10312 else
23d0a753 10313 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10314 }
d62a17ae 10315
05864da7
DS
10316 /* We RXed this path from one of our peers */
10317 else {
10318
10319 if (json_paths) {
47e12884
DA
10320 json_object_string_addf(json_peer, "peerId", "%pSU",
10321 &path->peer->su);
c949c771
DA
10322 json_object_string_addf(json_peer, "routerId", "%pI4",
10323 &path->peer->remote_id);
05864da7
DS
10324
10325 if (path->peer->hostname)
10326 json_object_string_add(json_peer, "hostname",
10327 path->peer->hostname);
10328
10329 if (path->peer->domainname)
10330 json_object_string_add(json_peer, "domainname",
10331 path->peer->domainname);
10332
10333 if (path->peer->conf_if)
10334 json_object_string_add(json_peer, "interface",
10335 path->peer->conf_if);
10336 } else {
10337 if (path->peer->conf_if) {
10338 if (path->peer->hostname
892fedb6
DA
10339 && CHECK_FLAG(path->peer->bgp->flags,
10340 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10341 vty_out(vty, " from %s(%s)",
10342 path->peer->hostname,
10343 path->peer->conf_if);
d62a17ae 10344 else
05864da7 10345 vty_out(vty, " from %s",
9b6d8fcf 10346 path->peer->conf_if);
d62a17ae 10347 } else {
05864da7 10348 if (path->peer->hostname
892fedb6
DA
10349 && CHECK_FLAG(path->peer->bgp->flags,
10350 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10351 vty_out(vty, " from %s(%s)",
10352 path->peer->hostname,
10353 path->peer->host);
d62a17ae 10354 else
47e12884
DA
10355 vty_out(vty, " from %pSU",
10356 &path->peer->su);
d62a17ae 10357 }
d62a17ae 10358
05864da7 10359 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10360 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10361 else
10362 vty_out(vty, " (%s)",
10363 inet_ntop(AF_INET,
10364 &path->peer->remote_id, buf1,
10365 sizeof(buf1)));
d62a17ae 10366 }
05864da7 10367 }
9df8b37c 10368
05864da7
DS
10369 /*
10370 * Note when vrfid of nexthop is different from that of prefix
10371 */
10372 if (path->extra && path->extra->bgp_orig) {
10373 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10374
05864da7
DS
10375 if (json_paths) {
10376 const char *vn;
9df8b37c 10377
05864da7
DS
10378 if (path->extra->bgp_orig->inst_type
10379 == BGP_INSTANCE_TYPE_DEFAULT)
10380 vn = VRF_DEFAULT_NAME;
10381 else
10382 vn = path->extra->bgp_orig->name;
9df8b37c 10383
05864da7 10384 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10385
05864da7
DS
10386 if (nexthop_vrfid == VRF_UNKNOWN) {
10387 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10388 } else {
05864da7
DS
10389 json_object_int_add(json_path, "nhVrfId",
10390 (int)nexthop_vrfid);
9df8b37c 10391 }
05864da7
DS
10392 } else {
10393 if (nexthop_vrfid == VRF_UNKNOWN)
10394 vty_out(vty, " vrf ?");
137147c6
DS
10395 else {
10396 struct vrf *vrf;
10397
10398 vrf = vrf_lookup_by_id(nexthop_vrfid);
10399 vty_out(vty, " vrf %s(%u)",
10400 VRF_LOGNAME(vrf), nexthop_vrfid);
10401 }
9df8b37c 10402 }
05864da7 10403 }
9df8b37c 10404
05864da7
DS
10405 if (nexthop_self) {
10406 if (json_paths) {
10407 json_object_boolean_true_add(json_path,
10408 "announceNexthopSelf");
10409 } else {
10410 vty_out(vty, " announce-nh-self");
9df8b37c 10411 }
05864da7 10412 }
9df8b37c 10413
05864da7
DS
10414 if (!json_paths)
10415 vty_out(vty, "\n");
d62a17ae 10416
05864da7
DS
10417 /* display the link-local nexthop */
10418 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10419 if (json_paths) {
10420 json_nexthop_ll = json_object_new_object();
c949c771
DA
10421 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10422 &attr->mp_nexthop_local);
515c2602 10423
939a97f4 10424 if (path->peer->hostname)
515c2602
DA
10425 json_object_string_add(json_nexthop_ll,
10426 "hostname",
939a97f4 10427 path->peer->hostname);
515c2602 10428
05864da7
DS
10429 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10430 json_object_string_add(json_nexthop_ll, "scope",
10431 "link-local");
d62a17ae 10432
05864da7
DS
10433 json_object_boolean_true_add(json_nexthop_ll,
10434 "accessible");
d62a17ae 10435
05864da7 10436 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10437 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10438 "used");
10439 else
10440 json_object_boolean_true_add(
10441 json_nexthop_global, "used");
10442 } else {
10443 vty_out(vty, " (%s) %s\n",
10444 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10445 buf, INET6_ADDRSTRLEN),
10446 attr->mp_nexthop_prefer_global
10447 ? "(prefer-global)"
10448 : "(used)");
d62a17ae 10449 }
05864da7
DS
10450 }
10451 /* If we do not have a link-local nexthop then we must flag the
10452 global as "used" */
10453 else {
10454 if (json_paths)
10455 json_object_boolean_true_add(json_nexthop_global,
10456 "used");
10457 }
d62a17ae 10458
b5e140c8 10459 if (safi == SAFI_EVPN &&
5e4d4c8a 10460 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10461 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10462 }
10463
05864da7
DS
10464 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10465 * Int/Ext/Local, Atomic, best */
10466 if (json_paths)
10467 json_object_string_add(json_path, "origin",
10468 bgp_origin_long_str[attr->origin]);
10469 else
10470 vty_out(vty, " Origin %s",
10471 bgp_origin_long_str[attr->origin]);
9df8b37c 10472
05864da7 10473 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10474 if (json_paths)
05864da7 10475 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10476 else
05864da7
DS
10477 vty_out(vty, ", metric %u", attr->med);
10478 }
9df8b37c 10479
05864da7
DS
10480 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10481 if (json_paths)
0fbac0b4 10482 json_object_int_add(json_path, "locPrf",
05864da7
DS
10483 attr->local_pref);
10484 else
10485 vty_out(vty, ", localpref %u", attr->local_pref);
10486 }
9df8b37c 10487
05864da7
DS
10488 if (attr->weight != 0) {
10489 if (json_paths)
10490 json_object_int_add(json_path, "weight", attr->weight);
10491 else
10492 vty_out(vty, ", weight %u", attr->weight);
10493 }
9df8b37c 10494
05864da7
DS
10495 if (attr->tag != 0) {
10496 if (json_paths)
10497 json_object_int_add(json_path, "tag", attr->tag);
10498 else
10499 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10500 }
9df8b37c 10501
05864da7
DS
10502 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10503 if (json_paths)
10504 json_object_boolean_false_add(json_path, "valid");
10505 else
10506 vty_out(vty, ", invalid");
10507 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10508 if (json_paths)
10509 json_object_boolean_true_add(json_path, "valid");
10510 else
10511 vty_out(vty, ", valid");
10512 }
9df8b37c 10513
7d3cae70
DA
10514 if (json_paths)
10515 json_object_int_add(json_path, "version", bn->version);
10516
05864da7
DS
10517 if (path->peer != bgp->peer_self) {
10518 if (path->peer->as == path->peer->local_as) {
10519 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10520 if (json_paths)
10521 json_object_string_add(
10522 json_peer, "type",
10523 "confed-internal");
d62a17ae 10524 else
05864da7 10525 vty_out(vty, ", confed-internal");
d62a17ae 10526 } else {
05864da7
DS
10527 if (json_paths)
10528 json_object_string_add(
10529 json_peer, "type", "internal");
10530 else
10531 vty_out(vty, ", internal");
9df8b37c 10532 }
05864da7
DS
10533 } else {
10534 if (bgp_confederation_peers_check(bgp,
10535 path->peer->as)) {
10536 if (json_paths)
10537 json_object_string_add(
10538 json_peer, "type",
10539 "confed-external");
d62a17ae 10540 else
05864da7 10541 vty_out(vty, ", confed-external");
d62a17ae 10542 } else {
05864da7
DS
10543 if (json_paths)
10544 json_object_string_add(
10545 json_peer, "type", "external");
10546 else
10547 vty_out(vty, ", external");
d62a17ae 10548 }
10549 }
05864da7
DS
10550 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10551 if (json_paths) {
10552 json_object_boolean_true_add(json_path, "aggregated");
10553 json_object_boolean_true_add(json_path, "local");
10554 } else {
10555 vty_out(vty, ", aggregated, local");
10556 }
10557 } else if (path->type != ZEBRA_ROUTE_BGP) {
10558 if (json_paths)
10559 json_object_boolean_true_add(json_path, "sourced");
10560 else
10561 vty_out(vty, ", sourced");
10562 } else {
10563 if (json_paths) {
10564 json_object_boolean_true_add(json_path, "sourced");
10565 json_object_boolean_true_add(json_path, "local");
10566 } else {
10567 vty_out(vty, ", sourced, local");
d62a17ae 10568 }
05864da7 10569 }
718e3744 10570
05864da7 10571 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10572 if (json_paths)
05864da7
DS
10573 json_object_boolean_true_add(json_path,
10574 "atomicAggregate");
d62a17ae 10575 else
05864da7
DS
10576 vty_out(vty, ", atomic-aggregate");
10577 }
d62a17ae 10578
d864dd9e
EB
10579 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10580 if (json_paths)
10581 json_object_int_add(json_path, "otc", attr->otc);
10582 else
10583 vty_out(vty, ", otc %u", attr->otc);
10584 }
10585
05864da7
DS
10586 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10587 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10588 && bgp_path_info_mpath_count(path))) {
10589 if (json_paths)
10590 json_object_boolean_true_add(json_path, "multipath");
10591 else
10592 vty_out(vty, ", multipath");
10593 }
50e05855 10594
05864da7
DS
10595 // Mark the bestpath(s)
10596 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10597 first_as = aspath_get_first_as(attr->aspath);
718e3744 10598
05864da7
DS
10599 if (json_paths) {
10600 if (!json_bestpath)
10601 json_bestpath = json_object_new_object();
10602 json_object_int_add(json_bestpath, "bestpathFromAs",
10603 first_as);
10604 } else {
10605 if (first_as)
10606 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10607 else
05864da7 10608 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10609 }
05864da7 10610 }
718e3744 10611
05864da7
DS
10612 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10613 if (json_paths) {
10614 if (!json_bestpath)
10615 json_bestpath = json_object_new_object();
10616 json_object_boolean_true_add(json_bestpath, "overall");
10617 json_object_string_add(
10618 json_bestpath, "selectionReason",
10619 bgp_path_selection_reason2str(bn->reason));
10620 } else {
10621 vty_out(vty, ", best");
10622 vty_out(vty, " (%s)",
10623 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10624 }
05864da7 10625 }
718e3744 10626
4027d19b 10627 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10628 if (json_paths)
10629 json_object_string_add(
10630 json_path, "rpkiValidationState",
4027d19b 10631 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10632 else
1d327209 10633 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10634 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10635 }
10636
05864da7
DS
10637 if (json_bestpath)
10638 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10639
05864da7
DS
10640 if (!json_paths)
10641 vty_out(vty, "\n");
10642
10643 /* Line 4 display Community */
29e72930 10644 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10645 if (json_paths) {
9a706b42
DA
10646 if (!bgp_attr_get_community(attr)->json)
10647 community_str(bgp_attr_get_community(attr),
c0945b78 10648 true, true);
9a706b42
DA
10649 json_object_lock(bgp_attr_get_community(attr)->json);
10650 json_object_object_add(
10651 json_path, "community",
10652 bgp_attr_get_community(attr)->json);
05864da7
DS
10653 } else {
10654 vty_out(vty, " Community: %s\n",
9a706b42 10655 bgp_attr_get_community(attr)->str);
d62a17ae 10656 }
05864da7 10657 }
718e3744 10658
05864da7
DS
10659 /* Line 5 display Extended-community */
10660 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10661 if (json_paths) {
10662 json_ext_community = json_object_new_object();
b53e67a3
DA
10663 json_object_string_add(
10664 json_ext_community, "string",
10665 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10666 json_object_object_add(json_path, "extendedCommunity",
10667 json_ext_community);
d62a17ae 10668 } else {
05864da7 10669 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10670 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10671 }
05864da7 10672 }
718e3744 10673
05864da7
DS
10674 /* Line 6 display Large community */
10675 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10676 if (json_paths) {
1bcf3a96
DA
10677 if (!bgp_attr_get_lcommunity(attr)->json)
10678 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10679 true, true);
1bcf3a96
DA
10680 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10681 json_object_object_add(
10682 json_path, "largeCommunity",
10683 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10684 } else {
10685 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10686 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10687 }
05864da7 10688 }
718e3744 10689
05864da7
DS
10690 /* Line 7 display Originator, Cluster-id */
10691 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10692 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10693 char buf[BUFSIZ] = {0};
10694
05864da7 10695 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10696 if (json_paths)
c949c771
DA
10697 json_object_string_addf(json_path,
10698 "originatorId", "%pI4",
10699 &attr->originator_id);
d62a17ae 10700 else
23d0a753
DA
10701 vty_out(vty, " Originator: %pI4",
10702 &attr->originator_id);
d62a17ae 10703 }
856ca177 10704
05864da7 10705 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10706 struct cluster_list *cluster =
10707 bgp_attr_get_cluster(attr);
05864da7 10708 int i;
d62a17ae 10709
10710 if (json_paths) {
05864da7
DS
10711 json_cluster_list = json_object_new_object();
10712 json_cluster_list_list =
10713 json_object_new_array();
10714
779fee93 10715 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10716 json_string = json_object_new_string(
779fee93
DS
10717 inet_ntop(AF_INET,
10718 &cluster->list[i],
10719 buf, sizeof(buf)));
05864da7
DS
10720 json_object_array_add(
10721 json_cluster_list_list,
10722 json_string);
10723 }
718e3744 10724
05864da7
DS
10725 /*
10726 * struct cluster_list does not have
10727 * "str" variable like aspath and community
10728 * do. Add this someday if someone asks
10729 * for it.
10730 * json_object_string_add(json_cluster_list,
779fee93 10731 * "string", cluster->str);
05864da7
DS
10732 */
10733 json_object_object_add(json_cluster_list,
10734 "list",
10735 json_cluster_list_list);
10736 json_object_object_add(json_path, "clusterList",
10737 json_cluster_list);
0dc8ee70 10738 } else {
05864da7
DS
10739 vty_out(vty, ", Cluster list: ");
10740
779fee93 10741 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10742 vty_out(vty, "%pI4 ",
779fee93 10743 &cluster->list[i]);
05864da7 10744 }
0dc8ee70 10745 }
d62a17ae 10746 }
718e3744 10747
d62a17ae 10748 if (!json_paths)
10749 vty_out(vty, "\n");
05864da7 10750 }
d62a17ae 10751
05864da7 10752 if (path->extra && path->extra->damp_info)
b4f7f45b 10753 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10754
05864da7
DS
10755 /* Remote Label */
10756 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10757 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10758 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10759 &bos);
d62a17ae 10760
05864da7
DS
10761 if (json_paths)
10762 json_object_int_add(json_path, "remoteLabel", label);
10763 else
10764 vty_out(vty, " Remote label: %d\n", label);
10765 }
d62a17ae 10766
e496b420
HS
10767 /* Remote SID */
10768 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10769 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10770 if (json_paths)
10771 json_object_string_add(json_path, "remoteSid", buf);
10772 else
10773 vty_out(vty, " Remote SID: %s\n", buf);
10774 }
10775
05864da7
DS
10776 /* Label Index */
10777 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10778 if (json_paths)
10779 json_object_int_add(json_path, "labelIndex",
10780 attr->label_index);
10781 else
10782 vty_out(vty, " Label Index: %d\n",
10783 attr->label_index);
10784 }
d62a17ae 10785
05864da7
DS
10786 /* Line 8 display Addpath IDs */
10787 if (path->addpath_rx_id
10788 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10789 if (json_paths) {
10790 json_object_int_add(json_path, "addpathRxId",
10791 path->addpath_rx_id);
d62a17ae 10792
05864da7
DS
10793 /* Keep backwards compatibility with the old API
10794 * by putting TX All's ID in the old field
10795 */
10796 json_object_int_add(
10797 json_path, "addpathTxId",
10798 path->tx_addpath
10799 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10800
05864da7
DS
10801 /* ... but create a specific field for each
10802 * strategy
10803 */
10804 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10805 json_object_int_add(
10806 json_path,
10807 bgp_addpath_names(i)->id_json_name,
10808 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10809 }
05864da7
DS
10810 } else {
10811 vty_out(vty, " AddPath ID: RX %u, ",
10812 path->addpath_rx_id);
d62a17ae 10813
05864da7 10814 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10815 }
05864da7 10816 }
520d5d76 10817
05864da7
DS
10818 /* If we used addpath to TX a non-bestpath we need to display
10819 * "Advertised to" on a path-by-path basis
10820 */
10821 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10822 first = 1;
dcc68b5e 10823
05864da7
DS
10824 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10825 addpath_capable =
10826 bgp_addpath_encode_tx(peer, afi, safi);
10827 has_adj = bgp_adj_out_lookup(
10828 peer, path->net,
10829 bgp_addpath_id_for_peer(peer, afi, safi,
10830 &path->tx_addpath));
10831
10832 if ((addpath_capable && has_adj)
10833 || (!addpath_capable && has_adj
10834 && CHECK_FLAG(path->flags,
10835 BGP_PATH_SELECTED))) {
10836 if (json_path && !json_adv_to)
10837 json_adv_to = json_object_new_object();
dcc68b5e 10838
05864da7
DS
10839 route_vty_out_advertised_to(
10840 vty, peer, &first,
10841 " Advertised to:", json_adv_to);
d62a17ae 10842 }
10843 }
718e3744 10844
05864da7
DS
10845 if (json_path) {
10846 if (json_adv_to) {
10847 json_object_object_add(
10848 json_path, "advertisedTo", json_adv_to);
d62a17ae 10849 }
05864da7
DS
10850 } else {
10851 if (!first) {
10852 vty_out(vty, "\n");
d62a17ae 10853 }
10854 }
05864da7 10855 }
b05a1c8b 10856
05864da7 10857 /* Line 9 display Uptime */
083ec940 10858 tbuf = time(NULL) - (monotime(NULL) - path->uptime);
05864da7
DS
10859 if (json_paths) {
10860 json_last_update = json_object_new_object();
10861 json_object_int_add(json_last_update, "epoch", tbuf);
10862 json_object_string_add(json_last_update, "string",
10863 ctime(&tbuf));
10864 json_object_object_add(json_path, "lastUpdate",
10865 json_last_update);
10866 } else
10867 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10868
05864da7
DS
10869 /* Line 10 display PMSI tunnel attribute, if present */
10870 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10871 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10872 bgp_attr_get_pmsi_tnl_type(attr),
10873 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10874
05864da7
DS
10875 if (json_paths) {
10876 json_pmsi = json_object_new_object();
10877 json_object_string_add(json_pmsi, "tunnelType", str);
10878 json_object_int_add(json_pmsi, "label",
10879 label2vni(&attr->label));
10880 json_object_object_add(json_path, "pmsi", json_pmsi);
10881 } else
10882 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10883 str, label2vni(&attr->label));
d62a17ae 10884 }
f1aa5d8a 10885
848e8cf6
DA
10886 if (path->peer->t_gr_restart &&
10887 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10888 unsigned long gr_remaining =
10889 thread_timer_remain_second(path->peer->t_gr_restart);
10890
10891 if (json_paths) {
10892 json_object_int_add(json_path,
10893 "gracefulRestartSecondsRemaining",
10894 gr_remaining);
10895 } else
10896 vty_out(vty,
10897 " Time until Graceful Restart stale route deleted: %lu\n",
10898 gr_remaining);
10899 }
10900
9a706b42
DA
10901 if (path->peer->t_llgr_stale[afi][safi] &&
10902 bgp_attr_get_community(attr) &&
10903 community_include(bgp_attr_get_community(attr),
10904 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10905 unsigned long llgr_remaining = thread_timer_remain_second(
10906 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10907
48ebba04
DA
10908 if (json_paths) {
10909 json_object_int_add(json_path, "llgrSecondsRemaining",
10910 llgr_remaining);
10911 } else
10912 vty_out(vty,
10913 " Time until Long-lived stale route deleted: %lu\n",
10914 llgr_remaining);
10915 }
10916
92269aa2
DS
10917 /* Output some debug about internal state of the dest flags */
10918 if (json_paths) {
10919 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10920 json_object_boolean_true_add(json_path, "processScheduled");
10921 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10922 json_object_boolean_true_add(json_path, "userCleared");
10923 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10924 json_object_boolean_true_add(json_path, "labelChanged");
10925 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10926 json_object_boolean_true_add(json_path, "registeredForLabel");
10927 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10928 json_object_boolean_true_add(json_path, "selectDefered");
10929 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10930 json_object_boolean_true_add(json_path, "fibInstalled");
10931 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10932 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10933
d62a17ae 10934 if (json_nexthop_global || json_nexthop_ll) {
10935 json_nexthops = json_object_new_array();
f1aa5d8a 10936
d62a17ae 10937 if (json_nexthop_global)
10938 json_object_array_add(json_nexthops,
10939 json_nexthop_global);
f1aa5d8a 10940
d62a17ae 10941 if (json_nexthop_ll)
10942 json_object_array_add(json_nexthops,
10943 json_nexthop_ll);
f1aa5d8a 10944
d62a17ae 10945 json_object_object_add(json_path, "nexthops",
10946 json_nexthops);
10947 }
10948
10949 json_object_object_add(json_path, "peer", json_peer);
10950 json_object_array_add(json_paths, json_path);
05864da7 10951 }
b366b518
BB
10952}
10953
96ade3ed 10954#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10955#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10956#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10957
a4d82a8a 10958static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10959 afi_t afi, safi_t safi, enum bgp_show_type type,
10960 bool use_json);
7f323236
DW
10961static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10962 const char *comstr, int exact, afi_t afi,
96c81f66 10963 safi_t safi, uint16_t show_flags);
d62a17ae 10964
1ae44dfc 10965static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10966 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10967 void *output_arg, const char *rd, int is_last,
96f3485c 10968 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10969 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10970 enum rpki_states rpki_target_state)
d62a17ae 10971{
40381db7 10972 struct bgp_path_info *pi;
9bcb3eef 10973 struct bgp_dest *dest;
2aad8c42
MS
10974 bool header = true;
10975 bool json_detail_header = false;
d62a17ae 10976 int display;
1ae44dfc
LB
10977 unsigned long output_count = 0;
10978 unsigned long total_count = 0;
d62a17ae 10979 struct prefix *p;
d62a17ae 10980 json_object *json_paths = NULL;
10981 int first = 1;
96f3485c
MK
10982 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10983 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10984 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10985
1ae44dfc 10986 if (output_cum && *output_cum != 0)
2aad8c42 10987 header = false;
1ae44dfc 10988
9386b588 10989 if (use_json && !*json_header_depth) {
96f3485c
MK
10990 if (all)
10991 *json_header_depth = 1;
10992 else {
10993 vty_out(vty, "{\n");
10994 *json_header_depth = 2;
10995 }
10996
d62a17ae 10997 vty_out(vty,
23d0a753
DA
10998 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10999 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 11000 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 11001 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 11002 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
11003 ? VRF_DEFAULT_NAME
11004 : bgp->name,
11005 table->version, &bgp->router_id,
01eced22 11006 bgp->default_local_pref, bgp->as);
9386b588 11007 if (rd) {
445c2480 11008 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
11009 ++*json_header_depth;
11010 }
d62a17ae 11011 }
718e3744 11012
445c2480
DS
11013 if (use_json && rd) {
11014 vty_out(vty, " \"%s\" : { ", rd);
11015 }
11016
2aad8c42
MS
11017 /* Check for 'json detail', where we need header output once per dest */
11018 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
11019 type != bgp_show_type_dampend_paths &&
11020 type != bgp_show_type_damp_neighbor &&
11021 type != bgp_show_type_flap_statistics &&
11022 type != bgp_show_type_flap_neighbor)
11023 json_detail_header = true;
11024
d62a17ae 11025 /* Start processing of routes. */
9bcb3eef
DS
11026 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
11027 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 11028 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 11029 bool json_detail = json_detail_header;
b54892e0 11030
9bcb3eef 11031 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 11032 if (pi == NULL)
98ce9a06 11033 continue;
d62a17ae 11034
98ce9a06 11035 display = 0;
98ce9a06
DS
11036 if (use_json)
11037 json_paths = json_object_new_array();
11038 else
11039 json_paths = NULL;
d62a17ae 11040
6f94b685 11041 for (; pi; pi = pi->next) {
9a706b42
DA
11042 struct community *picomm = NULL;
11043
11044 picomm = bgp_attr_get_community(pi->attr);
11045
98ce9a06 11046 total_count++;
1e2ce4f1 11047
7d3cae70
DA
11048 if (type == bgp_show_type_prefix_version) {
11049 uint32_t version =
11050 strtoul(output_arg, NULL, 10);
11051 if (dest->version < version)
11052 continue;
11053 }
11054
a70a28a5
DA
11055 if (type == bgp_show_type_community_alias) {
11056 char *alias = output_arg;
11057 char **communities;
11058 int num;
11059 bool found = false;
11060
9a706b42
DA
11061 if (picomm) {
11062 frrstr_split(picomm->str, " ",
11063 &communities, &num);
a70a28a5
DA
11064 for (int i = 0; i < num; i++) {
11065 const char *com2alias =
11066 bgp_community2alias(
11067 communities[i]);
cd9cc0e6
IR
11068 if (!found
11069 && strcmp(alias, com2alias)
11070 == 0)
a70a28a5 11071 found = true;
cd9cc0e6
IR
11072 XFREE(MTYPE_TMP,
11073 communities[i]);
a70a28a5 11074 }
cd9cc0e6 11075 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11076 }
11077
1bcf3a96
DA
11078 if (!found &&
11079 bgp_attr_get_lcommunity(pi->attr)) {
11080 frrstr_split(bgp_attr_get_lcommunity(
11081 pi->attr)
11082 ->str,
a70a28a5
DA
11083 " ", &communities, &num);
11084 for (int i = 0; i < num; i++) {
11085 const char *com2alias =
11086 bgp_community2alias(
11087 communities[i]);
cd9cc0e6
IR
11088 if (!found
11089 && strcmp(alias, com2alias)
11090 == 0)
a70a28a5 11091 found = true;
cd9cc0e6
IR
11092 XFREE(MTYPE_TMP,
11093 communities[i]);
a70a28a5 11094 }
cd9cc0e6 11095 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11096 }
11097
11098 if (!found)
11099 continue;
11100 }
11101
1e2ce4f1
DS
11102 if (type == bgp_show_type_rpki) {
11103 if (dest_p->family == AF_INET
11104 || dest_p->family == AF_INET6)
4027d19b 11105 rpki_curr_state = hook_call(
1e2ce4f1
DS
11106 bgp_rpki_prefix_status,
11107 pi->peer, pi->attr, dest_p);
4027d19b
DS
11108 if (rpki_target_state != RPKI_NOT_BEING_USED
11109 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11110 continue;
11111 }
11112
98ce9a06
DS
11113 if (type == bgp_show_type_flap_statistics
11114 || type == bgp_show_type_flap_neighbor
11115 || type == bgp_show_type_dampend_paths
11116 || type == bgp_show_type_damp_neighbor) {
40381db7 11117 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11118 continue;
11119 }
11120 if (type == bgp_show_type_regexp) {
11121 regex_t *regex = output_arg;
d62a17ae 11122
40381db7 11123 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11124 == REG_NOMATCH)
11125 continue;
11126 }
11127 if (type == bgp_show_type_prefix_list) {
11128 struct prefix_list *plist = output_arg;
d62a17ae 11129
9bcb3eef 11130 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11131 != PREFIX_PERMIT)
11132 continue;
11133 }
ed126382
DA
11134 if (type == bgp_show_type_access_list) {
11135 struct access_list *alist = output_arg;
11136
11137 if (access_list_apply(alist, dest_p) !=
11138 FILTER_PERMIT)
11139 continue;
11140 }
98ce9a06
DS
11141 if (type == bgp_show_type_filter_list) {
11142 struct as_list *as_list = output_arg;
d62a17ae 11143
40381db7 11144 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11145 != AS_FILTER_PERMIT)
11146 continue;
11147 }
11148 if (type == bgp_show_type_route_map) {
11149 struct route_map *rmap = output_arg;
9b6d8fcf 11150 struct bgp_path_info path;
98ce9a06 11151 struct attr dummy_attr;
b68885f9 11152 route_map_result_t ret;
d62a17ae 11153
6f4f49b2 11154 dummy_attr = *pi->attr;
d62a17ae 11155
40381db7 11156 path.peer = pi->peer;
9b6d8fcf 11157 path.attr = &dummy_attr;
d62a17ae 11158
1782514f 11159 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11160 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11161 if (ret == RMAP_DENYMATCH)
11162 continue;
11163 }
11164 if (type == bgp_show_type_neighbor
11165 || type == bgp_show_type_flap_neighbor
11166 || type == bgp_show_type_damp_neighbor) {
11167 union sockunion *su = output_arg;
11168
40381db7
DS
11169 if (pi->peer == NULL
11170 || pi->peer->su_remote == NULL
11171 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11172 continue;
11173 }
11174 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11175 uint32_t destination;
d62a17ae 11176
9bcb3eef 11177 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11178 if (IN_CLASSC(destination)
9bcb3eef 11179 && dest_p->prefixlen == 24)
98ce9a06
DS
11180 continue;
11181 if (IN_CLASSB(destination)
9bcb3eef 11182 && dest_p->prefixlen == 16)
98ce9a06
DS
11183 continue;
11184 if (IN_CLASSA(destination)
9bcb3eef 11185 && dest_p->prefixlen == 8)
98ce9a06
DS
11186 continue;
11187 }
11188 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11189 p = output_arg;
9bcb3eef 11190 if (!prefix_match(p, dest_p))
98ce9a06
DS
11191 continue;
11192 }
11193 if (type == bgp_show_type_community_all) {
9a706b42 11194 if (!picomm)
98ce9a06
DS
11195 continue;
11196 }
11197 if (type == bgp_show_type_community) {
11198 struct community *com = output_arg;
d62a17ae 11199
9a706b42 11200 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11201 continue;
11202 }
11203 if (type == bgp_show_type_community_exact) {
11204 struct community *com = output_arg;
d62a17ae 11205
9a706b42 11206 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11207 continue;
11208 }
11209 if (type == bgp_show_type_community_list) {
11210 struct community_list *list = output_arg;
d62a17ae 11211
9a706b42 11212 if (!community_list_match(picomm, list))
98ce9a06
DS
11213 continue;
11214 }
a4d82a8a 11215 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11216 struct community_list *list = output_arg;
d62a17ae 11217
9a706b42 11218 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11219 continue;
11220 }
11221 if (type == bgp_show_type_lcommunity) {
11222 struct lcommunity *lcom = output_arg;
d62a17ae 11223
1bcf3a96
DA
11224 if (!bgp_attr_get_lcommunity(pi->attr) ||
11225 !lcommunity_match(
11226 bgp_attr_get_lcommunity(pi->attr),
11227 lcom))
98ce9a06
DS
11228 continue;
11229 }
36a206db 11230
11231 if (type == bgp_show_type_lcommunity_exact) {
11232 struct lcommunity *lcom = output_arg;
11233
1bcf3a96
DA
11234 if (!bgp_attr_get_lcommunity(pi->attr) ||
11235 !lcommunity_cmp(
11236 bgp_attr_get_lcommunity(pi->attr),
11237 lcom))
36a206db 11238 continue;
11239 }
98ce9a06
DS
11240 if (type == bgp_show_type_lcommunity_list) {
11241 struct community_list *list = output_arg;
d62a17ae 11242
1bcf3a96
DA
11243 if (!lcommunity_list_match(
11244 bgp_attr_get_lcommunity(pi->attr),
11245 list))
98ce9a06
DS
11246 continue;
11247 }
36a206db 11248 if (type
11249 == bgp_show_type_lcommunity_list_exact) {
11250 struct community_list *list = output_arg;
11251
11252 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11253 bgp_attr_get_lcommunity(pi->attr),
11254 list))
36a206db 11255 continue;
11256 }
98ce9a06 11257 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11258 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11259 continue;
11260 }
11261 if (type == bgp_show_type_dampend_paths
11262 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11263 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11264 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11265 continue;
11266 }
11267
11268 if (!use_json && header) {
23d0a753
DA
11269 vty_out(vty,
11270 "BGP table version is %" PRIu64
11271 ", local router ID is %pI4, vrf id ",
11272 table->version, &bgp->router_id);
9df8b37c
PZ
11273 if (bgp->vrf_id == VRF_UNKNOWN)
11274 vty_out(vty, "%s", VRFID_NONE_STR);
11275 else
11276 vty_out(vty, "%u", bgp->vrf_id);
11277 vty_out(vty, "\n");
01eced22
AD
11278 vty_out(vty, "Default local pref %u, ",
11279 bgp->default_local_pref);
11280 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11281 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11282 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11283 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11284 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11285 if (type == bgp_show_type_dampend_paths
11286 || type == bgp_show_type_damp_neighbor)
98ce9a06 11287 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11288 else if (type == bgp_show_type_flap_statistics
11289 || type == bgp_show_type_flap_neighbor)
98ce9a06 11290 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11291 else
ae248832
MK
11292 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11293 : BGP_SHOW_HEADER));
2aad8c42
MS
11294 header = false;
11295
11296 } else if (json_detail && json_paths != NULL) {
11297 const struct prefix_rd *prd;
11298 json_object *jtemp;
11299
11300 /* Use common detail header, for most types;
11301 * need a json 'object'.
11302 */
11303
11304 jtemp = json_object_new_object();
11305 prd = bgp_rd_from_dest(dest, safi);
11306
11307 route_vty_out_detail_header(
11308 vty, bgp, dest, prd, table->afi,
11309 safi, jtemp);
11310
11311 json_object_array_add(json_paths, jtemp);
11312
11313 json_detail = false;
d62a17ae 11314 }
2aad8c42 11315
98ce9a06
DS
11316 if (rd != NULL && !display && !output_count) {
11317 if (!use_json)
11318 vty_out(vty,
11319 "Route Distinguisher: %s\n",
11320 rd);
d62a17ae 11321 }
98ce9a06
DS
11322 if (type == bgp_show_type_dampend_paths
11323 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11324 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11325 AFI_IP, safi, use_json,
11326 json_paths);
98ce9a06
DS
11327 else if (type == bgp_show_type_flap_statistics
11328 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11329 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11330 AFI_IP, safi, use_json,
11331 json_paths);
f280c93b
DA
11332 else {
11333 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11334 route_vty_out_detail(
11335 vty, bgp, dest, pi,
11336 family2afi(dest_p->family),
11337 safi, RPKI_NOT_BEING_USED,
11338 json_paths);
11339 else
11340 route_vty_out(vty, dest_p, pi, display,
11341 safi, json_paths, wide);
11342 }
98ce9a06 11343 display++;
d62a17ae 11344 }
11345
98ce9a06
DS
11346 if (display) {
11347 output_count++;
11348 if (!use_json)
11349 continue;
11350
625d2931 11351 /* encode prefix */
9bcb3eef 11352 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11353 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11354
1840384b 11355
b54892e0
DS
11356 bgp_fs_nlri_get_string(
11357 (unsigned char *)
9bcb3eef
DS
11358 dest_p->u.prefix_flowspec.ptr,
11359 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11360 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11361 family2afi(dest_p->u
11362 .prefix_flowspec.family));
625d2931 11363 if (first)
b54892e0 11364 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11365 dest_p->u.prefix_flowspec
b54892e0 11366 .prefixlen);
625d2931 11367 else
b54892e0 11368 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11369 dest_p->u.prefix_flowspec
b54892e0 11370 .prefixlen);
625d2931 11371 } else {
625d2931 11372 if (first)
1b78780b 11373 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11374 else
1b78780b 11375 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11376 }
3757f964 11377 vty_json(vty, json_paths);
449feb8e 11378 json_paths = NULL;
98ce9a06 11379 first = 0;
1f83ed02
DS
11380 } else
11381 json_object_free(json_paths);
98ce9a06
DS
11382 }
11383
1ae44dfc
LB
11384 if (output_cum) {
11385 output_count += *output_cum;
11386 *output_cum = output_count;
11387 }
11388 if (total_cum) {
11389 total_count += *total_cum;
11390 *total_cum = total_count;
11391 }
d62a17ae 11392 if (use_json) {
9386b588 11393 if (rd) {
a4d82a8a 11394 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11395 }
11396 if (is_last) {
a4d82a8a
PZ
11397 unsigned long i;
11398 for (i = 0; i < *json_header_depth; ++i)
11399 vty_out(vty, " } ");
96f3485c
MK
11400 if (!all)
11401 vty_out(vty, "\n");
9386b588 11402 }
d62a17ae 11403 } else {
1ae44dfc
LB
11404 if (is_last) {
11405 /* No route is displayed */
11406 if (output_count == 0) {
11407 if (type == bgp_show_type_normal)
11408 vty_out(vty,
11409 "No BGP prefixes displayed, %ld exist\n",
11410 total_count);
11411 } else
d62a17ae 11412 vty_out(vty,
1ae44dfc
LB
11413 "\nDisplayed %ld routes and %ld total paths\n",
11414 output_count, total_count);
11415 }
d62a17ae 11416 }
718e3744 11417
d62a17ae 11418 return CMD_SUCCESS;
718e3744 11419}
11420
1ae44dfc
LB
11421int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11422 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11423 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11424{
9bcb3eef 11425 struct bgp_dest *dest, *next;
1ae44dfc
LB
11426 unsigned long output_cum = 0;
11427 unsigned long total_cum = 0;
9386b588 11428 unsigned long json_header_depth = 0;
67009e22 11429 struct bgp_table *itable;
0136788c 11430 bool show_msg;
96c81f66 11431 uint16_t show_flags = 0;
0136788c
LB
11432
11433 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11434
96f3485c
MK
11435 if (use_json)
11436 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11437
9bcb3eef
DS
11438 for (dest = bgp_table_top(table); dest; dest = next) {
11439 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11440
9bcb3eef
DS
11441 next = bgp_route_next(dest);
11442 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11443 continue;
67009e22 11444
9bcb3eef 11445 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11446 if (itable != NULL) {
1ae44dfc 11447 struct prefix_rd prd;
06b9f471 11448 char rd[RD_ADDRSTRLEN];
1ae44dfc 11449
9bcb3eef 11450 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11451 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11452 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11453 rd, next == NULL, &output_cum,
11454 &total_cum, &json_header_depth,
1e2ce4f1 11455 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11456 if (next == NULL)
11457 show_msg = false;
1ae44dfc
LB
11458 }
11459 }
0136788c
LB
11460 if (show_msg) {
11461 if (output_cum == 0)
11462 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11463 total_cum);
11464 else
11465 vty_out(vty,
11466 "\nDisplayed %ld routes and %ld total paths\n",
11467 output_cum, total_cum);
11468 }
1ae44dfc
LB
11469 return CMD_SUCCESS;
11470}
2aad8c42 11471
d62a17ae 11472static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11473 enum bgp_show_type type, void *output_arg,
96c81f66 11474 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11475{
d62a17ae 11476 struct bgp_table *table;
9386b588 11477 unsigned long json_header_depth = 0;
96f3485c 11478 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11479
d62a17ae 11480 if (bgp == NULL) {
11481 bgp = bgp_get_default();
11482 }
fee0f4c6 11483
d62a17ae 11484 if (bgp == NULL) {
11485 if (!use_json)
11486 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11487 else
11488 vty_out(vty, "{}\n");
d62a17ae 11489 return CMD_WARNING;
11490 }
4dd6177e 11491
cd8c2a27
MS
11492 /* Labeled-unicast routes live in the unicast table. */
11493 if (safi == SAFI_LABELED_UNICAST)
11494 safi = SAFI_UNICAST;
11495
1ae44dfc 11496 table = bgp->rib[afi][safi];
d62a17ae 11497 /* use MPLS and ENCAP specific shows until they are merged */
11498 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11499 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11500 output_arg, use_json);
d62a17ae 11501 }
dba3c1d3
PG
11502
11503 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11504 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11505 output_arg, use_json,
11506 1, NULL, NULL);
11507 }
fee0f4c6 11508
96f3485c 11509 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11510 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11511 rpki_target_state);
fee0f4c6 11512}
11513
d62a17ae 11514static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11515 safi_t safi, uint16_t show_flags)
f186de26 11516{
d62a17ae 11517 struct listnode *node, *nnode;
11518 struct bgp *bgp;
11519 int is_first = 1;
9f049418 11520 bool route_output = false;
96f3485c 11521 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11522
d62a17ae 11523 if (use_json)
11524 vty_out(vty, "{\n");
9f689658 11525
d62a17ae 11526 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11527 route_output = true;
d62a17ae 11528 if (use_json) {
11529 if (!is_first)
11530 vty_out(vty, ",\n");
11531 else
11532 is_first = 0;
11533
11534 vty_out(vty, "\"%s\":",
11535 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11536 ? VRF_DEFAULT_NAME
d62a17ae 11537 : bgp->name);
11538 } else {
11539 vty_out(vty, "\nInstance %s:\n",
11540 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11541 ? VRF_DEFAULT_NAME
d62a17ae 11542 : bgp->name);
11543 }
11544 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11545 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11546 }
9f689658 11547
d62a17ae 11548 if (use_json)
11549 vty_out(vty, "}\n");
9f049418
DS
11550 else if (!route_output)
11551 vty_out(vty, "%% BGP instance not found\n");
f186de26 11552}
11553
718e3744 11554/* Header of detailed BGP route information */
d62a17ae 11555void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11556 struct bgp_dest *dest,
11557 const struct prefix_rd *prd,
d62a17ae 11558 afi_t afi, safi_t safi, json_object *json)
11559{
40381db7 11560 struct bgp_path_info *pi;
b54892e0 11561 const struct prefix *p;
d62a17ae 11562 struct peer *peer;
11563 struct listnode *node, *nnode;
06b9f471 11564 char buf1[RD_ADDRSTRLEN];
d62a17ae 11565 int count = 0;
11566 int best = 0;
11567 int suppress = 0;
c5f1e1b2
C
11568 int accept_own = 0;
11569 int route_filter_translated_v4 = 0;
11570 int route_filter_v4 = 0;
11571 int route_filter_translated_v6 = 0;
11572 int route_filter_v6 = 0;
11573 int llgr_stale = 0;
11574 int no_llgr = 0;
11575 int accept_own_nexthop = 0;
11576 int blackhole = 0;
d62a17ae 11577 int no_export = 0;
11578 int no_advertise = 0;
11579 int local_as = 0;
c5f1e1b2 11580 int no_peer = 0;
d62a17ae 11581 int first = 1;
11582 int has_valid_label = 0;
11583 mpls_label_t label = 0;
11584 json_object *json_adv_to = NULL;
67f67ba4
DA
11585 uint32_t ttl = 0;
11586 uint32_t bos = 0;
11587 uint32_t exp = 0;
9bedbb1e 11588
67f67ba4 11589 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11590
67f67ba4
DA
11591 p = bgp_dest_get_prefix(dest);
11592 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11593
44c69747 11594 if (safi == SAFI_EVPN) {
44c69747 11595 if (!json) {
2dbe669b 11596 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11597 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11598 : "",
2dbe669b 11599 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11600 } else {
11601 json_object_string_add(json, "rd",
11602 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11603 "");
11604 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11605 }
11606 } else {
11607 if (!json) {
9119ef3a
DA
11608 vty_out(vty,
11609 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11610 "\n",
d62a17ae 11611 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11612 ? prefix_rd2str(prd, buf1,
11613 sizeof(buf1))
11614 : ""),
9119ef3a
DA
11615 safi == SAFI_MPLS_VPN ? ":" : "", p,
11616 dest->version);
cd1964ff 11617
9119ef3a 11618 } else {
67d7e256 11619 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11620 json_object_int_add(json, "version", dest->version);
11621
11622 }
44c69747
LK
11623 }
11624
11625 if (has_valid_label) {
11626 if (json)
11627 json_object_int_add(json, "localLabel", label);
11628 else
d62a17ae 11629 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11630 }
11631
11632 if (!json)
d62a17ae 11633 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11634 vty_out(vty, "not allocated\n");
718e3744 11635
9bcb3eef 11636 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11637 struct community *picomm = NULL;
11638
11639 picomm = bgp_attr_get_community(pi->attr);
11640
d62a17ae 11641 count++;
40381db7 11642 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11643 best = count;
4056a5f6 11644 if (bgp_path_suppressed(pi))
d62a17ae 11645 suppress = 1;
cee9c031 11646
9a706b42 11647 if (!picomm)
cee9c031
QY
11648 continue;
11649
11650 no_advertise += community_include(
9a706b42
DA
11651 picomm, COMMUNITY_NO_ADVERTISE);
11652 no_export +=
11653 community_include(picomm, COMMUNITY_NO_EXPORT);
11654 local_as +=
11655 community_include(picomm, COMMUNITY_LOCAL_AS);
11656 accept_own +=
11657 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11658 route_filter_translated_v4 += community_include(
9a706b42 11659 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11660 route_filter_translated_v6 += community_include(
9a706b42 11661 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11662 route_filter_v4 += community_include(
9a706b42 11663 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11664 route_filter_v6 += community_include(
9a706b42
DA
11665 picomm, COMMUNITY_ROUTE_FILTER_v6);
11666 llgr_stale +=
11667 community_include(picomm, COMMUNITY_LLGR_STALE);
11668 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11669 accept_own_nexthop += community_include(
11670 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11671 blackhole +=
11672 community_include(picomm, COMMUNITY_BLACKHOLE);
11673 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11674 }
718e3744 11675 }
718e3744 11676
d62a17ae 11677 if (!json) {
11678 vty_out(vty, "Paths: (%d available", count);
11679 if (best) {
11680 vty_out(vty, ", best #%d", best);
b84060bb
PG
11681 if (safi == SAFI_UNICAST) {
11682 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11683 vty_out(vty, ", table %s",
11684 VRF_DEFAULT_NAME);
11685 else
11686 vty_out(vty, ", vrf %s",
11687 bgp->name);
11688 }
d62a17ae 11689 } else
11690 vty_out(vty, ", no best path");
11691
c5f1e1b2
C
11692 if (accept_own)
11693 vty_out(vty,
11694 ", accept own local route exported and imported in different VRF");
11695 else if (route_filter_translated_v4)
11696 vty_out(vty,
11697 ", mark translated RTs for VPNv4 route filtering");
11698 else if (route_filter_v4)
11699 vty_out(vty,
11700 ", attach RT as-is for VPNv4 route filtering");
11701 else if (route_filter_translated_v6)
11702 vty_out(vty,
11703 ", mark translated RTs for VPNv6 route filtering");
11704 else if (route_filter_v6)
11705 vty_out(vty,
11706 ", attach RT as-is for VPNv6 route filtering");
11707 else if (llgr_stale)
11708 vty_out(vty,
1479ed2f 11709 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11710 else if (no_llgr)
11711 vty_out(vty,
11712 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11713 else if (accept_own_nexthop)
11714 vty_out(vty,
11715 ", accept local nexthop");
11716 else if (blackhole)
11717 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11718 else if (no_export)
11719 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11720 else if (no_advertise)
11721 vty_out(vty, ", not advertised to any peer");
d62a17ae 11722 else if (local_as)
11723 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11724 else if (no_peer)
11725 vty_out(vty,
11726 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11727
11728 if (suppress)
11729 vty_out(vty,
11730 ", Advertisements suppressed by an aggregate.");
11731 vty_out(vty, ")\n");
11732 }
718e3744 11733
d62a17ae 11734 /* If we are not using addpath then we can display Advertised to and
11735 * that will
11736 * show what peers we advertised the bestpath to. If we are using
11737 * addpath
11738 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11739 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11740 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11741 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11742 if (json && !json_adv_to)
11743 json_adv_to = json_object_new_object();
11744
11745 route_vty_out_advertised_to(
11746 vty, peer, &first,
11747 " Advertised to non peer-group peers:\n ",
11748 json_adv_to);
11749 }
11750 }
11751
11752 if (json) {
11753 if (json_adv_to) {
11754 json_object_object_add(json, "advertisedTo",
11755 json_adv_to);
11756 }
11757 } else {
11758 if (first)
11759 vty_out(vty, " Not advertised to any peer");
11760 vty_out(vty, "\n");
11761 }
11762 }
718e3744 11763}
11764
edfee30d 11765static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11766 struct bgp_dest *bgp_node, struct vty *vty,
11767 struct bgp *bgp, afi_t afi, safi_t safi,
11768 json_object *json, enum bgp_path_type pathtype,
4027d19b 11769 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11770{
11771 struct bgp_path_info *pi;
11772 int header = 1;
11773 char rdbuf[RD_ADDRSTRLEN];
11774 json_object *json_header = NULL;
11775 json_object *json_paths = NULL;
4933eaaf 11776 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11777
9bcb3eef 11778 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11779 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11780
11781 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11782 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11783 pi->peer, pi->attr, p);
4933eaaf 11784
4027d19b
DS
11785 if (rpki_target_state != RPKI_NOT_BEING_USED
11786 && rpki_curr_state != rpki_target_state)
4933eaaf 11787 continue;
44c69747
LK
11788
11789 if (json && !json_paths) {
11790 /* Instantiate json_paths only if path is valid */
11791 json_paths = json_object_new_array();
11792 if (pfx_rd) {
11793 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11794 json_header = json_object_new_object();
11795 } else
11796 json_header = json;
11797 }
11798
11799 if (header) {
11800 route_vty_out_detail_header(
11801 vty, bgp, bgp_node, pfx_rd,
11802 AFI_IP, safi, json_header);
11803 header = 0;
11804 }
11805 (*display)++;
11806
11807 if (pathtype == BGP_PATH_SHOW_ALL
11808 || (pathtype == BGP_PATH_SHOW_BESTPATH
11809 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11810 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11811 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11812 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11813 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11814 safi, rpki_curr_state, json_paths);
44c69747
LK
11815 }
11816
11817 if (json && json_paths) {
11818 json_object_object_add(json_header, "paths", json_paths);
11819
11820 if (pfx_rd)
11821 json_object_object_add(json, rdbuf, json_header);
11822 }
11823}
11824
2aad8c42
MS
11825/*
11826 * Return rd based on safi
11827 */
11828static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11829 safi_t safi)
11830{
11831 switch (safi) {
11832 case SAFI_MPLS_VPN:
11833 case SAFI_ENCAP:
11834 case SAFI_EVPN:
11835 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11836 default:
11837 return NULL;
11838
11839 }
11840}
11841
718e3744 11842/* Display specified route of BGP table. */
d62a17ae 11843static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11844 struct bgp_table *rib, const char *ip_str,
11845 afi_t afi, safi_t safi,
4027d19b 11846 enum rpki_states rpki_target_state,
d62a17ae 11847 struct prefix_rd *prd, int prefix_check,
9f049418 11848 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11849{
11850 int ret;
d62a17ae 11851 int display = 0;
11852 struct prefix match;
9bcb3eef
DS
11853 struct bgp_dest *dest;
11854 struct bgp_dest *rm;
d62a17ae 11855 struct bgp_table *table;
11856 json_object *json = NULL;
11857 json_object *json_paths = NULL;
11858
11859 /* Check IP address argument. */
11860 ret = str2prefix(ip_str, &match);
11861 if (!ret) {
11862 vty_out(vty, "address is malformed\n");
11863 return CMD_WARNING;
11864 }
718e3744 11865
d62a17ae 11866 match.family = afi2family(afi);
b05a1c8b 11867
44c69747 11868 if (use_json)
d62a17ae 11869 json = json_object_new_object();
718e3744 11870
44c69747 11871 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11872 for (dest = bgp_table_top(rib); dest;
11873 dest = bgp_route_next(dest)) {
11874 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11875
9bcb3eef 11876 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11877 continue;
9bcb3eef 11878 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11879 if (!table)
ea47320b 11880 continue;
d62a17ae 11881
4953391b
DA
11882 rm = bgp_node_match(table, &match);
11883 if (rm == NULL)
ea47320b 11884 continue;
d62a17ae 11885
9bcb3eef 11886 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11887 if (prefix_check
b54892e0 11888 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11889 bgp_dest_unlock_node(rm);
ea47320b
DL
11890 continue;
11891 }
d62a17ae 11892
9bcb3eef 11893 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11894 bgp, afi, safi, json, pathtype,
4027d19b 11895 &display, rpki_target_state);
44c69747 11896
9bcb3eef 11897 bgp_dest_unlock_node(rm);
44c69747
LK
11898 }
11899 } else if (safi == SAFI_EVPN) {
9bcb3eef 11900 struct bgp_dest *longest_pfx;
cded3b72 11901 bool is_exact_pfxlen_match = false;
44c69747 11902
9bcb3eef
DS
11903 for (dest = bgp_table_top(rib); dest;
11904 dest = bgp_route_next(dest)) {
11905 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11906
9bcb3eef 11907 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11908 continue;
9bcb3eef 11909 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11910 if (!table)
11911 continue;
11912
11913 longest_pfx = NULL;
cded3b72 11914 is_exact_pfxlen_match = false;
44c69747
LK
11915 /*
11916 * Search through all the prefixes for a match. The
11917 * pfx's are enumerated in ascending order of pfxlens.
11918 * So, the last pfx match is the longest match. Set
11919 * is_exact_pfxlen_match when we get exact pfxlen match
11920 */
11921 for (rm = bgp_table_top(table); rm;
11922 rm = bgp_route_next(rm)) {
b54892e0 11923 const struct prefix *rm_p =
9bcb3eef 11924 bgp_dest_get_prefix(rm);
44c69747
LK
11925 /*
11926 * Get prefixlen of the ip-prefix within type5
11927 * evpn route
11928 */
b54892e0
DS
11929 if (evpn_type5_prefix_match(rm_p, &match)
11930 && rm->info) {
44c69747
LK
11931 longest_pfx = rm;
11932 int type5_pfxlen =
b54892e0
DS
11933 bgp_evpn_get_type5_prefixlen(
11934 rm_p);
44c69747 11935 if (type5_pfxlen == match.prefixlen) {
cded3b72 11936 is_exact_pfxlen_match = true;
9bcb3eef 11937 bgp_dest_unlock_node(rm);
44c69747
LK
11938 break;
11939 }
d62a17ae 11940 }
11941 }
ea47320b 11942
44c69747
LK
11943 if (!longest_pfx)
11944 continue;
11945
11946 if (prefix_check && !is_exact_pfxlen_match)
11947 continue;
11948
11949 rm = longest_pfx;
9bcb3eef 11950 bgp_dest_lock_node(rm);
44c69747 11951
9bcb3eef 11952 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11953 bgp, afi, safi, json, pathtype,
4027d19b 11954 &display, rpki_target_state);
44c69747 11955
9bcb3eef 11956 bgp_dest_unlock_node(rm);
d62a17ae 11957 }
98a9dbc7 11958 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11959 if (use_json)
11960 json_paths = json_object_new_array();
11961
63a0b7a9
PG
11962 display = bgp_flowspec_display_match_per_ip(afi, rib,
11963 &match, prefix_check,
11964 vty,
11965 use_json,
11966 json_paths);
d5f20468
SP
11967 if (use_json) {
11968 if (display)
11969 json_object_object_add(json, "paths",
11970 json_paths);
11971 else
11972 json_object_free(json_paths);
11973 }
d62a17ae 11974 } else {
4953391b
DA
11975 dest = bgp_node_match(rib, &match);
11976 if (dest != NULL) {
9bcb3eef 11977 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11978 if (!prefix_check
9bcb3eef
DS
11979 || dest_p->prefixlen == match.prefixlen) {
11980 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11981 safi, json, pathtype,
4027d19b 11982 &display, rpki_target_state);
d62a17ae 11983 }
11984
9bcb3eef 11985 bgp_dest_unlock_node(dest);
d62a17ae 11986 }
11987 }
e5eee9af 11988
d62a17ae 11989 if (use_json) {
75eeda93 11990 vty_json(vty, json);
d62a17ae 11991 } else {
11992 if (!display) {
11993 vty_out(vty, "%% Network not in table\n");
11994 return CMD_WARNING;
11995 }
11996 }
b05a1c8b 11997
d62a17ae 11998 return CMD_SUCCESS;
718e3744 11999}
12000
fee0f4c6 12001/* Display specified route of Main RIB */
d62a17ae 12002static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
12003 afi_t afi, safi_t safi, struct prefix_rd *prd,
12004 int prefix_check, enum bgp_path_type pathtype,
4027d19b 12005 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 12006{
9b86009a 12007 if (!bgp) {
d62a17ae 12008 bgp = bgp_get_default();
9b86009a
RW
12009 if (!bgp) {
12010 if (!use_json)
12011 vty_out(vty, "No BGP process is configured\n");
16307668
RW
12012 else
12013 vty_out(vty, "{}\n");
9b86009a
RW
12014 return CMD_WARNING;
12015 }
12016 }
d62a17ae 12017
12018 /* labeled-unicast routes live in the unicast table */
12019 if (safi == SAFI_LABELED_UNICAST)
12020 safi = SAFI_UNICAST;
12021
12022 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 12023 afi, safi, rpki_target_state, prd,
8aa22bbb 12024 prefix_check, pathtype, use_json);
d62a17ae 12025}
12026
12027static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 12028 struct cmd_token **argv, bool exact, afi_t afi,
12029 safi_t safi, bool uj)
d62a17ae 12030{
12031 struct lcommunity *lcom;
12032 struct buffer *b;
12033 int i;
12034 char *str;
12035 int first = 0;
96c81f66 12036 uint16_t show_flags = 0;
4f28b2b5 12037 int ret;
96f3485c
MK
12038
12039 if (uj)
12040 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 12041
12042 b = buffer_new(1024);
12043 for (i = 0; i < argc; i++) {
12044 if (first)
12045 buffer_putc(b, ' ');
12046 else {
12047 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12048 first = 1;
12049 buffer_putstr(b, argv[i]->arg);
12050 }
12051 }
12052 }
12053 buffer_putc(b, '\0');
57d187bc 12054
d62a17ae 12055 str = buffer_getstr(b);
12056 buffer_free(b);
57d187bc 12057
d62a17ae 12058 lcom = lcommunity_str2com(str);
12059 XFREE(MTYPE_TMP, str);
12060 if (!lcom) {
12061 vty_out(vty, "%% Large-community malformed\n");
12062 return CMD_WARNING;
12063 }
57d187bc 12064
4f28b2b5 12065 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12066 (exact ? bgp_show_type_lcommunity_exact
12067 : bgp_show_type_lcommunity),
12068 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12069
12070 lcommunity_free(&lcom);
12071 return ret;
57d187bc
JS
12072}
12073
d62a17ae 12074static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12075 const char *lcom, bool exact, afi_t afi,
12076 safi_t safi, bool uj)
57d187bc 12077{
d62a17ae 12078 struct community_list *list;
96c81f66 12079 uint16_t show_flags = 0;
96f3485c
MK
12080
12081 if (uj)
12082 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12083
57d187bc 12084
e237b0d2 12085 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12086 LARGE_COMMUNITY_LIST_MASTER);
12087 if (list == NULL) {
12088 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12089 lcom);
12090 return CMD_WARNING;
12091 }
57d187bc 12092
36a206db 12093 return bgp_show(vty, bgp, afi, safi,
12094 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12095 : bgp_show_type_lcommunity_list),
1e2ce4f1 12096 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12097}
12098
52951b63
DS
12099DEFUN (show_ip_bgp_large_community_list,
12100 show_ip_bgp_large_community_list_cmd,
77a3a95e 12101 "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
12102 SHOW_STR
12103 IP_STR
12104 BGP_STR
12105 BGP_INSTANCE_HELP_STR
9bedbb1e 12106 BGP_AFI_HELP_STR
4dd6177e 12107 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12108 "Display routes matching the large-community-list\n"
12109 "large-community-list number\n"
12110 "large-community-list name\n"
36a206db 12111 "Exact match of the large-communities\n"
52951b63
DS
12112 JSON_STR)
12113{
d62a17ae 12114 afi_t afi = AFI_IP6;
12115 safi_t safi = SAFI_UNICAST;
12116 int idx = 0;
36a206db 12117 bool exact_match = 0;
4d678463 12118 struct bgp *bgp = NULL;
9f049418 12119 bool uj = use_json(argc, argv);
d62a17ae 12120
ef3364f0
DA
12121 if (uj)
12122 argc--;
4d678463 12123
ef3364f0
DA
12124 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12125 &bgp, uj);
12126 if (!idx)
12127 return CMD_WARNING;
d62a17ae 12128
12129 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12130
12131 const char *clist_number_or_name = argv[++idx]->arg;
12132
12133 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12134 exact_match = 1;
12135
12136 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12137 exact_match, afi, safi, uj);
52951b63
DS
12138}
12139DEFUN (show_ip_bgp_large_community,
12140 show_ip_bgp_large_community_cmd,
36a206db 12141 "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
12142 SHOW_STR
12143 IP_STR
12144 BGP_STR
12145 BGP_INSTANCE_HELP_STR
9bedbb1e 12146 BGP_AFI_HELP_STR
4dd6177e 12147 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12148 "Display routes matching the large-communities\n"
12149 "List of large-community numbers\n"
36a206db 12150 "Exact match of the large-communities\n"
52951b63
DS
12151 JSON_STR)
12152{
d62a17ae 12153 afi_t afi = AFI_IP6;
12154 safi_t safi = SAFI_UNICAST;
12155 int idx = 0;
36a206db 12156 bool exact_match = 0;
4d678463 12157 struct bgp *bgp = NULL;
9f049418 12158 bool uj = use_json(argc, argv);
96c81f66 12159 uint16_t show_flags = 0;
d62a17ae 12160
96f3485c
MK
12161 if (uj) {
12162 argc--;
12163 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12164 }
4d678463 12165
96f3485c
MK
12166 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12167 &bgp, uj);
12168 if (!idx)
12169 return CMD_WARNING;
d62a17ae 12170
36a206db 12171 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12172 if (argv_find(argv, argc, "exact-match", &idx))
12173 exact_match = 1;
12174 return bgp_show_lcommunity(vty, bgp, argc, argv,
12175 exact_match, afi, safi, uj);
12176 } else
d62a17ae 12177 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12178 bgp_show_type_lcommunity_all, NULL, show_flags,
12179 RPKI_NOT_BEING_USED);
52951b63
DS
12180}
12181
71f1613a
DA
12182static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12183 safi_t safi, struct json_object *json_array);
d62a17ae 12184static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12185 safi_t safi, struct json_object *json);
e01ca200 12186
7b2ff250 12187
9ab0cf58
PG
12188DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12189 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12190 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12191 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12192{
12193 bool uj = use_json(argc, argv);
12194 struct bgp *bgp = NULL;
ec76a1d1
DA
12195 safi_t safi = SAFI_UNICAST;
12196 afi_t afi = AFI_IP6;
4265b261 12197 int idx = 0;
6c9d22e2
PG
12198 struct json_object *json_all = NULL;
12199 struct json_object *json_afi_safi = NULL;
4265b261
PG
12200
12201 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12202 &bgp, false);
71f1613a 12203 if (!idx)
4265b261 12204 return CMD_WARNING;
6c9d22e2 12205
4265b261 12206 if (uj)
6c9d22e2 12207 json_all = json_object_new_object();
4265b261 12208
9ab0cf58
PG
12209 FOREACH_AFI_SAFI (afi, safi) {
12210 /*
12211 * So limit output to those afi/safi pairs that
12212 * actually have something interesting in them
12213 */
12214 if (strmatch(get_afi_safi_str(afi, safi, true),
12215 "Unknown")) {
12216 continue;
12217 }
12218 if (uj) {
12219 json_afi_safi = json_object_new_array();
12220 json_object_object_add(
12221 json_all,
12222 get_afi_safi_str(afi, safi, true),
12223 json_afi_safi);
12224 } else {
12225 json_afi_safi = NULL;
6c9d22e2 12226 }
9ab0cf58
PG
12227
12228 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12229 }
6c9d22e2 12230
3757f964
DA
12231 if (uj)
12232 vty_json(vty, json_all);
6c9d22e2 12233
4265b261
PG
12234 return CMD_SUCCESS;
12235}
12236
7b2ff250 12237/* BGP route print out function without JSON */
14718643
PG
12238DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12239 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12240 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12241 SHOW_STR
12242 IP_STR
12243 BGP_STR
12244 BGP_INSTANCE_HELP_STR
12245 L2VPN_HELP_STR
12246 EVPN_HELP_STR
12247 "BGP RIB advertisement statistics\n"
12248 JSON_STR)
12249{
ec76a1d1
DA
12250 afi_t afi = AFI_IP6;
12251 safi_t safi = SAFI_UNICAST;
14718643
PG
12252 struct bgp *bgp = NULL;
12253 int idx = 0, ret;
12254 bool uj = use_json(argc, argv);
12255 struct json_object *json_afi_safi = NULL, *json = NULL;
12256
12257 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12258 &bgp, false);
12259 if (!idx)
12260 return CMD_WARNING;
12261
12262 if (uj)
12263 json_afi_safi = json_object_new_array();
12264 else
12265 json_afi_safi = NULL;
12266
12267 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12268
12269 if (uj) {
12270 json = json_object_new_object();
12271 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12272 json_afi_safi);
3757f964 12273 vty_json(vty, json);
14718643
PG
12274 }
12275 return ret;
12276}
12277
893cccd0 12278/* BGP route print out function without JSON */
9ab0cf58
PG
12279DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12280 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12281 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12282 "]]\
893cccd0 12283 statistics [json]",
9ab0cf58
PG
12284 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12285 BGP_SAFI_WITH_LABEL_HELP_STR
12286 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12287{
ec76a1d1
DA
12288 afi_t afi = AFI_IP6;
12289 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12290 struct bgp *bgp = NULL;
12291 int idx = 0, ret;
12292 bool uj = use_json(argc, argv);
6c9d22e2 12293 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12294
12295 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12296 &bgp, false);
12297 if (!idx)
12298 return CMD_WARNING;
6c9d22e2 12299
893cccd0 12300 if (uj)
6c9d22e2
PG
12301 json_afi_safi = json_object_new_array();
12302 else
12303 json_afi_safi = NULL;
12304
12305 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12306
12307 if (uj) {
12308 json = json_object_new_object();
12309 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12310 json_afi_safi);
3757f964 12311 vty_json(vty, json);
893cccd0
PG
12312 }
12313 return ret;
893cccd0 12314}
7b2ff250 12315
fe0f234d 12316DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12317 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12318 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12319 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12320 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12321 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12322 "Display the entries for all address families\n"
9ab0cf58
PG
12323 "Display detailed information about dampening\n"
12324 "Display detail of configured dampening parameters\n"
fe0f234d 12325 JSON_STR)
718e3744 12326{
d62a17ae 12327 afi_t afi = AFI_IP6;
12328 safi_t safi = SAFI_UNICAST;
d62a17ae 12329 struct bgp *bgp = NULL;
12330 int idx = 0;
96c81f66 12331 uint16_t show_flags = 0;
fe0f234d
RW
12332 bool uj = use_json(argc, argv);
12333
12334 if (uj) {
12335 argc--;
12336 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12337 }
96f3485c
MK
12338
12339 /* [<ipv4|ipv6> [all]] */
12340 if (all) {
12341 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12342 if (argv_find(argv, argc, "ipv4", &idx))
12343 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12344
12345 if (argv_find(argv, argc, "ipv6", &idx))
12346 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12347 }
d62a17ae 12348
12349 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12350 &bgp, false);
d62a17ae 12351 if (!idx)
12352 return CMD_WARNING;
12353
fe0f234d 12354 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12355}
12356
fe0f234d
RW
12357/* BGP route print out function */
12358DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12359 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12360 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12361 "]]\
96f3485c 12362 [all$all]\
cf4898bc
QY
12363 [cidr-only\
12364 |dampening <flap-statistics|dampened-paths>\
12365 |community [AA:NN|local-AS|no-advertise|no-export\
12366 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12367 |accept-own|accept-own-nexthop|route-filter-v6\
12368 |route-filter-v4|route-filter-translated-v6\
12369 |route-filter-translated-v4] [exact-match]\
70799983 12370 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12371 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12372 |prefix-list WORD\
ed126382 12373 |access-list ACCESSLIST_NAME\
70dd370f 12374 |route-map RMAP_NAME\
1e2ce4f1 12375 |rpki <invalid|valid|notfound>\
7d3cae70 12376 |version (1-4294967295)\
b4ad2fae 12377 |alias ALIAS_NAME\
39c3c736
RW
12378 |A.B.C.D/M longer-prefixes\
12379 |X:X::X:X/M longer-prefixes\
f280c93b 12380 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12381 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12382 BGP_SAFI_WITH_LABEL_HELP_STR
12383 "Display the entries for all address families\n"
12384 "Display only routes with non-natural netmasks\n"
12385 "Display detailed information about dampening\n"
12386 "Display flap statistics of routes\n"
12387 "Display paths suppressed due to dampening\n"
12388 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12389 "Do not send outside local AS (well-known community)\n"
12390 "Do not advertise to any peer (well-known community)\n"
12391 "Do not export to next AS (well-known community)\n"
12392 "Graceful shutdown (well-known community)\n"
12393 "Do not export to any peer (well-known community)\n"
12394 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12395 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12396 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12397 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12398 "Should accept VPN route with local nexthop (well-known community)\n"
12399 "RT VPNv6 route filtering (well-known community)\n"
12400 "RT VPNv4 route filtering (well-known community)\n"
12401 "RT translated VPNv6 route filtering (well-known community)\n"
12402 "RT translated VPNv4 route filtering (well-known community)\n"
12403 "Exact match of the communities\n"
70799983
RW
12404 "Community-list number\n"
12405 "Community-list name\n"
12406 "Display routes matching the community-list\n"
12407 "Exact match of the communities\n"
a7129347
RW
12408 "Display routes conforming to the filter-list\n"
12409 "Regular expression access list name\n"
6deaf579
RW
12410 "Display routes conforming to the prefix-list\n"
12411 "Prefix-list name\n"
ed126382
DA
12412 "Display routes conforming to the access-list\n"
12413 "Access-list name\n"
bf1a944a
RW
12414 "Display routes matching the route-map\n"
12415 "A route-map to match on\n"
a70a28a5
DA
12416 "RPKI route types\n"
12417 "A valid path as determined by rpki\n"
12418 "A invalid path as determined by rpki\n"
12419 "A path that has no rpki data\n"
12420 "Display prefixes with matching version numbers\n"
12421 "Version number and above\n"
12422 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12423 "BGP community alias\n"
12424 "IPv4 prefix\n"
12425 "Display route and more specific routes\n"
12426 "IPv6 prefix\n"
12427 "Display route and more specific routes\n"
12428 JSON_STR
a70a28a5
DA
12429 "Display detailed version of JSON output\n"
12430 "Increase table width for longer prefixes\n")
7b2ff250
DW
12431{
12432 afi_t afi = AFI_IP6;
12433 safi_t safi = SAFI_UNICAST;
12434 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12435 void *output_arg = NULL;
7b2ff250
DW
12436 struct bgp *bgp = NULL;
12437 int idx = 0;
d0086e8e 12438 int exact_match = 0;
96f3485c
MK
12439 char *community = NULL;
12440 bool first = true;
96c81f66 12441 uint16_t show_flags = 0;
4027d19b 12442 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12443 struct prefix p;
96f3485c
MK
12444
12445 if (uj) {
9f049418 12446 argc--;
96f3485c
MK
12447 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12448 }
12449
f280c93b
DA
12450 if (detail)
12451 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12452
96f3485c
MK
12453 /* [<ipv4|ipv6> [all]] */
12454 if (all) {
12455 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12456
12457 if (argv_find(argv, argc, "ipv4", &idx))
12458 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12459
12460 if (argv_find(argv, argc, "ipv6", &idx))
12461 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12462 }
12463
12464 if (wide)
12465 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12466
12467 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12468 &bgp, uj);
7b2ff250
DW
12469 if (!idx)
12470 return CMD_WARNING;
12471
7b2ff250 12472 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12473 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12474
12475 if (argv_find(argv, argc, "dampening", &idx)) {
12476 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12477 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12478 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12479 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12480 }
12481
12482 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12483 char *maybecomm = NULL;
d0086e8e 12484
79bc257a
RW
12485 if (idx + 1 < argc) {
12486 if (argv[idx + 1]->type == VARIABLE_TKN)
12487 maybecomm = argv[idx + 1]->arg;
12488 else
12489 maybecomm = argv[idx + 1]->text;
12490 }
12491
cf4898bc
QY
12492 if (maybecomm && !strmatch(maybecomm, "json")
12493 && !strmatch(maybecomm, "exact-match"))
12494 community = maybecomm;
d0086e8e 12495
cf4898bc
QY
12496 if (argv_find(argv, argc, "exact-match", &idx))
12497 exact_match = 1;
d0086e8e 12498
96f3485c
MK
12499 if (!community)
12500 sh_type = bgp_show_type_community_all;
12501 }
12502
70799983
RW
12503 if (argv_find(argv, argc, "community-list", &idx)) {
12504 const char *clist_number_or_name = argv[++idx]->arg;
12505 struct community_list *list;
12506
12507 if (argv_find(argv, argc, "exact-match", &idx))
12508 exact_match = 1;
12509
12510 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12511 COMMUNITY_LIST_MASTER);
12512 if (list == NULL) {
606d49a4 12513 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12514 clist_number_or_name);
12515 return CMD_WARNING;
12516 }
12517
12518 if (exact_match)
12519 sh_type = bgp_show_type_community_list_exact;
12520 else
12521 sh_type = bgp_show_type_community_list;
12522 output_arg = list;
12523 }
12524
a7129347
RW
12525 if (argv_find(argv, argc, "filter-list", &idx)) {
12526 const char *filter = argv[++idx]->arg;
12527 struct as_list *as_list;
12528
12529 as_list = as_list_lookup(filter);
12530 if (as_list == NULL) {
606d49a4 12531 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12532 filter);
12533 return CMD_WARNING;
12534 }
12535
12536 sh_type = bgp_show_type_filter_list;
12537 output_arg = as_list;
12538 }
12539
6deaf579
RW
12540 if (argv_find(argv, argc, "prefix-list", &idx)) {
12541 const char *prefix_list_str = argv[++idx]->arg;
12542 struct prefix_list *plist;
12543
12544 plist = prefix_list_lookup(afi, prefix_list_str);
12545 if (plist == NULL) {
606d49a4 12546 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12547 prefix_list_str);
12548 return CMD_WARNING;
12549 }
12550
12551 sh_type = bgp_show_type_prefix_list;
12552 output_arg = plist;
12553 }
12554
ed126382
DA
12555 if (argv_find(argv, argc, "access-list", &idx)) {
12556 const char *access_list_str = argv[++idx]->arg;
12557 struct access_list *alist;
12558
12559 alist = access_list_lookup(afi, access_list_str);
12560 if (!alist) {
606d49a4 12561 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12562 access_list_str);
12563 return CMD_WARNING;
12564 }
12565
12566 sh_type = bgp_show_type_access_list;
12567 output_arg = alist;
12568 }
12569
bf1a944a
RW
12570 if (argv_find(argv, argc, "route-map", &idx)) {
12571 const char *rmap_str = argv[++idx]->arg;
12572 struct route_map *rmap;
12573
12574 rmap = route_map_lookup_by_name(rmap_str);
12575 if (!rmap) {
606d49a4 12576 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12577 return CMD_WARNING;
12578 }
12579
12580 sh_type = bgp_show_type_route_map;
12581 output_arg = rmap;
12582 }
12583
1e2ce4f1
DS
12584 if (argv_find(argv, argc, "rpki", &idx)) {
12585 sh_type = bgp_show_type_rpki;
12586 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12587 rpki_target_state = RPKI_VALID;
1e2ce4f1 12588 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12589 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12590 }
12591
7d3cae70
DA
12592 /* Display prefixes with matching version numbers */
12593 if (argv_find(argv, argc, "version", &idx)) {
12594 sh_type = bgp_show_type_prefix_version;
2391833e 12595 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12596 }
12597
a70a28a5
DA
12598 /* Display prefixes with matching BGP community alias */
12599 if (argv_find(argv, argc, "alias", &idx)) {
12600 sh_type = bgp_show_type_community_alias;
2391833e 12601 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12602 }
12603
39c3c736
RW
12604 /* prefix-longer */
12605 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12606 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12607 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12608
12609 if (!str2prefix(prefix_str, &p)) {
12610 vty_out(vty, "%% Malformed Prefix\n");
12611 return CMD_WARNING;
12612 }
12613
12614 sh_type = bgp_show_type_prefix_longer;
12615 output_arg = &p;
a70a28a5
DA
12616 }
12617
96f3485c
MK
12618 if (!all) {
12619 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12620 if (community)
12621 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12622 exact_match, afi, safi,
12623 show_flags);
2391833e 12624 else
a70a28a5 12625 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12626 output_arg, show_flags,
a70a28a5 12627 rpki_target_state);
96f3485c 12628 } else {
fa5ac378
DA
12629 struct listnode *node;
12630 struct bgp *abgp;
96f3485c
MK
12631 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12632 * AFI_IP6 */
12633
12634 if (uj)
12635 vty_out(vty, "{\n");
12636
12637 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12638 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12639 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12640 ? AFI_IP
12641 : AFI_IP6;
fa5ac378
DA
12642 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12643 FOREACH_SAFI (safi) {
12644 if (!bgp_afi_safi_peer_exists(abgp, afi,
12645 safi))
12646 continue;
96f3485c 12647
fa5ac378
DA
12648 if (uj) {
12649 if (first)
12650 first = false;
12651 else
12652 vty_out(vty, ",\n");
12653 vty_out(vty, "\"%s\":{\n",
12654 get_afi_safi_str(afi,
12655 safi,
12656 true));
12657 } else
12658 vty_out(vty,
12659 "\nFor address family: %s\n",
12660 get_afi_safi_str(
12661 afi, safi,
12662 false));
12663
12664 if (community)
12665 bgp_show_community(
12666 vty, abgp, community,
12667 exact_match, afi, safi,
12668 show_flags);
96f3485c 12669 else
fa5ac378
DA
12670 bgp_show(vty, abgp, afi, safi,
12671 sh_type, output_arg,
12672 show_flags,
12673 rpki_target_state);
12674 if (uj)
12675 vty_out(vty, "}\n");
12676 }
96f3485c
MK
12677 }
12678 } else {
12679 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12680 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12681 FOREACH_AFI_SAFI (afi, safi) {
12682 if (!bgp_afi_safi_peer_exists(abgp, afi,
12683 safi))
12684 continue;
96f3485c 12685
fa5ac378
DA
12686 if (uj) {
12687 if (first)
12688 first = false;
12689 else
12690 vty_out(vty, ",\n");
12691
12692 vty_out(vty, "\"%s\":{\n",
12693 get_afi_safi_str(afi,
12694 safi,
12695 true));
12696 } else
12697 vty_out(vty,
12698 "\nFor address family: %s\n",
12699 get_afi_safi_str(
12700 afi, safi,
12701 false));
12702
12703 if (community)
12704 bgp_show_community(
12705 vty, abgp, community,
12706 exact_match, afi, safi,
12707 show_flags);
96f3485c 12708 else
fa5ac378
DA
12709 bgp_show(vty, abgp, afi, safi,
12710 sh_type, output_arg,
12711 show_flags,
12712 rpki_target_state);
12713 if (uj)
12714 vty_out(vty, "}\n");
12715 }
96f3485c
MK
12716 }
12717 }
12718 if (uj)
12719 vty_out(vty, "}\n");
12720 }
12721 return CMD_SUCCESS;
a636c635 12722}
47fc97cc 12723
718e3744 12724DEFUN (show_ip_bgp_route,
12725 show_ip_bgp_route_cmd,
8aa22bbb 12726 "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 12727 SHOW_STR
12728 IP_STR
12729 BGP_STR
a636c635 12730 BGP_INSTANCE_HELP_STR
4f280b15 12731 BGP_AFI_HELP_STR
4dd6177e 12732 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12733 "Network in the BGP routing table to display\n"
0c7b1b01 12734 "IPv4 prefix\n"
8c3deaae 12735 "Network in the BGP routing table to display\n"
0c7b1b01 12736 "IPv6 prefix\n"
4092b06c 12737 "Display only the bestpath\n"
b05a1c8b 12738 "Display only multipaths\n"
8aa22bbb
DS
12739 "Display only paths that match the specified rpki state\n"
12740 "A valid path as determined by rpki\n"
12741 "A invalid path as determined by rpki\n"
12742 "A path that has no rpki data\n"
9973d184 12743 JSON_STR)
4092b06c 12744{
d62a17ae 12745 int prefix_check = 0;
ae19d7dd 12746
d62a17ae 12747 afi_t afi = AFI_IP6;
12748 safi_t safi = SAFI_UNICAST;
12749 char *prefix = NULL;
12750 struct bgp *bgp = NULL;
12751 enum bgp_path_type path_type;
9f049418 12752 bool uj = use_json(argc, argv);
b05a1c8b 12753
d62a17ae 12754 int idx = 0;
ae19d7dd 12755
d62a17ae 12756 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12757 &bgp, uj);
d62a17ae 12758 if (!idx)
12759 return CMD_WARNING;
c41247f5 12760
d62a17ae 12761 if (!bgp) {
12762 vty_out(vty,
12763 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12764 return CMD_WARNING;
12765 }
a636c635 12766
d62a17ae 12767 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12768 if (argv_find(argv, argc, "A.B.C.D", &idx)
12769 || argv_find(argv, argc, "X:X::X:X", &idx))
12770 prefix_check = 0;
12771 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12772 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12773 prefix_check = 1;
12774
12775 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12776 && afi != AFI_IP6) {
12777 vty_out(vty,
12778 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12779 return CMD_WARNING;
12780 }
12781 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12782 && afi != AFI_IP) {
12783 vty_out(vty,
12784 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12785 return CMD_WARNING;
12786 }
12787
12788 prefix = argv[idx]->arg;
12789
12790 /* [<bestpath|multipath>] */
12791 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12792 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12793 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12794 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12795 else
360660c6 12796 path_type = BGP_PATH_SHOW_ALL;
a636c635 12797
d62a17ae 12798 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12799 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12800}
12801
8c3deaae
QY
12802DEFUN (show_ip_bgp_regexp,
12803 show_ip_bgp_regexp_cmd,
3e5b31b3 12804 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12805 SHOW_STR
12806 IP_STR
12807 BGP_STR
b00b230a 12808 BGP_INSTANCE_HELP_STR
4f280b15 12809 BGP_AFI_HELP_STR
4dd6177e 12810 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12811 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12812 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12813 JSON_STR)
8c3deaae 12814{
d62a17ae 12815 afi_t afi = AFI_IP6;
12816 safi_t safi = SAFI_UNICAST;
12817 struct bgp *bgp = NULL;
3e5b31b3
DA
12818 bool uj = use_json(argc, argv);
12819 char *regstr = NULL;
8c3deaae 12820
d62a17ae 12821 int idx = 0;
12822 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12823 &bgp, false);
d62a17ae 12824 if (!idx)
12825 return CMD_WARNING;
8c3deaae 12826
d62a17ae 12827 // get index of regex
3e5b31b3
DA
12828 if (argv_find(argv, argc, "REGEX", &idx))
12829 regstr = argv[idx]->arg;
8c3deaae 12830
5f71d11c 12831 assert(regstr);
3e5b31b3
DA
12832 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12833 bgp_show_type_regexp, uj);
8c3deaae
QY
12834}
12835
ae248832 12836DEFPY (show_ip_bgp_instance_all,
a636c635 12837 show_ip_bgp_instance_all_cmd,
ae248832 12838 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12839 SHOW_STR
a636c635 12840 IP_STR
4092b06c 12841 BGP_STR
a636c635 12842 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12843 BGP_AFI_HELP_STR
4dd6177e 12844 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12845 JSON_STR
12846 "Increase table width for longer prefixes\n")
4092b06c 12847{
54d05dea 12848 afi_t afi = AFI_IP6;
d62a17ae 12849 safi_t safi = SAFI_UNICAST;
12850 struct bgp *bgp = NULL;
d62a17ae 12851 int idx = 0;
96c81f66 12852 uint16_t show_flags = 0;
ae19d7dd 12853
96f3485c 12854 if (uj) {
d62a17ae 12855 argc--;
96f3485c
MK
12856 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12857 }
12858
12859 if (wide)
12860 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12861
9f049418
DS
12862 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12863 &bgp, uj);
12864 if (!idx)
12865 return CMD_WARNING;
12866
96f3485c 12867 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12868 return CMD_SUCCESS;
e3e29b32
LB
12869}
12870
a4d82a8a 12871static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12872 afi_t afi, safi_t safi, enum bgp_show_type type,
12873 bool use_json)
718e3744 12874{
d62a17ae 12875 regex_t *regex;
12876 int rc;
96c81f66 12877 uint16_t show_flags = 0;
96f3485c
MK
12878
12879 if (use_json)
12880 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12881
c3900853 12882 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12883 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12884 regstr);
12885 return CMD_WARNING_CONFIG_FAILED;
12886 }
12887
d62a17ae 12888 regex = bgp_regcomp(regstr);
12889 if (!regex) {
12890 vty_out(vty, "Can't compile regexp %s\n", regstr);
12891 return CMD_WARNING;
12892 }
a636c635 12893
1e2ce4f1
DS
12894 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12895 RPKI_NOT_BEING_USED);
d62a17ae 12896 bgp_regex_free(regex);
12897 return rc;
e3e29b32
LB
12898}
12899
7f323236
DW
12900static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12901 const char *comstr, int exact, afi_t afi,
96c81f66 12902 safi_t safi, uint16_t show_flags)
d62a17ae 12903{
12904 struct community *com;
d62a17ae 12905 int ret = 0;
12906
7f323236 12907 com = community_str2com(comstr);
d62a17ae 12908 if (!com) {
7f323236 12909 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12910 return CMD_WARNING;
12911 }
12912
12913 ret = bgp_show(vty, bgp, afi, safi,
12914 (exact ? bgp_show_type_community_exact
12915 : bgp_show_type_community),
1e2ce4f1 12916 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12917 community_free(&com);
46c3ce83 12918
d62a17ae 12919 return ret;
718e3744 12920}
12921
d62a17ae 12922enum bgp_stats {
12923 BGP_STATS_MAXBITLEN = 0,
12924 BGP_STATS_RIB,
12925 BGP_STATS_PREFIXES,
12926 BGP_STATS_TOTPLEN,
12927 BGP_STATS_UNAGGREGATEABLE,
12928 BGP_STATS_MAX_AGGREGATEABLE,
12929 BGP_STATS_AGGREGATES,
12930 BGP_STATS_SPACE,
12931 BGP_STATS_ASPATH_COUNT,
12932 BGP_STATS_ASPATH_MAXHOPS,
12933 BGP_STATS_ASPATH_TOTHOPS,
12934 BGP_STATS_ASPATH_MAXSIZE,
12935 BGP_STATS_ASPATH_TOTSIZE,
12936 BGP_STATS_ASN_HIGHEST,
12937 BGP_STATS_MAX,
a636c635 12938};
2815e61f 12939
9ab0cf58 12940#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12941#define TABLE_STATS_IDX_JSON 1
12942
12943static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12944 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12945 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12946 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12947 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12948 "unaggregateablePrefixes"},
12949 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12950 "maximumAggregateablePrefixes"},
12951 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12952 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12953 [BGP_STATS_SPACE] = {"Address space advertised",
12954 "addressSpaceAdvertised"},
9ab0cf58
PG
12955 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12956 "advertisementsWithPaths"},
12957 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12958 "longestAsPath"},
12959 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12960 "largestAsPath"},
12961 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12962 "averageAsPathLengthHops"},
12963 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12964 "averageAsPathSizeBytes"},
12965 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12966 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12967};
2815e61f 12968
d62a17ae 12969struct bgp_table_stats {
12970 struct bgp_table *table;
12971 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
12972
12973 unsigned long long
12974 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
12975 1];
12976
8d0ab76d 12977 double total_space;
ff7924f6
PJ
12978};
12979
9bcb3eef 12980static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12981 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12982{
9bcb3eef 12983 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12984 struct bgp_path_info *pi;
b54892e0 12985 const struct prefix *rn_p;
d62a17ae 12986
9bcb3eef 12987 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12988 return;
d62a17ae 12989
9bcb3eef 12990 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12991 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12992 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12993
0747643e 12994 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 12995 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12996 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12997 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12998
9bcb3eef 12999 if (pdest == NULL || pdest == top) {
9c14ec72
RW
13000 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
13001 /* announced address space */
13002 if (space)
b54892e0 13003 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 13004 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 13005 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 13006
9c14ec72 13007
9bcb3eef 13008 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
13009 ts->counts[BGP_STATS_RIB]++;
13010
05864da7
DS
13011 if (CHECK_FLAG(pi->attr->flag,
13012 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
13013 ts->counts[BGP_STATS_AGGREGATES]++;
13014
13015 /* as-path stats */
05864da7 13016 if (pi->attr->aspath) {
9c14ec72
RW
13017 unsigned int hops = aspath_count_hops(pi->attr->aspath);
13018 unsigned int size = aspath_size(pi->attr->aspath);
13019 as_t highest = aspath_highest(pi->attr->aspath);
13020
13021 ts->counts[BGP_STATS_ASPATH_COUNT]++;
13022
13023 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
13024 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
13025
13026 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
13027 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
13028
13029 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
13030 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
13031 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
13032 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
13033 }
13034 }
13035}
13036
cc9f21da 13037static void bgp_table_stats_walker(struct thread *t)
9c14ec72 13038{
9bcb3eef
DS
13039 struct bgp_dest *dest, *ndest;
13040 struct bgp_dest *top;
9c14ec72
RW
13041 struct bgp_table_stats *ts = THREAD_ARG(t);
13042 unsigned int space = 0;
13043
13044 if (!(top = bgp_table_top(ts->table)))
cc9f21da 13045 return;
9c14ec72
RW
13046
13047 switch (ts->table->afi) {
13048 case AFI_IP:
13049 space = IPV4_MAX_BITLEN;
13050 break;
13051 case AFI_IP6:
13052 space = IPV6_MAX_BITLEN;
13053 break;
3ba7b4af
TA
13054 case AFI_L2VPN:
13055 space = EVPN_ROUTE_PREFIXLEN;
13056 break;
9c14ec72 13057 default:
cc9f21da 13058 return;
9c14ec72
RW
13059 }
13060
13061 ts->counts[BGP_STATS_MAXBITLEN] = space;
13062
9bcb3eef 13063 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13064 if (ts->table->safi == SAFI_MPLS_VPN
13065 || ts->table->safi == SAFI_ENCAP
13066 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13067 struct bgp_table *table;
13068
9bcb3eef 13069 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13070 if (!table)
13071 continue;
13072
13073 top = bgp_table_top(table);
9bcb3eef
DS
13074 for (ndest = bgp_table_top(table); ndest;
13075 ndest = bgp_route_next(ndest))
13076 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13077 } else {
9bcb3eef 13078 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13079 }
13080 }
2815e61f 13081}
ff7924f6 13082
71f1613a
DA
13083static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13084 struct json_object *json_array)
13085{
13086 struct listnode *node, *nnode;
13087 struct bgp *bgp;
13088
13089 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13090 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13091}
13092
13093static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13094 safi_t safi, struct json_object *json_array)
2815e61f 13095{
d62a17ae 13096 struct bgp_table_stats ts;
13097 unsigned int i;
893cccd0
PG
13098 int ret = CMD_SUCCESS;
13099 char temp_buf[20];
6c9d22e2 13100 struct json_object *json = NULL;
0747643e
AQ
13101 uint32_t bitlen = 0;
13102 struct json_object *json_bitlen;
6c9d22e2
PG
13103
13104 if (json_array)
13105 json = json_object_new_object();
019386c2 13106
d62a17ae 13107 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13108 char warning_msg[50];
13109
13110 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13111 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13112 safi);
6c9d22e2
PG
13113
13114 if (!json)
893cccd0
PG
13115 vty_out(vty, "%s\n", warning_msg);
13116 else
9ab0cf58 13117 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13118
893cccd0
PG
13119 ret = CMD_WARNING;
13120 goto end_table_stats;
d62a17ae 13121 }
019386c2 13122
893cccd0 13123 if (!json)
5290ceab
DA
13124 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13125 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13126 else
13127 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13128
d62a17ae 13129 /* labeled-unicast routes live in the unicast table */
13130 if (safi == SAFI_LABELED_UNICAST)
13131 safi = SAFI_UNICAST;
019386c2 13132
d62a17ae 13133 memset(&ts, 0, sizeof(ts));
13134 ts.table = bgp->rib[afi][safi];
13135 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13136
d62a17ae 13137 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13138 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13139 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13140 continue;
13141
13142 switch (i) {
d62a17ae 13143 case BGP_STATS_ASPATH_TOTHOPS:
13144 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13145 if (!json) {
9ab0cf58
PG
13146 snprintf(
13147 temp_buf, sizeof(temp_buf), "%12.2f",
13148 ts.counts[i]
13149 ? (float)ts.counts[i]
13150 / (float)ts.counts
13151 [BGP_STATS_ASPATH_COUNT]
13152 : 0);
893cccd0 13153 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13154 table_stats_strs[i]
13155 [TABLE_STATS_IDX_VTY],
893cccd0 13156 temp_buf);
9ab0cf58
PG
13157 } else {
13158 json_object_double_add(
13159 json,
13160 table_stats_strs[i]
13161 [TABLE_STATS_IDX_JSON],
13162 ts.counts[i]
13163 ? (double)ts.counts[i]
13164 / (double)ts.counts
d62a17ae 13165 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13166 : 0);
13167 }
d62a17ae 13168 break;
13169 case BGP_STATS_TOTPLEN:
6c9d22e2 13170 if (!json) {
9ab0cf58
PG
13171 snprintf(
13172 temp_buf, sizeof(temp_buf), "%12.2f",
13173 ts.counts[i]
13174 ? (float)ts.counts[i]
13175 / (float)ts.counts
13176 [BGP_STATS_PREFIXES]
13177 : 0);
893cccd0 13178 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13179 table_stats_strs[i]
13180 [TABLE_STATS_IDX_VTY],
893cccd0 13181 temp_buf);
9ab0cf58
PG
13182 } else {
13183 json_object_double_add(
13184 json,
13185 table_stats_strs[i]
13186 [TABLE_STATS_IDX_JSON],
13187 ts.counts[i]
13188 ? (double)ts.counts[i]
13189 / (double)ts.counts
d62a17ae 13190 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13191 : 0);
13192 }
d62a17ae 13193 break;
13194 case BGP_STATS_SPACE:
6c9d22e2
PG
13195 if (!json) {
13196 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13197 ts.total_space);
893cccd0 13198 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13199 table_stats_strs[i]
13200 [TABLE_STATS_IDX_VTY],
893cccd0 13201 temp_buf);
9ab0cf58
PG
13202 } else {
13203 json_object_double_add(
13204 json,
13205 table_stats_strs[i]
13206 [TABLE_STATS_IDX_JSON],
13207 (double)ts.total_space);
13208 }
8d0ab76d 13209 if (afi == AFI_IP6) {
6c9d22e2
PG
13210 if (!json) {
13211 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13212 "%12g",
13213 ts.total_space
13214 * pow(2.0, -128 + 32));
6c9d22e2
PG
13215 vty_out(vty, "%30s: %s\n",
13216 "/32 equivalent %s\n",
13217 temp_buf);
9ab0cf58
PG
13218 } else {
13219 json_object_double_add(
13220 json, "/32equivalent",
13221 (double)(ts.total_space
13222 * pow(2.0,
13223 -128 + 32)));
13224 }
6c9d22e2
PG
13225 if (!json) {
13226 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13227 "%12g",
13228 ts.total_space
13229 * pow(2.0, -128 + 48));
6c9d22e2
PG
13230 vty_out(vty, "%30s: %s\n",
13231 "/48 equivalent %s\n",
13232 temp_buf);
9ab0cf58
PG
13233 } else {
13234 json_object_double_add(
13235 json, "/48equivalent",
13236 (double)(ts.total_space
13237 * pow(2.0,
13238 -128 + 48)));
13239 }
8d0ab76d 13240 } else {
6c9d22e2
PG
13241 if (!json) {
13242 snprintf(temp_buf, sizeof(temp_buf),
13243 "%12.2f",
9ab0cf58
PG
13244 ts.total_space * 100.
13245 * pow(2.0, -32));
6c9d22e2 13246 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13247 "% announced ", temp_buf);
13248 } else {
13249 json_object_double_add(
13250 json, "%announced",
13251 (double)(ts.total_space * 100.
13252 * pow(2.0, -32)));
13253 }
6c9d22e2
PG
13254 if (!json) {
13255 snprintf(temp_buf, sizeof(temp_buf),
13256 "%12.2f",
9ab0cf58
PG
13257 ts.total_space
13258 * pow(2.0, -32 + 8));
6c9d22e2
PG
13259 vty_out(vty, "%30s: %s\n",
13260 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13261 } else {
13262 json_object_double_add(
13263 json, "/8equivalent",
13264 (double)(ts.total_space
13265 * pow(2.0, -32 + 8)));
13266 }
6c9d22e2
PG
13267 if (!json) {
13268 snprintf(temp_buf, sizeof(temp_buf),
13269 "%12.2f",
9ab0cf58
PG
13270 ts.total_space
13271 * pow(2.0, -32 + 24));
6c9d22e2 13272 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13273 "/24 equivalent ", temp_buf);
13274 } else {
13275 json_object_double_add(
13276 json, "/24equivalent",
13277 (double)(ts.total_space
13278 * pow(2.0, -32 + 24)));
13279 }
8d0ab76d 13280 }
d62a17ae 13281 break;
13282 default:
6c9d22e2
PG
13283 if (!json) {
13284 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13285 ts.counts[i]);
893cccd0 13286 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13287 table_stats_strs[i]
13288 [TABLE_STATS_IDX_VTY],
13289 temp_buf);
13290 } else {
13291 json_object_int_add(
13292 json,
13293 table_stats_strs[i]
13294 [TABLE_STATS_IDX_JSON],
13295 ts.counts[i]);
13296 }
d62a17ae 13297 }
893cccd0
PG
13298 if (!json)
13299 vty_out(vty, "\n");
d62a17ae 13300 }
0747643e
AQ
13301
13302 switch (afi) {
13303 case AFI_IP:
13304 bitlen = IPV4_MAX_BITLEN;
13305 break;
13306 case AFI_IP6:
13307 bitlen = IPV6_MAX_BITLEN;
13308 break;
13309 case AFI_L2VPN:
13310 bitlen = EVPN_ROUTE_PREFIXLEN;
13311 break;
13312 default:
13313 break;
13314 }
13315
13316 if (json) {
13317 json_bitlen = json_object_new_array();
13318
13319 for (i = 0; i <= bitlen; i++) {
13320 struct json_object *ind_bit = json_object_new_object();
13321
13322 if (!ts.prefix_len_count[i])
13323 continue;
13324
13325 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13326 json_object_int_add(ind_bit, temp_buf,
13327 ts.prefix_len_count[i]);
13328 json_object_array_add(json_bitlen, ind_bit);
13329 }
13330 json_object_object_add(json, "prefixLength", json_bitlen);
13331 }
13332
9ab0cf58 13333end_table_stats:
6c9d22e2
PG
13334 if (json)
13335 json_object_array_add(json_array, json);
893cccd0 13336 return ret;
d62a17ae 13337}
13338
71f1613a
DA
13339static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13340 safi_t safi, struct json_object *json_array)
13341{
13342 if (!bgp) {
13343 bgp_table_stats_all(vty, afi, safi, json_array);
13344 return CMD_SUCCESS;
13345 }
13346
13347 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13348}
13349
d62a17ae 13350enum bgp_pcounts {
13351 PCOUNT_ADJ_IN = 0,
13352 PCOUNT_DAMPED,
13353 PCOUNT_REMOVED,
13354 PCOUNT_HISTORY,
13355 PCOUNT_STALE,
13356 PCOUNT_VALID,
13357 PCOUNT_ALL,
13358 PCOUNT_COUNTED,
7e3d9632 13359 PCOUNT_BPATH_SELECTED,
d62a17ae 13360 PCOUNT_PFCNT, /* the figure we display to users */
13361 PCOUNT_MAX,
a636c635 13362};
718e3744 13363
2b64873d 13364static const char *const pcount_strs[] = {
9d303b37
DL
13365 [PCOUNT_ADJ_IN] = "Adj-in",
13366 [PCOUNT_DAMPED] = "Damped",
13367 [PCOUNT_REMOVED] = "Removed",
13368 [PCOUNT_HISTORY] = "History",
13369 [PCOUNT_STALE] = "Stale",
13370 [PCOUNT_VALID] = "Valid",
13371 [PCOUNT_ALL] = "All RIB",
13372 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13373 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13374 [PCOUNT_PFCNT] = "Useable",
13375 [PCOUNT_MAX] = NULL,
a636c635 13376};
718e3744 13377
d62a17ae 13378struct peer_pcounts {
13379 unsigned int count[PCOUNT_MAX];
13380 const struct peer *peer;
13381 const struct bgp_table *table;
54317cba 13382 safi_t safi;
a636c635 13383};
47fc97cc 13384
9bcb3eef 13385static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13386{
54317cba
JW
13387 const struct bgp_adj_in *ain;
13388 const struct bgp_path_info *pi;
d62a17ae 13389 const struct peer *peer = pc->peer;
13390
54317cba
JW
13391 for (ain = rn->adj_in; ain; ain = ain->next)
13392 if (ain->peer == peer)
13393 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13394
9bcb3eef 13395 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13396
54317cba
JW
13397 if (pi->peer != peer)
13398 continue;
d62a17ae 13399
54317cba 13400 pc->count[PCOUNT_ALL]++;
d62a17ae 13401
54317cba
JW
13402 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13403 pc->count[PCOUNT_DAMPED]++;
13404 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13405 pc->count[PCOUNT_HISTORY]++;
13406 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13407 pc->count[PCOUNT_REMOVED]++;
13408 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13409 pc->count[PCOUNT_STALE]++;
13410 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13411 pc->count[PCOUNT_VALID]++;
13412 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13413 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13414 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13415 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13416
13417 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13418 pc->count[PCOUNT_COUNTED]++;
13419 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13420 flog_err(
13421 EC_LIB_DEVELOPMENT,
13422 "Attempting to count but flags say it is unusable");
13423 } else {
40381db7 13424 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13425 flog_err(
13426 EC_LIB_DEVELOPMENT,
13427 "Not counted but flags say we should");
d62a17ae 13428 }
13429 }
54317cba
JW
13430}
13431
cc9f21da 13432static void bgp_peer_count_walker(struct thread *t)
54317cba 13433{
9bcb3eef 13434 struct bgp_dest *rn, *rm;
54317cba
JW
13435 const struct bgp_table *table;
13436 struct peer_pcounts *pc = THREAD_ARG(t);
13437
13438 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13439 || pc->safi == SAFI_EVPN) {
13440 /* Special handling for 2-level routing tables. */
13441 for (rn = bgp_table_top(pc->table); rn;
13442 rn = bgp_route_next(rn)) {
9bcb3eef 13443 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13444 if (table != NULL)
13445 for (rm = bgp_table_top(table); rm;
13446 rm = bgp_route_next(rm))
13447 bgp_peer_count_proc(rm, pc);
13448 }
13449 } else
13450 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13451 bgp_peer_count_proc(rn, pc);
718e3744 13452}
13453
d62a17ae 13454static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13455 safi_t safi, bool use_json)
856ca177 13456{
d62a17ae 13457 struct peer_pcounts pcounts = {.peer = peer};
13458 unsigned int i;
13459 json_object *json = NULL;
13460 json_object *json_loop = NULL;
856ca177 13461
d62a17ae 13462 if (use_json) {
13463 json = json_object_new_object();
13464 json_loop = json_object_new_object();
13465 }
718e3744 13466
d62a17ae 13467 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13468 || !peer->bgp->rib[afi][safi]) {
13469 if (use_json) {
13470 json_object_string_add(
13471 json, "warning",
13472 "No such neighbor or address family");
13473 vty_out(vty, "%s\n", json_object_to_json_string(json));
13474 json_object_free(json);
d5f20468 13475 json_object_free(json_loop);
d62a17ae 13476 } else
13477 vty_out(vty, "%% No such neighbor or address family\n");
13478
13479 return CMD_WARNING;
13480 }
2a71e9ce 13481
d62a17ae 13482 memset(&pcounts, 0, sizeof(pcounts));
13483 pcounts.peer = peer;
13484 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13485 pcounts.safi = safi;
d62a17ae 13486
13487 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13488 * stats for the thread-walk (i.e. ensure this can't be blamed on
13489 * on just vty_read()).
13490 */
d62a17ae 13491 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13492
13493 if (use_json) {
13494 json_object_string_add(json, "prefixCountsFor", peer->host);
13495 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13496 get_afi_safi_str(afi, safi, true));
d62a17ae 13497 json_object_int_add(json, "pfxCounter",
13498 peer->pcount[afi][safi]);
13499
13500 for (i = 0; i < PCOUNT_MAX; i++)
13501 json_object_int_add(json_loop, pcount_strs[i],
13502 pcounts.count[i]);
13503
13504 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13505
13506 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13507 json_object_string_add(json, "pfxctDriftFor",
13508 peer->host);
13509 json_object_string_add(
13510 json, "recommended",
13511 "Please report this bug, with the above command output");
13512 }
75eeda93 13513 vty_json(vty, json);
d62a17ae 13514 } else {
13515
13516 if (peer->hostname
892fedb6 13517 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13518 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13519 peer->hostname, peer->host,
5cb5f4d0 13520 get_afi_safi_str(afi, safi, false));
d62a17ae 13521 } else {
13522 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13523 get_afi_safi_str(afi, safi, false));
d62a17ae 13524 }
13525
6cde4b45 13526 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13527 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13528
13529 for (i = 0; i < PCOUNT_MAX; i++)
13530 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13531 pcounts.count[i]);
13532
13533 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13534 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13535 vty_out(vty,
13536 "Please report this bug, with the above command output\n");
13537 }
13538 }
13539
13540 return CMD_SUCCESS;
718e3744 13541}
13542
a636c635
DW
13543DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13544 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13545 "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 13546 SHOW_STR
13547 IP_STR
13548 BGP_STR
8386ac43 13549 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13550 BGP_AFI_HELP_STR
13551 BGP_SAFI_HELP_STR
0b16f239
DS
13552 "Detailed information on TCP and BGP neighbor connections\n"
13553 "Neighbor to display information about\n"
13554 "Neighbor to display information about\n"
91d37724 13555 "Neighbor on BGP configured interface\n"
a636c635 13556 "Display detailed prefix count information\n"
9973d184 13557 JSON_STR)
0b16f239 13558{
d62a17ae 13559 afi_t afi = AFI_IP6;
13560 safi_t safi = SAFI_UNICAST;
13561 struct peer *peer;
13562 int idx = 0;
13563 struct bgp *bgp = NULL;
9f049418
DS
13564 bool uj = use_json(argc, argv);
13565
13566 if (uj)
13567 argc--;
856ca177 13568
d62a17ae 13569 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13570 &bgp, uj);
d62a17ae 13571 if (!idx)
13572 return CMD_WARNING;
0b16f239 13573
d62a17ae 13574 argv_find(argv, argc, "neighbors", &idx);
13575 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13576 if (!peer)
13577 return CMD_WARNING;
bb46e94f 13578
29c8d9da 13579 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13580}
0b16f239 13581
d6902373
PG
13582#ifdef KEEP_OLD_VPN_COMMANDS
13583DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13584 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13585 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13586 SHOW_STR
13587 IP_STR
13588 BGP_STR
d6902373 13589 BGP_VPNVX_HELP_STR
91d37724 13590 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13591 "Detailed information on TCP and BGP neighbor connections\n"
13592 "Neighbor to display information about\n"
13593 "Neighbor to display information about\n"
91d37724 13594 "Neighbor on BGP configured interface\n"
a636c635 13595 "Display detailed prefix count information\n"
9973d184 13596 JSON_STR)
a636c635 13597{
d62a17ae 13598 int idx_peer = 6;
13599 struct peer *peer;
9f049418 13600 bool uj = use_json(argc, argv);
a636c635 13601
d62a17ae 13602 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13603 if (!peer)
13604 return CMD_WARNING;
13605
13606 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13607}
13608
d6902373
PG
13609DEFUN (show_ip_bgp_vpn_all_route_prefix,
13610 show_ip_bgp_vpn_all_route_prefix_cmd,
13611 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13612 SHOW_STR
13613 IP_STR
13614 BGP_STR
d6902373 13615 BGP_VPNVX_HELP_STR
91d37724
QY
13616 "Display information about all VPNv4 NLRIs\n"
13617 "Network in the BGP routing table to display\n"
3a2d747c 13618 "Network in the BGP routing table to display\n"
9973d184 13619 JSON_STR)
91d37724 13620{
d62a17ae 13621 int idx = 0;
13622 char *network = NULL;
13623 struct bgp *bgp = bgp_get_default();
13624 if (!bgp) {
13625 vty_out(vty, "Can't find default instance\n");
13626 return CMD_WARNING;
13627 }
87e34b58 13628
d62a17ae 13629 if (argv_find(argv, argc, "A.B.C.D", &idx))
13630 network = argv[idx]->arg;
13631 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13632 network = argv[idx]->arg;
13633 else {
13634 vty_out(vty, "Unable to figure out Network\n");
13635 return CMD_WARNING;
13636 }
87e34b58 13637
d62a17ae 13638 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13639 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13640 use_json(argc, argv));
91d37724 13641}
d6902373 13642#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13643
44c69747
LK
13644DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13645 show_bgp_l2vpn_evpn_route_prefix_cmd,
13646 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13647 SHOW_STR
4c63a661
PG
13648 BGP_STR
13649 L2VPN_HELP_STR
13650 EVPN_HELP_STR
44c69747
LK
13651 "Network in the BGP routing table to display\n"
13652 "Network in the BGP routing table to display\n"
4c63a661
PG
13653 "Network in the BGP routing table to display\n"
13654 "Network in the BGP routing table to display\n"
13655 JSON_STR)
13656{
d62a17ae 13657 int idx = 0;
13658 char *network = NULL;
44c69747 13659 int prefix_check = 0;
a636c635 13660
44c69747
LK
13661 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13662 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13663 network = argv[idx]->arg;
44c69747 13664 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13665 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13666 network = argv[idx]->arg;
44c69747
LK
13667 prefix_check = 1;
13668 } else {
d62a17ae 13669 vty_out(vty, "Unable to figure out Network\n");
13670 return CMD_WARNING;
13671 }
44c69747
LK
13672 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13673 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13674 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13675}
13676
114fc229 13677static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13678 struct bgp_table *table, int *header1,
13679 int *header2, json_object *json,
13680 json_object *json_scode,
13681 json_object *json_ocode, bool wide)
13682{
13683 uint64_t version = table ? table->version : 0;
13684
13685 if (*header1) {
13686 if (json) {
13687 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13688 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13689 "%pI4", &peer->bgp->router_id);
2f9bc755 13690 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13691 peer->bgp->default_local_pref);
13692 json_object_int_add(json, "localAS",
13693 peer->change_local_as
13694 ? peer->change_local_as
13695 : peer->local_as);
2f9bc755
DS
13696 json_object_object_add(json, "bgpStatusCodes",
13697 json_scode);
13698 json_object_object_add(json, "bgpOriginCodes",
13699 json_ocode);
13700 } else {
13701 vty_out(vty,
23d0a753
DA
13702 "BGP table version is %" PRIu64
13703 ", local router ID is %pI4, vrf id ",
114fc229
DA
13704 version, &peer->bgp->router_id);
13705 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13706 vty_out(vty, "%s", VRFID_NONE_STR);
13707 else
114fc229 13708 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13709 vty_out(vty, "\n");
13710 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13711 peer->bgp->default_local_pref);
13712 vty_out(vty, "local AS %u\n",
13713 peer->change_local_as ? peer->change_local_as
13714 : peer->local_as);
2f9bc755
DS
13715 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13716 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13717 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13718 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13719 }
13720 *header1 = 0;
13721 }
13722 if (*header2) {
13723 if (!json)
13724 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13725 : BGP_SHOW_HEADER));
13726 *header2 = 0;
13727 }
13728}
13729
d9478df0
TA
13730static void
13731show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13732 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13733 const char *rmap_name, json_object *json, json_object *json_ar,
13734 json_object *json_scode, json_object *json_ocode,
96c81f66 13735 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13736 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13737{
d62a17ae 13738 struct bgp_adj_in *ain;
13739 struct bgp_adj_out *adj;
9bcb3eef 13740 struct bgp_dest *dest;
d62a17ae 13741 struct bgp *bgp;
d62a17ae 13742 struct attr attr;
13743 int ret;
13744 struct update_subgroup *subgrp;
d62a17ae 13745 struct peer_af *paf;
f99def61 13746 bool route_filtered;
96f3485c
MK
13747 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13748 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13749 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13750 || (safi == SAFI_EVPN))
13751 ? true
13752 : false;
a636c635 13753
d62a17ae 13754 bgp = peer->bgp;
a636c635 13755
d62a17ae 13756 subgrp = peer_subgroup(peer, afi, safi);
13757
6392aaa6 13758 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13759 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13760 if (use_json) {
13761 json_object_int_add(json, "bgpTableVersion",
13762 table->version);
c949c771
DA
13763 json_object_string_addf(json, "bgpLocalRouterId",
13764 "%pI4", &bgp->router_id);
01eced22
AD
13765 json_object_int_add(json, "defaultLocPrf",
13766 bgp->default_local_pref);
114fc229
DA
13767 json_object_int_add(json, "localAS",
13768 peer->change_local_as
13769 ? peer->change_local_as
13770 : peer->local_as);
d62a17ae 13771 json_object_object_add(json, "bgpStatusCodes",
13772 json_scode);
13773 json_object_object_add(json, "bgpOriginCodes",
13774 json_ocode);
07d0c4ed
DA
13775 json_object_string_add(
13776 json, "bgpOriginatingDefaultNetwork",
13777 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13778 } else {
23d0a753
DA
13779 vty_out(vty,
13780 "BGP table version is %" PRIu64
13781 ", local router ID is %pI4, vrf id ",
13782 table->version, &bgp->router_id);
9df8b37c
PZ
13783 if (bgp->vrf_id == VRF_UNKNOWN)
13784 vty_out(vty, "%s", VRFID_NONE_STR);
13785 else
13786 vty_out(vty, "%u", bgp->vrf_id);
13787 vty_out(vty, "\n");
01eced22
AD
13788 vty_out(vty, "Default local pref %u, ",
13789 bgp->default_local_pref);
114fc229
DA
13790 vty_out(vty, "local AS %u\n",
13791 peer->change_local_as ? peer->change_local_as
13792 : peer->local_as);
d62a17ae 13793 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13794 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13795 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13796 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13797
07d0c4ed
DA
13798 vty_out(vty, "Originating default network %s\n\n",
13799 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13800 }
d9478df0 13801 *header1 = 0;
d62a17ae 13802 }
a636c635 13803
9bcb3eef 13804 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13805 if (type == bgp_show_adj_route_received
13806 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13807 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13808 if (ain->peer != peer)
ea47320b 13809 continue;
6392aaa6 13810
114fc229 13811 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13812 header2, json, json_scode,
13813 json_ocode, wide);
13814
13815 if ((safi == SAFI_MPLS_VPN)
13816 || (safi == SAFI_ENCAP)
13817 || (safi == SAFI_EVPN)) {
13818 if (use_json)
13819 json_object_string_add(
13820 json_ar, "rd", rd_str);
13821 else if (show_rd && rd_str) {
13822 vty_out(vty,
13823 "Route Distinguisher: %s\n",
13824 rd_str);
13825 show_rd = false;
13826 }
13827 }
6392aaa6 13828
6f4f49b2 13829 attr = *ain->attr;
f99def61
AD
13830 route_filtered = false;
13831
13832 /* Filter prefix using distribute list,
13833 * filter list or prefix list
13834 */
b54892e0 13835 const struct prefix *rn_p =
9bcb3eef 13836 bgp_dest_get_prefix(dest);
b54892e0
DS
13837 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13838 safi))
13839 == FILTER_DENY)
f99def61
AD
13840 route_filtered = true;
13841
13842 /* Filter prefix using route-map */
b54892e0
DS
13843 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13844 safi, rmap_name, NULL,
13845 0, NULL);
6392aaa6 13846
13c8e163
AD
13847 if (type == bgp_show_adj_route_filtered &&
13848 !route_filtered && ret != RMAP_DENY) {
d498917e 13849 bgp_attr_flush(&attr);
6392aaa6 13850 continue;
d62a17ae 13851 }
6392aaa6 13852
d9478df0
TA
13853 if (type == bgp_show_adj_route_received
13854 && (route_filtered || ret == RMAP_DENY))
13855 (*filtered_count)++;
6392aaa6 13856
7d3cae70 13857 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13858 use_json, json_ar, wide);
d498917e 13859 bgp_attr_flush(&attr);
d9478df0 13860 (*output_count)++;
d62a17ae 13861 }
6392aaa6 13862 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13863 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13864 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13865 if (paf->peer != peer || !adj->attr)
924c3f6a 13866 continue;
d62a17ae 13867
114fc229 13868 show_adj_route_header(vty, peer, table,
d9478df0
TA
13869 header1, header2,
13870 json, json_scode,
13871 json_ocode, wide);
d62a17ae 13872
b54892e0 13873 const struct prefix *rn_p =
9bcb3eef 13874 bgp_dest_get_prefix(dest);
b54892e0 13875
6f4f49b2 13876 attr = *adj->attr;
b755861b 13877 ret = bgp_output_modifier(
b54892e0 13878 peer, rn_p, &attr, afi, safi,
b755861b 13879 rmap_name);
f46d8e1e 13880
b755861b 13881 if (ret != RMAP_DENY) {
d9478df0
TA
13882 if ((safi == SAFI_MPLS_VPN)
13883 || (safi == SAFI_ENCAP)
13884 || (safi == SAFI_EVPN)) {
13885 if (use_json)
13886 json_object_string_add(
13887 json_ar,
13888 "rd",
13889 rd_str);
13890 else if (show_rd
13891 && rd_str) {
13892 vty_out(vty,
13893 "Route Distinguisher: %s\n",
13894 rd_str);
13895 show_rd = false;
13896 }
13897 }
b54892e0 13898 route_vty_out_tmp(
7d3cae70
DA
13899 vty, dest, rn_p, &attr,
13900 safi, use_json, json_ar,
ae248832 13901 wide);
d9478df0 13902 (*output_count)++;
b755861b 13903 } else {
d9478df0 13904 (*filtered_count)++;
a2addae8 13905 }
b755861b 13906
d498917e 13907 bgp_attr_flush(&attr);
924c3f6a 13908 }
f20ce998
DS
13909 } else if (type == bgp_show_adj_route_bestpath) {
13910 struct bgp_path_info *pi;
13911
114fc229
DA
13912 show_adj_route_header(vty, peer, table, header1,
13913 header2, json, json_scode,
13914 json_ocode, wide);
f20ce998
DS
13915
13916 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13917 pi = pi->next) {
13918 if (pi->peer != peer)
13919 continue;
13920
13921 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13922 continue;
13923
7d3cae70 13924 route_vty_out_tmp(vty, dest,
f20ce998
DS
13925 bgp_dest_get_prefix(dest),
13926 pi->attr, safi, use_json,
13927 json_ar, wide);
d9478df0 13928 (*output_count)++;
f20ce998 13929 }
d62a17ae 13930 }
13931 }
a636c635 13932}
2a71e9ce 13933
d62a17ae 13934static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13935 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13936 const char *rmap_name, uint16_t show_flags)
0b16f239 13937{
d9478df0
TA
13938 struct bgp *bgp;
13939 struct bgp_table *table;
d62a17ae 13940 json_object *json = NULL;
d9478df0
TA
13941 json_object *json_scode = NULL;
13942 json_object *json_ocode = NULL;
13943 json_object *json_ar = NULL;
96f3485c 13944 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13945
d9478df0
TA
13946 /* Init BGP headers here so they're only displayed once
13947 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13948 */
13949 int header1 = 1;
13950 int header2 = 1;
13951
13952 /*
13953 * Initialize variables for each RD
13954 * All prefixes under an RD is aggregated within "json_routes"
13955 */
13956 char rd_str[BUFSIZ] = {0};
13957 json_object *json_routes = NULL;
13958
13959
13960 /* For 2-tier tables, prefix counts need to be
13961 * maintained across multiple runs of show_adj_route()
13962 */
13963 unsigned long output_count_per_rd;
13964 unsigned long filtered_count_per_rd;
13965 unsigned long output_count = 0;
13966 unsigned long filtered_count = 0;
13967
13968 if (use_json) {
d62a17ae 13969 json = json_object_new_object();
d9478df0
TA
13970 json_ar = json_object_new_object();
13971 json_scode = json_object_new_object();
13972 json_ocode = json_object_new_object();
13973
13974 json_object_string_add(json_scode, "suppressed", "s");
13975 json_object_string_add(json_scode, "damped", "d");
13976 json_object_string_add(json_scode, "history", "h");
13977 json_object_string_add(json_scode, "valid", "*");
13978 json_object_string_add(json_scode, "best", ">");
13979 json_object_string_add(json_scode, "multipath", "=");
13980 json_object_string_add(json_scode, "internal", "i");
13981 json_object_string_add(json_scode, "ribFailure", "r");
13982 json_object_string_add(json_scode, "stale", "S");
13983 json_object_string_add(json_scode, "removed", "R");
13984
13985 json_object_string_add(json_ocode, "igp", "i");
13986 json_object_string_add(json_ocode, "egp", "e");
13987 json_object_string_add(json_ocode, "incomplete", "?");
13988 }
0b16f239 13989
d62a17ae 13990 if (!peer || !peer->afc[afi][safi]) {
13991 if (use_json) {
13992 json_object_string_add(
13993 json, "warning",
13994 "No such neighbor or address family");
13995 vty_out(vty, "%s\n", json_object_to_json_string(json));
13996 json_object_free(json);
690c3134
MW
13997 json_object_free(json_ar);
13998 json_object_free(json_scode);
13999 json_object_free(json_ocode);
d62a17ae 14000 } else
14001 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 14002
d62a17ae 14003 return CMD_WARNING;
14004 }
14005
6392aaa6
PM
14006 if ((type == bgp_show_adj_route_received
14007 || type == bgp_show_adj_route_filtered)
d62a17ae 14008 && !CHECK_FLAG(peer->af_flags[afi][safi],
14009 PEER_FLAG_SOFT_RECONFIG)) {
14010 if (use_json) {
14011 json_object_string_add(
14012 json, "warning",
14013 "Inbound soft reconfiguration not enabled");
14014 vty_out(vty, "%s\n", json_object_to_json_string(json));
14015 json_object_free(json);
690c3134
MW
14016 json_object_free(json_ar);
14017 json_object_free(json_scode);
14018 json_object_free(json_ocode);
d62a17ae 14019 } else
14020 vty_out(vty,
14021 "%% Inbound soft reconfiguration not enabled\n");
14022
14023 return CMD_WARNING;
14024 }
0b16f239 14025
d9478df0
TA
14026 bgp = peer->bgp;
14027
14028 /* labeled-unicast routes live in the unicast table */
14029 if (safi == SAFI_LABELED_UNICAST)
14030 table = bgp->rib[afi][SAFI_UNICAST];
14031 else
14032 table = bgp->rib[afi][safi];
14033
14034 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14035 || (safi == SAFI_EVPN)) {
14036
14037 struct bgp_dest *dest;
14038
14039 for (dest = bgp_table_top(table); dest;
14040 dest = bgp_route_next(dest)) {
14041 table = bgp_dest_get_bgp_table_info(dest);
14042 if (!table)
14043 continue;
14044
14045 output_count_per_rd = 0;
14046 filtered_count_per_rd = 0;
14047
14048 if (use_json)
14049 json_routes = json_object_new_object();
14050
14051 const struct prefix_rd *prd;
14052 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14053 dest);
14054
14055 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14056
14057 show_adj_route(vty, peer, table, afi, safi, type,
14058 rmap_name, json, json_routes, json_scode,
14059 json_ocode, show_flags, &header1,
14060 &header2, rd_str, &output_count_per_rd,
14061 &filtered_count_per_rd);
14062
14063 /* Don't include an empty RD in the output! */
14064 if (json_routes && (output_count_per_rd > 0))
14065 json_object_object_add(json_ar, rd_str,
14066 json_routes);
14067
14068 output_count += output_count_per_rd;
14069 filtered_count += filtered_count_per_rd;
14070 }
14071 } else
14072 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14073 json, json_ar, json_scode, json_ocode,
14074 show_flags, &header1, &header2, rd_str,
14075 &output_count, &filtered_count);
14076
14077 if (use_json) {
c1984955
TA
14078 if (type == bgp_show_adj_route_advertised)
14079 json_object_object_add(json, "advertisedRoutes",
14080 json_ar);
14081 else
14082 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14083 json_object_int_add(json, "totalPrefixCounter", output_count);
14084 json_object_int_add(json, "filteredPrefixCounter",
14085 filtered_count);
14086
690c3134
MW
14087 /*
14088 * These fields only give up ownership to `json` when `header1`
14089 * is used (set to zero). See code in `show_adj_route` and
14090 * `show_adj_route_header`.
14091 */
14092 if (header1 == 1) {
d9478df0
TA
14093 json_object_free(json_scode);
14094 json_object_free(json_ocode);
14095 }
14096
75eeda93 14097 vty_json(vty, json);
d9478df0
TA
14098 } else if (output_count > 0) {
14099 if (filtered_count > 0)
14100 vty_out(vty,
14101 "\nTotal number of prefixes %ld (%ld filtered)\n",
14102 output_count, filtered_count);
14103 else
14104 vty_out(vty, "\nTotal number of prefixes %ld\n",
14105 output_count);
14106 }
0b16f239 14107
d62a17ae 14108 return CMD_SUCCESS;
a636c635 14109}
50ef26d4 14110
f20ce998
DS
14111DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14112 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14113 "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]",
14114 SHOW_STR
14115 IP_STR
14116 BGP_STR
14117 BGP_INSTANCE_HELP_STR
14118 BGP_AFI_HELP_STR
14119 BGP_SAFI_WITH_LABEL_HELP_STR
14120 "Detailed information on TCP and BGP neighbor connections\n"
14121 "Neighbor to display information about\n"
14122 "Neighbor to display information about\n"
14123 "Neighbor on BGP configured interface\n"
14124 "Display the routes selected by best path\n"
14125 JSON_STR
14126 "Increase table width for longer prefixes\n")
14127{
14128 afi_t afi = AFI_IP6;
14129 safi_t safi = SAFI_UNICAST;
14130 char *rmap_name = NULL;
14131 char *peerstr = NULL;
14132 struct bgp *bgp = NULL;
14133 struct peer *peer;
14134 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14135 int idx = 0;
96c81f66 14136 uint16_t show_flags = 0;
96f3485c
MK
14137
14138 if (uj)
14139 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14140
14141 if (wide)
14142 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14143
14144 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14145 &bgp, uj);
14146
14147 if (!idx)
14148 return CMD_WARNING;
14149
14150 argv_find(argv, argc, "neighbors", &idx);
14151 peerstr = argv[++idx]->arg;
14152
14153 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14154 if (!peer)
14155 return CMD_WARNING;
14156
96f3485c
MK
14157 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14158 show_flags);
f20ce998
DS
14159}
14160
ae248832 14161DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14162 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14163 "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 14164 SHOW_STR
14165 IP_STR
14166 BGP_STR
a636c635 14167 BGP_INSTANCE_HELP_STR
7395a2c9 14168 BGP_AFI_HELP_STR
4dd6177e 14169 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14170 "Display the entries for all address families\n"
718e3744 14171 "Detailed information on TCP and BGP neighbor connections\n"
14172 "Neighbor to display information about\n"
14173 "Neighbor to display information about\n"
91d37724 14174 "Neighbor on BGP configured interface\n"
a636c635 14175 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14176 "Display the received routes from neighbor\n"
14177 "Display the filtered routes received from neighbor\n"
a636c635
DW
14178 "Route-map to modify the attributes\n"
14179 "Name of the route map\n"
ae248832
MK
14180 JSON_STR
14181 "Increase table width for longer prefixes\n")
718e3744 14182{
d62a17ae 14183 afi_t afi = AFI_IP6;
14184 safi_t safi = SAFI_UNICAST;
d62a17ae 14185 char *peerstr = NULL;
d62a17ae 14186 struct bgp *bgp = NULL;
14187 struct peer *peer;
6392aaa6 14188 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14189 int idx = 0;
96f3485c 14190 bool first = true;
96c81f66 14191 uint16_t show_flags = 0;
75ce3b14
DA
14192 struct listnode *node;
14193 struct bgp *abgp;
6392aaa6 14194
96f3485c 14195 if (uj) {
d62a17ae 14196 argc--;
96f3485c
MK
14197 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14198 }
14199
14200 if (all) {
14201 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14202 if (argv_find(argv, argc, "ipv4", &idx))
14203 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14204
14205 if (argv_find(argv, argc, "ipv6", &idx))
14206 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14207 }
14208
14209 if (wide)
14210 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14211
9f049418
DS
14212 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14213 &bgp, uj);
14214 if (!idx)
14215 return CMD_WARNING;
14216
d62a17ae 14217 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14218 argv_find(argv, argc, "neighbors", &idx);
14219 peerstr = argv[++idx]->arg;
8c3deaae 14220
d62a17ae 14221 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14222 if (!peer)
14223 return CMD_WARNING;
856ca177 14224
d62a17ae 14225 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14226 type = bgp_show_adj_route_advertised;
14227 else if (argv_find(argv, argc, "received-routes", &idx))
14228 type = bgp_show_adj_route_received;
14229 else if (argv_find(argv, argc, "filtered-routes", &idx))
14230 type = bgp_show_adj_route_filtered;
14231
96f3485c 14232 if (!all)
70dd370f 14233 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14234 show_flags);
14235 if (uj)
14236 vty_out(vty, "{\n");
14237
14238 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14239 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14240 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14241 : AFI_IP6;
75ce3b14
DA
14242 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14243 FOREACH_SAFI (safi) {
14244 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14245 continue;
96f3485c 14246
75ce3b14
DA
14247 if (uj) {
14248 if (first)
14249 first = false;
14250 else
14251 vty_out(vty, ",\n");
14252 vty_out(vty, "\"%s\":",
14253 get_afi_safi_str(afi, safi,
14254 true));
14255 } else
14256 vty_out(vty,
14257 "\nFor address family: %s\n",
14258 get_afi_safi_str(afi, safi,
14259 false));
96f3485c 14260
75ce3b14 14261 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14262 route_map, show_flags);
75ce3b14 14263 }
96f3485c
MK
14264 }
14265 } else {
75ce3b14
DA
14266 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14267 FOREACH_AFI_SAFI (afi, safi) {
14268 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14269 continue;
96f3485c 14270
75ce3b14
DA
14271 if (uj) {
14272 if (first)
14273 first = false;
14274 else
14275 vty_out(vty, ",\n");
14276 vty_out(vty, "\"%s\":",
14277 get_afi_safi_str(afi, safi,
14278 true));
14279 } else
14280 vty_out(vty,
14281 "\nFor address family: %s\n",
14282 get_afi_safi_str(afi, safi,
14283 false));
96f3485c 14284
75ce3b14 14285 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14286 route_map, show_flags);
75ce3b14 14287 }
96f3485c
MK
14288 }
14289 }
14290 if (uj)
14291 vty_out(vty, "}\n");
14292
14293 return CMD_SUCCESS;
95cbbd2a
ML
14294}
14295
718e3744 14296DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14297 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14298 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14299 SHOW_STR
14300 IP_STR
14301 BGP_STR
d3120452 14302 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14303 BGP_AF_STR
14304 BGP_AF_STR
14305 BGP_AF_MODIFIER_STR
718e3744 14306 "Detailed information on TCP and BGP neighbor connections\n"
14307 "Neighbor to display information about\n"
14308 "Neighbor to display information about\n"
91d37724 14309 "Neighbor on BGP configured interface\n"
718e3744 14310 "Display information received from a BGP neighbor\n"
856ca177 14311 "Display the prefixlist filter\n"
9973d184 14312 JSON_STR)
718e3744 14313{
d62a17ae 14314 afi_t afi = AFI_IP6;
14315 safi_t safi = SAFI_UNICAST;
14316 char *peerstr = NULL;
d62a17ae 14317 char name[BUFSIZ];
d62a17ae 14318 struct peer *peer;
d3120452 14319 int count;
d62a17ae 14320 int idx = 0;
d3120452
IR
14321 struct bgp *bgp = NULL;
14322 bool uj = use_json(argc, argv);
14323
14324 if (uj)
14325 argc--;
14326
14327 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14328 &bgp, uj);
14329 if (!idx)
14330 return CMD_WARNING;
d62a17ae 14331
d62a17ae 14332 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14333 argv_find(argv, argc, "neighbors", &idx);
14334 peerstr = argv[++idx]->arg;
14335
d3120452
IR
14336 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14337 if (!peer)
14338 return CMD_WARNING;
718e3744 14339
4ced1a2c 14340 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14341 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14342 if (count) {
14343 if (!uj)
14344 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14345 get_afi_safi_str(afi, safi, false));
d62a17ae 14346 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14347 } else {
14348 if (uj)
14349 vty_out(vty, "{}\n");
14350 else
14351 vty_out(vty, "No functional output\n");
14352 }
718e3744 14353
d62a17ae 14354 return CMD_SUCCESS;
14355}
14356
14357static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14358 afi_t afi, safi_t safi,
9f049418 14359 enum bgp_show_type type, bool use_json)
d62a17ae 14360{
96c81f66 14361 uint16_t show_flags = 0;
96f3485c
MK
14362
14363 if (use_json)
14364 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14365
d62a17ae 14366 if (!peer || !peer->afc[afi][safi]) {
14367 if (use_json) {
14368 json_object *json_no = NULL;
14369 json_no = json_object_new_object();
14370 json_object_string_add(
14371 json_no, "warning",
14372 "No such neighbor or address family");
14373 vty_out(vty, "%s\n",
14374 json_object_to_json_string(json_no));
14375 json_object_free(json_no);
14376 } else
14377 vty_out(vty, "%% No such neighbor or address family\n");
14378 return CMD_WARNING;
14379 }
47fc97cc 14380
7daf25a3
TA
14381 /* labeled-unicast routes live in the unicast table */
14382 if (safi == SAFI_LABELED_UNICAST)
14383 safi = SAFI_UNICAST;
14384
1e2ce4f1
DS
14385 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14386 RPKI_NOT_BEING_USED);
718e3744 14387}
14388
dba3c1d3
PG
14389DEFUN (show_ip_bgp_flowspec_routes_detailed,
14390 show_ip_bgp_flowspec_routes_detailed_cmd,
14391 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14392 SHOW_STR
14393 IP_STR
14394 BGP_STR
14395 BGP_INSTANCE_HELP_STR
14396 BGP_AFI_HELP_STR
14397 "SAFI Flowspec\n"
14398 "Detailed information on flowspec entries\n"
14399 JSON_STR)
14400{
458c1475 14401 afi_t afi = AFI_IP6;
dba3c1d3
PG
14402 safi_t safi = SAFI_UNICAST;
14403 struct bgp *bgp = NULL;
14404 int idx = 0;
9f049418 14405 bool uj = use_json(argc, argv);
5be6fa9b 14406 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14407
96f3485c 14408 if (uj) {
9f049418 14409 argc--;
96f3485c
MK
14410 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14411 }
dba3c1d3
PG
14412
14413 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14414 &bgp, uj);
dba3c1d3
PG
14415 if (!idx)
14416 return CMD_WARNING;
14417
96f3485c 14418 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14419 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14420}
14421
718e3744 14422DEFUN (show_ip_bgp_neighbor_routes,
14423 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14424 "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 14425 SHOW_STR
14426 IP_STR
14427 BGP_STR
8386ac43 14428 BGP_INSTANCE_HELP_STR
4f280b15 14429 BGP_AFI_HELP_STR
4dd6177e 14430 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14431 "Detailed information on TCP and BGP neighbor connections\n"
14432 "Neighbor to display information about\n"
14433 "Neighbor to display information about\n"
91d37724 14434 "Neighbor on BGP configured interface\n"
2525cf39 14435 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14436 "Display the dampened routes received from neighbor\n"
14437 "Display routes learned from neighbor\n"
9973d184 14438 JSON_STR)
718e3744 14439{
d62a17ae 14440 char *peerstr = NULL;
14441 struct bgp *bgp = NULL;
14442 afi_t afi = AFI_IP6;
14443 safi_t safi = SAFI_UNICAST;
14444 struct peer *peer;
14445 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14446 int idx = 0;
9f049418
DS
14447 bool uj = use_json(argc, argv);
14448
14449 if (uj)
14450 argc--;
bb46e94f 14451
d62a17ae 14452 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14453 &bgp, uj);
d62a17ae 14454 if (!idx)
14455 return CMD_WARNING;
c493f2d8 14456
d62a17ae 14457 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14458 argv_find(argv, argc, "neighbors", &idx);
14459 peerstr = argv[++idx]->arg;
8c3deaae 14460
d62a17ae 14461 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14462 if (!peer)
d62a17ae 14463 return CMD_WARNING;
bb46e94f 14464
d62a17ae 14465 if (argv_find(argv, argc, "flap-statistics", &idx))
14466 sh_type = bgp_show_type_flap_neighbor;
14467 else if (argv_find(argv, argc, "dampened-routes", &idx))
14468 sh_type = bgp_show_type_damp_neighbor;
14469 else if (argv_find(argv, argc, "routes", &idx))
14470 sh_type = bgp_show_type_neighbor;
2525cf39 14471
d62a17ae 14472 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14473}
6b0655a2 14474
734b349e 14475struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14476
d62a17ae 14477struct bgp_distance {
14478 /* Distance value for the IP source prefix. */
d7c0a89a 14479 uint8_t distance;
718e3744 14480
d62a17ae 14481 /* Name of the access-list to be matched. */
14482 char *access_list;
718e3744 14483};
14484
4f280b15
LB
14485DEFUN (show_bgp_afi_vpn_rd_route,
14486 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14487 "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
14488 SHOW_STR
14489 BGP_STR
14490 BGP_AFI_HELP_STR
00e6edb9 14491 BGP_AF_MODIFIER_STR
4f280b15
LB
14492 "Display information for a route distinguisher\n"
14493 "Route Distinguisher\n"
a111dd97 14494 "All Route Distinguishers\n"
7395a2c9
DS
14495 "Network in the BGP routing table to display\n"
14496 "Network in the BGP routing table to display\n"
14497 JSON_STR)
4f280b15 14498{
d62a17ae 14499 int ret;
14500 struct prefix_rd prd;
14501 afi_t afi = AFI_MAX;
14502 int idx = 0;
4f280b15 14503
ff6566f3
DS
14504 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14505 vty_out(vty, "%% Malformed Address Family\n");
14506 return CMD_WARNING;
14507 }
14508
a111dd97
TA
14509 if (!strcmp(argv[5]->arg, "all"))
14510 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14511 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14512 RPKI_NOT_BEING_USED,
14513 use_json(argc, argv));
14514
d62a17ae 14515 ret = str2prefix_rd(argv[5]->arg, &prd);
14516 if (!ret) {
14517 vty_out(vty, "%% Malformed Route Distinguisher\n");
14518 return CMD_WARNING;
14519 }
ff6566f3 14520
d62a17ae 14521 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14522 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14523 use_json(argc, argv));
4f280b15
LB
14524}
14525
d62a17ae 14526static struct bgp_distance *bgp_distance_new(void)
718e3744 14527{
d62a17ae 14528 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14529}
14530
d62a17ae 14531static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14532{
d62a17ae 14533 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14534}
14535
585f1adc
IR
14536static int bgp_distance_set(struct vty *vty, const char *distance_str,
14537 const char *ip_str, const char *access_list_str)
718e3744 14538{
d62a17ae 14539 int ret;
585f1adc
IR
14540 afi_t afi;
14541 safi_t safi;
d62a17ae 14542 struct prefix p;
585f1adc 14543 uint8_t distance;
9bcb3eef 14544 struct bgp_dest *dest;
d62a17ae 14545 struct bgp_distance *bdistance;
718e3744 14546
585f1adc
IR
14547 afi = bgp_node_afi(vty);
14548 safi = bgp_node_safi(vty);
14549
d62a17ae 14550 ret = str2prefix(ip_str, &p);
14551 if (ret == 0) {
585f1adc 14552 vty_out(vty, "Malformed prefix\n");
d62a17ae 14553 return CMD_WARNING_CONFIG_FAILED;
14554 }
718e3744 14555
585f1adc
IR
14556 distance = atoi(distance_str);
14557
d62a17ae 14558 /* Get BGP distance node. */
9bcb3eef
DS
14559 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14560 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14561 if (bdistance)
9bcb3eef 14562 bgp_dest_unlock_node(dest);
ca2e160d 14563 else {
d62a17ae 14564 bdistance = bgp_distance_new();
9bcb3eef 14565 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14566 }
718e3744 14567
d62a17ae 14568 /* Set distance value. */
14569 bdistance->distance = distance;
718e3744 14570
d62a17ae 14571 /* Reset access-list configuration. */
e1b36e13 14572 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14573 if (access_list_str)
14574 bdistance->access_list =
14575 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14576
d62a17ae 14577 return CMD_SUCCESS;
718e3744 14578}
14579
585f1adc
IR
14580static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14581 const char *ip_str, const char *access_list_str)
718e3744 14582{
d62a17ae 14583 int ret;
585f1adc
IR
14584 afi_t afi;
14585 safi_t safi;
d62a17ae 14586 struct prefix p;
585f1adc 14587 int distance;
9bcb3eef 14588 struct bgp_dest *dest;
d62a17ae 14589 struct bgp_distance *bdistance;
718e3744 14590
585f1adc
IR
14591 afi = bgp_node_afi(vty);
14592 safi = bgp_node_safi(vty);
14593
d62a17ae 14594 ret = str2prefix(ip_str, &p);
14595 if (ret == 0) {
585f1adc 14596 vty_out(vty, "Malformed prefix\n");
d62a17ae 14597 return CMD_WARNING_CONFIG_FAILED;
14598 }
718e3744 14599
9bcb3eef
DS
14600 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14601 if (!dest) {
585f1adc 14602 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14603 return CMD_WARNING_CONFIG_FAILED;
14604 }
718e3744 14605
9bcb3eef 14606 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14607 distance = atoi(distance_str);
1f9a9fff 14608
d62a17ae 14609 if (bdistance->distance != distance) {
585f1adc 14610 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14611 bgp_dest_unlock_node(dest);
d62a17ae 14612 return CMD_WARNING_CONFIG_FAILED;
14613 }
718e3744 14614
0a22ddfb 14615 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14616 bgp_distance_free(bdistance);
718e3744 14617
9bcb3eef
DS
14618 bgp_dest_set_bgp_path_info(dest, NULL);
14619 bgp_dest_unlock_node(dest);
14620 bgp_dest_unlock_node(dest);
718e3744 14621
d62a17ae 14622 return CMD_SUCCESS;
718e3744 14623}
14624
718e3744 14625/* Apply BGP information to distance method. */
b8685f9b 14626uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14627 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14628{
9bcb3eef 14629 struct bgp_dest *dest;
801bb996 14630 struct prefix q = {0};
d62a17ae 14631 struct peer *peer;
14632 struct bgp_distance *bdistance;
14633 struct access_list *alist;
14634 struct bgp_static *bgp_static;
14635
14636 if (!bgp)
14637 return 0;
14638
40381db7 14639 peer = pinfo->peer;
d62a17ae 14640
7b7d48e5
DS
14641 if (pinfo->attr->distance)
14642 return pinfo->attr->distance;
14643
801bb996
CS
14644 /* Check source address.
14645 * Note: for aggregate route, peer can have unspec af type.
14646 */
14647 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14648 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14649 return 0;
14650
9bcb3eef
DS
14651 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14652 if (dest) {
14653 bdistance = bgp_dest_get_bgp_distance_info(dest);
14654 bgp_dest_unlock_node(dest);
d62a17ae 14655
14656 if (bdistance->access_list) {
14657 alist = access_list_lookup(afi, bdistance->access_list);
14658 if (alist
14659 && access_list_apply(alist, p) == FILTER_PERMIT)
14660 return bdistance->distance;
14661 } else
14662 return bdistance->distance;
718e3744 14663 }
718e3744 14664
d62a17ae 14665 /* Backdoor check. */
9bcb3eef
DS
14666 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14667 if (dest) {
14668 bgp_static = bgp_dest_get_bgp_static_info(dest);
14669 bgp_dest_unlock_node(dest);
718e3744 14670
d62a17ae 14671 if (bgp_static->backdoor) {
14672 if (bgp->distance_local[afi][safi])
14673 return bgp->distance_local[afi][safi];
14674 else
14675 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14676 }
718e3744 14677 }
718e3744 14678
d62a17ae 14679 if (peer->sort == BGP_PEER_EBGP) {
14680 if (bgp->distance_ebgp[afi][safi])
14681 return bgp->distance_ebgp[afi][safi];
14682 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14683 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14684 if (bgp->distance_ibgp[afi][safi])
14685 return bgp->distance_ibgp[afi][safi];
14686 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14687 } else {
14688 if (bgp->distance_local[afi][safi])
14689 return bgp->distance_local[afi][safi];
14690 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14691 }
718e3744 14692}
14693
a612fb77
DA
14694/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14695 * we should tell ZEBRA update the routes for a specific
14696 * AFI/SAFI to reflect changes in RIB.
14697 */
585f1adc
IR
14698static void bgp_announce_routes_distance_update(struct bgp *bgp,
14699 afi_t update_afi,
14700 safi_t update_safi)
a612fb77
DA
14701{
14702 afi_t afi;
14703 safi_t safi;
14704
14705 FOREACH_AFI_SAFI (afi, safi) {
14706 if (!bgp_fibupd_safi(safi))
14707 continue;
14708
8b54bc30
DA
14709 if (afi != update_afi && safi != update_safi)
14710 continue;
14711
14712 if (BGP_DEBUG(zebra, ZEBRA))
14713 zlog_debug(
14714 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14715 __func__, afi, safi);
14716 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14717 }
14718}
14719
585f1adc
IR
14720DEFUN (bgp_distance,
14721 bgp_distance_cmd,
14722 "distance bgp (1-255) (1-255) (1-255)",
14723 "Define an administrative distance\n"
14724 "BGP distance\n"
14725 "Distance for routes external to the AS\n"
14726 "Distance for routes internal to the AS\n"
14727 "Distance for local routes\n")
718e3744 14728{
585f1adc 14729 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14730 int idx_number = 2;
14731 int idx_number_2 = 3;
14732 int idx_number_3 = 4;
585f1adc
IR
14733 int distance_ebgp = atoi(argv[idx_number]->arg);
14734 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14735 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14736 afi_t afi;
14737 safi_t safi;
718e3744 14738
d62a17ae 14739 afi = bgp_node_afi(vty);
14740 safi = bgp_node_safi(vty);
718e3744 14741
585f1adc
IR
14742 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14743 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14744 || bgp->distance_local[afi][safi] != distance_local) {
14745 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14746 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14747 bgp->distance_local[afi][safi] = distance_local;
14748 bgp_announce_routes_distance_update(bgp, afi, safi);
14749 }
14750 return CMD_SUCCESS;
14751}
37a87b8f 14752
585f1adc
IR
14753DEFUN (no_bgp_distance,
14754 no_bgp_distance_cmd,
14755 "no distance bgp [(1-255) (1-255) (1-255)]",
14756 NO_STR
14757 "Define an administrative distance\n"
14758 "BGP distance\n"
14759 "Distance for routes external to the AS\n"
14760 "Distance for routes internal to the AS\n"
14761 "Distance for local routes\n")
718e3744 14762{
585f1adc 14763 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14764 afi_t afi;
14765 safi_t safi;
37a87b8f
CS
14766
14767 afi = bgp_node_afi(vty);
14768 safi = bgp_node_safi(vty);
14769
585f1adc
IR
14770 if (bgp->distance_ebgp[afi][safi] != 0
14771 || bgp->distance_ibgp[afi][safi] != 0
14772 || bgp->distance_local[afi][safi] != 0) {
14773 bgp->distance_ebgp[afi][safi] = 0;
14774 bgp->distance_ibgp[afi][safi] = 0;
14775 bgp->distance_local[afi][safi] = 0;
14776 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14777 }
585f1adc
IR
14778 return CMD_SUCCESS;
14779}
37a87b8f 14780
37a87b8f 14781
585f1adc
IR
14782DEFUN (bgp_distance_source,
14783 bgp_distance_source_cmd,
14784 "distance (1-255) A.B.C.D/M",
14785 "Define an administrative distance\n"
14786 "Administrative distance\n"
14787 "IP source prefix\n")
14788{
14789 int idx_number = 1;
14790 int idx_ipv4_prefixlen = 2;
14791 bgp_distance_set(vty, argv[idx_number]->arg,
14792 argv[idx_ipv4_prefixlen]->arg, NULL);
14793 return CMD_SUCCESS;
734b349e
MZ
14794}
14795
585f1adc
IR
14796DEFUN (no_bgp_distance_source,
14797 no_bgp_distance_source_cmd,
14798 "no distance (1-255) A.B.C.D/M",
14799 NO_STR
14800 "Define an administrative distance\n"
14801 "Administrative distance\n"
14802 "IP source prefix\n")
37a87b8f 14803{
585f1adc
IR
14804 int idx_number = 2;
14805 int idx_ipv4_prefixlen = 3;
14806 bgp_distance_unset(vty, argv[idx_number]->arg,
14807 argv[idx_ipv4_prefixlen]->arg, NULL);
14808 return CMD_SUCCESS;
37a87b8f
CS
14809}
14810
585f1adc
IR
14811DEFUN (bgp_distance_source_access_list,
14812 bgp_distance_source_access_list_cmd,
14813 "distance (1-255) A.B.C.D/M WORD",
14814 "Define an administrative distance\n"
14815 "Administrative distance\n"
14816 "IP source prefix\n"
14817 "Access list name\n")
37a87b8f 14818{
585f1adc
IR
14819 int idx_number = 1;
14820 int idx_ipv4_prefixlen = 2;
14821 int idx_word = 3;
14822 bgp_distance_set(vty, argv[idx_number]->arg,
14823 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14824 return CMD_SUCCESS;
14825}
718e3744 14826
585f1adc
IR
14827DEFUN (no_bgp_distance_source_access_list,
14828 no_bgp_distance_source_access_list_cmd,
14829 "no distance (1-255) A.B.C.D/M WORD",
14830 NO_STR
14831 "Define an administrative distance\n"
14832 "Administrative distance\n"
14833 "IP source prefix\n"
14834 "Access list name\n")
14835{
14836 int idx_number = 2;
14837 int idx_ipv4_prefixlen = 3;
14838 int idx_word = 4;
14839 bgp_distance_unset(vty, argv[idx_number]->arg,
14840 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14841 return CMD_SUCCESS;
14842}
37a87b8f 14843
585f1adc
IR
14844DEFUN (ipv6_bgp_distance_source,
14845 ipv6_bgp_distance_source_cmd,
14846 "distance (1-255) X:X::X:X/M",
14847 "Define an administrative distance\n"
14848 "Administrative distance\n"
14849 "IP source prefix\n")
14850{
14851 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14852 return CMD_SUCCESS;
14853}
7ebe9748 14854
585f1adc
IR
14855DEFUN (no_ipv6_bgp_distance_source,
14856 no_ipv6_bgp_distance_source_cmd,
14857 "no distance (1-255) X:X::X:X/M",
14858 NO_STR
14859 "Define an administrative distance\n"
14860 "Administrative distance\n"
14861 "IP source prefix\n")
14862{
14863 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14864 return CMD_SUCCESS;
14865}
37a87b8f 14866
585f1adc
IR
14867DEFUN (ipv6_bgp_distance_source_access_list,
14868 ipv6_bgp_distance_source_access_list_cmd,
14869 "distance (1-255) X:X::X:X/M WORD",
14870 "Define an administrative distance\n"
14871 "Administrative distance\n"
14872 "IP source prefix\n"
14873 "Access list name\n")
14874{
14875 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14876 return CMD_SUCCESS;
718e3744 14877}
14878
585f1adc
IR
14879DEFUN (no_ipv6_bgp_distance_source_access_list,
14880 no_ipv6_bgp_distance_source_access_list_cmd,
14881 "no distance (1-255) X:X::X:X/M WORD",
14882 NO_STR
14883 "Define an administrative distance\n"
14884 "Administrative distance\n"
14885 "IP source prefix\n"
14886 "Access list name\n")
718e3744 14887{
585f1adc
IR
14888 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14889 return CMD_SUCCESS;
14890}
37a87b8f 14891
585f1adc
IR
14892DEFUN (bgp_damp_set,
14893 bgp_damp_set_cmd,
a30fec23 14894 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14895 "BGP Specific commands\n"
14896 "Enable route-flap dampening\n"
14897 "Half-life time for the penalty\n"
14898 "Value to start reusing a route\n"
14899 "Value to start suppressing a route\n"
14900 "Maximum duration to suppress a stable route\n")
14901{
14902 VTY_DECLVAR_CONTEXT(bgp, bgp);
14903 int idx_half_life = 2;
14904 int idx_reuse = 3;
14905 int idx_suppress = 4;
14906 int idx_max_suppress = 5;
37a87b8f
CS
14907 int half = DEFAULT_HALF_LIFE * 60;
14908 int reuse = DEFAULT_REUSE;
14909 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14910 int max = 4 * half;
14911
14912 if (argc == 6) {
14913 half = atoi(argv[idx_half_life]->arg) * 60;
14914 reuse = atoi(argv[idx_reuse]->arg);
14915 suppress = atoi(argv[idx_suppress]->arg);
14916 max = atoi(argv[idx_max_suppress]->arg) * 60;
14917 } else if (argc == 3) {
14918 half = atoi(argv[idx_half_life]->arg) * 60;
14919 max = 4 * half;
14920 }
14921
14922 /*
14923 * These can't be 0 but our SA doesn't understand the
14924 * way our cli is constructed
14925 */
14926 assert(reuse);
14927 assert(half);
14928 if (suppress < reuse) {
14929 vty_out(vty,
14930 "Suppress value cannot be less than reuse value \n");
14931 return 0;
14932 }
14933
14934 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14935 reuse, suppress, max);
14936}
14937
14938DEFUN (bgp_damp_unset,
14939 bgp_damp_unset_cmd,
a30fec23 14940 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14941 NO_STR
14942 "BGP Specific commands\n"
14943 "Enable route-flap dampening\n"
14944 "Half-life time for the penalty\n"
14945 "Value to start reusing a route\n"
14946 "Value to start suppressing a route\n"
14947 "Maximum duration to suppress a stable route\n")
14948{
14949 VTY_DECLVAR_CONTEXT(bgp, bgp);
14950 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14951}
14952
718e3744 14953/* Display specified route of BGP table. */
d62a17ae 14954static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14955 const char *ip_str, afi_t afi, safi_t safi,
14956 struct prefix_rd *prd, int prefix_check)
14957{
14958 int ret;
14959 struct prefix match;
9bcb3eef
DS
14960 struct bgp_dest *dest;
14961 struct bgp_dest *rm;
40381db7
DS
14962 struct bgp_path_info *pi;
14963 struct bgp_path_info *pi_temp;
d62a17ae 14964 struct bgp *bgp;
14965 struct bgp_table *table;
14966
14967 /* BGP structure lookup. */
14968 if (view_name) {
14969 bgp = bgp_lookup_by_name(view_name);
14970 if (bgp == NULL) {
14971 vty_out(vty, "%% Can't find BGP instance %s\n",
14972 view_name);
14973 return CMD_WARNING;
14974 }
14975 } else {
14976 bgp = bgp_get_default();
14977 if (bgp == NULL) {
14978 vty_out(vty, "%% No BGP process is configured\n");
14979 return CMD_WARNING;
14980 }
718e3744 14981 }
718e3744 14982
d62a17ae 14983 /* Check IP address argument. */
14984 ret = str2prefix(ip_str, &match);
14985 if (!ret) {
14986 vty_out(vty, "%% address is malformed\n");
14987 return CMD_WARNING;
14988 }
718e3744 14989
d62a17ae 14990 match.family = afi2family(afi);
14991
14992 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14993 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14994 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14995 dest = bgp_route_next(dest)) {
14996 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14997
9bcb3eef 14998 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14999 continue;
9bcb3eef 15000 table = bgp_dest_get_bgp_table_info(dest);
67009e22 15001 if (!table)
ea47320b 15002 continue;
4953391b
DA
15003 rm = bgp_node_match(table, &match);
15004 if (rm == NULL)
ea47320b 15005 continue;
d62a17ae 15006
9bcb3eef 15007 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 15008
ea47320b 15009 if (!prefix_check
b54892e0 15010 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 15011 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
15012 while (pi) {
15013 if (pi->extra && pi->extra->damp_info) {
15014 pi_temp = pi->next;
ea47320b 15015 bgp_damp_info_free(
19971c9a 15016 pi->extra->damp_info,
5c8846f6 15017 1, afi, safi);
40381db7 15018 pi = pi_temp;
ea47320b 15019 } else
40381db7 15020 pi = pi->next;
d62a17ae 15021 }
ea47320b
DL
15022 }
15023
9bcb3eef 15024 bgp_dest_unlock_node(rm);
d62a17ae 15025 }
15026 } else {
4953391b
DA
15027 dest = bgp_node_match(bgp->rib[afi][safi], &match);
15028 if (dest != NULL) {
9bcb3eef 15029 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 15030
d62a17ae 15031 if (!prefix_check
9bcb3eef
DS
15032 || dest_p->prefixlen == match.prefixlen) {
15033 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
15034 while (pi) {
15035 if (pi->extra && pi->extra->damp_info) {
15036 pi_temp = pi->next;
d62a17ae 15037 bgp_damp_info_free(
19971c9a 15038 pi->extra->damp_info,
5c8846f6 15039 1, afi, safi);
40381db7 15040 pi = pi_temp;
d62a17ae 15041 } else
40381db7 15042 pi = pi->next;
d62a17ae 15043 }
15044 }
15045
9bcb3eef 15046 bgp_dest_unlock_node(dest);
d62a17ae 15047 }
15048 }
718e3744 15049
d62a17ae 15050 return CMD_SUCCESS;
718e3744 15051}
15052
15053DEFUN (clear_ip_bgp_dampening,
15054 clear_ip_bgp_dampening_cmd,
15055 "clear ip bgp dampening",
15056 CLEAR_STR
15057 IP_STR
15058 BGP_STR
15059 "Clear route flap dampening information\n")
15060{
b4f7f45b 15061 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15062 return CMD_SUCCESS;
718e3744 15063}
15064
15065DEFUN (clear_ip_bgp_dampening_prefix,
15066 clear_ip_bgp_dampening_prefix_cmd,
15067 "clear ip bgp dampening A.B.C.D/M",
15068 CLEAR_STR
15069 IP_STR
15070 BGP_STR
15071 "Clear route flap dampening information\n"
0c7b1b01 15072 "IPv4 prefix\n")
718e3744 15073{
d62a17ae 15074 int idx_ipv4_prefixlen = 4;
15075 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15076 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15077}
15078
15079DEFUN (clear_ip_bgp_dampening_address,
15080 clear_ip_bgp_dampening_address_cmd,
15081 "clear ip bgp dampening A.B.C.D",
15082 CLEAR_STR
15083 IP_STR
15084 BGP_STR
15085 "Clear route flap dampening information\n"
15086 "Network to clear damping information\n")
15087{
d62a17ae 15088 int idx_ipv4 = 4;
15089 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15090 SAFI_UNICAST, NULL, 0);
718e3744 15091}
15092
15093DEFUN (clear_ip_bgp_dampening_address_mask,
15094 clear_ip_bgp_dampening_address_mask_cmd,
15095 "clear ip bgp dampening A.B.C.D A.B.C.D",
15096 CLEAR_STR
15097 IP_STR
15098 BGP_STR
15099 "Clear route flap dampening information\n"
15100 "Network to clear damping information\n"
15101 "Network mask\n")
15102{
d62a17ae 15103 int idx_ipv4 = 4;
15104 int idx_ipv4_2 = 5;
15105 int ret;
15106 char prefix_str[BUFSIZ];
718e3744 15107
d62a17ae 15108 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15109 prefix_str, sizeof(prefix_str));
d62a17ae 15110 if (!ret) {
15111 vty_out(vty, "%% Inconsistent address and mask\n");
15112 return CMD_WARNING;
15113 }
718e3744 15114
d62a17ae 15115 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15116 NULL, 0);
718e3744 15117}
6b0655a2 15118
e3b78da8 15119static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15120{
15121 struct vty *vty = arg;
e3b78da8 15122 struct peer *peer = bucket->data;
825d9834 15123
47e12884 15124 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15125}
15126
2a0e69ae
DS
15127DEFUN (show_bgp_listeners,
15128 show_bgp_listeners_cmd,
15129 "show bgp listeners",
15130 SHOW_STR
15131 BGP_STR
15132 "Display Listen Sockets and who created them\n")
15133{
15134 bgp_dump_listener_info(vty);
15135
15136 return CMD_SUCCESS;
15137}
15138
825d9834
DS
15139DEFUN (show_bgp_peerhash,
15140 show_bgp_peerhash_cmd,
15141 "show bgp peerhash",
15142 SHOW_STR
15143 BGP_STR
15144 "Display information about the BGP peerhash\n")
15145{
15146 struct list *instances = bm->bgp;
15147 struct listnode *node;
15148 struct bgp *bgp;
15149
15150 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15151 vty_out(vty, "BGP: %s\n", bgp->name);
15152 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15153 vty);
15154 }
15155
15156 return CMD_SUCCESS;
15157}
15158
587ff0fd 15159/* also used for encap safi */
2b791107
DL
15160static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15161 afi_t afi, safi_t safi)
d62a17ae 15162{
9bcb3eef
DS
15163 struct bgp_dest *pdest;
15164 struct bgp_dest *dest;
d62a17ae 15165 struct bgp_table *table;
b54892e0
DS
15166 const struct prefix *p;
15167 const struct prefix_rd *prd;
d62a17ae 15168 struct bgp_static *bgp_static;
15169 mpls_label_t label;
d62a17ae 15170 char rdbuf[RD_ADDRSTRLEN];
15171
15172 /* Network configuration. */
9bcb3eef
DS
15173 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15174 pdest = bgp_route_next(pdest)) {
15175 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15176 if (!table)
ea47320b 15177 continue;
d62a17ae 15178
9bcb3eef
DS
15179 for (dest = bgp_table_top(table); dest;
15180 dest = bgp_route_next(dest)) {
15181 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15182 if (bgp_static == NULL)
ea47320b 15183 continue;
d62a17ae 15184
9bcb3eef
DS
15185 p = bgp_dest_get_prefix(dest);
15186 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15187 pdest);
d62a17ae 15188
ea47320b 15189 /* "network" configuration display. */
06b9f471 15190 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
15191 label = decode_label(&bgp_static->label);
15192
8228a9a7 15193 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
15194 if (safi == SAFI_MPLS_VPN)
15195 vty_out(vty, " label %u", label);
15196
15197 if (bgp_static->rmap.name)
15198 vty_out(vty, " route-map %s",
15199 bgp_static->rmap.name);
e2a86ad9
DS
15200
15201 if (bgp_static->backdoor)
15202 vty_out(vty, " backdoor");
15203
ea47320b
DL
15204 vty_out(vty, "\n");
15205 }
15206 }
d62a17ae 15207}
15208
2b791107
DL
15209static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15210 afi_t afi, safi_t safi)
d62a17ae 15211{
9bcb3eef
DS
15212 struct bgp_dest *pdest;
15213 struct bgp_dest *dest;
d62a17ae 15214 struct bgp_table *table;
b54892e0
DS
15215 const struct prefix *p;
15216 const struct prefix_rd *prd;
d62a17ae 15217 struct bgp_static *bgp_static;
ff44f570 15218 char buf[PREFIX_STRLEN * 2];
d62a17ae 15219 char buf2[SU_ADDRSTRLEN];
15220 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15221 char esi_buf[ESI_STR_LEN];
d62a17ae 15222
15223 /* Network configuration. */
9bcb3eef
DS
15224 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15225 pdest = bgp_route_next(pdest)) {
15226 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15227 if (!table)
ea47320b 15228 continue;
d62a17ae 15229
9bcb3eef
DS
15230 for (dest = bgp_table_top(table); dest;
15231 dest = bgp_route_next(dest)) {
15232 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15233 if (bgp_static == NULL)
ea47320b 15234 continue;
d62a17ae 15235
ea47320b 15236 char *macrouter = NULL;
d62a17ae 15237
ea47320b
DL
15238 if (bgp_static->router_mac)
15239 macrouter = prefix_mac2str(
15240 bgp_static->router_mac, NULL, 0);
15241 if (bgp_static->eth_s_id)
0a50c248
AK
15242 esi_to_str(bgp_static->eth_s_id,
15243 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15244 p = bgp_dest_get_prefix(dest);
15245 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15246
ea47320b 15247 /* "network" configuration display. */
06b9f471 15248 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15249 if (p->u.prefix_evpn.route_type == 5) {
15250 char local_buf[PREFIX_STRLEN];
3714a385 15251 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15252 struct prefix_evpn *)p)
15253 ? AF_INET
15254 : AF_INET6;
3714a385 15255 inet_ntop(family,
15256 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15257 local_buf, PREFIX_STRLEN);
772270f3
QY
15258 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15259 p->u.prefix_evpn.prefix_addr
15260 .ip_prefix_length);
197cb530
PG
15261 } else {
15262 prefix2str(p, buf, sizeof(buf));
15263 }
ea47320b 15264
a4d82a8a
PZ
15265 if (bgp_static->gatewayIp.family == AF_INET
15266 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15267 inet_ntop(bgp_static->gatewayIp.family,
15268 &bgp_static->gatewayIp.u.prefix, buf2,
15269 sizeof(buf2));
ea47320b 15270 vty_out(vty,
7bcc8dac 15271 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15272 buf, rdbuf,
15273 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15274 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15275 macrouter);
15276
0a22ddfb 15277 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15278 }
15279 }
3da6fcd5
PG
15280}
15281
718e3744 15282/* Configuration of static route announcement and aggregate
15283 information. */
2b791107
DL
15284void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15285 safi_t safi)
d62a17ae 15286{
9bcb3eef 15287 struct bgp_dest *dest;
b54892e0 15288 const struct prefix *p;
d62a17ae 15289 struct bgp_static *bgp_static;
15290 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15291
2b791107
DL
15292 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15293 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15294 return;
15295 }
d62a17ae 15296
2b791107
DL
15297 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15298 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15299 return;
15300 }
d62a17ae 15301
15302 /* Network configuration. */
9bcb3eef
DS
15303 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15304 dest = bgp_route_next(dest)) {
15305 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15306 if (bgp_static == NULL)
ea47320b 15307 continue;
d62a17ae 15308
9bcb3eef 15309 p = bgp_dest_get_prefix(dest);
d62a17ae 15310
8228a9a7 15311 vty_out(vty, " network %pFX", p);
d62a17ae 15312
ea47320b
DL
15313 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15314 vty_out(vty, " label-index %u",
15315 bgp_static->label_index);
d62a17ae 15316
ea47320b
DL
15317 if (bgp_static->rmap.name)
15318 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15319
15320 if (bgp_static->backdoor)
15321 vty_out(vty, " backdoor");
718e3744 15322
ea47320b
DL
15323 vty_out(vty, "\n");
15324 }
15325
d62a17ae 15326 /* Aggregate-address configuration. */
9bcb3eef
DS
15327 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15328 dest = bgp_route_next(dest)) {
15329 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15330 if (bgp_aggregate == NULL)
ea47320b 15331 continue;
d62a17ae 15332
9bcb3eef 15333 p = bgp_dest_get_prefix(dest);
d62a17ae 15334
8228a9a7 15335 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15336
ea47320b
DL
15337 if (bgp_aggregate->as_set)
15338 vty_out(vty, " as-set");
d62a17ae 15339
ea47320b
DL
15340 if (bgp_aggregate->summary_only)
15341 vty_out(vty, " summary-only");
718e3744 15342
20894f50
DA
15343 if (bgp_aggregate->rmap.name)
15344 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15345
229757f1
DA
15346 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15347 vty_out(vty, " origin %s",
15348 bgp_origin2str(bgp_aggregate->origin));
15349
6aabb15d
RZ
15350 if (bgp_aggregate->match_med)
15351 vty_out(vty, " matching-MED-only");
15352
365ab2e7
RZ
15353 if (bgp_aggregate->suppress_map_name)
15354 vty_out(vty, " suppress-map %s",
15355 bgp_aggregate->suppress_map_name);
15356
ea47320b
DL
15357 vty_out(vty, "\n");
15358 }
d62a17ae 15359}
734b349e 15360
2b791107 15361void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15362 safi_t safi)
d62a17ae 15363{
9bcb3eef 15364 struct bgp_dest *dest;
d62a17ae 15365 struct bgp_distance *bdistance;
15366
15367 /* Distance configuration. */
15368 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15369 && bgp->distance_local[afi][safi]
15370 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15371 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15372 || bgp->distance_local[afi][safi]
15373 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15374 vty_out(vty, " distance bgp %d %d %d\n",
15375 bgp->distance_ebgp[afi][safi],
15376 bgp->distance_ibgp[afi][safi],
15377 bgp->distance_local[afi][safi]);
15378 }
734b349e 15379
9bcb3eef
DS
15380 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15381 dest = bgp_route_next(dest)) {
15382 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15383 if (bdistance != NULL)
56ca3b5b 15384 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15385 bdistance->distance, dest,
d62a17ae 15386 bdistance->access_list ? bdistance->access_list
15387 : "");
ca2e160d 15388 }
718e3744 15389}
15390
15391/* Allocate routing table structure and install commands. */
d62a17ae 15392void bgp_route_init(void)
15393{
15394 afi_t afi;
15395 safi_t safi;
15396
15397 /* Init BGP distance table. */
05c7a1cc 15398 FOREACH_AFI_SAFI (afi, safi)
960035b2 15399 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15400
15401 /* IPv4 BGP commands. */
15402 install_element(BGP_NODE, &bgp_table_map_cmd);
15403 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15404 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15405
554b3b10 15406 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15407
15408 /* IPv4 unicast configuration. */
15409 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15410 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15411 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15412
554b3b10 15413 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15414
15415 /* IPv4 multicast configuration. */
15416 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15417 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15418 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15419 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15420
15421 /* IPv4 labeled-unicast configuration. */
fb985e0c 15422 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15423 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15424
d62a17ae 15425 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15426 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15427 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15428 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15429 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15430 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15431 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15432 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15433
15434 install_element(VIEW_NODE,
15435 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15436 install_element(VIEW_NODE,
15437 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15438 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15439 install_element(VIEW_NODE,
15440 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15441#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15442 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15443#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15444 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15445 install_element(VIEW_NODE,
44c69747 15446 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15447
d62a17ae 15448 /* BGP dampening clear commands */
15449 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15450 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15451
d62a17ae 15452 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15453 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15454
15455 /* prefix count */
15456 install_element(ENABLE_NODE,
15457 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15458#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15459 install_element(ENABLE_NODE,
15460 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15461#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15462
d62a17ae 15463 /* New config IPv6 BGP commands. */
15464 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15465 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15466 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15467
554b3b10 15468 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15469
15470 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15471
fb985e0c
DA
15472 /* IPv6 labeled unicast address family. */
15473 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15474 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15475
d62a17ae 15476 install_element(BGP_NODE, &bgp_distance_cmd);
15477 install_element(BGP_NODE, &no_bgp_distance_cmd);
15478 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15479 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15480 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15481 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15482 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15483 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15484 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15485 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15486 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15487 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15488 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15489 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15490 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15491 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15492 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15493 install_element(BGP_IPV4M_NODE,
15494 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15495 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15496 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15497 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15498 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15499 install_element(BGP_IPV6_NODE,
15500 &ipv6_bgp_distance_source_access_list_cmd);
15501 install_element(BGP_IPV6_NODE,
15502 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15503 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15504 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15505 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15506 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15507 install_element(BGP_IPV6M_NODE,
15508 &ipv6_bgp_distance_source_access_list_cmd);
15509 install_element(BGP_IPV6M_NODE,
15510 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15511
ef5f4b23 15512 /* BGP dampening */
585f1adc
IR
15513 install_element(BGP_NODE, &bgp_damp_set_cmd);
15514 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15515 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15516 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15517 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15518 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15519 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15520 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15521 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15522 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15523 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15524 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15525 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15526 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15527
15528 /* Large Communities */
15529 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15530 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15531
15532 /* show bgp ipv4 flowspec detailed */
15533 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15534
2a0e69ae 15535 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15536 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15537}
15538
15539void bgp_route_finish(void)
15540{
15541 afi_t afi;
15542 safi_t safi;
15543
05c7a1cc
QY
15544 FOREACH_AFI_SAFI (afi, safi) {
15545 bgp_table_unlock(bgp_distance_table[afi][safi]);
15546 bgp_distance_table[afi][safi] = NULL;
15547 }
228da428 15548}