]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
tests: Check if BGP as-override works correctly
[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
ff3bf9a4
DS
258 if (e->aggr_suppressors)
259 list_delete(&e->aggr_suppressors);
260
60605cbc
AK
261 if (e->mh_info)
262 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 263
ce3c0614
PG
264 if ((*extra)->bgp_fs_iprule)
265 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 266 if ((*extra)->bgp_fs_pbr)
6a154c88 267 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 268 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
269}
270
18ee8310
DS
271/* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
fb982c25 273 */
40381db7 274struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 275{
40381db7
DS
276 if (!pi->extra)
277 pi->extra = bgp_path_info_extra_new();
278 return pi->extra;
fb982c25
PJ
279}
280
718e3744 281/* Free bgp route information. */
9b6d8fcf 282static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 283{
05864da7 284 bgp_attr_unintern(&path->attr);
fb018d25 285
9b6d8fcf
DS
286 bgp_unlink_nexthop(path);
287 bgp_path_info_extra_free(&path->extra);
288 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
289 if (path->net)
290 bgp_addpath_free_info_data(&path->tx_addpath,
291 &path->net->tx_addpath);
718e3744 292
9b6d8fcf 293 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 294
9b6d8fcf 295 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 296}
297
9b6d8fcf 298struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 299{
9b6d8fcf
DS
300 path->lock++;
301 return path;
200df115 302}
303
9b6d8fcf 304struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 305{
9b6d8fcf
DS
306 assert(path && path->lock > 0);
307 path->lock--;
d62a17ae 308
9b6d8fcf 309 if (path->lock == 0) {
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
9b6d8fcf 314 return path;
200df115 315}
316
f009ff26 317/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 318static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 319{
320 struct peer *peer;
321 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 322 bool set_flag = false;
f009ff26 323 struct bgp *bgp = NULL;
324 struct bgp_table *table = NULL;
325 afi_t afi = 0;
326 safi_t safi = 0;
f009ff26 327
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
330 */
9bcb3eef 331 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 332 return 0;
333
9bcb3eef 334 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 335 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 336 zlog_debug(
56ca3b5b
DL
337 "Route %pBD is in workqueue and being processed, not deferred.",
338 dest);
b54892e0 339
5f9c1aa2 340 return 0;
341 }
342
9bcb3eef 343 table = bgp_dest_table(dest);
f009ff26 344 if (table) {
345 bgp = table->bgp;
346 afi = table->afi;
347 safi = table->safi;
348 }
349
9bcb3eef 350 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 351 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
352 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
353 continue;
354
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
357 */
36235319
QY
358 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
359 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 360 set_flag = true;
f009ff26 361 } else {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
364 */
365 peer = old_pi->peer;
36235319
QY
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
367 && BGP_PEER_RESTARTING_MODE(peer)
368 && (old_pi
369 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 370 set_flag = true;
f009ff26 371 }
372 }
373 if (set_flag)
374 break;
375 }
376
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
378 * is active
379 */
2ba1fe69 380 if (set_flag && table) {
f009ff26 381 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
382 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
383 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 384 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 385 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
386 zlog_debug("DEFER route %pBD, dest %p", dest,
387 dest);
f009ff26 388 return 0;
389 }
390 }
391 return -1;
392}
393
9bcb3eef 394void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 395{
4b7e6066 396 struct bgp_path_info *top;
718e3744 397
9bcb3eef 398 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 399
6f94b685 400 pi->next = top;
40381db7 401 pi->prev = NULL;
d62a17ae 402 if (top)
40381db7 403 top->prev = pi;
9bcb3eef 404 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 405
40381db7 406 bgp_path_info_lock(pi);
9bcb3eef 407 bgp_dest_lock_node(dest);
40381db7 408 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 409 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 410 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 411}
412
d62a17ae 413/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 414 completion callback *only* */
9bcb3eef 415void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 416{
40381db7
DS
417 if (pi->next)
418 pi->next->prev = pi->prev;
419 if (pi->prev)
420 pi->prev->next = pi->next;
d62a17ae 421 else
9bcb3eef 422 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 423
40381db7
DS
424 bgp_path_info_mpath_dequeue(pi);
425 bgp_path_info_unlock(pi);
7fd28dd2 426 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 427 bgp_dest_unlock_node(dest);
718e3744 428}
429
9bcb3eef 430void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 431{
9bcb3eef 432 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 433 /* set of previous already took care of pcount */
40381db7 434 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 435}
436
18ee8310 437/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
9bcb3eef 440void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 441{
9bcb3eef 442 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 443 /* unset of previous already took care of pcount */
40381db7 444 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
445}
446
d62a17ae 447/* Adjust pcount as required */
9bcb3eef 448static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 449{
d62a17ae 450 struct bgp_table *table;
67174041 451
9bcb3eef 452 assert(dest && bgp_dest_table(dest));
40381db7 453 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 454
9bcb3eef 455 table = bgp_dest_table(dest);
67174041 456
40381db7 457 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 458 return;
459
40381db7
DS
460 if (!BGP_PATH_COUNTABLE(pi)
461 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 462
40381db7 463 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 464
465 /* slight hack, but more robust against errors. */
40381db7
DS
466 if (pi->peer->pcount[table->afi][table->safi])
467 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 468 else
450971aa 469 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 470 "Asked to decrement 0 prefix count for peer");
40381db7
DS
471 } else if (BGP_PATH_COUNTABLE(pi)
472 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
473 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
474 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 475 }
1a392d46
PJ
476}
477
40381db7
DS
478static int bgp_label_index_differs(struct bgp_path_info *pi1,
479 struct bgp_path_info *pi2)
28d58fd7 480{
40381db7 481 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 482}
1a392d46 483
18ee8310 484/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
485 * This is here primarily to keep prefix-count in check.
486 */
9bcb3eef 487void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 488 uint32_t flag)
1a392d46 489{
40381db7 490 SET_FLAG(pi->flags, flag);
d62a17ae 491
492 /* early bath if we know it's not a flag that changes countability state
493 */
494 if (!CHECK_FLAG(flag,
1defdda8 495 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 496 return;
497
9bcb3eef 498 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
499}
500
9bcb3eef 501void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 502 uint32_t flag)
1a392d46 503{
40381db7 504 UNSET_FLAG(pi->flags, flag);
d62a17ae 505
506 /* early bath if we know it's not a flag that changes countability state
507 */
508 if (!CHECK_FLAG(flag,
1defdda8 509 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 510 return;
511
9bcb3eef 512 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
513}
514
718e3744 515/* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 517static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 518{
519 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
520 return attr->med;
521 else {
892fedb6 522 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 523 return BGP_MED_MAX;
524 else
525 return 0;
526 }
718e3744 527}
528
7533cad7
QY
529void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
530 size_t buf_len)
2ec1e66f 531{
40381db7 532 if (pi->addpath_rx_id)
7533cad7
QY
533 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
534 pi->peer->host, pi->addpath_rx_id);
d62a17ae 535 else
7533cad7 536 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 537}
9fbdd100 538
da0c0ef7
KM
539
540/*
541 * Get the ultimate path info.
542 */
543struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
544{
545 struct bgp_path_info *bpi_ultimate;
546
547 if (info->sub_type != BGP_ROUTE_IMPORTED)
548 return info;
549
550 for (bpi_ultimate = info;
551 bpi_ultimate->extra && bpi_ultimate->extra->parent;
552 bpi_ultimate = bpi_ultimate->extra->parent)
553 ;
554
555 return bpi_ultimate;
556}
557
d62a17ae 558/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 */
18ee8310
DS
560static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
561 struct bgp_path_info *exist, int *paths_eq,
562 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
563 char *pfx_buf, afi_t afi, safi_t safi,
564 enum bgp_path_selection_reason *reason)
d62a17ae 565{
5df26422 566 const struct prefix *new_p;
d62a17ae 567 struct attr *newattr, *existattr;
3061acc2
DA
568 enum bgp_peer_sort new_sort;
569 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
570 uint32_t new_pref;
571 uint32_t exist_pref;
572 uint32_t new_med;
573 uint32_t exist_med;
574 uint32_t new_weight;
575 uint32_t exist_weight;
d62a17ae 576 uint32_t newm, existm;
577 struct in_addr new_id;
578 struct in_addr exist_id;
579 int new_cluster;
580 int exist_cluster;
581 int internal_as_route;
582 int confed_as_route;
04d14c8b 583 int ret = 0;
ee88563a
JM
584 int igp_metric_ret = 0;
585 int peer_sort_ret = -1;
d62a17ae 586 char new_buf[PATH_ADDPATH_STR_BUFFER];
587 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
588 uint32_t new_mm_seq;
589 uint32_t exist_mm_seq;
6d8c603a 590 int nh_cmp;
d071f237
AK
591 esi_t *exist_esi;
592 esi_t *new_esi;
593 bool same_esi;
594 bool old_proxy;
595 bool new_proxy;
33c6e933 596 bool new_origin, exist_origin;
da0c0ef7 597 struct bgp_path_info *bpi_ultimate;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
1479ed2f
DA
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
639 *
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
643 */
9a706b42
DA
644 if (bgp_attr_get_community(newattr) &&
645 community_include(bgp_attr_get_community(newattr),
646 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf, new_buf, exist_buf);
651 return 0;
652 }
653
9a706b42
DA
654 if (bgp_attr_get_community(existattr) &&
655 community_include(bgp_attr_get_community(existattr),
656 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
657 if (debug)
658 zlog_debug(
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf, new_buf, exist_buf);
661 return 1;
662 }
663
5df26422
NS
664 new_p = bgp_dest_get_prefix(new->net);
665
d62a17ae 666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
668 */
5df26422
NS
669 if ((safi == SAFI_EVPN)
670 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 671 /* This is an error condition described in RFC 7432 Section
672 * 15.2. The RFC
673 * states that in this scenario "the PE MUST alert the operator"
674 * but it
675 * does not state what other action to take. In order to provide
676 * some
677 * consistency in this scenario we are going to prefer the path
678 * with the
679 * sticky flag.
680 */
681 if (newattr->sticky != existattr->sticky) {
682 if (!debug) {
5df26422
NS
683 prefix2str(new_p, pfx_buf,
684 sizeof(*pfx_buf)
685 * PREFIX2STR_BUFFER);
18ee8310 686 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
687 new, new_buf, sizeof(new_buf));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist, exist_buf, sizeof(exist_buf));
d62a17ae 690 }
691
692 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 693 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
694 if (debug)
695 zlog_debug(
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf, new_buf, exist_buf);
d62a17ae 698 return 1;
699 }
700
701 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
703 if (debug)
704 zlog_debug(
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf, new_buf, exist_buf);
d62a17ae 707 return 0;
708 }
709 }
128ea8ab 710
d071f237
AK
711 new_esi = bgp_evpn_attr_get_esi(newattr);
712 exist_esi = bgp_evpn_attr_get_esi(existattr);
713 if (bgp_evpn_is_esi_valid(new_esi) &&
714 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715 same_esi = true;
716 } else {
717 same_esi = false;
718 }
719
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
726 */
727 if (same_esi) {
728 char esi_buf[ESI_STR_LEN];
729
730 if (bgp_evpn_is_path_local(bgp, new)) {
731 *reason = bgp_path_selection_evpn_local_path;
732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf, new_buf, exist_buf,
736 esi_to_str(new_esi, esi_buf,
737 sizeof(esi_buf)));
738 return 1;
739 }
740 if (bgp_evpn_is_path_local(bgp, exist)) {
741 *reason = bgp_path_selection_evpn_local_path;
742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf, new_buf, exist_buf,
746 esi_to_str(new_esi, esi_buf,
747 sizeof(esi_buf)));
748 return 0;
749 }
750 }
751
d62a17ae 752 new_mm_seq = mac_mobility_seqnum(newattr);
753 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 754
d62a17ae 755 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 756 *reason = bgp_path_selection_evpn_seq;
d62a17ae 757 if (debug)
758 zlog_debug(
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf, new_buf, exist_buf, new_mm_seq,
761 exist_mm_seq);
762 return 1;
763 }
8ff56318 764
d62a17ae 765 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 766 *reason = bgp_path_selection_evpn_seq;
d62a17ae 767 if (debug)
768 zlog_debug(
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf, new_buf, exist_buf, new_mm_seq,
771 exist_mm_seq);
772 return 0;
773 }
6d8c603a 774
d071f237
AK
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
777 */
778 new_proxy = bgp_evpn_attr_is_proxy(newattr);
779 old_proxy = bgp_evpn_attr_is_proxy(existattr);
780 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781 old_proxy != new_proxy) {
782 if (!new_proxy) {
783 *reason = bgp_path_selection_evpn_non_proxy;
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf, new_buf, exist_buf);
788 return 1;
789 }
790
791 *reason = bgp_path_selection_evpn_non_proxy;
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf, new_buf, exist_buf);
796 return 0;
797 }
798
6d8c603a
AK
799 /*
800 * if sequence numbers are the same path with the lowest IP
801 * wins
802 */
803 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804 if (nh_cmp < 0) {
fdf81fa0 805 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
806 if (debug)
807 zlog_debug(
23d0a753 808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 809 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 810 &new->attr->nexthop);
6d8c603a
AK
811 return 1;
812 }
813 if (nh_cmp > 0) {
fdf81fa0 814 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
815 if (debug)
816 zlog_debug(
23d0a753 817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 818 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 819 &new->attr->nexthop);
6d8c603a
AK
820 return 0;
821 }
d62a17ae 822 }
9fbdd100 823
d62a17ae 824 /* 1. Weight check. */
d62a17ae 825 new_weight = newattr->weight;
826 exist_weight = existattr->weight;
8ff56318 827
d62a17ae 828 if (new_weight > exist_weight) {
fdf81fa0 829 *reason = bgp_path_selection_weight;
d62a17ae 830 if (debug)
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf, new_buf, exist_buf, new_weight,
833 exist_weight);
834 return 1;
835 }
718e3744 836
d62a17ae 837 if (new_weight < exist_weight) {
fdf81fa0 838 *reason = bgp_path_selection_weight;
d62a17ae 839 if (debug)
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf, new_buf, exist_buf, new_weight,
842 exist_weight);
843 return 0;
844 }
9fbdd100 845
d62a17ae 846 /* 2. Local preference check. */
847 new_pref = exist_pref = bgp->default_local_pref;
848
849 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 new_pref = newattr->local_pref;
851 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852 exist_pref = existattr->local_pref;
853
854 if (new_pref > exist_pref) {
fdf81fa0 855 *reason = bgp_path_selection_local_pref;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf, new_buf, exist_buf, new_pref,
860 exist_pref);
861 return 1;
862 }
718e3744 863
d62a17ae 864 if (new_pref < exist_pref) {
fdf81fa0 865 *reason = bgp_path_selection_local_pref;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf, new_buf, exist_buf, new_pref,
870 exist_pref);
871 return 0;
872 }
9fbdd100 873
d62a17ae 874 /* 3. Local route check. We prefer:
875 * - BGP_ROUTE_STATIC
876 * - BGP_ROUTE_AGGREGATE
877 * - BGP_ROUTE_REDISTRIBUTE
878 */
33c6e933
DS
879 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
880 new->sub_type == BGP_ROUTE_IMPORTED);
881 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
882 exist->sub_type == BGP_ROUTE_IMPORTED);
883
884 if (new_origin && !exist_origin) {
fdf81fa0 885 *reason = bgp_path_selection_local_route;
d62a17ae 886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to preferred BGP_ROUTE type",
889 pfx_buf, new_buf, exist_buf);
890 return 1;
891 }
718e3744 892
33c6e933 893 if (!new_origin && exist_origin) {
fdf81fa0 894 *reason = bgp_path_selection_local_route;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s loses to %s due to preferred BGP_ROUTE type",
898 pfx_buf, new_buf, exist_buf);
899 return 0;
6811845b 900 }
718e3744 901
da0c0ef7
KM
902 /* Here if these are imported routes then get ultimate pi for
903 * path compare.
904 */
905 new = bgp_get_imported_bpi_ultimate(new);
906 exist = bgp_get_imported_bpi_ultimate(exist);
907 newattr = new->attr;
908 existattr = exist->attr;
909
d62a17ae 910 /* 4. AS path length check. */
892fedb6 911 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 912 int exist_hops = aspath_count_hops(existattr->aspath);
913 int exist_confeds = aspath_count_confeds(existattr->aspath);
914
892fedb6 915 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 916 int aspath_hops;
917
918 aspath_hops = aspath_count_hops(newattr->aspath);
919 aspath_hops += aspath_count_confeds(newattr->aspath);
920
921 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 922 *reason = bgp_path_selection_confed_as_path;
d62a17ae 923 if (debug)
924 zlog_debug(
925 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
926 pfx_buf, new_buf, exist_buf,
927 aspath_hops,
928 (exist_hops + exist_confeds));
929 return 1;
930 }
931
932 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 933 *reason = bgp_path_selection_confed_as_path;
d62a17ae 934 if (debug)
935 zlog_debug(
936 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
937 pfx_buf, new_buf, exist_buf,
938 aspath_hops,
939 (exist_hops + exist_confeds));
940 return 0;
941 }
942 } else {
943 int newhops = aspath_count_hops(newattr->aspath);
944
945 if (newhops < exist_hops) {
fdf81fa0 946 *reason = bgp_path_selection_as_path;
d62a17ae 947 if (debug)
948 zlog_debug(
949 "%s: %s wins over %s due to aspath hopcount %d < %d",
950 pfx_buf, new_buf, exist_buf,
951 newhops, exist_hops);
952 return 1;
953 }
954
955 if (newhops > exist_hops) {
fdf81fa0 956 *reason = bgp_path_selection_as_path;
d62a17ae 957 if (debug)
958 zlog_debug(
959 "%s: %s loses to %s due to aspath hopcount %d > %d",
960 pfx_buf, new_buf, exist_buf,
961 newhops, exist_hops);
962 return 0;
963 }
964 }
965 }
9fbdd100 966
d62a17ae 967 /* 5. Origin check. */
968 if (newattr->origin < existattr->origin) {
fdf81fa0 969 *reason = bgp_path_selection_origin;
d62a17ae 970 if (debug)
971 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
972 pfx_buf, new_buf, exist_buf,
973 bgp_origin_long_str[newattr->origin],
974 bgp_origin_long_str[existattr->origin]);
975 return 1;
976 }
718e3744 977
d62a17ae 978 if (newattr->origin > existattr->origin) {
fdf81fa0 979 *reason = bgp_path_selection_origin;
d62a17ae 980 if (debug)
981 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
982 pfx_buf, new_buf, exist_buf,
983 bgp_origin_long_str[newattr->origin],
984 bgp_origin_long_str[existattr->origin]);
985 return 0;
986 }
718e3744 987
d62a17ae 988 /* 6. MED check. */
989 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
990 && aspath_count_hops(existattr->aspath) == 0);
991 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
992 && aspath_count_confeds(existattr->aspath) > 0
993 && aspath_count_hops(newattr->aspath) == 0
994 && aspath_count_hops(existattr->aspath) == 0);
995
892fedb6
DA
996 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
997 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 998 || aspath_cmp_left(newattr->aspath, existattr->aspath)
999 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1000 || internal_as_route) {
1001 new_med = bgp_med_value(new->attr, bgp);
1002 exist_med = bgp_med_value(exist->attr, bgp);
1003
1004 if (new_med < exist_med) {
fdf81fa0 1005 *reason = bgp_path_selection_med;
d62a17ae 1006 if (debug)
1007 zlog_debug(
1008 "%s: %s wins over %s due to MED %d < %d",
1009 pfx_buf, new_buf, exist_buf, new_med,
1010 exist_med);
1011 return 1;
1012 }
8ff56318 1013
d62a17ae 1014 if (new_med > exist_med) {
fdf81fa0 1015 *reason = bgp_path_selection_med;
d62a17ae 1016 if (debug)
1017 zlog_debug(
1018 "%s: %s loses to %s due to MED %d > %d",
1019 pfx_buf, new_buf, exist_buf, new_med,
1020 exist_med);
1021 return 0;
1022 }
1023 }
9fbdd100 1024
d62a17ae 1025 /* 7. Peer type check. */
1026 new_sort = new->peer->sort;
1027 exist_sort = exist->peer->sort;
1028
1029 if (new_sort == BGP_PEER_EBGP
1030 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1031 *reason = bgp_path_selection_peer;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1035 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1036 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1037 return 1;
1038 peer_sort_ret = 1;
d62a17ae 1039 }
718e3744 1040
d62a17ae 1041 if (exist_sort == BGP_PEER_EBGP
1042 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1043 *reason = bgp_path_selection_peer;
d62a17ae 1044 if (debug)
1045 zlog_debug(
1046 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1047 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1048 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1049 return 0;
1050 peer_sort_ret = 0;
d62a17ae 1051 }
8ff56318 1052
d62a17ae 1053 /* 8. IGP metric check. */
1054 newm = existm = 0;
8ff56318 1055
d62a17ae 1056 if (new->extra)
1057 newm = new->extra->igpmetric;
1058 if (exist->extra)
1059 existm = exist->extra->igpmetric;
9fbdd100 1060
d62a17ae 1061 if (newm < existm) {
ee88563a 1062 if (debug && peer_sort_ret < 0)
d62a17ae 1063 zlog_debug(
d588b995 1064 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1065 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1066 igp_metric_ret = 1;
d62a17ae 1067 }
718e3744 1068
d62a17ae 1069 if (newm > existm) {
ee88563a 1070 if (debug && peer_sort_ret < 0)
d62a17ae 1071 zlog_debug(
d588b995 1072 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1073 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1074 igp_metric_ret = 0;
5e242b0d 1075 }
5e242b0d 1076
d62a17ae 1077 /* 9. Same IGP metric. Compare the cluster list length as
1078 representative of IGP hops metric. Rewrite the metric value
1079 pair (newm, existm) with the cluster list length. Prefer the
1080 path with smaller cluster list length. */
1081 if (newm == existm) {
aa53c036
DS
1082 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1083 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1084 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1085 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1086 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1087
1088 if (newm < existm) {
ee88563a 1089 if (debug && peer_sort_ret < 0)
d62a17ae 1090 zlog_debug(
d588b995 1091 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1092 pfx_buf, new_buf, exist_buf,
1093 newm, existm);
ee88563a 1094 igp_metric_ret = 1;
d62a17ae 1095 }
1096
1097 if (newm > existm) {
ee88563a 1098 if (debug && peer_sort_ret < 0)
d62a17ae 1099 zlog_debug(
d588b995 1100 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1101 pfx_buf, new_buf, exist_buf,
1102 newm, existm);
ee88563a 1103 igp_metric_ret = 0;
d62a17ae 1104 }
1105 }
1106 }
31a4638f 1107
d62a17ae 1108 /* 10. confed-external vs. confed-internal */
1109 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1110 if (new_sort == BGP_PEER_CONFED
1111 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1112 *reason = bgp_path_selection_confed;
d62a17ae 1113 if (debug)
1114 zlog_debug(
1115 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1116 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1117 if (!CHECK_FLAG(bgp->flags,
1118 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1119 return 1;
1120 peer_sort_ret = 1;
d62a17ae 1121 }
718e3744 1122
d62a17ae 1123 if (exist_sort == BGP_PEER_CONFED
1124 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1125 *reason = bgp_path_selection_confed;
d62a17ae 1126 if (debug)
1127 zlog_debug(
1128 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1129 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1130 if (!CHECK_FLAG(bgp->flags,
1131 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1132 return 0;
1133 peer_sort_ret = 0;
d62a17ae 1134 }
1135 }
718e3744 1136
d62a17ae 1137 /* 11. Maximum path check. */
1138 if (newm == existm) {
1139 /* If one path has a label but the other does not, do not treat
1140 * them as equals for multipath
1141 */
a4d82a8a 1142 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1143 != (exist->extra
b57ba6d2 1144 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1145 if (debug)
1146 zlog_debug(
1147 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1148 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1149 } else if (CHECK_FLAG(bgp->flags,
1150 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1151
1152 /*
1153 * For the two paths, all comparison steps till IGP
1154 * metric
1155 * have succeeded - including AS_PATH hop count. Since
1156 * 'bgp
1157 * bestpath as-path multipath-relax' knob is on, we
1158 * don't need
1159 * an exact match of AS_PATH. Thus, mark the paths are
1160 * equal.
1161 * That will trigger both these paths to get into the
1162 * multipath
1163 * array.
1164 */
1165 *paths_eq = 1;
1166
1167 if (debug)
1168 zlog_debug(
1169 "%s: %s and %s are equal via multipath-relax",
1170 pfx_buf, new_buf, exist_buf);
1171 } else if (new->peer->sort == BGP_PEER_IBGP) {
1172 if (aspath_cmp(new->attr->aspath,
1173 exist->attr->aspath)) {
1174 *paths_eq = 1;
1175
1176 if (debug)
1177 zlog_debug(
1178 "%s: %s and %s are equal via matching aspaths",
1179 pfx_buf, new_buf, exist_buf);
1180 }
1181 } else if (new->peer->as == exist->peer->as) {
1182 *paths_eq = 1;
1183
1184 if (debug)
1185 zlog_debug(
1186 "%s: %s and %s are equal via same remote-as",
1187 pfx_buf, new_buf, exist_buf);
1188 }
1189 } else {
1190 /*
1191 * TODO: If unequal cost ibgp multipath is enabled we can
1192 * mark the paths as equal here instead of returning
1193 */
ee88563a
JM
1194
1195 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1196 * if either step 7 or 10 (peer type checks) yielded a winner,
1197 * that result was returned immediately. Returning from step 10
1198 * ignored the return value computed in steps 8 and 9 (IGP
1199 * metric checks). In order to preserve that behavior, if
1200 * peer_sort_ret is set, return that rather than igp_metric_ret.
1201 */
1202 ret = peer_sort_ret;
1203 if (peer_sort_ret < 0) {
1204 ret = igp_metric_ret;
1205 if (debug) {
1206 if (ret == 1)
1207 zlog_debug(
1208 "%s: %s wins over %s after IGP metric comparison",
1209 pfx_buf, new_buf, exist_buf);
1210 else
1211 zlog_debug(
1212 "%s: %s loses to %s after IGP metric comparison",
1213 pfx_buf, new_buf, exist_buf);
1214 }
1215 *reason = bgp_path_selection_igp_metric;
d62a17ae 1216 }
1217 return ret;
1218 }
718e3744 1219
ee88563a
JM
1220 /*
1221 * At this point, the decision whether to set *paths_eq = 1 has been
1222 * completed. If we deferred returning because of bestpath peer-type
1223 * relax configuration, return now.
1224 */
1225 if (peer_sort_ret >= 0)
1226 return peer_sort_ret;
1227
d62a17ae 1228 /* 12. If both paths are external, prefer the path that was received
1229 first (the oldest one). This step minimizes route-flap, since a
1230 newer path won't displace an older one, even if it was the
1231 preferred route based on the additional decision criteria below. */
892fedb6 1232 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1233 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1234 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1235 *reason = bgp_path_selection_older;
d62a17ae 1236 if (debug)
1237 zlog_debug(
1238 "%s: %s wins over %s due to oldest external",
1239 pfx_buf, new_buf, exist_buf);
1240 return 1;
1241 }
9fbdd100 1242
1defdda8 1243 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1244 *reason = bgp_path_selection_older;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s loses to %s due to oldest external",
1248 pfx_buf, new_buf, exist_buf);
1249 return 0;
1250 }
1251 }
718e3744 1252
ce5002c6 1253 /* 13. Router-ID comparison. */
d62a17ae 1254 /* If one of the paths is "stale", the corresponding peer router-id will
1255 * be 0 and would always win over the other path. If originator id is
ce5002c6 1256 * used for the comparison, it will decide which path is better.
d62a17ae 1257 */
1258 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1259 new_id.s_addr = newattr->originator_id.s_addr;
1260 else
1261 new_id.s_addr = new->peer->remote_id.s_addr;
1262 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1263 exist_id.s_addr = existattr->originator_id.s_addr;
1264 else
1265 exist_id.s_addr = exist->peer->remote_id.s_addr;
1266
1267 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1268 *reason = bgp_path_selection_router_id;
d62a17ae 1269 if (debug)
1270 zlog_debug(
1271 "%s: %s wins over %s due to Router-ID comparison",
1272 pfx_buf, new_buf, exist_buf);
1273 return 1;
1274 }
718e3744 1275
d62a17ae 1276 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1277 *reason = bgp_path_selection_router_id;
d62a17ae 1278 if (debug)
1279 zlog_debug(
1280 "%s: %s loses to %s due to Router-ID comparison",
1281 pfx_buf, new_buf, exist_buf);
1282 return 0;
1283 }
9fbdd100 1284
ce5002c6 1285 /* 14. Cluster length comparison. */
d62a17ae 1286 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1287 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1288
1289 if (new_cluster < exist_cluster) {
fdf81fa0 1290 *reason = bgp_path_selection_cluster_length;
d62a17ae 1291 if (debug)
1292 zlog_debug(
1293 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1294 pfx_buf, new_buf, exist_buf, new_cluster,
1295 exist_cluster);
1296 return 1;
1297 }
718e3744 1298
d62a17ae 1299 if (new_cluster > exist_cluster) {
fdf81fa0 1300 *reason = bgp_path_selection_cluster_length;
d62a17ae 1301 if (debug)
1302 zlog_debug(
1303 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1304 pfx_buf, new_buf, exist_buf, new_cluster,
1305 exist_cluster);
1306 return 0;
1307 }
9fbdd100 1308
ce5002c6 1309 /* 15. Neighbor address comparison. */
d62a17ae 1310 /* Do this only if neither path is "stale" as stale paths do not have
1311 * valid peer information (as the connection may or may not be up).
1312 */
1defdda8 1313 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1314 *reason = bgp_path_selection_stale;
d62a17ae 1315 if (debug)
1316 zlog_debug(
1317 "%s: %s wins over %s due to latter path being STALE",
1318 pfx_buf, new_buf, exist_buf);
1319 return 1;
1320 }
0de5153c 1321
1defdda8 1322 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1323 *reason = bgp_path_selection_stale;
d62a17ae 1324 if (debug)
1325 zlog_debug(
1326 "%s: %s loses to %s due to former path being STALE",
1327 pfx_buf, new_buf, exist_buf);
1328 return 0;
1329 }
718e3744 1330
d62a17ae 1331 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1332 if (new->peer->su_remote == NULL) {
1333 *reason = bgp_path_selection_local_configured;
d62a17ae 1334 return 0;
fdf81fa0
DS
1335 }
1336 if (exist->peer->su_remote == NULL) {
1337 *reason = bgp_path_selection_local_configured;
d62a17ae 1338 return 1;
fdf81fa0 1339 }
9fbdd100 1340
d62a17ae 1341 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1342
1343 if (ret == 1) {
fdf81fa0 1344 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1345 if (debug)
1346 zlog_debug(
1347 "%s: %s loses to %s due to Neighor IP comparison",
1348 pfx_buf, new_buf, exist_buf);
1349 return 0;
1350 }
1351
1352 if (ret == -1) {
fdf81fa0 1353 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1354 if (debug)
1355 zlog_debug(
1356 "%s: %s wins over %s due to Neighor IP comparison",
1357 pfx_buf, new_buf, exist_buf);
1358 return 1;
1359 }
9fbdd100 1360
fdf81fa0 1361 *reason = bgp_path_selection_default;
d62a17ae 1362 if (debug)
1363 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1364 pfx_buf, new_buf, exist_buf);
718e3744 1365
d62a17ae 1366 return 1;
718e3744 1367}
1368
d071f237
AK
1369
1370int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1371 struct bgp_path_info *exist, int *paths_eq)
1372{
1373 enum bgp_path_selection_reason reason;
1374 char pfx_buf[PREFIX2STR_BUFFER];
1375
1376 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1377 AFI_L2VPN, SAFI_EVPN, &reason);
1378}
1379
65efcfce
LB
1380/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1381 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1382 * multipath is enabled
65efcfce 1383 * This version is compatible with */
18ee8310
DS
1384int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1385 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1386 afi_t afi, safi_t safi,
1387 enum bgp_path_selection_reason *reason)
d62a17ae 1388{
1389 int paths_eq;
1390 int ret;
18ee8310 1391 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1392 afi, safi, reason);
d62a17ae 1393
1394 if (paths_eq)
1395 ret = 0;
1396 else {
1397 if (ret == 1)
1398 ret = -1;
1399 else
1400 ret = 1;
1401 }
1402 return ret;
65efcfce
LB
1403}
1404
5a1ae2c2
DS
1405static enum filter_type bgp_input_filter(struct peer *peer,
1406 const struct prefix *p,
d62a17ae 1407 struct attr *attr, afi_t afi,
1408 safi_t safi)
718e3744 1409{
d62a17ae 1410 struct bgp_filter *filter;
6401252f 1411 enum filter_type ret = FILTER_PERMIT;
718e3744 1412
d62a17ae 1413 filter = &peer->filter[afi][safi];
718e3744 1414
d62a17ae 1415#define FILTER_EXIST_WARN(F, f, filter) \
1416 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1417 zlog_debug("%s: Could not find configured input %s-list %s!", \
1418 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1419
1420 if (DISTRIBUTE_IN_NAME(filter)) {
1421 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1422
6401252f
QY
1423 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1424 == FILTER_DENY) {
1425 ret = FILTER_DENY;
1426 goto done;
1427 }
d62a17ae 1428 }
1429
1430 if (PREFIX_LIST_IN_NAME(filter)) {
1431 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1432
6401252f
QY
1433 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1434 == PREFIX_DENY) {
1435 ret = FILTER_DENY;
1436 goto done;
1437 }
d62a17ae 1438 }
1439
1440 if (FILTER_LIST_IN_NAME(filter)) {
1441 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1442
1443 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1444 == AS_FILTER_DENY) {
1445 ret = FILTER_DENY;
1446 goto done;
1447 }
d62a17ae 1448 }
1449
6401252f 1450done:
c7bb4f00 1451 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1452 char pfxprint[PREFIX2STR_BUFFER];
1453
1454 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1455 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1456 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1457 }
1458
1459 return ret;
650f76c2 1460#undef FILTER_EXIST_WARN
718e3744 1461}
1462
b8685f9b
DS
1463static enum filter_type bgp_output_filter(struct peer *peer,
1464 const struct prefix *p,
d62a17ae 1465 struct attr *attr, afi_t afi,
1466 safi_t safi)
718e3744 1467{
d62a17ae 1468 struct bgp_filter *filter;
6401252f 1469 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1470
1471 filter = &peer->filter[afi][safi];
1472
1473#define FILTER_EXIST_WARN(F, f, filter) \
1474 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1475 zlog_debug("%s: Could not find configured output %s-list %s!", \
1476 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1477
d62a17ae 1478 if (DISTRIBUTE_OUT_NAME(filter)) {
1479 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1480
6401252f
QY
1481 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1482 == FILTER_DENY) {
1483 ret = FILTER_DENY;
1484 goto done;
1485 }
d62a17ae 1486 }
1487
1488 if (PREFIX_LIST_OUT_NAME(filter)) {
1489 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1490
d62a17ae 1491 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1492 == PREFIX_DENY) {
1493 ret = FILTER_DENY;
1494 goto done;
1495 }
d62a17ae 1496 }
718e3744 1497
d62a17ae 1498 if (FILTER_LIST_OUT_NAME(filter)) {
1499 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1500
d62a17ae 1501 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1502 == AS_FILTER_DENY) {
1503 ret = FILTER_DENY;
1504 goto done;
1505 }
1506 }
1507
c7bb4f00 1508 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1509 char pfxprint[PREFIX2STR_BUFFER];
1510
1511 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1512 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1513 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1514 }
718e3744 1515
6401252f
QY
1516done:
1517 return ret;
650f76c2 1518#undef FILTER_EXIST_WARN
718e3744 1519}
1520
1521/* If community attribute includes no_export then return 1. */
3dc339cd 1522static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1523{
9a706b42 1524 if (bgp_attr_get_community(attr)) {
d62a17ae 1525 /* NO_ADVERTISE check. */
9a706b42
DA
1526 if (community_include(bgp_attr_get_community(attr),
1527 COMMUNITY_NO_ADVERTISE))
3dc339cd 1528 return true;
d62a17ae 1529
1530 /* NO_EXPORT check. */
9a706b42
DA
1531 if (peer->sort == BGP_PEER_EBGP &&
1532 community_include(bgp_attr_get_community(attr),
1533 COMMUNITY_NO_EXPORT))
3dc339cd 1534 return true;
d62a17ae 1535
1536 /* NO_EXPORT_SUBCONFED check. */
1537 if (peer->sort == BGP_PEER_EBGP
1538 || peer->sort == BGP_PEER_CONFED)
9a706b42 1539 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1540 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1541 return true;
d62a17ae 1542 }
3dc339cd 1543 return false;
718e3744 1544}
1545
1546/* Route reflection loop check. */
3dc339cd 1547static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1548{
d62a17ae 1549 struct in_addr cluster_id;
779fee93 1550 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1551
779fee93 1552 if (cluster) {
d62a17ae 1553 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1554 cluster_id = peer->bgp->cluster_id;
1555 else
1556 cluster_id = peer->bgp->router_id;
1557
779fee93 1558 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1559 return true;
d62a17ae 1560 }
3dc339cd 1561 return false;
718e3744 1562}
6b0655a2 1563
d864dd9e
EB
1564static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1565{
1566 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1567 if (peer->local_role == ROLE_PROVIDER ||
1568 peer->local_role == ROLE_RS_SERVER)
1569 return true;
1570 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1571 return true;
1572 return false;
1573 }
1574 if (peer->local_role == ROLE_CUSTOMER ||
1575 peer->local_role == ROLE_PEER ||
1576 peer->local_role == ROLE_RS_CLIENT) {
1577 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1578 attr->otc = peer->as;
1579 }
1580 return false;
1581}
1582
1583static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1584{
1585 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1586 if (peer->local_role == ROLE_CUSTOMER ||
1587 peer->local_role == ROLE_RS_CLIENT ||
1588 peer->local_role == ROLE_PEER)
1589 return true;
1590 return false;
1591 }
1592 if (peer->local_role == ROLE_PROVIDER ||
1593 peer->local_role == ROLE_PEER ||
1594 peer->local_role == ROLE_RS_SERVER) {
1595 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1596 attr->otc = peer->bgp->as;
1597 }
1598 return false;
1599}
1600
5a78f2bc
EB
1601static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1602{
1603 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1604}
1605
5a1ae2c2 1606static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1607 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1608 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1609 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1610{
d62a17ae 1611 struct bgp_filter *filter;
82b692c0
LK
1612 struct bgp_path_info rmap_path = { 0 };
1613 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1614 route_map_result_t ret;
1615 struct route_map *rmap = NULL;
718e3744 1616
d62a17ae 1617 filter = &peer->filter[afi][safi];
718e3744 1618
d62a17ae 1619 /* Apply default weight value. */
1620 if (peer->weight[afi][safi])
1621 attr->weight = peer->weight[afi][safi];
718e3744 1622
d62a17ae 1623 if (rmap_name) {
1624 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1625
d62a17ae 1626 if (rmap == NULL)
1627 return RMAP_DENY;
1628 } else {
1629 if (ROUTE_MAP_IN_NAME(filter)) {
1630 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1631
d62a17ae 1632 if (rmap == NULL)
1633 return RMAP_DENY;
1634 }
1635 }
0b16f239 1636
d62a17ae 1637 /* Route map apply. */
1638 if (rmap) {
6006b807 1639 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1640 /* Duplicate current value to new structure for modification. */
40381db7
DS
1641 rmap_path.peer = peer;
1642 rmap_path.attr = attr;
82b692c0 1643 rmap_path.extra = &extra;
9bcb3eef 1644 rmap_path.net = dest;
196c6b09 1645
82b692c0
LK
1646 extra.num_labels = num_labels;
1647 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1648 memcpy(extra.label, label,
1649 num_labels * sizeof(mpls_label_t));
718e3744 1650
d62a17ae 1651 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1652
d62a17ae 1653 /* Apply BGP route map to the attribute. */
1782514f 1654 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1655
d62a17ae 1656 peer->rmap_type = 0;
0b16f239 1657
1f2263be 1658 if (ret == RMAP_DENYMATCH)
d62a17ae 1659 return RMAP_DENY;
0b16f239 1660 }
d62a17ae 1661 return RMAP_PERMIT;
0b16f239
DS
1662}
1663
5f040085 1664static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1665 struct attr *attr, afi_t afi, safi_t safi,
1666 const char *rmap_name)
0b16f239 1667{
40381db7 1668 struct bgp_path_info rmap_path;
d62a17ae 1669 route_map_result_t ret;
1670 struct route_map *rmap = NULL;
d7c0a89a 1671 uint8_t rmap_type;
0b16f239 1672
b787157a
DS
1673 /*
1674 * So if we get to this point and have no rmap_name
1675 * we want to just show the output as it currently
1676 * exists.
1677 */
1678 if (!rmap_name)
1679 return RMAP_PERMIT;
0b16f239 1680
d62a17ae 1681 /* Apply default weight value. */
1682 if (peer->weight[afi][safi])
1683 attr->weight = peer->weight[afi][safi];
0b16f239 1684
b787157a 1685 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1686
b787157a
DS
1687 /*
1688 * If we have a route map name and we do not find
1689 * the routemap that means we have an implicit
1690 * deny.
1691 */
1692 if (rmap == NULL)
1693 return RMAP_DENY;
0b16f239 1694
6006b807 1695 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1696 /* Route map apply. */
544be979 1697 /* Duplicate current value to new structure for modification. */
40381db7
DS
1698 rmap_path.peer = peer;
1699 rmap_path.attr = attr;
0b16f239 1700
0f672529 1701 rmap_type = peer->rmap_type;
b787157a 1702 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1703
b787157a 1704 /* Apply BGP route map to the attribute. */
1782514f 1705 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1706
0f672529 1707 peer->rmap_type = rmap_type;
b787157a
DS
1708
1709 if (ret == RMAP_DENYMATCH)
1710 /*
1711 * caller has multiple error paths with bgp_attr_flush()
1712 */
1713 return RMAP_DENY;
ac41b2a2 1714
d62a17ae 1715 return RMAP_PERMIT;
718e3744 1716}
6b0655a2 1717
5000f21c 1718/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1719static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1720 struct peer *peer, struct attr *attr)
1721{
1722 if (peer->sort == BGP_PEER_EBGP
1723 && (peer_af_flag_check(peer, afi, safi,
1724 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1725 || peer_af_flag_check(peer, afi, safi,
1726 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1727 || peer_af_flag_check(peer, afi, safi,
1728 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1729 || peer_af_flag_check(peer, afi, safi,
1730 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1731 // Take action on the entire aspath
1732 if (peer_af_flag_check(peer, afi, safi,
1733 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1734 || peer_af_flag_check(peer, afi, safi,
1735 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1736 if (peer_af_flag_check(
1737 peer, afi, safi,
1738 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1739 attr->aspath = aspath_replace_private_asns(
bf26b80e 1740 attr->aspath, bgp->as, peer->as);
d62a17ae 1741
179d5a0e
TA
1742 /*
1743 * Even if the aspath consists of just private ASNs we
1744 * need to walk the AS-Path to maintain all instances
1745 * of the peer's ASN to break possible loops.
1746 */
d62a17ae 1747 else
1748 attr->aspath = aspath_remove_private_asns(
bf26b80e 1749 attr->aspath, peer->as);
d62a17ae 1750 }
1751
1752 // 'all' was not specified so the entire aspath must be private
1753 // ASNs
1754 // for us to do anything
1755 else if (aspath_private_as_check(attr->aspath)) {
1756 if (peer_af_flag_check(
1757 peer, afi, safi,
1758 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1759 attr->aspath = aspath_replace_private_asns(
bf26b80e 1760 attr->aspath, bgp->as, peer->as);
d62a17ae 1761 else
179d5a0e
TA
1762 /*
1763 * Walk the aspath to retain any instances of
1764 * the peer_asn
1765 */
1766 attr->aspath = aspath_remove_private_asns(
1767 attr->aspath, peer->as);
d62a17ae 1768 }
1769 }
5000f21c
DS
1770}
1771
c7122e14 1772/* If this is an EBGP peer with as-override */
d62a17ae 1773static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1774 struct peer *peer, struct attr *attr)
1775{
1776 if (peer->sort == BGP_PEER_EBGP
1777 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1778 if (aspath_single_asn_check(attr->aspath, peer->as))
1779 attr->aspath = aspath_replace_specific_asn(
1780 attr->aspath, peer->as, bgp->as);
1781 }
1782}
1783
1479ed2f
DA
1784void bgp_attr_add_llgr_community(struct attr *attr)
1785{
1786 struct community *old;
1787 struct community *new;
1788 struct community *merge;
1789 struct community *llgr;
1790
9a706b42 1791 old = bgp_attr_get_community(attr);
1479ed2f
DA
1792 llgr = community_str2com("llgr-stale");
1793
1794 assert(llgr);
1795
1796 if (old) {
1797 merge = community_merge(community_dup(old), llgr);
1798
1799 if (old->refcnt == 0)
1800 community_free(&old);
1801
1802 new = community_uniq_sort(merge);
1803 community_free(&merge);
1804 } else {
1805 new = community_dup(llgr);
1806 }
1807
1808 community_free(&llgr);
1809
9a706b42 1810 bgp_attr_set_community(attr, new);
1479ed2f
DA
1811}
1812
7f323236
DW
1813void bgp_attr_add_gshut_community(struct attr *attr)
1814{
1815 struct community *old;
1816 struct community *new;
1817 struct community *merge;
1818 struct community *gshut;
1819
9a706b42 1820 old = bgp_attr_get_community(attr);
7f323236
DW
1821 gshut = community_str2com("graceful-shutdown");
1822
990f4f91 1823 assert(gshut);
1824
7f323236
DW
1825 if (old) {
1826 merge = community_merge(community_dup(old), gshut);
1827
a4d82a8a 1828 if (old->refcnt == 0)
3c1f53de 1829 community_free(&old);
7f323236
DW
1830
1831 new = community_uniq_sort(merge);
3c1f53de 1832 community_free(&merge);
7f323236
DW
1833 } else {
1834 new = community_dup(gshut);
1835 }
1836
3c1f53de 1837 community_free(&gshut);
9a706b42 1838 bgp_attr_set_community(attr, new);
7f323236
DW
1839
1840 /* When we add the graceful-shutdown community we must also
1841 * lower the local-preference */
1842 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1843 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1844}
1845
1846
e73c112e
MK
1847/* Notify BGP Conditional advertisement scanner process. */
1848void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1849{
e73c112e 1850 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1851 afi_t afi = SUBGRP_AFI(subgrp);
1852 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1853 struct bgp_filter *filter = &peer->filter[afi][safi];
1854
1855 if (!ADVERTISE_MAP_NAME(filter))
1856 return;
1857
52979c3b
DS
1858 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1859 return;
e73c112e 1860
52979c3b 1861 peer->advmap_table_change = true;
e73c112e
MK
1862}
1863
1864
f2ee6d5c 1865void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1866{
960035b2 1867 if (family == AF_INET) {
975a328e
DA
1868 attr->nexthop.s_addr = INADDR_ANY;
1869 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1870 }
d62a17ae 1871 if (family == AF_INET6)
1872 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1873 if (family == AF_EVPN)
1874 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1875}
1876
9bcb3eef 1877bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1878 struct update_subgroup *subgrp,
7f7940e6 1879 const struct prefix *p, struct attr *attr,
51c3a7de 1880 struct attr *post_attr)
d62a17ae 1881{
1882 struct bgp_filter *filter;
1883 struct peer *from;
1884 struct peer *peer;
1885 struct peer *onlypeer;
1886 struct bgp *bgp;
40381db7 1887 struct attr *piattr;
b68885f9 1888 route_map_result_t ret;
d62a17ae 1889 int transparent;
1890 int reflect;
1891 afi_t afi;
1892 safi_t safi;
1893 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1894 bool nh_reset = false;
1895 uint64_t cum_bw;
d62a17ae 1896
1897 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1898 return false;
d62a17ae 1899
1900 afi = SUBGRP_AFI(subgrp);
1901 safi = SUBGRP_SAFI(subgrp);
1902 peer = SUBGRP_PEER(subgrp);
1903 onlypeer = NULL;
1904 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1905 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1906
40381db7 1907 from = pi->peer;
d62a17ae 1908 filter = &peer->filter[afi][safi];
1909 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1910 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1911 : pi->attr;
3f9c7369 1912
d0bf49ec
LS
1913 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1914 peer->pmax_out[afi][safi] != 0 &&
1915 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1916 if (BGP_DEBUG(update, UPDATE_OUT) ||
1917 BGP_DEBUG(update, UPDATE_PREFIX)) {
1918 zlog_debug("%s reached maximum prefix to be send (%u)",
1919 peer->host, peer->pmax_out[afi][safi]);
1920 }
1921 return false;
1922 }
1923
49e5a4a0 1924#ifdef ENABLE_BGP_VNC
d62a17ae 1925 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1926 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1927 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1928
1929 /*
1930 * direct and direct_ext type routes originate internally even
1931 * though they can have peer pointers that reference other
1932 * systems
1933 */
8228a9a7
DS
1934 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1935 __func__, p);
d62a17ae 1936 samepeer_safe = 1;
1937 }
65efcfce
LB
1938#endif
1939
ddb5b488
PZ
1940 if (((afi == AFI_IP) || (afi == AFI_IP6))
1941 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1942 && (pi->type == ZEBRA_ROUTE_BGP)
1943 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1944
1945 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1946
1947 samepeer_safe = 1;
1948 }
1949
d62a17ae 1950 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1951 * pi is valid */
1952 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1953 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1954 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1955 return false;
d62a17ae 1956 }
adbac85e 1957
d62a17ae 1958 /* If this is not the bestpath then check to see if there is an enabled
1959 * addpath
1960 * feature that requires us to advertise it */
40381db7 1961 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1962 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1963 return false;
d62a17ae 1964 }
1965 }
06370dac 1966
d62a17ae 1967 /* Aggregate-address suppress check. */
4056a5f6
RZ
1968 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1969 return false;
3f9c7369 1970
13b7e7f0
DS
1971 /*
1972 * If we are doing VRF 2 VRF leaking via the import
1973 * statement, we want to prevent the route going
1974 * off box as that the RT and RD created are localy
1975 * significant and globaly useless.
1976 */
40381db7
DS
1977 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1978 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1979 return false;
13b7e7f0 1980
d62a17ae 1981 /* If it's labeled safi, make sure the route has a valid label. */
1982 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1983 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1984 if (!bgp_is_valid_label(&label)) {
1985 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1986 zlog_debug("u%" PRIu64 ":s%" PRIu64
1987 " %pFX is filtered - no label (%p)",
d62a17ae 1988 subgrp->update_group->id, subgrp->id,
8228a9a7 1989 p, &label);
3dc339cd 1990 return false;
d62a17ae 1991 }
1992 }
cd1964ff 1993
d62a17ae 1994 /* Do not send back route to sender. */
1995 if (onlypeer && from == onlypeer) {
3dc339cd 1996 return false;
d62a17ae 1997 }
3f9c7369 1998
d62a17ae 1999 /* Do not send the default route in the BGP table if the neighbor is
2000 * configured for default-originate */
2001 if (CHECK_FLAG(peer->af_flags[afi][safi],
2002 PEER_FLAG_DEFAULT_ORIGINATE)) {
2003 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2004 return false;
d62a17ae 2005 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2006 return false;
d62a17ae 2007 }
4125bb67 2008
d62a17ae 2009 /* Transparency check. */
2010 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2011 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2012 transparent = 1;
2013 else
2014 transparent = 0;
2015
2016 /* If community is not disabled check the no-export and local. */
40381db7 2017 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2018 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2019 zlog_debug("%s: community filter check fail for %pFX",
2020 __func__, p);
3dc339cd 2021 return false;
d62a17ae 2022 }
3f9c7369 2023
d62a17ae 2024 /* If the attribute has originator-id and it is same as remote
2025 peer's id. */
40381db7
DS
2026 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2027 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2028 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2029 zlog_debug(
8228a9a7
DS
2030 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
2031 onlypeer->host, p);
3dc339cd 2032 return false;
d62a17ae 2033 }
3f9c7369 2034
d62a17ae 2035 /* ORF prefix-list filter check */
2036 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2037 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2038 || CHECK_FLAG(peer->af_cap[afi][safi],
2039 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2040 if (peer->orf_plist[afi][safi]) {
2041 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2042 == PREFIX_DENY) {
2043 if (bgp_debug_update(NULL, p,
2044 subgrp->update_group, 0))
2045 zlog_debug(
8228a9a7
DS
2046 "%s [Update:SEND] %pFX is filtered via ORF",
2047 peer->host, p);
3dc339cd 2048 return false;
d62a17ae 2049 }
2050 }
2051
2052 /* Output filter check. */
40381db7 2053 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2054 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2055 zlog_debug("%s [Update:SEND] %pFX is filtered",
2056 peer->host, p);
3dc339cd 2057 return false;
d62a17ae 2058 }
3f9c7369 2059
d62a17ae 2060 /* AS path loop check. */
2b31007c
RZ
2061 if (onlypeer && onlypeer->as_path_loop_detection
2062 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2063 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2064 zlog_debug(
3efd0893 2065 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2066 onlypeer->host, onlypeer->as);
3dc339cd 2067 return false;
d62a17ae 2068 }
3f9c7369 2069
d62a17ae 2070 /* If we're a CONFED we need to loop check the CONFED ID too */
2071 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2072 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2073 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2074 zlog_debug(
3efd0893 2075 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2076 peer->host, bgp->confed_id);
3dc339cd 2077 return false;
d62a17ae 2078 }
3f9c7369 2079 }
3f9c7369 2080
d62a17ae 2081 /* Route-Reflect check. */
2082 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2083 reflect = 1;
2084 else
2085 reflect = 0;
2086
2087 /* IBGP reflection check. */
2088 if (reflect && !samepeer_safe) {
2089 /* A route from a Client peer. */
2090 if (CHECK_FLAG(from->af_flags[afi][safi],
2091 PEER_FLAG_REFLECTOR_CLIENT)) {
2092 /* Reflect to all the Non-Client peers and also to the
2093 Client peers other than the originator. Originator
2094 check
2095 is already done. So there is noting to do. */
2096 /* no bgp client-to-client reflection check. */
892fedb6
DA
2097 if (CHECK_FLAG(bgp->flags,
2098 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2099 if (CHECK_FLAG(peer->af_flags[afi][safi],
2100 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2101 return false;
d62a17ae 2102 } else {
2103 /* A route from a Non-client peer. Reflect to all other
2104 clients. */
2105 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2106 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2107 return false;
d62a17ae 2108 }
2109 }
3f9c7369 2110
51c3a7de
DA
2111 /* For modify attribute, copy it to temporary structure.
2112 * post_attr comes from BGP conditional advertisements, where
2113 * attributes are already processed by advertise-map route-map,
2114 * and this needs to be saved instead of overwriting from the
2115 * path attributes.
2116 */
2117 if (post_attr)
2118 *attr = *post_attr;
2119 else
2120 *attr = *piattr;
d62a17ae 2121
2122 /* If local-preference is not set. */
2123 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2124 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2125 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2126 attr->local_pref = bgp->default_local_pref;
3f9c7369 2127 }
3f9c7369 2128
d62a17ae 2129 /* If originator-id is not set and the route is to be reflected,
2130 set the originator id */
2131 if (reflect
2132 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2133 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2134 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2135 }
3f9c7369 2136
d62a17ae 2137 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2138 */
2139 if (peer->sort == BGP_PEER_EBGP
2140 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2141 if (from != bgp->peer_self && !transparent
2142 && !CHECK_FLAG(peer->af_flags[afi][safi],
2143 PEER_FLAG_MED_UNCHANGED))
2144 attr->flag &=
2145 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2146 }
3f9c7369 2147
d62a17ae 2148 /* Since the nexthop attribute can vary per peer, it is not explicitly
2149 * set
2150 * in announce check, only certain flags and length (or number of
2151 * nexthops
2152 * -- for IPv6/MP_REACH) are set here in order to guide the update
2153 * formation
2154 * code in setting the nexthop(s) on a per peer basis in
2155 * reformat_peer().
2156 * Typically, the source nexthop in the attribute is preserved but in
2157 * the
2158 * scenarios where we know it will always be overwritten, we reset the
2159 * nexthop to "0" in an attempt to achieve better Update packing. An
2160 * example of this is when a prefix from each of 2 IBGP peers needs to
2161 * be
2162 * announced to an EBGP peer (and they have the same attributes barring
2163 * their nexthop).
2164 */
2165 if (reflect)
2166 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2167
2168#define NEXTHOP_IS_V6 \
2169 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2170 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2171 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2172 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2173
2174 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2175 * if
2176 * the peer (group) is configured to receive link-local nexthop
2177 * unchanged
c728d027
DA
2178 * and it is available in the prefix OR we're not reflecting the route,
2179 * link-local nexthop address is valid and
d62a17ae 2180 * the peer (group) to whom we're going to announce is on a shared
2181 * network
2182 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2183 * By checking if nexthop LL address is valid we are sure that
2184 * we do not announce LL address as `::`.
d62a17ae 2185 */
2186 if (NEXTHOP_IS_V6) {
2187 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2188 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2189 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2190 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2191 || (!reflect && !transparent
c728d027
DA
2192 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2193 && peer->shared_network
d62a17ae 2194 && (from == bgp->peer_self
2195 || peer->sort == BGP_PEER_EBGP))) {
2196 attr->mp_nexthop_len =
2197 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2198 }
3f9c7369 2199
d62a17ae 2200 /* Clear off link-local nexthop in source, whenever it is not
2201 * needed to
2202 * ensure more prefixes share the same attribute for
2203 * announcement.
2204 */
2205 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2206 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2207 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2208 }
3f9c7369 2209
5a78f2bc
EB
2210 if (bgp_check_role_applicability(afi, safi) &&
2211 bgp_otc_egress(peer, attr))
d864dd9e
EB
2212 return false;
2213
d62a17ae 2214 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2215 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2216
2217 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2218 if (!post_attr &&
2219 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2220 struct bgp_path_info rmap_path = {0};
2221 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2222 struct attr dummy_attr = {0};
d62a17ae 2223
e34291b8 2224 /* Fill temp path_info */
9bcb3eef
DS
2225 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2226 pi, peer, attr);
16f7ce2b 2227
d62a17ae 2228 /* don't confuse inbound and outbound setting */
2229 RESET_FLAG(attr->rmap_change_flags);
2230
2231 /*
2232 * The route reflector is not allowed to modify the attributes
2233 * of the reflected IBGP routes unless explicitly allowed.
2234 */
2235 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2236 && !CHECK_FLAG(bgp->flags,
2237 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2238 dummy_attr = *attr;
40381db7 2239 rmap_path.attr = &dummy_attr;
d62a17ae 2240 }
3f9c7369 2241
d62a17ae 2242 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2243
4056a5f6 2244 if (bgp_path_suppressed(pi))
d62a17ae 2245 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2246 &rmap_path);
d62a17ae 2247 else
2248 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2249 &rmap_path);
d62a17ae 2250
7e7639f5 2251 bgp_attr_flush(&dummy_attr);
d62a17ae 2252 peer->rmap_type = 0;
2253
2254 if (ret == RMAP_DENYMATCH) {
778048bf 2255 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2256 zlog_debug(
02494580
DA
2257 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2258 peer->host, p,
2259 ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2260 bgp_attr_flush(rmap_path.attr);
3dc339cd 2261 return false;
d62a17ae 2262 }
3f9c7369 2263 }
3f9c7369 2264
9dac9fc8
DA
2265 /* RFC 8212 to prevent route leaks.
2266 * This specification intends to improve this situation by requiring the
2267 * explicit configuration of both BGP Import and Export Policies for any
2268 * External BGP (EBGP) session such as customers, peers, or
2269 * confederation boundaries for all enabled address families. Through
2270 * codification of the aforementioned requirement, operators will
2271 * benefit from consistent behavior across different BGP
2272 * implementations.
2273 */
1d3fdccf 2274 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2275 if (!bgp_outbound_policy_exists(peer, filter)) {
2276 if (monotime_since(&bgp->ebgprequirespolicywarning,
2277 NULL) > FIFTEENMINUTE2USEC ||
2278 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2279 zlog_warn(
2280 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2281 monotime(&bgp->ebgprequirespolicywarning);
2282 }
3dc339cd 2283 return false;
b17826b7 2284 }
9dac9fc8 2285
fb29348a
DA
2286 /* draft-ietf-idr-deprecate-as-set-confed-set
2287 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2288 * Eventually, This document (if approved) updates RFC 4271
2289 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2290 * and obsoletes RFC 6472.
2291 */
7f972cd8 2292 if (peer->bgp->reject_as_sets)
fb29348a 2293 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2294 return false;
fb29348a 2295
33d022bc
DA
2296 /* Codification of AS 0 Processing */
2297 if (aspath_check_as_zero(attr->aspath))
e2369003 2298 return false;
33d022bc 2299
637e5ba4 2300 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2301 if (peer->sort == BGP_PEER_IBGP
2302 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2303 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2304 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2305 } else {
2306 bgp_attr_add_gshut_community(attr);
2307 }
2308 }
2309
1479ed2f
DA
2310 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2311 * Capability" to a neighbor MUST perform the following upon receiving
2312 * a route from that neighbor with the "LLGR_STALE" community, or upon
2313 * attaching the "LLGR_STALE" community itself per Section 4.2:
2314 *
2315 * The route SHOULD NOT be advertised to any neighbor from which the
2316 * Long-lived Graceful Restart Capability has not been received.
2317 */
9a706b42
DA
2318 if (bgp_attr_get_community(attr) &&
2319 community_include(bgp_attr_get_community(attr),
2320 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2321 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2322 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2323 return false;
2324
d62a17ae 2325 /* After route-map has been applied, we check to see if the nexthop to
2326 * be carried in the attribute (that is used for the announcement) can
2327 * be cleared off or not. We do this in all cases where we would be
2328 * setting the nexthop to "ourselves". For IPv6, we only need to
2329 * consider
2330 * the global nexthop here; the link-local nexthop would have been
2331 * cleared
2332 * already, and if not, it is required by the update formation code.
2333 * Also see earlier comments in this function.
2334 */
2335 /*
2336 * If route-map has performed some operation on the nexthop or the peer
2337 * configuration says to pass it unchanged, we cannot reset the nexthop
2338 * here, so only attempt to do it if these aren't true. Note that the
2339 * route-map handler itself might have cleared the nexthop, if for
2340 * example,
2341 * it is configured as 'peer-address'.
2342 */
2343 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2344 piattr->rmap_change_flags)
d62a17ae 2345 && !transparent
2346 && !CHECK_FLAG(peer->af_flags[afi][safi],
2347 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2348 /* We can reset the nexthop, if setting (or forcing) it to
2349 * 'self' */
2350 if (CHECK_FLAG(peer->af_flags[afi][safi],
2351 PEER_FLAG_NEXTHOP_SELF)
2352 || CHECK_FLAG(peer->af_flags[afi][safi],
2353 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2354 if (!reflect
2355 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2356 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2357 subgroup_announce_reset_nhop(
2358 (peer_cap_enhe(peer, afi, safi)
2359 ? AF_INET6
2360 : p->family),
2361 attr);
7b651a32 2362 nh_reset = true;
2363 }
d62a17ae 2364 } else if (peer->sort == BGP_PEER_EBGP) {
2365 /* Can also reset the nexthop if announcing to EBGP, but
2366 * only if
2367 * no peer in the subgroup is on a shared subnet.
2368 * Note: 3rd party nexthop currently implemented for
2369 * IPv4 only.
2370 */
737af885
BS
2371 if ((p->family == AF_INET) &&
2372 (!bgp_subgrp_multiaccess_check_v4(
2373 piattr->nexthop,
7b651a32 2374 subgrp, from))) {
d62a17ae 2375 subgroup_announce_reset_nhop(
2376 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2377 ? AF_INET6
2378 : p->family),
737af885 2379 attr);
7b651a32 2380 nh_reset = true;
2381 }
737af885
BS
2382
2383 if ((p->family == AF_INET6) &&
2384 (!bgp_subgrp_multiaccess_check_v6(
2385 piattr->mp_nexthop_global,
7b651a32 2386 subgrp, from))) {
737af885
BS
2387 subgroup_announce_reset_nhop(
2388 (peer_cap_enhe(peer, afi, safi)
2389 ? AF_INET6
2390 : p->family),
2391 attr);
7b651a32 2392 nh_reset = true;
2393 }
737af885
BS
2394
2395
2396
40381db7 2397 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2398 /*
2399 * This flag is used for leaked vpn-vrf routes
2400 */
2401 int family = p->family;
2402
2403 if (peer_cap_enhe(peer, afi, safi))
2404 family = AF_INET6;
2405
2406 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2407 zlog_debug(
1defdda8 2408 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2409 __func__, family2str(family));
2410 subgroup_announce_reset_nhop(family, attr);
7b651a32 2411 nh_reset = true;
d62a17ae 2412 }
63696f1d 2413 }
960035b2 2414
63696f1d 2415 /* If IPv6/MP and nexthop does not have any override and happens
2416 * to
2417 * be a link-local address, reset it so that we don't pass along
2418 * the
2419 * source's link-local IPv6 address to recipients who may not be
2420 * on
2421 * the same interface.
2422 */
2423 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2424 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2425 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2426 nh_reset = true;
2427 }
d62a17ae 2428 }
3f9c7369 2429
7b651a32 2430 /*
2431 * When the next hop is set to ourselves, if all multipaths have
2432 * link-bandwidth announce the cumulative bandwidth as that makes
2433 * the most sense. However, don't modify if the link-bandwidth has
2434 * been explicitly set by user policy.
2435 */
2436 if (nh_reset &&
f7e1c681 2437 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2438 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2439 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2440 bgp_attr_set_ecommunity(
2441 attr,
2442 ecommunity_replace_linkbw(
2443 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2444 CHECK_FLAG(
2445 peer->flags,
2446 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2447
3dc339cd 2448 return true;
3f9c7369
DS
2449}
2450
cc9f21da 2451static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2452{
2453 struct afi_safi_info *info;
2454 afi_t afi;
2455 safi_t safi;
2456 struct bgp *bgp;
2457
2458 info = THREAD_ARG(thread);
2459 afi = info->afi;
2460 safi = info->safi;
2461 bgp = info->bgp;
2462
2463 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2464 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2465 safi);
f009ff26 2466
2467 bgp->gr_info[afi][safi].t_route_select = NULL;
2468
2469 XFREE(MTYPE_TMP, info);
2470
2471 /* Best path selection */
cc9f21da 2472 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2473}
2474
9bcb3eef 2475void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2476 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2477 struct bgp_path_info_pair *result, afi_t afi,
2478 safi_t safi)
2479{
2480 struct bgp_path_info *new_select;
2481 struct bgp_path_info *old_select;
40381db7
DS
2482 struct bgp_path_info *pi;
2483 struct bgp_path_info *pi1;
2484 struct bgp_path_info *pi2;
2485 struct bgp_path_info *nextpi = NULL;
d62a17ae 2486 int paths_eq, do_mpath, debug;
2487 struct list mp_list;
2488 char pfx_buf[PREFIX2STR_BUFFER];
2489 char path_buf[PATH_ADDPATH_STR_BUFFER];
2490
2491 bgp_mp_list_init(&mp_list);
2492 do_mpath =
2493 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2494
9bcb3eef 2495 debug = bgp_debug_bestpath(dest);
d62a17ae 2496
2497 if (debug)
9bcb3eef 2498 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2499
9bcb3eef 2500 dest->reason = bgp_path_selection_none;
d62a17ae 2501 /* bgp deterministic-med */
2502 new_select = NULL;
892fedb6 2503 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2504
1defdda8 2505 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2506 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2507 pi1 = pi1->next)
9bcb3eef 2508 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2509 BGP_PATH_DMED_SELECTED);
d62a17ae 2510
9bcb3eef 2511 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2512 pi1 = pi1->next) {
40381db7 2513 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2514 continue;
40381db7 2515 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2516 continue;
ea8b2282 2517 if (pi1->peer != bgp->peer_self)
feb17238 2518 if (!peer_established(pi1->peer))
d62a17ae 2519 continue;
2520
40381db7
DS
2521 new_select = pi1;
2522 if (pi1->next) {
2523 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2524 if (CHECK_FLAG(pi2->flags,
1defdda8 2525 BGP_PATH_DMED_CHECK))
d62a17ae 2526 continue;
40381db7 2527 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2528 continue;
ea8b2282 2529 if (pi2->peer != bgp->peer_self
d62a17ae 2530 && !CHECK_FLAG(
ea8b2282
DS
2531 pi2->peer->sflags,
2532 PEER_STATUS_NSF_WAIT))
40381db7 2533 if (pi2->peer->status
d62a17ae 2534 != Established)
2535 continue;
2536
121e245d
DS
2537 if (!aspath_cmp_left(pi1->attr->aspath,
2538 pi2->attr->aspath)
2539 && !aspath_cmp_left_confed(
40381db7 2540 pi1->attr->aspath,
121e245d
DS
2541 pi2->attr->aspath))
2542 continue;
d62a17ae 2543
121e245d
DS
2544 if (bgp_path_info_cmp(
2545 bgp, pi2, new_select,
2546 &paths_eq, mpath_cfg, debug,
fdf81fa0 2547 pfx_buf, afi, safi,
9bcb3eef 2548 &dest->reason)) {
121e245d 2549 bgp_path_info_unset_flag(
9bcb3eef 2550 dest, new_select,
121e245d
DS
2551 BGP_PATH_DMED_SELECTED);
2552 new_select = pi2;
d62a17ae 2553 }
121e245d
DS
2554
2555 bgp_path_info_set_flag(
9bcb3eef 2556 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2557 }
2558 }
9bcb3eef 2559 bgp_path_info_set_flag(dest, new_select,
18ee8310 2560 BGP_PATH_DMED_CHECK);
9bcb3eef 2561 bgp_path_info_set_flag(dest, new_select,
18ee8310 2562 BGP_PATH_DMED_SELECTED);
d62a17ae 2563
2564 if (debug) {
18ee8310 2565 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2566 new_select, path_buf, sizeof(path_buf));
8228a9a7 2567 zlog_debug(
4378495a
DS
2568 "%pBD(%s): %s is the bestpath from AS %u",
2569 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2570 aspath_get_first_as(
2571 new_select->attr->aspath));
d62a17ae 2572 }
2573 }
2574 }
96450faf 2575
d62a17ae 2576 /* Check old selected route and new selected route. */
2577 old_select = NULL;
2578 new_select = NULL;
9bcb3eef 2579 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2580 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2581 enum bgp_path_selection_reason reason;
2582
40381db7
DS
2583 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2584 old_select = pi;
d62a17ae 2585
40381db7 2586 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2587 /* reap REMOVED routes, if needs be
2588 * selected route must stay for a while longer though
2589 */
40381db7
DS
2590 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2591 && (pi != old_select))
9bcb3eef 2592 bgp_path_info_reap(dest, pi);
d62a17ae 2593
ddb5b488 2594 if (debug)
40381db7
DS
2595 zlog_debug("%s: pi %p in holddown", __func__,
2596 pi);
ddb5b488 2597
d62a17ae 2598 continue;
2599 }
96450faf 2600
40381db7
DS
2601 if (pi->peer && pi->peer != bgp->peer_self
2602 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2603 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2604
2605 if (debug)
2606 zlog_debug(
40381db7
DS
2607 "%s: pi %p non self peer %s not estab state",
2608 __func__, pi, pi->peer->host);
ddb5b488 2609
d62a17ae 2610 continue;
ddb5b488 2611 }
9fbdd100 2612
892fedb6 2613 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2614 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2615 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2616 if (debug)
40381db7 2617 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2618 continue;
2619 }
9fbdd100 2620
9bcb3eef 2621 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2622
9bcb3eef 2623 reason = dest->reason;
40381db7 2624 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2625 debug, pfx_buf, afi, safi,
2626 &dest->reason)) {
19ea4cec
DS
2627 if (new_select == NULL &&
2628 reason != bgp_path_selection_none)
9bcb3eef 2629 dest->reason = reason;
40381db7 2630 new_select = pi;
d62a17ae 2631 }
2632 }
718e3744 2633
d62a17ae 2634 /* Now that we know which path is the bestpath see if any of the other
2635 * paths
2636 * qualify as multipaths
2637 */
2638 if (debug) {
2639 if (new_select)
7533cad7
QY
2640 bgp_path_info_path_with_addpath_rx_str(
2641 new_select, path_buf, sizeof(path_buf));
d62a17ae 2642 else
772270f3 2643 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2644 zlog_debug(
4378495a
DS
2645 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2646 dest, bgp->name_pretty, path_buf,
d62a17ae 2647 old_select ? old_select->peer->host : "NONE");
96450faf 2648 }
9fbdd100 2649
d62a17ae 2650 if (do_mpath && new_select) {
9bcb3eef 2651 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2652 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2653
2654 if (debug)
18ee8310 2655 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2656 pi, path_buf, sizeof(path_buf));
d62a17ae 2657
40381db7 2658 if (pi == new_select) {
d62a17ae 2659 if (debug)
2660 zlog_debug(
4378495a
DS
2661 "%pBD(%s): %s is the bestpath, add to the multipath list",
2662 dest, bgp->name_pretty,
2663 path_buf);
40381db7 2664 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2665 continue;
2666 }
2667
40381db7 2668 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2669 continue;
2670
40381db7
DS
2671 if (pi->peer && pi->peer != bgp->peer_self
2672 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2673 PEER_STATUS_NSF_WAIT))
feb17238 2674 if (!peer_established(pi->peer))
d62a17ae 2675 continue;
2676
40381db7 2677 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2678 if (debug)
2679 zlog_debug(
8228a9a7
DS
2680 "%pBD: %s has the same nexthop as the bestpath, skip it",
2681 dest, path_buf);
d62a17ae 2682 continue;
2683 }
2684
40381db7 2685 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2686 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2687 &dest->reason);
d62a17ae 2688
2689 if (paths_eq) {
2690 if (debug)
2691 zlog_debug(
8228a9a7
DS
2692 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2693 dest, path_buf);
40381db7 2694 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2695 }
2696 }
2697 }
fee0f4c6 2698
4378495a 2699 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2700 mpath_cfg);
2701 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2702 bgp_mp_list_clear(&mp_list);
96450faf 2703
9bcb3eef 2704 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2705
d62a17ae 2706 result->old = old_select;
2707 result->new = new_select;
96450faf 2708
d62a17ae 2709 return;
fee0f4c6 2710}
2711
3f9c7369
DS
2712/*
2713 * A new route/change in bestpath of an existing route. Evaluate the path
2714 * for advertisement to the subgroup.
2715 */
3dc339cd
DA
2716void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2717 struct bgp_path_info *selected,
9bcb3eef 2718 struct bgp_dest *dest,
3dc339cd 2719 uint32_t addpath_tx_id)
d62a17ae 2720{
b54892e0 2721 const struct prefix *p;
d62a17ae 2722 struct peer *onlypeer;
2723 struct attr attr;
2724 afi_t afi;
2725 safi_t safi;
a77e2f4b
S
2726 struct bgp *bgp;
2727 bool advertise;
adbac85e 2728
9bcb3eef 2729 p = bgp_dest_get_prefix(dest);
d62a17ae 2730 afi = SUBGRP_AFI(subgrp);
2731 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2732 bgp = SUBGRP_INST(subgrp);
d62a17ae 2733 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2734 : NULL);
2735
2dbe669b
DA
2736 if (BGP_DEBUG(update, UPDATE_OUT))
2737 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2738
d62a17ae 2739 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2740 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2741 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2742 return;
d62a17ae 2743
6006b807 2744 memset(&attr, 0, sizeof(attr));
d62a17ae 2745 /* It's initialized in bgp_announce_check() */
2746
a77e2f4b
S
2747 /* Announcement to the subgroup. If the route is filtered withdraw it.
2748 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2749 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2750 * route
d62a17ae 2751 */
a77e2f4b
S
2752 advertise = bgp_check_advertise(bgp, dest);
2753
d62a17ae 2754 if (selected) {
7f7940e6 2755 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2756 NULL)) {
a77e2f4b
S
2757 /* Route is selected, if the route is already installed
2758 * in FIB, then it is advertised
2759 */
be785e35
DS
2760 if (advertise) {
2761 if (!bgp_check_withdrawal(bgp, dest))
2762 bgp_adj_out_set_subgroup(
2763 dest, subgrp, &attr, selected);
2764 else
2765 bgp_adj_out_unset_subgroup(
2766 dest, subgrp, 1, addpath_tx_id);
2767 }
a77e2f4b 2768 } else
9bcb3eef 2769 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2770 addpath_tx_id);
d62a17ae 2771 }
2772
2773 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2774 else {
9bcb3eef 2775 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2776 }
200df115 2777}
fee0f4c6 2778
3064bf43 2779/*
e1072051 2780 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2781 * This is called at the end of route processing.
3064bf43 2782 */
9bcb3eef 2783void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2784{
40381db7 2785 struct bgp_path_info *pi;
3064bf43 2786
9bcb3eef 2787 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2788 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2789 continue;
40381db7
DS
2790 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2791 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2792 }
3064bf43 2793}
2794
2795/*
2796 * Has the route changed from the RIB's perspective? This is invoked only
2797 * if the route selection returns the same best route as earlier - to
2798 * determine if we need to update zebra or not.
2799 */
9bcb3eef 2800bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2801{
4b7e6066 2802 struct bgp_path_info *mpinfo;
d62a17ae 2803
2bb9eff4
DS
2804 /* If this is multipath, check all selected paths for any nexthop
2805 * change or attribute change. Some attribute changes (e.g., community)
2806 * aren't of relevance to the RIB, but we'll update zebra to ensure
2807 * we handle the case of BGP nexthop change. This is the behavior
2808 * when the best path has an attribute change anyway.
d62a17ae 2809 */
1defdda8 2810 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2811 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2812 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2813 return true;
d62a17ae 2814
2bb9eff4
DS
2815 /*
2816 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2817 */
18ee8310
DS
2818 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2819 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2820 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2821 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2822 return true;
d62a17ae 2823 }
3064bf43 2824
d62a17ae 2825 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2826 return false;
3064bf43 2827}
2828
d62a17ae 2829struct bgp_process_queue {
2830 struct bgp *bgp;
9bcb3eef 2831 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2832#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2833 unsigned int flags;
2834 unsigned int queued;
200df115 2835};
2836
3b0c17e1 2837static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2838 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2839 struct bgp_path_info *new_select,
2840 struct bgp_path_info *old_select)
2841{
9bcb3eef 2842 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2843
2844 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2845 return;
2846
2847 if (advertise_type5_routes(bgp, afi) && new_select
2848 && is_route_injectable_into_evpn(new_select)) {
2849
2850 /* apply the route-map */
2851 if (bgp->adv_cmd_rmap[afi][safi].map) {
2852 route_map_result_t ret;
2853 struct bgp_path_info rmap_path;
2854 struct bgp_path_info_extra rmap_path_extra;
2855 struct attr dummy_attr;
2856
2857 dummy_attr = *new_select->attr;
2858
2859 /* Fill temp path_info */
9bcb3eef 2860 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2861 new_select, new_select->peer,
2862 &dummy_attr);
2863
2864 RESET_FLAG(dummy_attr.rmap_change_flags);
2865
2866 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2867 p, &rmap_path);
3b0c17e1 2868
2869 if (ret == RMAP_DENYMATCH) {
2870 bgp_attr_flush(&dummy_attr);
2871 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2872 safi);
2873 } else
2874 bgp_evpn_advertise_type5_route(
2875 bgp, p, &dummy_attr, afi, safi);
2876 } else {
2877 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2878 afi, safi);
2879 }
2880 } else if (advertise_type5_routes(bgp, afi) && old_select
2881 && is_route_injectable_into_evpn(old_select))
2882 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2883}
2884
bb2ca692
MS
2885/*
2886 * Utility to determine whether a particular path_info should use
2887 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2888 * in a path where we basically _know_ this is a BGP-LU route.
2889 */
2890static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2891{
2892 /* Certain types get imp null; so do paths where the nexthop is
2893 * not labeled.
2894 */
2895 if (new_select->sub_type == BGP_ROUTE_STATIC
2896 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2897 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2898 return true;
2899 else if (new_select->extra == NULL ||
2900 !bgp_is_valid_label(&new_select->extra->label[0]))
2901 /* TODO -- should be configurable? */
2902 return true;
2903 else
2904 return false;
2905}
2906
3103e8d2
DS
2907/*
2908 * old_select = The old best path
2909 * new_select = the new best path
2910 *
2911 * if (!old_select && new_select)
2912 * We are sending new information on.
2913 *
2914 * if (old_select && new_select) {
2915 * if (new_select != old_select)
2916 * We have a new best path send a change
2917 * else
2918 * We've received a update with new attributes that needs
2919 * to be passed on.
2920 * }
2921 *
2922 * if (old_select && !new_select)
2923 * We have no eligible route that we can announce or the rn
2924 * is being removed.
2925 */
9bcb3eef 2926static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2927 afi_t afi, safi_t safi)
d62a17ae 2928{
4b7e6066
DS
2929 struct bgp_path_info *new_select;
2930 struct bgp_path_info *old_select;
2931 struct bgp_path_info_pair old_and_new;
ddb5b488 2932 int debug = 0;
d62a17ae 2933
892fedb6 2934 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2935 if (dest)
2936 debug = bgp_debug_bestpath(dest);
b54892e0 2937 if (debug)
f4c713ae 2938 zlog_debug(
56ca3b5b 2939 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2940 __func__, dest);
f4c713ae
LB
2941 return;
2942 }
d62a17ae 2943 /* Is it end of initial update? (after startup) */
9bcb3eef 2944 if (!dest) {
e36f61b5
DS
2945 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2946 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2947
2948 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2949 FOREACH_AFI_SAFI (afi, safi) {
2950 if (bgp_fibupd_safi(safi))
2951 bgp_zebra_announce_table(bgp, afi, safi);
2952 }
d62a17ae 2953 bgp->main_peers_update_hold = 0;
2954
2955 bgp_start_routeadv(bgp);
aac24838 2956 return;
d62a17ae 2957 }
cb1faec9 2958
9bcb3eef 2959 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2960
9bcb3eef 2961 debug = bgp_debug_bestpath(dest);
b54892e0 2962 if (debug)
4378495a
DS
2963 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2964 dest, bgp->name_pretty, afi2str(afi),
2965 safi2str(safi));
ddb5b488 2966
f009ff26 2967 /* The best path calculation for the route is deferred if
2968 * BGP_NODE_SELECT_DEFER is set
2969 */
9bcb3eef 2970 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2971 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2972 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2973 return;
2974 }
2975
d62a17ae 2976 /* Best path selection. */
9bcb3eef 2977 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2978 afi, safi);
2979 old_select = old_and_new.old;
2980 new_select = old_and_new.new;
2981
2982 /* Do we need to allocate or free labels?
2983 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2984 * necessary to do this upon changes to best path. Exceptions:
2985 * - label index has changed -> recalculate resulting label
2986 * - path_info sub_type changed -> switch to/from implicit-null
2987 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2988 */
318cac96 2989 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2990 if (new_select) {
2991 if (!old_select
2992 || bgp_label_index_differs(new_select, old_select)
57592a53 2993 || new_select->sub_type != old_select->sub_type
9bcb3eef 2994 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2995 /* Enforced penultimate hop popping:
2996 * implicit-null for local routes, aggregate
2997 * and redistributed routes
2998 */
bb2ca692 2999 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3000 if (CHECK_FLAG(
9bcb3eef 3001 dest->flags,
992dd67e
PR
3002 BGP_NODE_REGISTERED_FOR_LABEL)
3003 || CHECK_FLAG(
3004 dest->flags,
3005 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3006 bgp_unregister_for_label(dest);
67f67ba4
DA
3007 dest->local_label = mpls_lse_encode(
3008 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3009 1);
9bcb3eef 3010 bgp_set_valid_label(&dest->local_label);
d62a17ae 3011 } else
9bcb3eef
DS
3012 bgp_register_for_label(dest,
3013 new_select);
d62a17ae 3014 }
9bcb3eef 3015 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3016 BGP_NODE_REGISTERED_FOR_LABEL)
3017 || CHECK_FLAG(dest->flags,
3018 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3019 bgp_unregister_for_label(dest);
318cac96 3020 }
992dd67e
PR
3021 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3022 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3023 bgp_unregister_for_label(dest);
d62a17ae 3024 }
cd1964ff 3025
b54892e0 3026 if (debug)
ddb5b488 3027 zlog_debug(
4378495a
DS
3028 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3029 __func__, dest, bgp->name_pretty, afi2str(afi),
3030 safi2str(safi), old_select, new_select);
ddb5b488 3031
d62a17ae 3032 /* If best route remains the same and this is not due to user-initiated
3033 * clear, see exactly what needs to be done.
3034 */
d62a17ae 3035 if (old_select && old_select == new_select
9bcb3eef 3036 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3037 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3038 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3039 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3040#ifdef ENABLE_BGP_VNC
d62a17ae 3041 vnc_import_bgp_add_route(bgp, p, old_select);
3042 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3043#endif
bb744275 3044 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3045 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3046
be785e35
DS
3047 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3048 && new_select->sub_type == BGP_ROUTE_NORMAL)
3049 SET_FLAG(dest->flags,
3050 BGP_NODE_FIB_INSTALL_PENDING);
3051
ddb5b488
PZ
3052 if (new_select->type == ZEBRA_ROUTE_BGP
3053 && (new_select->sub_type == BGP_ROUTE_NORMAL
3054 || new_select->sub_type
3055 == BGP_ROUTE_IMPORTED))
3056
9bcb3eef 3057 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3058 bgp, afi, safi);
3059 }
d62a17ae 3060 }
d62a17ae 3061
3062 /* If there is a change of interest to peers, reannounce the
3063 * route. */
1defdda8 3064 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3065 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3066 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3067 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3068
3069 /* unicast routes must also be annouced to
3070 * labeled-unicast update-groups */
3071 if (safi == SAFI_UNICAST)
3072 group_announce_route(bgp, afi,
9bcb3eef 3073 SAFI_LABELED_UNICAST, dest,
d62a17ae 3074 new_select);
3075
1defdda8 3076 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3077 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3078 }
fee0f4c6 3079
3b0c17e1 3080 /* advertise/withdraw type-5 routes */
3081 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3082 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3083 bgp_process_evpn_route_injection(
9bcb3eef 3084 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3085
b1875e65 3086 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3087 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3088 bgp_zebra_clear_route_change_flags(dest);
3089 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3090 return;
d62a17ae 3091 }
8ad7271d 3092
d62a17ae 3093 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3094 */
9bcb3eef 3095 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3096
3097 /* bestpath has changed; bump version */
3098 if (old_select || new_select) {
9bcb3eef 3099 bgp_bump_version(dest);
d62a17ae 3100
3101 if (!bgp->t_rmap_def_originate_eval) {
3102 bgp_lock(bgp);
3103 thread_add_timer(
3104 bm->master,
3105 update_group_refresh_default_originate_route_map,
3106 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3107 &bgp->t_rmap_def_originate_eval);
3108 }
3109 }
3f9c7369 3110
d62a17ae 3111 if (old_select)
9bcb3eef 3112 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3113 if (new_select) {
ddb5b488
PZ
3114 if (debug)
3115 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3116 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3117 bgp_path_info_unset_flag(dest, new_select,
3118 BGP_PATH_ATTR_CHANGED);
1defdda8 3119 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3120 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3121 }
338b3424 3122
49e5a4a0 3123#ifdef ENABLE_BGP_VNC
d62a17ae 3124 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3125 if (old_select != new_select) {
3126 if (old_select) {
3127 vnc_import_bgp_exterior_del_route(bgp, p,
3128 old_select);
3129 vnc_import_bgp_del_route(bgp, p, old_select);
3130 }
3131 if (new_select) {
3132 vnc_import_bgp_exterior_add_route(bgp, p,
3133 new_select);
3134 vnc_import_bgp_add_route(bgp, p, new_select);
3135 }
3136 }
3137 }
65efcfce
LB
3138#endif
3139
9bcb3eef 3140 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3141
3142 /* unicast routes must also be annouced to labeled-unicast update-groups
3143 */
3144 if (safi == SAFI_UNICAST)
9bcb3eef 3145 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3146 new_select);
3147
3148 /* FIB update. */
3149 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3150 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3151
d62a17ae 3152 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3153 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3154 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3155 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3156
be785e35
DS
3157 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3158 SET_FLAG(dest->flags,
3159 BGP_NODE_FIB_INSTALL_PENDING);
3160
2b659f33
MK
3161 /* if this is an evpn imported type-5 prefix,
3162 * we need to withdraw the route first to clear
3163 * the nh neigh and the RMAC entry.
3164 */
3165 if (old_select &&
3166 is_route_parent_evpn(old_select))
3167 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3168
9bcb3eef 3169 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3170 } else {
d62a17ae 3171 /* Withdraw the route from the kernel. */
3172 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3173 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3174 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3175 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3176
568e10ca 3177 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3178 }
718e3744 3179 }
3064bf43 3180
9bcb3eef 3181 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3182 old_select);
5424b7ba 3183
d62a17ae 3184 /* Clear any route change flags. */
9bcb3eef 3185 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3186
18ee8310 3187 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3188 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3189 bgp_path_info_reap(dest, old_select);
d62a17ae 3190
9bcb3eef 3191 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3192 return;
718e3744 3193}
3194
f009ff26 3195/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3196int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3197{
9bcb3eef 3198 struct bgp_dest *dest;
f009ff26 3199 int cnt = 0;
3200 struct afi_safi_info *thread_info;
f009ff26 3201
56c226e7
DS
3202 if (bgp->gr_info[afi][safi].t_route_select) {
3203 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3204
3205 thread_info = THREAD_ARG(t);
3206 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3207 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3208 }
f009ff26 3209
3210 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3211 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3212 get_afi_safi_str(afi, safi, false),
26742171 3213 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3214 }
3215
3216 /* Process the route list */
6338d242 3217 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3218 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3219 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3220 dest = bgp_route_next(dest)) {
3221 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3222 continue;
3223
3224 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3225 bgp->gr_info[afi][safi].gr_deferred--;
3226 bgp_process_main_one(bgp, dest, afi, safi);
3227 cnt++;
067ea165
CB
3228 }
3229 /* If iteration stopped before the entire table was traversed then the
3230 * node needs to be unlocked.
3231 */
3232 if (dest) {
3233 bgp_dest_unlock_node(dest);
3234 dest = NULL;
f009ff26 3235 }
3236
9e3b51a7 3237 /* Send EOR message when all routes are processed */
6338d242 3238 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3239 bgp_send_delayed_eor(bgp);
8c48b3b6 3240 /* Send route processing complete message to RIB */
3241 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3242 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3243 return 0;
9e3b51a7 3244 }
f009ff26 3245
3246 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3247
3248 thread_info->afi = afi;
3249 thread_info->safi = safi;
3250 thread_info->bgp = bgp;
3251
3252 /* If there are more routes to be processed, start the
3253 * selection timer
3254 */
3255 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3256 BGP_ROUTE_SELECT_DELAY,
3257 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3258 return 0;
3259}
3260
aac24838 3261static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3262{
aac24838
JB
3263 struct bgp_process_queue *pqnode = data;
3264 struct bgp *bgp = pqnode->bgp;
d62a17ae 3265 struct bgp_table *table;
9bcb3eef 3266 struct bgp_dest *dest;
aac24838
JB
3267
3268 /* eoiu marker */
3269 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3270 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3271 /* should always have dedicated wq call */
3272 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3273 return WQ_SUCCESS;
3274 }
3275
ac021f40 3276 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3277 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3278 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3279 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3280 table = bgp_dest_table(dest);
3281 /* note, new DESTs may be added as part of processing */
3282 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3283
9bcb3eef 3284 bgp_dest_unlock_node(dest);
d62a17ae 3285 bgp_table_unlock(table);
3286 }
aac24838
JB
3287
3288 return WQ_SUCCESS;
3289}
3290
3291static void bgp_processq_del(struct work_queue *wq, void *data)
3292{
3293 struct bgp_process_queue *pqnode = data;
3294
3295 bgp_unlock(pqnode->bgp);
3296
3297 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3298}
3299
b6c386bb 3300void bgp_process_queue_init(struct bgp *bgp)
200df115 3301{
b6c386bb
DS
3302 if (!bgp->process_queue) {
3303 char name[BUFSIZ];
3304
3305 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3306 bgp->process_queue = work_queue_new(bm->master, name);
3307 }
3308
3309 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3310 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3311 bgp->process_queue->spec.max_retries = 0;
3312 bgp->process_queue->spec.hold = 50;
d62a17ae 3313 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3314 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3315}
3316
cfe8d15a 3317static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3318{
3319 struct bgp_process_queue *pqnode;
3320
a4d82a8a
PZ
3321 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3322 sizeof(struct bgp_process_queue));
aac24838
JB
3323
3324 /* unlocked in bgp_processq_del */
3325 pqnode->bgp = bgp_lock(bgp);
3326 STAILQ_INIT(&pqnode->pqueue);
3327
aac24838
JB
3328 return pqnode;
3329}
3330
9bcb3eef 3331void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3332{
aac24838 3333#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3334 struct work_queue *wq = bgp->process_queue;
d62a17ae 3335 struct bgp_process_queue *pqnode;
cfe8d15a 3336 int pqnode_reuse = 0;
495f0b13 3337
d62a17ae 3338 /* already scheduled for processing? */
9bcb3eef 3339 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3340 return;
2e02b9b2 3341
f009ff26 3342 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3343 * the workqueue
3344 */
9bcb3eef 3345 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3346 if (BGP_DEBUG(update, UPDATE_OUT))
3347 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3348 dest);
f009ff26 3349 return;
3350 }
3351
46aeabed
LS
3352 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3353 if (BGP_DEBUG(update, UPDATE_OUT))
3354 zlog_debug(
3355 "Soft reconfigure table in progress for route %p",
3356 dest);
3357 return;
3358 }
3359
aac24838 3360 if (wq == NULL)
d62a17ae 3361 return;
3362
aac24838 3363 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3364 limit only if is from the same BGP view and it's not an EOIU marker
3365 */
aac24838
JB
3366 if (work_queue_item_count(wq)) {
3367 struct work_queue_item *item = work_queue_last_item(wq);
3368 pqnode = item->data;
228da428 3369
a4d82a8a
PZ
3370 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3371 || pqnode->bgp != bgp
3372 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3373 pqnode = bgp_processq_alloc(bgp);
3374 else
3375 pqnode_reuse = 1;
aac24838 3376 } else
cfe8d15a 3377 pqnode = bgp_processq_alloc(bgp);
aac24838 3378 /* all unlocked in bgp_process_wq */
9bcb3eef 3379 bgp_table_lock(bgp_dest_table(dest));
aac24838 3380
9bcb3eef
DS
3381 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3382 bgp_dest_lock_node(dest);
aac24838 3383
60466a63 3384 /* can't be enqueued twice */
9bcb3eef
DS
3385 assert(STAILQ_NEXT(dest, pq) == NULL);
3386 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3387 pqnode->queued++;
3388
cfe8d15a
LB
3389 if (!pqnode_reuse)
3390 work_queue_add(wq, pqnode);
3391
d62a17ae 3392 return;
fee0f4c6 3393}
0a486e5f 3394
d62a17ae 3395void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3396{
d62a17ae 3397 struct bgp_process_queue *pqnode;
cb1faec9 3398
b6c386bb 3399 if (bgp->process_queue == NULL)
d62a17ae 3400 return;
2e02b9b2 3401
cfe8d15a 3402 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3403
aac24838 3404 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3405 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3406}
3407
cc9f21da 3408static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3409{
d62a17ae 3410 struct peer *peer;
0a486e5f 3411
d62a17ae 3412 peer = THREAD_ARG(thread);
3413 peer->t_pmax_restart = NULL;
0a486e5f 3414
d62a17ae 3415 if (bgp_debug_neighbor_events(peer))
3416 zlog_debug(
3417 "%s Maximum-prefix restart timer expired, restore peering",
3418 peer->host);
0a486e5f 3419
a9bafa95 3420 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3421 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3422}
3423
9cbd06e0
DA
3424static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3425 safi_t safi)
3426{
3427 uint32_t count = 0;
f41b0459 3428 bool filtered = false;
9cbd06e0
DA
3429 struct bgp_dest *dest;
3430 struct bgp_adj_in *ain;
40bb2ccf 3431 struct attr attr = {};
9cbd06e0
DA
3432 struct bgp_table *table = peer->bgp->rib[afi][safi];
3433
3434 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3435 for (ain = dest->adj_in; ain; ain = ain->next) {
3436 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3437
3438 attr = *ain->attr;
9cbd06e0
DA
3439
3440 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3441 == FILTER_DENY)
f41b0459
DA
3442 filtered = true;
3443
3444 if (bgp_input_modifier(
3445 peer, rn_p, &attr, afi, safi,
3446 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3447 NULL, 0, NULL)
3448 == RMAP_DENY)
3449 filtered = true;
3450
3451 if (filtered)
9cbd06e0 3452 count++;
f41b0459 3453
d498917e 3454 bgp_attr_flush(&attr);
9cbd06e0
DA
3455 }
3456 }
3457
3458 return count;
3459}
3460
3dc339cd
DA
3461bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3462 int always)
718e3744 3463{
d62a17ae 3464 iana_afi_t pkt_afi;
5c525538 3465 iana_safi_t pkt_safi;
9cbd06e0
DA
3466 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3467 PEER_FLAG_MAX_PREFIX_FORCE))
3468 ? bgp_filtered_routes_count(peer, afi, safi)
3469 + peer->pcount[afi][safi]
3470 : peer->pcount[afi][safi];
9cabb64b 3471
d62a17ae 3472 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3473 return false;
e0701b79 3474
9cbd06e0 3475 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3476 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3477 PEER_STATUS_PREFIX_LIMIT)
3478 && !always)
3dc339cd 3479 return false;
e0701b79 3480
d62a17ae 3481 zlog_info(
f70c91dc
DA
3482 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3483 get_afi_safi_str(afi, safi, false), peer, pcount,
3484 peer->pmax[afi][safi]);
d62a17ae 3485 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3486
3487 if (CHECK_FLAG(peer->af_flags[afi][safi],
3488 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3489 return false;
d62a17ae 3490
3491 /* Convert AFI, SAFI to values for packet. */
3492 pkt_afi = afi_int2iana(afi);
3493 pkt_safi = safi_int2iana(safi);
3494 {
d7c0a89a 3495 uint8_t ndata[7];
d62a17ae 3496
3497 ndata[0] = (pkt_afi >> 8);
3498 ndata[1] = pkt_afi;
3499 ndata[2] = pkt_safi;
3500 ndata[3] = (peer->pmax[afi][safi] >> 24);
3501 ndata[4] = (peer->pmax[afi][safi] >> 16);
3502 ndata[5] = (peer->pmax[afi][safi] >> 8);
3503 ndata[6] = (peer->pmax[afi][safi]);
3504
3505 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3506 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3507 BGP_NOTIFY_CEASE_MAX_PREFIX,
3508 ndata, 7);
3509 }
3510
3511 /* Dynamic peers will just close their connection. */
3512 if (peer_dynamic_neighbor(peer))
3dc339cd 3513 return true;
d62a17ae 3514
3515 /* restart timer start */
3516 if (peer->pmax_restart[afi][safi]) {
3517 peer->v_pmax_restart =
3518 peer->pmax_restart[afi][safi] * 60;
3519
3520 if (bgp_debug_neighbor_events(peer))
3521 zlog_debug(
f70c91dc
DA
3522 "%pBP Maximum-prefix restart timer started for %d secs",
3523 peer, peer->v_pmax_restart);
d62a17ae 3524
3525 BGP_TIMER_ON(peer->t_pmax_restart,
3526 bgp_maximum_prefix_restart_timer,
3527 peer->v_pmax_restart);
3528 }
3529
3dc339cd 3530 return true;
d62a17ae 3531 } else
3532 UNSET_FLAG(peer->af_sflags[afi][safi],
3533 PEER_STATUS_PREFIX_LIMIT);
3534
b1823b69
DS
3535 if (pcount
3536 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3537 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3538 PEER_STATUS_PREFIX_THRESHOLD)
3539 && !always)
3dc339cd 3540 return false;
d62a17ae 3541
3542 zlog_info(
f70c91dc
DA
3543 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3544 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3545 peer->pmax[afi][safi]);
d62a17ae 3546 SET_FLAG(peer->af_sflags[afi][safi],
3547 PEER_STATUS_PREFIX_THRESHOLD);
3548 } else
3549 UNSET_FLAG(peer->af_sflags[afi][safi],
3550 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3551 return false;
718e3744 3552}
3553
b40d939b 3554/* Unconditionally remove the route from the RIB, without taking
3555 * damping into consideration (eg, because the session went down)
3556 */
9bcb3eef 3557void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3558 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3559{
f009ff26 3560
3561 struct bgp *bgp = NULL;
3562 bool delete_route = false;
3563
9bcb3eef
DS
3564 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3565 safi);
d62a17ae 3566
f009ff26 3567 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3568 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3569
f009ff26 3570 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3571 * flag
3572 */
3573 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3574 delete_route = true;
9bcb3eef 3575 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3576 delete_route = true;
f009ff26 3577 if (delete_route) {
9bcb3eef
DS
3578 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3579 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3580 bgp = pi->peer->bgp;
26742171 3581 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3582 }
3583 }
3584 }
4a11bf2c 3585
9bcb3eef
DS
3586 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3587 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3588}
3589
9bcb3eef 3590static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3591 struct peer *peer, afi_t afi, safi_t safi,
3592 struct prefix_rd *prd)
3593{
9bcb3eef 3594 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3595
d62a17ae 3596 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3597 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3598 */
b4f7f45b
IR
3599 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3600 && peer->sort == BGP_PEER_EBGP)
3601 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3602 == BGP_DAMP_SUPPRESSED) {
3603 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3604 safi);
3605 return;
d62a17ae 3606 }
3607
49e5a4a0 3608#ifdef ENABLE_BGP_VNC
d62a17ae 3609 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3610 struct bgp_dest *pdest = NULL;
d62a17ae 3611 struct bgp_table *table = NULL;
3612
9bcb3eef
DS
3613 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3614 (struct prefix *)prd);
3615 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3616 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3617
3618 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3619 peer->bgp, prd, table, p, pi);
d62a17ae 3620 }
9bcb3eef 3621 bgp_dest_unlock_node(pdest);
d62a17ae 3622 }
3623 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3624 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3625
b54892e0
DS
3626 vnc_import_bgp_del_route(peer->bgp, p, pi);
3627 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3628 }
65efcfce 3629 }
d62a17ae 3630#endif
128ea8ab 3631
d62a17ae 3632 /* If this is an EVPN route, process for un-import. */
3633 if (safi == SAFI_EVPN)
b54892e0 3634 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3635
9bcb3eef 3636 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3637}
3638
4b7e6066
DS
3639struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3640 struct peer *peer, struct attr *attr,
9bcb3eef 3641 struct bgp_dest *dest)
fb018d25 3642{
4b7e6066 3643 struct bgp_path_info *new;
fb018d25 3644
d62a17ae 3645 /* Make new BGP info. */
4b7e6066 3646 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3647 new->type = type;
3648 new->instance = instance;
3649 new->sub_type = sub_type;
3650 new->peer = peer;
3651 new->attr = attr;
3652 new->uptime = bgp_clock();
9bcb3eef 3653 new->net = dest;
d62a17ae 3654 return new;
fb018d25
DS
3655}
3656
c265ee22 3657/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3658bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3659 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3660 struct bgp_dest *dest)
d62a17ae 3661{
2dbe3fa9 3662 bool ret = false;
b099a5c8
DA
3663 bool is_bgp_static_route =
3664 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3665 : false;
d62a17ae 3666
e8442016
DS
3667 /*
3668 * Only validated for unicast and multicast currently.
3669 * Also valid for EVPN where the nexthop is an IP address.
3670 * If we are a bgp static route being checked then there is
3671 * no need to check to see if the nexthop is martian as
3672 * that it should be ok.
3673 */
3674 if (is_bgp_static_route ||
3675 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3676 return false;
d62a17ae 3677
3678 /* If NEXT_HOP is present, validate it. */
3679 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3680 if (attr->nexthop.s_addr == INADDR_ANY ||
3681 !ipv4_unicast_valid(&attr->nexthop) ||
3682 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3683 return true;
d62a17ae 3684 }
c265ee22 3685
d62a17ae 3686 /* If MP_NEXTHOP is present, validate it. */
3687 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3688 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3689 * it is not an IPv6 link-local address.
0355b41d
DA
3690 *
3691 * If we receive an UPDATE with nexthop length set to 32 bytes
3692 * we shouldn't discard an UPDATE if it's set to (::).
3693 * The link-local (2st) is validated along the code path later.
d62a17ae 3694 */
3695 if (attr->mp_nexthop_len) {
3696 switch (attr->mp_nexthop_len) {
3697 case BGP_ATTR_NHLEN_IPV4:
3698 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3699 ret = (attr->mp_nexthop_global_in.s_addr ==
3700 INADDR_ANY ||
3701 !ipv4_unicast_valid(
3702 &attr->mp_nexthop_global_in) ||
3703 bgp_nexthop_self(bgp, afi, type, stype, attr,
3704 dest));
d62a17ae 3705 break;
3706
3707 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3708 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3709 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3710 &attr->mp_nexthop_global)
d62a17ae 3711 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3712 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3713 &attr->mp_nexthop_global)
3714 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3715 dest));
d62a17ae 3716 break;
0355b41d
DA
3717 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3718 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3719 || IN6_IS_ADDR_MULTICAST(
3720 &attr->mp_nexthop_global)
3721 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3722 dest));
0355b41d 3723 break;
d62a17ae 3724
3725 default:
3dc339cd 3726 ret = true;
d62a17ae 3727 break;
3728 }
3729 }
c265ee22 3730
d62a17ae 3731 return ret;
3732}
3733
aade37d7 3734static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3735{
3736 struct community *old;
3737 struct community *new;
3738 struct community *merge;
aade37d7 3739 struct community *no_export;
2721dd61 3740
9a706b42 3741 old = bgp_attr_get_community(attr);
aade37d7 3742 no_export = community_str2com("no-export");
2721dd61 3743
b4efa101
DA
3744 assert(no_export);
3745
2721dd61 3746 if (old) {
aade37d7 3747 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3748
3749 if (!old->refcnt)
3750 community_free(&old);
3751
3752 new = community_uniq_sort(merge);
3753 community_free(&merge);
3754 } else {
aade37d7 3755 new = community_dup(no_export);
2721dd61
DA
3756 }
3757
aade37d7 3758 community_free(&no_export);
2721dd61 3759
9a706b42 3760 bgp_attr_set_community(attr, new);
2721dd61
DA
3761}
3762
5a1ae2c2 3763int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3764 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3765 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3766 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3767 struct bgp_route_evpn *evpn)
d62a17ae 3768{
3769 int ret;
3770 int aspath_loop_count = 0;
9bcb3eef 3771 struct bgp_dest *dest;
d62a17ae 3772 struct bgp *bgp;
3773 struct attr new_attr;
3774 struct attr *attr_new;
40381db7 3775 struct bgp_path_info *pi;
4b7e6066
DS
3776 struct bgp_path_info *new;
3777 struct bgp_path_info_extra *extra;
d62a17ae 3778 const char *reason;
3779 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3780 int connected = 0;
3781 int do_loop_check = 1;
3782 int has_valid_label = 0;
7c312383 3783 afi_t nh_afi;
949b0f24 3784 uint8_t pi_type = 0;
3785 uint8_t pi_sub_type = 0;
9146341f 3786 bool force_evpn_import = false;
907707db 3787 safi_t orig_safi = safi;
a486300b 3788 bool leak_success = true;
949b0f24 3789
c7bb4f00 3790 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3791 char pfxprint[PREFIX2STR_BUFFER];
3792
3793 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3794 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3795 afi, safi, attr);
6401252f
QY
3796 }
3797
49e5a4a0 3798#ifdef ENABLE_BGP_VNC
d62a17ae 3799 int vnc_implicit_withdraw = 0;
65efcfce 3800#endif
d62a17ae 3801 int same_attr = 0;
718e3744 3802
907707db
MS
3803 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3804 if (orig_safi == SAFI_LABELED_UNICAST)
3805 safi = SAFI_UNICAST;
3806
6006b807 3807 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3808 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3809 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3810
d62a17ae 3811 bgp = peer->bgp;
9bcb3eef 3812 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3813 /* TODO: Check to see if we can get rid of "is_valid_label" */
3814 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3815 has_valid_label = (num_labels > 0) ? 1 : 0;
3816 else
3817 has_valid_label = bgp_is_valid_label(label);
718e3744 3818
28f66de2
MS
3819 if (has_valid_label)
3820 assert(label != NULL);
3821
66ff6089
AD
3822 /* Update overlay index of the attribute */
3823 if (afi == AFI_L2VPN && evpn)
3824 memcpy(&attr->evpn_overlay, evpn,
3825 sizeof(struct bgp_route_evpn));
3826
d62a17ae 3827 /* When peer's soft reconfiguration enabled. Record input packet in
3828 Adj-RIBs-In. */
3829 if (!soft_reconfig
3830 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3831 && peer != bgp->peer_self)
9bcb3eef 3832 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3833
3834 /* Check previously received route. */
9bcb3eef 3835 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3836 if (pi->peer == peer && pi->type == type
3837 && pi->sub_type == sub_type
3838 && pi->addpath_rx_id == addpath_id)
d62a17ae 3839 break;
3840
3841 /* AS path local-as loop check. */
3842 if (peer->change_local_as) {
c4368918
DW
3843 if (peer->allowas_in[afi][safi])
3844 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3845 else if (!CHECK_FLAG(peer->flags,
3846 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3847 aspath_loop_count = 1;
3848
3849 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3850 > aspath_loop_count) {
b4d46cc9 3851 peer->stat_pfx_aspath_loop++;
692174a1 3852 reason = "as-path contains our own AS;";
d62a17ae 3853 goto filtered;
3854 }
718e3744 3855 }
718e3744 3856
d62a17ae 3857 /* If the peer is configured for "allowas-in origin" and the last ASN in
3858 * the
3859 * as-path is our ASN then we do not need to call aspath_loop_check
3860 */
3861 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3862 if (aspath_get_last_as(attr->aspath) == bgp->as)
3863 do_loop_check = 0;
3864
3865 /* AS path loop check. */
3866 if (do_loop_check) {
3867 if (aspath_loop_check(attr->aspath, bgp->as)
3868 > peer->allowas_in[afi][safi]
3869 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3870 && aspath_loop_check(attr->aspath, bgp->confed_id)
3871 > peer->allowas_in[afi][safi])) {
b4d46cc9 3872 peer->stat_pfx_aspath_loop++;
d62a17ae 3873 reason = "as-path contains our own AS;";
3874 goto filtered;
3875 }
3876 }
aac9ef6c 3877
d62a17ae 3878 /* Route reflector originator ID check. */
3879 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3880 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3881 peer->stat_pfx_originator_loop++;
d62a17ae 3882 reason = "originator is us;";
3883 goto filtered;
3884 }
718e3744 3885
d62a17ae 3886 /* Route reflector cluster ID check. */
3887 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3888 peer->stat_pfx_cluster_loop++;
d62a17ae 3889 reason = "reflected from the same cluster;";
3890 goto filtered;
3891 }
718e3744 3892
d62a17ae 3893 /* Apply incoming filter. */
907707db 3894 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3895 peer->stat_pfx_filter++;
d62a17ae 3896 reason = "filter;";
3897 goto filtered;
3898 }
718e3744 3899
a8b72dc6
DA
3900 /* RFC 8212 to prevent route leaks.
3901 * This specification intends to improve this situation by requiring the
3902 * explicit configuration of both BGP Import and Export Policies for any
3903 * External BGP (EBGP) session such as customers, peers, or
3904 * confederation boundaries for all enabled address families. Through
3905 * codification of the aforementioned requirement, operators will
3906 * benefit from consistent behavior across different BGP
3907 * implementations.
3908 */
1d3fdccf 3909 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3910 if (!bgp_inbound_policy_exists(peer,
3911 &peer->filter[afi][safi])) {
3912 reason = "inbound policy missing";
b17826b7
DS
3913 if (monotime_since(&bgp->ebgprequirespolicywarning,
3914 NULL) > FIFTEENMINUTE2USEC ||
3915 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3916 zlog_warn(
3917 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3918 monotime(&bgp->ebgprequirespolicywarning);
3919 }
a8b72dc6
DA
3920 goto filtered;
3921 }
3922
fb29348a
DA
3923 /* draft-ietf-idr-deprecate-as-set-confed-set
3924 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3925 * Eventually, This document (if approved) updates RFC 4271
3926 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3927 * and obsoletes RFC 6472.
3928 */
7f972cd8 3929 if (peer->bgp->reject_as_sets)
fb29348a
DA
3930 if (aspath_check_as_sets(attr->aspath)) {
3931 reason =
3932 "as-path contains AS_SET or AS_CONFED_SET type;";
3933 goto filtered;
3934 }
3935
6f4f49b2 3936 new_attr = *attr;
d62a17ae 3937
3938 /* Apply incoming route-map.
3939 * NB: new_attr may now contain newly allocated values from route-map
3940 * "set"
3941 * commands, so we need bgp_attr_flush in the error paths, until we
3942 * intern
3943 * the attr (which takes over the memory references) */
907707db 3944 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3945 num_labels, dest)
3946 == RMAP_DENY) {
b4d46cc9 3947 peer->stat_pfx_filter++;
d62a17ae 3948 reason = "route-map;";
3949 bgp_attr_flush(&new_attr);
3950 goto filtered;
3951 }
718e3744 3952
05864da7 3953 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3954 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3955 /* remove from RIB previous entry */
3956 bgp_zebra_withdraw(p, pi, bgp, safi);
3957 }
3958
7f323236
DW
3959 if (peer->sort == BGP_PEER_EBGP) {
3960
2721dd61
DA
3961 /* rfc7999:
3962 * A BGP speaker receiving an announcement tagged with the
3963 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3964 * NO_EXPORT community as defined in RFC1997, or a
3965 * similar community, to prevent propagation of the
3966 * prefix outside the local AS. The community to prevent
3967 * propagation SHOULD be chosen according to the operator's
3968 * routing policy.
3969 */
9a706b42
DA
3970 if (bgp_attr_get_community(&new_attr) &&
3971 community_include(bgp_attr_get_community(&new_attr),
3972 COMMUNITY_BLACKHOLE))
aade37d7 3973 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3974
a4d82a8a
PZ
3975 /* If we receive the graceful-shutdown community from an eBGP
3976 * peer we must lower local-preference */
9a706b42
DA
3977 if (bgp_attr_get_community(&new_attr) &&
3978 community_include(bgp_attr_get_community(&new_attr),
3979 COMMUNITY_GSHUT)) {
7f323236
DW
3980 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3981 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3982
a4d82a8a
PZ
3983 /* If graceful-shutdown is configured then add the GSHUT
3984 * community to all paths received from eBGP peers */
637e5ba4 3985 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3986 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3987 }
3988
949b0f24 3989 if (pi) {
3990 pi_type = pi->type;
3991 pi_sub_type = pi->sub_type;
3992 }
3993
d62a17ae 3994 /* next hop check. */
a4d82a8a 3995 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3996 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3997 &new_attr, dest)) {
b4d46cc9 3998 peer->stat_pfx_nh_invalid++;
d62a17ae 3999 reason = "martian or self next-hop;";
4000 bgp_attr_flush(&new_attr);
4001 goto filtered;
4002 }
718e3744 4003
5c14a191 4004 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4005 peer->stat_pfx_nh_invalid++;
4e802e66 4006 reason = "self mac;";
4dbf2038 4007 bgp_attr_flush(&new_attr);
4e802e66
DS
4008 goto filtered;
4009 }
4010
5a78f2bc
EB
4011 if (bgp_check_role_applicability(afi, safi) &&
4012 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4013 reason = "failing otc validation";
4014 bgp_attr_flush(&new_attr);
4015 goto filtered;
4016 }
a1b773e2
DS
4017 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4018 * condition :
4019 * Suppress fib is enabled
4020 * BGP_OPT_NO_FIB is not enabled
4021 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4022 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4023 */
4024 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4025 && (sub_type == BGP_ROUTE_NORMAL)
4026 && (!bgp_option_check(BGP_OPT_NO_FIB))
4027 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4028 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4029
9cbd06e0
DA
4030 /* If maximum prefix count is configured and current prefix
4031 * count exeed it.
4032 */
4dbf2038
IR
4033 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4034 bgp_attr_flush(&new_attr);
9cbd06e0 4035 return -1;
4dbf2038
IR
4036 }
4037
4038 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4039
d62a17ae 4040 /* If the update is implicit withdraw. */
40381db7
DS
4041 if (pi) {
4042 pi->uptime = bgp_clock();
4043 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4044
9bcb3eef 4045 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4046
d62a17ae 4047 /* Same attribute comes in. */
40381db7 4048 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4049 && same_attr
d62a17ae 4050 && (!has_valid_label
40381db7 4051 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4052 num_labels * sizeof(mpls_label_t))
66ff6089 4053 == 0)) {
b4f7f45b
IR
4054 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4055 BGP_CONFIG_DAMPENING)
d62a17ae 4056 && peer->sort == BGP_PEER_EBGP
40381db7 4057 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4058 if (bgp_debug_update(peer, p, NULL, 1)) {
4059 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4060 afi, safi, prd, p, label,
4061 num_labels, addpath_id ? 1 : 0,
66ff6089 4062 addpath_id, evpn, pfx_buf,
a4d82a8a 4063 sizeof(pfx_buf));
f70c91dc 4064 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4065 pfx_buf);
4066 }
4067
9bcb3eef 4068 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4069 != BGP_DAMP_SUPPRESSED) {
40381db7 4070 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4071 safi);
9bcb3eef 4072 bgp_process(bgp, dest, afi, safi);
d62a17ae 4073 }
4074 } else /* Duplicate - odd */
4075 {
4076 if (bgp_debug_update(peer, p, NULL, 1)) {
4077 if (!peer->rcvd_attr_printed) {
4078 zlog_debug(
f70c91dc
DA
4079 "%pBP rcvd UPDATE w/ attr: %s",
4080 peer,
d62a17ae 4081 peer->rcvd_attr_str);
4082 peer->rcvd_attr_printed = 1;
4083 }
4084
4085 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4086 afi, safi, prd, p, label,
4087 num_labels, addpath_id ? 1 : 0,
66ff6089 4088 addpath_id, evpn, pfx_buf,
a4d82a8a 4089 sizeof(pfx_buf));
d62a17ae 4090 zlog_debug(
f70c91dc
DA
4091 "%pBP rcvd %s...duplicate ignored",
4092 peer, pfx_buf);
d62a17ae 4093 }
4094
4095 /* graceful restart STALE flag unset. */
40381db7 4096 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4097 bgp_path_info_unset_flag(
9bcb3eef
DS
4098 dest, pi, BGP_PATH_STALE);
4099 bgp_dest_set_defer_flag(dest, false);
4100 bgp_process(bgp, dest, afi, safi);
d62a17ae 4101 }
4102 }
4103
9bcb3eef 4104 bgp_dest_unlock_node(dest);
d62a17ae 4105 bgp_attr_unintern(&attr_new);
4106
4107 return 0;
4108 }
718e3744 4109
d62a17ae 4110 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4111 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4112 if (bgp_debug_update(peer, p, NULL, 1)) {
4113 bgp_debug_rdpfxpath2str(
a4d82a8a 4114 afi, safi, prd, p, label, num_labels,
66ff6089 4115 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4116 pfx_buf, sizeof(pfx_buf));
d62a17ae 4117 zlog_debug(
f70c91dc
DA
4118 "%pBP rcvd %s, flapped quicker than processing",
4119 peer, pfx_buf);
d62a17ae 4120 }
4121
9bcb3eef 4122 bgp_path_info_restore(dest, pi);
9146341f 4123
4124 /*
4125 * If the BGP_PATH_REMOVED flag is set, then EVPN
4126 * routes would have been unimported already when a
4127 * prior BGP withdraw processing happened. Such routes
4128 * need to be imported again, so flag accordingly.
4129 */
4130 force_evpn_import = true;
d62a17ae 4131 }
718e3744 4132
d62a17ae 4133 /* Received Logging. */
4134 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4135 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4136 num_labels, addpath_id ? 1 : 0,
66ff6089 4137 addpath_id, evpn, pfx_buf,
a4d82a8a 4138 sizeof(pfx_buf));
f70c91dc 4139 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4140 }
718e3744 4141
d62a17ae 4142 /* graceful restart STALE flag unset. */
f009ff26 4143 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4144 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4145 bgp_dest_set_defer_flag(dest, false);
f009ff26 4146 }
d62a17ae 4147
4148 /* The attribute is changed. */
9bcb3eef 4149 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4150
4151 /* implicit withdraw, decrement aggregate and pcount here.
4152 * only if update is accepted, they'll increment below.
4153 */
40381db7 4154 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4155
4156 /* Update bgp route dampening information. */
b4f7f45b 4157 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4158 && peer->sort == BGP_PEER_EBGP) {
4159 /* This is implicit withdraw so we should update
b4f7f45b
IR
4160 dampening
4161 information. */
40381db7 4162 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4163 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4164 }
49e5a4a0 4165#ifdef ENABLE_BGP_VNC
d62a17ae 4166 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4167 struct bgp_dest *pdest = NULL;
d62a17ae 4168 struct bgp_table *table = NULL;
4169
9bcb3eef
DS
4170 pdest = bgp_node_get(bgp->rib[afi][safi],
4171 (struct prefix *)prd);
4172 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4173 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4174
4175 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4176 bgp, prd, table, p, pi);
d62a17ae 4177 }
9bcb3eef 4178 bgp_dest_unlock_node(pdest);
d62a17ae 4179 }
4180 if ((afi == AFI_IP || afi == AFI_IP6)
4181 && (safi == SAFI_UNICAST)) {
40381db7 4182 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4183 /*
4184 * Implicit withdraw case.
4185 */
4186 ++vnc_implicit_withdraw;
40381db7
DS
4187 vnc_import_bgp_del_route(bgp, p, pi);
4188 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4189 }
4190 }
65efcfce 4191#endif
128ea8ab 4192
d62a17ae 4193 /* Special handling for EVPN update of an existing route. If the
4194 * extended community attribute has changed, we need to
4195 * un-import
4196 * the route using its existing extended community. It will be
4197 * subsequently processed for import with the new extended
4198 * community.
4199 */
6f8c9c11
PR
4200 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4201 && !same_attr) {
40381db7 4202 if ((pi->attr->flag
d62a17ae 4203 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4204 && (attr_new->flag
4205 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4206 int cmp;
4207
b53e67a3
DA
4208 cmp = ecommunity_cmp(
4209 bgp_attr_get_ecommunity(pi->attr),
4210 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4211 if (!cmp) {
4212 if (bgp_debug_update(peer, p, NULL, 1))
4213 zlog_debug(
4214 "Change in EXT-COMM, existing %s new %s",
4215 ecommunity_str(
b53e67a3
DA
4216 bgp_attr_get_ecommunity(
4217 pi->attr)),
d62a17ae 4218 ecommunity_str(
b53e67a3
DA
4219 bgp_attr_get_ecommunity(
4220 attr_new)));
6f8c9c11
PR
4221 if (safi == SAFI_EVPN)
4222 bgp_evpn_unimport_route(
4223 bgp, afi, safi, p, pi);
4224 else /* SAFI_MPLS_VPN */
4225 vpn_leak_to_vrf_withdraw(bgp,
4226 pi);
d62a17ae 4227 }
4228 }
4229 }
718e3744 4230
d62a17ae 4231 /* Update to new attribute. */
40381db7
DS
4232 bgp_attr_unintern(&pi->attr);
4233 pi->attr = attr_new;
d62a17ae 4234
4235 /* Update MPLS label */
4236 if (has_valid_label) {
40381db7 4237 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4238 if (extra->label != label) {
4239 memcpy(&extra->label, label,
dbd587da 4240 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4241 extra->num_labels = num_labels;
4242 }
b57ba6d2
MK
4243 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4244 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4245 }
718e3744 4246
e496b420
HS
4247 /* Update SRv6 SID */
4248 if (attr->srv6_l3vpn) {
4249 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4250 if (sid_diff(&extra->sid[0].sid,
4251 &attr->srv6_l3vpn->sid)) {
4252 sid_copy(&extra->sid[0].sid,
e496b420
HS
4253 &attr->srv6_l3vpn->sid);
4254 extra->num_sids = 1;
cc8f05df 4255
16f3db2d
RS
4256 extra->sid[0].loc_block_len = 0;
4257 extra->sid[0].loc_node_len = 0;
4258 extra->sid[0].func_len = 0;
4259 extra->sid[0].arg_len = 0;
ea7cd161
RS
4260 extra->sid[0].transposition_len = 0;
4261 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4262
4263 if (attr->srv6_l3vpn->loc_block_len != 0) {
4264 extra->sid[0].loc_block_len =
4265 attr->srv6_l3vpn->loc_block_len;
4266 extra->sid[0].loc_node_len =
4267 attr->srv6_l3vpn->loc_node_len;
4268 extra->sid[0].func_len =
4269 attr->srv6_l3vpn->func_len;
4270 extra->sid[0].arg_len =
4271 attr->srv6_l3vpn->arg_len;
ea7cd161 4272 extra->sid[0].transposition_len =
cc8f05df 4273 attr->srv6_l3vpn
ea7cd161
RS
4274 ->transposition_len;
4275 extra->sid[0].transposition_offset =
cc8f05df 4276 attr->srv6_l3vpn
ea7cd161
RS
4277 ->transposition_offset;
4278 }
e496b420
HS
4279 }
4280 } else if (attr->srv6_vpn) {
4281 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4282 if (sid_diff(&extra->sid[0].sid,
4283 &attr->srv6_vpn->sid)) {
4284 sid_copy(&extra->sid[0].sid,
4285 &attr->srv6_vpn->sid);
e496b420
HS
4286 extra->num_sids = 1;
4287 }
4288 }
4289
49e5a4a0 4290#ifdef ENABLE_BGP_VNC
d62a17ae 4291 if ((afi == AFI_IP || afi == AFI_IP6)
4292 && (safi == SAFI_UNICAST)) {
4293 if (vnc_implicit_withdraw) {
4294 /*
4295 * Add back the route with its new attributes
4296 * (e.g., nexthop).
4297 * The route is still selected, until the route
4298 * selection
4299 * queued by bgp_process actually runs. We have
4300 * to make this
4301 * update to the VNC side immediately to avoid
4302 * racing against
4303 * configuration changes (e.g., route-map
4304 * changes) which
4305 * trigger re-importation of the entire RIB.
4306 */
40381db7
DS
4307 vnc_import_bgp_add_route(bgp, p, pi);
4308 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4309 }
4310 }
65efcfce
LB
4311#endif
4312
d62a17ae 4313 /* Update bgp route dampening information. */
b4f7f45b 4314 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4315 && peer->sort == BGP_PEER_EBGP) {
4316 /* Now we do normal update dampening. */
9bcb3eef 4317 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4318 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4319 bgp_dest_unlock_node(dest);
d62a17ae 4320 return 0;
4321 }
4322 }
128ea8ab 4323
d62a17ae 4324 /* Nexthop reachability check - for unicast and
4325 * labeled-unicast.. */
7c312383
AD
4326 if (((afi == AFI_IP || afi == AFI_IP6)
4327 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4328 || (safi == SAFI_EVPN &&
4329 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4330 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4331 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4332 && !CHECK_FLAG(peer->flags,
4333 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4334 && !CHECK_FLAG(bgp->flags,
4335 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4336 connected = 1;
4337 else
4338 connected = 0;
4339
960035b2
PZ
4340 struct bgp *bgp_nexthop = bgp;
4341
40381db7
DS
4342 if (pi->extra && pi->extra->bgp_orig)
4343 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4344
7c312383
AD
4345 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4346
4347 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4348 safi, pi, NULL, connected,
4349 p)
a4d82a8a 4350 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4351 bgp_path_info_set_flag(dest, pi,
4352 BGP_PATH_VALID);
d62a17ae 4353 else {
4354 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4355 zlog_debug("%s(%pI4): NH unresolved",
4356 __func__,
4357 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4358 }
9bcb3eef 4359 bgp_path_info_unset_flag(dest, pi,
18ee8310 4360 BGP_PATH_VALID);
d62a17ae 4361 }
4362 } else
9bcb3eef 4363 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4364
49e5a4a0 4365#ifdef ENABLE_BGP_VNC
d62a17ae 4366 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4367 struct bgp_dest *pdest = NULL;
d62a17ae 4368 struct bgp_table *table = NULL;
4369
9bcb3eef
DS
4370 pdest = bgp_node_get(bgp->rib[afi][safi],
4371 (struct prefix *)prd);
4372 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4373 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4374
4375 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4376 bgp, prd, table, p, pi);
d62a17ae 4377 }
9bcb3eef 4378 bgp_dest_unlock_node(pdest);
d62a17ae 4379 }
4380#endif
718e3744 4381
d62a17ae 4382 /* If this is an EVPN route and some attribute has changed,
9146341f 4383 * or we are explicitly told to perform a route import, process
d62a17ae 4384 * route for import. If the extended community has changed, we
4385 * would
4386 * have done the un-import earlier and the import would result
4387 * in the
4388 * route getting injected into appropriate L2 VNIs. If it is
4389 * just
4390 * some other attribute change, the import will result in
4391 * updating
4392 * the attributes for the route in the VNI(s).
4393 */
9146341f 4394 if (safi == SAFI_EVPN &&
4395 (!same_attr || force_evpn_import) &&
7c312383 4396 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4397 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4398
4399 /* Process change. */
40381db7 4400 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4401
9bcb3eef
DS
4402 bgp_process(bgp, dest, afi, safi);
4403 bgp_dest_unlock_node(dest);
558d1fec 4404
ddb5b488
PZ
4405 if (SAFI_UNICAST == safi
4406 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4407 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4408
40381db7 4409 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4410 }
4411 if ((SAFI_MPLS_VPN == safi)
4412 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4413
a486300b 4414 leak_success = vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4415 }
4416
49e5a4a0 4417#ifdef ENABLE_BGP_VNC
d62a17ae 4418 if (SAFI_MPLS_VPN == safi) {
4419 mpls_label_t label_decoded = decode_label(label);
28070ee3 4420
d62a17ae 4421 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4422 type, sub_type, &label_decoded);
4423 }
4424 if (SAFI_ENCAP == safi) {
4425 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4426 type, sub_type, NULL);
4427 }
28070ee3 4428#endif
a486300b
PG
4429 if ((safi == SAFI_MPLS_VPN) &&
4430 !CHECK_FLAG(bgp->af_flags[afi][safi],
4431 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4432 !leak_success) {
4433 bgp_unlink_nexthop(pi);
4434 bgp_path_info_delete(dest, pi);
4435 }
d62a17ae 4436 return 0;
4437 } // End of implicit withdraw
718e3744 4438
d62a17ae 4439 /* Received Logging. */
4440 if (bgp_debug_update(peer, p, NULL, 1)) {
4441 if (!peer->rcvd_attr_printed) {
f70c91dc 4442 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4443 peer->rcvd_attr_str);
4444 peer->rcvd_attr_printed = 1;
4445 }
718e3744 4446
a4d82a8a 4447 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4448 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4449 pfx_buf, sizeof(pfx_buf));
f70c91dc 4450 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4451 }
718e3744 4452
d62a17ae 4453 /* Make new BGP info. */
9bcb3eef 4454 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4455
d62a17ae 4456 /* Update MPLS label */
4457 if (has_valid_label) {
18ee8310 4458 extra = bgp_path_info_extra_get(new);
8ba71050 4459 if (extra->label != label) {
dbd587da
QY
4460 memcpy(&extra->label, label,
4461 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4462 extra->num_labels = num_labels;
4463 }
b57ba6d2
MK
4464 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4465 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4466 }
718e3744 4467
e496b420
HS
4468 /* Update SRv6 SID */
4469 if (safi == SAFI_MPLS_VPN) {
4470 extra = bgp_path_info_extra_get(new);
4471 if (attr->srv6_l3vpn) {
16f3db2d 4472 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4473 extra->num_sids = 1;
cc8f05df 4474
16f3db2d
RS
4475 extra->sid[0].loc_block_len =
4476 attr->srv6_l3vpn->loc_block_len;
4477 extra->sid[0].loc_node_len =
4478 attr->srv6_l3vpn->loc_node_len;
4479 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4480 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4481 extra->sid[0].transposition_len =
4482 attr->srv6_l3vpn->transposition_len;
4483 extra->sid[0].transposition_offset =
4484 attr->srv6_l3vpn->transposition_offset;
e496b420 4485 } else if (attr->srv6_vpn) {
16f3db2d 4486 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4487 extra->num_sids = 1;
4488 }
4489 }
4490
d62a17ae 4491 /* Nexthop reachability check. */
7c312383
AD
4492 if (((afi == AFI_IP || afi == AFI_IP6)
4493 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4494 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4495 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4496 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4497 && !CHECK_FLAG(peer->flags,
4498 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4499 && !CHECK_FLAG(bgp->flags,
4500 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4501 connected = 1;
4502 else
4503 connected = 0;
4504
7c312383
AD
4505 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4506
4053e952 4507 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4508 connected, p)
a4d82a8a 4509 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4510 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4511 else {
4512 if (BGP_DEBUG(nht, NHT)) {
4513 char buf1[INET6_ADDRSTRLEN];
4514 inet_ntop(AF_INET,
4515 (const void *)&attr_new->nexthop,
4516 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4517 zlog_debug("%s(%s): NH unresolved", __func__,
4518 buf1);
d62a17ae 4519 }
9bcb3eef 4520 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4521 }
4522 } else
9bcb3eef 4523 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4524
d62a17ae 4525 /* Addpath ID */
4526 new->addpath_rx_id = addpath_id;
4527
4528 /* Increment prefix */
4529 bgp_aggregate_increment(bgp, p, new, afi, safi);
4530
4531 /* Register new BGP information. */
9bcb3eef 4532 bgp_path_info_add(dest, new);
d62a17ae 4533
4534 /* route_node_get lock */
9bcb3eef 4535 bgp_dest_unlock_node(dest);
558d1fec 4536
49e5a4a0 4537#ifdef ENABLE_BGP_VNC
d62a17ae 4538 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4539 struct bgp_dest *pdest = NULL;
d62a17ae 4540 struct bgp_table *table = NULL;
4541
9bcb3eef
DS
4542 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4543 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4544 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4545
4546 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4547 bgp, prd, table, p, new);
4548 }
9bcb3eef 4549 bgp_dest_unlock_node(pdest);
d62a17ae 4550 }
65efcfce
LB
4551#endif
4552
d62a17ae 4553 /* If this is an EVPN route, process for import. */
7c312383 4554 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4555 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4556
9bcb3eef 4557 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4558
d62a17ae 4559 /* Process change. */
9bcb3eef 4560 bgp_process(bgp, dest, afi, safi);
718e3744 4561
ddb5b488
PZ
4562 if (SAFI_UNICAST == safi
4563 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4564 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4565 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4566 }
4567 if ((SAFI_MPLS_VPN == safi)
4568 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
a486300b 4569 leak_success = vpn_leak_to_vrf_update(bgp, new);
ddb5b488 4570 }
49e5a4a0 4571#ifdef ENABLE_BGP_VNC
d62a17ae 4572 if (SAFI_MPLS_VPN == safi) {
4573 mpls_label_t label_decoded = decode_label(label);
28070ee3 4574
d62a17ae 4575 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4576 sub_type, &label_decoded);
4577 }
4578 if (SAFI_ENCAP == safi) {
4579 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4580 sub_type, NULL);
4581 }
28070ee3 4582#endif
a486300b
PG
4583 if ((safi == SAFI_MPLS_VPN) &&
4584 !CHECK_FLAG(bgp->af_flags[afi][safi],
4585 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4586 !leak_success) {
4587 bgp_unlink_nexthop(new);
4588 bgp_path_info_delete(dest, new);
4589 }
28070ee3 4590
d62a17ae 4591 return 0;
718e3744 4592
d62a17ae 4593/* This BGP update is filtered. Log the reason then update BGP
4594 entry. */
4595filtered:
9bcb3eef 4596 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4597
d62a17ae 4598 if (bgp_debug_update(peer, p, NULL, 1)) {
4599 if (!peer->rcvd_attr_printed) {
f70c91dc 4600 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4601 peer->rcvd_attr_str);
4602 peer->rcvd_attr_printed = 1;
4603 }
718e3744 4604
a4d82a8a 4605 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4606 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4607 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4608 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4609 peer, pfx_buf, reason);
d62a17ae 4610 }
128ea8ab 4611
40381db7 4612 if (pi) {
d62a17ae 4613 /* If this is an EVPN route, un-import it as it is now filtered.
4614 */
4615 if (safi == SAFI_EVPN)
40381db7 4616 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4617
ddb5b488
PZ
4618 if (SAFI_UNICAST == safi
4619 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4620 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4621
40381db7 4622 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4623 }
4624 if ((SAFI_MPLS_VPN == safi)
4625 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4626
40381db7 4627 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4628 }
4629
9bcb3eef 4630 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4631 }
4632
9bcb3eef 4633 bgp_dest_unlock_node(dest);
558d1fec 4634
49e5a4a0 4635#ifdef ENABLE_BGP_VNC
d62a17ae 4636 /*
4637 * Filtered update is treated as an implicit withdrawal (see
4638 * bgp_rib_remove()
4639 * a few lines above)
4640 */
4641 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4642 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4643 0);
4644 }
97736e32
PZ
4645#endif
4646
d62a17ae 4647 return 0;
718e3744 4648}
4649
26a3ffd6 4650int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4651 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4652 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4653 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4654{
d62a17ae 4655 struct bgp *bgp;
4656 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4657 struct bgp_dest *dest;
40381db7 4658 struct bgp_path_info *pi;
718e3744 4659
49e5a4a0 4660#ifdef ENABLE_BGP_VNC
d62a17ae 4661 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4662 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4663 0);
4664 }
28070ee3
PZ
4665#endif
4666
d62a17ae 4667 bgp = peer->bgp;
4668
4669 /* Lookup node. */
9bcb3eef 4670 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4671
4672 /* If peer is soft reconfiguration enabled. Record input packet for
4673 * further calculation.
4674 *
4675 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4676 * routes that are filtered. This tanks out Quagga RS pretty badly due
4677 * to
4678 * the iteration over all RS clients.
4679 * Since we need to remove the entry from adj_in anyway, do that first
4680 * and
4681 * if there was no entry, we don't need to do anything more.
4682 */
4683 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4684 && peer != bgp->peer_self)
9bcb3eef 4685 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4686 peer->stat_pfx_dup_withdraw++;
4687
d62a17ae 4688 if (bgp_debug_update(peer, p, NULL, 1)) {
4689 bgp_debug_rdpfxpath2str(
a4d82a8a 4690 afi, safi, prd, p, label, num_labels,
6c995628
AD
4691 addpath_id ? 1 : 0, addpath_id, NULL,
4692 pfx_buf, sizeof(pfx_buf));
d62a17ae 4693 zlog_debug(
4694 "%s withdrawing route %s not in adj-in",
4695 peer->host, pfx_buf);
4696 }
9bcb3eef 4697 bgp_dest_unlock_node(dest);
d62a17ae 4698 return 0;
4699 }
cd808e74 4700
d62a17ae 4701 /* Lookup withdrawn route. */
9bcb3eef 4702 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4703 if (pi->peer == peer && pi->type == type
4704 && pi->sub_type == sub_type
4705 && pi->addpath_rx_id == addpath_id)
d62a17ae 4706 break;
4707
4708 /* Logging. */
4709 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4710 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4711 addpath_id ? 1 : 0, addpath_id, NULL,
4712 pfx_buf, sizeof(pfx_buf));
f70c91dc 4713 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4714 pfx_buf);
4715 }
718e3744 4716
d62a17ae 4717 /* Withdraw specified route from routing table. */
40381db7 4718 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4719 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4720 if (SAFI_UNICAST == safi
4721 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4722 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4723 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4724 }
4725 if ((SAFI_MPLS_VPN == safi)
4726 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4727
40381db7 4728 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4729 }
4730 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4731 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4732 addpath_id ? 1 : 0, addpath_id, NULL,
4733 pfx_buf, sizeof(pfx_buf));
d62a17ae 4734 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4735 }
718e3744 4736
d62a17ae 4737 /* Unlock bgp_node_get() lock. */
9bcb3eef 4738 bgp_dest_unlock_node(dest);
d62a17ae 4739
4740 return 0;
718e3744 4741}
6b0655a2 4742
d62a17ae 4743void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4744 int withdraw)
718e3744 4745{
d62a17ae 4746 struct update_subgroup *subgrp;
4747 subgrp = peer_subgroup(peer, afi, safi);
4748 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4749}
6182d65b 4750
718e3744 4751
3f9c7369
DS
4752/*
4753 * bgp_stop_announce_route_timer
4754 */
d62a17ae 4755void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4756{
d62a17ae 4757 if (!paf->t_announce_route)
4758 return;
4759
c3aaa89a 4760 THREAD_OFF(paf->t_announce_route);
718e3744 4761}
6b0655a2 4762
3f9c7369
DS
4763/*
4764 * bgp_announce_route_timer_expired
4765 *
4766 * Callback that is invoked when the route announcement timer for a
4767 * peer_af expires.
4768 */
cc9f21da 4769static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4770{
d62a17ae 4771 struct peer_af *paf;
4772 struct peer *peer;
558d1fec 4773
d62a17ae 4774 paf = THREAD_ARG(t);
4775 peer = paf->peer;
718e3744 4776
feb17238 4777 if (!peer_established(peer))
cc9f21da 4778 return;
3f9c7369 4779
d62a17ae 4780 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4781 return;
3f9c7369 4782
d62a17ae 4783 peer_af_announce_route(paf, 1);
c5aec50b
MK
4784
4785 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4786 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4787}
4788
3f9c7369
DS
4789/*
4790 * bgp_announce_route
4791 *
4792 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4793 *
4794 * if force is true we will force an update even if the update
4795 * limiting code is attempted to kick in.
3f9c7369 4796 */
e1a32ec1 4797void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4798{
4799 struct peer_af *paf;
4800 struct update_subgroup *subgrp;
4801
4802 paf = peer_af_find(peer, afi, safi);
4803 if (!paf)
4804 return;
4805 subgrp = PAF_SUBGRP(paf);
4806
4807 /*
4808 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4809 * or a refresh has already been triggered.
4810 */
4811 if (!subgrp || paf->t_announce_route)
4812 return;
4813
e1a32ec1
DS
4814 if (force)
4815 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4816
d62a17ae 4817 /*
4818 * Start a timer to stagger/delay the announce. This serves
4819 * two purposes - announcement can potentially be combined for
4820 * multiple peers and the announcement doesn't happen in the
4821 * vty context.
4822 */
4823 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4824 (subgrp->peer_count == 1)
4825 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4826 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4827 &paf->t_announce_route);
3f9c7369
DS
4828}
4829
4830/*
4831 * Announce routes from all AF tables to a peer.
4832 *
4833 * This should ONLY be called when there is a need to refresh the
4834 * routes to the peer based on a policy change for this peer alone
4835 * or a route refresh request received from the peer.
4836 * The operation will result in splitting the peer from its existing
4837 * subgroups and putting it in new subgroups.
4838 */
d62a17ae 4839void bgp_announce_route_all(struct peer *peer)
718e3744 4840{
d62a17ae 4841 afi_t afi;
4842 safi_t safi;
4843
05c7a1cc 4844 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4845 bgp_announce_route(peer, afi, safi, false);
718e3744 4846}
6b0655a2 4847
46aeabed
LS
4848/* Flag or unflag bgp_dest to determine whether it should be treated by
4849 * bgp_soft_reconfig_table_task.
4850 * Flag if flag is true. Unflag if flag is false.
4851 */
4852static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4853{
4854 struct bgp_dest *dest;
4855 struct bgp_adj_in *ain;
4856
4857 if (!table)
4858 return;
4859
4860 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4861 for (ain = dest->adj_in; ain; ain = ain->next) {
4862 if (ain->peer != NULL)
4863 break;
4864 }
4865 if (flag && ain != NULL && ain->peer != NULL)
4866 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4867 else
4868 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4869 }
4870}
4871
4872static int bgp_soft_reconfig_table_update(struct peer *peer,
4873 struct bgp_dest *dest,
4874 struct bgp_adj_in *ain, afi_t afi,
4875 safi_t safi, struct prefix_rd *prd)
4876{
4877 struct bgp_path_info *pi;
4878 uint32_t num_labels = 0;
4879 mpls_label_t *label_pnt = NULL;
4880 struct bgp_route_evpn evpn;
4881
4882 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4883 if (pi->peer == peer)
4884 break;
4885
4886 if (pi && pi->extra)
4887 num_labels = pi->extra->num_labels;
4888 if (num_labels)
4889 label_pnt = &pi->extra->label[0];
4890 if (pi)
4891 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4892 sizeof(evpn));
4893 else
4894 memset(&evpn, 0, sizeof(evpn));
4895
4896 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4897 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4898 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4899 &evpn);
4900}
4901
d62a17ae 4902static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4903 struct bgp_table *table,
4904 struct prefix_rd *prd)
718e3744 4905{
d62a17ae 4906 int ret;
9bcb3eef 4907 struct bgp_dest *dest;
d62a17ae 4908 struct bgp_adj_in *ain;
718e3744 4909
d62a17ae 4910 if (!table)
4911 table = peer->bgp->rib[afi][safi];
718e3744 4912
9bcb3eef
DS
4913 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4914 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4915 if (ain->peer != peer)
4916 continue;
8692c506 4917
46aeabed
LS
4918 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4919 afi, safi, prd);
ea47320b
DL
4920
4921 if (ret < 0) {
9bcb3eef 4922 bgp_dest_unlock_node(dest);
ea47320b 4923 return;
d62a17ae 4924 }
4925 }
718e3744 4926}
4927
46aeabed
LS
4928/* Do soft reconfig table per bgp table.
4929 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4930 * when BGP_NODE_SOFT_RECONFIG is set,
4931 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4932 * Schedule a new thread to continue the job.
4933 * Without splitting the full job into several part,
4934 * vtysh waits for the job to finish before responding to a BGP command
4935 */
cc9f21da 4936static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4937{
4938 uint32_t iter, max_iter;
4939 int ret;
4940 struct bgp_dest *dest;
4941 struct bgp_adj_in *ain;
4942 struct peer *peer;
4943 struct bgp_table *table;
4944 struct prefix_rd *prd;
4945 struct listnode *node, *nnode;
4946
4947 table = THREAD_ARG(thread);
4948 prd = NULL;
4949
4950 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4951 if (table->soft_reconfig_init) {
4952 /* first call of the function with a new srta structure.
4953 * Don't do any treatment this time on nodes
4954 * in order vtysh to respond quickly
4955 */
4956 max_iter = 0;
4957 }
4958
4959 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4960 dest = bgp_route_next(dest)) {
4961 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4962 continue;
4963
4964 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4965
4966 for (ain = dest->adj_in; ain; ain = ain->next) {
4967 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4968 nnode, peer)) {
4969 if (ain->peer != peer)
4970 continue;
4971
4972 ret = bgp_soft_reconfig_table_update(
4973 peer, dest, ain, table->afi,
4974 table->safi, prd);
4975 iter++;
4976
4977 if (ret < 0) {
4978 bgp_dest_unlock_node(dest);
4979 listnode_delete(
4980 table->soft_reconfig_peers,
4981 peer);
4982 bgp_announce_route(peer, table->afi,
e1a32ec1 4983 table->safi, false);
46aeabed
LS
4984 if (list_isempty(
4985 table->soft_reconfig_peers)) {
4986 list_delete(
4987 &table->soft_reconfig_peers);
4988 bgp_soft_reconfig_table_flag(
4989 table, false);
cc9f21da 4990 return;
46aeabed
LS
4991 }
4992 }
4993 }
4994 }
4995 }
4996
4997 /* we're either starting the initial iteration,
4998 * or we're going to continue an ongoing iteration
4999 */
5000 if (dest || table->soft_reconfig_init) {
5001 table->soft_reconfig_init = false;
5002 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5003 table, 0, &table->soft_reconfig_thread);
cc9f21da 5004 return;
46aeabed
LS
5005 }
5006 /* we're done, clean up the background iteration context info and
5007 schedule route annoucement
5008 */
5009 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5010 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5011 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5012 }
5013
5014 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5015}
5016
5017
5018/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5019 * and peer.
5020 * - bgp cannot be NULL
5021 * - if table and peer are NULL, cancel all threads within the bgp instance
5022 * - if table is NULL and peer is not,
5023 * remove peer in all threads within the bgp instance
5024 * - if peer is NULL, cancel all threads matching table within the bgp instance
5025 */
5026void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5027 const struct bgp_table *table,
5028 const struct peer *peer)
5029{
5030 struct peer *npeer;
5031 struct listnode *node, *nnode;
5032 int afi, safi;
5033 struct bgp_table *ntable;
5034
5035 if (!bgp)
5036 return;
5037
5038 FOREACH_AFI_SAFI (afi, safi) {
5039 ntable = bgp->rib[afi][safi];
5040 if (!ntable)
5041 continue;
5042 if (table && table != ntable)
5043 continue;
5044
5045 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5046 npeer)) {
5047 if (peer && peer != npeer)
5048 continue;
5049 listnode_delete(ntable->soft_reconfig_peers, npeer);
5050 }
5051
5052 if (!ntable->soft_reconfig_peers
5053 || !list_isempty(ntable->soft_reconfig_peers))
5054 continue;
5055
5056 list_delete(&ntable->soft_reconfig_peers);
5057 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5058 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5059 }
5060}
5061
d62a17ae 5062void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5063{
9bcb3eef 5064 struct bgp_dest *dest;
d62a17ae 5065 struct bgp_table *table;
46aeabed
LS
5066 struct listnode *node, *nnode;
5067 struct peer *npeer;
5068 struct peer_af *paf;
718e3744 5069
feb17238 5070 if (!peer_established(peer))
d62a17ae 5071 return;
718e3744 5072
d62a17ae 5073 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5074 && (safi != SAFI_EVPN)) {
5075 table = peer->bgp->rib[afi][safi];
5076 if (!table)
5077 return;
5078
5079 table->soft_reconfig_init = true;
5080
5081 if (!table->soft_reconfig_peers)
5082 table->soft_reconfig_peers = list_new();
5083 npeer = NULL;
5084 /* add peer to the table soft_reconfig_peers if not already
5085 * there
5086 */
5087 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5088 npeer)) {
5089 if (peer == npeer)
5090 break;
5091 }
5092 if (peer != npeer)
5093 listnode_add(table->soft_reconfig_peers, peer);
5094
5095 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5096 * on table would start back at the beginning.
5097 */
5098 bgp_soft_reconfig_table_flag(table, true);
5099
5100 if (!table->soft_reconfig_thread)
5101 thread_add_event(bm->master,
5102 bgp_soft_reconfig_table_task, table, 0,
5103 &table->soft_reconfig_thread);
5104 /* Cancel bgp_announce_route_timer_expired threads.
5105 * bgp_announce_route_timer_expired threads have been scheduled
5106 * to announce routes as soon as the soft_reconfigure process
5107 * finishes.
5108 * In this case, soft_reconfigure is also scheduled by using
5109 * a thread but is planned after the
5110 * bgp_announce_route_timer_expired threads. It means that,
5111 * without cancelling the threads, the route announcement task
5112 * would run before the soft reconfiguration one. That would
5113 * useless and would block vtysh during several seconds. Route
5114 * announcements are rescheduled as soon as the soft_reconfigure
5115 * process finishes.
5116 */
5117 paf = peer_af_find(peer, afi, safi);
5118 if (paf)
5119 bgp_stop_announce_route_timer(paf);
5120 } else
9bcb3eef
DS
5121 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5122 dest = bgp_route_next(dest)) {
5123 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5124
b54892e0
DS
5125 if (table == NULL)
5126 continue;
8692c506 5127
9bcb3eef 5128 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5129 struct prefix_rd prd;
5130
5131 prd.family = AF_UNSPEC;
5132 prd.prefixlen = 64;
5133 memcpy(&prd.val, p->u.val, 8);
5134
5135 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5136 }
718e3744 5137}
6b0655a2 5138
228da428 5139
d62a17ae 5140struct bgp_clear_node_queue {
9bcb3eef 5141 struct bgp_dest *dest;
228da428
CC
5142};
5143
d62a17ae 5144static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5145{
d62a17ae 5146 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5147 struct bgp_dest *dest = cnq->dest;
d62a17ae 5148 struct peer *peer = wq->spec.data;
40381db7 5149 struct bgp_path_info *pi;
3103e8d2 5150 struct bgp *bgp;
9bcb3eef
DS
5151 afi_t afi = bgp_dest_table(dest)->afi;
5152 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5153
9bcb3eef 5154 assert(dest && peer);
3103e8d2 5155 bgp = peer->bgp;
d62a17ae 5156
5157 /* It is possible that we have multiple paths for a prefix from a peer
5158 * if that peer is using AddPath.
5159 */
9bcb3eef 5160 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5161 if (pi->peer != peer)
ea47320b
DL
5162 continue;
5163
5164 /* graceful restart STALE flag set. */
9af52ccf
DA
5165 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5166 && peer->nsf[afi][safi])
5167 || CHECK_FLAG(peer->af_sflags[afi][safi],
5168 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5169 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5170 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5171 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5172 else {
5173 /* If this is an EVPN route, process for
5174 * un-import. */
5175 if (safi == SAFI_EVPN)
9bcb3eef
DS
5176 bgp_evpn_unimport_route(
5177 bgp, afi, safi,
5178 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5179 /* Handle withdraw for VRF route-leaking and L3VPN */
5180 if (SAFI_UNICAST == safi
5181 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5182 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5183 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5184 bgp, pi);
960035b2 5185 }
3103e8d2 5186 if (SAFI_MPLS_VPN == safi &&
960035b2 5187 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5188 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5189 }
3103e8d2 5190
9bcb3eef 5191 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5192 }
ea47320b 5193 }
d62a17ae 5194 return WQ_SUCCESS;
200df115 5195}
5196
d62a17ae 5197static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5198{
d62a17ae 5199 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5200 struct bgp_dest *dest = cnq->dest;
5201 struct bgp_table *table = bgp_dest_table(dest);
228da428 5202
9bcb3eef 5203 bgp_dest_unlock_node(dest);
d62a17ae 5204 bgp_table_unlock(table);
5205 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5206}
5207
d62a17ae 5208static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5209{
d62a17ae 5210 struct peer *peer = wq->spec.data;
64e580a7 5211
d62a17ae 5212 /* Tickle FSM to start moving again */
5213 BGP_EVENT_ADD(peer, Clearing_Completed);
5214
5215 peer_unlock(peer); /* bgp_clear_route */
200df115 5216}
718e3744 5217
d62a17ae 5218static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5219{
d62a17ae 5220 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5221
5222 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5223#undef CLEAR_QUEUE_NAME_LEN
5224
0ce1ca80 5225 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5226 peer->clear_node_queue->spec.hold = 10;
5227 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5228 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5229 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5230 peer->clear_node_queue->spec.max_retries = 0;
5231
5232 /* we only 'lock' this peer reference when the queue is actually active
5233 */
5234 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5235}
5236
d62a17ae 5237static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5238 struct bgp_table *table)
65ca75e0 5239{
9bcb3eef 5240 struct bgp_dest *dest;
b6c386bb 5241 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5242
d62a17ae 5243 if (!table)
5244 table = peer->bgp->rib[afi][safi];
dc83d712 5245
d62a17ae 5246 /* If still no table => afi/safi isn't configured at all or smth. */
5247 if (!table)
5248 return;
dc83d712 5249
9bcb3eef 5250 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5251 struct bgp_path_info *pi, *next;
d62a17ae 5252 struct bgp_adj_in *ain;
5253 struct bgp_adj_in *ain_next;
5254
5255 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5256 * queued for every clearing peer, regardless of whether it is
5257 * relevant to the peer at hand.
5258 *
5259 * Overview: There are 3 different indices which need to be
5260 * scrubbed, potentially, when a peer is removed:
5261 *
5262 * 1 peer's routes visible via the RIB (ie accepted routes)
5263 * 2 peer's routes visible by the (optional) peer's adj-in index
5264 * 3 other routes visible by the peer's adj-out index
5265 *
5266 * 3 there is no hurry in scrubbing, once the struct peer is
5267 * removed from bgp->peer, we could just GC such deleted peer's
5268 * adj-outs at our leisure.
5269 *
5270 * 1 and 2 must be 'scrubbed' in some way, at least made
5271 * invisible via RIB index before peer session is allowed to be
5272 * brought back up. So one needs to know when such a 'search' is
5273 * complete.
5274 *
5275 * Ideally:
5276 *
5277 * - there'd be a single global queue or a single RIB walker
5278 * - rather than tracking which route_nodes still need to be
5279 * examined on a peer basis, we'd track which peers still
5280 * aren't cleared
5281 *
5282 * Given that our per-peer prefix-counts now should be reliable,
5283 * this may actually be achievable. It doesn't seem to be a huge
5284 * problem at this time,
5285 *
5286 * It is possible that we have multiple paths for a prefix from
5287 * a peer
5288 * if that peer is using AddPath.
5289 */
9bcb3eef 5290 ain = dest->adj_in;
d62a17ae 5291 while (ain) {
5292 ain_next = ain->next;
5293
6a840fd9 5294 if (ain->peer == peer)
9bcb3eef 5295 bgp_adj_in_remove(dest, ain);
d62a17ae 5296
5297 ain = ain_next;
5298 }
5299
9bcb3eef 5300 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5301 next = pi->next;
5302 if (pi->peer != peer)
d62a17ae 5303 continue;
5304
5305 if (force)
9bcb3eef 5306 bgp_path_info_reap(dest, pi);
d62a17ae 5307 else {
5308 struct bgp_clear_node_queue *cnq;
5309
5310 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5311 bgp_table_lock(bgp_dest_table(dest));
5312 bgp_dest_lock_node(dest);
d62a17ae 5313 cnq = XCALLOC(
5314 MTYPE_BGP_CLEAR_NODE_QUEUE,
5315 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5316 cnq->dest = dest;
d62a17ae 5317 work_queue_add(peer->clear_node_queue, cnq);
5318 break;
5319 }
5320 }
5321 }
5322 return;
5323}
5324
5325void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5326{
9bcb3eef 5327 struct bgp_dest *dest;
d62a17ae 5328 struct bgp_table *table;
5329
5330 if (peer->clear_node_queue == NULL)
5331 bgp_clear_node_queue_init(peer);
5332
5333 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5334 * Idle until it receives a Clearing_Completed event. This protects
5335 * against peers which flap faster than we can we clear, which could
5336 * lead to:
5337 *
5338 * a) race with routes from the new session being installed before
5339 * clear_route_node visits the node (to delete the route of that
5340 * peer)
5341 * b) resource exhaustion, clear_route_node likely leads to an entry
5342 * on the process_main queue. Fast-flapping could cause that queue
5343 * to grow and grow.
5344 */
5345
5346 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5347 * the unlock will happen upon work-queue completion; other wise, the
5348 * unlock happens at the end of this function.
5349 */
5350 if (!peer->clear_node_queue->thread)
5351 peer_lock(peer);
5352
5353 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5354 bgp_clear_route_table(peer, afi, safi, NULL);
5355 else
9bcb3eef
DS
5356 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5357 dest = bgp_route_next(dest)) {
5358 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5359 if (!table)
5360 continue;
5361
5362 bgp_clear_route_table(peer, afi, safi, table);
5363 }
d62a17ae 5364
5365 /* unlock if no nodes got added to the clear-node-queue. */
5366 if (!peer->clear_node_queue->thread)
5367 peer_unlock(peer);
718e3744 5368}
d62a17ae 5369
5370void bgp_clear_route_all(struct peer *peer)
718e3744 5371{
d62a17ae 5372 afi_t afi;
5373 safi_t safi;
718e3744 5374
05c7a1cc
QY
5375 FOREACH_AFI_SAFI (afi, safi)
5376 bgp_clear_route(peer, afi, safi);
65efcfce 5377
49e5a4a0 5378#ifdef ENABLE_BGP_VNC
d62a17ae 5379 rfapiProcessPeerDown(peer);
65efcfce 5380#endif
718e3744 5381}
5382
d62a17ae 5383void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5384{
d62a17ae 5385 struct bgp_table *table;
9bcb3eef 5386 struct bgp_dest *dest;
d62a17ae 5387 struct bgp_adj_in *ain;
5388 struct bgp_adj_in *ain_next;
718e3744 5389
d62a17ae 5390 table = peer->bgp->rib[afi][safi];
718e3744 5391
d62a17ae 5392 /* It is possible that we have multiple paths for a prefix from a peer
5393 * if that peer is using AddPath.
5394 */
9bcb3eef
DS
5395 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5396 ain = dest->adj_in;
43143c8f 5397
d62a17ae 5398 while (ain) {
5399 ain_next = ain->next;
43143c8f 5400
6a840fd9 5401 if (ain->peer == peer)
9bcb3eef 5402 bgp_adj_in_remove(dest, ain);
43143c8f 5403
d62a17ae 5404 ain = ain_next;
5405 }
5406 }
718e3744 5407}
93406d87 5408
1479ed2f
DA
5409/* If any of the routes from the peer have been marked with the NO_LLGR
5410 * community, either as sent by the peer, or as the result of a configured
5411 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5412 * operation of [RFC4271].
5413 */
d62a17ae 5414void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5415{
9bcb3eef 5416 struct bgp_dest *dest;
40381db7 5417 struct bgp_path_info *pi;
d62a17ae 5418 struct bgp_table *table;
5419
9af52ccf 5420 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5421 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5422 dest = bgp_route_next(dest)) {
5423 struct bgp_dest *rm;
d62a17ae 5424
5425 /* look for neighbor in tables */
9bcb3eef 5426 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5427 if (!table)
ea47320b
DL
5428 continue;
5429
5430 for (rm = bgp_table_top(table); rm;
5431 rm = bgp_route_next(rm))
9bcb3eef 5432 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5433 pi = pi->next) {
40381db7 5434 if (pi->peer != peer)
ea47320b 5435 continue;
1479ed2f
DA
5436 if (CHECK_FLAG(
5437 peer->af_sflags[afi][safi],
5438 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5439 bgp_attr_get_community(pi->attr) &&
1479ed2f 5440 !community_include(
9a706b42
DA
5441 bgp_attr_get_community(
5442 pi->attr),
1479ed2f 5443 COMMUNITY_NO_LLGR))
e3015d91 5444 continue;
40381db7 5445 if (!CHECK_FLAG(pi->flags,
1defdda8 5446 BGP_PATH_STALE))
e3015d91 5447 continue;
ea47320b 5448
641065d4
KM
5449 /*
5450 * If this is VRF leaked route
5451 * process for withdraw.
5452 */
5453 if (pi->sub_type ==
5454 BGP_ROUTE_IMPORTED &&
5455 peer->bgp->inst_type ==
5456 BGP_INSTANCE_TYPE_DEFAULT)
5457 vpn_leak_to_vrf_withdraw(
5458 peer->bgp, pi);
5459
40381db7 5460 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5461 break;
5462 }
d62a17ae 5463 }
5464 } else {
9bcb3eef
DS
5465 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5466 dest = bgp_route_next(dest))
5467 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5468 pi = pi->next) {
40381db7 5469 if (pi->peer != peer)
ea47320b 5470 continue;
1479ed2f
DA
5471 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5472 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5473 bgp_attr_get_community(pi->attr) &&
5474 !community_include(
5475 bgp_attr_get_community(pi->attr),
5476 COMMUNITY_NO_LLGR))
e3015d91 5477 continue;
40381db7 5478 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5479 continue;
641065d4
KM
5480 if (safi == SAFI_UNICAST &&
5481 (peer->bgp->inst_type ==
5482 BGP_INSTANCE_TYPE_VRF ||
5483 peer->bgp->inst_type ==
5484 BGP_INSTANCE_TYPE_DEFAULT))
5485 vpn_leak_from_vrf_withdraw(
5486 bgp_get_default(), peer->bgp,
5487 pi);
5488
9bcb3eef 5489 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5490 break;
5491 }
d62a17ae 5492 }
93406d87 5493}
6b0655a2 5494
9af52ccf
DA
5495void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5496{
5497 struct bgp_dest *dest, *ndest;
5498 struct bgp_path_info *pi;
5499 struct bgp_table *table;
5500
5501 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5502 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5503 dest = bgp_route_next(dest)) {
5504 table = bgp_dest_get_bgp_table_info(dest);
5505 if (!table)
5506 continue;
5507
5508 for (ndest = bgp_table_top(table); ndest;
5509 ndest = bgp_route_next(ndest)) {
5510 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5511 pi = pi->next) {
5512 if (pi->peer != peer)
5513 continue;
5514
5515 if ((CHECK_FLAG(
5516 peer->af_sflags[afi][safi],
5517 PEER_STATUS_ENHANCED_REFRESH))
5518 && !CHECK_FLAG(pi->flags,
5519 BGP_PATH_STALE)
5520 && !CHECK_FLAG(
5521 pi->flags,
5522 BGP_PATH_UNUSEABLE)) {
5523 if (bgp_debug_neighbor_events(
5524 peer))
5525 zlog_debug(
5526 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5527 peer->host,
5528 afi2str(afi),
5529 safi2str(safi),
5530 bgp_dest_get_prefix(
5531 ndest));
5532
5533 bgp_path_info_set_flag(
5534 ndest, pi,
5535 BGP_PATH_STALE);
5536 }
5537 }
5538 }
5539 }
5540 } else {
5541 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5542 dest = bgp_route_next(dest)) {
5543 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5544 pi = pi->next) {
5545 if (pi->peer != peer)
5546 continue;
5547
5548 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5549 PEER_STATUS_ENHANCED_REFRESH))
5550 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5551 && !CHECK_FLAG(pi->flags,
5552 BGP_PATH_UNUSEABLE)) {
5553 if (bgp_debug_neighbor_events(peer))
5554 zlog_debug(
5555 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5556 peer->host,
5557 afi2str(afi),
5558 safi2str(safi),
5559 bgp_dest_get_prefix(
5560 dest));
5561
5562 bgp_path_info_set_flag(dest, pi,
5563 BGP_PATH_STALE);
5564 }
5565 }
5566 }
5567 }
5568}
5569
3dc339cd 5570bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5571{
e0df4c04 5572 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5573 return true;
e0df4c04 5574
9dac9fc8
DA
5575 if (peer->sort == BGP_PEER_EBGP
5576 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5577 || FILTER_LIST_OUT_NAME(filter)
5578 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5579 return true;
5580 return false;
9dac9fc8
DA
5581}
5582
3dc339cd 5583bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5584{
e0df4c04 5585 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5586 return true;
e0df4c04 5587
9dac9fc8
DA
5588 if (peer->sort == BGP_PEER_EBGP
5589 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5590 || FILTER_LIST_IN_NAME(filter)
5591 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5592 return true;
5593 return false;
9dac9fc8
DA
5594}
5595
568e10ca 5596static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5597 safi_t safi)
bb86c601 5598{
9bcb3eef 5599 struct bgp_dest *dest;
40381db7 5600 struct bgp_path_info *pi;
4b7e6066 5601 struct bgp_path_info *next;
bb86c601 5602
9bcb3eef
DS
5603 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5604 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5605 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5606
40381db7 5607 next = pi->next;
1b7bb747
CS
5608
5609 /* Unimport EVPN routes from VRFs */
5610 if (safi == SAFI_EVPN)
5611 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5612 SAFI_EVPN, p, pi);
1b7bb747 5613
40381db7
DS
5614 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5615 && pi->type == ZEBRA_ROUTE_BGP
5616 && (pi->sub_type == BGP_ROUTE_NORMAL
5617 || pi->sub_type == BGP_ROUTE_AGGREGATE
5618 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5619
d62a17ae 5620 if (bgp_fibupd_safi(safi))
b54892e0 5621 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5622 }
9514b37d 5623
9bcb3eef 5624 bgp_path_info_reap(dest, pi);
d62a17ae 5625 }
bb86c601
LB
5626}
5627
718e3744 5628/* Delete all kernel routes. */
d62a17ae 5629void bgp_cleanup_routes(struct bgp *bgp)
5630{
5631 afi_t afi;
9bcb3eef 5632 struct bgp_dest *dest;
67009e22 5633 struct bgp_table *table;
d62a17ae 5634
5635 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5636 if (afi == AFI_L2VPN)
5637 continue;
568e10ca 5638 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5639 SAFI_UNICAST);
d62a17ae 5640 /*
5641 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5642 */
5643 if (afi != AFI_L2VPN) {
5644 safi_t safi;
5645 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5646 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5647 dest = bgp_route_next(dest)) {
5648 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5649 if (table != NULL) {
5650 bgp_cleanup_table(bgp, table, safi);
5651 bgp_table_finish(&table);
9bcb3eef
DS
5652 bgp_dest_set_bgp_table_info(dest, NULL);
5653 bgp_dest_unlock_node(dest);
d62a17ae 5654 }
5655 }
5656 safi = SAFI_ENCAP;
9bcb3eef
DS
5657 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5658 dest = bgp_route_next(dest)) {
5659 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5660 if (table != NULL) {
5661 bgp_cleanup_table(bgp, table, safi);
5662 bgp_table_finish(&table);
9bcb3eef
DS
5663 bgp_dest_set_bgp_table_info(dest, NULL);
5664 bgp_dest_unlock_node(dest);
d62a17ae 5665 }
5666 }
5667 }
5668 }
9bcb3eef
DS
5669 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5670 dest = bgp_route_next(dest)) {
5671 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5672 if (table != NULL) {
5673 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5674 bgp_table_finish(&table);
9bcb3eef
DS
5675 bgp_dest_set_bgp_table_info(dest, NULL);
5676 bgp_dest_unlock_node(dest);
d62a17ae 5677 }
bb86c601 5678 }
718e3744 5679}
5680
d62a17ae 5681void bgp_reset(void)
718e3744 5682{
d62a17ae 5683 vty_reset();
5684 bgp_zclient_reset();
5685 access_list_reset();
5686 prefix_list_reset();
718e3744 5687}
6b0655a2 5688
be92fc9f 5689bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5690{
d62a17ae 5691 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5692 && CHECK_FLAG(peer->af_cap[afi][safi],
5693 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5694}
5695
718e3744 5696/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5697 value. */
d62a17ae 5698int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5699 struct bgp_nlri *packet)
5700{
d7c0a89a
QY
5701 uint8_t *pnt;
5702 uint8_t *lim;
d62a17ae 5703 struct prefix p;
5704 int psize;
5705 int ret;
5706 afi_t afi;
5707 safi_t safi;
be92fc9f 5708 bool addpath_capable;
d7c0a89a 5709 uint32_t addpath_id;
d62a17ae 5710
d62a17ae 5711 pnt = packet->nlri;
5712 lim = pnt + packet->length;
5713 afi = packet->afi;
5714 safi = packet->safi;
5715 addpath_id = 0;
be92fc9f 5716 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5717
5718 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5719 syntactic validity. If the field is syntactically incorrect,
5720 then the Error Subcode is set to Invalid Network Field. */
5721 for (; pnt < lim; pnt += psize) {
5722 /* Clear prefix structure. */
6006b807 5723 memset(&p, 0, sizeof(p));
d62a17ae 5724
be92fc9f 5725 if (addpath_capable) {
d62a17ae 5726
5727 /* When packet overflow occurs return immediately. */
761ed665 5728 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5729 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5730
a3a850a1 5731 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5732 addpath_id = ntohl(addpath_id);
d62a17ae 5733 pnt += BGP_ADDPATH_ID_LEN;
5734 }
718e3744 5735
d62a17ae 5736 /* Fetch prefix length. */
5737 p.prefixlen = *pnt++;
5738 /* afi/safi validity already verified by caller,
5739 * bgp_update_receive */
5740 p.family = afi2family(afi);
5741
5742 /* Prefix length check. */
5743 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5744 flog_err(
e50f7cfd 5745 EC_BGP_UPDATE_RCV,
14454c9f 5746 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5747 peer->host, p.prefixlen, packet->afi);
513386b5 5748 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5749 }
6b0655a2 5750
d62a17ae 5751 /* Packet size overflow check. */
5752 psize = PSIZE(p.prefixlen);
5753
5754 /* When packet overflow occur return immediately. */
5755 if (pnt + psize > lim) {
af4c2728 5756 flog_err(
e50f7cfd 5757 EC_BGP_UPDATE_RCV,
d62a17ae 5758 "%s [Error] Update packet error (prefix length %d overflows packet)",
5759 peer->host, p.prefixlen);
513386b5 5760 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5761 }
5762
5763 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5764 * prefix for the v4 and v6 afi's and unicast/multicast */
5765 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5766 flog_err(
e50f7cfd 5767 EC_BGP_UPDATE_RCV,
d62a17ae 5768 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5769 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5770 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5771 }
5772
5773 /* Fetch prefix from NLRI packet. */
a85297a7 5774 memcpy(p.u.val, pnt, psize);
d62a17ae 5775
5776 /* Check address. */
5777 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5778 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5779 /* From RFC4271 Section 6.3:
5780 *
5781 * If a prefix in the NLRI field is semantically
5782 * incorrect
5783 * (e.g., an unexpected multicast IP address),
5784 * an error SHOULD
5785 * be logged locally, and the prefix SHOULD be
5786 * ignored.
a4d82a8a 5787 */
af4c2728 5788 flog_err(
e50f7cfd 5789 EC_BGP_UPDATE_RCV,
23d0a753
DA
5790 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5791 peer->host, &p.u.prefix4);
d62a17ae 5792 continue;
5793 }
5794 }
5795
5796 /* Check address. */
5797 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5798 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5799 flog_err(
e50f7cfd 5800 EC_BGP_UPDATE_RCV,
c0d72166
DS
5801 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5802 peer->host, &p.u.prefix6);
d62a17ae 5803
5804 continue;
5805 }
5806 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5807 flog_err(
e50f7cfd 5808 EC_BGP_UPDATE_RCV,
c0d72166
DS
5809 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5810 peer->host, &p.u.prefix6);
d62a17ae 5811
5812 continue;
5813 }
5814 }
5815
5816 /* Normal process. */
5817 if (attr)
5818 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5819 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5820 NULL, NULL, 0, 0, NULL);
d62a17ae 5821 else
5822 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5823 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5824 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5825 NULL);
d62a17ae 5826
513386b5
DA
5827 /* Do not send BGP notification twice when maximum-prefix count
5828 * overflow. */
5829 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5830 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5831
5832 /* Address family configuration mismatch. */
d62a17ae 5833 if (ret < 0)
513386b5 5834 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5835 }
5836
5837 /* Packet length consistency check. */
5838 if (pnt != lim) {
af4c2728 5839 flog_err(
e50f7cfd 5840 EC_BGP_UPDATE_RCV,
d62a17ae 5841 "%s [Error] Update packet error (prefix length mismatch with total length)",
5842 peer->host);
513386b5 5843 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5844 }
6b0655a2 5845
513386b5 5846 return BGP_NLRI_PARSE_OK;
718e3744 5847}
5848
d62a17ae 5849static struct bgp_static *bgp_static_new(void)
718e3744 5850{
d62a17ae 5851 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5852}
5853
d62a17ae 5854static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5855{
0a22ddfb 5856 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5857 route_map_counter_decrement(bgp_static->rmap.map);
5858
0a22ddfb 5859 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5860 XFREE(MTYPE_BGP_STATIC, bgp_static);
5861}
5862
5f040085 5863void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5864 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5865{
9bcb3eef 5866 struct bgp_dest *dest;
40381db7 5867 struct bgp_path_info *pi;
4b7e6066 5868 struct bgp_path_info *new;
40381db7 5869 struct bgp_path_info rmap_path;
d62a17ae 5870 struct attr attr;
5871 struct attr *attr_new;
b68885f9 5872 route_map_result_t ret;
49e5a4a0 5873#ifdef ENABLE_BGP_VNC
d62a17ae 5874 int vnc_implicit_withdraw = 0;
65efcfce 5875#endif
fee0f4c6 5876
d62a17ae 5877 assert(bgp_static);
dd8103a9 5878
9bcb3eef 5879 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5880
0f05ea43 5881 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5882
d62a17ae 5883 attr.nexthop = bgp_static->igpnexthop;
5884 attr.med = bgp_static->igpmetric;
5885 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5886
d62a17ae 5887 if (bgp_static->atomic)
5888 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5889
d62a17ae 5890 /* Store label index, if required. */
5891 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5892 attr.label_index = bgp_static->label_index;
5893 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5894 }
718e3744 5895
d62a17ae 5896 /* Apply route-map. */
5897 if (bgp_static->rmap.name) {
5898 struct attr attr_tmp = attr;
80ced710 5899
6006b807 5900 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5901 rmap_path.peer = bgp->peer_self;
5902 rmap_path.attr = &attr_tmp;
fee0f4c6 5903
d62a17ae 5904 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5905
1782514f 5906 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5907
d62a17ae 5908 bgp->peer_self->rmap_type = 0;
718e3744 5909
d62a17ae 5910 if (ret == RMAP_DENYMATCH) {
5911 /* Free uninterned attribute. */
5912 bgp_attr_flush(&attr_tmp);
718e3744 5913
d62a17ae 5914 /* Unintern original. */
5915 aspath_unintern(&attr.aspath);
5916 bgp_static_withdraw(bgp, p, afi, safi);
5917 return;
5918 }
7f323236 5919
637e5ba4 5920 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5921 bgp_attr_add_gshut_community(&attr_tmp);
5922
d62a17ae 5923 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5924 } else {
5925
637e5ba4 5926 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5927 bgp_attr_add_gshut_community(&attr);
5928
d62a17ae 5929 attr_new = bgp_attr_intern(&attr);
7f323236 5930 }
718e3744 5931
9bcb3eef 5932 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5933 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5934 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5935 break;
5936
40381db7
DS
5937 if (pi) {
5938 if (attrhash_cmp(pi->attr, attr_new)
5939 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5940 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5941 bgp_dest_unlock_node(dest);
d62a17ae 5942 bgp_attr_unintern(&attr_new);
5943 aspath_unintern(&attr.aspath);
5944 return;
5945 } else {
5946 /* The attribute is changed. */
9bcb3eef 5947 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5948
5949 /* Rewrite BGP route information. */
40381db7 5950 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5951 bgp_path_info_restore(dest, pi);
d62a17ae 5952 else
40381db7 5953 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5954#ifdef ENABLE_BGP_VNC
d62a17ae 5955 if ((afi == AFI_IP || afi == AFI_IP6)
5956 && (safi == SAFI_UNICAST)) {
40381db7 5957 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5958 /*
5959 * Implicit withdraw case.
40381db7 5960 * We have to do this before pi is
d62a17ae 5961 * changed
5962 */
5963 ++vnc_implicit_withdraw;
40381db7 5964 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5965 vnc_import_bgp_exterior_del_route(
40381db7 5966 bgp, p, pi);
d62a17ae 5967 }
5968 }
65efcfce 5969#endif
40381db7
DS
5970 bgp_attr_unintern(&pi->attr);
5971 pi->attr = attr_new;
5972 pi->uptime = bgp_clock();
49e5a4a0 5973#ifdef ENABLE_BGP_VNC
d62a17ae 5974 if ((afi == AFI_IP || afi == AFI_IP6)
5975 && (safi == SAFI_UNICAST)) {
5976 if (vnc_implicit_withdraw) {
40381db7 5977 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5978 vnc_import_bgp_exterior_add_route(
40381db7 5979 bgp, p, pi);
d62a17ae 5980 }
5981 }
65efcfce 5982#endif
718e3744 5983
d62a17ae 5984 /* Nexthop reachability check. */
892fedb6 5985 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5986 && (safi == SAFI_UNICAST
5987 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5988
5989 struct bgp *bgp_nexthop = bgp;
5990
40381db7
DS
5991 if (pi->extra && pi->extra->bgp_orig)
5992 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5993
5994 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5995 afi, safi, pi, NULL,
654a5978 5996 0, p))
9bcb3eef 5997 bgp_path_info_set_flag(dest, pi,
18ee8310 5998 BGP_PATH_VALID);
d62a17ae 5999 else {
6000 if (BGP_DEBUG(nht, NHT)) {
6001 char buf1[INET6_ADDRSTRLEN];
6002 inet_ntop(p->family,
6003 &p->u.prefix, buf1,
6004 INET6_ADDRSTRLEN);
6005 zlog_debug(
6006 "%s(%s): Route not in table, not advertising",
15569c58 6007 __func__, buf1);
d62a17ae 6008 }
18ee8310 6009 bgp_path_info_unset_flag(
9bcb3eef 6010 dest, pi, BGP_PATH_VALID);
d62a17ae 6011 }
6012 } else {
6013 /* Delete the NHT structure if any, if we're
6014 * toggling between
6015 * enabling/disabling import check. We
6016 * deregister the route
6017 * from NHT to avoid overloading NHT and the
6018 * process interaction
6019 */
40381db7 6020 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6021 bgp_path_info_set_flag(dest, pi,
6022 BGP_PATH_VALID);
d62a17ae 6023 }
6024 /* Process change. */
40381db7 6025 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6026 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6027
6028 if (SAFI_UNICAST == safi
6029 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6030 || bgp->inst_type
6031 == BGP_INSTANCE_TYPE_DEFAULT)) {
6032 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6033 pi);
ddb5b488
PZ
6034 }
6035
9bcb3eef 6036 bgp_dest_unlock_node(dest);
d62a17ae 6037 aspath_unintern(&attr.aspath);
6038 return;
6039 }
718e3744 6040 }
718e3744 6041
d62a17ae 6042 /* Make new BGP info. */
6043 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6044 attr_new, dest);
d62a17ae 6045 /* Nexthop reachability check. */
892fedb6 6046 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6047 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6048 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6049 p))
9bcb3eef 6050 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6051 else {
6052 if (BGP_DEBUG(nht, NHT)) {
6053 char buf1[INET6_ADDRSTRLEN];
6054 inet_ntop(p->family, &p->u.prefix, buf1,
6055 INET6_ADDRSTRLEN);
6056 zlog_debug(
6057 "%s(%s): Route not in table, not advertising",
15569c58 6058 __func__, buf1);
d62a17ae 6059 }
9bcb3eef 6060 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6061 }
6062 } else {
6063 /* Delete the NHT structure if any, if we're toggling between
6064 * enabling/disabling import check. We deregister the route
6065 * from NHT to avoid overloading NHT and the process interaction
6066 */
6067 bgp_unlink_nexthop(new);
6068
9bcb3eef 6069 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6070 }
078430f6 6071
d62a17ae 6072 /* Aggregate address increment. */
6073 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6074
d62a17ae 6075 /* Register new BGP information. */
9bcb3eef 6076 bgp_path_info_add(dest, new);
718e3744 6077
d62a17ae 6078 /* route_node_get lock */
9bcb3eef 6079 bgp_dest_unlock_node(dest);
d62a17ae 6080
6081 /* Process change. */
9bcb3eef 6082 bgp_process(bgp, dest, afi, safi);
d62a17ae 6083
ddb5b488
PZ
6084 if (SAFI_UNICAST == safi
6085 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6086 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6087 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6088 }
6089
d62a17ae 6090 /* Unintern original. */
6091 aspath_unintern(&attr.aspath);
718e3744 6092}
6093
5f040085 6094void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6095 safi_t safi)
718e3744 6096{
9bcb3eef 6097 struct bgp_dest *dest;
40381db7 6098 struct bgp_path_info *pi;
718e3744 6099
9bcb3eef 6100 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6101
d62a17ae 6102 /* Check selected route and self inserted route. */
9bcb3eef 6103 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6104 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6105 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6106 break;
6107
6108 /* Withdraw static BGP route from routing table. */
40381db7 6109 if (pi) {
ddb5b488
PZ
6110 if (SAFI_UNICAST == safi
6111 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6112 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6113 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6114 }
40381db7
DS
6115 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6116 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6117 bgp_path_info_delete(dest, pi);
6118 bgp_process(bgp, dest, afi, safi);
d62a17ae 6119 }
718e3744 6120
d62a17ae 6121 /* Unlock bgp_node_lookup. */
9bcb3eef 6122 bgp_dest_unlock_node(dest);
718e3744 6123}
6124
137446f9
LB
6125/*
6126 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6127 */
5f040085 6128static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6129 afi_t afi, safi_t safi,
6130 struct prefix_rd *prd)
718e3744 6131{
9bcb3eef 6132 struct bgp_dest *dest;
40381db7 6133 struct bgp_path_info *pi;
718e3744 6134
9bcb3eef 6135 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6136
d62a17ae 6137 /* Check selected route and self inserted route. */
9bcb3eef 6138 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6139 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6140 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6141 break;
718e3744 6142
d62a17ae 6143 /* Withdraw static BGP route from routing table. */
40381db7 6144 if (pi) {
49e5a4a0 6145#ifdef ENABLE_BGP_VNC
d62a17ae 6146 rfapiProcessWithdraw(
40381db7 6147 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6148 1); /* Kill, since it is an administrative change */
65efcfce 6149#endif
ddb5b488
PZ
6150 if (SAFI_MPLS_VPN == safi
6151 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6152 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6153 }
40381db7 6154 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6155 bgp_path_info_delete(dest, pi);
6156 bgp_process(bgp, dest, afi, safi);
d62a17ae 6157 }
718e3744 6158
d62a17ae 6159 /* Unlock bgp_node_lookup. */
9bcb3eef 6160 bgp_dest_unlock_node(dest);
718e3744 6161}
6162
5f040085 6163static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6164 struct bgp_static *bgp_static, afi_t afi,
6165 safi_t safi)
137446f9 6166{
9bcb3eef 6167 struct bgp_dest *dest;
4b7e6066 6168 struct bgp_path_info *new;
d62a17ae 6169 struct attr *attr_new;
6170 struct attr attr = {0};
40381db7 6171 struct bgp_path_info *pi;
49e5a4a0 6172#ifdef ENABLE_BGP_VNC
d62a17ae 6173 mpls_label_t label = 0;
65efcfce 6174#endif
d7c0a89a 6175 uint32_t num_labels = 0;
137446f9 6176
d62a17ae 6177 assert(bgp_static);
137446f9 6178
b57ba6d2
MK
6179 if (bgp_static->label != MPLS_INVALID_LABEL)
6180 num_labels = 1;
9bcb3eef
DS
6181 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6182 &bgp_static->prd);
137446f9 6183
0f05ea43 6184 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6185
d62a17ae 6186 attr.nexthop = bgp_static->igpnexthop;
6187 attr.med = bgp_static->igpmetric;
6188 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6189
d62a17ae 6190 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6191 || (safi == SAFI_ENCAP)) {
6192 if (afi == AFI_IP) {
6193 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6194 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6195 }
6196 }
6197 if (afi == AFI_L2VPN) {
b04c1e99
IR
6198 if (bgp_static->gatewayIp.family == AF_INET) {
6199 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6200 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6201 &bgp_static->gatewayIp.u.prefix4,
6202 IPV4_MAX_BYTELEN);
b04c1e99
IR
6203 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6204 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6205 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6206 &bgp_static->gatewayIp.u.prefix6,
6207 IPV6_MAX_BYTELEN);
b04c1e99 6208 }
0a50c248 6209 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6210 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6211 struct bgp_encap_type_vxlan bet;
6006b807 6212 memset(&bet, 0, sizeof(bet));
3714a385 6213 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6214 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6215 }
6216 if (bgp_static->router_mac) {
6217 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6218 }
6219 }
6220 /* Apply route-map. */
6221 if (bgp_static->rmap.name) {
6222 struct attr attr_tmp = attr;
40381db7 6223 struct bgp_path_info rmap_path;
b68885f9 6224 route_map_result_t ret;
137446f9 6225
40381db7
DS
6226 rmap_path.peer = bgp->peer_self;
6227 rmap_path.attr = &attr_tmp;
137446f9 6228
d62a17ae 6229 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6230
1782514f 6231 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6232
d62a17ae 6233 bgp->peer_self->rmap_type = 0;
137446f9 6234
d62a17ae 6235 if (ret == RMAP_DENYMATCH) {
6236 /* Free uninterned attribute. */
6237 bgp_attr_flush(&attr_tmp);
137446f9 6238
d62a17ae 6239 /* Unintern original. */
6240 aspath_unintern(&attr.aspath);
6241 bgp_static_withdraw_safi(bgp, p, afi, safi,
6242 &bgp_static->prd);
6243 return;
6244 }
137446f9 6245
d62a17ae 6246 attr_new = bgp_attr_intern(&attr_tmp);
6247 } else {
6248 attr_new = bgp_attr_intern(&attr);
6249 }
137446f9 6250
9bcb3eef 6251 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6252 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6253 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6254 break;
6255
40381db7 6256 if (pi) {
40381db7 6257 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6258 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6259 bgp_dest_unlock_node(dest);
d62a17ae 6260 bgp_attr_unintern(&attr_new);
6261 aspath_unintern(&attr.aspath);
6262 return;
6263 } else {
6264 /* The attribute is changed. */
9bcb3eef 6265 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6266
6267 /* Rewrite BGP route information. */
40381db7 6268 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6269 bgp_path_info_restore(dest, pi);
d62a17ae 6270 else
40381db7
DS
6271 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6272 bgp_attr_unintern(&pi->attr);
6273 pi->attr = attr_new;
6274 pi->uptime = bgp_clock();
49e5a4a0 6275#ifdef ENABLE_BGP_VNC
40381db7
DS
6276 if (pi->extra)
6277 label = decode_label(&pi->extra->label[0]);
65efcfce 6278#endif
137446f9 6279
d62a17ae 6280 /* Process change. */
40381db7 6281 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6282 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6283
6284 if (SAFI_MPLS_VPN == safi
6285 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6286 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6287 }
49e5a4a0 6288#ifdef ENABLE_BGP_VNC
40381db7
DS
6289 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6290 pi->attr, afi, safi, pi->type,
6291 pi->sub_type, &label);
65efcfce 6292#endif
9bcb3eef 6293 bgp_dest_unlock_node(dest);
d62a17ae 6294 aspath_unintern(&attr.aspath);
6295 return;
6296 }
6297 }
137446f9
LB
6298
6299
d62a17ae 6300 /* Make new BGP info. */
6301 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6302 attr_new, dest);
1defdda8 6303 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6304 bgp_path_info_extra_get(new);
b57ba6d2
MK
6305 if (num_labels) {
6306 new->extra->label[0] = bgp_static->label;
6307 new->extra->num_labels = num_labels;
6308 }
49e5a4a0 6309#ifdef ENABLE_BGP_VNC
d62a17ae 6310 label = decode_label(&bgp_static->label);
65efcfce 6311#endif
137446f9 6312
d62a17ae 6313 /* Aggregate address increment. */
6314 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6315
d62a17ae 6316 /* Register new BGP information. */
9bcb3eef 6317 bgp_path_info_add(dest, new);
d62a17ae 6318 /* route_node_get lock */
9bcb3eef 6319 bgp_dest_unlock_node(dest);
137446f9 6320
d62a17ae 6321 /* Process change. */
9bcb3eef 6322 bgp_process(bgp, dest, afi, safi);
137446f9 6323
ddb5b488
PZ
6324 if (SAFI_MPLS_VPN == safi
6325 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6326 vpn_leak_to_vrf_update(bgp, new);
6327 }
49e5a4a0 6328#ifdef ENABLE_BGP_VNC
d62a17ae 6329 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6330 safi, new->type, new->sub_type, &label);
65efcfce
LB
6331#endif
6332
d62a17ae 6333 /* Unintern original. */
6334 aspath_unintern(&attr.aspath);
137446f9
LB
6335}
6336
718e3744 6337/* Configure static BGP network. When user don't run zebra, static
6338 route should be installed as valid. */
585f1adc
IR
6339static int bgp_static_set(struct vty *vty, const char *negate,
6340 const char *ip_str, afi_t afi, safi_t safi,
6341 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6342{
585f1adc
IR
6343 VTY_DECLVAR_CONTEXT(bgp, bgp);
6344 int ret;
d62a17ae 6345 struct prefix p;
6346 struct bgp_static *bgp_static;
9bcb3eef 6347 struct bgp_dest *dest;
d7c0a89a 6348 uint8_t need_update = 0;
d62a17ae 6349
585f1adc
IR
6350 /* Convert IP prefix string to struct prefix. */
6351 ret = str2prefix(ip_str, &p);
6352 if (!ret) {
6353 vty_out(vty, "%% Malformed prefix\n");
6354 return CMD_WARNING_CONFIG_FAILED;
6355 }
6356 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6357 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6358 return CMD_WARNING_CONFIG_FAILED;
6359 }
6360
d62a17ae 6361 apply_mask(&p);
718e3744 6362
e2a86ad9 6363 if (negate) {
718e3744 6364
e2a86ad9 6365 /* Set BGP static route configuration. */
9bcb3eef 6366 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6367
9bcb3eef 6368 if (!dest) {
585f1adc
IR
6369 vty_out(vty, "%% Can't find static route specified\n");
6370 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6371 }
6372
9bcb3eef 6373 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6374
e2a86ad9
DS
6375 if ((label_index != BGP_INVALID_LABEL_INDEX)
6376 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6377 vty_out(vty,
6378 "%% label-index doesn't match static route\n");
70d9b134 6379 bgp_dest_unlock_node(dest);
585f1adc 6380 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6381 }
d62a17ae 6382
e2a86ad9
DS
6383 if ((rmap && bgp_static->rmap.name)
6384 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6385 vty_out(vty,
6386 "%% route-map name doesn't match static route\n");
70d9b134 6387 bgp_dest_unlock_node(dest);
585f1adc 6388 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6389 }
718e3744 6390
e2a86ad9
DS
6391 /* Update BGP RIB. */
6392 if (!bgp_static->backdoor)
6393 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6394
e2a86ad9
DS
6395 /* Clear configuration. */
6396 bgp_static_free(bgp_static);
9bcb3eef
DS
6397 bgp_dest_set_bgp_static_info(dest, NULL);
6398 bgp_dest_unlock_node(dest);
6399 bgp_dest_unlock_node(dest);
e2a86ad9 6400 } else {
718e3744 6401
e2a86ad9 6402 /* Set BGP static route configuration. */
9bcb3eef
DS
6403 dest = bgp_node_get(bgp->route[afi][safi], &p);
6404 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6405 if (bgp_static) {
e2a86ad9 6406 /* Configuration change. */
e2a86ad9
DS
6407 /* Label index cannot be changed. */
6408 if (bgp_static->label_index != label_index) {
585f1adc
IR
6409 vty_out(vty, "%% cannot change label-index\n");
6410 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6411 }
d62a17ae 6412
e2a86ad9 6413 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6414 if (bgp_static->valid
6415 && bgp_static->backdoor != backdoor)
e2a86ad9 6416 need_update = 1;
718e3744 6417
e2a86ad9 6418 bgp_static->backdoor = backdoor;
718e3744 6419
e2a86ad9 6420 if (rmap) {
0a22ddfb
QY
6421 XFREE(MTYPE_ROUTE_MAP_NAME,
6422 bgp_static->rmap.name);
b4897fa5 6423 route_map_counter_decrement(
6424 bgp_static->rmap.map);
e2a86ad9
DS
6425 bgp_static->rmap.name =
6426 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6427 bgp_static->rmap.map =
6428 route_map_lookup_by_name(rmap);
b4897fa5 6429 route_map_counter_increment(
6430 bgp_static->rmap.map);
e2a86ad9 6431 } else {
0a22ddfb
QY
6432 XFREE(MTYPE_ROUTE_MAP_NAME,
6433 bgp_static->rmap.name);
b4897fa5 6434 route_map_counter_decrement(
6435 bgp_static->rmap.map);
e2a86ad9
DS
6436 bgp_static->rmap.map = NULL;
6437 bgp_static->valid = 0;
6438 }
9bcb3eef 6439 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6440 } else {
6441 /* New configuration. */
6442 bgp_static = bgp_static_new();
6443 bgp_static->backdoor = backdoor;
6444 bgp_static->valid = 0;
6445 bgp_static->igpmetric = 0;
975a328e 6446 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6447 bgp_static->label_index = label_index;
718e3744 6448
e2a86ad9 6449 if (rmap) {
0a22ddfb
QY
6450 XFREE(MTYPE_ROUTE_MAP_NAME,
6451 bgp_static->rmap.name);
b4897fa5 6452 route_map_counter_decrement(
6453 bgp_static->rmap.map);
e2a86ad9
DS
6454 bgp_static->rmap.name =
6455 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6456 bgp_static->rmap.map =
6457 route_map_lookup_by_name(rmap);
b4897fa5 6458 route_map_counter_increment(
6459 bgp_static->rmap.map);
e2a86ad9 6460 }
9bcb3eef 6461 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6462 }
d62a17ae 6463
e2a86ad9
DS
6464 bgp_static->valid = 1;
6465 if (need_update)
6466 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6467
e2a86ad9
DS
6468 if (!bgp_static->backdoor)
6469 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6470 }
d62a17ae 6471
585f1adc 6472 return CMD_SUCCESS;
d62a17ae 6473}
6474
6475void bgp_static_add(struct bgp *bgp)
6476{
6477 afi_t afi;
6478 safi_t safi;
9bcb3eef
DS
6479 struct bgp_dest *dest;
6480 struct bgp_dest *rm;
d62a17ae 6481 struct bgp_table *table;
6482 struct bgp_static *bgp_static;
6483
47fc6261 6484 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6485 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6486 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6487 dest = bgp_route_next(dest)) {
6488 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6489 continue;
ea47320b 6490
05c7a1cc
QY
6491 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6492 || (safi == SAFI_EVPN)) {
9bcb3eef 6493 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6494
6495 for (rm = bgp_table_top(table); rm;
6496 rm = bgp_route_next(rm)) {
a78beeb5 6497 bgp_static =
9bcb3eef 6498 bgp_dest_get_bgp_static_info(
5a8ba9fc 6499 rm);
9bcb3eef
DS
6500 bgp_static_update_safi(
6501 bgp, bgp_dest_get_prefix(rm),
6502 bgp_static, afi, safi);
d62a17ae 6503 }
05c7a1cc 6504 } else {
5a8ba9fc 6505 bgp_static_update(
9bcb3eef
DS
6506 bgp, bgp_dest_get_prefix(dest),
6507 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6508 safi);
ea47320b 6509 }
05c7a1cc 6510 }
47fc6261 6511 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6512}
6513
718e3744 6514/* Called from bgp_delete(). Delete all static routes from the BGP
6515 instance. */
d62a17ae 6516void bgp_static_delete(struct bgp *bgp)
6517{
6518 afi_t afi;
6519 safi_t safi;
9bcb3eef
DS
6520 struct bgp_dest *dest;
6521 struct bgp_dest *rm;
d62a17ae 6522 struct bgp_table *table;
6523 struct bgp_static *bgp_static;
6524
05c7a1cc 6525 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6526 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6527 dest = bgp_route_next(dest)) {
6528 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6529 continue;
ea47320b 6530
05c7a1cc
QY
6531 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6532 || (safi == SAFI_EVPN)) {
9bcb3eef 6533 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6534
6535 for (rm = bgp_table_top(table); rm;
6536 rm = bgp_route_next(rm)) {
a78beeb5 6537 bgp_static =
9bcb3eef 6538 bgp_dest_get_bgp_static_info(
5a8ba9fc 6539 rm);
c7d14ba6
PG
6540 if (!bgp_static)
6541 continue;
6542
05c7a1cc 6543 bgp_static_withdraw_safi(
9bcb3eef 6544 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6545 AFI_IP, safi,
6546 (struct prefix_rd *)
9bcb3eef
DS
6547 bgp_dest_get_prefix(
6548 dest));
ea47320b 6549 bgp_static_free(bgp_static);
811c6797 6550 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6551 NULL);
811c6797 6552 bgp_dest_unlock_node(rm);
d62a17ae 6553 }
05c7a1cc 6554 } else {
9bcb3eef 6555 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6556 bgp_static_withdraw(bgp,
9bcb3eef 6557 bgp_dest_get_prefix(dest),
b54892e0 6558 afi, safi);
05c7a1cc 6559 bgp_static_free(bgp_static);
9bcb3eef
DS
6560 bgp_dest_set_bgp_static_info(dest, NULL);
6561 bgp_dest_unlock_node(dest);
ea47320b 6562 }
05c7a1cc 6563 }
d62a17ae 6564}
6565
6566void bgp_static_redo_import_check(struct bgp *bgp)
6567{
6568 afi_t afi;
6569 safi_t safi;
9bcb3eef
DS
6570 struct bgp_dest *dest;
6571 struct bgp_dest *rm;
d62a17ae 6572 struct bgp_table *table;
6573 struct bgp_static *bgp_static;
6574
6575 /* Use this flag to force reprocessing of the route */
892fedb6 6576 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6577 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6578 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6579 dest = bgp_route_next(dest)) {
6580 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6581 continue;
ea47320b 6582
05c7a1cc
QY
6583 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6584 || (safi == SAFI_EVPN)) {
9bcb3eef 6585 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6586
6587 for (rm = bgp_table_top(table); rm;
6588 rm = bgp_route_next(rm)) {
a78beeb5 6589 bgp_static =
9bcb3eef 6590 bgp_dest_get_bgp_static_info(
5a8ba9fc 6591 rm);
9bcb3eef
DS
6592 bgp_static_update_safi(
6593 bgp, bgp_dest_get_prefix(rm),
6594 bgp_static, afi, safi);
d62a17ae 6595 }
05c7a1cc 6596 } else {
9bcb3eef
DS
6597 bgp_static = bgp_dest_get_bgp_static_info(dest);
6598 bgp_static_update(bgp,
6599 bgp_dest_get_prefix(dest),
6600 bgp_static, afi, safi);
ea47320b 6601 }
05c7a1cc
QY
6602 }
6603 }
892fedb6 6604 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6605}
6606
6607static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6608 safi_t safi)
6609{
6610 struct bgp_table *table;
9bcb3eef 6611 struct bgp_dest *dest;
40381db7 6612 struct bgp_path_info *pi;
d62a17ae 6613
dfb6fd1d
NT
6614 /* Do not install the aggregate route if BGP is in the
6615 * process of termination.
6616 */
892fedb6
DA
6617 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6618 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6619 return;
6620
d62a17ae 6621 table = bgp->rib[afi][safi];
9bcb3eef
DS
6622 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6623 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6624 if (pi->peer == bgp->peer_self
6625 && ((pi->type == ZEBRA_ROUTE_BGP
6626 && pi->sub_type == BGP_ROUTE_STATIC)
6627 || (pi->type != ZEBRA_ROUTE_BGP
6628 && pi->sub_type
d62a17ae 6629 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6630 bgp_aggregate_decrement(
6631 bgp, bgp_dest_get_prefix(dest), pi, afi,
6632 safi);
40381db7 6633 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6634 bgp_path_info_delete(dest, pi);
6635 bgp_process(bgp, dest, afi, safi);
d62a17ae 6636 }
6637 }
6638 }
ad4cbda1 6639}
6640
6641/*
6642 * Purge all networks and redistributed routes from routing table.
6643 * Invoked upon the instance going down.
6644 */
d62a17ae 6645void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6646{
d62a17ae 6647 afi_t afi;
6648 safi_t safi;
ad4cbda1 6649
05c7a1cc
QY
6650 FOREACH_AFI_SAFI (afi, safi)
6651 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6652}
6653
137446f9
LB
6654/*
6655 * gpz 110624
6656 * Currently this is used to set static routes for VPN and ENCAP.
6657 * I think it can probably be factored with bgp_static_set.
6658 */
d62a17ae 6659int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6660 const char *ip_str, const char *rd_str,
6661 const char *label_str, const char *rmap_str,
6662 int evpn_type, const char *esi, const char *gwip,
6663 const char *ethtag, const char *routermac)
6664{
6665 VTY_DECLVAR_CONTEXT(bgp, bgp);
6666 int ret;
6667 struct prefix p;
6668 struct prefix_rd prd;
9bcb3eef
DS
6669 struct bgp_dest *pdest;
6670 struct bgp_dest *dest;
d62a17ae 6671 struct bgp_table *table;
6672 struct bgp_static *bgp_static;
6673 mpls_label_t label = MPLS_INVALID_LABEL;
6674 struct prefix gw_ip;
6675
6676 /* validate ip prefix */
6677 ret = str2prefix(ip_str, &p);
6678 if (!ret) {
6679 vty_out(vty, "%% Malformed prefix\n");
6680 return CMD_WARNING_CONFIG_FAILED;
6681 }
6682 apply_mask(&p);
6683 if ((afi == AFI_L2VPN)
6684 && (bgp_build_evpn_prefix(evpn_type,
6685 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6686 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6687 return CMD_WARNING_CONFIG_FAILED;
6688 }
718e3744 6689
d62a17ae 6690 ret = str2prefix_rd(rd_str, &prd);
6691 if (!ret) {
6692 vty_out(vty, "%% Malformed rd\n");
6693 return CMD_WARNING_CONFIG_FAILED;
6694 }
718e3744 6695
d62a17ae 6696 if (label_str) {
6697 unsigned long label_val;
6698 label_val = strtoul(label_str, NULL, 10);
6699 encode_label(label_val, &label);
6700 }
9bedbb1e 6701
d62a17ae 6702 if (safi == SAFI_EVPN) {
6703 if (esi && str2esi(esi, NULL) == 0) {
6704 vty_out(vty, "%% Malformed ESI\n");
6705 return CMD_WARNING_CONFIG_FAILED;
6706 }
6707 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6708 vty_out(vty, "%% Malformed Router MAC\n");
6709 return CMD_WARNING_CONFIG_FAILED;
6710 }
6711 if (gwip) {
6006b807 6712 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6713 ret = str2prefix(gwip, &gw_ip);
6714 if (!ret) {
6715 vty_out(vty, "%% Malformed GatewayIp\n");
6716 return CMD_WARNING_CONFIG_FAILED;
6717 }
6718 if ((gw_ip.family == AF_INET
3714a385 6719 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6720 (struct prefix_evpn *)&p))
6721 || (gw_ip.family == AF_INET6
3714a385 6722 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6723 (struct prefix_evpn *)&p))) {
6724 vty_out(vty,
6725 "%% GatewayIp family differs with IP prefix\n");
6726 return CMD_WARNING_CONFIG_FAILED;
6727 }
6728 }
6729 }
9bcb3eef
DS
6730 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6731 if (!bgp_dest_has_bgp_path_info_data(pdest))
6732 bgp_dest_set_bgp_table_info(pdest,
67009e22 6733 bgp_table_init(bgp, afi, safi));
9bcb3eef 6734 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6735
9bcb3eef 6736 dest = bgp_node_get(table, &p);
d62a17ae 6737
9bcb3eef 6738 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6739 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6740 bgp_dest_unlock_node(dest);
d62a17ae 6741 } else {
6742 /* New configuration. */
6743 bgp_static = bgp_static_new();
6744 bgp_static->backdoor = 0;
6745 bgp_static->valid = 0;
6746 bgp_static->igpmetric = 0;
975a328e 6747 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6748 bgp_static->label = label;
6749 bgp_static->prd = prd;
6750
6751 if (rmap_str) {
0a22ddfb 6752 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6753 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6754 bgp_static->rmap.name =
6755 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6756 bgp_static->rmap.map =
6757 route_map_lookup_by_name(rmap_str);
b4897fa5 6758 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6759 }
718e3744 6760
d62a17ae 6761 if (safi == SAFI_EVPN) {
6762 if (esi) {
6763 bgp_static->eth_s_id =
6764 XCALLOC(MTYPE_ATTR,
0a50c248 6765 sizeof(esi_t));
d62a17ae 6766 str2esi(esi, bgp_static->eth_s_id);
6767 }
6768 if (routermac) {
6769 bgp_static->router_mac =
28328ea9 6770 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6771 (void)prefix_str2mac(routermac,
6772 bgp_static->router_mac);
d62a17ae 6773 }
6774 if (gwip)
6775 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6776 }
9bcb3eef 6777 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6778
d62a17ae 6779 bgp_static->valid = 1;
6780 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6781 }
718e3744 6782
d62a17ae 6783 return CMD_SUCCESS;
718e3744 6784}
6785
6786/* Configure static BGP network. */
d62a17ae 6787int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6788 const char *ip_str, const char *rd_str,
6789 const char *label_str, int evpn_type, const char *esi,
6790 const char *gwip, const char *ethtag)
6791{
6792 VTY_DECLVAR_CONTEXT(bgp, bgp);
6793 int ret;
6794 struct prefix p;
6795 struct prefix_rd prd;
9bcb3eef
DS
6796 struct bgp_dest *pdest;
6797 struct bgp_dest *dest;
d62a17ae 6798 struct bgp_table *table;
6799 struct bgp_static *bgp_static;
6800 mpls_label_t label = MPLS_INVALID_LABEL;
6801
6802 /* Convert IP prefix string to struct prefix. */
6803 ret = str2prefix(ip_str, &p);
6804 if (!ret) {
6805 vty_out(vty, "%% Malformed prefix\n");
6806 return CMD_WARNING_CONFIG_FAILED;
6807 }
6808 apply_mask(&p);
6809 if ((afi == AFI_L2VPN)
6810 && (bgp_build_evpn_prefix(evpn_type,
6811 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6812 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6813 return CMD_WARNING_CONFIG_FAILED;
6814 }
6815 ret = str2prefix_rd(rd_str, &prd);
6816 if (!ret) {
6817 vty_out(vty, "%% Malformed rd\n");
6818 return CMD_WARNING_CONFIG_FAILED;
6819 }
718e3744 6820
d62a17ae 6821 if (label_str) {
6822 unsigned long label_val;
6823 label_val = strtoul(label_str, NULL, 10);
6824 encode_label(label_val, &label);
6825 }
718e3744 6826
9bcb3eef
DS
6827 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6828 if (!bgp_dest_has_bgp_path_info_data(pdest))
6829 bgp_dest_set_bgp_table_info(pdest,
67009e22 6830 bgp_table_init(bgp, afi, safi));
d62a17ae 6831 else
9bcb3eef
DS
6832 bgp_dest_unlock_node(pdest);
6833 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6834
9bcb3eef 6835 dest = bgp_node_lookup(table, &p);
6b0655a2 6836
9bcb3eef 6837 if (dest) {
d62a17ae 6838 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6839
9bcb3eef 6840 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6841 bgp_static_free(bgp_static);
9bcb3eef
DS
6842 bgp_dest_set_bgp_static_info(dest, NULL);
6843 bgp_dest_unlock_node(dest);
6844 bgp_dest_unlock_node(dest);
d62a17ae 6845 } else
6846 vty_out(vty, "%% Can't find the route\n");
6847
6848 return CMD_SUCCESS;
6849}
6850
6851static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6852 const char *rmap_name)
6853{
6854 VTY_DECLVAR_CONTEXT(bgp, bgp);
6855 struct bgp_rmap *rmap;
6856
6857 rmap = &bgp->table_map[afi][safi];
6858 if (rmap_name) {
0a22ddfb 6859 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6860 route_map_counter_decrement(rmap->map);
d62a17ae 6861 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6862 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6863 route_map_counter_increment(rmap->map);
d62a17ae 6864 } else {
0a22ddfb 6865 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6866 route_map_counter_decrement(rmap->map);
d62a17ae 6867 rmap->map = NULL;
6868 }
73ac8160 6869
d62a17ae 6870 if (bgp_fibupd_safi(safi))
6871 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6872
d62a17ae 6873 return CMD_SUCCESS;
73ac8160
DS
6874}
6875
d62a17ae 6876static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6877 const char *rmap_name)
73ac8160 6878{
d62a17ae 6879 VTY_DECLVAR_CONTEXT(bgp, bgp);
6880 struct bgp_rmap *rmap;
73ac8160 6881
d62a17ae 6882 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6883 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6884 route_map_counter_decrement(rmap->map);
d62a17ae 6885 rmap->map = NULL;
73ac8160 6886
d62a17ae 6887 if (bgp_fibupd_safi(safi))
6888 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6889
d62a17ae 6890 return CMD_SUCCESS;
73ac8160
DS
6891}
6892
2b791107 6893void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6894 safi_t safi)
73ac8160 6895{
d62a17ae 6896 if (bgp->table_map[afi][safi].name) {
d62a17ae 6897 vty_out(vty, " table-map %s\n",
6898 bgp->table_map[afi][safi].name);
6899 }
73ac8160
DS
6900}
6901
73ac8160
DS
6902DEFUN (bgp_table_map,
6903 bgp_table_map_cmd,
6904 "table-map WORD",
6905 "BGP table to RIB route download filter\n"
6906 "Name of the route map\n")
6907{
d62a17ae 6908 int idx_word = 1;
6909 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6910 argv[idx_word]->arg);
73ac8160
DS
6911}
6912DEFUN (no_bgp_table_map,
6913 no_bgp_table_map_cmd,
6914 "no table-map WORD",
3a2d747c 6915 NO_STR
73ac8160
DS
6916 "BGP table to RIB route download filter\n"
6917 "Name of the route map\n")
6918{
d62a17ae 6919 int idx_word = 2;
6920 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6921 argv[idx_word]->arg);
73ac8160
DS
6922}
6923
585f1adc
IR
6924DEFPY(bgp_network,
6925 bgp_network_cmd,
6926 "[no] network \
6927 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 6928 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
6929 backdoor$backdoor}]",
6930 NO_STR
6931 "Specify a network to announce via BGP\n"
6932 "IPv4 prefix\n"
6933 "Network number\n"
6934 "Network mask\n"
6935 "Network mask\n"
6936 "Route-map to modify the attributes\n"
6937 "Name of the route map\n"
6938 "Label index to associate with the prefix\n"
6939 "Label index value\n"
6940 "Specify a BGP backdoor route\n")
6941{
6942 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6943
6944 if (address_str) {
6945 int ret;
718e3744 6946
e2a86ad9 6947 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6948 addr_prefix_str,
6949 sizeof(addr_prefix_str));
e2a86ad9
DS
6950 if (!ret) {
6951 vty_out(vty, "%% Inconsistent address and mask\n");
6952 return CMD_WARNING_CONFIG_FAILED;
6953 }
d62a17ae 6954 }
718e3744 6955
585f1adc
IR
6956 return bgp_static_set(
6957 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6958 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6959 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6960}
6961
585f1adc
IR
6962DEFPY(ipv6_bgp_network,
6963 ipv6_bgp_network_cmd,
6964 "[no] network X:X::X:X/M$prefix \
70dd370f 6965 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
6966 NO_STR
6967 "Specify a network to announce via BGP\n"
6968 "IPv6 prefix\n"
6969 "Route-map to modify the attributes\n"
6970 "Name of the route map\n"
6971 "Label index to associate with the prefix\n"
6972 "Label index value\n")
37a87b8f 6973{
585f1adc
IR
6974 return bgp_static_set(
6975 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6976 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6977}
6978
d62a17ae 6979static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6980{
d62a17ae 6981 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6982}
6983
d62a17ae 6984static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6985{
365ab2e7
RZ
6986 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6987 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6988 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6989 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6990 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6991}
718e3744 6992
365ab2e7
RZ
6993/**
6994 * Helper function to avoid repeated code: prepare variables for a
6995 * `route_map_apply` call.
6996 *
6997 * \returns `true` on route map match, otherwise `false`.
6998 */
6999static bool aggr_suppress_map_test(struct bgp *bgp,
7000 struct bgp_aggregate *aggregate,
7001 struct bgp_path_info *pi)
7002{
7003 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7004 route_map_result_t rmr = RMAP_DENYMATCH;
7005 struct bgp_path_info rmap_path = {};
7006 struct attr attr = {};
7007
7008 /* No route map entries created, just don't match. */
7009 if (aggregate->suppress_map == NULL)
7010 return false;
7011
7012 /* Call route map matching and return result. */
7013 attr.aspath = aspath_empty();
7014 rmap_path.peer = bgp->peer_self;
7015 rmap_path.attr = &attr;
7016
7017 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7018 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7019 bgp->peer_self->rmap_type = 0;
7020
7021 bgp_attr_flush(&attr);
afb254d7 7022 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7023
7024 return rmr == RMAP_PERMITMATCH;
7025}
7026
4056a5f6
RZ
7027/** Test whether the aggregation has suppressed this path or not. */
7028static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7029 struct bgp_path_info *pi)
7030{
7031 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7032 return false;
7033
7034 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7035}
7036
7037/**
7038 * Suppress this path and keep the reference.
7039 *
7040 * \returns `true` if needs processing otherwise `false`.
7041 */
7042static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7043 struct bgp_path_info *pi)
7044{
7045 struct bgp_path_info_extra *pie;
7046
7047 /* Path is already suppressed by this aggregation. */
7048 if (aggr_suppress_exists(aggregate, pi))
7049 return false;
7050
7051 pie = bgp_path_info_extra_get(pi);
7052
7053 /* This is the first suppression, allocate memory and list it. */
7054 if (pie->aggr_suppressors == NULL)
7055 pie->aggr_suppressors = list_new();
7056
7057 listnode_add(pie->aggr_suppressors, aggregate);
7058
7059 /* Only mark for processing if suppressed. */
7060 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7061 if (BGP_DEBUG(update, UPDATE_OUT))
7062 zlog_debug("aggregate-address suppressing: %pFX",
7063 bgp_dest_get_prefix(pi->net));
7064
4056a5f6
RZ
7065 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7066 return true;
7067 }
7068
7069 return false;
7070}
7071
7072/**
7073 * Unsuppress this path and remove the reference.
7074 *
7075 * \returns `true` if needs processing otherwise `false`.
7076 */
7077static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7078 struct bgp_path_info *pi)
7079{
7080 /* Path wasn't suppressed. */
7081 if (!aggr_suppress_exists(aggregate, pi))
7082 return false;
7083
7084 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7085
7086 /* Unsuppress and free extra memory if last item. */
7087 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7088 if (BGP_DEBUG(update, UPDATE_OUT))
7089 zlog_debug("aggregate-address unsuppressing: %pFX",
7090 bgp_dest_get_prefix(pi->net));
7091
4056a5f6
RZ
7092 list_delete(&pi->extra->aggr_suppressors);
7093 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7094 return true;
7095 }
7096
7097 return false;
7098}
7099
3dc339cd
DA
7100static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7101 struct aspath *aspath,
7102 struct community *comm,
7103 struct ecommunity *ecomm,
7104 struct lcommunity *lcomm)
eaaf8adb
DS
7105{
7106 static struct aspath *ae = NULL;
7107
7108 if (!ae)
7109 ae = aspath_empty();
7110
40381db7 7111 if (!pi)
3dc339cd 7112 return false;
eaaf8adb 7113
40381db7 7114 if (origin != pi->attr->origin)
3dc339cd 7115 return false;
eaaf8adb 7116
40381db7 7117 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7118 return false;
29f7d023 7119
9a706b42 7120 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7121 return false;
eaaf8adb 7122
b53e67a3 7123 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7124 return false;
eaaf8adb 7125
1bcf3a96 7126 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7127 return false;
dd18c5a9 7128
40381db7 7129 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7130 return false;
7ce8a8e0 7131
3dc339cd 7132 return true;
eaaf8adb
DS
7133}
7134
5f040085
DS
7135static void bgp_aggregate_install(
7136 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7137 uint8_t origin, struct aspath *aspath, struct community *community,
7138 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7139 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7140{
9bcb3eef 7141 struct bgp_dest *dest;
c701010e 7142 struct bgp_table *table;
6f94b685 7143 struct bgp_path_info *pi, *orig, *new;
20894f50 7144 struct attr *attr;
c701010e
DS
7145
7146 table = bgp->rib[afi][safi];
7147
9bcb3eef 7148 dest = bgp_node_get(table, p);
eaaf8adb 7149
9bcb3eef 7150 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7151 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7152 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7153 break;
7154
6aabb15d
RZ
7155 /*
7156 * If we have paths with different MEDs, then don't install
7157 * (or uninstall) the aggregate route.
7158 */
7159 if (aggregate->match_med && aggregate->med_mismatched)
7160 goto uninstall_aggregate_route;
7161
c701010e 7162 if (aggregate->count > 0) {
eaaf8adb
DS
7163 /*
7164 * If the aggregate information has not changed
7165 * no need to re-install it again.
7166 */
6f94b685 7167 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7168 ecommunity, lcommunity)) {
9bcb3eef 7169 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7170
7171 if (aspath)
7172 aspath_free(aspath);
7173 if (community)
3c1f53de 7174 community_free(&community);
3da2cc32
DS
7175 if (ecommunity)
7176 ecommunity_free(&ecommunity);
dd18c5a9
DS
7177 if (lcommunity)
7178 lcommunity_free(&lcommunity);
eaaf8adb
DS
7179
7180 return;
7181 }
7182
7183 /*
7184 * Mark the old as unusable
7185 */
40381db7 7186 if (pi)
9bcb3eef 7187 bgp_path_info_delete(dest, pi);
eaaf8adb 7188
20894f50
DA
7189 attr = bgp_attr_aggregate_intern(
7190 bgp, origin, aspath, community, ecommunity, lcommunity,
7191 aggregate, atomic_aggregate, p);
7192
7193 if (!attr) {
7194 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7195 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7196 zlog_debug("%s: %pFX null attribute", __func__,
7197 p);
20894f50
DA
7198 return;
7199 }
7200
3da2cc32 7201 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7202 bgp->peer_self, attr, dest);
20894f50 7203
1defdda8 7204 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7205
9bcb3eef
DS
7206 bgp_path_info_add(dest, new);
7207 bgp_process(bgp, dest, afi, safi);
c701010e 7208 } else {
6aabb15d 7209 uninstall_aggregate_route:
6f94b685 7210 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7211 if (pi->peer == bgp->peer_self
7212 && pi->type == ZEBRA_ROUTE_BGP
7213 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7214 break;
7215
7216 /* Withdraw static BGP route from routing table. */
40381db7 7217 if (pi) {
9bcb3eef
DS
7218 bgp_path_info_delete(dest, pi);
7219 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7220 }
7221 }
7222
9bcb3eef 7223 bgp_dest_unlock_node(dest);
c701010e
DS
7224}
7225
6aabb15d
RZ
7226/**
7227 * Check if the current path has different MED than other known paths.
7228 *
7229 * \returns `true` if the MED matched the others else `false`.
7230 */
7231static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7232 struct bgp *bgp, struct bgp_path_info *pi)
7233{
7234 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7235
7236 /* This is the first route being analyzed. */
7237 if (!aggregate->med_initialized) {
7238 aggregate->med_initialized = true;
7239 aggregate->med_mismatched = false;
7240 aggregate->med_matched_value = cur_med;
7241 } else {
7242 /* Check if routes with different MED showed up. */
7243 if (cur_med != aggregate->med_matched_value)
7244 aggregate->med_mismatched = true;
7245 }
7246
7247 return !aggregate->med_mismatched;
7248}
7249
7250/**
7251 * Initializes and tests all routes in the aggregate address path for MED
7252 * values.
7253 *
7254 * \returns `true` if all MEDs are the same otherwise `false`.
7255 */
7256static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7257 struct bgp *bgp, const struct prefix *p,
7258 afi_t afi, safi_t safi)
7259{
7260 struct bgp_table *table = bgp->rib[afi][safi];
7261 const struct prefix *dest_p;
7262 struct bgp_dest *dest, *top;
7263 struct bgp_path_info *pi;
7264 bool med_matched = true;
7265
7266 aggregate->med_initialized = false;
7267
7268 top = bgp_node_get(table, p);
7269 for (dest = bgp_node_get(table, p); dest;
7270 dest = bgp_route_next_until(dest, top)) {
7271 dest_p = bgp_dest_get_prefix(dest);
7272 if (dest_p->prefixlen <= p->prefixlen)
7273 continue;
7274
7275 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7276 if (BGP_PATH_HOLDDOWN(pi))
7277 continue;
7278 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7279 continue;
7280 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7281 med_matched = false;
7282 break;
7283 }
7284 }
7285 if (!med_matched)
7286 break;
7287 }
7288 bgp_dest_unlock_node(top);
7289
7290 return med_matched;
7291}
7292
7293/**
7294 * Toggles the route suppression status for this aggregate address
7295 * configuration.
7296 */
4056a5f6
RZ
7297void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7298 struct bgp *bgp, const struct prefix *p,
7299 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7300{
7301 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7302 const struct prefix *dest_p;
7303 struct bgp_dest *dest, *top;
7304 struct bgp_path_info *pi;
7305 bool toggle_suppression;
7306
7307 /* We've found a different MED we must revert any suppressed routes. */
7308 top = bgp_node_get(table, p);
7309 for (dest = bgp_node_get(table, p); dest;
7310 dest = bgp_route_next_until(dest, top)) {
7311 dest_p = bgp_dest_get_prefix(dest);
7312 if (dest_p->prefixlen <= p->prefixlen)
7313 continue;
7314
7315 toggle_suppression = false;
7316 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7317 if (BGP_PATH_HOLDDOWN(pi))
7318 continue;
7319 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7320 continue;
7321
6aabb15d
RZ
7322 /* We are toggling suppression back. */
7323 if (suppress) {
6aabb15d 7324 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7325 if (aggr_suppress_path(aggregate, pi))
7326 toggle_suppression = true;
6aabb15d
RZ
7327 continue;
7328 }
7329
6aabb15d 7330 /* Install route if there is no more suppression. */
4056a5f6 7331 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7332 toggle_suppression = true;
6aabb15d
RZ
7333 }
7334
7335 if (toggle_suppression)
7336 bgp_process(bgp, dest, afi, safi);
7337 }
7338 bgp_dest_unlock_node(top);
7339}
7340
7341/**
7342 * Aggregate address MED matching incremental test: this function is called
7343 * when the initial aggregation occurred and we are only testing a single
7344 * new path.
7345 *
7346 * In addition to testing and setting the MED validity it also installs back
7347 * suppressed routes (if summary is configured).
7348 *
7349 * Must not be called in `bgp_aggregate_route`.
7350 */
7351static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7352 struct bgp *bgp, const struct prefix *p,
7353 afi_t afi, safi_t safi,
7354 struct bgp_path_info *pi, bool is_adding)
7355{
7356 /* MED matching disabled. */
7357 if (!aggregate->match_med)
7358 return;
7359
7360 /* Aggregation with different MED, nothing to do. */
7361 if (aggregate->med_mismatched)
7362 return;
7363
7364 /*
7365 * Test the current entry:
7366 *
7367 * is_adding == true: if the new entry doesn't match then we must
7368 * install all suppressed routes.
7369 *
7370 * is_adding == false: if the entry being removed was the last
7371 * unmatching entry then we can suppress all routes.
7372 */
7373 if (!is_adding) {
7374 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7375 && aggregate->summary_only)
7376 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7377 safi, true);
7378 } else
7379 bgp_aggregate_med_match(aggregate, bgp, pi);
7380
7381 /* No mismatches, just quit. */
7382 if (!aggregate->med_mismatched)
7383 return;
7384
7385 /* Route summarization is disabled. */
7386 if (!aggregate->summary_only)
7387 return;
7388
7389 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7390}
7391
b5d58c32 7392/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7393void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7394 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7395{
7396 struct bgp_table *table;
9bcb3eef
DS
7397 struct bgp_dest *top;
7398 struct bgp_dest *dest;
d7c0a89a 7399 uint8_t origin;
d62a17ae 7400 struct aspath *aspath = NULL;
d62a17ae 7401 struct community *community = NULL;
3da2cc32 7402 struct ecommunity *ecommunity = NULL;
dd18c5a9 7403 struct lcommunity *lcommunity = NULL;
40381db7 7404 struct bgp_path_info *pi;
d62a17ae 7405 unsigned long match = 0;
d7c0a89a 7406 uint8_t atomic_aggregate = 0;
d62a17ae 7407
9f822fa2
S
7408 /* If the bgp instance is being deleted or self peer is deleted
7409 * then do not create aggregate route
7410 */
892fedb6
DA
7411 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7412 || (bgp->peer_self == NULL))
9f822fa2
S
7413 return;
7414
6aabb15d
RZ
7415 /* Initialize and test routes for MED difference. */
7416 if (aggregate->match_med)
7417 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7418
4056a5f6
RZ
7419 /*
7420 * Reset aggregate count: we might've been called from route map
7421 * update so in that case we must retest all more specific routes.
7422 *
7423 * \see `bgp_route_map_process_update`.
7424 */
7425 aggregate->count = 0;
7426 aggregate->incomplete_origin_count = 0;
7427 aggregate->incomplete_origin_count = 0;
7428 aggregate->egp_origin_count = 0;
7429
d62a17ae 7430 /* ORIGIN attribute: If at least one route among routes that are
7431 aggregated has ORIGIN with the value INCOMPLETE, then the
7432 aggregated route must have the ORIGIN attribute with the value
7433 INCOMPLETE. Otherwise, if at least one route among routes that
7434 are aggregated has ORIGIN with the value EGP, then the aggregated
7435 route must have the origin attribute with the value EGP. In all
7436 other case the value of the ORIGIN attribute of the aggregated
7437 route is INTERNAL. */
7438 origin = BGP_ORIGIN_IGP;
718e3744 7439
d62a17ae 7440 table = bgp->rib[afi][safi];
718e3744 7441
d62a17ae 7442 top = bgp_node_get(table, p);
9bcb3eef
DS
7443 for (dest = bgp_node_get(table, p); dest;
7444 dest = bgp_route_next_until(dest, top)) {
7445 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7446
9bcb3eef 7447 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7448 continue;
d62a17ae 7449
a77e2f4b
S
7450 /* If suppress fib is enabled and route not installed
7451 * in FIB, skip the route
7452 */
7453 if (!bgp_check_advertise(bgp, dest))
7454 continue;
7455
c2ff8b3e 7456 match = 0;
d62a17ae 7457
9bcb3eef 7458 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7459 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7460 continue;
718e3744 7461
40381db7 7462 if (pi->attr->flag
c2ff8b3e
DS
7463 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7464 atomic_aggregate = 1;
d62a17ae 7465
40381db7 7466 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7467 continue;
d62a17ae 7468
f273fef1
DS
7469 /*
7470 * summary-only aggregate route suppress
7471 * aggregated route announcements.
6aabb15d
RZ
7472 *
7473 * MED matching:
7474 * Don't create summaries if MED didn't match
7475 * otherwise neither the specific routes and the
7476 * aggregation will be announced.
f273fef1 7477 */
6aabb15d
RZ
7478 if (aggregate->summary_only
7479 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7480 if (aggr_suppress_path(aggregate, pi))
7481 match++;
d62a17ae 7482 }
c2ff8b3e 7483
365ab2e7
RZ
7484 /*
7485 * Suppress more specific routes that match the route
7486 * map results.
7487 *
7488 * MED matching:
7489 * Don't suppress routes if MED matching is enabled and
7490 * it mismatched otherwise we might end up with no
7491 * routes for this path.
7492 */
7493 if (aggregate->suppress_map_name
7494 && AGGREGATE_MED_VALID(aggregate)
7495 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7496 if (aggr_suppress_path(aggregate, pi))
7497 match++;
d62a17ae 7498 }
c2ff8b3e
DS
7499
7500 aggregate->count++;
7501
f273fef1
DS
7502 /*
7503 * If at least one route among routes that are
7504 * aggregated has ORIGIN with the value INCOMPLETE,
7505 * then the aggregated route MUST have the ORIGIN
7506 * attribute with the value INCOMPLETE. Otherwise, if
7507 * at least one route among routes that are aggregated
7508 * has ORIGIN with the value EGP, then the aggregated
7509 * route MUST have the ORIGIN attribute with the value
7510 * EGP.
7511 */
fc968841
NT
7512 switch (pi->attr->origin) {
7513 case BGP_ORIGIN_INCOMPLETE:
7514 aggregate->incomplete_origin_count++;
7515 break;
7516 case BGP_ORIGIN_EGP:
7517 aggregate->egp_origin_count++;
7518 break;
7519 default:
7520 /*Do nothing.
7521 */
7522 break;
7523 }
c2ff8b3e
DS
7524
7525 if (!aggregate->as_set)
7526 continue;
7527
f273fef1
DS
7528 /*
7529 * as-set aggregate route generate origin, as path,
7530 * and community aggregation.
7531 */
fc968841
NT
7532 /* Compute aggregate route's as-path.
7533 */
ef51a7d8 7534 bgp_compute_aggregate_aspath_hash(aggregate,
7535 pi->attr->aspath);
c2ff8b3e 7536
fc968841
NT
7537 /* Compute aggregate route's community.
7538 */
9a706b42 7539 if (bgp_attr_get_community(pi->attr))
21fec674 7540 bgp_compute_aggregate_community_hash(
9a706b42
DA
7541 aggregate,
7542 bgp_attr_get_community(pi->attr));
dd18c5a9 7543
fc968841
NT
7544 /* Compute aggregate route's extended community.
7545 */
b53e67a3 7546 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7547 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7548 aggregate,
7549 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7550
7551 /* Compute aggregate route's large community.
7552 */
1bcf3a96 7553 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7554 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7555 aggregate,
7556 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7557 }
c2ff8b3e 7558 if (match)
9bcb3eef 7559 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7560 }
21fec674 7561 if (aggregate->as_set) {
ef51a7d8 7562 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7563 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7564 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7565 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7566 }
7567
f1eb1f05 7568
9bcb3eef 7569 bgp_dest_unlock_node(top);
718e3744 7570
718e3744 7571
fc968841
NT
7572 if (aggregate->incomplete_origin_count > 0)
7573 origin = BGP_ORIGIN_INCOMPLETE;
7574 else if (aggregate->egp_origin_count > 0)
7575 origin = BGP_ORIGIN_EGP;
d62a17ae 7576
229757f1
DA
7577 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7578 origin = aggregate->origin;
7579
fc968841
NT
7580 if (aggregate->as_set) {
7581 if (aggregate->aspath)
7582 /* Retrieve aggregate route's as-path.
7583 */
7584 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7585
fc968841
NT
7586 if (aggregate->community)
7587 /* Retrieve aggregate route's community.
7588 */
7589 community = community_dup(aggregate->community);
3da2cc32 7590
fc968841
NT
7591 if (aggregate->ecommunity)
7592 /* Retrieve aggregate route's ecommunity.
7593 */
7594 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7595
fc968841
NT
7596 if (aggregate->lcommunity)
7597 /* Retrieve aggregate route's lcommunity.
7598 */
7599 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7600 }
718e3744 7601
c701010e 7602 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7603 ecommunity, lcommunity, atomic_aggregate,
7604 aggregate);
718e3744 7605}
7606
5f040085
DS
7607void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7608 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7609{
7610 struct bgp_table *table;
9bcb3eef
DS
7611 struct bgp_dest *top;
7612 struct bgp_dest *dest;
40381db7 7613 struct bgp_path_info *pi;
3b7db173
DS
7614 unsigned long match;
7615
7616 table = bgp->rib[afi][safi];
7617
7618 /* If routes exists below this node, generate aggregate routes. */
7619 top = bgp_node_get(table, p);
9bcb3eef
DS
7620 for (dest = bgp_node_get(table, p); dest;
7621 dest = bgp_route_next_until(dest, top)) {
7622 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7623
9bcb3eef 7624 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7625 continue;
7626 match = 0;
7627
9bcb3eef 7628 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7629 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7630 continue;
7631
40381db7 7632 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7633 continue;
7634
92b175bd
RZ
7635 /*
7636 * This route is suppressed: attempt to unsuppress it.
7637 *
7638 * `aggr_unsuppress_path` will fail if this particular
7639 * aggregate route was not the suppressor.
7640 */
7641 if (pi->extra && pi->extra->aggr_suppressors &&
7642 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7643 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7644 match++;
3b7db173 7645 }
365ab2e7 7646
3b7db173 7647 aggregate->count--;
fc968841
NT
7648
7649 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7650 aggregate->incomplete_origin_count--;
7651 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7652 aggregate->egp_origin_count--;
7653
7654 if (aggregate->as_set) {
7655 /* Remove as-path from aggregate.
7656 */
ef51a7d8 7657 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7658 aggregate,
7659 pi->attr->aspath);
7660
9a706b42 7661 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7662 /* Remove community from aggregate.
7663 */
21fec674 7664 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7665 aggregate,
7666 bgp_attr_get_community(
7667 pi->attr));
fc968841 7668
b53e67a3 7669 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7670 /* Remove ecommunity from aggregate.
7671 */
4edd83f9 7672 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7673 aggregate,
7674 bgp_attr_get_ecommunity(
7675 pi->attr));
fc968841 7676
1bcf3a96 7677 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7678 /* Remove lcommunity from aggregate.
7679 */
f1eb1f05 7680 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7681 aggregate,
7682 bgp_attr_get_lcommunity(
7683 pi->attr));
fc968841 7684 }
3b7db173
DS
7685 }
7686
7687 /* If this node was suppressed, process the change. */
7688 if (match)
9bcb3eef 7689 bgp_process(bgp, dest, afi, safi);
3b7db173 7690 }
f1eb1f05 7691 if (aggregate->as_set) {
ef51a7d8 7692 aspath_free(aggregate->aspath);
7693 aggregate->aspath = NULL;
21fec674 7694 if (aggregate->community)
7695 community_free(&aggregate->community);
4edd83f9 7696 if (aggregate->ecommunity)
7697 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7698 if (aggregate->lcommunity)
7699 lcommunity_free(&aggregate->lcommunity);
7700 }
7701
9bcb3eef 7702 bgp_dest_unlock_node(top);
3b7db173 7703}
718e3744 7704
5f040085
DS
7705static void bgp_add_route_to_aggregate(struct bgp *bgp,
7706 const struct prefix *aggr_p,
fc968841
NT
7707 struct bgp_path_info *pinew, afi_t afi,
7708 safi_t safi,
7709 struct bgp_aggregate *aggregate)
7710{
7711 uint8_t origin;
7712 struct aspath *aspath = NULL;
7713 uint8_t atomic_aggregate = 0;
7714 struct community *community = NULL;
7715 struct ecommunity *ecommunity = NULL;
7716 struct lcommunity *lcommunity = NULL;
7717
a4559740 7718 /* If the bgp instance is being deleted or self peer is deleted
7719 * then do not create aggregate route
7720 */
7721 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7722 || (bgp->peer_self == NULL))
7723 return;
7724
fc968841
NT
7725 /* ORIGIN attribute: If at least one route among routes that are
7726 * aggregated has ORIGIN with the value INCOMPLETE, then the
7727 * aggregated route must have the ORIGIN attribute with the value
7728 * INCOMPLETE. Otherwise, if at least one route among routes that
7729 * are aggregated has ORIGIN with the value EGP, then the aggregated
7730 * route must have the origin attribute with the value EGP. In all
7731 * other case the value of the ORIGIN attribute of the aggregated
7732 * route is INTERNAL.
7733 */
7734 origin = BGP_ORIGIN_IGP;
7735
7736 aggregate->count++;
7737
6aabb15d
RZ
7738 /*
7739 * This must be called before `summary` check to avoid
7740 * "suppressing" twice.
7741 */
7742 if (aggregate->match_med)
7743 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7744 pinew, true);
7745
7746 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7747 aggr_suppress_path(aggregate, pinew);
fc968841 7748
365ab2e7
RZ
7749 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7750 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7751 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7752
7753 switch (pinew->attr->origin) {
7754 case BGP_ORIGIN_INCOMPLETE:
7755 aggregate->incomplete_origin_count++;
7756 break;
7757 case BGP_ORIGIN_EGP:
7758 aggregate->egp_origin_count++;
7759 break;
7760 default:
7761 /* Do nothing.
7762 */
7763 break;
7764 }
7765
7766 if (aggregate->incomplete_origin_count > 0)
7767 origin = BGP_ORIGIN_INCOMPLETE;
7768 else if (aggregate->egp_origin_count > 0)
7769 origin = BGP_ORIGIN_EGP;
7770
229757f1
DA
7771 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7772 origin = aggregate->origin;
7773
fc968841
NT
7774 if (aggregate->as_set) {
7775 /* Compute aggregate route's as-path.
7776 */
7777 bgp_compute_aggregate_aspath(aggregate,
7778 pinew->attr->aspath);
7779
7780 /* Compute aggregate route's community.
7781 */
9a706b42 7782 if (bgp_attr_get_community(pinew->attr))
fc968841 7783 bgp_compute_aggregate_community(
9a706b42 7784 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7785
7786 /* Compute aggregate route's extended community.
7787 */
b53e67a3 7788 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7789 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7790 aggregate,
7791 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7792
7793 /* Compute aggregate route's large community.
7794 */
1bcf3a96 7795 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7796 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7797 aggregate,
7798 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7799
7800 /* Retrieve aggregate route's as-path.
7801 */
7802 if (aggregate->aspath)
7803 aspath = aspath_dup(aggregate->aspath);
7804
7805 /* Retrieve aggregate route's community.
7806 */
7807 if (aggregate->community)
7808 community = community_dup(aggregate->community);
7809
7810 /* Retrieve aggregate route's ecommunity.
7811 */
7812 if (aggregate->ecommunity)
7813 ecommunity = ecommunity_dup(aggregate->ecommunity);
7814
7815 /* Retrieve aggregate route's lcommunity.
7816 */
7817 if (aggregate->lcommunity)
7818 lcommunity = lcommunity_dup(aggregate->lcommunity);
7819 }
7820
7821 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7822 aspath, community, ecommunity,
7823 lcommunity, atomic_aggregate, aggregate);
7824}
7825
7826static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7827 safi_t safi,
7828 struct bgp_path_info *pi,
7829 struct bgp_aggregate *aggregate,
5f040085 7830 const struct prefix *aggr_p)
fc968841
NT
7831{
7832 uint8_t origin;
7833 struct aspath *aspath = NULL;
7834 uint8_t atomic_aggregate = 0;
7835 struct community *community = NULL;
7836 struct ecommunity *ecommunity = NULL;
7837 struct lcommunity *lcommunity = NULL;
7838 unsigned long match = 0;
7839
a4559740 7840 /* If the bgp instance is being deleted or self peer is deleted
7841 * then do not create aggregate route
7842 */
7843 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7844 || (bgp->peer_self == NULL))
7845 return;
7846
fc968841
NT
7847 if (BGP_PATH_HOLDDOWN(pi))
7848 return;
7849
7850 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7851 return;
7852
4056a5f6
RZ
7853 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7854 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7855 match++;
fc968841 7856
365ab2e7 7857 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7858 && aggr_suppress_map_test(bgp, aggregate, pi))
7859 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7860 match++;
fc968841 7861
6aabb15d 7862 /*
365ab2e7 7863 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7864 * "unsuppressing" twice.
7865 */
7866 if (aggregate->match_med)
7867 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7868 true);
7869
fc968841
NT
7870 if (aggregate->count > 0)
7871 aggregate->count--;
7872
7873 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7874 aggregate->incomplete_origin_count--;
7875 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7876 aggregate->egp_origin_count--;
7877
7878 if (aggregate->as_set) {
7879 /* Remove as-path from aggregate.
7880 */
7881 bgp_remove_aspath_from_aggregate(aggregate,
7882 pi->attr->aspath);
7883
9a706b42 7884 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7885 /* Remove community from aggregate.
7886 */
7887 bgp_remove_community_from_aggregate(
9a706b42 7888 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7889
b53e67a3 7890 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7891 /* Remove ecommunity from aggregate.
7892 */
7893 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7894 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7895
1bcf3a96 7896 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7897 /* Remove lcommunity from aggregate.
7898 */
7899 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7900 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7901 }
7902
7903 /* If this node was suppressed, process the change. */
7904 if (match)
7905 bgp_process(bgp, pi->net, afi, safi);
7906
7907 origin = BGP_ORIGIN_IGP;
7908 if (aggregate->incomplete_origin_count > 0)
7909 origin = BGP_ORIGIN_INCOMPLETE;
7910 else if (aggregate->egp_origin_count > 0)
7911 origin = BGP_ORIGIN_EGP;
7912
229757f1
DA
7913 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7914 origin = aggregate->origin;
7915
fc968841
NT
7916 if (aggregate->as_set) {
7917 /* Retrieve aggregate route's as-path.
7918 */
7919 if (aggregate->aspath)
7920 aspath = aspath_dup(aggregate->aspath);
7921
7922 /* Retrieve aggregate route's community.
7923 */
7924 if (aggregate->community)
7925 community = community_dup(aggregate->community);
7926
7927 /* Retrieve aggregate route's ecommunity.
7928 */
7929 if (aggregate->ecommunity)
7930 ecommunity = ecommunity_dup(aggregate->ecommunity);
7931
7932 /* Retrieve aggregate route's lcommunity.
7933 */
7934 if (aggregate->lcommunity)
7935 lcommunity = lcommunity_dup(aggregate->lcommunity);
7936 }
7937
7938 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7939 aspath, community, ecommunity,
7940 lcommunity, atomic_aggregate, aggregate);
7941}
7942
5a1ae2c2 7943void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7944 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7945{
9bcb3eef
DS
7946 struct bgp_dest *child;
7947 struct bgp_dest *dest;
d62a17ae 7948 struct bgp_aggregate *aggregate;
7949 struct bgp_table *table;
718e3744 7950
d62a17ae 7951 table = bgp->aggregate[afi][safi];
f018db83 7952
d62a17ae 7953 /* No aggregates configured. */
7954 if (bgp_table_top_nolock(table) == NULL)
7955 return;
f018db83 7956
d62a17ae 7957 if (p->prefixlen == 0)
7958 return;
718e3744 7959
40381db7 7960 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7961 return;
718e3744 7962
a77e2f4b
S
7963 /* If suppress fib is enabled and route not installed
7964 * in FIB, do not update the aggregate route
7965 */
7966 if (!bgp_check_advertise(bgp, pi->net))
7967 return;
7968
d62a17ae 7969 child = bgp_node_get(table, p);
718e3744 7970
d62a17ae 7971 /* Aggregate address configuration check. */
9bcb3eef
DS
7972 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7973 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7974
9bcb3eef
DS
7975 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7976 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7977 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7978 aggregate);
d62a17ae 7979 }
b1e62edd 7980 }
9bcb3eef 7981 bgp_dest_unlock_node(child);
718e3744 7982}
7983
5a1ae2c2 7984void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7985 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7986{
9bcb3eef
DS
7987 struct bgp_dest *child;
7988 struct bgp_dest *dest;
d62a17ae 7989 struct bgp_aggregate *aggregate;
7990 struct bgp_table *table;
718e3744 7991
d62a17ae 7992 table = bgp->aggregate[afi][safi];
718e3744 7993
d62a17ae 7994 /* No aggregates configured. */
7995 if (bgp_table_top_nolock(table) == NULL)
7996 return;
718e3744 7997
d62a17ae 7998 if (p->prefixlen == 0)
7999 return;
718e3744 8000
d62a17ae 8001 child = bgp_node_get(table, p);
718e3744 8002
d62a17ae 8003 /* Aggregate address configuration check. */
9bcb3eef
DS
8004 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8005 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8006
9bcb3eef
DS
8007 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8008 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8009 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8010 aggregate, dest_p);
d62a17ae 8011 }
b1e62edd 8012 }
9bcb3eef 8013 bgp_dest_unlock_node(child);
d62a17ae 8014}
718e3744 8015
718e3744 8016/* Aggregate route attribute. */
8017#define AGGREGATE_SUMMARY_ONLY 1
8018#define AGGREGATE_AS_SET 1
fb29348a 8019#define AGGREGATE_AS_UNSET 0
718e3744 8020
229757f1
DA
8021static const char *bgp_origin2str(uint8_t origin)
8022{
8023 switch (origin) {
8024 case BGP_ORIGIN_IGP:
8025 return "igp";
8026 case BGP_ORIGIN_EGP:
8027 return "egp";
8028 case BGP_ORIGIN_INCOMPLETE:
8029 return "incomplete";
8030 }
8031 return "n/a";
8032}
8033
fdeb5a81 8034static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8035{
8036 switch (v_state) {
fdeb5a81
DS
8037 case RPKI_NOT_BEING_USED:
8038 return "not used";
8039 case RPKI_VALID:
b5b99af8 8040 return "valid";
fdeb5a81 8041 case RPKI_NOTFOUND:
b5b99af8 8042 return "not found";
fdeb5a81 8043 case RPKI_INVALID:
b5b99af8 8044 return "invalid";
b5b99af8 8045 }
fdeb5a81
DS
8046
8047 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8048 return "ERROR";
8049}
8050
585f1adc
IR
8051static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8052 afi_t afi, safi_t safi)
718e3744 8053{
585f1adc
IR
8054 VTY_DECLVAR_CONTEXT(bgp, bgp);
8055 int ret;
8056 struct prefix p;
9bcb3eef 8057 struct bgp_dest *dest;
d62a17ae 8058 struct bgp_aggregate *aggregate;
718e3744 8059
585f1adc
IR
8060 /* Convert string to prefix structure. */
8061 ret = str2prefix(prefix_str, &p);
8062 if (!ret) {
8063 vty_out(vty, "Malformed prefix\n");
8064 return CMD_WARNING_CONFIG_FAILED;
8065 }
8066 apply_mask(&p);
a4559740 8067
d62a17ae 8068 /* Old configuration check. */
585f1adc 8069 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8070 if (!dest) {
585f1adc
IR
8071 vty_out(vty,
8072 "%% There is no aggregate-address configuration.\n");
8073 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8074 }
f6269b4f 8075
9bcb3eef 8076 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8077 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8078 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8079 NULL, NULL, 0, aggregate);
d62a17ae 8080
8081 /* Unlock aggregate address configuration. */
9bcb3eef 8082 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8083
8084 if (aggregate->community)
8085 community_free(&aggregate->community);
8086
8087 if (aggregate->community_hash) {
8088 /* Delete all communities in the hash.
8089 */
8090 hash_clean(aggregate->community_hash,
8091 bgp_aggr_community_remove);
8092 /* Free up the community_hash.
8093 */
8094 hash_free(aggregate->community_hash);
8095 }
8096
8097 if (aggregate->ecommunity)
8098 ecommunity_free(&aggregate->ecommunity);
8099
8100 if (aggregate->ecommunity_hash) {
8101 /* Delete all ecommunities in the hash.
8102 */
8103 hash_clean(aggregate->ecommunity_hash,
8104 bgp_aggr_ecommunity_remove);
8105 /* Free up the ecommunity_hash.
8106 */
8107 hash_free(aggregate->ecommunity_hash);
8108 }
8109
8110 if (aggregate->lcommunity)
8111 lcommunity_free(&aggregate->lcommunity);
8112
8113 if (aggregate->lcommunity_hash) {
8114 /* Delete all lcommunities in the hash.
8115 */
8116 hash_clean(aggregate->lcommunity_hash,
8117 bgp_aggr_lcommunity_remove);
8118 /* Free up the lcommunity_hash.
8119 */
8120 hash_free(aggregate->lcommunity_hash);
8121 }
8122
8123 if (aggregate->aspath)
8124 aspath_free(aggregate->aspath);
8125
8126 if (aggregate->aspath_hash) {
8127 /* Delete all as-paths in the hash.
8128 */
8129 hash_clean(aggregate->aspath_hash,
8130 bgp_aggr_aspath_remove);
8131 /* Free up the aspath_hash.
8132 */
8133 hash_free(aggregate->aspath_hash);
8134 }
8135
d62a17ae 8136 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8137 bgp_dest_unlock_node(dest);
8138 bgp_dest_unlock_node(dest);
d62a17ae 8139
585f1adc 8140 return CMD_SUCCESS;
d62a17ae 8141}
8142
585f1adc
IR
8143static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8144 safi_t safi, const char *rmap,
8145 uint8_t summary_only, uint8_t as_set,
8146 uint8_t origin, bool match_med,
8147 const char *suppress_map)
d62a17ae 8148{
585f1adc 8149 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8150 int ret;
585f1adc 8151 struct prefix p;
9bcb3eef 8152 struct bgp_dest *dest;
d62a17ae 8153 struct bgp_aggregate *aggregate;
fb29348a 8154 uint8_t as_set_new = as_set;
d62a17ae 8155
365ab2e7 8156 if (suppress_map && summary_only) {
585f1adc 8157 vty_out(vty,
365ab2e7 8158 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8159 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8160 }
8161
585f1adc
IR
8162 /* Convert string to prefix structure. */
8163 ret = str2prefix(prefix_str, &p);
8164 if (!ret) {
8165 vty_out(vty, "Malformed prefix\n");
8166 return CMD_WARNING_CONFIG_FAILED;
8167 }
8168 apply_mask(&p);
d62a17ae 8169
585f1adc
IR
8170 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8171 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8172 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8173 prefix_str);
8174 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8175 }
8176
d62a17ae 8177 /* Old configuration check. */
585f1adc 8178 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8179 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8180
20894f50 8181 if (aggregate) {
585f1adc 8182 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8183 /* try to remove the old entry */
585f1adc 8184 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8185 if (ret) {
585f1adc 8186 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8187 bgp_dest_unlock_node(dest);
585f1adc 8188 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8189 }
8190 }
718e3744 8191
d62a17ae 8192 /* Make aggregate address structure. */
8193 aggregate = bgp_aggregate_new();
8194 aggregate->summary_only = summary_only;
6aabb15d 8195 aggregate->match_med = match_med;
fb29348a
DA
8196
8197 /* Network operators MUST NOT locally generate any new
8198 * announcements containing AS_SET or AS_CONFED_SET. If they have
8199 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8200 * SHOULD withdraw those routes and re-announce routes for the
8201 * aggregate or component prefixes (i.e., the more-specific routes
8202 * subsumed by the previously aggregated route) without AS_SET
8203 * or AS_CONFED_SET in the updates.
8204 */
7f972cd8 8205 if (bgp->reject_as_sets) {
fb29348a
DA
8206 if (as_set == AGGREGATE_AS_SET) {
8207 as_set_new = AGGREGATE_AS_UNSET;
8208 zlog_warn(
63efca0e 8209 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8210 __func__);
585f1adc 8211 vty_out(vty,
fb29348a
DA
8212 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8213 }
8214 }
8215
8216 aggregate->as_set = as_set_new;
d62a17ae 8217 aggregate->safi = safi;
229757f1
DA
8218 /* Override ORIGIN attribute if defined.
8219 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8220 * to IGP which is not what rfc4271 says.
8221 * This enables the same behavior, optionally.
8222 */
8223 aggregate->origin = origin;
20894f50
DA
8224
8225 if (rmap) {
8226 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8227 route_map_counter_decrement(aggregate->rmap.map);
8228 aggregate->rmap.name =
8229 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8230 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8231 route_map_counter_increment(aggregate->rmap.map);
8232 }
365ab2e7
RZ
8233
8234 if (suppress_map) {
8235 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8236 route_map_counter_decrement(aggregate->suppress_map);
8237
8238 aggregate->suppress_map_name =
8239 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8240 aggregate->suppress_map =
8241 route_map_lookup_by_name(aggregate->suppress_map_name);
8242 route_map_counter_increment(aggregate->suppress_map);
8243 }
8244
9bcb3eef 8245 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8246
d62a17ae 8247 /* Aggregate address insert into BGP routing table. */
585f1adc 8248 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8249
585f1adc 8250 return CMD_SUCCESS;
718e3744 8251}
8252
585f1adc
IR
8253DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8254 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8255 "as-set$as_set_s"
8256 "|summary-only$summary_only"
cacba915 8257 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8258 "|origin <egp|igp|incomplete>$origin_s"
8259 "|matching-MED-only$match_med"
cacba915 8260 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8261 "}]",
8262 NO_STR
8263 "Configure BGP aggregate entries\n"
764402fe
DA
8264 "Aggregate prefix\n"
8265 "Aggregate address\n"
8266 "Aggregate mask\n"
585f1adc
IR
8267 "Generate AS set path information\n"
8268 "Filter more specific routes from updates\n"
8269 "Apply route map to aggregate network\n"
8270 "Route map name\n"
8271 "BGP origin code\n"
8272 "Remote EGP\n"
8273 "Local IGP\n"
8274 "Unknown heritage\n"
8275 "Only aggregate routes with matching MED\n"
8276 "Suppress the selected more specific routes\n"
8277 "Route map with the route selectors\n")
8278{
8279 const char *prefix_s = NULL;
554b3b10 8280 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8281 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8282 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8283 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8284
554b3b10 8285 if (addr_str) {
7533cad7
QY
8286 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8287 sizeof(prefix_buf))
554b3b10
RZ
8288 == 0) {
8289 vty_out(vty, "%% Inconsistent address and mask\n");
8290 return CMD_WARNING_CONFIG_FAILED;
8291 }
585f1adc
IR
8292 prefix_s = prefix_buf;
8293 } else
8294 prefix_s = prefix_str;
37a87b8f 8295
585f1adc
IR
8296 if (origin_s) {
8297 if (strcmp(origin_s, "egp") == 0)
8298 origin = BGP_ORIGIN_EGP;
8299 else if (strcmp(origin_s, "igp") == 0)
8300 origin = BGP_ORIGIN_IGP;
8301 else if (strcmp(origin_s, "incomplete") == 0)
8302 origin = BGP_ORIGIN_INCOMPLETE;
8303 }
90e21f35 8304
585f1adc
IR
8305 if (as_set_s)
8306 as_set = AGGREGATE_AS_SET;
554b3b10 8307
585f1adc 8308 /* Handle configuration removal, otherwise installation. */
554b3b10 8309 if (no)
585f1adc
IR
8310 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8311
8312 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8313 summary_only != NULL, as_set, origin,
8314 match_med != NULL, suppress_map);
8315}
8316
8317DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8318 "[no] aggregate-address X:X::X:X/M$prefix [{"
8319 "as-set$as_set_s"
8320 "|summary-only$summary_only"
cacba915 8321 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8322 "|origin <egp|igp|incomplete>$origin_s"
8323 "|matching-MED-only$match_med"
cacba915 8324 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8325 "}]",
8326 NO_STR
8327 "Configure BGP aggregate entries\n"
8328 "Aggregate prefix\n"
8329 "Generate AS set path information\n"
8330 "Filter more specific routes from updates\n"
8331 "Apply route map to aggregate network\n"
8332 "Route map name\n"
8333 "BGP origin code\n"
8334 "Remote EGP\n"
8335 "Local IGP\n"
8336 "Unknown heritage\n"
8337 "Only aggregate routes with matching MED\n"
8338 "Suppress the selected more specific routes\n"
8339 "Route map with the route selectors\n")
8340{
8341 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8342 int as_set = AGGREGATE_AS_UNSET;
8343
8344 if (origin_s) {
8345 if (strcmp(origin_s, "egp") == 0)
8346 origin = BGP_ORIGIN_EGP;
8347 else if (strcmp(origin_s, "igp") == 0)
8348 origin = BGP_ORIGIN_IGP;
8349 else if (strcmp(origin_s, "incomplete") == 0)
8350 origin = BGP_ORIGIN_INCOMPLETE;
8351 }
8352
8353 if (as_set_s)
8354 as_set = AGGREGATE_AS_SET;
8355
8356 /* Handle configuration removal, otherwise installation. */
554b3b10 8357 if (no)
585f1adc
IR
8358 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8359 SAFI_UNICAST);
554b3b10 8360
585f1adc
IR
8361 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8362 rmap_name, summary_only != NULL, as_set,
8363 origin, match_med != NULL, suppress_map);
718e3744 8364}
8365
718e3744 8366/* Redistribute route treatment. */
d62a17ae 8367void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8368 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8369 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8370 enum blackhole_type bhtype, uint32_t metric,
8371 uint8_t type, unsigned short instance,
8372 route_tag_t tag)
d62a17ae 8373{
4b7e6066 8374 struct bgp_path_info *new;
40381db7
DS
8375 struct bgp_path_info *bpi;
8376 struct bgp_path_info rmap_path;
9bcb3eef 8377 struct bgp_dest *bn;
d62a17ae 8378 struct attr attr;
8379 struct attr *new_attr;
8380 afi_t afi;
b68885f9 8381 route_map_result_t ret;
d62a17ae 8382 struct bgp_redist *red;
8383
8384 /* Make default attribute. */
0f05ea43 8385 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8386 /*
8387 * This must not be NULL to satisfy Coverity SA
8388 */
8389 assert(attr.aspath);
9de1f7ff 8390
a4d82a8a 8391 switch (nhtype) {
9de1f7ff
DS
8392 case NEXTHOP_TYPE_IFINDEX:
8393 break;
8394 case NEXTHOP_TYPE_IPV4:
8395 case NEXTHOP_TYPE_IPV4_IFINDEX:
8396 attr.nexthop = nexthop->ipv4;
8397 break;
8398 case NEXTHOP_TYPE_IPV6:
8399 case NEXTHOP_TYPE_IPV6_IFINDEX:
8400 attr.mp_nexthop_global = nexthop->ipv6;
8401 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8402 break;
8403 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8404 switch (p->family) {
8405 case AF_INET:
9de1f7ff 8406 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8407 break;
8408 case AF_INET6:
9de1f7ff
DS
8409 memset(&attr.mp_nexthop_global, 0,
8410 sizeof(attr.mp_nexthop_global));
74489921 8411 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8412 break;
74489921 8413 }
0789eb69 8414 attr.bh_type = bhtype;
9de1f7ff 8415 break;
d62a17ae 8416 }
0789eb69 8417 attr.nh_type = nhtype;
74489921 8418 attr.nh_ifindex = ifindex;
f04a80a5 8419
d62a17ae 8420 attr.med = metric;
957f74c3 8421 attr.distance = distance;
d62a17ae 8422 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8423 attr.tag = tag;
718e3744 8424
d62a17ae 8425 afi = family2afi(p->family);
6aeb9e78 8426
d62a17ae 8427 red = bgp_redist_lookup(bgp, afi, type, instance);
8428 if (red) {
8429 struct attr attr_new;
718e3744 8430
d62a17ae 8431 /* Copy attribute for modification. */
6f4f49b2 8432 attr_new = attr;
718e3744 8433
d62a17ae 8434 if (red->redist_metric_flag)
8435 attr_new.med = red->redist_metric;
718e3744 8436
d62a17ae 8437 /* Apply route-map. */
8438 if (red->rmap.name) {
6006b807 8439 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8440 rmap_path.peer = bgp->peer_self;
8441 rmap_path.attr = &attr_new;
718e3744 8442
d62a17ae 8443 SET_FLAG(bgp->peer_self->rmap_type,
8444 PEER_RMAP_TYPE_REDISTRIBUTE);
8445
1782514f 8446 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8447
8448 bgp->peer_self->rmap_type = 0;
8449
8450 if (ret == RMAP_DENYMATCH) {
8451 /* Free uninterned attribute. */
8452 bgp_attr_flush(&attr_new);
8453
8454 /* Unintern original. */
8455 aspath_unintern(&attr.aspath);
8456 bgp_redistribute_delete(bgp, p, type, instance);
8457 return;
8458 }
8459 }
8460
637e5ba4 8461 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8462 bgp_attr_add_gshut_community(&attr_new);
8463
d62a17ae 8464 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8465 SAFI_UNICAST, p, NULL);
8466
8467 new_attr = bgp_attr_intern(&attr_new);
8468
9bcb3eef 8469 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8470 if (bpi->peer == bgp->peer_self
8471 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8472 break;
8473
40381db7 8474 if (bpi) {
d62a17ae 8475 /* Ensure the (source route) type is updated. */
40381db7
DS
8476 bpi->type = type;
8477 if (attrhash_cmp(bpi->attr, new_attr)
8478 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8479 bgp_attr_unintern(&new_attr);
8480 aspath_unintern(&attr.aspath);
9bcb3eef 8481 bgp_dest_unlock_node(bn);
d62a17ae 8482 return;
8483 } else {
8484 /* The attribute is changed. */
40381db7 8485 bgp_path_info_set_flag(bn, bpi,
18ee8310 8486 BGP_PATH_ATTR_CHANGED);
d62a17ae 8487
8488 /* Rewrite BGP route information. */
40381db7
DS
8489 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8490 bgp_path_info_restore(bn, bpi);
d62a17ae 8491 else
40381db7
DS
8492 bgp_aggregate_decrement(
8493 bgp, p, bpi, afi, SAFI_UNICAST);
8494 bgp_attr_unintern(&bpi->attr);
8495 bpi->attr = new_attr;
8496 bpi->uptime = bgp_clock();
d62a17ae 8497
8498 /* Process change. */
40381db7 8499 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8500 SAFI_UNICAST);
8501 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8502 bgp_dest_unlock_node(bn);
d62a17ae 8503 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8504
8505 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8506 || (bgp->inst_type
8507 == BGP_INSTANCE_TYPE_DEFAULT)) {
8508
8509 vpn_leak_from_vrf_update(
40381db7 8510 bgp_get_default(), bgp, bpi);
ddb5b488 8511 }
d62a17ae 8512 return;
8513 }
8514 }
8515
8516 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8517 bgp->peer_self, new_attr, bn);
1defdda8 8518 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8519
8520 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8521 bgp_path_info_add(bn, new);
9bcb3eef 8522 bgp_dest_unlock_node(bn);
be785e35 8523 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8524 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8525
8526 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8527 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8528
8529 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8530 }
d62a17ae 8531 }
8532
8533 /* Unintern original. */
8534 aspath_unintern(&attr.aspath);
718e3744 8535}
8536
d7c0a89a
QY
8537void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8538 unsigned short instance)
718e3744 8539{
d62a17ae 8540 afi_t afi;
9bcb3eef 8541 struct bgp_dest *dest;
40381db7 8542 struct bgp_path_info *pi;
d62a17ae 8543 struct bgp_redist *red;
718e3744 8544
d62a17ae 8545 afi = family2afi(p->family);
718e3744 8546
d62a17ae 8547 red = bgp_redist_lookup(bgp, afi, type, instance);
8548 if (red) {
9bcb3eef
DS
8549 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8550 SAFI_UNICAST, p, NULL);
d62a17ae 8551
9bcb3eef 8552 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8553 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8554 break;
8555
40381db7 8556 if (pi) {
ddb5b488
PZ
8557 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8558 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8559
8560 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8561 bgp, pi);
ddb5b488 8562 }
40381db7 8563 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8564 bgp_path_info_delete(dest, pi);
8565 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8566 }
9bcb3eef 8567 bgp_dest_unlock_node(dest);
d62a17ae 8568 }
8569}
8570
8571/* Withdraw specified route type's route. */
8572void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8573 unsigned short instance)
d62a17ae 8574{
9bcb3eef 8575 struct bgp_dest *dest;
40381db7 8576 struct bgp_path_info *pi;
d62a17ae 8577 struct bgp_table *table;
8578
8579 table = bgp->rib[afi][SAFI_UNICAST];
8580
9bcb3eef
DS
8581 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8582 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8583 if (pi->peer == bgp->peer_self && pi->type == type
8584 && pi->instance == instance)
d62a17ae 8585 break;
8586
40381db7 8587 if (pi) {
ddb5b488
PZ
8588 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8589 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8590
8591 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8592 bgp, pi);
ddb5b488 8593 }
9bcb3eef 8594 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8595 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8596 bgp_path_info_delete(dest, pi);
8597 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8598 }
718e3744 8599 }
718e3744 8600}
6b0655a2 8601
718e3744 8602/* Static function to display route. */
7d3cae70
DA
8603static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8604 struct vty *vty, json_object *json, bool wide)
718e3744 8605{
be054588 8606 int len = 0;
d62a17ae 8607 char buf[BUFSIZ];
718e3744 8608
d62a17ae 8609 if (p->family == AF_INET) {
c6462ff4 8610 if (!json) {
8228a9a7 8611 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8612 } else {
8613 json_object_string_add(json, "prefix",
8614 inet_ntop(p->family,
8615 &p->u.prefix, buf,
8616 BUFSIZ));
8617 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8618 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8619 json_object_int_add(json, "version", dest->version);
c6462ff4 8620 }
d62a17ae 8621 } else if (p->family == AF_ETHERNET) {
8228a9a7 8622 len = vty_out(vty, "%pFX", p);
b03b8898 8623 } else if (p->family == AF_EVPN) {
57f7feb6 8624 if (!json)
2dbe669b 8625 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8626 else
60466a63 8627 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8628 } else if (p->family == AF_FLOWSPEC) {
8629 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8630 json ?
8631 NLRI_STRING_FORMAT_JSON_SIMPLE :
8632 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8633 } else {
c6462ff4 8634 if (!json)
8228a9a7 8635 len = vty_out(vty, "%pFX", p);
50e05855
AD
8636 else {
8637 json_object_string_add(json, "prefix",
8638 inet_ntop(p->family,
8639 &p->u.prefix, buf,
8640 BUFSIZ));
8641 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8642 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8643 json_object_int_add(json, "version", dest->version);
37d4e0df 8644 }
9c92b5f7 8645 }
d62a17ae 8646
9c92b5f7 8647 if (!json) {
ae248832 8648 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8649 if (len < 1)
8650 vty_out(vty, "\n%*s", 20, " ");
8651 else
8652 vty_out(vty, "%*s", len, " ");
8653 }
718e3744 8654}
8655
d62a17ae 8656enum bgp_display_type {
8657 normal_list,
718e3744 8658};
8659
1d7260a1 8660const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8661{
8662 switch (reason) {
8663 case bgp_path_selection_none:
8664 return "Nothing to Select";
8665 case bgp_path_selection_first:
8666 return "First path received";
8667 case bgp_path_selection_evpn_sticky_mac:
8668 return "EVPN Sticky Mac";
8669 case bgp_path_selection_evpn_seq:
8670 return "EVPN sequence number";
8671 case bgp_path_selection_evpn_lower_ip:
8672 return "EVPN lower IP";
8673 case bgp_path_selection_evpn_local_path:
8674 return "EVPN local ES path";
8675 case bgp_path_selection_evpn_non_proxy:
8676 return "EVPN non proxy";
8677 case bgp_path_selection_weight:
8678 return "Weight";
8679 case bgp_path_selection_local_pref:
8680 return "Local Pref";
8681 case bgp_path_selection_local_route:
8682 return "Local Route";
8683 case bgp_path_selection_confed_as_path:
8684 return "Confederation based AS Path";
8685 case bgp_path_selection_as_path:
8686 return "AS Path";
8687 case bgp_path_selection_origin:
8688 return "Origin";
8689 case bgp_path_selection_med:
8690 return "MED";
8691 case bgp_path_selection_peer:
8692 return "Peer Type";
8693 case bgp_path_selection_confed:
8694 return "Confed Peer Type";
8695 case bgp_path_selection_igp_metric:
8696 return "IGP Metric";
8697 case bgp_path_selection_older:
8698 return "Older Path";
8699 case bgp_path_selection_router_id:
8700 return "Router ID";
8701 case bgp_path_selection_cluster_length:
bcab253c 8702 return "Cluster length";
bbb46eb5
DA
8703 case bgp_path_selection_stale:
8704 return "Path Staleness";
8705 case bgp_path_selection_local_configured:
8706 return "Locally configured route";
8707 case bgp_path_selection_neighbor_ip:
8708 return "Neighbor IP";
8709 case bgp_path_selection_default:
8710 return "Nothing left to compare";
8711 }
8712 return "Invalid (internal error)";
8713}
8714
18ee8310 8715/* Print the short form route status for a bgp_path_info */
4b7e6066 8716static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8717 struct bgp_path_info *path,
82c298be 8718 const struct prefix *p,
d62a17ae 8719 json_object *json_path)
718e3744 8720{
82c298be
DA
8721 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8722
d62a17ae 8723 if (json_path) {
b05a1c8b 8724
d62a17ae 8725 /* Route status display. */
9b6d8fcf 8726 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8727 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8728
9b6d8fcf 8729 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8730 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8731
4056a5f6 8732 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8733 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8734
9b6d8fcf
DS
8735 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8736 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8737 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8738
d62a17ae 8739 /* Selected */
9b6d8fcf 8740 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8741 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8742
9b6d8fcf 8743 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8744 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8745
bbb46eb5 8746 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8747 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8748 json_object_string_add(json_path, "selectionReason",
8749 bgp_path_selection_reason2str(
8750 path->net->reason));
8751 }
b05a1c8b 8752
9b6d8fcf 8753 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8754 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8755
d62a17ae 8756 /* Internal route. */
9b6d8fcf
DS
8757 if ((path->peer->as)
8758 && (path->peer->as == path->peer->local_as))
d62a17ae 8759 json_object_string_add(json_path, "pathFrom",
8760 "internal");
8761 else
8762 json_object_string_add(json_path, "pathFrom",
8763 "external");
b05a1c8b 8764
d62a17ae 8765 return;
8766 }
b05a1c8b 8767
82c298be
DA
8768 /* RPKI validation state */
8769 rpki_state =
8770 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8771
8772 if (rpki_state == RPKI_VALID)
8773 vty_out(vty, "V");
8774 else if (rpki_state == RPKI_INVALID)
8775 vty_out(vty, "I");
8776 else if (rpki_state == RPKI_NOTFOUND)
8777 vty_out(vty, "N");
8778
d62a17ae 8779 /* Route status display. */
9b6d8fcf 8780 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8781 vty_out(vty, "R");
9b6d8fcf 8782 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8783 vty_out(vty, "S");
4056a5f6 8784 else if (bgp_path_suppressed(path))
d62a17ae 8785 vty_out(vty, "s");
9b6d8fcf
DS
8786 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8787 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8788 vty_out(vty, "*");
8789 else
8790 vty_out(vty, " ");
8791
8792 /* Selected */
9b6d8fcf 8793 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8794 vty_out(vty, "h");
9b6d8fcf 8795 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8796 vty_out(vty, "d");
9b6d8fcf 8797 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8798 vty_out(vty, ">");
9b6d8fcf 8799 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8800 vty_out(vty, "=");
8801 else
8802 vty_out(vty, " ");
718e3744 8803
d62a17ae 8804 /* Internal route. */
9b6d8fcf
DS
8805 if (path->peer && (path->peer->as)
8806 && (path->peer->as == path->peer->local_as))
d62a17ae 8807 vty_out(vty, "i");
8808 else
8809 vty_out(vty, " ");
b40d939b 8810}
8811
2ba93fd6
DA
8812static char *bgp_nexthop_hostname(struct peer *peer,
8813 struct bgp_nexthop_cache *bnc)
25b5da8d 8814{
892fedb6 8815 if (peer->hostname
aef999a2 8816 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8817 return peer->hostname;
8818 return NULL;
8819}
8820
b40d939b 8821/* called from terminal list command */
bd494ec5 8822void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8823 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8824 json_object *json_paths, bool wide)
d62a17ae 8825{
aef999a2 8826 int len;
515c2602 8827 struct attr *attr = path->attr;
d62a17ae 8828 json_object *json_path = NULL;
8829 json_object *json_nexthops = NULL;
8830 json_object *json_nexthop_global = NULL;
8831 json_object *json_nexthop_ll = NULL;
6f214dd3 8832 json_object *json_ext_community = NULL;
9df8b37c 8833 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8834 bool nexthop_self =
9b6d8fcf 8835 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8836 bool nexthop_othervrf = false;
43089216 8837 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8838 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8839 char *nexthop_hostname =
8840 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8841 char esi_buf[ESI_STR_LEN];
d62a17ae 8842
8843 if (json_paths)
8844 json_path = json_object_new_object();
8845
8846 /* short status lead text */
82c298be 8847 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8848
8849 if (!json_paths) {
8850 /* print prefix and mask */
8851 if (!display)
7d3cae70 8852 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8853 else
ae248832 8854 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8855 } else {
7d3cae70 8856 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8857 }
47fc97cc 8858
9df8b37c
PZ
8859 /*
8860 * If vrf id of nexthop is different from that of prefix,
8861 * set up printable string to append
8862 */
9b6d8fcf 8863 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8864 const char *self = "";
8865
8866 if (nexthop_self)
8867 self = "<";
8868
8869 nexthop_othervrf = true;
9b6d8fcf 8870 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8871
9b6d8fcf 8872 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8873 snprintf(vrf_id_str, sizeof(vrf_id_str),
8874 "@%s%s", VRFID_NONE_STR, self);
8875 else
8876 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8877 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8878
9b6d8fcf
DS
8879 if (path->extra->bgp_orig->inst_type
8880 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8881
9b6d8fcf 8882 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8883 } else {
8884 const char *self = "";
8885
8886 if (nexthop_self)
8887 self = "<";
8888
8889 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8890 }
8891
445c2480
DS
8892 /*
8893 * For ENCAP and EVPN routes, nexthop address family is not
8894 * neccessarily the same as the prefix address family.
8895 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8896 * EVPN routes are also exchanged with a MP nexthop. Currently,
8897 * this
8898 * is only IPv4, the value will be present in either
8899 * attr->nexthop or
8900 * attr->mp_nexthop_global_in
8901 */
8902 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8903 char buf[BUFSIZ];
8904 char nexthop[128];
8905 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8906
8907 switch (af) {
8908 case AF_INET:
772270f3
QY
8909 snprintf(nexthop, sizeof(nexthop), "%s",
8910 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8911 BUFSIZ));
445c2480
DS
8912 break;
8913 case AF_INET6:
772270f3
QY
8914 snprintf(nexthop, sizeof(nexthop), "%s",
8915 inet_ntop(af, &attr->mp_nexthop_global, buf,
8916 BUFSIZ));
445c2480
DS
8917 break;
8918 default:
772270f3 8919 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8920 break;
d62a17ae 8921 }
d62a17ae 8922
445c2480
DS
8923 if (json_paths) {
8924 json_nexthop_global = json_object_new_object();
8925
515c2602
DA
8926 json_object_string_add(json_nexthop_global, "ip",
8927 nexthop);
8928
939a97f4 8929 if (path->peer->hostname)
515c2602
DA
8930 json_object_string_add(json_nexthop_global,
8931 "hostname",
939a97f4 8932 path->peer->hostname);
515c2602
DA
8933
8934 json_object_string_add(json_nexthop_global, "afi",
8935 (af == AF_INET) ? "ipv4"
8936 : "ipv6");
445c2480
DS
8937 json_object_boolean_true_add(json_nexthop_global,
8938 "used");
aef999a2
DA
8939 } else {
8940 if (nexthop_hostname)
8941 len = vty_out(vty, "%s(%s)%s", nexthop,
8942 nexthop_hostname, vrf_id_str);
8943 else
8944 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8945
ae248832 8946 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8947 if (len < 1)
8948 vty_out(vty, "\n%*s", 36, " ");
8949 else
8950 vty_out(vty, "%*s", len, " ");
8951 }
445c2480
DS
8952 } else if (safi == SAFI_EVPN) {
8953 if (json_paths) {
8954 json_nexthop_global = json_object_new_object();
8955
c949c771
DA
8956 json_object_string_addf(json_nexthop_global, "ip",
8957 "%pI4", &attr->nexthop);
515c2602 8958
939a97f4 8959 if (path->peer->hostname)
515c2602
DA
8960 json_object_string_add(json_nexthop_global,
8961 "hostname",
939a97f4 8962 path->peer->hostname);
515c2602 8963
a4d82a8a
PZ
8964 json_object_string_add(json_nexthop_global, "afi",
8965 "ipv4");
445c2480
DS
8966 json_object_boolean_true_add(json_nexthop_global,
8967 "used");
aef999a2
DA
8968 } else {
8969 if (nexthop_hostname)
8970 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8971 nexthop_hostname, vrf_id_str);
8972 else
8973 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8974 vrf_id_str);
8975
ae248832 8976 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8977 if (len < 1)
8978 vty_out(vty, "\n%*s", 36, " ");
8979 else
8980 vty_out(vty, "%*s", len, " ");
8981 }
d33fc23b 8982 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8983 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8984 if (json_paths) {
8985 json_nexthop_global = json_object_new_object();
515c2602 8986
026b914a
PG
8987 json_object_string_add(json_nexthop_global,
8988 "afi", "ipv4");
c949c771
DA
8989 json_object_string_addf(json_nexthop_global,
8990 "ip", "%pI4",
8991 &attr->nexthop);
515c2602 8992
939a97f4 8993 if (path->peer->hostname)
515c2602
DA
8994 json_object_string_add(
8995 json_nexthop_global, "hostname",
939a97f4 8996 path->peer->hostname);
515c2602 8997
50e05855
AD
8998 json_object_boolean_true_add(
8999 json_nexthop_global,
026b914a
PG
9000 "used");
9001 } else {
aef999a2
DA
9002 if (nexthop_hostname)
9003 len = vty_out(vty, "%pI4(%s)%s",
9004 &attr->nexthop,
9005 nexthop_hostname,
9006 vrf_id_str);
9007 else
9008 len = vty_out(vty, "%pI4%s",
9009 &attr->nexthop,
9010 vrf_id_str);
9011
ae248832 9012 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9013 if (len < 1)
9014 vty_out(vty, "\n%*s", 36, " ");
9015 else
9016 vty_out(vty, "%*s", len, " ");
026b914a
PG
9017 }
9018 }
d33fc23b 9019 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
9020 if (json_paths) {
9021 json_nexthop_global = json_object_new_object();
d62a17ae 9022
c949c771
DA
9023 json_object_string_addf(json_nexthop_global, "ip",
9024 "%pI4", &attr->nexthop);
515c2602 9025
939a97f4 9026 if (path->peer->hostname)
515c2602
DA
9027 json_object_string_add(json_nexthop_global,
9028 "hostname",
939a97f4 9029 path->peer->hostname);
445c2480 9030
a4d82a8a
PZ
9031 json_object_string_add(json_nexthop_global, "afi",
9032 "ipv4");
445c2480
DS
9033 json_object_boolean_true_add(json_nexthop_global,
9034 "used");
9035 } else {
aef999a2
DA
9036 if (nexthop_hostname)
9037 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9038 nexthop_hostname, vrf_id_str);
9039 else
9040 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9041 vrf_id_str);
9df8b37c 9042
ae248832 9043 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9044 if (len < 1)
9045 vty_out(vty, "\n%*s", 36, " ");
9046 else
9047 vty_out(vty, "%*s", len, " ");
d62a17ae 9048 }
445c2480 9049 }
b05a1c8b 9050
445c2480 9051 /* IPv6 Next Hop */
a4d82a8a 9052 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
9053 if (json_paths) {
9054 json_nexthop_global = json_object_new_object();
c949c771
DA
9055 json_object_string_addf(json_nexthop_global, "ip",
9056 "%pI6",
9057 &attr->mp_nexthop_global);
515c2602 9058
939a97f4 9059 if (path->peer->hostname)
515c2602
DA
9060 json_object_string_add(json_nexthop_global,
9061 "hostname",
939a97f4 9062 path->peer->hostname);
515c2602 9063
a4d82a8a
PZ
9064 json_object_string_add(json_nexthop_global, "afi",
9065 "ipv6");
9066 json_object_string_add(json_nexthop_global, "scope",
9067 "global");
445c2480
DS
9068
9069 /* We display both LL & GL if both have been
9070 * received */
0606039c
DA
9071 if ((attr->mp_nexthop_len
9072 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9073 || (path->peer->conf_if)) {
a4d82a8a 9074 json_nexthop_ll = json_object_new_object();
c949c771
DA
9075 json_object_string_addf(
9076 json_nexthop_ll, "ip", "%pI6",
9077 &attr->mp_nexthop_local);
515c2602 9078
939a97f4 9079 if (path->peer->hostname)
515c2602
DA
9080 json_object_string_add(
9081 json_nexthop_ll, "hostname",
939a97f4 9082 path->peer->hostname);
515c2602 9083
a4d82a8a
PZ
9084 json_object_string_add(json_nexthop_ll, "afi",
9085 "ipv6");
9086 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9087 "link-local");
d62a17ae 9088
a4d82a8a
PZ
9089 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9090 &attr->mp_nexthop_local)
445c2480
DS
9091 != 0)
9092 && !attr->mp_nexthop_prefer_global)
d62a17ae 9093 json_object_boolean_true_add(
a4d82a8a 9094 json_nexthop_ll, "used");
445c2480
DS
9095 else
9096 json_object_boolean_true_add(
a4d82a8a 9097 json_nexthop_global, "used");
445c2480
DS
9098 } else
9099 json_object_boolean_true_add(
9100 json_nexthop_global, "used");
9101 } else {
9102 /* Display LL if LL/Global both in table unless
9103 * prefer-global is set */
0606039c
DA
9104 if (((attr->mp_nexthop_len
9105 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9106 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9107 || (path->peer->conf_if)) {
9108 if (path->peer->conf_if) {
a4d82a8a 9109 len = vty_out(vty, "%s",
9b6d8fcf 9110 path->peer->conf_if);
ae248832
MK
9111 /* len of IPv6 addr + max len of def
9112 * ifname */
9113 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9114
9115 if (len < 1)
a4d82a8a 9116 vty_out(vty, "\n%*s", 36, " ");
445c2480 9117 else
a4d82a8a 9118 vty_out(vty, "%*s", len, " ");
d62a17ae 9119 } else {
aef999a2
DA
9120 if (nexthop_hostname)
9121 len = vty_out(
9122 vty, "%pI6(%s)%s",
9123 &attr->mp_nexthop_local,
9124 nexthop_hostname,
9125 vrf_id_str);
9126 else
9127 len = vty_out(
9128 vty, "%pI6%s",
9129 &attr->mp_nexthop_local,
9130 vrf_id_str);
9131
ae248832 9132 len = wide ? (41 - len) : (16 - len);
d62a17ae 9133
9134 if (len < 1)
a4d82a8a 9135 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9136 else
a4d82a8a 9137 vty_out(vty, "%*s", len, " ");
d62a17ae 9138 }
445c2480 9139 } else {
aef999a2
DA
9140 if (nexthop_hostname)
9141 len = vty_out(vty, "%pI6(%s)%s",
9142 &attr->mp_nexthop_global,
9143 nexthop_hostname,
9144 vrf_id_str);
9145 else
9146 len = vty_out(vty, "%pI6%s",
9147 &attr->mp_nexthop_global,
9148 vrf_id_str);
9149
ae248832 9150 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9151
9152 if (len < 1)
9153 vty_out(vty, "\n%*s", 36, " ");
9154 else
9155 vty_out(vty, "%*s", len, " ");
d62a17ae 9156 }
9157 }
445c2480 9158 }
718e3744 9159
445c2480
DS
9160 /* MED/Metric */
9161 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9162 if (json_paths)
50e05855 9163 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9164 else if (wide)
9165 vty_out(vty, "%7u", attr->med);
0fbac0b4 9166 else
445c2480 9167 vty_out(vty, "%10u", attr->med);
ae248832
MK
9168 else if (!json_paths) {
9169 if (wide)
9170 vty_out(vty, "%*s", 7, " ");
9171 else
9172 vty_out(vty, "%*s", 10, " ");
9173 }
d62a17ae 9174
445c2480
DS
9175 /* Local Pref */
9176 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9177 if (json_paths)
50e05855 9178 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9179 attr->local_pref);
9180 else
445c2480
DS
9181 vty_out(vty, "%7u", attr->local_pref);
9182 else if (!json_paths)
9183 vty_out(vty, " ");
d62a17ae 9184
445c2480
DS
9185 if (json_paths)
9186 json_object_int_add(json_path, "weight", attr->weight);
9187 else
9188 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9189
47e12884
DA
9190 if (json_paths)
9191 json_object_string_addf(json_path, "peerId", "%pSU",
9192 &path->peer->su);
b05a1c8b 9193
445c2480
DS
9194 /* Print aspath */
9195 if (attr->aspath) {
0fbac0b4 9196 if (json_paths)
50e05855 9197 json_object_string_add(json_path, "path",
0fbac0b4
DA
9198 attr->aspath->str);
9199 else
445c2480 9200 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9201 }
f1aa5d8a 9202
445c2480
DS
9203 /* Print origin */
9204 if (json_paths)
a4d82a8a
PZ
9205 json_object_string_add(json_path, "origin",
9206 bgp_origin_long_str[attr->origin]);
445c2480
DS
9207 else
9208 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9209
9df8b37c 9210 if (json_paths) {
d071f237 9211 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9212 json_object_string_add(json_path, "esi",
9213 esi_to_str(&attr->esi,
9214 esi_buf, sizeof(esi_buf)));
9215 }
6f214dd3
CS
9216 if (safi == SAFI_EVPN &&
9217 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9218 json_ext_community = json_object_new_object();
b53e67a3
DA
9219 json_object_string_add(
9220 json_ext_community, "string",
9221 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9222 json_object_object_add(json_path,
9223 "extendedCommunity",
9224 json_ext_community);
9225 }
9226
9df8b37c
PZ
9227 if (nexthop_self)
9228 json_object_boolean_true_add(json_path,
9229 "announceNexthopSelf");
9230 if (nexthop_othervrf) {
9231 json_object_string_add(json_path, "nhVrfName",
9232 nexthop_vrfname);
9233
9234 json_object_int_add(json_path, "nhVrfId",
9235 ((nexthop_vrfid == VRF_UNKNOWN)
9236 ? -1
9237 : (int)nexthop_vrfid));
9238 }
9239 }
9240
d62a17ae 9241 if (json_paths) {
9242 if (json_nexthop_global || json_nexthop_ll) {
9243 json_nexthops = json_object_new_array();
f1aa5d8a 9244
d62a17ae 9245 if (json_nexthop_global)
9246 json_object_array_add(json_nexthops,
9247 json_nexthop_global);
f1aa5d8a 9248
d62a17ae 9249 if (json_nexthop_ll)
9250 json_object_array_add(json_nexthops,
9251 json_nexthop_ll);
f1aa5d8a 9252
d62a17ae 9253 json_object_object_add(json_path, "nexthops",
9254 json_nexthops);
9255 }
9256
9257 json_object_array_add(json_paths, json_path);
9258 } else {
9259 vty_out(vty, "\n");
6f214dd3 9260
b5e140c8 9261 if (safi == SAFI_EVPN) {
d071f237 9262 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9263 /* XXX - add these params to the json out */
b5e140c8 9264 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9265 vty_out(vty, "ESI:%s",
9266 esi_to_str(&attr->esi, esi_buf,
9267 sizeof(esi_buf)));
60605cbc 9268
229587fb 9269 vty_out(vty, "\n");
b5e140c8
AK
9270 }
9271 if (attr->flag &
9272 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9273 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9274 vty_out(vty, "%s\n",
9275 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9276 }
6f214dd3
CS
9277 }
9278
49e5a4a0 9279#ifdef ENABLE_BGP_VNC
d62a17ae 9280 /* prints an additional line, indented, with VNC info, if
9281 * present */
9282 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9283 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9284#endif
d62a17ae 9285 }
9286}
718e3744 9287
9288/* called from terminal list command */
7d3cae70
DA
9289void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9290 const struct prefix *p, struct attr *attr, safi_t safi,
9291 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9292{
9293 json_object *json_status = NULL;
9294 json_object *json_net = NULL;
aef999a2 9295 int len;
d62a17ae 9296 char buff[BUFSIZ];
dc387b0f 9297
d62a17ae 9298 /* Route status display. */
9299 if (use_json) {
9300 json_status = json_object_new_object();
9301 json_net = json_object_new_object();
9302 } else {
9303 vty_out(vty, "*");
9304 vty_out(vty, ">");
9305 vty_out(vty, " ");
9306 }
718e3744 9307
d62a17ae 9308 /* print prefix and mask */
50e05855 9309 if (use_json) {
dc387b0f
LK
9310 if (safi == SAFI_EVPN)
9311 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9312 else if (p->family == AF_INET || p->family == AF_INET6) {
9313 json_object_string_add(
9314 json_net, "addrPrefix",
9315 inet_ntop(p->family, &p->u.prefix, buff,
9316 BUFSIZ));
9317 json_object_int_add(json_net, "prefixLen",
9318 p->prefixlen);
67d7e256 9319 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9320 }
50e05855 9321 } else
7d3cae70 9322 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9323
9324 /* Print attribute */
9325 if (attr) {
9326 if (use_json) {
9327 if (p->family == AF_INET
9328 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9329 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9330 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9331 json_object_string_addf(
9332 json_net, "nextHop", "%pI4",
9333 &attr->mp_nexthop_global_in);
d62a17ae 9334 else
c949c771
DA
9335 json_object_string_addf(
9336 json_net, "nextHop", "%pI4",
9337 &attr->nexthop);
d62a17ae 9338 } else if (p->family == AF_INET6
9339 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9340 json_object_string_addf(
9341 json_net, "nextHopGlobal", "%pI6",
9342 &attr->mp_nexthop_global);
23d0a753
DA
9343 } else if (p->family == AF_EVPN
9344 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9345 json_object_string_addf(
9346 json_net, "nextHop", "%pI4",
9347 &attr->mp_nexthop_global_in);
23d0a753 9348 }
d62a17ae 9349
9350 if (attr->flag
9351 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9352 json_object_int_add(json_net, "metric",
9353 attr->med);
9354
0fbac0b4 9355 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9356 json_object_int_add(json_net, "locPrf",
0fbac0b4 9357 attr->local_pref);
d62a17ae 9358
9359 json_object_int_add(json_net, "weight", attr->weight);
9360
9361 /* Print aspath */
0fbac0b4 9362 if (attr->aspath)
50e05855 9363 json_object_string_add(json_net, "path",
0fbac0b4 9364 attr->aspath->str);
d62a17ae 9365
9366 /* Print origin */
9367 json_object_string_add(json_net, "bgpOriginCode",
9368 bgp_origin_str[attr->origin]);
9369 } else {
9370 if (p->family == AF_INET
9371 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9372 || safi == SAFI_EVPN
9373 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9374 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9375 || safi == SAFI_EVPN)
23d0a753
DA
9376 vty_out(vty, "%-16pI4",
9377 &attr->mp_nexthop_global_in);
ae248832 9378 else if (wide)
23d0a753 9379 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9380 else
23d0a753 9381 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9382 } else if (p->family == AF_INET6
9383 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9384 char buf[BUFSIZ];
9385
9386 len = vty_out(
9387 vty, "%s",
9388 inet_ntop(AF_INET6,
9389 &attr->mp_nexthop_global, buf,
9390 BUFSIZ));
ae248832 9391 len = wide ? (41 - len) : (16 - len);
d62a17ae 9392 if (len < 1)
9393 vty_out(vty, "\n%*s", 36, " ");
9394 else
9395 vty_out(vty, "%*s", len, " ");
9396 }
9397 if (attr->flag
9398 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9399 if (wide)
9400 vty_out(vty, "%7u", attr->med);
9401 else
9402 vty_out(vty, "%10u", attr->med);
9403 else if (wide)
9404 vty_out(vty, " ");
d62a17ae 9405 else
9406 vty_out(vty, " ");
718e3744 9407
d62a17ae 9408 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9409 vty_out(vty, "%7u", attr->local_pref);
9410 else
9411 vty_out(vty, " ");
9412
9413 vty_out(vty, "%7u ", attr->weight);
9414
9415 /* Print aspath */
9416 if (attr->aspath)
9417 aspath_print_vty(vty, "%s", attr->aspath, " ");
9418
9419 /* Print origin */
9420 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9421 }
9422 }
9423 if (use_json) {
9424 json_object_boolean_true_add(json_status, "*");
9425 json_object_boolean_true_add(json_status, ">");
9426 json_object_object_add(json_net, "appliedStatusSymbols",
9427 json_status);
1608ff77 9428
dc387b0f
LK
9429 prefix2str(p, buff, PREFIX_STRLEN);
9430 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9431 } else
9432 vty_out(vty, "\n");
9433}
9434
bd494ec5 9435void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9436 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9437 json_object *json)
9438{
9439 json_object *json_out = NULL;
9440 struct attr *attr;
9441 mpls_label_t label = MPLS_INVALID_LABEL;
9442
9b6d8fcf 9443 if (!path->extra)
d62a17ae 9444 return;
9445
9446 if (json)
9447 json_out = json_object_new_object();
9448
9449 /* short status lead text */
82c298be 9450 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9451
9452 /* print prefix and mask */
9453 if (json == NULL) {
9454 if (!display)
7d3cae70 9455 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9456 else
9457 vty_out(vty, "%*s", 17, " ");
9458 }
9459
9460 /* Print attribute */
9b6d8fcf 9461 attr = path->attr;
05864da7
DS
9462 if (((p->family == AF_INET)
9463 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9464 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9465 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9466 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9467 || safi == SAFI_EVPN) {
9468 if (json)
c949c771
DA
9469 json_object_string_addf(
9470 json_out, "mpNexthopGlobalIn", "%pI4",
9471 &attr->mp_nexthop_global_in);
05864da7 9472 else
23d0a753
DA
9473 vty_out(vty, "%-16pI4",
9474 &attr->mp_nexthop_global_in);
05864da7
DS
9475 } else {
9476 if (json)
c949c771
DA
9477 json_object_string_addf(json_out, "nexthop",
9478 "%pI4", &attr->nexthop);
05864da7 9479 else
23d0a753 9480 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9481 }
9482 } else if (((p->family == AF_INET6)
9483 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9484 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9485 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9486 char buf_a[512];
9487
9488 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9489 if (json)
c949c771
DA
9490 json_object_string_addf(
9491 json_out, "mpNexthopGlobalIn", "%pI6",
9492 &attr->mp_nexthop_global);
05864da7
DS
9493 else
9494 vty_out(vty, "%s",
9495 inet_ntop(AF_INET6,
9496 &attr->mp_nexthop_global,
9497 buf_a, sizeof(buf_a)));
9498 } else if (attr->mp_nexthop_len
9499 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9500 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9501 &attr->mp_nexthop_global,
9502 &attr->mp_nexthop_local);
9503 if (json)
9504 json_object_string_add(json_out,
9505 "mpNexthopGlobalLocal",
9506 buf_a);
9507 else
9508 vty_out(vty, "%s", buf_a);
d62a17ae 9509 }
9510 }
9511
9b6d8fcf 9512 label = decode_label(&path->extra->label[0]);
d62a17ae 9513
9514 if (bgp_is_valid_label(&label)) {
9515 if (json) {
9516 json_object_int_add(json_out, "notag", label);
9517 json_object_array_add(json, json_out);
9518 } else {
9519 vty_out(vty, "notag/%d", label);
9520 vty_out(vty, "\n");
9521 }
700ddfed
PG
9522 } else if (!json)
9523 vty_out(vty, "\n");
d62a17ae 9524}
718e3744 9525
bd494ec5 9526void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9527 struct bgp_path_info *path, int display,
d62a17ae 9528 json_object *json_paths)
718e3744 9529{
d62a17ae 9530 struct attr *attr;
d62a17ae 9531 json_object *json_path = NULL;
14f51eba
LK
9532 json_object *json_nexthop = NULL;
9533 json_object *json_overlay = NULL;
856ca177 9534
9b6d8fcf 9535 if (!path->extra)
d62a17ae 9536 return;
718e3744 9537
14f51eba
LK
9538 if (json_paths) {
9539 json_path = json_object_new_object();
9540 json_overlay = json_object_new_object();
9541 json_nexthop = json_object_new_object();
9542 }
9543
d62a17ae 9544 /* short status lead text */
82c298be 9545 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9546
d62a17ae 9547 /* print prefix and mask */
9548 if (!display)
7d3cae70 9549 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9550 else
9551 vty_out(vty, "%*s", 17, " ");
9552
9553 /* Print attribute */
9b6d8fcf 9554 attr = path->attr;
05864da7 9555 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9556
05864da7
DS
9557 switch (af) {
9558 case AF_INET:
05864da7 9559 if (!json_path) {
db66cf7c 9560 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9561 } else {
db66cf7c
DA
9562 json_object_string_addf(json_nexthop, "ip", "%pI4",
9563 &attr->mp_nexthop_global_in);
14f51eba 9564
05864da7 9565 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9566
05864da7
DS
9567 json_object_object_add(json_path, "nexthop",
9568 json_nexthop);
9569 }
9570 break;
9571 case AF_INET6:
05864da7 9572 if (!json_path) {
db66cf7c
DA
9573 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9574 &attr->mp_nexthop_local);
05864da7 9575 } else {
db66cf7c
DA
9576 json_object_string_addf(json_nexthop, "ipv6Global",
9577 "%pI6",
9578 &attr->mp_nexthop_global);
14f51eba 9579
db66cf7c
DA
9580 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9581 "%pI6",
9582 &attr->mp_nexthop_local);
14f51eba 9583
05864da7 9584 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9585
05864da7
DS
9586 json_object_object_add(json_path, "nexthop",
9587 json_nexthop);
9588 }
9589 break;
9590 default:
9591 if (!json_path) {
9592 vty_out(vty, "?");
9593 } else {
9594 json_object_string_add(json_nexthop, "Error",
9595 "Unsupported address-family");
77a2f8e5
DA
9596 json_object_string_add(json_nexthop, "error",
9597 "Unsupported address-family");
d62a17ae 9598 }
05864da7 9599 }
988258b4 9600
6c924775
DS
9601 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9602
05864da7 9603 if (!json_path)
db66cf7c 9604 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9605 else
db66cf7c 9606 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9607
b53e67a3 9608 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9609 char *mac = NULL;
9610 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9611 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9612 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9613
9614 if (routermac)
9615 mac = ecom_mac2str((char *)routermac->val);
9616 if (mac) {
9617 if (!json_path) {
c4efd0f4 9618 vty_out(vty, "/%s", mac);
05864da7
DS
9619 } else {
9620 json_object_string_add(json_overlay, "rmac",
9621 mac);
988258b4 9622 }
05864da7 9623 XFREE(MTYPE_TMP, mac);
988258b4 9624 }
05864da7 9625 }
718e3744 9626
05864da7
DS
9627 if (!json_path) {
9628 vty_out(vty, "\n");
9629 } else {
9630 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9631
05864da7 9632 json_object_array_add(json_paths, json_path);
14f51eba 9633 }
d62a17ae 9634}
718e3744 9635
d62a17ae 9636/* dampening route */
5f040085
DS
9637static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9638 struct bgp_path_info *path, int display,
9639 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9640 json_object *json_paths)
d62a17ae 9641{
e5be8c1d 9642 struct attr *attr = path->attr;
d62a17ae 9643 int len;
9644 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9645 json_object *json_path = NULL;
9646
9647 if (use_json)
9648 json_path = json_object_new_object();
d62a17ae 9649
9650 /* short status lead text */
e5be8c1d 9651 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9652
9653 /* print prefix and mask */
9654 if (!use_json) {
9655 if (!display)
7d3cae70 9656 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9657 else
9658 vty_out(vty, "%*s", 17, " ");
d62a17ae 9659
e5be8c1d
DA
9660 len = vty_out(vty, "%s", path->peer->host);
9661 len = 17 - len;
9662
9663 if (len < 1)
d62a17ae 9664 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9665 else
9666 vty_out(vty, "%*s", len, " ");
d62a17ae 9667
9b6d8fcf
DS
9668 vty_out(vty, "%s ",
9669 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9670 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9671 use_json, NULL));
d62a17ae 9672
e5be8c1d 9673 if (attr->aspath)
05864da7 9674 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9675
05864da7
DS
9676 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9677
d62a17ae 9678 vty_out(vty, "\n");
e5be8c1d
DA
9679 } else {
9680 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9681 safi, use_json, json_path);
9682
9683 if (attr->aspath)
9684 json_object_string_add(json_path, "asPath",
9685 attr->aspath->str);
9686
9687 json_object_string_add(json_path, "origin",
9688 bgp_origin_str[attr->origin]);
9689 json_object_string_add(json_path, "peerHost", path->peer->host);
9690
9691 json_object_array_add(json_paths, json_path);
9692 }
d62a17ae 9693}
718e3744 9694
d62a17ae 9695/* flap route */
5f040085
DS
9696static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9697 struct bgp_path_info *path, int display,
9698 afi_t afi, safi_t safi, bool use_json,
31258046 9699 json_object *json_paths)
784d3a42 9700{
31258046 9701 struct attr *attr = path->attr;
d62a17ae 9702 struct bgp_damp_info *bdi;
9703 char timebuf[BGP_UPTIME_LEN];
9704 int len;
31258046 9705 json_object *json_path = NULL;
784d3a42 9706
9b6d8fcf 9707 if (!path->extra)
d62a17ae 9708 return;
784d3a42 9709
31258046
DA
9710 if (use_json)
9711 json_path = json_object_new_object();
9712
9b6d8fcf 9713 bdi = path->extra->damp_info;
784d3a42 9714
d62a17ae 9715 /* short status lead text */
31258046 9716 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9717
d62a17ae 9718 if (!use_json) {
9719 if (!display)
7d3cae70 9720 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9721 else
9722 vty_out(vty, "%*s", 17, " ");
784d3a42 9723
31258046
DA
9724 len = vty_out(vty, "%s", path->peer->host);
9725 len = 16 - len;
9726 if (len < 1)
d62a17ae 9727 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9728 else
9729 vty_out(vty, "%*s", len, " ");
784d3a42 9730
31258046
DA
9731 len = vty_out(vty, "%d", bdi->flap);
9732 len = 5 - len;
9733 if (len < 1)
d62a17ae 9734 vty_out(vty, " ");
d62a17ae 9735 else
9736 vty_out(vty, "%*s", len, " ");
d62a17ae 9737
996c9314
LB
9738 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9739 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9740
31258046
DA
9741 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9742 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9743 vty_out(vty, "%s ",
9b6d8fcf 9744 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9745 BGP_UPTIME_LEN, afi,
31258046
DA
9746 safi, use_json, NULL));
9747 else
d62a17ae 9748 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9749
31258046 9750 if (attr->aspath)
05864da7 9751 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9752
05864da7
DS
9753 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9754
d62a17ae 9755 vty_out(vty, "\n");
31258046
DA
9756 } else {
9757 json_object_string_add(json_path, "peerHost", path->peer->host);
9758 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9759
9760 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9761 json_path);
9762
9763 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9764 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9765 bgp_damp_reuse_time_vty(vty, path, timebuf,
9766 BGP_UPTIME_LEN, afi, safi,
9767 use_json, json_path);
9768
9769 if (attr->aspath)
9770 json_object_string_add(json_path, "asPath",
9771 attr->aspath->str);
9772
9773 json_object_string_add(json_path, "origin",
9774 bgp_origin_str[attr->origin]);
9775
9776 json_object_array_add(json_paths, json_path);
9777 }
d62a17ae 9778}
9779
9780static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9781 int *first, const char *header,
9782 json_object *json_adv_to)
9783{
d62a17ae 9784 json_object *json_peer = NULL;
9785
9786 if (json_adv_to) {
9787 /* 'advertised-to' is a dictionary of peers we have advertised
9788 * this
9789 * prefix too. The key is the peer's IP or swpX, the value is
9790 * the
9791 * hostname if we know it and "" if not.
9792 */
9793 json_peer = json_object_new_object();
9794
9795 if (peer->hostname)
9796 json_object_string_add(json_peer, "hostname",
9797 peer->hostname);
9798
9799 if (peer->conf_if)
9800 json_object_object_add(json_adv_to, peer->conf_if,
9801 json_peer);
9802 else
47e12884
DA
9803 json_object_object_addf(json_adv_to, json_peer, "%pSU",
9804 &peer->su);
d62a17ae 9805 } else {
9806 if (*first) {
9807 vty_out(vty, "%s", header);
9808 *first = 0;
9809 }
9810
9811 if (peer->hostname
892fedb6 9812 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9813 if (peer->conf_if)
9814 vty_out(vty, " %s(%s)", peer->hostname,
9815 peer->conf_if);
9816 else
47e12884
DA
9817 vty_out(vty, " %s(%pSU)", peer->hostname,
9818 &peer->su);
d62a17ae 9819 } else {
9820 if (peer->conf_if)
9821 vty_out(vty, " %s", peer->conf_if);
9822 else
47e12884 9823 vty_out(vty, " %pSU", &peer->su);
d62a17ae 9824 }
9825 }
784d3a42
PG
9826}
9827
dcc68b5e
MS
9828static void route_vty_out_tx_ids(struct vty *vty,
9829 struct bgp_addpath_info_data *d)
9830{
9831 int i;
9832
9833 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9834 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9835 d->addpath_tx_id[i],
9836 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9837 }
9838}
9839
5e4d4c8a 9840static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9841 struct bgp_path_info *pi,
9842 struct attr *attr,
9843 json_object *json_path)
5e4d4c8a
AK
9844{
9845 char esi_buf[ESI_STR_LEN];
9846 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9847 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9848 ATTR_ES_PEER_ROUTER);
9849 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9850 ATTR_ES_PEER_ACTIVE);
9851 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9852 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9853 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9854 if (json_path) {
9855 json_object *json_es_info = NULL;
9856
9857 json_object_string_add(
9858 json_path, "esi",
9859 esi_buf);
9860 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9861 json_es_info = json_object_new_object();
9862 if (es_local)
9863 json_object_boolean_true_add(
9864 json_es_info, "localEs");
9865 if (peer_active)
9866 json_object_boolean_true_add(
9867 json_es_info, "peerActive");
9868 if (peer_proxy)
9869 json_object_boolean_true_add(
9870 json_es_info, "peerProxy");
9871 if (peer_router)
9872 json_object_boolean_true_add(
9873 json_es_info, "peerRouter");
9874 if (attr->mm_sync_seqnum)
9875 json_object_int_add(
9876 json_es_info, "peerSeq",
9877 attr->mm_sync_seqnum);
9878 json_object_object_add(
9879 json_path, "es_info",
9880 json_es_info);
9881 }
9882 } else {
9883 if (bgp_evpn_attr_is_sync(attr))
9884 vty_out(vty,
9885 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9886 esi_buf,
9887 es_local ? "local-es":"",
9888 peer_proxy ? "proxy " : "",
9889 peer_active ? "active ":"",
9890 peer_router ? "router ":"",
9891 attr->mm_sync_seqnum);
9892 else
9893 vty_out(vty, " ESI %s %s\n",
9894 esi_buf,
9895 es_local ? "local-es":"");
9896 }
9897}
9898
4933eaaf
DS
9899void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9900 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9901 enum rpki_states rpki_curr_state,
9902 json_object *json_paths)
d62a17ae 9903{
9904 char buf[INET6_ADDRSTRLEN];
9905 char buf1[BUFSIZ];
515c2602 9906 struct attr *attr = path->attr;
d62a17ae 9907 time_t tbuf;
9908 json_object *json_bestpath = NULL;
9909 json_object *json_cluster_list = NULL;
9910 json_object *json_cluster_list_list = NULL;
9911 json_object *json_ext_community = NULL;
9912 json_object *json_last_update = NULL;
7fd077aa 9913 json_object *json_pmsi = NULL;
d62a17ae 9914 json_object *json_nexthop_global = NULL;
9915 json_object *json_nexthop_ll = NULL;
9916 json_object *json_nexthops = NULL;
9917 json_object *json_path = NULL;
9918 json_object *json_peer = NULL;
9919 json_object *json_string = NULL;
9920 json_object *json_adv_to = NULL;
9921 int first = 0;
9922 struct listnode *node, *nnode;
9923 struct peer *peer;
be92fc9f 9924 bool addpath_capable;
d62a17ae 9925 int has_adj;
9926 unsigned int first_as;
1defdda8 9927 bool nexthop_self =
9b6d8fcf 9928 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9929 int i;
2ba93fd6
DA
9930 char *nexthop_hostname =
9931 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
9932 uint32_t ttl = 0;
9933 uint32_t bos = 0;
9934 uint32_t exp = 0;
9935 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 9936
9937 if (json_paths) {
9938 json_path = json_object_new_object();
9939 json_peer = json_object_new_object();
9940 json_nexthop_global = json_object_new_object();
9941 }
9942
8304dabf
AD
9943 if (safi == SAFI_EVPN) {
9944 if (!json_paths)
9945 vty_out(vty, " Route %pRN", bn);
9946 }
9947
44c69747 9948 if (path->extra) {
b57ba6d2 9949 char tag_buf[30];
d62a17ae 9950
d62a17ae 9951 tag_buf[0] = '\0';
9b6d8fcf
DS
9952 if (path->extra && path->extra->num_labels) {
9953 bgp_evpn_label2str(path->extra->label,
9954 path->extra->num_labels, tag_buf,
a4d82a8a 9955 sizeof(tag_buf));
d62a17ae 9956 }
d7325ee7 9957 if (safi == SAFI_EVPN) {
44c69747 9958 if (!json_paths) {
44c69747
LK
9959 if (tag_buf[0] != '\0')
9960 vty_out(vty, " VNI %s", tag_buf);
44c69747 9961 } else {
77a2f8e5 9962 if (tag_buf[0]) {
44c69747
LK
9963 json_object_string_add(json_path, "VNI",
9964 tag_buf);
77a2f8e5
DA
9965 json_object_string_add(json_path, "vni",
9966 tag_buf);
9967 }
44c69747 9968 }
d7325ee7
DD
9969 }
9970
44c69747 9971 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9972 struct bgp_path_info *parent_ri;
9bcb3eef 9973 struct bgp_dest *dest, *pdest;
d62a17ae 9974
9b6d8fcf 9975 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9976 dest = parent_ri->net;
9977 if (dest && dest->pdest) {
9978 pdest = dest->pdest;
9979 prefix_rd2str(
9980 (struct prefix_rd *)bgp_dest_get_prefix(
9981 pdest),
9982 buf1, sizeof(buf1));
d7325ee7 9983 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9984 vty_out(vty,
58bff4d1 9985 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9986 buf1,
9987 (struct prefix_evpn *)
9988 bgp_dest_get_prefix(
9989 dest),
9990 tag_buf);
58bff4d1
AK
9991 if (attr->es_flags & ATTR_ES_L3_NHG)
9992 vty_out(vty, ", L3NHG %s",
9993 (attr->es_flags
9994 & ATTR_ES_L3_NHG_ACTIVE)
9995 ? "active"
9996 : "inactive");
9997 vty_out(vty, "\n");
9998
d7325ee7 9999 } else
2dbe669b
DA
10000 vty_out(vty,
10001 " Imported from %s:%pFX\n",
10002 buf1,
10003 (struct prefix_evpn *)
10004 bgp_dest_get_prefix(
10005 dest));
d62a17ae 10006 }
10007 }
10008 }
d62a17ae 10009
8304dabf
AD
10010 if (safi == SAFI_EVPN
10011 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10012 char gwip_buf[INET6_ADDRSTRLEN];
10013
860e740b
IR
10014 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10015 sizeof(gwip_buf));
8304dabf
AD
10016
10017 if (json_paths)
10018 json_object_string_add(json_path, "gatewayIP",
10019 gwip_buf);
10020 else
10021 vty_out(vty, " Gateway IP %s", gwip_buf);
10022 }
10023
10024 if (safi == SAFI_EVPN)
10025 vty_out(vty, "\n");
10026
05864da7
DS
10027 /* Line1 display AS-path, Aggregator */
10028 if (attr->aspath) {
10029 if (json_paths) {
10030 if (!attr->aspath->json)
10031 aspath_str_update(attr->aspath, true);
10032 json_object_lock(attr->aspath->json);
10033 json_object_object_add(json_path, "aspath",
10034 attr->aspath->json);
10035 } else {
10036 if (attr->aspath->segments)
10037 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10038 else
05864da7 10039 vty_out(vty, " Local");
d62a17ae 10040 }
05864da7 10041 }
d62a17ae 10042
05864da7
DS
10043 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10044 if (json_paths)
10045 json_object_boolean_true_add(json_path, "removed");
10046 else
10047 vty_out(vty, ", (removed)");
10048 }
d62a17ae 10049
05864da7
DS
10050 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10051 if (json_paths)
10052 json_object_boolean_true_add(json_path, "stale");
10053 else
10054 vty_out(vty, ", (stale)");
10055 }
d62a17ae 10056
05864da7
DS
10057 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10058 if (json_paths) {
10059 json_object_int_add(json_path, "aggregatorAs",
10060 attr->aggregator_as);
c949c771
DA
10061 json_object_string_addf(json_path, "aggregatorId",
10062 "%pI4", &attr->aggregator_addr);
05864da7 10063 } else {
88d495a9
DA
10064 vty_out(vty, ", (aggregated by %u %pI4)",
10065 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10066 }
05864da7 10067 }
d62a17ae 10068
05864da7
DS
10069 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10070 PEER_FLAG_REFLECTOR_CLIENT)) {
10071 if (json_paths)
10072 json_object_boolean_true_add(json_path,
10073 "rxedFromRrClient");
10074 else
10075 vty_out(vty, ", (Received from a RR-client)");
10076 }
d62a17ae 10077
05864da7
DS
10078 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10079 PEER_FLAG_RSERVER_CLIENT)) {
10080 if (json_paths)
10081 json_object_boolean_true_add(json_path,
10082 "rxedFromRsClient");
10083 else
10084 vty_out(vty, ", (Received from a RS-client)");
10085 }
d62a17ae 10086
05864da7
DS
10087 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10088 if (json_paths)
10089 json_object_boolean_true_add(json_path,
10090 "dampeningHistoryEntry");
10091 else
10092 vty_out(vty, ", (history entry)");
10093 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10094 if (json_paths)
10095 json_object_boolean_true_add(json_path,
10096 "dampeningSuppressed");
10097 else
10098 vty_out(vty, ", (suppressed due to dampening)");
10099 }
d62a17ae 10100
05864da7
DS
10101 if (!json_paths)
10102 vty_out(vty, "\n");
d62a17ae 10103
05864da7
DS
10104 /* Line2 display Next-hop, Neighbor, Router-id */
10105 /* Display the nexthop */
9bcb3eef 10106 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10107
10108 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10109 || bn_p->family == AF_EVPN)
05864da7
DS
10110 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10111 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10112 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10113 || safi == SAFI_EVPN) {
515c2602 10114 if (json_paths) {
c949c771
DA
10115 json_object_string_addf(
10116 json_nexthop_global, "ip", "%pI4",
10117 &attr->mp_nexthop_global_in);
515c2602 10118
939a97f4 10119 if (path->peer->hostname)
515c2602
DA
10120 json_object_string_add(
10121 json_nexthop_global, "hostname",
939a97f4 10122 path->peer->hostname);
aef999a2
DA
10123 } else {
10124 if (nexthop_hostname)
10125 vty_out(vty, " %pI4(%s)",
10126 &attr->mp_nexthop_global_in,
10127 nexthop_hostname);
10128 else
10129 vty_out(vty, " %pI4",
10130 &attr->mp_nexthop_global_in);
10131 }
d62a17ae 10132 } else {
515c2602 10133 if (json_paths) {
c949c771
DA
10134 json_object_string_addf(json_nexthop_global,
10135 "ip", "%pI4",
10136 &attr->nexthop);
515c2602 10137
939a97f4 10138 if (path->peer->hostname)
515c2602
DA
10139 json_object_string_add(
10140 json_nexthop_global, "hostname",
939a97f4 10141 path->peer->hostname);
aef999a2
DA
10142 } else {
10143 if (nexthop_hostname)
10144 vty_out(vty, " %pI4(%s)",
10145 &attr->nexthop,
10146 nexthop_hostname);
10147 else
10148 vty_out(vty, " %pI4",
10149 &attr->nexthop);
10150 }
d62a17ae 10151 }
10152
05864da7
DS
10153 if (json_paths)
10154 json_object_string_add(json_nexthop_global, "afi",
10155 "ipv4");
10156 } else {
10157 if (json_paths) {
c949c771
DA
10158 json_object_string_addf(json_nexthop_global, "ip",
10159 "%pI6",
10160 &attr->mp_nexthop_global);
515c2602 10161
939a97f4 10162 if (path->peer->hostname)
515c2602
DA
10163 json_object_string_add(json_nexthop_global,
10164 "hostname",
939a97f4 10165 path->peer->hostname);
515c2602 10166
05864da7
DS
10167 json_object_string_add(json_nexthop_global, "afi",
10168 "ipv6");
10169 json_object_string_add(json_nexthop_global, "scope",
10170 "global");
10171 } else {
aef999a2
DA
10172 if (nexthop_hostname)
10173 vty_out(vty, " %pI6(%s)",
10174 &attr->mp_nexthop_global,
10175 nexthop_hostname);
10176 else
10177 vty_out(vty, " %pI6",
10178 &attr->mp_nexthop_global);
d62a17ae 10179 }
05864da7 10180 }
d62a17ae 10181
05864da7
DS
10182 /* Display the IGP cost or 'inaccessible' */
10183 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10184 if (json_paths)
10185 json_object_boolean_false_add(json_nexthop_global,
10186 "accessible");
10187 else
10188 vty_out(vty, " (inaccessible)");
10189 } else {
10190 if (path->extra && path->extra->igpmetric) {
d62a17ae 10191 if (json_paths)
05864da7
DS
10192 json_object_int_add(json_nexthop_global,
10193 "metric",
10194 path->extra->igpmetric);
d62a17ae 10195 else
05864da7
DS
10196 vty_out(vty, " (metric %u)",
10197 path->extra->igpmetric);
d62a17ae 10198 }
10199
05864da7 10200 /* IGP cost is 0, display this only for json */
d62a17ae 10201 else {
d62a17ae 10202 if (json_paths)
05864da7
DS
10203 json_object_int_add(json_nexthop_global,
10204 "metric", 0);
d62a17ae 10205 }
d62a17ae 10206
05864da7
DS
10207 if (json_paths)
10208 json_object_boolean_true_add(json_nexthop_global,
10209 "accessible");
10210 }
d62a17ae 10211
05864da7
DS
10212 /* Display peer "from" output */
10213 /* This path was originated locally */
10214 if (path->peer == bgp->peer_self) {
d62a17ae 10215
05864da7 10216 if (safi == SAFI_EVPN
b54892e0 10217 || (bn_p->family == AF_INET
05864da7 10218 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10219 if (json_paths)
05864da7
DS
10220 json_object_string_add(json_peer, "peerId",
10221 "0.0.0.0");
d62a17ae 10222 else
05864da7
DS
10223 vty_out(vty, " from 0.0.0.0 ");
10224 } else {
d62a17ae 10225 if (json_paths)
05864da7
DS
10226 json_object_string_add(json_peer, "peerId",
10227 "::");
d62a17ae 10228 else
05864da7 10229 vty_out(vty, " from :: ");
d62a17ae 10230 }
d62a17ae 10231
4e9a9863 10232 if (json_paths)
c949c771
DA
10233 json_object_string_addf(json_peer, "routerId", "%pI4",
10234 &bgp->router_id);
4e9a9863 10235 else
23d0a753 10236 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10237 }
d62a17ae 10238
05864da7
DS
10239 /* We RXed this path from one of our peers */
10240 else {
10241
10242 if (json_paths) {
47e12884
DA
10243 json_object_string_addf(json_peer, "peerId", "%pSU",
10244 &path->peer->su);
c949c771
DA
10245 json_object_string_addf(json_peer, "routerId", "%pI4",
10246 &path->peer->remote_id);
05864da7
DS
10247
10248 if (path->peer->hostname)
10249 json_object_string_add(json_peer, "hostname",
10250 path->peer->hostname);
10251
10252 if (path->peer->domainname)
10253 json_object_string_add(json_peer, "domainname",
10254 path->peer->domainname);
10255
10256 if (path->peer->conf_if)
10257 json_object_string_add(json_peer, "interface",
10258 path->peer->conf_if);
10259 } else {
10260 if (path->peer->conf_if) {
10261 if (path->peer->hostname
892fedb6
DA
10262 && CHECK_FLAG(path->peer->bgp->flags,
10263 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10264 vty_out(vty, " from %s(%s)",
10265 path->peer->hostname,
10266 path->peer->conf_if);
d62a17ae 10267 else
05864da7 10268 vty_out(vty, " from %s",
9b6d8fcf 10269 path->peer->conf_if);
d62a17ae 10270 } else {
05864da7 10271 if (path->peer->hostname
892fedb6
DA
10272 && CHECK_FLAG(path->peer->bgp->flags,
10273 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10274 vty_out(vty, " from %s(%s)",
10275 path->peer->hostname,
10276 path->peer->host);
d62a17ae 10277 else
47e12884
DA
10278 vty_out(vty, " from %pSU",
10279 &path->peer->su);
d62a17ae 10280 }
d62a17ae 10281
05864da7 10282 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10283 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10284 else
10285 vty_out(vty, " (%s)",
10286 inet_ntop(AF_INET,
10287 &path->peer->remote_id, buf1,
10288 sizeof(buf1)));
d62a17ae 10289 }
05864da7 10290 }
9df8b37c 10291
05864da7
DS
10292 /*
10293 * Note when vrfid of nexthop is different from that of prefix
10294 */
10295 if (path->extra && path->extra->bgp_orig) {
10296 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10297
05864da7
DS
10298 if (json_paths) {
10299 const char *vn;
9df8b37c 10300
05864da7
DS
10301 if (path->extra->bgp_orig->inst_type
10302 == BGP_INSTANCE_TYPE_DEFAULT)
10303 vn = VRF_DEFAULT_NAME;
10304 else
10305 vn = path->extra->bgp_orig->name;
9df8b37c 10306
05864da7 10307 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10308
05864da7
DS
10309 if (nexthop_vrfid == VRF_UNKNOWN) {
10310 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10311 } else {
05864da7
DS
10312 json_object_int_add(json_path, "nhVrfId",
10313 (int)nexthop_vrfid);
9df8b37c 10314 }
05864da7
DS
10315 } else {
10316 if (nexthop_vrfid == VRF_UNKNOWN)
10317 vty_out(vty, " vrf ?");
137147c6
DS
10318 else {
10319 struct vrf *vrf;
10320
10321 vrf = vrf_lookup_by_id(nexthop_vrfid);
10322 vty_out(vty, " vrf %s(%u)",
10323 VRF_LOGNAME(vrf), nexthop_vrfid);
10324 }
9df8b37c 10325 }
05864da7 10326 }
9df8b37c 10327
05864da7
DS
10328 if (nexthop_self) {
10329 if (json_paths) {
10330 json_object_boolean_true_add(json_path,
10331 "announceNexthopSelf");
10332 } else {
10333 vty_out(vty, " announce-nh-self");
9df8b37c 10334 }
05864da7 10335 }
9df8b37c 10336
05864da7
DS
10337 if (!json_paths)
10338 vty_out(vty, "\n");
d62a17ae 10339
05864da7
DS
10340 /* display the link-local nexthop */
10341 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10342 if (json_paths) {
10343 json_nexthop_ll = json_object_new_object();
c949c771
DA
10344 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10345 &attr->mp_nexthop_local);
515c2602 10346
939a97f4 10347 if (path->peer->hostname)
515c2602
DA
10348 json_object_string_add(json_nexthop_ll,
10349 "hostname",
939a97f4 10350 path->peer->hostname);
515c2602 10351
05864da7
DS
10352 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10353 json_object_string_add(json_nexthop_ll, "scope",
10354 "link-local");
d62a17ae 10355
05864da7
DS
10356 json_object_boolean_true_add(json_nexthop_ll,
10357 "accessible");
d62a17ae 10358
05864da7 10359 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10360 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10361 "used");
10362 else
10363 json_object_boolean_true_add(
10364 json_nexthop_global, "used");
10365 } else {
10366 vty_out(vty, " (%s) %s\n",
10367 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10368 buf, INET6_ADDRSTRLEN),
10369 attr->mp_nexthop_prefer_global
10370 ? "(prefer-global)"
10371 : "(used)");
d62a17ae 10372 }
05864da7
DS
10373 }
10374 /* If we do not have a link-local nexthop then we must flag the
10375 global as "used" */
10376 else {
10377 if (json_paths)
10378 json_object_boolean_true_add(json_nexthop_global,
10379 "used");
10380 }
d62a17ae 10381
b5e140c8 10382 if (safi == SAFI_EVPN &&
5e4d4c8a 10383 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10384 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10385 }
10386
05864da7
DS
10387 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10388 * Int/Ext/Local, Atomic, best */
10389 if (json_paths)
10390 json_object_string_add(json_path, "origin",
10391 bgp_origin_long_str[attr->origin]);
10392 else
10393 vty_out(vty, " Origin %s",
10394 bgp_origin_long_str[attr->origin]);
9df8b37c 10395
05864da7 10396 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10397 if (json_paths)
05864da7 10398 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10399 else
05864da7
DS
10400 vty_out(vty, ", metric %u", attr->med);
10401 }
9df8b37c 10402
05864da7
DS
10403 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10404 if (json_paths)
0fbac0b4 10405 json_object_int_add(json_path, "locPrf",
05864da7
DS
10406 attr->local_pref);
10407 else
10408 vty_out(vty, ", localpref %u", attr->local_pref);
10409 }
9df8b37c 10410
05864da7
DS
10411 if (attr->weight != 0) {
10412 if (json_paths)
10413 json_object_int_add(json_path, "weight", attr->weight);
10414 else
10415 vty_out(vty, ", weight %u", attr->weight);
10416 }
9df8b37c 10417
05864da7
DS
10418 if (attr->tag != 0) {
10419 if (json_paths)
10420 json_object_int_add(json_path, "tag", attr->tag);
10421 else
10422 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10423 }
9df8b37c 10424
05864da7
DS
10425 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10426 if (json_paths)
10427 json_object_boolean_false_add(json_path, "valid");
10428 else
10429 vty_out(vty, ", invalid");
10430 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10431 if (json_paths)
10432 json_object_boolean_true_add(json_path, "valid");
10433 else
10434 vty_out(vty, ", valid");
10435 }
9df8b37c 10436
7d3cae70
DA
10437 if (json_paths)
10438 json_object_int_add(json_path, "version", bn->version);
10439
05864da7
DS
10440 if (path->peer != bgp->peer_self) {
10441 if (path->peer->as == path->peer->local_as) {
10442 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10443 if (json_paths)
10444 json_object_string_add(
10445 json_peer, "type",
10446 "confed-internal");
d62a17ae 10447 else
05864da7 10448 vty_out(vty, ", confed-internal");
d62a17ae 10449 } else {
05864da7
DS
10450 if (json_paths)
10451 json_object_string_add(
10452 json_peer, "type", "internal");
10453 else
10454 vty_out(vty, ", internal");
9df8b37c 10455 }
05864da7
DS
10456 } else {
10457 if (bgp_confederation_peers_check(bgp,
10458 path->peer->as)) {
10459 if (json_paths)
10460 json_object_string_add(
10461 json_peer, "type",
10462 "confed-external");
d62a17ae 10463 else
05864da7 10464 vty_out(vty, ", confed-external");
d62a17ae 10465 } else {
05864da7
DS
10466 if (json_paths)
10467 json_object_string_add(
10468 json_peer, "type", "external");
10469 else
10470 vty_out(vty, ", external");
d62a17ae 10471 }
10472 }
05864da7
DS
10473 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10474 if (json_paths) {
10475 json_object_boolean_true_add(json_path, "aggregated");
10476 json_object_boolean_true_add(json_path, "local");
10477 } else {
10478 vty_out(vty, ", aggregated, local");
10479 }
10480 } else if (path->type != ZEBRA_ROUTE_BGP) {
10481 if (json_paths)
10482 json_object_boolean_true_add(json_path, "sourced");
10483 else
10484 vty_out(vty, ", sourced");
10485 } else {
10486 if (json_paths) {
10487 json_object_boolean_true_add(json_path, "sourced");
10488 json_object_boolean_true_add(json_path, "local");
10489 } else {
10490 vty_out(vty, ", sourced, local");
d62a17ae 10491 }
05864da7 10492 }
718e3744 10493
05864da7 10494 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10495 if (json_paths)
05864da7
DS
10496 json_object_boolean_true_add(json_path,
10497 "atomicAggregate");
d62a17ae 10498 else
05864da7
DS
10499 vty_out(vty, ", atomic-aggregate");
10500 }
d62a17ae 10501
d864dd9e
EB
10502 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10503 if (json_paths)
10504 json_object_int_add(json_path, "otc", attr->otc);
10505 else
10506 vty_out(vty, ", otc %u", attr->otc);
10507 }
10508
05864da7
DS
10509 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10510 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10511 && bgp_path_info_mpath_count(path))) {
10512 if (json_paths)
10513 json_object_boolean_true_add(json_path, "multipath");
10514 else
10515 vty_out(vty, ", multipath");
10516 }
50e05855 10517
05864da7
DS
10518 // Mark the bestpath(s)
10519 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10520 first_as = aspath_get_first_as(attr->aspath);
718e3744 10521
05864da7
DS
10522 if (json_paths) {
10523 if (!json_bestpath)
10524 json_bestpath = json_object_new_object();
10525 json_object_int_add(json_bestpath, "bestpathFromAs",
10526 first_as);
10527 } else {
10528 if (first_as)
10529 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10530 else
05864da7 10531 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10532 }
05864da7 10533 }
718e3744 10534
05864da7
DS
10535 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10536 if (json_paths) {
10537 if (!json_bestpath)
10538 json_bestpath = json_object_new_object();
10539 json_object_boolean_true_add(json_bestpath, "overall");
10540 json_object_string_add(
10541 json_bestpath, "selectionReason",
10542 bgp_path_selection_reason2str(bn->reason));
10543 } else {
10544 vty_out(vty, ", best");
10545 vty_out(vty, " (%s)",
10546 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10547 }
05864da7 10548 }
718e3744 10549
4027d19b 10550 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10551 if (json_paths)
10552 json_object_string_add(
10553 json_path, "rpkiValidationState",
4027d19b 10554 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10555 else
1d327209 10556 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10557 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10558 }
10559
05864da7
DS
10560 if (json_bestpath)
10561 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10562
05864da7
DS
10563 if (!json_paths)
10564 vty_out(vty, "\n");
10565
10566 /* Line 4 display Community */
29e72930 10567 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10568 if (json_paths) {
9a706b42
DA
10569 if (!bgp_attr_get_community(attr)->json)
10570 community_str(bgp_attr_get_community(attr),
c0945b78 10571 true, true);
9a706b42
DA
10572 json_object_lock(bgp_attr_get_community(attr)->json);
10573 json_object_object_add(
10574 json_path, "community",
10575 bgp_attr_get_community(attr)->json);
05864da7
DS
10576 } else {
10577 vty_out(vty, " Community: %s\n",
9a706b42 10578 bgp_attr_get_community(attr)->str);
d62a17ae 10579 }
05864da7 10580 }
718e3744 10581
05864da7
DS
10582 /* Line 5 display Extended-community */
10583 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10584 if (json_paths) {
10585 json_ext_community = json_object_new_object();
b53e67a3
DA
10586 json_object_string_add(
10587 json_ext_community, "string",
10588 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10589 json_object_object_add(json_path, "extendedCommunity",
10590 json_ext_community);
d62a17ae 10591 } else {
05864da7 10592 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10593 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10594 }
05864da7 10595 }
718e3744 10596
05864da7
DS
10597 /* Line 6 display Large community */
10598 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10599 if (json_paths) {
1bcf3a96
DA
10600 if (!bgp_attr_get_lcommunity(attr)->json)
10601 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10602 true, true);
1bcf3a96
DA
10603 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10604 json_object_object_add(
10605 json_path, "largeCommunity",
10606 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10607 } else {
10608 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10609 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10610 }
05864da7 10611 }
718e3744 10612
05864da7
DS
10613 /* Line 7 display Originator, Cluster-id */
10614 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10615 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10616 char buf[BUFSIZ] = {0};
10617
05864da7 10618 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10619 if (json_paths)
c949c771
DA
10620 json_object_string_addf(json_path,
10621 "originatorId", "%pI4",
10622 &attr->originator_id);
d62a17ae 10623 else
23d0a753
DA
10624 vty_out(vty, " Originator: %pI4",
10625 &attr->originator_id);
d62a17ae 10626 }
856ca177 10627
05864da7 10628 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10629 struct cluster_list *cluster =
10630 bgp_attr_get_cluster(attr);
05864da7 10631 int i;
d62a17ae 10632
10633 if (json_paths) {
05864da7
DS
10634 json_cluster_list = json_object_new_object();
10635 json_cluster_list_list =
10636 json_object_new_array();
10637
779fee93 10638 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10639 json_string = json_object_new_string(
779fee93
DS
10640 inet_ntop(AF_INET,
10641 &cluster->list[i],
10642 buf, sizeof(buf)));
05864da7
DS
10643 json_object_array_add(
10644 json_cluster_list_list,
10645 json_string);
10646 }
718e3744 10647
05864da7
DS
10648 /*
10649 * struct cluster_list does not have
10650 * "str" variable like aspath and community
10651 * do. Add this someday if someone asks
10652 * for it.
10653 * json_object_string_add(json_cluster_list,
779fee93 10654 * "string", cluster->str);
05864da7
DS
10655 */
10656 json_object_object_add(json_cluster_list,
10657 "list",
10658 json_cluster_list_list);
10659 json_object_object_add(json_path, "clusterList",
10660 json_cluster_list);
0dc8ee70 10661 } else {
05864da7
DS
10662 vty_out(vty, ", Cluster list: ");
10663
779fee93 10664 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10665 vty_out(vty, "%pI4 ",
779fee93 10666 &cluster->list[i]);
05864da7 10667 }
0dc8ee70 10668 }
d62a17ae 10669 }
718e3744 10670
d62a17ae 10671 if (!json_paths)
10672 vty_out(vty, "\n");
05864da7 10673 }
d62a17ae 10674
05864da7 10675 if (path->extra && path->extra->damp_info)
b4f7f45b 10676 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10677
05864da7
DS
10678 /* Remote Label */
10679 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10680 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10681 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10682 &bos);
d62a17ae 10683
05864da7
DS
10684 if (json_paths)
10685 json_object_int_add(json_path, "remoteLabel", label);
10686 else
10687 vty_out(vty, " Remote label: %d\n", label);
10688 }
d62a17ae 10689
e496b420
HS
10690 /* Remote SID */
10691 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10692 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10693 if (json_paths)
10694 json_object_string_add(json_path, "remoteSid", buf);
10695 else
10696 vty_out(vty, " Remote SID: %s\n", buf);
10697 }
10698
05864da7
DS
10699 /* Label Index */
10700 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10701 if (json_paths)
10702 json_object_int_add(json_path, "labelIndex",
10703 attr->label_index);
10704 else
10705 vty_out(vty, " Label Index: %d\n",
10706 attr->label_index);
10707 }
d62a17ae 10708
05864da7
DS
10709 /* Line 8 display Addpath IDs */
10710 if (path->addpath_rx_id
10711 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10712 if (json_paths) {
10713 json_object_int_add(json_path, "addpathRxId",
10714 path->addpath_rx_id);
d62a17ae 10715
05864da7
DS
10716 /* Keep backwards compatibility with the old API
10717 * by putting TX All's ID in the old field
10718 */
10719 json_object_int_add(
10720 json_path, "addpathTxId",
10721 path->tx_addpath
10722 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10723
05864da7
DS
10724 /* ... but create a specific field for each
10725 * strategy
10726 */
10727 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10728 json_object_int_add(
10729 json_path,
10730 bgp_addpath_names(i)->id_json_name,
10731 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10732 }
05864da7
DS
10733 } else {
10734 vty_out(vty, " AddPath ID: RX %u, ",
10735 path->addpath_rx_id);
d62a17ae 10736
05864da7 10737 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10738 }
05864da7 10739 }
520d5d76 10740
05864da7
DS
10741 /* If we used addpath to TX a non-bestpath we need to display
10742 * "Advertised to" on a path-by-path basis
10743 */
10744 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10745 first = 1;
dcc68b5e 10746
05864da7
DS
10747 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10748 addpath_capable =
10749 bgp_addpath_encode_tx(peer, afi, safi);
10750 has_adj = bgp_adj_out_lookup(
10751 peer, path->net,
10752 bgp_addpath_id_for_peer(peer, afi, safi,
10753 &path->tx_addpath));
10754
10755 if ((addpath_capable && has_adj)
10756 || (!addpath_capable && has_adj
10757 && CHECK_FLAG(path->flags,
10758 BGP_PATH_SELECTED))) {
10759 if (json_path && !json_adv_to)
10760 json_adv_to = json_object_new_object();
dcc68b5e 10761
05864da7
DS
10762 route_vty_out_advertised_to(
10763 vty, peer, &first,
10764 " Advertised to:", json_adv_to);
d62a17ae 10765 }
10766 }
718e3744 10767
05864da7
DS
10768 if (json_path) {
10769 if (json_adv_to) {
10770 json_object_object_add(
10771 json_path, "advertisedTo", json_adv_to);
d62a17ae 10772 }
05864da7
DS
10773 } else {
10774 if (!first) {
10775 vty_out(vty, "\n");
d62a17ae 10776 }
10777 }
05864da7 10778 }
b05a1c8b 10779
05864da7
DS
10780 /* Line 9 display Uptime */
10781 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10782 if (json_paths) {
10783 json_last_update = json_object_new_object();
10784 json_object_int_add(json_last_update, "epoch", tbuf);
10785 json_object_string_add(json_last_update, "string",
10786 ctime(&tbuf));
10787 json_object_object_add(json_path, "lastUpdate",
10788 json_last_update);
10789 } else
10790 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10791
05864da7
DS
10792 /* Line 10 display PMSI tunnel attribute, if present */
10793 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10794 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10795 bgp_attr_get_pmsi_tnl_type(attr),
10796 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10797
05864da7
DS
10798 if (json_paths) {
10799 json_pmsi = json_object_new_object();
10800 json_object_string_add(json_pmsi, "tunnelType", str);
10801 json_object_int_add(json_pmsi, "label",
10802 label2vni(&attr->label));
10803 json_object_object_add(json_path, "pmsi", json_pmsi);
10804 } else
10805 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10806 str, label2vni(&attr->label));
d62a17ae 10807 }
f1aa5d8a 10808
848e8cf6
DA
10809 if (path->peer->t_gr_restart &&
10810 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10811 unsigned long gr_remaining =
10812 thread_timer_remain_second(path->peer->t_gr_restart);
10813
10814 if (json_paths) {
10815 json_object_int_add(json_path,
10816 "gracefulRestartSecondsRemaining",
10817 gr_remaining);
10818 } else
10819 vty_out(vty,
10820 " Time until Graceful Restart stale route deleted: %lu\n",
10821 gr_remaining);
10822 }
10823
9a706b42
DA
10824 if (path->peer->t_llgr_stale[afi][safi] &&
10825 bgp_attr_get_community(attr) &&
10826 community_include(bgp_attr_get_community(attr),
10827 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10828 unsigned long llgr_remaining = thread_timer_remain_second(
10829 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10830
48ebba04
DA
10831 if (json_paths) {
10832 json_object_int_add(json_path, "llgrSecondsRemaining",
10833 llgr_remaining);
10834 } else
10835 vty_out(vty,
10836 " Time until Long-lived stale route deleted: %lu\n",
10837 llgr_remaining);
10838 }
10839
92269aa2
DS
10840 /* Output some debug about internal state of the dest flags */
10841 if (json_paths) {
10842 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10843 json_object_boolean_true_add(json_path, "processScheduled");
10844 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10845 json_object_boolean_true_add(json_path, "userCleared");
10846 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10847 json_object_boolean_true_add(json_path, "labelChanged");
10848 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10849 json_object_boolean_true_add(json_path, "registeredForLabel");
10850 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10851 json_object_boolean_true_add(json_path, "selectDefered");
10852 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10853 json_object_boolean_true_add(json_path, "fibInstalled");
10854 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10855 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10856
d62a17ae 10857 if (json_nexthop_global || json_nexthop_ll) {
10858 json_nexthops = json_object_new_array();
f1aa5d8a 10859
d62a17ae 10860 if (json_nexthop_global)
10861 json_object_array_add(json_nexthops,
10862 json_nexthop_global);
f1aa5d8a 10863
d62a17ae 10864 if (json_nexthop_ll)
10865 json_object_array_add(json_nexthops,
10866 json_nexthop_ll);
f1aa5d8a 10867
d62a17ae 10868 json_object_object_add(json_path, "nexthops",
10869 json_nexthops);
10870 }
10871
10872 json_object_object_add(json_path, "peer", json_peer);
10873 json_object_array_add(json_paths, json_path);
05864da7 10874 }
b366b518
BB
10875}
10876
96ade3ed 10877#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10878#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10879#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10880
a4d82a8a 10881static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10882 afi_t afi, safi_t safi, enum bgp_show_type type,
10883 bool use_json);
7f323236
DW
10884static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10885 const char *comstr, int exact, afi_t afi,
96c81f66 10886 safi_t safi, uint16_t show_flags);
d62a17ae 10887
1ae44dfc 10888static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10889 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10890 void *output_arg, const char *rd, int is_last,
96f3485c 10891 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10892 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10893 enum rpki_states rpki_target_state)
d62a17ae 10894{
40381db7 10895 struct bgp_path_info *pi;
9bcb3eef 10896 struct bgp_dest *dest;
2aad8c42
MS
10897 bool header = true;
10898 bool json_detail_header = false;
d62a17ae 10899 int display;
1ae44dfc
LB
10900 unsigned long output_count = 0;
10901 unsigned long total_count = 0;
d62a17ae 10902 struct prefix *p;
d62a17ae 10903 json_object *json_paths = NULL;
10904 int first = 1;
96f3485c
MK
10905 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10906 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10907 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10908
1ae44dfc 10909 if (output_cum && *output_cum != 0)
2aad8c42 10910 header = false;
1ae44dfc 10911
9386b588 10912 if (use_json && !*json_header_depth) {
96f3485c
MK
10913 if (all)
10914 *json_header_depth = 1;
10915 else {
10916 vty_out(vty, "{\n");
10917 *json_header_depth = 2;
10918 }
10919
d62a17ae 10920 vty_out(vty,
23d0a753
DA
10921 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10922 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10923 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10924 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10925 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10926 ? VRF_DEFAULT_NAME
10927 : bgp->name,
10928 table->version, &bgp->router_id,
01eced22 10929 bgp->default_local_pref, bgp->as);
9386b588 10930 if (rd) {
445c2480 10931 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10932 ++*json_header_depth;
10933 }
d62a17ae 10934 }
718e3744 10935
445c2480
DS
10936 if (use_json && rd) {
10937 vty_out(vty, " \"%s\" : { ", rd);
10938 }
10939
2aad8c42
MS
10940 /* Check for 'json detail', where we need header output once per dest */
10941 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10942 type != bgp_show_type_dampend_paths &&
10943 type != bgp_show_type_damp_neighbor &&
10944 type != bgp_show_type_flap_statistics &&
10945 type != bgp_show_type_flap_neighbor)
10946 json_detail_header = true;
10947
d62a17ae 10948 /* Start processing of routes. */
9bcb3eef
DS
10949 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10950 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10951 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10952 bool json_detail = json_detail_header;
b54892e0 10953
9bcb3eef 10954 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10955 if (pi == NULL)
98ce9a06 10956 continue;
d62a17ae 10957
98ce9a06 10958 display = 0;
98ce9a06
DS
10959 if (use_json)
10960 json_paths = json_object_new_array();
10961 else
10962 json_paths = NULL;
d62a17ae 10963
6f94b685 10964 for (; pi; pi = pi->next) {
9a706b42
DA
10965 struct community *picomm = NULL;
10966
10967 picomm = bgp_attr_get_community(pi->attr);
10968
98ce9a06 10969 total_count++;
1e2ce4f1 10970
7d3cae70
DA
10971 if (type == bgp_show_type_prefix_version) {
10972 uint32_t version =
10973 strtoul(output_arg, NULL, 10);
10974 if (dest->version < version)
10975 continue;
10976 }
10977
a70a28a5
DA
10978 if (type == bgp_show_type_community_alias) {
10979 char *alias = output_arg;
10980 char **communities;
10981 int num;
10982 bool found = false;
10983
9a706b42
DA
10984 if (picomm) {
10985 frrstr_split(picomm->str, " ",
10986 &communities, &num);
a70a28a5
DA
10987 for (int i = 0; i < num; i++) {
10988 const char *com2alias =
10989 bgp_community2alias(
10990 communities[i]);
cd9cc0e6
IR
10991 if (!found
10992 && strcmp(alias, com2alias)
10993 == 0)
a70a28a5 10994 found = true;
cd9cc0e6
IR
10995 XFREE(MTYPE_TMP,
10996 communities[i]);
a70a28a5 10997 }
cd9cc0e6 10998 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10999 }
11000
1bcf3a96
DA
11001 if (!found &&
11002 bgp_attr_get_lcommunity(pi->attr)) {
11003 frrstr_split(bgp_attr_get_lcommunity(
11004 pi->attr)
11005 ->str,
a70a28a5
DA
11006 " ", &communities, &num);
11007 for (int i = 0; i < num; i++) {
11008 const char *com2alias =
11009 bgp_community2alias(
11010 communities[i]);
cd9cc0e6
IR
11011 if (!found
11012 && strcmp(alias, com2alias)
11013 == 0)
a70a28a5 11014 found = true;
cd9cc0e6
IR
11015 XFREE(MTYPE_TMP,
11016 communities[i]);
a70a28a5 11017 }
cd9cc0e6 11018 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11019 }
11020
11021 if (!found)
11022 continue;
11023 }
11024
1e2ce4f1
DS
11025 if (type == bgp_show_type_rpki) {
11026 if (dest_p->family == AF_INET
11027 || dest_p->family == AF_INET6)
4027d19b 11028 rpki_curr_state = hook_call(
1e2ce4f1
DS
11029 bgp_rpki_prefix_status,
11030 pi->peer, pi->attr, dest_p);
4027d19b
DS
11031 if (rpki_target_state != RPKI_NOT_BEING_USED
11032 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11033 continue;
11034 }
11035
98ce9a06
DS
11036 if (type == bgp_show_type_flap_statistics
11037 || type == bgp_show_type_flap_neighbor
11038 || type == bgp_show_type_dampend_paths
11039 || type == bgp_show_type_damp_neighbor) {
40381db7 11040 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11041 continue;
11042 }
11043 if (type == bgp_show_type_regexp) {
11044 regex_t *regex = output_arg;
d62a17ae 11045
40381db7 11046 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11047 == REG_NOMATCH)
11048 continue;
11049 }
11050 if (type == bgp_show_type_prefix_list) {
11051 struct prefix_list *plist = output_arg;
d62a17ae 11052
9bcb3eef 11053 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11054 != PREFIX_PERMIT)
11055 continue;
11056 }
11057 if (type == bgp_show_type_filter_list) {
11058 struct as_list *as_list = output_arg;
d62a17ae 11059
40381db7 11060 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11061 != AS_FILTER_PERMIT)
11062 continue;
11063 }
11064 if (type == bgp_show_type_route_map) {
11065 struct route_map *rmap = output_arg;
9b6d8fcf 11066 struct bgp_path_info path;
98ce9a06 11067 struct attr dummy_attr;
b68885f9 11068 route_map_result_t ret;
d62a17ae 11069
6f4f49b2 11070 dummy_attr = *pi->attr;
d62a17ae 11071
40381db7 11072 path.peer = pi->peer;
9b6d8fcf 11073 path.attr = &dummy_attr;
d62a17ae 11074
1782514f 11075 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11076 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11077 if (ret == RMAP_DENYMATCH)
11078 continue;
11079 }
11080 if (type == bgp_show_type_neighbor
11081 || type == bgp_show_type_flap_neighbor
11082 || type == bgp_show_type_damp_neighbor) {
11083 union sockunion *su = output_arg;
11084
40381db7
DS
11085 if (pi->peer == NULL
11086 || pi->peer->su_remote == NULL
11087 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11088 continue;
11089 }
11090 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11091 uint32_t destination;
d62a17ae 11092
9bcb3eef 11093 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11094 if (IN_CLASSC(destination)
9bcb3eef 11095 && dest_p->prefixlen == 24)
98ce9a06
DS
11096 continue;
11097 if (IN_CLASSB(destination)
9bcb3eef 11098 && dest_p->prefixlen == 16)
98ce9a06
DS
11099 continue;
11100 if (IN_CLASSA(destination)
9bcb3eef 11101 && dest_p->prefixlen == 8)
98ce9a06
DS
11102 continue;
11103 }
11104 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11105 p = output_arg;
9bcb3eef 11106 if (!prefix_match(p, dest_p))
98ce9a06
DS
11107 continue;
11108 }
11109 if (type == bgp_show_type_community_all) {
9a706b42 11110 if (!picomm)
98ce9a06
DS
11111 continue;
11112 }
11113 if (type == bgp_show_type_community) {
11114 struct community *com = output_arg;
d62a17ae 11115
9a706b42 11116 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11117 continue;
11118 }
11119 if (type == bgp_show_type_community_exact) {
11120 struct community *com = output_arg;
d62a17ae 11121
9a706b42 11122 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11123 continue;
11124 }
11125 if (type == bgp_show_type_community_list) {
11126 struct community_list *list = output_arg;
d62a17ae 11127
9a706b42 11128 if (!community_list_match(picomm, list))
98ce9a06
DS
11129 continue;
11130 }
a4d82a8a 11131 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11132 struct community_list *list = output_arg;
d62a17ae 11133
9a706b42 11134 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11135 continue;
11136 }
11137 if (type == bgp_show_type_lcommunity) {
11138 struct lcommunity *lcom = output_arg;
d62a17ae 11139
1bcf3a96
DA
11140 if (!bgp_attr_get_lcommunity(pi->attr) ||
11141 !lcommunity_match(
11142 bgp_attr_get_lcommunity(pi->attr),
11143 lcom))
98ce9a06
DS
11144 continue;
11145 }
36a206db 11146
11147 if (type == bgp_show_type_lcommunity_exact) {
11148 struct lcommunity *lcom = output_arg;
11149
1bcf3a96
DA
11150 if (!bgp_attr_get_lcommunity(pi->attr) ||
11151 !lcommunity_cmp(
11152 bgp_attr_get_lcommunity(pi->attr),
11153 lcom))
36a206db 11154 continue;
11155 }
98ce9a06
DS
11156 if (type == bgp_show_type_lcommunity_list) {
11157 struct community_list *list = output_arg;
d62a17ae 11158
1bcf3a96
DA
11159 if (!lcommunity_list_match(
11160 bgp_attr_get_lcommunity(pi->attr),
11161 list))
98ce9a06
DS
11162 continue;
11163 }
36a206db 11164 if (type
11165 == bgp_show_type_lcommunity_list_exact) {
11166 struct community_list *list = output_arg;
11167
11168 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11169 bgp_attr_get_lcommunity(pi->attr),
11170 list))
36a206db 11171 continue;
11172 }
98ce9a06 11173 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11174 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11175 continue;
11176 }
11177 if (type == bgp_show_type_dampend_paths
11178 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11179 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11180 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11181 continue;
11182 }
11183
11184 if (!use_json && header) {
23d0a753
DA
11185 vty_out(vty,
11186 "BGP table version is %" PRIu64
11187 ", local router ID is %pI4, vrf id ",
11188 table->version, &bgp->router_id);
9df8b37c
PZ
11189 if (bgp->vrf_id == VRF_UNKNOWN)
11190 vty_out(vty, "%s", VRFID_NONE_STR);
11191 else
11192 vty_out(vty, "%u", bgp->vrf_id);
11193 vty_out(vty, "\n");
01eced22
AD
11194 vty_out(vty, "Default local pref %u, ",
11195 bgp->default_local_pref);
11196 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11197 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11198 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11199 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11200 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11201 if (type == bgp_show_type_dampend_paths
11202 || type == bgp_show_type_damp_neighbor)
98ce9a06 11203 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11204 else if (type == bgp_show_type_flap_statistics
11205 || type == bgp_show_type_flap_neighbor)
98ce9a06 11206 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11207 else
ae248832
MK
11208 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11209 : BGP_SHOW_HEADER));
2aad8c42
MS
11210 header = false;
11211
11212 } else if (json_detail && json_paths != NULL) {
11213 const struct prefix_rd *prd;
11214 json_object *jtemp;
11215
11216 /* Use common detail header, for most types;
11217 * need a json 'object'.
11218 */
11219
11220 jtemp = json_object_new_object();
11221 prd = bgp_rd_from_dest(dest, safi);
11222
11223 route_vty_out_detail_header(
11224 vty, bgp, dest, prd, table->afi,
11225 safi, jtemp);
11226
11227 json_object_array_add(json_paths, jtemp);
11228
11229 json_detail = false;
d62a17ae 11230 }
2aad8c42 11231
98ce9a06
DS
11232 if (rd != NULL && !display && !output_count) {
11233 if (!use_json)
11234 vty_out(vty,
11235 "Route Distinguisher: %s\n",
11236 rd);
d62a17ae 11237 }
98ce9a06
DS
11238 if (type == bgp_show_type_dampend_paths
11239 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11240 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11241 AFI_IP, safi, use_json,
11242 json_paths);
98ce9a06
DS
11243 else if (type == bgp_show_type_flap_statistics
11244 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11245 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11246 AFI_IP, safi, use_json,
11247 json_paths);
f280c93b
DA
11248 else {
11249 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11250 route_vty_out_detail(
11251 vty, bgp, dest, pi,
11252 family2afi(dest_p->family),
11253 safi, RPKI_NOT_BEING_USED,
11254 json_paths);
11255 else
11256 route_vty_out(vty, dest_p, pi, display,
11257 safi, json_paths, wide);
11258 }
98ce9a06 11259 display++;
d62a17ae 11260 }
11261
98ce9a06
DS
11262 if (display) {
11263 output_count++;
11264 if (!use_json)
11265 continue;
11266
625d2931 11267 /* encode prefix */
9bcb3eef 11268 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11269 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11270
1840384b 11271
b54892e0
DS
11272 bgp_fs_nlri_get_string(
11273 (unsigned char *)
9bcb3eef
DS
11274 dest_p->u.prefix_flowspec.ptr,
11275 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11276 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11277 family2afi(dest_p->u
11278 .prefix_flowspec.family));
625d2931 11279 if (first)
b54892e0 11280 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11281 dest_p->u.prefix_flowspec
b54892e0 11282 .prefixlen);
625d2931 11283 else
b54892e0 11284 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11285 dest_p->u.prefix_flowspec
b54892e0 11286 .prefixlen);
625d2931 11287 } else {
625d2931 11288 if (first)
1b78780b 11289 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11290 else
1b78780b 11291 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11292 }
3757f964 11293 vty_json(vty, json_paths);
449feb8e 11294 json_paths = NULL;
98ce9a06 11295 first = 0;
1f83ed02
DS
11296 } else
11297 json_object_free(json_paths);
98ce9a06
DS
11298 }
11299
1ae44dfc
LB
11300 if (output_cum) {
11301 output_count += *output_cum;
11302 *output_cum = output_count;
11303 }
11304 if (total_cum) {
11305 total_count += *total_cum;
11306 *total_cum = total_count;
11307 }
d62a17ae 11308 if (use_json) {
9386b588 11309 if (rd) {
a4d82a8a 11310 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11311 }
11312 if (is_last) {
a4d82a8a
PZ
11313 unsigned long i;
11314 for (i = 0; i < *json_header_depth; ++i)
11315 vty_out(vty, " } ");
96f3485c
MK
11316 if (!all)
11317 vty_out(vty, "\n");
9386b588 11318 }
d62a17ae 11319 } else {
1ae44dfc
LB
11320 if (is_last) {
11321 /* No route is displayed */
11322 if (output_count == 0) {
11323 if (type == bgp_show_type_normal)
11324 vty_out(vty,
11325 "No BGP prefixes displayed, %ld exist\n",
11326 total_count);
11327 } else
d62a17ae 11328 vty_out(vty,
1ae44dfc
LB
11329 "\nDisplayed %ld routes and %ld total paths\n",
11330 output_count, total_count);
11331 }
d62a17ae 11332 }
718e3744 11333
d62a17ae 11334 return CMD_SUCCESS;
718e3744 11335}
11336
1ae44dfc
LB
11337int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11338 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11339 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11340{
9bcb3eef 11341 struct bgp_dest *dest, *next;
1ae44dfc
LB
11342 unsigned long output_cum = 0;
11343 unsigned long total_cum = 0;
9386b588 11344 unsigned long json_header_depth = 0;
67009e22 11345 struct bgp_table *itable;
0136788c 11346 bool show_msg;
96c81f66 11347 uint16_t show_flags = 0;
0136788c
LB
11348
11349 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11350
96f3485c
MK
11351 if (use_json)
11352 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11353
9bcb3eef
DS
11354 for (dest = bgp_table_top(table); dest; dest = next) {
11355 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11356
9bcb3eef
DS
11357 next = bgp_route_next(dest);
11358 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11359 continue;
67009e22 11360
9bcb3eef 11361 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11362 if (itable != NULL) {
1ae44dfc 11363 struct prefix_rd prd;
06b9f471 11364 char rd[RD_ADDRSTRLEN];
1ae44dfc 11365
9bcb3eef 11366 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11367 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11368 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11369 rd, next == NULL, &output_cum,
11370 &total_cum, &json_header_depth,
1e2ce4f1 11371 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11372 if (next == NULL)
11373 show_msg = false;
1ae44dfc
LB
11374 }
11375 }
0136788c
LB
11376 if (show_msg) {
11377 if (output_cum == 0)
11378 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11379 total_cum);
11380 else
11381 vty_out(vty,
11382 "\nDisplayed %ld routes and %ld total paths\n",
11383 output_cum, total_cum);
11384 }
1ae44dfc
LB
11385 return CMD_SUCCESS;
11386}
2aad8c42 11387
d62a17ae 11388static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11389 enum bgp_show_type type, void *output_arg,
96c81f66 11390 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11391{
d62a17ae 11392 struct bgp_table *table;
9386b588 11393 unsigned long json_header_depth = 0;
96f3485c 11394 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11395
d62a17ae 11396 if (bgp == NULL) {
11397 bgp = bgp_get_default();
11398 }
fee0f4c6 11399
d62a17ae 11400 if (bgp == NULL) {
11401 if (!use_json)
11402 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11403 else
11404 vty_out(vty, "{}\n");
d62a17ae 11405 return CMD_WARNING;
11406 }
4dd6177e 11407
cd8c2a27
MS
11408 /* Labeled-unicast routes live in the unicast table. */
11409 if (safi == SAFI_LABELED_UNICAST)
11410 safi = SAFI_UNICAST;
11411
1ae44dfc 11412 table = bgp->rib[afi][safi];
d62a17ae 11413 /* use MPLS and ENCAP specific shows until they are merged */
11414 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11415 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11416 output_arg, use_json);
d62a17ae 11417 }
dba3c1d3
PG
11418
11419 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11420 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11421 output_arg, use_json,
11422 1, NULL, NULL);
11423 }
fee0f4c6 11424
96f3485c 11425 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11426 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11427 rpki_target_state);
fee0f4c6 11428}
11429
d62a17ae 11430static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11431 safi_t safi, uint16_t show_flags)
f186de26 11432{
d62a17ae 11433 struct listnode *node, *nnode;
11434 struct bgp *bgp;
11435 int is_first = 1;
9f049418 11436 bool route_output = false;
96f3485c 11437 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11438
d62a17ae 11439 if (use_json)
11440 vty_out(vty, "{\n");
9f689658 11441
d62a17ae 11442 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11443 route_output = true;
d62a17ae 11444 if (use_json) {
11445 if (!is_first)
11446 vty_out(vty, ",\n");
11447 else
11448 is_first = 0;
11449
11450 vty_out(vty, "\"%s\":",
11451 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11452 ? VRF_DEFAULT_NAME
d62a17ae 11453 : bgp->name);
11454 } else {
11455 vty_out(vty, "\nInstance %s:\n",
11456 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11457 ? VRF_DEFAULT_NAME
d62a17ae 11458 : bgp->name);
11459 }
11460 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11461 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11462 }
9f689658 11463
d62a17ae 11464 if (use_json)
11465 vty_out(vty, "}\n");
9f049418
DS
11466 else if (!route_output)
11467 vty_out(vty, "%% BGP instance not found\n");
f186de26 11468}
11469
718e3744 11470/* Header of detailed BGP route information */
d62a17ae 11471void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11472 struct bgp_dest *dest,
11473 const struct prefix_rd *prd,
d62a17ae 11474 afi_t afi, safi_t safi, json_object *json)
11475{
40381db7 11476 struct bgp_path_info *pi;
b54892e0 11477 const struct prefix *p;
d62a17ae 11478 struct peer *peer;
11479 struct listnode *node, *nnode;
06b9f471 11480 char buf1[RD_ADDRSTRLEN];
d62a17ae 11481 int count = 0;
11482 int best = 0;
11483 int suppress = 0;
c5f1e1b2
C
11484 int accept_own = 0;
11485 int route_filter_translated_v4 = 0;
11486 int route_filter_v4 = 0;
11487 int route_filter_translated_v6 = 0;
11488 int route_filter_v6 = 0;
11489 int llgr_stale = 0;
11490 int no_llgr = 0;
11491 int accept_own_nexthop = 0;
11492 int blackhole = 0;
d62a17ae 11493 int no_export = 0;
11494 int no_advertise = 0;
11495 int local_as = 0;
c5f1e1b2 11496 int no_peer = 0;
d62a17ae 11497 int first = 1;
11498 int has_valid_label = 0;
11499 mpls_label_t label = 0;
11500 json_object *json_adv_to = NULL;
67f67ba4
DA
11501 uint32_t ttl = 0;
11502 uint32_t bos = 0;
11503 uint32_t exp = 0;
9bedbb1e 11504
67f67ba4 11505 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11506
67f67ba4
DA
11507 p = bgp_dest_get_prefix(dest);
11508 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11509
44c69747 11510 if (safi == SAFI_EVPN) {
d62a17ae 11511
44c69747 11512 if (!json) {
2dbe669b 11513 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11514 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11515 : "",
2dbe669b 11516 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11517 } else {
11518 json_object_string_add(json, "rd",
11519 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11520 "");
11521 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11522 }
11523 } else {
11524 if (!json) {
9119ef3a
DA
11525 vty_out(vty,
11526 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11527 "\n",
d62a17ae 11528 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11529 ? prefix_rd2str(prd, buf1,
11530 sizeof(buf1))
11531 : ""),
9119ef3a
DA
11532 safi == SAFI_MPLS_VPN ? ":" : "", p,
11533 dest->version);
cd1964ff 11534
9119ef3a 11535 } else {
67d7e256 11536 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11537 json_object_int_add(json, "version", dest->version);
11538
11539 }
44c69747
LK
11540 }
11541
11542 if (has_valid_label) {
11543 if (json)
11544 json_object_int_add(json, "localLabel", label);
11545 else
d62a17ae 11546 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11547 }
11548
11549 if (!json)
d62a17ae 11550 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11551 vty_out(vty, "not allocated\n");
718e3744 11552
9bcb3eef 11553 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11554 struct community *picomm = NULL;
11555
11556 picomm = bgp_attr_get_community(pi->attr);
11557
d62a17ae 11558 count++;
40381db7 11559 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11560 best = count;
4056a5f6 11561 if (bgp_path_suppressed(pi))
d62a17ae 11562 suppress = 1;
cee9c031 11563
9a706b42 11564 if (!picomm)
cee9c031
QY
11565 continue;
11566
11567 no_advertise += community_include(
9a706b42
DA
11568 picomm, COMMUNITY_NO_ADVERTISE);
11569 no_export +=
11570 community_include(picomm, COMMUNITY_NO_EXPORT);
11571 local_as +=
11572 community_include(picomm, COMMUNITY_LOCAL_AS);
11573 accept_own +=
11574 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11575 route_filter_translated_v4 += community_include(
9a706b42 11576 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11577 route_filter_translated_v6 += community_include(
9a706b42 11578 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11579 route_filter_v4 += community_include(
9a706b42 11580 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11581 route_filter_v6 += community_include(
9a706b42
DA
11582 picomm, COMMUNITY_ROUTE_FILTER_v6);
11583 llgr_stale +=
11584 community_include(picomm, COMMUNITY_LLGR_STALE);
11585 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11586 accept_own_nexthop += community_include(
11587 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11588 blackhole +=
11589 community_include(picomm, COMMUNITY_BLACKHOLE);
11590 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11591 }
718e3744 11592 }
718e3744 11593
d62a17ae 11594 if (!json) {
11595 vty_out(vty, "Paths: (%d available", count);
11596 if (best) {
11597 vty_out(vty, ", best #%d", best);
b84060bb
PG
11598 if (safi == SAFI_UNICAST) {
11599 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11600 vty_out(vty, ", table %s",
11601 VRF_DEFAULT_NAME);
11602 else
11603 vty_out(vty, ", vrf %s",
11604 bgp->name);
11605 }
d62a17ae 11606 } else
11607 vty_out(vty, ", no best path");
11608
c5f1e1b2
C
11609 if (accept_own)
11610 vty_out(vty,
11611 ", accept own local route exported and imported in different VRF");
11612 else if (route_filter_translated_v4)
11613 vty_out(vty,
11614 ", mark translated RTs for VPNv4 route filtering");
11615 else if (route_filter_v4)
11616 vty_out(vty,
11617 ", attach RT as-is for VPNv4 route filtering");
11618 else if (route_filter_translated_v6)
11619 vty_out(vty,
11620 ", mark translated RTs for VPNv6 route filtering");
11621 else if (route_filter_v6)
11622 vty_out(vty,
11623 ", attach RT as-is for VPNv6 route filtering");
11624 else if (llgr_stale)
11625 vty_out(vty,
1479ed2f 11626 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11627 else if (no_llgr)
11628 vty_out(vty,
11629 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11630 else if (accept_own_nexthop)
11631 vty_out(vty,
11632 ", accept local nexthop");
11633 else if (blackhole)
11634 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11635 else if (no_export)
11636 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11637 else if (no_advertise)
11638 vty_out(vty, ", not advertised to any peer");
d62a17ae 11639 else if (local_as)
11640 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11641 else if (no_peer)
11642 vty_out(vty,
11643 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11644
11645 if (suppress)
11646 vty_out(vty,
11647 ", Advertisements suppressed by an aggregate.");
11648 vty_out(vty, ")\n");
11649 }
718e3744 11650
d62a17ae 11651 /* If we are not using addpath then we can display Advertised to and
11652 * that will
11653 * show what peers we advertised the bestpath to. If we are using
11654 * addpath
11655 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11656 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11657 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11658 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11659 if (json && !json_adv_to)
11660 json_adv_to = json_object_new_object();
11661
11662 route_vty_out_advertised_to(
11663 vty, peer, &first,
11664 " Advertised to non peer-group peers:\n ",
11665 json_adv_to);
11666 }
11667 }
11668
11669 if (json) {
11670 if (json_adv_to) {
11671 json_object_object_add(json, "advertisedTo",
11672 json_adv_to);
11673 }
11674 } else {
11675 if (first)
11676 vty_out(vty, " Not advertised to any peer");
11677 vty_out(vty, "\n");
11678 }
11679 }
718e3744 11680}
11681
edfee30d 11682static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11683 struct bgp_dest *bgp_node, struct vty *vty,
11684 struct bgp *bgp, afi_t afi, safi_t safi,
11685 json_object *json, enum bgp_path_type pathtype,
4027d19b 11686 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11687{
11688 struct bgp_path_info *pi;
11689 int header = 1;
11690 char rdbuf[RD_ADDRSTRLEN];
11691 json_object *json_header = NULL;
11692 json_object *json_paths = NULL;
4933eaaf 11693 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11694
9bcb3eef 11695 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11696 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11697
11698 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11699 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11700 pi->peer, pi->attr, p);
4933eaaf 11701
4027d19b
DS
11702 if (rpki_target_state != RPKI_NOT_BEING_USED
11703 && rpki_curr_state != rpki_target_state)
4933eaaf 11704 continue;
44c69747
LK
11705
11706 if (json && !json_paths) {
11707 /* Instantiate json_paths only if path is valid */
11708 json_paths = json_object_new_array();
11709 if (pfx_rd) {
11710 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11711 json_header = json_object_new_object();
11712 } else
11713 json_header = json;
11714 }
11715
11716 if (header) {
11717 route_vty_out_detail_header(
11718 vty, bgp, bgp_node, pfx_rd,
11719 AFI_IP, safi, json_header);
11720 header = 0;
11721 }
11722 (*display)++;
11723
11724 if (pathtype == BGP_PATH_SHOW_ALL
11725 || (pathtype == BGP_PATH_SHOW_BESTPATH
11726 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11727 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11728 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11729 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11730 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11731 safi, rpki_curr_state, json_paths);
44c69747
LK
11732 }
11733
11734 if (json && json_paths) {
11735 json_object_object_add(json_header, "paths", json_paths);
11736
11737 if (pfx_rd)
11738 json_object_object_add(json, rdbuf, json_header);
11739 }
11740}
11741
2aad8c42
MS
11742/*
11743 * Return rd based on safi
11744 */
11745static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11746 safi_t safi)
11747{
11748 switch (safi) {
11749 case SAFI_MPLS_VPN:
11750 case SAFI_ENCAP:
11751 case SAFI_EVPN:
11752 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11753 default:
11754 return NULL;
11755
11756 }
11757}
11758
718e3744 11759/* Display specified route of BGP table. */
d62a17ae 11760static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11761 struct bgp_table *rib, const char *ip_str,
11762 afi_t afi, safi_t safi,
4027d19b 11763 enum rpki_states rpki_target_state,
d62a17ae 11764 struct prefix_rd *prd, int prefix_check,
9f049418 11765 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11766{
11767 int ret;
d62a17ae 11768 int display = 0;
11769 struct prefix match;
9bcb3eef
DS
11770 struct bgp_dest *dest;
11771 struct bgp_dest *rm;
d62a17ae 11772 struct bgp_table *table;
11773 json_object *json = NULL;
11774 json_object *json_paths = NULL;
11775
11776 /* Check IP address argument. */
11777 ret = str2prefix(ip_str, &match);
11778 if (!ret) {
11779 vty_out(vty, "address is malformed\n");
11780 return CMD_WARNING;
11781 }
718e3744 11782
d62a17ae 11783 match.family = afi2family(afi);
b05a1c8b 11784
44c69747 11785 if (use_json)
d62a17ae 11786 json = json_object_new_object();
718e3744 11787
44c69747 11788 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11789 for (dest = bgp_table_top(rib); dest;
11790 dest = bgp_route_next(dest)) {
11791 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11792
9bcb3eef 11793 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11794 continue;
9bcb3eef 11795 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11796 if (!table)
ea47320b 11797 continue;
d62a17ae 11798
4953391b
DA
11799 rm = bgp_node_match(table, &match);
11800 if (rm == NULL)
ea47320b 11801 continue;
d62a17ae 11802
9bcb3eef 11803 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11804 if (prefix_check
b54892e0 11805 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11806 bgp_dest_unlock_node(rm);
ea47320b
DL
11807 continue;
11808 }
d62a17ae 11809
9bcb3eef 11810 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11811 bgp, afi, safi, json, pathtype,
4027d19b 11812 &display, rpki_target_state);
44c69747 11813
9bcb3eef 11814 bgp_dest_unlock_node(rm);
44c69747
LK
11815 }
11816 } else if (safi == SAFI_EVPN) {
9bcb3eef 11817 struct bgp_dest *longest_pfx;
cded3b72 11818 bool is_exact_pfxlen_match = false;
44c69747 11819
9bcb3eef
DS
11820 for (dest = bgp_table_top(rib); dest;
11821 dest = bgp_route_next(dest)) {
11822 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11823
9bcb3eef 11824 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11825 continue;
9bcb3eef 11826 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11827 if (!table)
11828 continue;
11829
11830 longest_pfx = NULL;
cded3b72 11831 is_exact_pfxlen_match = false;
44c69747
LK
11832 /*
11833 * Search through all the prefixes for a match. The
11834 * pfx's are enumerated in ascending order of pfxlens.
11835 * So, the last pfx match is the longest match. Set
11836 * is_exact_pfxlen_match when we get exact pfxlen match
11837 */
11838 for (rm = bgp_table_top(table); rm;
11839 rm = bgp_route_next(rm)) {
b54892e0 11840 const struct prefix *rm_p =
9bcb3eef 11841 bgp_dest_get_prefix(rm);
44c69747
LK
11842 /*
11843 * Get prefixlen of the ip-prefix within type5
11844 * evpn route
11845 */
b54892e0
DS
11846 if (evpn_type5_prefix_match(rm_p, &match)
11847 && rm->info) {
44c69747
LK
11848 longest_pfx = rm;
11849 int type5_pfxlen =
b54892e0
DS
11850 bgp_evpn_get_type5_prefixlen(
11851 rm_p);
44c69747 11852 if (type5_pfxlen == match.prefixlen) {
cded3b72 11853 is_exact_pfxlen_match = true;
9bcb3eef 11854 bgp_dest_unlock_node(rm);
44c69747
LK
11855 break;
11856 }
d62a17ae 11857 }
11858 }
ea47320b 11859
44c69747
LK
11860 if (!longest_pfx)
11861 continue;
11862
11863 if (prefix_check && !is_exact_pfxlen_match)
11864 continue;
11865
11866 rm = longest_pfx;
9bcb3eef 11867 bgp_dest_lock_node(rm);
44c69747 11868
9bcb3eef 11869 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11870 bgp, afi, safi, json, pathtype,
4027d19b 11871 &display, rpki_target_state);
44c69747 11872
9bcb3eef 11873 bgp_dest_unlock_node(rm);
d62a17ae 11874 }
98a9dbc7 11875 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11876 if (use_json)
11877 json_paths = json_object_new_array();
11878
63a0b7a9
PG
11879 display = bgp_flowspec_display_match_per_ip(afi, rib,
11880 &match, prefix_check,
11881 vty,
11882 use_json,
11883 json_paths);
d5f20468
SP
11884 if (use_json) {
11885 if (display)
11886 json_object_object_add(json, "paths",
11887 json_paths);
11888 else
11889 json_object_free(json_paths);
11890 }
d62a17ae 11891 } else {
4953391b
DA
11892 dest = bgp_node_match(rib, &match);
11893 if (dest != NULL) {
9bcb3eef 11894 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11895 if (!prefix_check
9bcb3eef
DS
11896 || dest_p->prefixlen == match.prefixlen) {
11897 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11898 safi, json, pathtype,
4027d19b 11899 &display, rpki_target_state);
d62a17ae 11900 }
11901
9bcb3eef 11902 bgp_dest_unlock_node(dest);
d62a17ae 11903 }
11904 }
e5eee9af 11905
d62a17ae 11906 if (use_json) {
75eeda93 11907 vty_json(vty, json);
d62a17ae 11908 } else {
11909 if (!display) {
11910 vty_out(vty, "%% Network not in table\n");
11911 return CMD_WARNING;
11912 }
11913 }
b05a1c8b 11914
d62a17ae 11915 return CMD_SUCCESS;
718e3744 11916}
11917
fee0f4c6 11918/* Display specified route of Main RIB */
d62a17ae 11919static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11920 afi_t afi, safi_t safi, struct prefix_rd *prd,
11921 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11922 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11923{
9b86009a 11924 if (!bgp) {
d62a17ae 11925 bgp = bgp_get_default();
9b86009a
RW
11926 if (!bgp) {
11927 if (!use_json)
11928 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11929 else
11930 vty_out(vty, "{}\n");
9b86009a
RW
11931 return CMD_WARNING;
11932 }
11933 }
d62a17ae 11934
11935 /* labeled-unicast routes live in the unicast table */
11936 if (safi == SAFI_LABELED_UNICAST)
11937 safi = SAFI_UNICAST;
11938
11939 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11940 afi, safi, rpki_target_state, prd,
8aa22bbb 11941 prefix_check, pathtype, use_json);
d62a17ae 11942}
11943
11944static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11945 struct cmd_token **argv, bool exact, afi_t afi,
11946 safi_t safi, bool uj)
d62a17ae 11947{
11948 struct lcommunity *lcom;
11949 struct buffer *b;
11950 int i;
11951 char *str;
11952 int first = 0;
96c81f66 11953 uint16_t show_flags = 0;
4f28b2b5 11954 int ret;
96f3485c
MK
11955
11956 if (uj)
11957 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11958
11959 b = buffer_new(1024);
11960 for (i = 0; i < argc; i++) {
11961 if (first)
11962 buffer_putc(b, ' ');
11963 else {
11964 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11965 first = 1;
11966 buffer_putstr(b, argv[i]->arg);
11967 }
11968 }
11969 }
11970 buffer_putc(b, '\0');
57d187bc 11971
d62a17ae 11972 str = buffer_getstr(b);
11973 buffer_free(b);
57d187bc 11974
d62a17ae 11975 lcom = lcommunity_str2com(str);
11976 XFREE(MTYPE_TMP, str);
11977 if (!lcom) {
11978 vty_out(vty, "%% Large-community malformed\n");
11979 return CMD_WARNING;
11980 }
57d187bc 11981
4f28b2b5 11982 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11983 (exact ? bgp_show_type_lcommunity_exact
11984 : bgp_show_type_lcommunity),
11985 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11986
11987 lcommunity_free(&lcom);
11988 return ret;
57d187bc
JS
11989}
11990
d62a17ae 11991static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11992 const char *lcom, bool exact, afi_t afi,
11993 safi_t safi, bool uj)
57d187bc 11994{
d62a17ae 11995 struct community_list *list;
96c81f66 11996 uint16_t show_flags = 0;
96f3485c
MK
11997
11998 if (uj)
11999 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12000
57d187bc 12001
e237b0d2 12002 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12003 LARGE_COMMUNITY_LIST_MASTER);
12004 if (list == NULL) {
12005 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12006 lcom);
12007 return CMD_WARNING;
12008 }
57d187bc 12009
36a206db 12010 return bgp_show(vty, bgp, afi, safi,
12011 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12012 : bgp_show_type_lcommunity_list),
1e2ce4f1 12013 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12014}
12015
52951b63
DS
12016DEFUN (show_ip_bgp_large_community_list,
12017 show_ip_bgp_large_community_list_cmd,
77a3a95e 12018 "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
12019 SHOW_STR
12020 IP_STR
12021 BGP_STR
12022 BGP_INSTANCE_HELP_STR
9bedbb1e 12023 BGP_AFI_HELP_STR
4dd6177e 12024 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12025 "Display routes matching the large-community-list\n"
12026 "large-community-list number\n"
12027 "large-community-list name\n"
36a206db 12028 "Exact match of the large-communities\n"
52951b63
DS
12029 JSON_STR)
12030{
d62a17ae 12031 afi_t afi = AFI_IP6;
12032 safi_t safi = SAFI_UNICAST;
12033 int idx = 0;
36a206db 12034 bool exact_match = 0;
4d678463 12035 struct bgp *bgp = NULL;
9f049418 12036 bool uj = use_json(argc, argv);
d62a17ae 12037
ef3364f0
DA
12038 if (uj)
12039 argc--;
4d678463 12040
ef3364f0
DA
12041 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12042 &bgp, uj);
12043 if (!idx)
12044 return CMD_WARNING;
d62a17ae 12045
12046 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12047
12048 const char *clist_number_or_name = argv[++idx]->arg;
12049
12050 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12051 exact_match = 1;
12052
12053 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12054 exact_match, afi, safi, uj);
52951b63
DS
12055}
12056DEFUN (show_ip_bgp_large_community,
12057 show_ip_bgp_large_community_cmd,
36a206db 12058 "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
12059 SHOW_STR
12060 IP_STR
12061 BGP_STR
12062 BGP_INSTANCE_HELP_STR
9bedbb1e 12063 BGP_AFI_HELP_STR
4dd6177e 12064 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12065 "Display routes matching the large-communities\n"
12066 "List of large-community numbers\n"
36a206db 12067 "Exact match of the large-communities\n"
52951b63
DS
12068 JSON_STR)
12069{
d62a17ae 12070 afi_t afi = AFI_IP6;
12071 safi_t safi = SAFI_UNICAST;
12072 int idx = 0;
36a206db 12073 bool exact_match = 0;
4d678463 12074 struct bgp *bgp = NULL;
9f049418 12075 bool uj = use_json(argc, argv);
96c81f66 12076 uint16_t show_flags = 0;
d62a17ae 12077
96f3485c
MK
12078 if (uj) {
12079 argc--;
12080 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12081 }
4d678463 12082
96f3485c
MK
12083 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12084 &bgp, uj);
12085 if (!idx)
12086 return CMD_WARNING;
d62a17ae 12087
36a206db 12088 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12089 if (argv_find(argv, argc, "exact-match", &idx))
12090 exact_match = 1;
12091 return bgp_show_lcommunity(vty, bgp, argc, argv,
12092 exact_match, afi, safi, uj);
12093 } else
d62a17ae 12094 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12095 bgp_show_type_lcommunity_all, NULL, show_flags,
12096 RPKI_NOT_BEING_USED);
52951b63
DS
12097}
12098
71f1613a
DA
12099static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12100 safi_t safi, struct json_object *json_array);
d62a17ae 12101static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12102 safi_t safi, struct json_object *json);
e01ca200 12103
7b2ff250 12104
9ab0cf58
PG
12105DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12106 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12107 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12108 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12109{
12110 bool uj = use_json(argc, argv);
12111 struct bgp *bgp = NULL;
ec76a1d1
DA
12112 safi_t safi = SAFI_UNICAST;
12113 afi_t afi = AFI_IP6;
4265b261 12114 int idx = 0;
6c9d22e2
PG
12115 struct json_object *json_all = NULL;
12116 struct json_object *json_afi_safi = NULL;
4265b261
PG
12117
12118 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12119 &bgp, false);
71f1613a 12120 if (!idx)
4265b261 12121 return CMD_WARNING;
6c9d22e2 12122
4265b261 12123 if (uj)
6c9d22e2 12124 json_all = json_object_new_object();
4265b261 12125
9ab0cf58
PG
12126 FOREACH_AFI_SAFI (afi, safi) {
12127 /*
12128 * So limit output to those afi/safi pairs that
12129 * actually have something interesting in them
12130 */
12131 if (strmatch(get_afi_safi_str(afi, safi, true),
12132 "Unknown")) {
12133 continue;
12134 }
12135 if (uj) {
12136 json_afi_safi = json_object_new_array();
12137 json_object_object_add(
12138 json_all,
12139 get_afi_safi_str(afi, safi, true),
12140 json_afi_safi);
12141 } else {
12142 json_afi_safi = NULL;
6c9d22e2 12143 }
9ab0cf58
PG
12144
12145 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12146 }
6c9d22e2 12147
3757f964
DA
12148 if (uj)
12149 vty_json(vty, json_all);
6c9d22e2 12150
4265b261
PG
12151 return CMD_SUCCESS;
12152}
12153
7b2ff250 12154/* BGP route print out function without JSON */
14718643
PG
12155DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12156 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12157 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12158 SHOW_STR
12159 IP_STR
12160 BGP_STR
12161 BGP_INSTANCE_HELP_STR
12162 L2VPN_HELP_STR
12163 EVPN_HELP_STR
12164 "BGP RIB advertisement statistics\n"
12165 JSON_STR)
12166{
ec76a1d1
DA
12167 afi_t afi = AFI_IP6;
12168 safi_t safi = SAFI_UNICAST;
14718643
PG
12169 struct bgp *bgp = NULL;
12170 int idx = 0, ret;
12171 bool uj = use_json(argc, argv);
12172 struct json_object *json_afi_safi = NULL, *json = NULL;
12173
12174 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12175 &bgp, false);
12176 if (!idx)
12177 return CMD_WARNING;
12178
12179 if (uj)
12180 json_afi_safi = json_object_new_array();
12181 else
12182 json_afi_safi = NULL;
12183
12184 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12185
12186 if (uj) {
12187 json = json_object_new_object();
12188 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12189 json_afi_safi);
3757f964 12190 vty_json(vty, json);
14718643
PG
12191 }
12192 return ret;
12193}
12194
893cccd0 12195/* BGP route print out function without JSON */
9ab0cf58
PG
12196DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12197 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12198 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12199 "]]\
893cccd0 12200 statistics [json]",
9ab0cf58
PG
12201 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12202 BGP_SAFI_WITH_LABEL_HELP_STR
12203 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12204{
ec76a1d1
DA
12205 afi_t afi = AFI_IP6;
12206 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12207 struct bgp *bgp = NULL;
12208 int idx = 0, ret;
12209 bool uj = use_json(argc, argv);
6c9d22e2 12210 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12211
12212 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12213 &bgp, false);
12214 if (!idx)
12215 return CMD_WARNING;
6c9d22e2 12216
893cccd0 12217 if (uj)
6c9d22e2
PG
12218 json_afi_safi = json_object_new_array();
12219 else
12220 json_afi_safi = NULL;
12221
12222 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12223
12224 if (uj) {
12225 json = json_object_new_object();
12226 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12227 json_afi_safi);
3757f964 12228 vty_json(vty, json);
893cccd0
PG
12229 }
12230 return ret;
893cccd0 12231}
7b2ff250 12232
fe0f234d 12233DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12234 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12235 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12236 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12237 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12238 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12239 "Display the entries for all address families\n"
9ab0cf58
PG
12240 "Display detailed information about dampening\n"
12241 "Display detail of configured dampening parameters\n"
fe0f234d 12242 JSON_STR)
718e3744 12243{
d62a17ae 12244 afi_t afi = AFI_IP6;
12245 safi_t safi = SAFI_UNICAST;
d62a17ae 12246 struct bgp *bgp = NULL;
12247 int idx = 0;
96c81f66 12248 uint16_t show_flags = 0;
fe0f234d
RW
12249 bool uj = use_json(argc, argv);
12250
12251 if (uj) {
12252 argc--;
12253 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12254 }
96f3485c
MK
12255
12256 /* [<ipv4|ipv6> [all]] */
12257 if (all) {
12258 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12259 if (argv_find(argv, argc, "ipv4", &idx))
12260 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12261
12262 if (argv_find(argv, argc, "ipv6", &idx))
12263 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12264 }
d62a17ae 12265
12266 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12267 &bgp, false);
d62a17ae 12268 if (!idx)
12269 return CMD_WARNING;
12270
fe0f234d 12271 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12272}
12273
fe0f234d
RW
12274/* BGP route print out function */
12275DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12276 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12277 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12278 "]]\
96f3485c 12279 [all$all]\
cf4898bc
QY
12280 [cidr-only\
12281 |dampening <flap-statistics|dampened-paths>\
12282 |community [AA:NN|local-AS|no-advertise|no-export\
12283 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12284 |accept-own|accept-own-nexthop|route-filter-v6\
12285 |route-filter-v4|route-filter-translated-v6\
12286 |route-filter-translated-v4] [exact-match]\
70799983 12287 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12288 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12289 |prefix-list WORD\
70dd370f 12290 |route-map RMAP_NAME\
1e2ce4f1 12291 |rpki <invalid|valid|notfound>\
7d3cae70 12292 |version (1-4294967295)\
b4ad2fae 12293 |alias ALIAS_NAME\
39c3c736
RW
12294 |A.B.C.D/M longer-prefixes\
12295 |X:X::X:X/M longer-prefixes\
f280c93b 12296 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12297 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12298 BGP_SAFI_WITH_LABEL_HELP_STR
12299 "Display the entries for all address families\n"
12300 "Display only routes with non-natural netmasks\n"
12301 "Display detailed information about dampening\n"
12302 "Display flap statistics of routes\n"
12303 "Display paths suppressed due to dampening\n"
12304 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12305 "Do not send outside local AS (well-known community)\n"
12306 "Do not advertise to any peer (well-known community)\n"
12307 "Do not export to next AS (well-known community)\n"
12308 "Graceful shutdown (well-known community)\n"
12309 "Do not export to any peer (well-known community)\n"
12310 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12311 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12312 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12313 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12314 "Should accept VPN route with local nexthop (well-known community)\n"
12315 "RT VPNv6 route filtering (well-known community)\n"
12316 "RT VPNv4 route filtering (well-known community)\n"
12317 "RT translated VPNv6 route filtering (well-known community)\n"
12318 "RT translated VPNv4 route filtering (well-known community)\n"
12319 "Exact match of the communities\n"
70799983
RW
12320 "Community-list number\n"
12321 "Community-list name\n"
12322 "Display routes matching the community-list\n"
12323 "Exact match of the communities\n"
a7129347
RW
12324 "Display routes conforming to the filter-list\n"
12325 "Regular expression access list name\n"
6deaf579
RW
12326 "Display routes conforming to the prefix-list\n"
12327 "Prefix-list name\n"
bf1a944a
RW
12328 "Display routes matching the route-map\n"
12329 "A route-map to match on\n"
a70a28a5
DA
12330 "RPKI route types\n"
12331 "A valid path as determined by rpki\n"
12332 "A invalid path as determined by rpki\n"
12333 "A path that has no rpki data\n"
12334 "Display prefixes with matching version numbers\n"
12335 "Version number and above\n"
12336 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12337 "BGP community alias\n"
12338 "IPv4 prefix\n"
12339 "Display route and more specific routes\n"
12340 "IPv6 prefix\n"
12341 "Display route and more specific routes\n"
12342 JSON_STR
a70a28a5
DA
12343 "Display detailed version of JSON output\n"
12344 "Increase table width for longer prefixes\n")
7b2ff250
DW
12345{
12346 afi_t afi = AFI_IP6;
12347 safi_t safi = SAFI_UNICAST;
12348 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12349 void *output_arg = NULL;
7b2ff250
DW
12350 struct bgp *bgp = NULL;
12351 int idx = 0;
d0086e8e 12352 int exact_match = 0;
96f3485c
MK
12353 char *community = NULL;
12354 bool first = true;
96c81f66 12355 uint16_t show_flags = 0;
4027d19b 12356 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12357 struct prefix p;
96f3485c
MK
12358
12359 if (uj) {
9f049418 12360 argc--;
96f3485c
MK
12361 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12362 }
12363
f280c93b
DA
12364 if (detail)
12365 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12366
96f3485c
MK
12367 /* [<ipv4|ipv6> [all]] */
12368 if (all) {
12369 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12370
12371 if (argv_find(argv, argc, "ipv4", &idx))
12372 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12373
12374 if (argv_find(argv, argc, "ipv6", &idx))
12375 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12376 }
12377
12378 if (wide)
12379 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12380
12381 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12382 &bgp, uj);
7b2ff250
DW
12383 if (!idx)
12384 return CMD_WARNING;
12385
7b2ff250 12386 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12387 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12388
12389 if (argv_find(argv, argc, "dampening", &idx)) {
12390 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12391 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12392 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12393 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12394 }
12395
12396 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12397 char *maybecomm = NULL;
d0086e8e 12398
79bc257a
RW
12399 if (idx + 1 < argc) {
12400 if (argv[idx + 1]->type == VARIABLE_TKN)
12401 maybecomm = argv[idx + 1]->arg;
12402 else
12403 maybecomm = argv[idx + 1]->text;
12404 }
12405
cf4898bc
QY
12406 if (maybecomm && !strmatch(maybecomm, "json")
12407 && !strmatch(maybecomm, "exact-match"))
12408 community = maybecomm;
d0086e8e 12409
cf4898bc
QY
12410 if (argv_find(argv, argc, "exact-match", &idx))
12411 exact_match = 1;
d0086e8e 12412
96f3485c
MK
12413 if (!community)
12414 sh_type = bgp_show_type_community_all;
12415 }
12416
70799983
RW
12417 if (argv_find(argv, argc, "community-list", &idx)) {
12418 const char *clist_number_or_name = argv[++idx]->arg;
12419 struct community_list *list;
12420
12421 if (argv_find(argv, argc, "exact-match", &idx))
12422 exact_match = 1;
12423
12424 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12425 COMMUNITY_LIST_MASTER);
12426 if (list == NULL) {
12427 vty_out(vty,
12428 "%% %s is not a valid community-list name\n",
12429 clist_number_or_name);
12430 return CMD_WARNING;
12431 }
12432
12433 if (exact_match)
12434 sh_type = bgp_show_type_community_list_exact;
12435 else
12436 sh_type = bgp_show_type_community_list;
12437 output_arg = list;
12438 }
12439
a7129347
RW
12440 if (argv_find(argv, argc, "filter-list", &idx)) {
12441 const char *filter = argv[++idx]->arg;
12442 struct as_list *as_list;
12443
12444 as_list = as_list_lookup(filter);
12445 if (as_list == NULL) {
12446 vty_out(vty,
12447 "%% %s is not a valid AS-path access-list name\n",
12448 filter);
12449 return CMD_WARNING;
12450 }
12451
12452 sh_type = bgp_show_type_filter_list;
12453 output_arg = as_list;
12454 }
12455
6deaf579
RW
12456 if (argv_find(argv, argc, "prefix-list", &idx)) {
12457 const char *prefix_list_str = argv[++idx]->arg;
12458 struct prefix_list *plist;
12459
12460 plist = prefix_list_lookup(afi, prefix_list_str);
12461 if (plist == NULL) {
12462 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12463 prefix_list_str);
12464 return CMD_WARNING;
12465 }
12466
12467 sh_type = bgp_show_type_prefix_list;
12468 output_arg = plist;
12469 }
12470
bf1a944a
RW
12471 if (argv_find(argv, argc, "route-map", &idx)) {
12472 const char *rmap_str = argv[++idx]->arg;
12473 struct route_map *rmap;
12474
12475 rmap = route_map_lookup_by_name(rmap_str);
12476 if (!rmap) {
12477 vty_out(vty, "%% %s is not a valid route-map name\n",
12478 rmap_str);
12479 return CMD_WARNING;
12480 }
12481
12482 sh_type = bgp_show_type_route_map;
12483 output_arg = rmap;
12484 }
12485
1e2ce4f1
DS
12486 if (argv_find(argv, argc, "rpki", &idx)) {
12487 sh_type = bgp_show_type_rpki;
12488 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12489 rpki_target_state = RPKI_VALID;
1e2ce4f1 12490 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12491 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12492 }
12493
7d3cae70
DA
12494 /* Display prefixes with matching version numbers */
12495 if (argv_find(argv, argc, "version", &idx)) {
12496 sh_type = bgp_show_type_prefix_version;
2391833e 12497 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12498 }
12499
a70a28a5
DA
12500 /* Display prefixes with matching BGP community alias */
12501 if (argv_find(argv, argc, "alias", &idx)) {
12502 sh_type = bgp_show_type_community_alias;
2391833e 12503 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12504 }
12505
39c3c736
RW
12506 /* prefix-longer */
12507 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12508 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12509 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12510
12511 if (!str2prefix(prefix_str, &p)) {
12512 vty_out(vty, "%% Malformed Prefix\n");
12513 return CMD_WARNING;
12514 }
12515
12516 sh_type = bgp_show_type_prefix_longer;
12517 output_arg = &p;
a70a28a5
DA
12518 }
12519
96f3485c
MK
12520 if (!all) {
12521 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12522 if (community)
12523 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12524 exact_match, afi, safi,
12525 show_flags);
2391833e 12526 else
a70a28a5 12527 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12528 output_arg, show_flags,
a70a28a5 12529 rpki_target_state);
96f3485c 12530 } else {
fa5ac378
DA
12531 struct listnode *node;
12532 struct bgp *abgp;
96f3485c
MK
12533 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12534 * AFI_IP6 */
12535
12536 if (uj)
12537 vty_out(vty, "{\n");
12538
12539 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12540 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12541 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12542 ? AFI_IP
12543 : AFI_IP6;
fa5ac378
DA
12544 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12545 FOREACH_SAFI (safi) {
12546 if (!bgp_afi_safi_peer_exists(abgp, afi,
12547 safi))
12548 continue;
96f3485c 12549
fa5ac378
DA
12550 if (uj) {
12551 if (first)
12552 first = false;
12553 else
12554 vty_out(vty, ",\n");
12555 vty_out(vty, "\"%s\":{\n",
12556 get_afi_safi_str(afi,
12557 safi,
12558 true));
12559 } else
12560 vty_out(vty,
12561 "\nFor address family: %s\n",
12562 get_afi_safi_str(
12563 afi, safi,
12564 false));
12565
12566 if (community)
12567 bgp_show_community(
12568 vty, abgp, community,
12569 exact_match, afi, safi,
12570 show_flags);
96f3485c 12571 else
fa5ac378
DA
12572 bgp_show(vty, abgp, afi, safi,
12573 sh_type, output_arg,
12574 show_flags,
12575 rpki_target_state);
12576 if (uj)
12577 vty_out(vty, "}\n");
12578 }
96f3485c
MK
12579 }
12580 } else {
12581 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12582 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12583 FOREACH_AFI_SAFI (afi, safi) {
12584 if (!bgp_afi_safi_peer_exists(abgp, afi,
12585 safi))
12586 continue;
96f3485c 12587
fa5ac378
DA
12588 if (uj) {
12589 if (first)
12590 first = false;
12591 else
12592 vty_out(vty, ",\n");
12593
12594 vty_out(vty, "\"%s\":{\n",
12595 get_afi_safi_str(afi,
12596 safi,
12597 true));
12598 } else
12599 vty_out(vty,
12600 "\nFor address family: %s\n",
12601 get_afi_safi_str(
12602 afi, safi,
12603 false));
12604
12605 if (community)
12606 bgp_show_community(
12607 vty, abgp, community,
12608 exact_match, afi, safi,
12609 show_flags);
96f3485c 12610 else
fa5ac378
DA
12611 bgp_show(vty, abgp, afi, safi,
12612 sh_type, output_arg,
12613 show_flags,
12614 rpki_target_state);
12615 if (uj)
12616 vty_out(vty, "}\n");
12617 }
96f3485c
MK
12618 }
12619 }
12620 if (uj)
12621 vty_out(vty, "}\n");
12622 }
12623 return CMD_SUCCESS;
a636c635 12624}
47fc97cc 12625
718e3744 12626DEFUN (show_ip_bgp_route,
12627 show_ip_bgp_route_cmd,
8aa22bbb 12628 "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 12629 SHOW_STR
12630 IP_STR
12631 BGP_STR
a636c635 12632 BGP_INSTANCE_HELP_STR
4f280b15 12633 BGP_AFI_HELP_STR
4dd6177e 12634 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12635 "Network in the BGP routing table to display\n"
0c7b1b01 12636 "IPv4 prefix\n"
8c3deaae 12637 "Network in the BGP routing table to display\n"
0c7b1b01 12638 "IPv6 prefix\n"
4092b06c 12639 "Display only the bestpath\n"
b05a1c8b 12640 "Display only multipaths\n"
8aa22bbb
DS
12641 "Display only paths that match the specified rpki state\n"
12642 "A valid path as determined by rpki\n"
12643 "A invalid path as determined by rpki\n"
12644 "A path that has no rpki data\n"
9973d184 12645 JSON_STR)
4092b06c 12646{
d62a17ae 12647 int prefix_check = 0;
ae19d7dd 12648
d62a17ae 12649 afi_t afi = AFI_IP6;
12650 safi_t safi = SAFI_UNICAST;
12651 char *prefix = NULL;
12652 struct bgp *bgp = NULL;
12653 enum bgp_path_type path_type;
9f049418 12654 bool uj = use_json(argc, argv);
b05a1c8b 12655
d62a17ae 12656 int idx = 0;
ae19d7dd 12657
d62a17ae 12658 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12659 &bgp, uj);
d62a17ae 12660 if (!idx)
12661 return CMD_WARNING;
c41247f5 12662
d62a17ae 12663 if (!bgp) {
12664 vty_out(vty,
12665 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12666 return CMD_WARNING;
12667 }
a636c635 12668
d62a17ae 12669 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12670 if (argv_find(argv, argc, "A.B.C.D", &idx)
12671 || argv_find(argv, argc, "X:X::X:X", &idx))
12672 prefix_check = 0;
12673 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12674 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12675 prefix_check = 1;
12676
12677 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12678 && afi != AFI_IP6) {
12679 vty_out(vty,
12680 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12681 return CMD_WARNING;
12682 }
12683 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12684 && afi != AFI_IP) {
12685 vty_out(vty,
12686 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12687 return CMD_WARNING;
12688 }
12689
12690 prefix = argv[idx]->arg;
12691
12692 /* [<bestpath|multipath>] */
12693 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12694 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12695 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12696 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12697 else
360660c6 12698 path_type = BGP_PATH_SHOW_ALL;
a636c635 12699
d62a17ae 12700 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12701 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12702}
12703
8c3deaae
QY
12704DEFUN (show_ip_bgp_regexp,
12705 show_ip_bgp_regexp_cmd,
3e5b31b3 12706 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12707 SHOW_STR
12708 IP_STR
12709 BGP_STR
b00b230a 12710 BGP_INSTANCE_HELP_STR
4f280b15 12711 BGP_AFI_HELP_STR
4dd6177e 12712 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12713 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12714 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12715 JSON_STR)
8c3deaae 12716{
d62a17ae 12717 afi_t afi = AFI_IP6;
12718 safi_t safi = SAFI_UNICAST;
12719 struct bgp *bgp = NULL;
3e5b31b3
DA
12720 bool uj = use_json(argc, argv);
12721 char *regstr = NULL;
8c3deaae 12722
d62a17ae 12723 int idx = 0;
12724 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12725 &bgp, false);
d62a17ae 12726 if (!idx)
12727 return CMD_WARNING;
8c3deaae 12728
d62a17ae 12729 // get index of regex
3e5b31b3
DA
12730 if (argv_find(argv, argc, "REGEX", &idx))
12731 regstr = argv[idx]->arg;
8c3deaae 12732
5f71d11c 12733 assert(regstr);
3e5b31b3
DA
12734 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12735 bgp_show_type_regexp, uj);
8c3deaae
QY
12736}
12737
ae248832 12738DEFPY (show_ip_bgp_instance_all,
a636c635 12739 show_ip_bgp_instance_all_cmd,
ae248832 12740 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12741 SHOW_STR
a636c635 12742 IP_STR
4092b06c 12743 BGP_STR
a636c635 12744 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12745 BGP_AFI_HELP_STR
4dd6177e 12746 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12747 JSON_STR
12748 "Increase table width for longer prefixes\n")
4092b06c 12749{
54d05dea 12750 afi_t afi = AFI_IP6;
d62a17ae 12751 safi_t safi = SAFI_UNICAST;
12752 struct bgp *bgp = NULL;
d62a17ae 12753 int idx = 0;
96c81f66 12754 uint16_t show_flags = 0;
ae19d7dd 12755
96f3485c 12756 if (uj) {
d62a17ae 12757 argc--;
96f3485c
MK
12758 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12759 }
12760
12761 if (wide)
12762 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12763
9f049418
DS
12764 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12765 &bgp, uj);
12766 if (!idx)
12767 return CMD_WARNING;
12768
96f3485c 12769 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12770 return CMD_SUCCESS;
e3e29b32
LB
12771}
12772
a4d82a8a 12773static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12774 afi_t afi, safi_t safi, enum bgp_show_type type,
12775 bool use_json)
718e3744 12776{
d62a17ae 12777 regex_t *regex;
12778 int rc;
96c81f66 12779 uint16_t show_flags = 0;
96f3485c
MK
12780
12781 if (use_json)
12782 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12783
c3900853 12784 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12785 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12786 regstr);
12787 return CMD_WARNING_CONFIG_FAILED;
12788 }
12789
d62a17ae 12790 regex = bgp_regcomp(regstr);
12791 if (!regex) {
12792 vty_out(vty, "Can't compile regexp %s\n", regstr);
12793 return CMD_WARNING;
12794 }
a636c635 12795
1e2ce4f1
DS
12796 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12797 RPKI_NOT_BEING_USED);
d62a17ae 12798 bgp_regex_free(regex);
12799 return rc;
e3e29b32
LB
12800}
12801
7f323236
DW
12802static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12803 const char *comstr, int exact, afi_t afi,
96c81f66 12804 safi_t safi, uint16_t show_flags)
d62a17ae 12805{
12806 struct community *com;
d62a17ae 12807 int ret = 0;
12808
7f323236 12809 com = community_str2com(comstr);
d62a17ae 12810 if (!com) {
7f323236 12811 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12812 return CMD_WARNING;
12813 }
12814
12815 ret = bgp_show(vty, bgp, afi, safi,
12816 (exact ? bgp_show_type_community_exact
12817 : bgp_show_type_community),
1e2ce4f1 12818 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12819 community_free(&com);
46c3ce83 12820
d62a17ae 12821 return ret;
718e3744 12822}
12823
d62a17ae 12824enum bgp_stats {
12825 BGP_STATS_MAXBITLEN = 0,
12826 BGP_STATS_RIB,
12827 BGP_STATS_PREFIXES,
12828 BGP_STATS_TOTPLEN,
12829 BGP_STATS_UNAGGREGATEABLE,
12830 BGP_STATS_MAX_AGGREGATEABLE,
12831 BGP_STATS_AGGREGATES,
12832 BGP_STATS_SPACE,
12833 BGP_STATS_ASPATH_COUNT,
12834 BGP_STATS_ASPATH_MAXHOPS,
12835 BGP_STATS_ASPATH_TOTHOPS,
12836 BGP_STATS_ASPATH_MAXSIZE,
12837 BGP_STATS_ASPATH_TOTSIZE,
12838 BGP_STATS_ASN_HIGHEST,
12839 BGP_STATS_MAX,
a636c635 12840};
2815e61f 12841
9ab0cf58 12842#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12843#define TABLE_STATS_IDX_JSON 1
12844
12845static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12846 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12847 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12848 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12849 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12850 "unaggregateablePrefixes"},
12851 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12852 "maximumAggregateablePrefixes"},
12853 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12854 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12855 [BGP_STATS_SPACE] = {"Address space advertised",
12856 "addressSpaceAdvertised"},
9ab0cf58
PG
12857 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12858 "advertisementsWithPaths"},
12859 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12860 "longestAsPath"},
12861 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12862 "largestAsPath"},
12863 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12864 "averageAsPathLengthHops"},
12865 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12866 "averageAsPathSizeBytes"},
12867 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12868 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12869};
2815e61f 12870
d62a17ae 12871struct bgp_table_stats {
12872 struct bgp_table *table;
12873 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
12874
12875 unsigned long long
12876 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
12877 1];
12878
8d0ab76d 12879 double total_space;
ff7924f6
PJ
12880};
12881
9bcb3eef 12882static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12883 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12884{
9bcb3eef 12885 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12886 struct bgp_path_info *pi;
b54892e0 12887 const struct prefix *rn_p;
d62a17ae 12888
9bcb3eef 12889 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12890 return;
d62a17ae 12891
9bcb3eef 12892 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12893 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12894 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12895
0747643e 12896 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 12897 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12898 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12899 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12900
9bcb3eef 12901 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12902 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12903 /* announced address space */
12904 if (space)
b54892e0 12905 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12906 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12907 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12908
9c14ec72 12909
9bcb3eef 12910 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12911 ts->counts[BGP_STATS_RIB]++;
12912
05864da7
DS
12913 if (CHECK_FLAG(pi->attr->flag,
12914 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12915 ts->counts[BGP_STATS_AGGREGATES]++;
12916
12917 /* as-path stats */
05864da7 12918 if (pi->attr->aspath) {
9c14ec72
RW
12919 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12920 unsigned int size = aspath_size(pi->attr->aspath);
12921 as_t highest = aspath_highest(pi->attr->aspath);
12922
12923 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12924
12925 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12926 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12927
12928 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12929 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12930
12931 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12932 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12933 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12934 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12935 }
12936 }
12937}
12938
cc9f21da 12939static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12940{
9bcb3eef
DS
12941 struct bgp_dest *dest, *ndest;
12942 struct bgp_dest *top;
9c14ec72
RW
12943 struct bgp_table_stats *ts = THREAD_ARG(t);
12944 unsigned int space = 0;
12945
12946 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12947 return;
9c14ec72
RW
12948
12949 switch (ts->table->afi) {
12950 case AFI_IP:
12951 space = IPV4_MAX_BITLEN;
12952 break;
12953 case AFI_IP6:
12954 space = IPV6_MAX_BITLEN;
12955 break;
3ba7b4af
TA
12956 case AFI_L2VPN:
12957 space = EVPN_ROUTE_PREFIXLEN;
12958 break;
9c14ec72 12959 default:
cc9f21da 12960 return;
9c14ec72
RW
12961 }
12962
12963 ts->counts[BGP_STATS_MAXBITLEN] = space;
12964
9bcb3eef 12965 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12966 if (ts->table->safi == SAFI_MPLS_VPN
12967 || ts->table->safi == SAFI_ENCAP
12968 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12969 struct bgp_table *table;
12970
9bcb3eef 12971 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12972 if (!table)
12973 continue;
12974
12975 top = bgp_table_top(table);
9bcb3eef
DS
12976 for (ndest = bgp_table_top(table); ndest;
12977 ndest = bgp_route_next(ndest))
12978 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12979 } else {
9bcb3eef 12980 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12981 }
12982 }
2815e61f 12983}
ff7924f6 12984
71f1613a
DA
12985static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12986 struct json_object *json_array)
12987{
12988 struct listnode *node, *nnode;
12989 struct bgp *bgp;
12990
12991 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12992 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12993}
12994
12995static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12996 safi_t safi, struct json_object *json_array)
2815e61f 12997{
d62a17ae 12998 struct bgp_table_stats ts;
12999 unsigned int i;
893cccd0
PG
13000 int ret = CMD_SUCCESS;
13001 char temp_buf[20];
6c9d22e2 13002 struct json_object *json = NULL;
0747643e
AQ
13003 uint32_t bitlen = 0;
13004 struct json_object *json_bitlen;
6c9d22e2
PG
13005
13006 if (json_array)
13007 json = json_object_new_object();
019386c2 13008
d62a17ae 13009 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13010 char warning_msg[50];
13011
13012 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13013 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13014 safi);
6c9d22e2
PG
13015
13016 if (!json)
893cccd0
PG
13017 vty_out(vty, "%s\n", warning_msg);
13018 else
9ab0cf58 13019 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13020
893cccd0
PG
13021 ret = CMD_WARNING;
13022 goto end_table_stats;
d62a17ae 13023 }
019386c2 13024
893cccd0 13025 if (!json)
5290ceab
DA
13026 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13027 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13028 else
13029 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13030
d62a17ae 13031 /* labeled-unicast routes live in the unicast table */
13032 if (safi == SAFI_LABELED_UNICAST)
13033 safi = SAFI_UNICAST;
019386c2 13034
d62a17ae 13035 memset(&ts, 0, sizeof(ts));
13036 ts.table = bgp->rib[afi][safi];
13037 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13038
d62a17ae 13039 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13040 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13041 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13042 continue;
13043
13044 switch (i) {
d62a17ae 13045 case BGP_STATS_ASPATH_TOTHOPS:
13046 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13047 if (!json) {
9ab0cf58
PG
13048 snprintf(
13049 temp_buf, sizeof(temp_buf), "%12.2f",
13050 ts.counts[i]
13051 ? (float)ts.counts[i]
13052 / (float)ts.counts
13053 [BGP_STATS_ASPATH_COUNT]
13054 : 0);
893cccd0 13055 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13056 table_stats_strs[i]
13057 [TABLE_STATS_IDX_VTY],
893cccd0 13058 temp_buf);
9ab0cf58
PG
13059 } else {
13060 json_object_double_add(
13061 json,
13062 table_stats_strs[i]
13063 [TABLE_STATS_IDX_JSON],
13064 ts.counts[i]
13065 ? (double)ts.counts[i]
13066 / (double)ts.counts
d62a17ae 13067 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13068 : 0);
13069 }
d62a17ae 13070 break;
13071 case BGP_STATS_TOTPLEN:
6c9d22e2 13072 if (!json) {
9ab0cf58
PG
13073 snprintf(
13074 temp_buf, sizeof(temp_buf), "%12.2f",
13075 ts.counts[i]
13076 ? (float)ts.counts[i]
13077 / (float)ts.counts
13078 [BGP_STATS_PREFIXES]
13079 : 0);
893cccd0 13080 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13081 table_stats_strs[i]
13082 [TABLE_STATS_IDX_VTY],
893cccd0 13083 temp_buf);
9ab0cf58
PG
13084 } else {
13085 json_object_double_add(
13086 json,
13087 table_stats_strs[i]
13088 [TABLE_STATS_IDX_JSON],
13089 ts.counts[i]
13090 ? (double)ts.counts[i]
13091 / (double)ts.counts
d62a17ae 13092 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13093 : 0);
13094 }
d62a17ae 13095 break;
13096 case BGP_STATS_SPACE:
6c9d22e2
PG
13097 if (!json) {
13098 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13099 ts.total_space);
893cccd0 13100 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13101 table_stats_strs[i]
13102 [TABLE_STATS_IDX_VTY],
893cccd0 13103 temp_buf);
9ab0cf58
PG
13104 } else {
13105 json_object_double_add(
13106 json,
13107 table_stats_strs[i]
13108 [TABLE_STATS_IDX_JSON],
13109 (double)ts.total_space);
13110 }
8d0ab76d 13111 if (afi == AFI_IP6) {
6c9d22e2
PG
13112 if (!json) {
13113 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13114 "%12g",
13115 ts.total_space
13116 * pow(2.0, -128 + 32));
6c9d22e2
PG
13117 vty_out(vty, "%30s: %s\n",
13118 "/32 equivalent %s\n",
13119 temp_buf);
9ab0cf58
PG
13120 } else {
13121 json_object_double_add(
13122 json, "/32equivalent",
13123 (double)(ts.total_space
13124 * pow(2.0,
13125 -128 + 32)));
13126 }
6c9d22e2
PG
13127 if (!json) {
13128 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13129 "%12g",
13130 ts.total_space
13131 * pow(2.0, -128 + 48));
6c9d22e2
PG
13132 vty_out(vty, "%30s: %s\n",
13133 "/48 equivalent %s\n",
13134 temp_buf);
9ab0cf58
PG
13135 } else {
13136 json_object_double_add(
13137 json, "/48equivalent",
13138 (double)(ts.total_space
13139 * pow(2.0,
13140 -128 + 48)));
13141 }
8d0ab76d 13142 } else {
6c9d22e2
PG
13143 if (!json) {
13144 snprintf(temp_buf, sizeof(temp_buf),
13145 "%12.2f",
9ab0cf58
PG
13146 ts.total_space * 100.
13147 * pow(2.0, -32));
6c9d22e2 13148 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13149 "% announced ", temp_buf);
13150 } else {
13151 json_object_double_add(
13152 json, "%announced",
13153 (double)(ts.total_space * 100.
13154 * pow(2.0, -32)));
13155 }
6c9d22e2
PG
13156 if (!json) {
13157 snprintf(temp_buf, sizeof(temp_buf),
13158 "%12.2f",
9ab0cf58
PG
13159 ts.total_space
13160 * pow(2.0, -32 + 8));
6c9d22e2
PG
13161 vty_out(vty, "%30s: %s\n",
13162 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13163 } else {
13164 json_object_double_add(
13165 json, "/8equivalent",
13166 (double)(ts.total_space
13167 * pow(2.0, -32 + 8)));
13168 }
6c9d22e2
PG
13169 if (!json) {
13170 snprintf(temp_buf, sizeof(temp_buf),
13171 "%12.2f",
9ab0cf58
PG
13172 ts.total_space
13173 * pow(2.0, -32 + 24));
6c9d22e2 13174 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13175 "/24 equivalent ", temp_buf);
13176 } else {
13177 json_object_double_add(
13178 json, "/24equivalent",
13179 (double)(ts.total_space
13180 * pow(2.0, -32 + 24)));
13181 }
8d0ab76d 13182 }
d62a17ae 13183 break;
13184 default:
6c9d22e2
PG
13185 if (!json) {
13186 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13187 ts.counts[i]);
893cccd0 13188 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13189 table_stats_strs[i]
13190 [TABLE_STATS_IDX_VTY],
13191 temp_buf);
13192 } else {
13193 json_object_int_add(
13194 json,
13195 table_stats_strs[i]
13196 [TABLE_STATS_IDX_JSON],
13197 ts.counts[i]);
13198 }
d62a17ae 13199 }
893cccd0
PG
13200 if (!json)
13201 vty_out(vty, "\n");
d62a17ae 13202 }
0747643e
AQ
13203
13204 switch (afi) {
13205 case AFI_IP:
13206 bitlen = IPV4_MAX_BITLEN;
13207 break;
13208 case AFI_IP6:
13209 bitlen = IPV6_MAX_BITLEN;
13210 break;
13211 case AFI_L2VPN:
13212 bitlen = EVPN_ROUTE_PREFIXLEN;
13213 break;
13214 default:
13215 break;
13216 }
13217
13218 if (json) {
13219 json_bitlen = json_object_new_array();
13220
13221 for (i = 0; i <= bitlen; i++) {
13222 struct json_object *ind_bit = json_object_new_object();
13223
13224 if (!ts.prefix_len_count[i])
13225 continue;
13226
13227 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13228 json_object_int_add(ind_bit, temp_buf,
13229 ts.prefix_len_count[i]);
13230 json_object_array_add(json_bitlen, ind_bit);
13231 }
13232 json_object_object_add(json, "prefixLength", json_bitlen);
13233 }
13234
9ab0cf58 13235end_table_stats:
6c9d22e2
PG
13236 if (json)
13237 json_object_array_add(json_array, json);
893cccd0 13238 return ret;
d62a17ae 13239}
13240
71f1613a
DA
13241static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13242 safi_t safi, struct json_object *json_array)
13243{
13244 if (!bgp) {
13245 bgp_table_stats_all(vty, afi, safi, json_array);
13246 return CMD_SUCCESS;
13247 }
13248
13249 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13250}
13251
d62a17ae 13252enum bgp_pcounts {
13253 PCOUNT_ADJ_IN = 0,
13254 PCOUNT_DAMPED,
13255 PCOUNT_REMOVED,
13256 PCOUNT_HISTORY,
13257 PCOUNT_STALE,
13258 PCOUNT_VALID,
13259 PCOUNT_ALL,
13260 PCOUNT_COUNTED,
7e3d9632 13261 PCOUNT_BPATH_SELECTED,
d62a17ae 13262 PCOUNT_PFCNT, /* the figure we display to users */
13263 PCOUNT_MAX,
a636c635 13264};
718e3744 13265
2b64873d 13266static const char *const pcount_strs[] = {
9d303b37
DL
13267 [PCOUNT_ADJ_IN] = "Adj-in",
13268 [PCOUNT_DAMPED] = "Damped",
13269 [PCOUNT_REMOVED] = "Removed",
13270 [PCOUNT_HISTORY] = "History",
13271 [PCOUNT_STALE] = "Stale",
13272 [PCOUNT_VALID] = "Valid",
13273 [PCOUNT_ALL] = "All RIB",
13274 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13275 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13276 [PCOUNT_PFCNT] = "Useable",
13277 [PCOUNT_MAX] = NULL,
a636c635 13278};
718e3744 13279
d62a17ae 13280struct peer_pcounts {
13281 unsigned int count[PCOUNT_MAX];
13282 const struct peer *peer;
13283 const struct bgp_table *table;
54317cba 13284 safi_t safi;
a636c635 13285};
47fc97cc 13286
9bcb3eef 13287static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13288{
54317cba
JW
13289 const struct bgp_adj_in *ain;
13290 const struct bgp_path_info *pi;
d62a17ae 13291 const struct peer *peer = pc->peer;
13292
54317cba
JW
13293 for (ain = rn->adj_in; ain; ain = ain->next)
13294 if (ain->peer == peer)
13295 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13296
9bcb3eef 13297 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13298
54317cba
JW
13299 if (pi->peer != peer)
13300 continue;
d62a17ae 13301
54317cba 13302 pc->count[PCOUNT_ALL]++;
d62a17ae 13303
54317cba
JW
13304 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13305 pc->count[PCOUNT_DAMPED]++;
13306 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13307 pc->count[PCOUNT_HISTORY]++;
13308 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13309 pc->count[PCOUNT_REMOVED]++;
13310 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13311 pc->count[PCOUNT_STALE]++;
13312 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13313 pc->count[PCOUNT_VALID]++;
13314 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13315 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13316 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13317 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13318
13319 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13320 pc->count[PCOUNT_COUNTED]++;
13321 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13322 flog_err(
13323 EC_LIB_DEVELOPMENT,
13324 "Attempting to count but flags say it is unusable");
13325 } else {
40381db7 13326 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13327 flog_err(
13328 EC_LIB_DEVELOPMENT,
13329 "Not counted but flags say we should");
d62a17ae 13330 }
13331 }
54317cba
JW
13332}
13333
cc9f21da 13334static void bgp_peer_count_walker(struct thread *t)
54317cba 13335{
9bcb3eef 13336 struct bgp_dest *rn, *rm;
54317cba
JW
13337 const struct bgp_table *table;
13338 struct peer_pcounts *pc = THREAD_ARG(t);
13339
13340 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13341 || pc->safi == SAFI_EVPN) {
13342 /* Special handling for 2-level routing tables. */
13343 for (rn = bgp_table_top(pc->table); rn;
13344 rn = bgp_route_next(rn)) {
9bcb3eef 13345 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13346 if (table != NULL)
13347 for (rm = bgp_table_top(table); rm;
13348 rm = bgp_route_next(rm))
13349 bgp_peer_count_proc(rm, pc);
13350 }
13351 } else
13352 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13353 bgp_peer_count_proc(rn, pc);
718e3744 13354}
13355
d62a17ae 13356static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13357 safi_t safi, bool use_json)
856ca177 13358{
d62a17ae 13359 struct peer_pcounts pcounts = {.peer = peer};
13360 unsigned int i;
13361 json_object *json = NULL;
13362 json_object *json_loop = NULL;
856ca177 13363
d62a17ae 13364 if (use_json) {
13365 json = json_object_new_object();
13366 json_loop = json_object_new_object();
13367 }
718e3744 13368
d62a17ae 13369 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13370 || !peer->bgp->rib[afi][safi]) {
13371 if (use_json) {
13372 json_object_string_add(
13373 json, "warning",
13374 "No such neighbor or address family");
13375 vty_out(vty, "%s\n", json_object_to_json_string(json));
13376 json_object_free(json);
d5f20468 13377 json_object_free(json_loop);
d62a17ae 13378 } else
13379 vty_out(vty, "%% No such neighbor or address family\n");
13380
13381 return CMD_WARNING;
13382 }
2a71e9ce 13383
d62a17ae 13384 memset(&pcounts, 0, sizeof(pcounts));
13385 pcounts.peer = peer;
13386 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13387 pcounts.safi = safi;
d62a17ae 13388
13389 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13390 * stats for the thread-walk (i.e. ensure this can't be blamed on
13391 * on just vty_read()).
13392 */
d62a17ae 13393 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13394
13395 if (use_json) {
13396 json_object_string_add(json, "prefixCountsFor", peer->host);
13397 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13398 get_afi_safi_str(afi, safi, true));
d62a17ae 13399 json_object_int_add(json, "pfxCounter",
13400 peer->pcount[afi][safi]);
13401
13402 for (i = 0; i < PCOUNT_MAX; i++)
13403 json_object_int_add(json_loop, pcount_strs[i],
13404 pcounts.count[i]);
13405
13406 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13407
13408 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13409 json_object_string_add(json, "pfxctDriftFor",
13410 peer->host);
13411 json_object_string_add(
13412 json, "recommended",
13413 "Please report this bug, with the above command output");
13414 }
75eeda93 13415 vty_json(vty, json);
d62a17ae 13416 } else {
13417
13418 if (peer->hostname
892fedb6 13419 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13420 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13421 peer->hostname, peer->host,
5cb5f4d0 13422 get_afi_safi_str(afi, safi, false));
d62a17ae 13423 } else {
13424 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13425 get_afi_safi_str(afi, safi, false));
d62a17ae 13426 }
13427
6cde4b45 13428 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13429 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13430
13431 for (i = 0; i < PCOUNT_MAX; i++)
13432 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13433 pcounts.count[i]);
13434
13435 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13436 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13437 vty_out(vty,
13438 "Please report this bug, with the above command output\n");
13439 }
13440 }
13441
13442 return CMD_SUCCESS;
718e3744 13443}
13444
a636c635
DW
13445DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13446 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13447 "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 13448 SHOW_STR
13449 IP_STR
13450 BGP_STR
8386ac43 13451 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13452 BGP_AFI_HELP_STR
13453 BGP_SAFI_HELP_STR
0b16f239
DS
13454 "Detailed information on TCP and BGP neighbor connections\n"
13455 "Neighbor to display information about\n"
13456 "Neighbor to display information about\n"
91d37724 13457 "Neighbor on BGP configured interface\n"
a636c635 13458 "Display detailed prefix count information\n"
9973d184 13459 JSON_STR)
0b16f239 13460{
d62a17ae 13461 afi_t afi = AFI_IP6;
13462 safi_t safi = SAFI_UNICAST;
13463 struct peer *peer;
13464 int idx = 0;
13465 struct bgp *bgp = NULL;
9f049418
DS
13466 bool uj = use_json(argc, argv);
13467
13468 if (uj)
13469 argc--;
856ca177 13470
d62a17ae 13471 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13472 &bgp, uj);
d62a17ae 13473 if (!idx)
13474 return CMD_WARNING;
0b16f239 13475
d62a17ae 13476 argv_find(argv, argc, "neighbors", &idx);
13477 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13478 if (!peer)
13479 return CMD_WARNING;
bb46e94f 13480
29c8d9da 13481 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13482}
0b16f239 13483
d6902373
PG
13484#ifdef KEEP_OLD_VPN_COMMANDS
13485DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13486 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13487 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13488 SHOW_STR
13489 IP_STR
13490 BGP_STR
d6902373 13491 BGP_VPNVX_HELP_STR
91d37724 13492 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13493 "Detailed information on TCP and BGP neighbor connections\n"
13494 "Neighbor to display information about\n"
13495 "Neighbor to display information about\n"
91d37724 13496 "Neighbor on BGP configured interface\n"
a636c635 13497 "Display detailed prefix count information\n"
9973d184 13498 JSON_STR)
a636c635 13499{
d62a17ae 13500 int idx_peer = 6;
13501 struct peer *peer;
9f049418 13502 bool uj = use_json(argc, argv);
a636c635 13503
d62a17ae 13504 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13505 if (!peer)
13506 return CMD_WARNING;
13507
13508 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13509}
13510
d6902373
PG
13511DEFUN (show_ip_bgp_vpn_all_route_prefix,
13512 show_ip_bgp_vpn_all_route_prefix_cmd,
13513 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13514 SHOW_STR
13515 IP_STR
13516 BGP_STR
d6902373 13517 BGP_VPNVX_HELP_STR
91d37724
QY
13518 "Display information about all VPNv4 NLRIs\n"
13519 "Network in the BGP routing table to display\n"
3a2d747c 13520 "Network in the BGP routing table to display\n"
9973d184 13521 JSON_STR)
91d37724 13522{
d62a17ae 13523 int idx = 0;
13524 char *network = NULL;
13525 struct bgp *bgp = bgp_get_default();
13526 if (!bgp) {
13527 vty_out(vty, "Can't find default instance\n");
13528 return CMD_WARNING;
13529 }
87e34b58 13530
d62a17ae 13531 if (argv_find(argv, argc, "A.B.C.D", &idx))
13532 network = argv[idx]->arg;
13533 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13534 network = argv[idx]->arg;
13535 else {
13536 vty_out(vty, "Unable to figure out Network\n");
13537 return CMD_WARNING;
13538 }
87e34b58 13539
d62a17ae 13540 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13541 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13542 use_json(argc, argv));
91d37724 13543}
d6902373 13544#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13545
44c69747
LK
13546DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13547 show_bgp_l2vpn_evpn_route_prefix_cmd,
13548 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13549 SHOW_STR
4c63a661
PG
13550 BGP_STR
13551 L2VPN_HELP_STR
13552 EVPN_HELP_STR
44c69747
LK
13553 "Network in the BGP routing table to display\n"
13554 "Network in the BGP routing table to display\n"
4c63a661
PG
13555 "Network in the BGP routing table to display\n"
13556 "Network in the BGP routing table to display\n"
13557 JSON_STR)
13558{
d62a17ae 13559 int idx = 0;
13560 char *network = NULL;
44c69747 13561 int prefix_check = 0;
a636c635 13562
44c69747
LK
13563 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13564 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13565 network = argv[idx]->arg;
44c69747 13566 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13567 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13568 network = argv[idx]->arg;
44c69747
LK
13569 prefix_check = 1;
13570 } else {
d62a17ae 13571 vty_out(vty, "Unable to figure out Network\n");
13572 return CMD_WARNING;
13573 }
44c69747
LK
13574 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13575 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13576 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13577}
13578
114fc229 13579static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13580 struct bgp_table *table, int *header1,
13581 int *header2, json_object *json,
13582 json_object *json_scode,
13583 json_object *json_ocode, bool wide)
13584{
13585 uint64_t version = table ? table->version : 0;
13586
13587 if (*header1) {
13588 if (json) {
13589 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13590 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13591 "%pI4", &peer->bgp->router_id);
2f9bc755 13592 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13593 peer->bgp->default_local_pref);
13594 json_object_int_add(json, "localAS",
13595 peer->change_local_as
13596 ? peer->change_local_as
13597 : peer->local_as);
2f9bc755
DS
13598 json_object_object_add(json, "bgpStatusCodes",
13599 json_scode);
13600 json_object_object_add(json, "bgpOriginCodes",
13601 json_ocode);
13602 } else {
13603 vty_out(vty,
23d0a753
DA
13604 "BGP table version is %" PRIu64
13605 ", local router ID is %pI4, vrf id ",
114fc229
DA
13606 version, &peer->bgp->router_id);
13607 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13608 vty_out(vty, "%s", VRFID_NONE_STR);
13609 else
114fc229 13610 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13611 vty_out(vty, "\n");
13612 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13613 peer->bgp->default_local_pref);
13614 vty_out(vty, "local AS %u\n",
13615 peer->change_local_as ? peer->change_local_as
13616 : peer->local_as);
2f9bc755
DS
13617 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13618 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13619 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13620 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13621 }
13622 *header1 = 0;
13623 }
13624 if (*header2) {
13625 if (!json)
13626 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13627 : BGP_SHOW_HEADER));
13628 *header2 = 0;
13629 }
13630}
13631
d9478df0
TA
13632static void
13633show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13634 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13635 const char *rmap_name, json_object *json, json_object *json_ar,
13636 json_object *json_scode, json_object *json_ocode,
96c81f66 13637 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13638 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13639{
d62a17ae 13640 struct bgp_adj_in *ain;
13641 struct bgp_adj_out *adj;
9bcb3eef 13642 struct bgp_dest *dest;
d62a17ae 13643 struct bgp *bgp;
d62a17ae 13644 struct attr attr;
13645 int ret;
13646 struct update_subgroup *subgrp;
d62a17ae 13647 struct peer_af *paf;
f99def61 13648 bool route_filtered;
96f3485c
MK
13649 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13650 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13651 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13652 || (safi == SAFI_EVPN))
13653 ? true
13654 : false;
a636c635 13655
d62a17ae 13656 bgp = peer->bgp;
a636c635 13657
d62a17ae 13658 subgrp = peer_subgroup(peer, afi, safi);
13659
6392aaa6 13660 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13661 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13662 if (use_json) {
13663 json_object_int_add(json, "bgpTableVersion",
13664 table->version);
c949c771
DA
13665 json_object_string_addf(json, "bgpLocalRouterId",
13666 "%pI4", &bgp->router_id);
01eced22
AD
13667 json_object_int_add(json, "defaultLocPrf",
13668 bgp->default_local_pref);
114fc229
DA
13669 json_object_int_add(json, "localAS",
13670 peer->change_local_as
13671 ? peer->change_local_as
13672 : peer->local_as);
d62a17ae 13673 json_object_object_add(json, "bgpStatusCodes",
13674 json_scode);
13675 json_object_object_add(json, "bgpOriginCodes",
13676 json_ocode);
07d0c4ed
DA
13677 json_object_string_add(
13678 json, "bgpOriginatingDefaultNetwork",
13679 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13680 } else {
23d0a753
DA
13681 vty_out(vty,
13682 "BGP table version is %" PRIu64
13683 ", local router ID is %pI4, vrf id ",
13684 table->version, &bgp->router_id);
9df8b37c
PZ
13685 if (bgp->vrf_id == VRF_UNKNOWN)
13686 vty_out(vty, "%s", VRFID_NONE_STR);
13687 else
13688 vty_out(vty, "%u", bgp->vrf_id);
13689 vty_out(vty, "\n");
01eced22
AD
13690 vty_out(vty, "Default local pref %u, ",
13691 bgp->default_local_pref);
114fc229
DA
13692 vty_out(vty, "local AS %u\n",
13693 peer->change_local_as ? peer->change_local_as
13694 : peer->local_as);
d62a17ae 13695 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13696 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13697 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13698 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13699
07d0c4ed
DA
13700 vty_out(vty, "Originating default network %s\n\n",
13701 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13702 }
d9478df0 13703 *header1 = 0;
d62a17ae 13704 }
a636c635 13705
9bcb3eef 13706 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13707 if (type == bgp_show_adj_route_received
13708 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13709 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13710 if (ain->peer != peer)
ea47320b 13711 continue;
6392aaa6 13712
114fc229 13713 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13714 header2, json, json_scode,
13715 json_ocode, wide);
13716
13717 if ((safi == SAFI_MPLS_VPN)
13718 || (safi == SAFI_ENCAP)
13719 || (safi == SAFI_EVPN)) {
13720 if (use_json)
13721 json_object_string_add(
13722 json_ar, "rd", rd_str);
13723 else if (show_rd && rd_str) {
13724 vty_out(vty,
13725 "Route Distinguisher: %s\n",
13726 rd_str);
13727 show_rd = false;
13728 }
13729 }
6392aaa6 13730
6f4f49b2 13731 attr = *ain->attr;
f99def61
AD
13732 route_filtered = false;
13733
13734 /* Filter prefix using distribute list,
13735 * filter list or prefix list
13736 */
b54892e0 13737 const struct prefix *rn_p =
9bcb3eef 13738 bgp_dest_get_prefix(dest);
b54892e0
DS
13739 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13740 safi))
13741 == FILTER_DENY)
f99def61
AD
13742 route_filtered = true;
13743
13744 /* Filter prefix using route-map */
b54892e0
DS
13745 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13746 safi, rmap_name, NULL,
13747 0, NULL);
6392aaa6 13748
13c8e163
AD
13749 if (type == bgp_show_adj_route_filtered &&
13750 !route_filtered && ret != RMAP_DENY) {
d498917e 13751 bgp_attr_flush(&attr);
6392aaa6 13752 continue;
d62a17ae 13753 }
6392aaa6 13754
d9478df0
TA
13755 if (type == bgp_show_adj_route_received
13756 && (route_filtered || ret == RMAP_DENY))
13757 (*filtered_count)++;
6392aaa6 13758
7d3cae70 13759 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13760 use_json, json_ar, wide);
d498917e 13761 bgp_attr_flush(&attr);
d9478df0 13762 (*output_count)++;
d62a17ae 13763 }
6392aaa6 13764 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13765 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13766 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13767 if (paf->peer != peer || !adj->attr)
924c3f6a 13768 continue;
d62a17ae 13769
114fc229 13770 show_adj_route_header(vty, peer, table,
d9478df0
TA
13771 header1, header2,
13772 json, json_scode,
13773 json_ocode, wide);
d62a17ae 13774
b54892e0 13775 const struct prefix *rn_p =
9bcb3eef 13776 bgp_dest_get_prefix(dest);
b54892e0 13777
6f4f49b2 13778 attr = *adj->attr;
b755861b 13779 ret = bgp_output_modifier(
b54892e0 13780 peer, rn_p, &attr, afi, safi,
b755861b 13781 rmap_name);
f46d8e1e 13782
b755861b 13783 if (ret != RMAP_DENY) {
d9478df0
TA
13784 if ((safi == SAFI_MPLS_VPN)
13785 || (safi == SAFI_ENCAP)
13786 || (safi == SAFI_EVPN)) {
13787 if (use_json)
13788 json_object_string_add(
13789 json_ar,
13790 "rd",
13791 rd_str);
13792 else if (show_rd
13793 && rd_str) {
13794 vty_out(vty,
13795 "Route Distinguisher: %s\n",
13796 rd_str);
13797 show_rd = false;
13798 }
13799 }
b54892e0 13800 route_vty_out_tmp(
7d3cae70
DA
13801 vty, dest, rn_p, &attr,
13802 safi, use_json, json_ar,
ae248832 13803 wide);
d9478df0 13804 (*output_count)++;
b755861b 13805 } else {
d9478df0 13806 (*filtered_count)++;
a2addae8 13807 }
b755861b 13808
d498917e 13809 bgp_attr_flush(&attr);
924c3f6a 13810 }
f20ce998
DS
13811 } else if (type == bgp_show_adj_route_bestpath) {
13812 struct bgp_path_info *pi;
13813
114fc229
DA
13814 show_adj_route_header(vty, peer, table, header1,
13815 header2, json, json_scode,
13816 json_ocode, wide);
f20ce998
DS
13817
13818 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13819 pi = pi->next) {
13820 if (pi->peer != peer)
13821 continue;
13822
13823 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13824 continue;
13825
7d3cae70 13826 route_vty_out_tmp(vty, dest,
f20ce998
DS
13827 bgp_dest_get_prefix(dest),
13828 pi->attr, safi, use_json,
13829 json_ar, wide);
d9478df0 13830 (*output_count)++;
f20ce998 13831 }
d62a17ae 13832 }
13833 }
a636c635 13834}
2a71e9ce 13835
d62a17ae 13836static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13837 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13838 const char *rmap_name, uint16_t show_flags)
0b16f239 13839{
d9478df0
TA
13840 struct bgp *bgp;
13841 struct bgp_table *table;
d62a17ae 13842 json_object *json = NULL;
d9478df0
TA
13843 json_object *json_scode = NULL;
13844 json_object *json_ocode = NULL;
13845 json_object *json_ar = NULL;
96f3485c 13846 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13847
d9478df0
TA
13848 /* Init BGP headers here so they're only displayed once
13849 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13850 */
13851 int header1 = 1;
13852 int header2 = 1;
13853
13854 /*
13855 * Initialize variables for each RD
13856 * All prefixes under an RD is aggregated within "json_routes"
13857 */
13858 char rd_str[BUFSIZ] = {0};
13859 json_object *json_routes = NULL;
13860
13861
13862 /* For 2-tier tables, prefix counts need to be
13863 * maintained across multiple runs of show_adj_route()
13864 */
13865 unsigned long output_count_per_rd;
13866 unsigned long filtered_count_per_rd;
13867 unsigned long output_count = 0;
13868 unsigned long filtered_count = 0;
13869
13870 if (use_json) {
d62a17ae 13871 json = json_object_new_object();
d9478df0
TA
13872 json_ar = json_object_new_object();
13873 json_scode = json_object_new_object();
13874 json_ocode = json_object_new_object();
13875
13876 json_object_string_add(json_scode, "suppressed", "s");
13877 json_object_string_add(json_scode, "damped", "d");
13878 json_object_string_add(json_scode, "history", "h");
13879 json_object_string_add(json_scode, "valid", "*");
13880 json_object_string_add(json_scode, "best", ">");
13881 json_object_string_add(json_scode, "multipath", "=");
13882 json_object_string_add(json_scode, "internal", "i");
13883 json_object_string_add(json_scode, "ribFailure", "r");
13884 json_object_string_add(json_scode, "stale", "S");
13885 json_object_string_add(json_scode, "removed", "R");
13886
13887 json_object_string_add(json_ocode, "igp", "i");
13888 json_object_string_add(json_ocode, "egp", "e");
13889 json_object_string_add(json_ocode, "incomplete", "?");
13890 }
0b16f239 13891
d62a17ae 13892 if (!peer || !peer->afc[afi][safi]) {
13893 if (use_json) {
13894 json_object_string_add(
13895 json, "warning",
13896 "No such neighbor or address family");
13897 vty_out(vty, "%s\n", json_object_to_json_string(json));
13898 json_object_free(json);
690c3134
MW
13899 json_object_free(json_ar);
13900 json_object_free(json_scode);
13901 json_object_free(json_ocode);
d62a17ae 13902 } else
13903 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13904
d62a17ae 13905 return CMD_WARNING;
13906 }
13907
6392aaa6
PM
13908 if ((type == bgp_show_adj_route_received
13909 || type == bgp_show_adj_route_filtered)
d62a17ae 13910 && !CHECK_FLAG(peer->af_flags[afi][safi],
13911 PEER_FLAG_SOFT_RECONFIG)) {
13912 if (use_json) {
13913 json_object_string_add(
13914 json, "warning",
13915 "Inbound soft reconfiguration not enabled");
13916 vty_out(vty, "%s\n", json_object_to_json_string(json));
13917 json_object_free(json);
690c3134
MW
13918 json_object_free(json_ar);
13919 json_object_free(json_scode);
13920 json_object_free(json_ocode);
d62a17ae 13921 } else
13922 vty_out(vty,
13923 "%% Inbound soft reconfiguration not enabled\n");
13924
13925 return CMD_WARNING;
13926 }
0b16f239 13927
d9478df0
TA
13928 bgp = peer->bgp;
13929
13930 /* labeled-unicast routes live in the unicast table */
13931 if (safi == SAFI_LABELED_UNICAST)
13932 table = bgp->rib[afi][SAFI_UNICAST];
13933 else
13934 table = bgp->rib[afi][safi];
13935
13936 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13937 || (safi == SAFI_EVPN)) {
13938
13939 struct bgp_dest *dest;
13940
13941 for (dest = bgp_table_top(table); dest;
13942 dest = bgp_route_next(dest)) {
13943 table = bgp_dest_get_bgp_table_info(dest);
13944 if (!table)
13945 continue;
13946
13947 output_count_per_rd = 0;
13948 filtered_count_per_rd = 0;
13949
13950 if (use_json)
13951 json_routes = json_object_new_object();
13952
13953 const struct prefix_rd *prd;
13954 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13955 dest);
13956
13957 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13958
13959 show_adj_route(vty, peer, table, afi, safi, type,
13960 rmap_name, json, json_routes, json_scode,
13961 json_ocode, show_flags, &header1,
13962 &header2, rd_str, &output_count_per_rd,
13963 &filtered_count_per_rd);
13964
13965 /* Don't include an empty RD in the output! */
13966 if (json_routes && (output_count_per_rd > 0))
13967 json_object_object_add(json_ar, rd_str,
13968 json_routes);
13969
13970 output_count += output_count_per_rd;
13971 filtered_count += filtered_count_per_rd;
13972 }
13973 } else
13974 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13975 json, json_ar, json_scode, json_ocode,
13976 show_flags, &header1, &header2, rd_str,
13977 &output_count, &filtered_count);
13978
13979 if (use_json) {
c1984955
TA
13980 if (type == bgp_show_adj_route_advertised)
13981 json_object_object_add(json, "advertisedRoutes",
13982 json_ar);
13983 else
13984 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
13985 json_object_int_add(json, "totalPrefixCounter", output_count);
13986 json_object_int_add(json, "filteredPrefixCounter",
13987 filtered_count);
13988
690c3134
MW
13989 /*
13990 * These fields only give up ownership to `json` when `header1`
13991 * is used (set to zero). See code in `show_adj_route` and
13992 * `show_adj_route_header`.
13993 */
13994 if (header1 == 1) {
d9478df0
TA
13995 json_object_free(json_scode);
13996 json_object_free(json_ocode);
13997 }
13998
75eeda93 13999 vty_json(vty, json);
d9478df0
TA
14000 } else if (output_count > 0) {
14001 if (filtered_count > 0)
14002 vty_out(vty,
14003 "\nTotal number of prefixes %ld (%ld filtered)\n",
14004 output_count, filtered_count);
14005 else
14006 vty_out(vty, "\nTotal number of prefixes %ld\n",
14007 output_count);
14008 }
0b16f239 14009
d62a17ae 14010 return CMD_SUCCESS;
a636c635 14011}
50ef26d4 14012
f20ce998
DS
14013DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14014 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14015 "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]",
14016 SHOW_STR
14017 IP_STR
14018 BGP_STR
14019 BGP_INSTANCE_HELP_STR
14020 BGP_AFI_HELP_STR
14021 BGP_SAFI_WITH_LABEL_HELP_STR
14022 "Detailed information on TCP and BGP neighbor connections\n"
14023 "Neighbor to display information about\n"
14024 "Neighbor to display information about\n"
14025 "Neighbor on BGP configured interface\n"
14026 "Display the routes selected by best path\n"
14027 JSON_STR
14028 "Increase table width for longer prefixes\n")
14029{
14030 afi_t afi = AFI_IP6;
14031 safi_t safi = SAFI_UNICAST;
14032 char *rmap_name = NULL;
14033 char *peerstr = NULL;
14034 struct bgp *bgp = NULL;
14035 struct peer *peer;
14036 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14037 int idx = 0;
96c81f66 14038 uint16_t show_flags = 0;
96f3485c
MK
14039
14040 if (uj)
14041 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14042
14043 if (wide)
14044 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14045
14046 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14047 &bgp, uj);
14048
14049 if (!idx)
14050 return CMD_WARNING;
14051
14052 argv_find(argv, argc, "neighbors", &idx);
14053 peerstr = argv[++idx]->arg;
14054
14055 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14056 if (!peer)
14057 return CMD_WARNING;
14058
96f3485c
MK
14059 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14060 show_flags);
f20ce998
DS
14061}
14062
ae248832 14063DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14064 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14065 "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 14066 SHOW_STR
14067 IP_STR
14068 BGP_STR
a636c635 14069 BGP_INSTANCE_HELP_STR
7395a2c9 14070 BGP_AFI_HELP_STR
4dd6177e 14071 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14072 "Display the entries for all address families\n"
718e3744 14073 "Detailed information on TCP and BGP neighbor connections\n"
14074 "Neighbor to display information about\n"
14075 "Neighbor to display information about\n"
91d37724 14076 "Neighbor on BGP configured interface\n"
a636c635 14077 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14078 "Display the received routes from neighbor\n"
14079 "Display the filtered routes received from neighbor\n"
a636c635
DW
14080 "Route-map to modify the attributes\n"
14081 "Name of the route map\n"
ae248832
MK
14082 JSON_STR
14083 "Increase table width for longer prefixes\n")
718e3744 14084{
d62a17ae 14085 afi_t afi = AFI_IP6;
14086 safi_t safi = SAFI_UNICAST;
d62a17ae 14087 char *peerstr = NULL;
d62a17ae 14088 struct bgp *bgp = NULL;
14089 struct peer *peer;
6392aaa6 14090 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14091 int idx = 0;
96f3485c 14092 bool first = true;
96c81f66 14093 uint16_t show_flags = 0;
75ce3b14
DA
14094 struct listnode *node;
14095 struct bgp *abgp;
6392aaa6 14096
96f3485c 14097 if (uj) {
d62a17ae 14098 argc--;
96f3485c
MK
14099 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14100 }
14101
14102 if (all) {
14103 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14104 if (argv_find(argv, argc, "ipv4", &idx))
14105 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14106
14107 if (argv_find(argv, argc, "ipv6", &idx))
14108 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14109 }
14110
14111 if (wide)
14112 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14113
9f049418
DS
14114 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14115 &bgp, uj);
14116 if (!idx)
14117 return CMD_WARNING;
14118
d62a17ae 14119 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14120 argv_find(argv, argc, "neighbors", &idx);
14121 peerstr = argv[++idx]->arg;
8c3deaae 14122
d62a17ae 14123 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14124 if (!peer)
14125 return CMD_WARNING;
856ca177 14126
d62a17ae 14127 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14128 type = bgp_show_adj_route_advertised;
14129 else if (argv_find(argv, argc, "received-routes", &idx))
14130 type = bgp_show_adj_route_received;
14131 else if (argv_find(argv, argc, "filtered-routes", &idx))
14132 type = bgp_show_adj_route_filtered;
14133
96f3485c 14134 if (!all)
70dd370f 14135 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14136 show_flags);
14137 if (uj)
14138 vty_out(vty, "{\n");
14139
14140 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14141 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14142 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14143 : AFI_IP6;
75ce3b14
DA
14144 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14145 FOREACH_SAFI (safi) {
14146 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14147 continue;
96f3485c 14148
75ce3b14
DA
14149 if (uj) {
14150 if (first)
14151 first = false;
14152 else
14153 vty_out(vty, ",\n");
14154 vty_out(vty, "\"%s\":",
14155 get_afi_safi_str(afi, safi,
14156 true));
14157 } else
14158 vty_out(vty,
14159 "\nFor address family: %s\n",
14160 get_afi_safi_str(afi, safi,
14161 false));
96f3485c 14162
75ce3b14 14163 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14164 route_map, show_flags);
75ce3b14 14165 }
96f3485c
MK
14166 }
14167 } else {
75ce3b14
DA
14168 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14169 FOREACH_AFI_SAFI (afi, safi) {
14170 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14171 continue;
96f3485c 14172
75ce3b14
DA
14173 if (uj) {
14174 if (first)
14175 first = false;
14176 else
14177 vty_out(vty, ",\n");
14178 vty_out(vty, "\"%s\":",
14179 get_afi_safi_str(afi, safi,
14180 true));
14181 } else
14182 vty_out(vty,
14183 "\nFor address family: %s\n",
14184 get_afi_safi_str(afi, safi,
14185 false));
96f3485c 14186
75ce3b14 14187 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14188 route_map, show_flags);
75ce3b14 14189 }
96f3485c
MK
14190 }
14191 }
14192 if (uj)
14193 vty_out(vty, "}\n");
14194
14195 return CMD_SUCCESS;
95cbbd2a
ML
14196}
14197
718e3744 14198DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14199 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14200 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14201 SHOW_STR
14202 IP_STR
14203 BGP_STR
d3120452 14204 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14205 BGP_AF_STR
14206 BGP_AF_STR
14207 BGP_AF_MODIFIER_STR
718e3744 14208 "Detailed information on TCP and BGP neighbor connections\n"
14209 "Neighbor to display information about\n"
14210 "Neighbor to display information about\n"
91d37724 14211 "Neighbor on BGP configured interface\n"
718e3744 14212 "Display information received from a BGP neighbor\n"
856ca177 14213 "Display the prefixlist filter\n"
9973d184 14214 JSON_STR)
718e3744 14215{
d62a17ae 14216 afi_t afi = AFI_IP6;
14217 safi_t safi = SAFI_UNICAST;
14218 char *peerstr = NULL;
d62a17ae 14219 char name[BUFSIZ];
d62a17ae 14220 struct peer *peer;
d3120452 14221 int count;
d62a17ae 14222 int idx = 0;
d3120452
IR
14223 struct bgp *bgp = NULL;
14224 bool uj = use_json(argc, argv);
14225
14226 if (uj)
14227 argc--;
14228
14229 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14230 &bgp, uj);
14231 if (!idx)
14232 return CMD_WARNING;
d62a17ae 14233
d62a17ae 14234 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14235 argv_find(argv, argc, "neighbors", &idx);
14236 peerstr = argv[++idx]->arg;
14237
d3120452
IR
14238 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14239 if (!peer)
14240 return CMD_WARNING;
718e3744 14241
4ced1a2c 14242 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14243 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14244 if (count) {
14245 if (!uj)
14246 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14247 get_afi_safi_str(afi, safi, false));
d62a17ae 14248 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14249 } else {
14250 if (uj)
14251 vty_out(vty, "{}\n");
14252 else
14253 vty_out(vty, "No functional output\n");
14254 }
718e3744 14255
d62a17ae 14256 return CMD_SUCCESS;
14257}
14258
14259static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14260 afi_t afi, safi_t safi,
9f049418 14261 enum bgp_show_type type, bool use_json)
d62a17ae 14262{
96c81f66 14263 uint16_t show_flags = 0;
96f3485c
MK
14264
14265 if (use_json)
14266 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14267
d62a17ae 14268 if (!peer || !peer->afc[afi][safi]) {
14269 if (use_json) {
14270 json_object *json_no = NULL;
14271 json_no = json_object_new_object();
14272 json_object_string_add(
14273 json_no, "warning",
14274 "No such neighbor or address family");
14275 vty_out(vty, "%s\n",
14276 json_object_to_json_string(json_no));
14277 json_object_free(json_no);
14278 } else
14279 vty_out(vty, "%% No such neighbor or address family\n");
14280 return CMD_WARNING;
14281 }
47fc97cc 14282
7daf25a3
TA
14283 /* labeled-unicast routes live in the unicast table */
14284 if (safi == SAFI_LABELED_UNICAST)
14285 safi = SAFI_UNICAST;
14286
1e2ce4f1
DS
14287 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14288 RPKI_NOT_BEING_USED);
718e3744 14289}
14290
dba3c1d3
PG
14291DEFUN (show_ip_bgp_flowspec_routes_detailed,
14292 show_ip_bgp_flowspec_routes_detailed_cmd,
14293 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14294 SHOW_STR
14295 IP_STR
14296 BGP_STR
14297 BGP_INSTANCE_HELP_STR
14298 BGP_AFI_HELP_STR
14299 "SAFI Flowspec\n"
14300 "Detailed information on flowspec entries\n"
14301 JSON_STR)
14302{
458c1475 14303 afi_t afi = AFI_IP6;
dba3c1d3
PG
14304 safi_t safi = SAFI_UNICAST;
14305 struct bgp *bgp = NULL;
14306 int idx = 0;
9f049418 14307 bool uj = use_json(argc, argv);
5be6fa9b 14308 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14309
96f3485c 14310 if (uj) {
9f049418 14311 argc--;
96f3485c
MK
14312 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14313 }
dba3c1d3
PG
14314
14315 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14316 &bgp, uj);
dba3c1d3
PG
14317 if (!idx)
14318 return CMD_WARNING;
14319
96f3485c 14320 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14321 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14322}
14323
718e3744 14324DEFUN (show_ip_bgp_neighbor_routes,
14325 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14326 "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 14327 SHOW_STR
14328 IP_STR
14329 BGP_STR
8386ac43 14330 BGP_INSTANCE_HELP_STR
4f280b15 14331 BGP_AFI_HELP_STR
4dd6177e 14332 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14333 "Detailed information on TCP and BGP neighbor connections\n"
14334 "Neighbor to display information about\n"
14335 "Neighbor to display information about\n"
91d37724 14336 "Neighbor on BGP configured interface\n"
2525cf39 14337 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14338 "Display the dampened routes received from neighbor\n"
14339 "Display routes learned from neighbor\n"
9973d184 14340 JSON_STR)
718e3744 14341{
d62a17ae 14342 char *peerstr = NULL;
14343 struct bgp *bgp = NULL;
14344 afi_t afi = AFI_IP6;
14345 safi_t safi = SAFI_UNICAST;
14346 struct peer *peer;
14347 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14348 int idx = 0;
9f049418
DS
14349 bool uj = use_json(argc, argv);
14350
14351 if (uj)
14352 argc--;
bb46e94f 14353
d62a17ae 14354 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14355 &bgp, uj);
d62a17ae 14356 if (!idx)
14357 return CMD_WARNING;
c493f2d8 14358
d62a17ae 14359 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14360 argv_find(argv, argc, "neighbors", &idx);
14361 peerstr = argv[++idx]->arg;
8c3deaae 14362
d62a17ae 14363 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14364 if (!peer)
d62a17ae 14365 return CMD_WARNING;
bb46e94f 14366
d62a17ae 14367 if (argv_find(argv, argc, "flap-statistics", &idx))
14368 sh_type = bgp_show_type_flap_neighbor;
14369 else if (argv_find(argv, argc, "dampened-routes", &idx))
14370 sh_type = bgp_show_type_damp_neighbor;
14371 else if (argv_find(argv, argc, "routes", &idx))
14372 sh_type = bgp_show_type_neighbor;
2525cf39 14373
d62a17ae 14374 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14375}
6b0655a2 14376
734b349e 14377struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14378
d62a17ae 14379struct bgp_distance {
14380 /* Distance value for the IP source prefix. */
d7c0a89a 14381 uint8_t distance;
718e3744 14382
d62a17ae 14383 /* Name of the access-list to be matched. */
14384 char *access_list;
718e3744 14385};
14386
4f280b15
LB
14387DEFUN (show_bgp_afi_vpn_rd_route,
14388 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14389 "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
14390 SHOW_STR
14391 BGP_STR
14392 BGP_AFI_HELP_STR
00e6edb9 14393 BGP_AF_MODIFIER_STR
4f280b15
LB
14394 "Display information for a route distinguisher\n"
14395 "Route Distinguisher\n"
a111dd97 14396 "All Route Distinguishers\n"
7395a2c9
DS
14397 "Network in the BGP routing table to display\n"
14398 "Network in the BGP routing table to display\n"
14399 JSON_STR)
4f280b15 14400{
d62a17ae 14401 int ret;
14402 struct prefix_rd prd;
14403 afi_t afi = AFI_MAX;
14404 int idx = 0;
4f280b15 14405
ff6566f3
DS
14406 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14407 vty_out(vty, "%% Malformed Address Family\n");
14408 return CMD_WARNING;
14409 }
14410
a111dd97
TA
14411 if (!strcmp(argv[5]->arg, "all"))
14412 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14413 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14414 RPKI_NOT_BEING_USED,
14415 use_json(argc, argv));
14416
d62a17ae 14417 ret = str2prefix_rd(argv[5]->arg, &prd);
14418 if (!ret) {
14419 vty_out(vty, "%% Malformed Route Distinguisher\n");
14420 return CMD_WARNING;
14421 }
ff6566f3 14422
d62a17ae 14423 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14424 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14425 use_json(argc, argv));
4f280b15
LB
14426}
14427
d62a17ae 14428static struct bgp_distance *bgp_distance_new(void)
718e3744 14429{
d62a17ae 14430 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14431}
14432
d62a17ae 14433static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14434{
d62a17ae 14435 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14436}
14437
585f1adc
IR
14438static int bgp_distance_set(struct vty *vty, const char *distance_str,
14439 const char *ip_str, const char *access_list_str)
718e3744 14440{
d62a17ae 14441 int ret;
585f1adc
IR
14442 afi_t afi;
14443 safi_t safi;
d62a17ae 14444 struct prefix p;
585f1adc 14445 uint8_t distance;
9bcb3eef 14446 struct bgp_dest *dest;
d62a17ae 14447 struct bgp_distance *bdistance;
718e3744 14448
585f1adc
IR
14449 afi = bgp_node_afi(vty);
14450 safi = bgp_node_safi(vty);
14451
d62a17ae 14452 ret = str2prefix(ip_str, &p);
14453 if (ret == 0) {
585f1adc 14454 vty_out(vty, "Malformed prefix\n");
d62a17ae 14455 return CMD_WARNING_CONFIG_FAILED;
14456 }
718e3744 14457
585f1adc
IR
14458 distance = atoi(distance_str);
14459
d62a17ae 14460 /* Get BGP distance node. */
9bcb3eef
DS
14461 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14462 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14463 if (bdistance)
9bcb3eef 14464 bgp_dest_unlock_node(dest);
ca2e160d 14465 else {
d62a17ae 14466 bdistance = bgp_distance_new();
9bcb3eef 14467 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14468 }
718e3744 14469
d62a17ae 14470 /* Set distance value. */
14471 bdistance->distance = distance;
718e3744 14472
d62a17ae 14473 /* Reset access-list configuration. */
e1b36e13 14474 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14475 if (access_list_str)
14476 bdistance->access_list =
14477 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14478
d62a17ae 14479 return CMD_SUCCESS;
718e3744 14480}
14481
585f1adc
IR
14482static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14483 const char *ip_str, const char *access_list_str)
718e3744 14484{
d62a17ae 14485 int ret;
585f1adc
IR
14486 afi_t afi;
14487 safi_t safi;
d62a17ae 14488 struct prefix p;
585f1adc 14489 int distance;
9bcb3eef 14490 struct bgp_dest *dest;
d62a17ae 14491 struct bgp_distance *bdistance;
718e3744 14492
585f1adc
IR
14493 afi = bgp_node_afi(vty);
14494 safi = bgp_node_safi(vty);
14495
d62a17ae 14496 ret = str2prefix(ip_str, &p);
14497 if (ret == 0) {
585f1adc 14498 vty_out(vty, "Malformed prefix\n");
d62a17ae 14499 return CMD_WARNING_CONFIG_FAILED;
14500 }
718e3744 14501
9bcb3eef
DS
14502 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14503 if (!dest) {
585f1adc 14504 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14505 return CMD_WARNING_CONFIG_FAILED;
14506 }
718e3744 14507
9bcb3eef 14508 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14509 distance = atoi(distance_str);
1f9a9fff 14510
d62a17ae 14511 if (bdistance->distance != distance) {
585f1adc 14512 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14513 bgp_dest_unlock_node(dest);
d62a17ae 14514 return CMD_WARNING_CONFIG_FAILED;
14515 }
718e3744 14516
0a22ddfb 14517 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14518 bgp_distance_free(bdistance);
718e3744 14519
9bcb3eef
DS
14520 bgp_dest_set_bgp_path_info(dest, NULL);
14521 bgp_dest_unlock_node(dest);
14522 bgp_dest_unlock_node(dest);
718e3744 14523
d62a17ae 14524 return CMD_SUCCESS;
718e3744 14525}
14526
718e3744 14527/* Apply BGP information to distance method. */
b8685f9b 14528uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14529 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14530{
9bcb3eef 14531 struct bgp_dest *dest;
801bb996 14532 struct prefix q = {0};
d62a17ae 14533 struct peer *peer;
14534 struct bgp_distance *bdistance;
14535 struct access_list *alist;
14536 struct bgp_static *bgp_static;
14537
14538 if (!bgp)
14539 return 0;
14540
40381db7 14541 peer = pinfo->peer;
d62a17ae 14542
7b7d48e5
DS
14543 if (pinfo->attr->distance)
14544 return pinfo->attr->distance;
14545
801bb996
CS
14546 /* Check source address.
14547 * Note: for aggregate route, peer can have unspec af type.
14548 */
14549 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14550 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14551 return 0;
14552
9bcb3eef
DS
14553 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14554 if (dest) {
14555 bdistance = bgp_dest_get_bgp_distance_info(dest);
14556 bgp_dest_unlock_node(dest);
d62a17ae 14557
14558 if (bdistance->access_list) {
14559 alist = access_list_lookup(afi, bdistance->access_list);
14560 if (alist
14561 && access_list_apply(alist, p) == FILTER_PERMIT)
14562 return bdistance->distance;
14563 } else
14564 return bdistance->distance;
718e3744 14565 }
718e3744 14566
d62a17ae 14567 /* Backdoor check. */
9bcb3eef
DS
14568 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14569 if (dest) {
14570 bgp_static = bgp_dest_get_bgp_static_info(dest);
14571 bgp_dest_unlock_node(dest);
718e3744 14572
d62a17ae 14573 if (bgp_static->backdoor) {
14574 if (bgp->distance_local[afi][safi])
14575 return bgp->distance_local[afi][safi];
14576 else
14577 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14578 }
718e3744 14579 }
718e3744 14580
d62a17ae 14581 if (peer->sort == BGP_PEER_EBGP) {
14582 if (bgp->distance_ebgp[afi][safi])
14583 return bgp->distance_ebgp[afi][safi];
14584 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14585 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14586 if (bgp->distance_ibgp[afi][safi])
14587 return bgp->distance_ibgp[afi][safi];
14588 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14589 } else {
14590 if (bgp->distance_local[afi][safi])
14591 return bgp->distance_local[afi][safi];
14592 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14593 }
718e3744 14594}
14595
a612fb77
DA
14596/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14597 * we should tell ZEBRA update the routes for a specific
14598 * AFI/SAFI to reflect changes in RIB.
14599 */
585f1adc
IR
14600static void bgp_announce_routes_distance_update(struct bgp *bgp,
14601 afi_t update_afi,
14602 safi_t update_safi)
a612fb77
DA
14603{
14604 afi_t afi;
14605 safi_t safi;
14606
14607 FOREACH_AFI_SAFI (afi, safi) {
14608 if (!bgp_fibupd_safi(safi))
14609 continue;
14610
8b54bc30
DA
14611 if (afi != update_afi && safi != update_safi)
14612 continue;
14613
14614 if (BGP_DEBUG(zebra, ZEBRA))
14615 zlog_debug(
14616 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14617 __func__, afi, safi);
14618 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14619 }
14620}
14621
585f1adc
IR
14622DEFUN (bgp_distance,
14623 bgp_distance_cmd,
14624 "distance bgp (1-255) (1-255) (1-255)",
14625 "Define an administrative distance\n"
14626 "BGP distance\n"
14627 "Distance for routes external to the AS\n"
14628 "Distance for routes internal to the AS\n"
14629 "Distance for local routes\n")
718e3744 14630{
585f1adc 14631 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14632 int idx_number = 2;
14633 int idx_number_2 = 3;
14634 int idx_number_3 = 4;
585f1adc
IR
14635 int distance_ebgp = atoi(argv[idx_number]->arg);
14636 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14637 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14638 afi_t afi;
14639 safi_t safi;
718e3744 14640
d62a17ae 14641 afi = bgp_node_afi(vty);
14642 safi = bgp_node_safi(vty);
718e3744 14643
585f1adc
IR
14644 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14645 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14646 || bgp->distance_local[afi][safi] != distance_local) {
14647 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14648 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14649 bgp->distance_local[afi][safi] = distance_local;
14650 bgp_announce_routes_distance_update(bgp, afi, safi);
14651 }
14652 return CMD_SUCCESS;
14653}
37a87b8f 14654
585f1adc
IR
14655DEFUN (no_bgp_distance,
14656 no_bgp_distance_cmd,
14657 "no distance bgp [(1-255) (1-255) (1-255)]",
14658 NO_STR
14659 "Define an administrative distance\n"
14660 "BGP distance\n"
14661 "Distance for routes external to the AS\n"
14662 "Distance for routes internal to the AS\n"
14663 "Distance for local routes\n")
718e3744 14664{
585f1adc 14665 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14666 afi_t afi;
14667 safi_t safi;
37a87b8f
CS
14668
14669 afi = bgp_node_afi(vty);
14670 safi = bgp_node_safi(vty);
14671
585f1adc
IR
14672 if (bgp->distance_ebgp[afi][safi] != 0
14673 || bgp->distance_ibgp[afi][safi] != 0
14674 || bgp->distance_local[afi][safi] != 0) {
14675 bgp->distance_ebgp[afi][safi] = 0;
14676 bgp->distance_ibgp[afi][safi] = 0;
14677 bgp->distance_local[afi][safi] = 0;
14678 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14679 }
585f1adc
IR
14680 return CMD_SUCCESS;
14681}
37a87b8f 14682
37a87b8f 14683
585f1adc
IR
14684DEFUN (bgp_distance_source,
14685 bgp_distance_source_cmd,
14686 "distance (1-255) A.B.C.D/M",
14687 "Define an administrative distance\n"
14688 "Administrative distance\n"
14689 "IP source prefix\n")
14690{
14691 int idx_number = 1;
14692 int idx_ipv4_prefixlen = 2;
14693 bgp_distance_set(vty, argv[idx_number]->arg,
14694 argv[idx_ipv4_prefixlen]->arg, NULL);
14695 return CMD_SUCCESS;
734b349e
MZ
14696}
14697
585f1adc
IR
14698DEFUN (no_bgp_distance_source,
14699 no_bgp_distance_source_cmd,
14700 "no distance (1-255) A.B.C.D/M",
14701 NO_STR
14702 "Define an administrative distance\n"
14703 "Administrative distance\n"
14704 "IP source prefix\n")
37a87b8f 14705{
585f1adc
IR
14706 int idx_number = 2;
14707 int idx_ipv4_prefixlen = 3;
14708 bgp_distance_unset(vty, argv[idx_number]->arg,
14709 argv[idx_ipv4_prefixlen]->arg, NULL);
14710 return CMD_SUCCESS;
37a87b8f
CS
14711}
14712
585f1adc
IR
14713DEFUN (bgp_distance_source_access_list,
14714 bgp_distance_source_access_list_cmd,
14715 "distance (1-255) A.B.C.D/M WORD",
14716 "Define an administrative distance\n"
14717 "Administrative distance\n"
14718 "IP source prefix\n"
14719 "Access list name\n")
37a87b8f 14720{
585f1adc
IR
14721 int idx_number = 1;
14722 int idx_ipv4_prefixlen = 2;
14723 int idx_word = 3;
14724 bgp_distance_set(vty, argv[idx_number]->arg,
14725 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14726 return CMD_SUCCESS;
14727}
718e3744 14728
585f1adc
IR
14729DEFUN (no_bgp_distance_source_access_list,
14730 no_bgp_distance_source_access_list_cmd,
14731 "no distance (1-255) A.B.C.D/M WORD",
14732 NO_STR
14733 "Define an administrative distance\n"
14734 "Administrative distance\n"
14735 "IP source prefix\n"
14736 "Access list name\n")
14737{
14738 int idx_number = 2;
14739 int idx_ipv4_prefixlen = 3;
14740 int idx_word = 4;
14741 bgp_distance_unset(vty, argv[idx_number]->arg,
14742 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14743 return CMD_SUCCESS;
14744}
37a87b8f 14745
585f1adc
IR
14746DEFUN (ipv6_bgp_distance_source,
14747 ipv6_bgp_distance_source_cmd,
14748 "distance (1-255) X:X::X:X/M",
14749 "Define an administrative distance\n"
14750 "Administrative distance\n"
14751 "IP source prefix\n")
14752{
14753 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14754 return CMD_SUCCESS;
14755}
7ebe9748 14756
585f1adc
IR
14757DEFUN (no_ipv6_bgp_distance_source,
14758 no_ipv6_bgp_distance_source_cmd,
14759 "no distance (1-255) X:X::X:X/M",
14760 NO_STR
14761 "Define an administrative distance\n"
14762 "Administrative distance\n"
14763 "IP source prefix\n")
14764{
14765 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14766 return CMD_SUCCESS;
14767}
37a87b8f 14768
585f1adc
IR
14769DEFUN (ipv6_bgp_distance_source_access_list,
14770 ipv6_bgp_distance_source_access_list_cmd,
14771 "distance (1-255) X:X::X:X/M WORD",
14772 "Define an administrative distance\n"
14773 "Administrative distance\n"
14774 "IP source prefix\n"
14775 "Access list name\n")
14776{
14777 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14778 return CMD_SUCCESS;
718e3744 14779}
14780
585f1adc
IR
14781DEFUN (no_ipv6_bgp_distance_source_access_list,
14782 no_ipv6_bgp_distance_source_access_list_cmd,
14783 "no distance (1-255) X:X::X:X/M WORD",
14784 NO_STR
14785 "Define an administrative distance\n"
14786 "Administrative distance\n"
14787 "IP source prefix\n"
14788 "Access list name\n")
718e3744 14789{
585f1adc
IR
14790 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14791 return CMD_SUCCESS;
14792}
37a87b8f 14793
585f1adc
IR
14794DEFUN (bgp_damp_set,
14795 bgp_damp_set_cmd,
a30fec23 14796 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14797 "BGP Specific commands\n"
14798 "Enable route-flap dampening\n"
14799 "Half-life time for the penalty\n"
14800 "Value to start reusing a route\n"
14801 "Value to start suppressing a route\n"
14802 "Maximum duration to suppress a stable route\n")
14803{
14804 VTY_DECLVAR_CONTEXT(bgp, bgp);
14805 int idx_half_life = 2;
14806 int idx_reuse = 3;
14807 int idx_suppress = 4;
14808 int idx_max_suppress = 5;
37a87b8f
CS
14809 int half = DEFAULT_HALF_LIFE * 60;
14810 int reuse = DEFAULT_REUSE;
14811 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14812 int max = 4 * half;
14813
14814 if (argc == 6) {
14815 half = atoi(argv[idx_half_life]->arg) * 60;
14816 reuse = atoi(argv[idx_reuse]->arg);
14817 suppress = atoi(argv[idx_suppress]->arg);
14818 max = atoi(argv[idx_max_suppress]->arg) * 60;
14819 } else if (argc == 3) {
14820 half = atoi(argv[idx_half_life]->arg) * 60;
14821 max = 4 * half;
14822 }
14823
14824 /*
14825 * These can't be 0 but our SA doesn't understand the
14826 * way our cli is constructed
14827 */
14828 assert(reuse);
14829 assert(half);
14830 if (suppress < reuse) {
14831 vty_out(vty,
14832 "Suppress value cannot be less than reuse value \n");
14833 return 0;
14834 }
14835
14836 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14837 reuse, suppress, max);
14838}
14839
14840DEFUN (bgp_damp_unset,
14841 bgp_damp_unset_cmd,
a30fec23 14842 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14843 NO_STR
14844 "BGP Specific commands\n"
14845 "Enable route-flap dampening\n"
14846 "Half-life time for the penalty\n"
14847 "Value to start reusing a route\n"
14848 "Value to start suppressing a route\n"
14849 "Maximum duration to suppress a stable route\n")
14850{
14851 VTY_DECLVAR_CONTEXT(bgp, bgp);
14852 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14853}
14854
718e3744 14855/* Display specified route of BGP table. */
d62a17ae 14856static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14857 const char *ip_str, afi_t afi, safi_t safi,
14858 struct prefix_rd *prd, int prefix_check)
14859{
14860 int ret;
14861 struct prefix match;
9bcb3eef
DS
14862 struct bgp_dest *dest;
14863 struct bgp_dest *rm;
40381db7
DS
14864 struct bgp_path_info *pi;
14865 struct bgp_path_info *pi_temp;
d62a17ae 14866 struct bgp *bgp;
14867 struct bgp_table *table;
14868
14869 /* BGP structure lookup. */
14870 if (view_name) {
14871 bgp = bgp_lookup_by_name(view_name);
14872 if (bgp == NULL) {
14873 vty_out(vty, "%% Can't find BGP instance %s\n",
14874 view_name);
14875 return CMD_WARNING;
14876 }
14877 } else {
14878 bgp = bgp_get_default();
14879 if (bgp == NULL) {
14880 vty_out(vty, "%% No BGP process is configured\n");
14881 return CMD_WARNING;
14882 }
718e3744 14883 }
718e3744 14884
d62a17ae 14885 /* Check IP address argument. */
14886 ret = str2prefix(ip_str, &match);
14887 if (!ret) {
14888 vty_out(vty, "%% address is malformed\n");
14889 return CMD_WARNING;
14890 }
718e3744 14891
d62a17ae 14892 match.family = afi2family(afi);
14893
14894 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14895 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14896 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14897 dest = bgp_route_next(dest)) {
14898 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14899
9bcb3eef 14900 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14901 continue;
9bcb3eef 14902 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14903 if (!table)
ea47320b 14904 continue;
4953391b
DA
14905 rm = bgp_node_match(table, &match);
14906 if (rm == NULL)
ea47320b 14907 continue;
d62a17ae 14908
9bcb3eef 14909 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14910
ea47320b 14911 if (!prefix_check
b54892e0 14912 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14913 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14914 while (pi) {
14915 if (pi->extra && pi->extra->damp_info) {
14916 pi_temp = pi->next;
ea47320b 14917 bgp_damp_info_free(
19971c9a 14918 pi->extra->damp_info,
5c8846f6 14919 1, afi, safi);
40381db7 14920 pi = pi_temp;
ea47320b 14921 } else
40381db7 14922 pi = pi->next;
d62a17ae 14923 }
ea47320b
DL
14924 }
14925
9bcb3eef 14926 bgp_dest_unlock_node(rm);
d62a17ae 14927 }
14928 } else {
4953391b
DA
14929 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14930 if (dest != NULL) {
9bcb3eef 14931 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14932
d62a17ae 14933 if (!prefix_check
9bcb3eef
DS
14934 || dest_p->prefixlen == match.prefixlen) {
14935 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14936 while (pi) {
14937 if (pi->extra && pi->extra->damp_info) {
14938 pi_temp = pi->next;
d62a17ae 14939 bgp_damp_info_free(
19971c9a 14940 pi->extra->damp_info,
5c8846f6 14941 1, afi, safi);
40381db7 14942 pi = pi_temp;
d62a17ae 14943 } else
40381db7 14944 pi = pi->next;
d62a17ae 14945 }
14946 }
14947
9bcb3eef 14948 bgp_dest_unlock_node(dest);
d62a17ae 14949 }
14950 }
718e3744 14951
d62a17ae 14952 return CMD_SUCCESS;
718e3744 14953}
14954
14955DEFUN (clear_ip_bgp_dampening,
14956 clear_ip_bgp_dampening_cmd,
14957 "clear ip bgp dampening",
14958 CLEAR_STR
14959 IP_STR
14960 BGP_STR
14961 "Clear route flap dampening information\n")
14962{
b4f7f45b 14963 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14964 return CMD_SUCCESS;
718e3744 14965}
14966
14967DEFUN (clear_ip_bgp_dampening_prefix,
14968 clear_ip_bgp_dampening_prefix_cmd,
14969 "clear ip bgp dampening A.B.C.D/M",
14970 CLEAR_STR
14971 IP_STR
14972 BGP_STR
14973 "Clear route flap dampening information\n"
0c7b1b01 14974 "IPv4 prefix\n")
718e3744 14975{
d62a17ae 14976 int idx_ipv4_prefixlen = 4;
14977 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14978 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14979}
14980
14981DEFUN (clear_ip_bgp_dampening_address,
14982 clear_ip_bgp_dampening_address_cmd,
14983 "clear ip bgp dampening A.B.C.D",
14984 CLEAR_STR
14985 IP_STR
14986 BGP_STR
14987 "Clear route flap dampening information\n"
14988 "Network to clear damping information\n")
14989{
d62a17ae 14990 int idx_ipv4 = 4;
14991 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14992 SAFI_UNICAST, NULL, 0);
718e3744 14993}
14994
14995DEFUN (clear_ip_bgp_dampening_address_mask,
14996 clear_ip_bgp_dampening_address_mask_cmd,
14997 "clear ip bgp dampening A.B.C.D A.B.C.D",
14998 CLEAR_STR
14999 IP_STR
15000 BGP_STR
15001 "Clear route flap dampening information\n"
15002 "Network to clear damping information\n"
15003 "Network mask\n")
15004{
d62a17ae 15005 int idx_ipv4 = 4;
15006 int idx_ipv4_2 = 5;
15007 int ret;
15008 char prefix_str[BUFSIZ];
718e3744 15009
d62a17ae 15010 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15011 prefix_str, sizeof(prefix_str));
d62a17ae 15012 if (!ret) {
15013 vty_out(vty, "%% Inconsistent address and mask\n");
15014 return CMD_WARNING;
15015 }
718e3744 15016
d62a17ae 15017 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15018 NULL, 0);
718e3744 15019}
6b0655a2 15020
e3b78da8 15021static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15022{
15023 struct vty *vty = arg;
e3b78da8 15024 struct peer *peer = bucket->data;
825d9834 15025
47e12884 15026 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15027}
15028
2a0e69ae
DS
15029DEFUN (show_bgp_listeners,
15030 show_bgp_listeners_cmd,
15031 "show bgp listeners",
15032 SHOW_STR
15033 BGP_STR
15034 "Display Listen Sockets and who created them\n")
15035{
15036 bgp_dump_listener_info(vty);
15037
15038 return CMD_SUCCESS;
15039}
15040
825d9834
DS
15041DEFUN (show_bgp_peerhash,
15042 show_bgp_peerhash_cmd,
15043 "show bgp peerhash",
15044 SHOW_STR
15045 BGP_STR
15046 "Display information about the BGP peerhash\n")
15047{
15048 struct list *instances = bm->bgp;
15049 struct listnode *node;
15050 struct bgp *bgp;
15051
15052 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15053 vty_out(vty, "BGP: %s\n", bgp->name);
15054 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15055 vty);
15056 }
15057
15058 return CMD_SUCCESS;
15059}
15060
587ff0fd 15061/* also used for encap safi */
2b791107
DL
15062static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15063 afi_t afi, safi_t safi)
d62a17ae 15064{
9bcb3eef
DS
15065 struct bgp_dest *pdest;
15066 struct bgp_dest *dest;
d62a17ae 15067 struct bgp_table *table;
b54892e0
DS
15068 const struct prefix *p;
15069 const struct prefix_rd *prd;
d62a17ae 15070 struct bgp_static *bgp_static;
15071 mpls_label_t label;
d62a17ae 15072 char rdbuf[RD_ADDRSTRLEN];
15073
15074 /* Network configuration. */
9bcb3eef
DS
15075 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15076 pdest = bgp_route_next(pdest)) {
15077 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15078 if (!table)
ea47320b 15079 continue;
d62a17ae 15080
9bcb3eef
DS
15081 for (dest = bgp_table_top(table); dest;
15082 dest = bgp_route_next(dest)) {
15083 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15084 if (bgp_static == NULL)
ea47320b 15085 continue;
d62a17ae 15086
9bcb3eef
DS
15087 p = bgp_dest_get_prefix(dest);
15088 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15089 pdest);
d62a17ae 15090
ea47320b 15091 /* "network" configuration display. */
06b9f471 15092 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
15093 label = decode_label(&bgp_static->label);
15094
8228a9a7 15095 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
15096 if (safi == SAFI_MPLS_VPN)
15097 vty_out(vty, " label %u", label);
15098
15099 if (bgp_static->rmap.name)
15100 vty_out(vty, " route-map %s",
15101 bgp_static->rmap.name);
e2a86ad9
DS
15102
15103 if (bgp_static->backdoor)
15104 vty_out(vty, " backdoor");
15105
ea47320b
DL
15106 vty_out(vty, "\n");
15107 }
15108 }
d62a17ae 15109}
15110
2b791107
DL
15111static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15112 afi_t afi, safi_t safi)
d62a17ae 15113{
9bcb3eef
DS
15114 struct bgp_dest *pdest;
15115 struct bgp_dest *dest;
d62a17ae 15116 struct bgp_table *table;
b54892e0
DS
15117 const struct prefix *p;
15118 const struct prefix_rd *prd;
d62a17ae 15119 struct bgp_static *bgp_static;
ff44f570 15120 char buf[PREFIX_STRLEN * 2];
d62a17ae 15121 char buf2[SU_ADDRSTRLEN];
15122 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15123 char esi_buf[ESI_STR_LEN];
d62a17ae 15124
15125 /* Network configuration. */
9bcb3eef
DS
15126 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15127 pdest = bgp_route_next(pdest)) {
15128 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15129 if (!table)
ea47320b 15130 continue;
d62a17ae 15131
9bcb3eef
DS
15132 for (dest = bgp_table_top(table); dest;
15133 dest = bgp_route_next(dest)) {
15134 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15135 if (bgp_static == NULL)
ea47320b 15136 continue;
d62a17ae 15137
ea47320b 15138 char *macrouter = NULL;
d62a17ae 15139
ea47320b
DL
15140 if (bgp_static->router_mac)
15141 macrouter = prefix_mac2str(
15142 bgp_static->router_mac, NULL, 0);
15143 if (bgp_static->eth_s_id)
0a50c248
AK
15144 esi_to_str(bgp_static->eth_s_id,
15145 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15146 p = bgp_dest_get_prefix(dest);
15147 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15148
ea47320b 15149 /* "network" configuration display. */
06b9f471 15150 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15151 if (p->u.prefix_evpn.route_type == 5) {
15152 char local_buf[PREFIX_STRLEN];
3714a385 15153 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15154 struct prefix_evpn *)p)
15155 ? AF_INET
15156 : AF_INET6;
3714a385 15157 inet_ntop(family,
15158 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15159 local_buf, PREFIX_STRLEN);
772270f3
QY
15160 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15161 p->u.prefix_evpn.prefix_addr
15162 .ip_prefix_length);
197cb530
PG
15163 } else {
15164 prefix2str(p, buf, sizeof(buf));
15165 }
ea47320b 15166
a4d82a8a
PZ
15167 if (bgp_static->gatewayIp.family == AF_INET
15168 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15169 inet_ntop(bgp_static->gatewayIp.family,
15170 &bgp_static->gatewayIp.u.prefix, buf2,
15171 sizeof(buf2));
ea47320b 15172 vty_out(vty,
7bcc8dac 15173 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15174 buf, rdbuf,
15175 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15176 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15177 macrouter);
15178
0a22ddfb 15179 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15180 }
15181 }
3da6fcd5
PG
15182}
15183
718e3744 15184/* Configuration of static route announcement and aggregate
15185 information. */
2b791107
DL
15186void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15187 safi_t safi)
d62a17ae 15188{
9bcb3eef 15189 struct bgp_dest *dest;
b54892e0 15190 const struct prefix *p;
d62a17ae 15191 struct bgp_static *bgp_static;
15192 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15193
2b791107
DL
15194 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15195 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15196 return;
15197 }
d62a17ae 15198
2b791107
DL
15199 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15200 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15201 return;
15202 }
d62a17ae 15203
15204 /* Network configuration. */
9bcb3eef
DS
15205 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15206 dest = bgp_route_next(dest)) {
15207 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15208 if (bgp_static == NULL)
ea47320b 15209 continue;
d62a17ae 15210
9bcb3eef 15211 p = bgp_dest_get_prefix(dest);
d62a17ae 15212
8228a9a7 15213 vty_out(vty, " network %pFX", p);
d62a17ae 15214
ea47320b
DL
15215 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15216 vty_out(vty, " label-index %u",
15217 bgp_static->label_index);
d62a17ae 15218
ea47320b
DL
15219 if (bgp_static->rmap.name)
15220 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15221
15222 if (bgp_static->backdoor)
15223 vty_out(vty, " backdoor");
718e3744 15224
ea47320b
DL
15225 vty_out(vty, "\n");
15226 }
15227
d62a17ae 15228 /* Aggregate-address configuration. */
9bcb3eef
DS
15229 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15230 dest = bgp_route_next(dest)) {
15231 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15232 if (bgp_aggregate == NULL)
ea47320b 15233 continue;
d62a17ae 15234
9bcb3eef 15235 p = bgp_dest_get_prefix(dest);
d62a17ae 15236
8228a9a7 15237 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15238
ea47320b
DL
15239 if (bgp_aggregate->as_set)
15240 vty_out(vty, " as-set");
d62a17ae 15241
ea47320b
DL
15242 if (bgp_aggregate->summary_only)
15243 vty_out(vty, " summary-only");
718e3744 15244
20894f50
DA
15245 if (bgp_aggregate->rmap.name)
15246 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15247
229757f1
DA
15248 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15249 vty_out(vty, " origin %s",
15250 bgp_origin2str(bgp_aggregate->origin));
15251
6aabb15d
RZ
15252 if (bgp_aggregate->match_med)
15253 vty_out(vty, " matching-MED-only");
15254
365ab2e7
RZ
15255 if (bgp_aggregate->suppress_map_name)
15256 vty_out(vty, " suppress-map %s",
15257 bgp_aggregate->suppress_map_name);
15258
ea47320b
DL
15259 vty_out(vty, "\n");
15260 }
d62a17ae 15261}
734b349e 15262
2b791107 15263void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15264 safi_t safi)
d62a17ae 15265{
9bcb3eef 15266 struct bgp_dest *dest;
d62a17ae 15267 struct bgp_distance *bdistance;
15268
15269 /* Distance configuration. */
15270 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15271 && bgp->distance_local[afi][safi]
15272 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15273 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15274 || bgp->distance_local[afi][safi]
15275 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15276 vty_out(vty, " distance bgp %d %d %d\n",
15277 bgp->distance_ebgp[afi][safi],
15278 bgp->distance_ibgp[afi][safi],
15279 bgp->distance_local[afi][safi]);
15280 }
734b349e 15281
9bcb3eef
DS
15282 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15283 dest = bgp_route_next(dest)) {
15284 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15285 if (bdistance != NULL)
56ca3b5b 15286 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15287 bdistance->distance, dest,
d62a17ae 15288 bdistance->access_list ? bdistance->access_list
15289 : "");
ca2e160d 15290 }
718e3744 15291}
15292
15293/* Allocate routing table structure and install commands. */
d62a17ae 15294void bgp_route_init(void)
15295{
15296 afi_t afi;
15297 safi_t safi;
15298
15299 /* Init BGP distance table. */
05c7a1cc 15300 FOREACH_AFI_SAFI (afi, safi)
960035b2 15301 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15302
15303 /* IPv4 BGP commands. */
15304 install_element(BGP_NODE, &bgp_table_map_cmd);
15305 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15306 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15307
554b3b10 15308 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15309
15310 /* IPv4 unicast configuration. */
15311 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15312 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15313 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15314
554b3b10 15315 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15316
15317 /* IPv4 multicast configuration. */
15318 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15319 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15320 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15321 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15322
15323 /* IPv4 labeled-unicast configuration. */
fb985e0c 15324 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15325 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15326
d62a17ae 15327 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15328 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15329 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15330 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15331 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15332 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15333 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15334 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15335
15336 install_element(VIEW_NODE,
15337 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15338 install_element(VIEW_NODE,
15339 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15340 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15341 install_element(VIEW_NODE,
15342 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15343#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15344 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15345#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15346 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15347 install_element(VIEW_NODE,
44c69747 15348 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15349
d62a17ae 15350 /* BGP dampening clear commands */
15351 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15352 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15353
d62a17ae 15354 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15355 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15356
15357 /* prefix count */
15358 install_element(ENABLE_NODE,
15359 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15360#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15361 install_element(ENABLE_NODE,
15362 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15363#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15364
d62a17ae 15365 /* New config IPv6 BGP commands. */
15366 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15367 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15368 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15369
554b3b10 15370 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15371
15372 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15373
fb985e0c
DA
15374 /* IPv6 labeled unicast address family. */
15375 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15376 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15377
d62a17ae 15378 install_element(BGP_NODE, &bgp_distance_cmd);
15379 install_element(BGP_NODE, &no_bgp_distance_cmd);
15380 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15381 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15382 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15383 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15384 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15385 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15386 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15387 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15388 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15389 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15390 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15391 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15392 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15393 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15394 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15395 install_element(BGP_IPV4M_NODE,
15396 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15397 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15398 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15399 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15400 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15401 install_element(BGP_IPV6_NODE,
15402 &ipv6_bgp_distance_source_access_list_cmd);
15403 install_element(BGP_IPV6_NODE,
15404 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15405 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15406 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15407 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15408 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15409 install_element(BGP_IPV6M_NODE,
15410 &ipv6_bgp_distance_source_access_list_cmd);
15411 install_element(BGP_IPV6M_NODE,
15412 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15413
ef5f4b23 15414 /* BGP dampening */
585f1adc
IR
15415 install_element(BGP_NODE, &bgp_damp_set_cmd);
15416 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15417 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15418 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15419 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15420 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15421 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15422 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15423 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15424 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15425 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15426 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15427 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15428 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15429
15430 /* Large Communities */
15431 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15432 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15433
15434 /* show bgp ipv4 flowspec detailed */
15435 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15436
2a0e69ae 15437 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15438 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15439}
15440
15441void bgp_route_finish(void)
15442{
15443 afi_t afi;
15444 safi_t safi;
15445
05c7a1cc
QY
15446 FOREACH_AFI_SAFI (afi, safi) {
15447 bgp_table_unlock(bgp_distance_table[afi][safi]);
15448 bgp_distance_table[afi][safi] = NULL;
15449 }
228da428 15450}