]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #11710 from donaldsharp/split_up_test_multicast_pim_static_rp
[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{
9bbdb457
DA
1776 if (peer->sort == BGP_PEER_EBGP &&
1777 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
1778 attr->aspath = aspath_replace_specific_asn(attr->aspath,
1779 peer->as, bgp->as);
d62a17ae 1780}
1781
1479ed2f
DA
1782void bgp_attr_add_llgr_community(struct attr *attr)
1783{
1784 struct community *old;
1785 struct community *new;
1786 struct community *merge;
1787 struct community *llgr;
1788
9a706b42 1789 old = bgp_attr_get_community(attr);
1479ed2f
DA
1790 llgr = community_str2com("llgr-stale");
1791
1792 assert(llgr);
1793
1794 if (old) {
1795 merge = community_merge(community_dup(old), llgr);
1796
1797 if (old->refcnt == 0)
1798 community_free(&old);
1799
1800 new = community_uniq_sort(merge);
1801 community_free(&merge);
1802 } else {
1803 new = community_dup(llgr);
1804 }
1805
1806 community_free(&llgr);
1807
9a706b42 1808 bgp_attr_set_community(attr, new);
1479ed2f
DA
1809}
1810
7f323236
DW
1811void bgp_attr_add_gshut_community(struct attr *attr)
1812{
1813 struct community *old;
1814 struct community *new;
1815 struct community *merge;
1816 struct community *gshut;
1817
9a706b42 1818 old = bgp_attr_get_community(attr);
7f323236
DW
1819 gshut = community_str2com("graceful-shutdown");
1820
990f4f91 1821 assert(gshut);
1822
7f323236
DW
1823 if (old) {
1824 merge = community_merge(community_dup(old), gshut);
1825
a4d82a8a 1826 if (old->refcnt == 0)
3c1f53de 1827 community_free(&old);
7f323236
DW
1828
1829 new = community_uniq_sort(merge);
3c1f53de 1830 community_free(&merge);
7f323236
DW
1831 } else {
1832 new = community_dup(gshut);
1833 }
1834
3c1f53de 1835 community_free(&gshut);
9a706b42 1836 bgp_attr_set_community(attr, new);
7f323236
DW
1837
1838 /* When we add the graceful-shutdown community we must also
1839 * lower the local-preference */
1840 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1841 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1842}
1843
1844
e73c112e
MK
1845/* Notify BGP Conditional advertisement scanner process. */
1846void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1847{
e73c112e 1848 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1849 afi_t afi = SUBGRP_AFI(subgrp);
1850 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1851 struct bgp_filter *filter = &peer->filter[afi][safi];
1852
1853 if (!ADVERTISE_MAP_NAME(filter))
1854 return;
1855
52979c3b
DS
1856 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1857 return;
e73c112e 1858
52979c3b 1859 peer->advmap_table_change = true;
e73c112e
MK
1860}
1861
1862
f2ee6d5c 1863void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1864{
960035b2 1865 if (family == AF_INET) {
975a328e
DA
1866 attr->nexthop.s_addr = INADDR_ANY;
1867 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1868 }
d62a17ae 1869 if (family == AF_INET6)
1870 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1871 if (family == AF_EVPN)
1872 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1873}
1874
9bcb3eef 1875bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1876 struct update_subgroup *subgrp,
7f7940e6 1877 const struct prefix *p, struct attr *attr,
51c3a7de 1878 struct attr *post_attr)
d62a17ae 1879{
1880 struct bgp_filter *filter;
1881 struct peer *from;
1882 struct peer *peer;
1883 struct peer *onlypeer;
1884 struct bgp *bgp;
40381db7 1885 struct attr *piattr;
b68885f9 1886 route_map_result_t ret;
d62a17ae 1887 int transparent;
1888 int reflect;
1889 afi_t afi;
1890 safi_t safi;
1891 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1892 bool nh_reset = false;
1893 uint64_t cum_bw;
d62a17ae 1894
1895 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1896 return false;
d62a17ae 1897
1898 afi = SUBGRP_AFI(subgrp);
1899 safi = SUBGRP_SAFI(subgrp);
1900 peer = SUBGRP_PEER(subgrp);
1901 onlypeer = NULL;
1902 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1903 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1904
40381db7 1905 from = pi->peer;
d62a17ae 1906 filter = &peer->filter[afi][safi];
1907 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1908 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1909 : pi->attr;
3f9c7369 1910
d0bf49ec
LS
1911 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1912 peer->pmax_out[afi][safi] != 0 &&
1913 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1914 if (BGP_DEBUG(update, UPDATE_OUT) ||
1915 BGP_DEBUG(update, UPDATE_PREFIX)) {
1916 zlog_debug("%s reached maximum prefix to be send (%u)",
1917 peer->host, peer->pmax_out[afi][safi]);
1918 }
1919 return false;
1920 }
1921
49e5a4a0 1922#ifdef ENABLE_BGP_VNC
d62a17ae 1923 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1924 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1925 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1926
1927 /*
1928 * direct and direct_ext type routes originate internally even
1929 * though they can have peer pointers that reference other
1930 * systems
1931 */
8228a9a7
DS
1932 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1933 __func__, p);
d62a17ae 1934 samepeer_safe = 1;
1935 }
65efcfce
LB
1936#endif
1937
ddb5b488
PZ
1938 if (((afi == AFI_IP) || (afi == AFI_IP6))
1939 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1940 && (pi->type == ZEBRA_ROUTE_BGP)
1941 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1942
1943 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1944
1945 samepeer_safe = 1;
1946 }
1947
d62a17ae 1948 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1949 * pi is valid */
1950 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1951 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1952 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1953 return false;
d62a17ae 1954 }
adbac85e 1955
d62a17ae 1956 /* If this is not the bestpath then check to see if there is an enabled
1957 * addpath
1958 * feature that requires us to advertise it */
40381db7 1959 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1960 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1961 return false;
d62a17ae 1962 }
1963 }
06370dac 1964
d62a17ae 1965 /* Aggregate-address suppress check. */
4056a5f6
RZ
1966 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1967 return false;
3f9c7369 1968
13b7e7f0
DS
1969 /*
1970 * If we are doing VRF 2 VRF leaking via the import
1971 * statement, we want to prevent the route going
1972 * off box as that the RT and RD created are localy
1973 * significant and globaly useless.
1974 */
40381db7
DS
1975 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1976 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1977 return false;
13b7e7f0 1978
d62a17ae 1979 /* If it's labeled safi, make sure the route has a valid label. */
1980 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1981 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1982 if (!bgp_is_valid_label(&label)) {
1983 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1984 zlog_debug("u%" PRIu64 ":s%" PRIu64
1985 " %pFX is filtered - no label (%p)",
d62a17ae 1986 subgrp->update_group->id, subgrp->id,
8228a9a7 1987 p, &label);
3dc339cd 1988 return false;
d62a17ae 1989 }
1990 }
cd1964ff 1991
d62a17ae 1992 /* Do not send back route to sender. */
1993 if (onlypeer && from == onlypeer) {
3dc339cd 1994 return false;
d62a17ae 1995 }
3f9c7369 1996
d62a17ae 1997 /* Do not send the default route in the BGP table if the neighbor is
1998 * configured for default-originate */
1999 if (CHECK_FLAG(peer->af_flags[afi][safi],
2000 PEER_FLAG_DEFAULT_ORIGINATE)) {
2001 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2002 return false;
d62a17ae 2003 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2004 return false;
d62a17ae 2005 }
4125bb67 2006
d62a17ae 2007 /* Transparency check. */
2008 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2009 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2010 transparent = 1;
2011 else
2012 transparent = 0;
2013
2014 /* If community is not disabled check the no-export and local. */
40381db7 2015 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2016 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2017 zlog_debug("%s: community filter check fail for %pFX",
2018 __func__, p);
3dc339cd 2019 return false;
d62a17ae 2020 }
3f9c7369 2021
d62a17ae 2022 /* If the attribute has originator-id and it is same as remote
2023 peer's id. */
40381db7
DS
2024 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2025 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2026 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2027 zlog_debug(
8228a9a7
DS
2028 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
2029 onlypeer->host, p);
3dc339cd 2030 return false;
d62a17ae 2031 }
3f9c7369 2032
d62a17ae 2033 /* ORF prefix-list filter check */
2034 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2035 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2036 || CHECK_FLAG(peer->af_cap[afi][safi],
2037 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2038 if (peer->orf_plist[afi][safi]) {
2039 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2040 == PREFIX_DENY) {
2041 if (bgp_debug_update(NULL, p,
2042 subgrp->update_group, 0))
2043 zlog_debug(
8228a9a7
DS
2044 "%s [Update:SEND] %pFX is filtered via ORF",
2045 peer->host, p);
3dc339cd 2046 return false;
d62a17ae 2047 }
2048 }
2049
2050 /* Output filter check. */
40381db7 2051 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2052 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2053 zlog_debug("%s [Update:SEND] %pFX is filtered",
2054 peer->host, p);
3dc339cd 2055 return false;
d62a17ae 2056 }
3f9c7369 2057
d62a17ae 2058 /* AS path loop check. */
2b31007c
RZ
2059 if (onlypeer && onlypeer->as_path_loop_detection
2060 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2061 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2062 zlog_debug(
3efd0893 2063 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2064 onlypeer->host, onlypeer->as);
3dc339cd 2065 return false;
d62a17ae 2066 }
3f9c7369 2067
d62a17ae 2068 /* If we're a CONFED we need to loop check the CONFED ID too */
2069 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2070 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2071 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2072 zlog_debug(
3efd0893 2073 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2074 peer->host, bgp->confed_id);
3dc339cd 2075 return false;
d62a17ae 2076 }
3f9c7369 2077 }
3f9c7369 2078
d62a17ae 2079 /* Route-Reflect check. */
2080 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2081 reflect = 1;
2082 else
2083 reflect = 0;
2084
2085 /* IBGP reflection check. */
2086 if (reflect && !samepeer_safe) {
2087 /* A route from a Client peer. */
2088 if (CHECK_FLAG(from->af_flags[afi][safi],
2089 PEER_FLAG_REFLECTOR_CLIENT)) {
2090 /* Reflect to all the Non-Client peers and also to the
2091 Client peers other than the originator. Originator
2092 check
2093 is already done. So there is noting to do. */
2094 /* no bgp client-to-client reflection check. */
892fedb6
DA
2095 if (CHECK_FLAG(bgp->flags,
2096 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2097 if (CHECK_FLAG(peer->af_flags[afi][safi],
2098 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2099 return false;
d62a17ae 2100 } else {
2101 /* A route from a Non-client peer. Reflect to all other
2102 clients. */
2103 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2104 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2105 return false;
d62a17ae 2106 }
2107 }
3f9c7369 2108
51c3a7de
DA
2109 /* For modify attribute, copy it to temporary structure.
2110 * post_attr comes from BGP conditional advertisements, where
2111 * attributes are already processed by advertise-map route-map,
2112 * and this needs to be saved instead of overwriting from the
2113 * path attributes.
2114 */
2115 if (post_attr)
2116 *attr = *post_attr;
2117 else
2118 *attr = *piattr;
d62a17ae 2119
2120 /* If local-preference is not set. */
2121 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2122 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2123 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2124 attr->local_pref = bgp->default_local_pref;
3f9c7369 2125 }
3f9c7369 2126
d62a17ae 2127 /* If originator-id is not set and the route is to be reflected,
2128 set the originator id */
2129 if (reflect
2130 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2131 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2132 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2133 }
3f9c7369 2134
d62a17ae 2135 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2136 */
2137 if (peer->sort == BGP_PEER_EBGP
2138 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2139 if (from != bgp->peer_self && !transparent
2140 && !CHECK_FLAG(peer->af_flags[afi][safi],
2141 PEER_FLAG_MED_UNCHANGED))
2142 attr->flag &=
2143 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2144 }
3f9c7369 2145
d62a17ae 2146 /* Since the nexthop attribute can vary per peer, it is not explicitly
2147 * set
2148 * in announce check, only certain flags and length (or number of
2149 * nexthops
2150 * -- for IPv6/MP_REACH) are set here in order to guide the update
2151 * formation
2152 * code in setting the nexthop(s) on a per peer basis in
2153 * reformat_peer().
2154 * Typically, the source nexthop in the attribute is preserved but in
2155 * the
2156 * scenarios where we know it will always be overwritten, we reset the
2157 * nexthop to "0" in an attempt to achieve better Update packing. An
2158 * example of this is when a prefix from each of 2 IBGP peers needs to
2159 * be
2160 * announced to an EBGP peer (and they have the same attributes barring
2161 * their nexthop).
2162 */
2163 if (reflect)
2164 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2165
2166#define NEXTHOP_IS_V6 \
2167 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2168 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2169 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2170 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2171
2172 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2173 * if
2174 * the peer (group) is configured to receive link-local nexthop
2175 * unchanged
c728d027
DA
2176 * and it is available in the prefix OR we're not reflecting the route,
2177 * link-local nexthop address is valid and
d62a17ae 2178 * the peer (group) to whom we're going to announce is on a shared
2179 * network
2180 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2181 * By checking if nexthop LL address is valid we are sure that
2182 * we do not announce LL address as `::`.
d62a17ae 2183 */
2184 if (NEXTHOP_IS_V6) {
2185 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2186 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2187 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2188 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2189 || (!reflect && !transparent
c728d027
DA
2190 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2191 && peer->shared_network
d62a17ae 2192 && (from == bgp->peer_self
2193 || peer->sort == BGP_PEER_EBGP))) {
2194 attr->mp_nexthop_len =
2195 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2196 }
3f9c7369 2197
d62a17ae 2198 /* Clear off link-local nexthop in source, whenever it is not
2199 * needed to
2200 * ensure more prefixes share the same attribute for
2201 * announcement.
2202 */
2203 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2204 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2205 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2206 }
3f9c7369 2207
5a78f2bc
EB
2208 if (bgp_check_role_applicability(afi, safi) &&
2209 bgp_otc_egress(peer, attr))
d864dd9e
EB
2210 return false;
2211
d62a17ae 2212 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2213 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2214
2215 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2216 if (!post_attr &&
2217 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2218 struct bgp_path_info rmap_path = {0};
2219 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2220 struct attr dummy_attr = {0};
d62a17ae 2221
e34291b8 2222 /* Fill temp path_info */
9bcb3eef
DS
2223 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2224 pi, peer, attr);
16f7ce2b 2225
d62a17ae 2226 /* don't confuse inbound and outbound setting */
2227 RESET_FLAG(attr->rmap_change_flags);
2228
2229 /*
2230 * The route reflector is not allowed to modify the attributes
2231 * of the reflected IBGP routes unless explicitly allowed.
2232 */
2233 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2234 && !CHECK_FLAG(bgp->flags,
2235 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2236 dummy_attr = *attr;
40381db7 2237 rmap_path.attr = &dummy_attr;
d62a17ae 2238 }
3f9c7369 2239
d62a17ae 2240 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2241
4056a5f6 2242 if (bgp_path_suppressed(pi))
d62a17ae 2243 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2244 &rmap_path);
d62a17ae 2245 else
2246 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2247 &rmap_path);
d62a17ae 2248
7e7639f5 2249 bgp_attr_flush(&dummy_attr);
d62a17ae 2250 peer->rmap_type = 0;
2251
2252 if (ret == RMAP_DENYMATCH) {
778048bf 2253 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2254 zlog_debug(
02494580
DA
2255 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2256 peer->host, p,
2257 ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2258 bgp_attr_flush(rmap_path.attr);
3dc339cd 2259 return false;
d62a17ae 2260 }
3f9c7369 2261 }
3f9c7369 2262
9dac9fc8
DA
2263 /* RFC 8212 to prevent route leaks.
2264 * This specification intends to improve this situation by requiring the
2265 * explicit configuration of both BGP Import and Export Policies for any
2266 * External BGP (EBGP) session such as customers, peers, or
2267 * confederation boundaries for all enabled address families. Through
2268 * codification of the aforementioned requirement, operators will
2269 * benefit from consistent behavior across different BGP
2270 * implementations.
2271 */
1d3fdccf 2272 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2273 if (!bgp_outbound_policy_exists(peer, filter)) {
2274 if (monotime_since(&bgp->ebgprequirespolicywarning,
2275 NULL) > FIFTEENMINUTE2USEC ||
2276 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2277 zlog_warn(
2278 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2279 monotime(&bgp->ebgprequirespolicywarning);
2280 }
3dc339cd 2281 return false;
b17826b7 2282 }
9dac9fc8 2283
fb29348a
DA
2284 /* draft-ietf-idr-deprecate-as-set-confed-set
2285 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2286 * Eventually, This document (if approved) updates RFC 4271
2287 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2288 * and obsoletes RFC 6472.
2289 */
7f972cd8 2290 if (peer->bgp->reject_as_sets)
fb29348a 2291 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2292 return false;
fb29348a 2293
33d022bc
DA
2294 /* Codification of AS 0 Processing */
2295 if (aspath_check_as_zero(attr->aspath))
e2369003 2296 return false;
33d022bc 2297
637e5ba4 2298 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2299 if (peer->sort == BGP_PEER_IBGP
2300 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2301 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2302 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2303 } else {
2304 bgp_attr_add_gshut_community(attr);
2305 }
2306 }
2307
1479ed2f
DA
2308 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2309 * Capability" to a neighbor MUST perform the following upon receiving
2310 * a route from that neighbor with the "LLGR_STALE" community, or upon
2311 * attaching the "LLGR_STALE" community itself per Section 4.2:
2312 *
2313 * The route SHOULD NOT be advertised to any neighbor from which the
2314 * Long-lived Graceful Restart Capability has not been received.
2315 */
9a706b42
DA
2316 if (bgp_attr_get_community(attr) &&
2317 community_include(bgp_attr_get_community(attr),
2318 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2319 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2320 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2321 return false;
2322
d62a17ae 2323 /* After route-map has been applied, we check to see if the nexthop to
2324 * be carried in the attribute (that is used for the announcement) can
2325 * be cleared off or not. We do this in all cases where we would be
2326 * setting the nexthop to "ourselves". For IPv6, we only need to
2327 * consider
2328 * the global nexthop here; the link-local nexthop would have been
2329 * cleared
2330 * already, and if not, it is required by the update formation code.
2331 * Also see earlier comments in this function.
2332 */
2333 /*
2334 * If route-map has performed some operation on the nexthop or the peer
2335 * configuration says to pass it unchanged, we cannot reset the nexthop
2336 * here, so only attempt to do it if these aren't true. Note that the
2337 * route-map handler itself might have cleared the nexthop, if for
2338 * example,
2339 * it is configured as 'peer-address'.
2340 */
2341 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2342 piattr->rmap_change_flags)
d62a17ae 2343 && !transparent
2344 && !CHECK_FLAG(peer->af_flags[afi][safi],
2345 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2346 /* We can reset the nexthop, if setting (or forcing) it to
2347 * 'self' */
2348 if (CHECK_FLAG(peer->af_flags[afi][safi],
2349 PEER_FLAG_NEXTHOP_SELF)
2350 || CHECK_FLAG(peer->af_flags[afi][safi],
2351 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2352 if (!reflect
2353 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2354 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2355 subgroup_announce_reset_nhop(
2356 (peer_cap_enhe(peer, afi, safi)
2357 ? AF_INET6
2358 : p->family),
2359 attr);
7b651a32 2360 nh_reset = true;
2361 }
d62a17ae 2362 } else if (peer->sort == BGP_PEER_EBGP) {
2363 /* Can also reset the nexthop if announcing to EBGP, but
2364 * only if
2365 * no peer in the subgroup is on a shared subnet.
2366 * Note: 3rd party nexthop currently implemented for
2367 * IPv4 only.
2368 */
737af885
BS
2369 if ((p->family == AF_INET) &&
2370 (!bgp_subgrp_multiaccess_check_v4(
2371 piattr->nexthop,
7b651a32 2372 subgrp, from))) {
d62a17ae 2373 subgroup_announce_reset_nhop(
2374 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2375 ? AF_INET6
2376 : p->family),
737af885 2377 attr);
7b651a32 2378 nh_reset = true;
2379 }
737af885
BS
2380
2381 if ((p->family == AF_INET6) &&
2382 (!bgp_subgrp_multiaccess_check_v6(
2383 piattr->mp_nexthop_global,
7b651a32 2384 subgrp, from))) {
737af885
BS
2385 subgroup_announce_reset_nhop(
2386 (peer_cap_enhe(peer, afi, safi)
2387 ? AF_INET6
2388 : p->family),
2389 attr);
7b651a32 2390 nh_reset = true;
2391 }
737af885
BS
2392
2393
2394
40381db7 2395 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2396 /*
2397 * This flag is used for leaked vpn-vrf routes
2398 */
2399 int family = p->family;
2400
2401 if (peer_cap_enhe(peer, afi, safi))
2402 family = AF_INET6;
2403
2404 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2405 zlog_debug(
1defdda8 2406 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2407 __func__, family2str(family));
2408 subgroup_announce_reset_nhop(family, attr);
7b651a32 2409 nh_reset = true;
d62a17ae 2410 }
63696f1d 2411 }
960035b2 2412
63696f1d 2413 /* If IPv6/MP and nexthop does not have any override and happens
2414 * to
2415 * be a link-local address, reset it so that we don't pass along
2416 * the
2417 * source's link-local IPv6 address to recipients who may not be
2418 * on
2419 * the same interface.
2420 */
2421 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2422 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2423 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2424 nh_reset = true;
2425 }
d62a17ae 2426 }
3f9c7369 2427
7b651a32 2428 /*
2429 * When the next hop is set to ourselves, if all multipaths have
2430 * link-bandwidth announce the cumulative bandwidth as that makes
2431 * the most sense. However, don't modify if the link-bandwidth has
2432 * been explicitly set by user policy.
2433 */
2434 if (nh_reset &&
f7e1c681 2435 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2436 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2437 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2438 bgp_attr_set_ecommunity(
2439 attr,
2440 ecommunity_replace_linkbw(
2441 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2442 CHECK_FLAG(
2443 peer->flags,
2444 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2445
3dc339cd 2446 return true;
3f9c7369
DS
2447}
2448
cc9f21da 2449static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2450{
2451 struct afi_safi_info *info;
2452 afi_t afi;
2453 safi_t safi;
2454 struct bgp *bgp;
2455
2456 info = THREAD_ARG(thread);
2457 afi = info->afi;
2458 safi = info->safi;
2459 bgp = info->bgp;
2460
2461 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2462 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2463 safi);
f009ff26 2464
2465 bgp->gr_info[afi][safi].t_route_select = NULL;
2466
2467 XFREE(MTYPE_TMP, info);
2468
2469 /* Best path selection */
cc9f21da 2470 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2471}
2472
9bcb3eef 2473void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2474 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2475 struct bgp_path_info_pair *result, afi_t afi,
2476 safi_t safi)
2477{
2478 struct bgp_path_info *new_select;
2479 struct bgp_path_info *old_select;
40381db7
DS
2480 struct bgp_path_info *pi;
2481 struct bgp_path_info *pi1;
2482 struct bgp_path_info *pi2;
2483 struct bgp_path_info *nextpi = NULL;
d62a17ae 2484 int paths_eq, do_mpath, debug;
2485 struct list mp_list;
2486 char pfx_buf[PREFIX2STR_BUFFER];
2487 char path_buf[PATH_ADDPATH_STR_BUFFER];
2488
2489 bgp_mp_list_init(&mp_list);
2490 do_mpath =
2491 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2492
9bcb3eef 2493 debug = bgp_debug_bestpath(dest);
d62a17ae 2494
2495 if (debug)
9bcb3eef 2496 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2497
9bcb3eef 2498 dest->reason = bgp_path_selection_none;
d62a17ae 2499 /* bgp deterministic-med */
2500 new_select = NULL;
892fedb6 2501 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2502
1defdda8 2503 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2504 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2505 pi1 = pi1->next)
9bcb3eef 2506 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2507 BGP_PATH_DMED_SELECTED);
d62a17ae 2508
9bcb3eef 2509 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2510 pi1 = pi1->next) {
40381db7 2511 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2512 continue;
40381db7 2513 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2514 continue;
ea8b2282 2515 if (pi1->peer != bgp->peer_self)
feb17238 2516 if (!peer_established(pi1->peer))
d62a17ae 2517 continue;
2518
40381db7
DS
2519 new_select = pi1;
2520 if (pi1->next) {
2521 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2522 if (CHECK_FLAG(pi2->flags,
1defdda8 2523 BGP_PATH_DMED_CHECK))
d62a17ae 2524 continue;
40381db7 2525 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2526 continue;
ea8b2282 2527 if (pi2->peer != bgp->peer_self
d62a17ae 2528 && !CHECK_FLAG(
ea8b2282
DS
2529 pi2->peer->sflags,
2530 PEER_STATUS_NSF_WAIT))
40381db7 2531 if (pi2->peer->status
d62a17ae 2532 != Established)
2533 continue;
2534
121e245d
DS
2535 if (!aspath_cmp_left(pi1->attr->aspath,
2536 pi2->attr->aspath)
2537 && !aspath_cmp_left_confed(
40381db7 2538 pi1->attr->aspath,
121e245d
DS
2539 pi2->attr->aspath))
2540 continue;
d62a17ae 2541
121e245d
DS
2542 if (bgp_path_info_cmp(
2543 bgp, pi2, new_select,
2544 &paths_eq, mpath_cfg, debug,
fdf81fa0 2545 pfx_buf, afi, safi,
9bcb3eef 2546 &dest->reason)) {
121e245d 2547 bgp_path_info_unset_flag(
9bcb3eef 2548 dest, new_select,
121e245d
DS
2549 BGP_PATH_DMED_SELECTED);
2550 new_select = pi2;
d62a17ae 2551 }
121e245d
DS
2552
2553 bgp_path_info_set_flag(
9bcb3eef 2554 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2555 }
2556 }
9bcb3eef 2557 bgp_path_info_set_flag(dest, new_select,
18ee8310 2558 BGP_PATH_DMED_CHECK);
9bcb3eef 2559 bgp_path_info_set_flag(dest, new_select,
18ee8310 2560 BGP_PATH_DMED_SELECTED);
d62a17ae 2561
2562 if (debug) {
18ee8310 2563 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2564 new_select, path_buf, sizeof(path_buf));
8228a9a7 2565 zlog_debug(
4378495a
DS
2566 "%pBD(%s): %s is the bestpath from AS %u",
2567 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2568 aspath_get_first_as(
2569 new_select->attr->aspath));
d62a17ae 2570 }
2571 }
2572 }
96450faf 2573
d62a17ae 2574 /* Check old selected route and new selected route. */
2575 old_select = NULL;
2576 new_select = NULL;
9bcb3eef 2577 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2578 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2579 enum bgp_path_selection_reason reason;
2580
40381db7
DS
2581 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2582 old_select = pi;
d62a17ae 2583
40381db7 2584 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2585 /* reap REMOVED routes, if needs be
2586 * selected route must stay for a while longer though
2587 */
40381db7
DS
2588 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2589 && (pi != old_select))
9bcb3eef 2590 bgp_path_info_reap(dest, pi);
d62a17ae 2591
ddb5b488 2592 if (debug)
40381db7
DS
2593 zlog_debug("%s: pi %p in holddown", __func__,
2594 pi);
ddb5b488 2595
d62a17ae 2596 continue;
2597 }
96450faf 2598
40381db7
DS
2599 if (pi->peer && pi->peer != bgp->peer_self
2600 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2601 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2602
2603 if (debug)
2604 zlog_debug(
40381db7
DS
2605 "%s: pi %p non self peer %s not estab state",
2606 __func__, pi, pi->peer->host);
ddb5b488 2607
d62a17ae 2608 continue;
ddb5b488 2609 }
9fbdd100 2610
892fedb6 2611 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2612 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2613 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2614 if (debug)
40381db7 2615 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2616 continue;
2617 }
9fbdd100 2618
9bcb3eef 2619 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2620
9bcb3eef 2621 reason = dest->reason;
40381db7 2622 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2623 debug, pfx_buf, afi, safi,
2624 &dest->reason)) {
19ea4cec
DS
2625 if (new_select == NULL &&
2626 reason != bgp_path_selection_none)
9bcb3eef 2627 dest->reason = reason;
40381db7 2628 new_select = pi;
d62a17ae 2629 }
2630 }
718e3744 2631
d62a17ae 2632 /* Now that we know which path is the bestpath see if any of the other
2633 * paths
2634 * qualify as multipaths
2635 */
2636 if (debug) {
2637 if (new_select)
7533cad7
QY
2638 bgp_path_info_path_with_addpath_rx_str(
2639 new_select, path_buf, sizeof(path_buf));
d62a17ae 2640 else
772270f3 2641 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2642 zlog_debug(
4378495a
DS
2643 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2644 dest, bgp->name_pretty, path_buf,
d62a17ae 2645 old_select ? old_select->peer->host : "NONE");
96450faf 2646 }
9fbdd100 2647
d62a17ae 2648 if (do_mpath && new_select) {
9bcb3eef 2649 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2650 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2651
2652 if (debug)
18ee8310 2653 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2654 pi, path_buf, sizeof(path_buf));
d62a17ae 2655
40381db7 2656 if (pi == new_select) {
d62a17ae 2657 if (debug)
2658 zlog_debug(
4378495a
DS
2659 "%pBD(%s): %s is the bestpath, add to the multipath list",
2660 dest, bgp->name_pretty,
2661 path_buf);
40381db7 2662 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2663 continue;
2664 }
2665
40381db7 2666 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2667 continue;
2668
40381db7
DS
2669 if (pi->peer && pi->peer != bgp->peer_self
2670 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2671 PEER_STATUS_NSF_WAIT))
feb17238 2672 if (!peer_established(pi->peer))
d62a17ae 2673 continue;
2674
40381db7 2675 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2676 if (debug)
2677 zlog_debug(
8228a9a7
DS
2678 "%pBD: %s has the same nexthop as the bestpath, skip it",
2679 dest, path_buf);
d62a17ae 2680 continue;
2681 }
2682
40381db7 2683 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2684 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2685 &dest->reason);
d62a17ae 2686
2687 if (paths_eq) {
2688 if (debug)
2689 zlog_debug(
8228a9a7
DS
2690 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2691 dest, path_buf);
40381db7 2692 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2693 }
2694 }
2695 }
fee0f4c6 2696
4378495a 2697 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2698 mpath_cfg);
2699 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2700 bgp_mp_list_clear(&mp_list);
96450faf 2701
9bcb3eef 2702 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2703
d62a17ae 2704 result->old = old_select;
2705 result->new = new_select;
96450faf 2706
d62a17ae 2707 return;
fee0f4c6 2708}
2709
3f9c7369
DS
2710/*
2711 * A new route/change in bestpath of an existing route. Evaluate the path
2712 * for advertisement to the subgroup.
2713 */
3dc339cd
DA
2714void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2715 struct bgp_path_info *selected,
9bcb3eef 2716 struct bgp_dest *dest,
3dc339cd 2717 uint32_t addpath_tx_id)
d62a17ae 2718{
b54892e0 2719 const struct prefix *p;
d62a17ae 2720 struct peer *onlypeer;
2721 struct attr attr;
2722 afi_t afi;
2723 safi_t safi;
a77e2f4b
S
2724 struct bgp *bgp;
2725 bool advertise;
adbac85e 2726
9bcb3eef 2727 p = bgp_dest_get_prefix(dest);
d62a17ae 2728 afi = SUBGRP_AFI(subgrp);
2729 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2730 bgp = SUBGRP_INST(subgrp);
d62a17ae 2731 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2732 : NULL);
2733
2dbe669b
DA
2734 if (BGP_DEBUG(update, UPDATE_OUT))
2735 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2736
d62a17ae 2737 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2738 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2739 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2740 return;
d62a17ae 2741
6006b807 2742 memset(&attr, 0, sizeof(attr));
d62a17ae 2743 /* It's initialized in bgp_announce_check() */
2744
a77e2f4b
S
2745 /* Announcement to the subgroup. If the route is filtered withdraw it.
2746 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2747 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2748 * route
d62a17ae 2749 */
a77e2f4b
S
2750 advertise = bgp_check_advertise(bgp, dest);
2751
d62a17ae 2752 if (selected) {
7f7940e6 2753 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2754 NULL)) {
a77e2f4b
S
2755 /* Route is selected, if the route is already installed
2756 * in FIB, then it is advertised
2757 */
be785e35
DS
2758 if (advertise) {
2759 if (!bgp_check_withdrawal(bgp, dest))
2760 bgp_adj_out_set_subgroup(
2761 dest, subgrp, &attr, selected);
2762 else
2763 bgp_adj_out_unset_subgroup(
2764 dest, subgrp, 1, addpath_tx_id);
2765 }
a77e2f4b 2766 } else
9bcb3eef 2767 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2768 addpath_tx_id);
d62a17ae 2769 }
2770
2771 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2772 else {
9bcb3eef 2773 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2774 }
200df115 2775}
fee0f4c6 2776
3064bf43 2777/*
e1072051 2778 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2779 * This is called at the end of route processing.
3064bf43 2780 */
9bcb3eef 2781void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2782{
40381db7 2783 struct bgp_path_info *pi;
3064bf43 2784
9bcb3eef 2785 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2786 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2787 continue;
40381db7
DS
2788 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2789 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2790 }
3064bf43 2791}
2792
2793/*
2794 * Has the route changed from the RIB's perspective? This is invoked only
2795 * if the route selection returns the same best route as earlier - to
2796 * determine if we need to update zebra or not.
2797 */
9bcb3eef 2798bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2799{
4b7e6066 2800 struct bgp_path_info *mpinfo;
d62a17ae 2801
2bb9eff4
DS
2802 /* If this is multipath, check all selected paths for any nexthop
2803 * change or attribute change. Some attribute changes (e.g., community)
2804 * aren't of relevance to the RIB, but we'll update zebra to ensure
2805 * we handle the case of BGP nexthop change. This is the behavior
2806 * when the best path has an attribute change anyway.
d62a17ae 2807 */
1defdda8 2808 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2809 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2810 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2811 return true;
d62a17ae 2812
2bb9eff4
DS
2813 /*
2814 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2815 */
18ee8310
DS
2816 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2817 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2818 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2819 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2820 return true;
d62a17ae 2821 }
3064bf43 2822
d62a17ae 2823 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2824 return false;
3064bf43 2825}
2826
d62a17ae 2827struct bgp_process_queue {
2828 struct bgp *bgp;
9bcb3eef 2829 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2830#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2831 unsigned int flags;
2832 unsigned int queued;
200df115 2833};
2834
3b0c17e1 2835static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2836 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2837 struct bgp_path_info *new_select,
2838 struct bgp_path_info *old_select)
2839{
9bcb3eef 2840 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2841
2842 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2843 return;
2844
2845 if (advertise_type5_routes(bgp, afi) && new_select
2846 && is_route_injectable_into_evpn(new_select)) {
2847
2848 /* apply the route-map */
2849 if (bgp->adv_cmd_rmap[afi][safi].map) {
2850 route_map_result_t ret;
2851 struct bgp_path_info rmap_path;
2852 struct bgp_path_info_extra rmap_path_extra;
2853 struct attr dummy_attr;
2854
2855 dummy_attr = *new_select->attr;
2856
2857 /* Fill temp path_info */
9bcb3eef 2858 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2859 new_select, new_select->peer,
2860 &dummy_attr);
2861
2862 RESET_FLAG(dummy_attr.rmap_change_flags);
2863
2864 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2865 p, &rmap_path);
3b0c17e1 2866
2867 if (ret == RMAP_DENYMATCH) {
2868 bgp_attr_flush(&dummy_attr);
2869 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2870 safi);
2871 } else
2872 bgp_evpn_advertise_type5_route(
2873 bgp, p, &dummy_attr, afi, safi);
2874 } else {
2875 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2876 afi, safi);
2877 }
2878 } else if (advertise_type5_routes(bgp, afi) && old_select
2879 && is_route_injectable_into_evpn(old_select))
2880 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2881}
2882
bb2ca692
MS
2883/*
2884 * Utility to determine whether a particular path_info should use
2885 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2886 * in a path where we basically _know_ this is a BGP-LU route.
2887 */
2888static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2889{
2890 /* Certain types get imp null; so do paths where the nexthop is
2891 * not labeled.
2892 */
2893 if (new_select->sub_type == BGP_ROUTE_STATIC
2894 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2895 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2896 return true;
2897 else if (new_select->extra == NULL ||
2898 !bgp_is_valid_label(&new_select->extra->label[0]))
2899 /* TODO -- should be configurable? */
2900 return true;
2901 else
2902 return false;
2903}
2904
3103e8d2
DS
2905/*
2906 * old_select = The old best path
2907 * new_select = the new best path
2908 *
2909 * if (!old_select && new_select)
2910 * We are sending new information on.
2911 *
2912 * if (old_select && new_select) {
2913 * if (new_select != old_select)
2914 * We have a new best path send a change
2915 * else
2916 * We've received a update with new attributes that needs
2917 * to be passed on.
2918 * }
2919 *
2920 * if (old_select && !new_select)
2921 * We have no eligible route that we can announce or the rn
2922 * is being removed.
2923 */
9bcb3eef 2924static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2925 afi_t afi, safi_t safi)
d62a17ae 2926{
4b7e6066
DS
2927 struct bgp_path_info *new_select;
2928 struct bgp_path_info *old_select;
2929 struct bgp_path_info_pair old_and_new;
ddb5b488 2930 int debug = 0;
d62a17ae 2931
892fedb6 2932 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2933 if (dest)
2934 debug = bgp_debug_bestpath(dest);
b54892e0 2935 if (debug)
f4c713ae 2936 zlog_debug(
56ca3b5b 2937 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2938 __func__, dest);
f4c713ae
LB
2939 return;
2940 }
d62a17ae 2941 /* Is it end of initial update? (after startup) */
9bcb3eef 2942 if (!dest) {
e36f61b5
DS
2943 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2944 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2945
2946 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2947 FOREACH_AFI_SAFI (afi, safi) {
2948 if (bgp_fibupd_safi(safi))
2949 bgp_zebra_announce_table(bgp, afi, safi);
2950 }
d62a17ae 2951 bgp->main_peers_update_hold = 0;
2952
2953 bgp_start_routeadv(bgp);
aac24838 2954 return;
d62a17ae 2955 }
cb1faec9 2956
9bcb3eef 2957 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2958
9bcb3eef 2959 debug = bgp_debug_bestpath(dest);
b54892e0 2960 if (debug)
4378495a
DS
2961 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2962 dest, bgp->name_pretty, afi2str(afi),
2963 safi2str(safi));
ddb5b488 2964
f009ff26 2965 /* The best path calculation for the route is deferred if
2966 * BGP_NODE_SELECT_DEFER is set
2967 */
9bcb3eef 2968 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2969 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2970 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2971 return;
2972 }
2973
d62a17ae 2974 /* Best path selection. */
9bcb3eef 2975 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2976 afi, safi);
2977 old_select = old_and_new.old;
2978 new_select = old_and_new.new;
2979
2980 /* Do we need to allocate or free labels?
2981 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2982 * necessary to do this upon changes to best path. Exceptions:
2983 * - label index has changed -> recalculate resulting label
2984 * - path_info sub_type changed -> switch to/from implicit-null
2985 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2986 */
318cac96 2987 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2988 if (new_select) {
2989 if (!old_select
2990 || bgp_label_index_differs(new_select, old_select)
57592a53 2991 || new_select->sub_type != old_select->sub_type
9bcb3eef 2992 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2993 /* Enforced penultimate hop popping:
2994 * implicit-null for local routes, aggregate
2995 * and redistributed routes
2996 */
bb2ca692 2997 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2998 if (CHECK_FLAG(
9bcb3eef 2999 dest->flags,
992dd67e
PR
3000 BGP_NODE_REGISTERED_FOR_LABEL)
3001 || CHECK_FLAG(
3002 dest->flags,
3003 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3004 bgp_unregister_for_label(dest);
67f67ba4
DA
3005 dest->local_label = mpls_lse_encode(
3006 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3007 1);
9bcb3eef 3008 bgp_set_valid_label(&dest->local_label);
d62a17ae 3009 } else
9bcb3eef
DS
3010 bgp_register_for_label(dest,
3011 new_select);
d62a17ae 3012 }
9bcb3eef 3013 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3014 BGP_NODE_REGISTERED_FOR_LABEL)
3015 || CHECK_FLAG(dest->flags,
3016 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3017 bgp_unregister_for_label(dest);
318cac96 3018 }
992dd67e
PR
3019 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3020 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3021 bgp_unregister_for_label(dest);
d62a17ae 3022 }
cd1964ff 3023
b54892e0 3024 if (debug)
ddb5b488 3025 zlog_debug(
4378495a
DS
3026 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3027 __func__, dest, bgp->name_pretty, afi2str(afi),
3028 safi2str(safi), old_select, new_select);
ddb5b488 3029
d62a17ae 3030 /* If best route remains the same and this is not due to user-initiated
3031 * clear, see exactly what needs to be done.
3032 */
d62a17ae 3033 if (old_select && old_select == new_select
9bcb3eef 3034 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3035 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3036 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3037 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3038#ifdef ENABLE_BGP_VNC
d62a17ae 3039 vnc_import_bgp_add_route(bgp, p, old_select);
3040 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3041#endif
bb744275 3042 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3043 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3044
be785e35
DS
3045 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3046 && new_select->sub_type == BGP_ROUTE_NORMAL)
3047 SET_FLAG(dest->flags,
3048 BGP_NODE_FIB_INSTALL_PENDING);
3049
ddb5b488
PZ
3050 if (new_select->type == ZEBRA_ROUTE_BGP
3051 && (new_select->sub_type == BGP_ROUTE_NORMAL
3052 || new_select->sub_type
3053 == BGP_ROUTE_IMPORTED))
3054
9bcb3eef 3055 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3056 bgp, afi, safi);
3057 }
d62a17ae 3058 }
d62a17ae 3059
3060 /* If there is a change of interest to peers, reannounce the
3061 * route. */
1defdda8 3062 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3063 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3064 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3065 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3066
3067 /* unicast routes must also be annouced to
3068 * labeled-unicast update-groups */
3069 if (safi == SAFI_UNICAST)
3070 group_announce_route(bgp, afi,
9bcb3eef 3071 SAFI_LABELED_UNICAST, dest,
d62a17ae 3072 new_select);
3073
1defdda8 3074 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3075 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3076 }
fee0f4c6 3077
3b0c17e1 3078 /* advertise/withdraw type-5 routes */
3079 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3080 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3081 bgp_process_evpn_route_injection(
9bcb3eef 3082 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3083
b1875e65 3084 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3085 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3086 bgp_zebra_clear_route_change_flags(dest);
3087 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3088 return;
d62a17ae 3089 }
8ad7271d 3090
d62a17ae 3091 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3092 */
9bcb3eef 3093 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3094
3095 /* bestpath has changed; bump version */
3096 if (old_select || new_select) {
9bcb3eef 3097 bgp_bump_version(dest);
d62a17ae 3098
3099 if (!bgp->t_rmap_def_originate_eval) {
3100 bgp_lock(bgp);
3101 thread_add_timer(
3102 bm->master,
3103 update_group_refresh_default_originate_route_map,
3104 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3105 &bgp->t_rmap_def_originate_eval);
3106 }
3107 }
3f9c7369 3108
d62a17ae 3109 if (old_select)
9bcb3eef 3110 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3111 if (new_select) {
ddb5b488
PZ
3112 if (debug)
3113 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3114 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3115 bgp_path_info_unset_flag(dest, new_select,
3116 BGP_PATH_ATTR_CHANGED);
1defdda8 3117 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3118 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3119 }
338b3424 3120
49e5a4a0 3121#ifdef ENABLE_BGP_VNC
d62a17ae 3122 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3123 if (old_select != new_select) {
3124 if (old_select) {
3125 vnc_import_bgp_exterior_del_route(bgp, p,
3126 old_select);
3127 vnc_import_bgp_del_route(bgp, p, old_select);
3128 }
3129 if (new_select) {
3130 vnc_import_bgp_exterior_add_route(bgp, p,
3131 new_select);
3132 vnc_import_bgp_add_route(bgp, p, new_select);
3133 }
3134 }
3135 }
65efcfce
LB
3136#endif
3137
9bcb3eef 3138 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3139
3140 /* unicast routes must also be annouced to labeled-unicast update-groups
3141 */
3142 if (safi == SAFI_UNICAST)
9bcb3eef 3143 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3144 new_select);
3145
3146 /* FIB update. */
3147 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3148 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3149
d62a17ae 3150 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3151 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3152 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3153 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3154
be785e35
DS
3155 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3156 SET_FLAG(dest->flags,
3157 BGP_NODE_FIB_INSTALL_PENDING);
3158
2b659f33
MK
3159 /* if this is an evpn imported type-5 prefix,
3160 * we need to withdraw the route first to clear
3161 * the nh neigh and the RMAC entry.
3162 */
3163 if (old_select &&
3164 is_route_parent_evpn(old_select))
3165 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3166
9bcb3eef 3167 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3168 } else {
d62a17ae 3169 /* Withdraw the route from the kernel. */
3170 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3171 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3172 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3173 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3174
568e10ca 3175 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3176 }
718e3744 3177 }
3064bf43 3178
9bcb3eef 3179 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3180 old_select);
5424b7ba 3181
d62a17ae 3182 /* Clear any route change flags. */
9bcb3eef 3183 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3184
18ee8310 3185 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3186 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3187 bgp_path_info_reap(dest, old_select);
d62a17ae 3188
9bcb3eef 3189 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3190 return;
718e3744 3191}
3192
f009ff26 3193/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3194int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3195{
9bcb3eef 3196 struct bgp_dest *dest;
f009ff26 3197 int cnt = 0;
3198 struct afi_safi_info *thread_info;
f009ff26 3199
56c226e7
DS
3200 if (bgp->gr_info[afi][safi].t_route_select) {
3201 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3202
3203 thread_info = THREAD_ARG(t);
3204 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3205 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3206 }
f009ff26 3207
3208 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3209 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3210 get_afi_safi_str(afi, safi, false),
26742171 3211 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3212 }
3213
3214 /* Process the route list */
6338d242 3215 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3216 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3217 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3218 dest = bgp_route_next(dest)) {
3219 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3220 continue;
3221
3222 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3223 bgp->gr_info[afi][safi].gr_deferred--;
3224 bgp_process_main_one(bgp, dest, afi, safi);
3225 cnt++;
067ea165
CB
3226 }
3227 /* If iteration stopped before the entire table was traversed then the
3228 * node needs to be unlocked.
3229 */
3230 if (dest) {
3231 bgp_dest_unlock_node(dest);
3232 dest = NULL;
f009ff26 3233 }
3234
9e3b51a7 3235 /* Send EOR message when all routes are processed */
6338d242 3236 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3237 bgp_send_delayed_eor(bgp);
8c48b3b6 3238 /* Send route processing complete message to RIB */
3239 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3240 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3241 return 0;
9e3b51a7 3242 }
f009ff26 3243
3244 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3245
3246 thread_info->afi = afi;
3247 thread_info->safi = safi;
3248 thread_info->bgp = bgp;
3249
3250 /* If there are more routes to be processed, start the
3251 * selection timer
3252 */
3253 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3254 BGP_ROUTE_SELECT_DELAY,
3255 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3256 return 0;
3257}
3258
aac24838 3259static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3260{
aac24838
JB
3261 struct bgp_process_queue *pqnode = data;
3262 struct bgp *bgp = pqnode->bgp;
d62a17ae 3263 struct bgp_table *table;
9bcb3eef 3264 struct bgp_dest *dest;
aac24838
JB
3265
3266 /* eoiu marker */
3267 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3268 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3269 /* should always have dedicated wq call */
3270 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3271 return WQ_SUCCESS;
3272 }
3273
ac021f40 3274 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3275 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3276 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3277 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3278 table = bgp_dest_table(dest);
3279 /* note, new DESTs may be added as part of processing */
3280 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3281
9bcb3eef 3282 bgp_dest_unlock_node(dest);
d62a17ae 3283 bgp_table_unlock(table);
3284 }
aac24838
JB
3285
3286 return WQ_SUCCESS;
3287}
3288
3289static void bgp_processq_del(struct work_queue *wq, void *data)
3290{
3291 struct bgp_process_queue *pqnode = data;
3292
3293 bgp_unlock(pqnode->bgp);
3294
3295 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3296}
3297
b6c386bb 3298void bgp_process_queue_init(struct bgp *bgp)
200df115 3299{
b6c386bb
DS
3300 if (!bgp->process_queue) {
3301 char name[BUFSIZ];
3302
3303 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3304 bgp->process_queue = work_queue_new(bm->master, name);
3305 }
3306
3307 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3308 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3309 bgp->process_queue->spec.max_retries = 0;
3310 bgp->process_queue->spec.hold = 50;
d62a17ae 3311 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3312 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3313}
3314
cfe8d15a 3315static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3316{
3317 struct bgp_process_queue *pqnode;
3318
a4d82a8a
PZ
3319 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3320 sizeof(struct bgp_process_queue));
aac24838
JB
3321
3322 /* unlocked in bgp_processq_del */
3323 pqnode->bgp = bgp_lock(bgp);
3324 STAILQ_INIT(&pqnode->pqueue);
3325
aac24838
JB
3326 return pqnode;
3327}
3328
9bcb3eef 3329void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3330{
aac24838 3331#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3332 struct work_queue *wq = bgp->process_queue;
d62a17ae 3333 struct bgp_process_queue *pqnode;
cfe8d15a 3334 int pqnode_reuse = 0;
495f0b13 3335
d62a17ae 3336 /* already scheduled for processing? */
9bcb3eef 3337 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3338 return;
2e02b9b2 3339
f009ff26 3340 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3341 * the workqueue
3342 */
9bcb3eef 3343 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3344 if (BGP_DEBUG(update, UPDATE_OUT))
3345 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3346 dest);
f009ff26 3347 return;
3348 }
3349
46aeabed
LS
3350 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3351 if (BGP_DEBUG(update, UPDATE_OUT))
3352 zlog_debug(
3353 "Soft reconfigure table in progress for route %p",
3354 dest);
3355 return;
3356 }
3357
aac24838 3358 if (wq == NULL)
d62a17ae 3359 return;
3360
aac24838 3361 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3362 limit only if is from the same BGP view and it's not an EOIU marker
3363 */
aac24838
JB
3364 if (work_queue_item_count(wq)) {
3365 struct work_queue_item *item = work_queue_last_item(wq);
3366 pqnode = item->data;
228da428 3367
a4d82a8a
PZ
3368 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3369 || pqnode->bgp != bgp
3370 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3371 pqnode = bgp_processq_alloc(bgp);
3372 else
3373 pqnode_reuse = 1;
aac24838 3374 } else
cfe8d15a 3375 pqnode = bgp_processq_alloc(bgp);
aac24838 3376 /* all unlocked in bgp_process_wq */
9bcb3eef 3377 bgp_table_lock(bgp_dest_table(dest));
aac24838 3378
9bcb3eef
DS
3379 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3380 bgp_dest_lock_node(dest);
aac24838 3381
60466a63 3382 /* can't be enqueued twice */
9bcb3eef
DS
3383 assert(STAILQ_NEXT(dest, pq) == NULL);
3384 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3385 pqnode->queued++;
3386
cfe8d15a
LB
3387 if (!pqnode_reuse)
3388 work_queue_add(wq, pqnode);
3389
d62a17ae 3390 return;
fee0f4c6 3391}
0a486e5f 3392
d62a17ae 3393void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3394{
d62a17ae 3395 struct bgp_process_queue *pqnode;
cb1faec9 3396
b6c386bb 3397 if (bgp->process_queue == NULL)
d62a17ae 3398 return;
2e02b9b2 3399
cfe8d15a 3400 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3401
aac24838 3402 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3403 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3404}
3405
cc9f21da 3406static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3407{
d62a17ae 3408 struct peer *peer;
0a486e5f 3409
d62a17ae 3410 peer = THREAD_ARG(thread);
3411 peer->t_pmax_restart = NULL;
0a486e5f 3412
d62a17ae 3413 if (bgp_debug_neighbor_events(peer))
3414 zlog_debug(
3415 "%s Maximum-prefix restart timer expired, restore peering",
3416 peer->host);
0a486e5f 3417
a9bafa95 3418 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3419 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3420}
3421
9cbd06e0
DA
3422static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3423 safi_t safi)
3424{
3425 uint32_t count = 0;
f41b0459 3426 bool filtered = false;
9cbd06e0
DA
3427 struct bgp_dest *dest;
3428 struct bgp_adj_in *ain;
40bb2ccf 3429 struct attr attr = {};
9cbd06e0
DA
3430 struct bgp_table *table = peer->bgp->rib[afi][safi];
3431
3432 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3433 for (ain = dest->adj_in; ain; ain = ain->next) {
3434 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3435
3436 attr = *ain->attr;
9cbd06e0
DA
3437
3438 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3439 == FILTER_DENY)
f41b0459
DA
3440 filtered = true;
3441
3442 if (bgp_input_modifier(
3443 peer, rn_p, &attr, afi, safi,
3444 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3445 NULL, 0, NULL)
3446 == RMAP_DENY)
3447 filtered = true;
3448
3449 if (filtered)
9cbd06e0 3450 count++;
f41b0459 3451
d498917e 3452 bgp_attr_flush(&attr);
9cbd06e0
DA
3453 }
3454 }
3455
3456 return count;
3457}
3458
3dc339cd
DA
3459bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3460 int always)
718e3744 3461{
d62a17ae 3462 iana_afi_t pkt_afi;
5c525538 3463 iana_safi_t pkt_safi;
9cbd06e0
DA
3464 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3465 PEER_FLAG_MAX_PREFIX_FORCE))
3466 ? bgp_filtered_routes_count(peer, afi, safi)
3467 + peer->pcount[afi][safi]
3468 : peer->pcount[afi][safi];
9cabb64b 3469
d62a17ae 3470 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3471 return false;
e0701b79 3472
9cbd06e0 3473 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3474 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3475 PEER_STATUS_PREFIX_LIMIT)
3476 && !always)
3dc339cd 3477 return false;
e0701b79 3478
d62a17ae 3479 zlog_info(
f70c91dc
DA
3480 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3481 get_afi_safi_str(afi, safi, false), peer, pcount,
3482 peer->pmax[afi][safi]);
d62a17ae 3483 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3484
3485 if (CHECK_FLAG(peer->af_flags[afi][safi],
3486 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3487 return false;
d62a17ae 3488
3489 /* Convert AFI, SAFI to values for packet. */
3490 pkt_afi = afi_int2iana(afi);
3491 pkt_safi = safi_int2iana(safi);
3492 {
d7c0a89a 3493 uint8_t ndata[7];
d62a17ae 3494
3495 ndata[0] = (pkt_afi >> 8);
3496 ndata[1] = pkt_afi;
3497 ndata[2] = pkt_safi;
3498 ndata[3] = (peer->pmax[afi][safi] >> 24);
3499 ndata[4] = (peer->pmax[afi][safi] >> 16);
3500 ndata[5] = (peer->pmax[afi][safi] >> 8);
3501 ndata[6] = (peer->pmax[afi][safi]);
3502
3503 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3504 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3505 BGP_NOTIFY_CEASE_MAX_PREFIX,
3506 ndata, 7);
3507 }
3508
3509 /* Dynamic peers will just close their connection. */
3510 if (peer_dynamic_neighbor(peer))
3dc339cd 3511 return true;
d62a17ae 3512
3513 /* restart timer start */
3514 if (peer->pmax_restart[afi][safi]) {
3515 peer->v_pmax_restart =
3516 peer->pmax_restart[afi][safi] * 60;
3517
3518 if (bgp_debug_neighbor_events(peer))
3519 zlog_debug(
f70c91dc
DA
3520 "%pBP Maximum-prefix restart timer started for %d secs",
3521 peer, peer->v_pmax_restart);
d62a17ae 3522
3523 BGP_TIMER_ON(peer->t_pmax_restart,
3524 bgp_maximum_prefix_restart_timer,
3525 peer->v_pmax_restart);
3526 }
3527
3dc339cd 3528 return true;
d62a17ae 3529 } else
3530 UNSET_FLAG(peer->af_sflags[afi][safi],
3531 PEER_STATUS_PREFIX_LIMIT);
3532
b1823b69
DS
3533 if (pcount
3534 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3535 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3536 PEER_STATUS_PREFIX_THRESHOLD)
3537 && !always)
3dc339cd 3538 return false;
d62a17ae 3539
3540 zlog_info(
f70c91dc
DA
3541 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3542 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3543 peer->pmax[afi][safi]);
d62a17ae 3544 SET_FLAG(peer->af_sflags[afi][safi],
3545 PEER_STATUS_PREFIX_THRESHOLD);
3546 } else
3547 UNSET_FLAG(peer->af_sflags[afi][safi],
3548 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3549 return false;
718e3744 3550}
3551
b40d939b 3552/* Unconditionally remove the route from the RIB, without taking
3553 * damping into consideration (eg, because the session went down)
3554 */
9bcb3eef 3555void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3556 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3557{
f009ff26 3558
3559 struct bgp *bgp = NULL;
3560 bool delete_route = false;
3561
9bcb3eef
DS
3562 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3563 safi);
d62a17ae 3564
f009ff26 3565 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3566 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3567
f009ff26 3568 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3569 * flag
3570 */
3571 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3572 delete_route = true;
9bcb3eef 3573 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3574 delete_route = true;
f009ff26 3575 if (delete_route) {
9bcb3eef
DS
3576 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3577 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3578 bgp = pi->peer->bgp;
26742171 3579 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3580 }
3581 }
3582 }
4a11bf2c 3583
9bcb3eef
DS
3584 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3585 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3586}
3587
9bcb3eef 3588static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3589 struct peer *peer, afi_t afi, safi_t safi,
3590 struct prefix_rd *prd)
3591{
9bcb3eef 3592 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3593
d62a17ae 3594 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3595 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3596 */
b4f7f45b
IR
3597 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3598 && peer->sort == BGP_PEER_EBGP)
3599 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3600 == BGP_DAMP_SUPPRESSED) {
3601 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3602 safi);
3603 return;
d62a17ae 3604 }
3605
49e5a4a0 3606#ifdef ENABLE_BGP_VNC
d62a17ae 3607 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3608 struct bgp_dest *pdest = NULL;
d62a17ae 3609 struct bgp_table *table = NULL;
3610
9bcb3eef
DS
3611 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3612 (struct prefix *)prd);
3613 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3614 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3615
3616 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3617 peer->bgp, prd, table, p, pi);
d62a17ae 3618 }
9bcb3eef 3619 bgp_dest_unlock_node(pdest);
d62a17ae 3620 }
3621 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3622 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3623
b54892e0
DS
3624 vnc_import_bgp_del_route(peer->bgp, p, pi);
3625 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3626 }
65efcfce 3627 }
d62a17ae 3628#endif
128ea8ab 3629
d62a17ae 3630 /* If this is an EVPN route, process for un-import. */
3631 if (safi == SAFI_EVPN)
b54892e0 3632 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3633
9bcb3eef 3634 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3635}
3636
4b7e6066
DS
3637struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3638 struct peer *peer, struct attr *attr,
9bcb3eef 3639 struct bgp_dest *dest)
fb018d25 3640{
4b7e6066 3641 struct bgp_path_info *new;
fb018d25 3642
d62a17ae 3643 /* Make new BGP info. */
4b7e6066 3644 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3645 new->type = type;
3646 new->instance = instance;
3647 new->sub_type = sub_type;
3648 new->peer = peer;
3649 new->attr = attr;
3650 new->uptime = bgp_clock();
9bcb3eef 3651 new->net = dest;
d62a17ae 3652 return new;
fb018d25
DS
3653}
3654
c265ee22 3655/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3656bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3657 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3658 struct bgp_dest *dest)
d62a17ae 3659{
2dbe3fa9 3660 bool ret = false;
b099a5c8
DA
3661 bool is_bgp_static_route =
3662 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3663 : false;
d62a17ae 3664
e8442016
DS
3665 /*
3666 * Only validated for unicast and multicast currently.
3667 * Also valid for EVPN where the nexthop is an IP address.
3668 * If we are a bgp static route being checked then there is
3669 * no need to check to see if the nexthop is martian as
3670 * that it should be ok.
3671 */
3672 if (is_bgp_static_route ||
3673 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3674 return false;
d62a17ae 3675
3676 /* If NEXT_HOP is present, validate it. */
3677 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3678 if (attr->nexthop.s_addr == INADDR_ANY ||
3679 !ipv4_unicast_valid(&attr->nexthop) ||
3680 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3681 return true;
d62a17ae 3682 }
c265ee22 3683
d62a17ae 3684 /* If MP_NEXTHOP is present, validate it. */
3685 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3686 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3687 * it is not an IPv6 link-local address.
0355b41d
DA
3688 *
3689 * If we receive an UPDATE with nexthop length set to 32 bytes
3690 * we shouldn't discard an UPDATE if it's set to (::).
3691 * The link-local (2st) is validated along the code path later.
d62a17ae 3692 */
3693 if (attr->mp_nexthop_len) {
3694 switch (attr->mp_nexthop_len) {
3695 case BGP_ATTR_NHLEN_IPV4:
3696 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3697 ret = (attr->mp_nexthop_global_in.s_addr ==
3698 INADDR_ANY ||
3699 !ipv4_unicast_valid(
3700 &attr->mp_nexthop_global_in) ||
3701 bgp_nexthop_self(bgp, afi, type, stype, attr,
3702 dest));
d62a17ae 3703 break;
3704
3705 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3706 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3707 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3708 &attr->mp_nexthop_global)
d62a17ae 3709 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3710 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3711 &attr->mp_nexthop_global)
3712 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3713 dest));
d62a17ae 3714 break;
0355b41d
DA
3715 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3716 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3717 || IN6_IS_ADDR_MULTICAST(
3718 &attr->mp_nexthop_global)
3719 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3720 dest));
0355b41d 3721 break;
d62a17ae 3722
3723 default:
3dc339cd 3724 ret = true;
d62a17ae 3725 break;
3726 }
3727 }
c265ee22 3728
d62a17ae 3729 return ret;
3730}
3731
aade37d7 3732static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3733{
3734 struct community *old;
3735 struct community *new;
3736 struct community *merge;
aade37d7 3737 struct community *no_export;
2721dd61 3738
9a706b42 3739 old = bgp_attr_get_community(attr);
aade37d7 3740 no_export = community_str2com("no-export");
2721dd61 3741
b4efa101
DA
3742 assert(no_export);
3743
2721dd61 3744 if (old) {
aade37d7 3745 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3746
3747 if (!old->refcnt)
3748 community_free(&old);
3749
3750 new = community_uniq_sort(merge);
3751 community_free(&merge);
3752 } else {
aade37d7 3753 new = community_dup(no_export);
2721dd61
DA
3754 }
3755
aade37d7 3756 community_free(&no_export);
2721dd61 3757
9a706b42 3758 bgp_attr_set_community(attr, new);
2721dd61
DA
3759}
3760
5a1ae2c2 3761int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3762 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3763 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3764 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3765 struct bgp_route_evpn *evpn)
d62a17ae 3766{
3767 int ret;
3768 int aspath_loop_count = 0;
9bcb3eef 3769 struct bgp_dest *dest;
d62a17ae 3770 struct bgp *bgp;
3771 struct attr new_attr;
3772 struct attr *attr_new;
40381db7 3773 struct bgp_path_info *pi;
4b7e6066
DS
3774 struct bgp_path_info *new;
3775 struct bgp_path_info_extra *extra;
d62a17ae 3776 const char *reason;
3777 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3778 int connected = 0;
3779 int do_loop_check = 1;
3780 int has_valid_label = 0;
7c312383 3781 afi_t nh_afi;
949b0f24 3782 uint8_t pi_type = 0;
3783 uint8_t pi_sub_type = 0;
9146341f 3784 bool force_evpn_import = false;
907707db 3785 safi_t orig_safi = safi;
a486300b 3786 bool leak_success = true;
949b0f24 3787
c7bb4f00 3788 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3789 char pfxprint[PREFIX2STR_BUFFER];
3790
3791 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3792 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3793 afi, safi, attr);
6401252f
QY
3794 }
3795
49e5a4a0 3796#ifdef ENABLE_BGP_VNC
d62a17ae 3797 int vnc_implicit_withdraw = 0;
65efcfce 3798#endif
d62a17ae 3799 int same_attr = 0;
718e3744 3800
907707db
MS
3801 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3802 if (orig_safi == SAFI_LABELED_UNICAST)
3803 safi = SAFI_UNICAST;
3804
6006b807 3805 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3806 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3807 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3808
d62a17ae 3809 bgp = peer->bgp;
9bcb3eef 3810 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3811 /* TODO: Check to see if we can get rid of "is_valid_label" */
3812 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3813 has_valid_label = (num_labels > 0) ? 1 : 0;
3814 else
3815 has_valid_label = bgp_is_valid_label(label);
718e3744 3816
28f66de2
MS
3817 if (has_valid_label)
3818 assert(label != NULL);
3819
66ff6089
AD
3820 /* Update overlay index of the attribute */
3821 if (afi == AFI_L2VPN && evpn)
3822 memcpy(&attr->evpn_overlay, evpn,
3823 sizeof(struct bgp_route_evpn));
3824
d62a17ae 3825 /* When peer's soft reconfiguration enabled. Record input packet in
3826 Adj-RIBs-In. */
3827 if (!soft_reconfig
3828 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3829 && peer != bgp->peer_self)
9bcb3eef 3830 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3831
3832 /* Check previously received route. */
9bcb3eef 3833 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3834 if (pi->peer == peer && pi->type == type
3835 && pi->sub_type == sub_type
3836 && pi->addpath_rx_id == addpath_id)
d62a17ae 3837 break;
3838
3839 /* AS path local-as loop check. */
3840 if (peer->change_local_as) {
c4368918
DW
3841 if (peer->allowas_in[afi][safi])
3842 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3843 else if (!CHECK_FLAG(peer->flags,
3844 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3845 aspath_loop_count = 1;
3846
3847 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3848 > aspath_loop_count) {
b4d46cc9 3849 peer->stat_pfx_aspath_loop++;
692174a1 3850 reason = "as-path contains our own AS;";
d62a17ae 3851 goto filtered;
3852 }
718e3744 3853 }
718e3744 3854
d62a17ae 3855 /* If the peer is configured for "allowas-in origin" and the last ASN in
3856 * the
3857 * as-path is our ASN then we do not need to call aspath_loop_check
3858 */
3859 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3860 if (aspath_get_last_as(attr->aspath) == bgp->as)
3861 do_loop_check = 0;
3862
3863 /* AS path loop check. */
3864 if (do_loop_check) {
3865 if (aspath_loop_check(attr->aspath, bgp->as)
3866 > peer->allowas_in[afi][safi]
3867 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3868 && aspath_loop_check(attr->aspath, bgp->confed_id)
3869 > peer->allowas_in[afi][safi])) {
b4d46cc9 3870 peer->stat_pfx_aspath_loop++;
d62a17ae 3871 reason = "as-path contains our own AS;";
3872 goto filtered;
3873 }
3874 }
aac9ef6c 3875
d62a17ae 3876 /* Route reflector originator ID check. */
3877 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3878 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3879 peer->stat_pfx_originator_loop++;
d62a17ae 3880 reason = "originator is us;";
3881 goto filtered;
3882 }
718e3744 3883
d62a17ae 3884 /* Route reflector cluster ID check. */
3885 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3886 peer->stat_pfx_cluster_loop++;
d62a17ae 3887 reason = "reflected from the same cluster;";
3888 goto filtered;
3889 }
718e3744 3890
d62a17ae 3891 /* Apply incoming filter. */
907707db 3892 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3893 peer->stat_pfx_filter++;
d62a17ae 3894 reason = "filter;";
3895 goto filtered;
3896 }
718e3744 3897
a8b72dc6
DA
3898 /* RFC 8212 to prevent route leaks.
3899 * This specification intends to improve this situation by requiring the
3900 * explicit configuration of both BGP Import and Export Policies for any
3901 * External BGP (EBGP) session such as customers, peers, or
3902 * confederation boundaries for all enabled address families. Through
3903 * codification of the aforementioned requirement, operators will
3904 * benefit from consistent behavior across different BGP
3905 * implementations.
3906 */
1d3fdccf 3907 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3908 if (!bgp_inbound_policy_exists(peer,
3909 &peer->filter[afi][safi])) {
3910 reason = "inbound policy missing";
b17826b7
DS
3911 if (monotime_since(&bgp->ebgprequirespolicywarning,
3912 NULL) > FIFTEENMINUTE2USEC ||
3913 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3914 zlog_warn(
3915 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3916 monotime(&bgp->ebgprequirespolicywarning);
3917 }
a8b72dc6
DA
3918 goto filtered;
3919 }
3920
fb29348a
DA
3921 /* draft-ietf-idr-deprecate-as-set-confed-set
3922 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3923 * Eventually, This document (if approved) updates RFC 4271
3924 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3925 * and obsoletes RFC 6472.
3926 */
7f972cd8 3927 if (peer->bgp->reject_as_sets)
fb29348a
DA
3928 if (aspath_check_as_sets(attr->aspath)) {
3929 reason =
3930 "as-path contains AS_SET or AS_CONFED_SET type;";
3931 goto filtered;
3932 }
3933
6f4f49b2 3934 new_attr = *attr;
d62a17ae 3935
3936 /* Apply incoming route-map.
3937 * NB: new_attr may now contain newly allocated values from route-map
3938 * "set"
3939 * commands, so we need bgp_attr_flush in the error paths, until we
3940 * intern
3941 * the attr (which takes over the memory references) */
907707db 3942 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3943 num_labels, dest)
3944 == RMAP_DENY) {
b4d46cc9 3945 peer->stat_pfx_filter++;
d62a17ae 3946 reason = "route-map;";
3947 bgp_attr_flush(&new_attr);
3948 goto filtered;
3949 }
718e3744 3950
05864da7 3951 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3952 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3953 /* remove from RIB previous entry */
3954 bgp_zebra_withdraw(p, pi, bgp, safi);
3955 }
3956
7f323236
DW
3957 if (peer->sort == BGP_PEER_EBGP) {
3958
2721dd61
DA
3959 /* rfc7999:
3960 * A BGP speaker receiving an announcement tagged with the
3961 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3962 * NO_EXPORT community as defined in RFC1997, or a
3963 * similar community, to prevent propagation of the
3964 * prefix outside the local AS. The community to prevent
3965 * propagation SHOULD be chosen according to the operator's
3966 * routing policy.
3967 */
9a706b42
DA
3968 if (bgp_attr_get_community(&new_attr) &&
3969 community_include(bgp_attr_get_community(&new_attr),
3970 COMMUNITY_BLACKHOLE))
aade37d7 3971 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3972
a4d82a8a
PZ
3973 /* If we receive the graceful-shutdown community from an eBGP
3974 * peer we must lower local-preference */
9a706b42
DA
3975 if (bgp_attr_get_community(&new_attr) &&
3976 community_include(bgp_attr_get_community(&new_attr),
3977 COMMUNITY_GSHUT)) {
7f323236
DW
3978 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3979 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3980
a4d82a8a
PZ
3981 /* If graceful-shutdown is configured then add the GSHUT
3982 * community to all paths received from eBGP peers */
637e5ba4 3983 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3984 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3985 }
3986
949b0f24 3987 if (pi) {
3988 pi_type = pi->type;
3989 pi_sub_type = pi->sub_type;
3990 }
3991
d62a17ae 3992 /* next hop check. */
a4d82a8a 3993 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3994 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3995 &new_attr, dest)) {
b4d46cc9 3996 peer->stat_pfx_nh_invalid++;
d62a17ae 3997 reason = "martian or self next-hop;";
3998 bgp_attr_flush(&new_attr);
3999 goto filtered;
4000 }
718e3744 4001
5c14a191 4002 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4003 peer->stat_pfx_nh_invalid++;
4e802e66 4004 reason = "self mac;";
4dbf2038 4005 bgp_attr_flush(&new_attr);
4e802e66
DS
4006 goto filtered;
4007 }
4008
5a78f2bc
EB
4009 if (bgp_check_role_applicability(afi, safi) &&
4010 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4011 reason = "failing otc validation";
4012 bgp_attr_flush(&new_attr);
4013 goto filtered;
4014 }
a1b773e2
DS
4015 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4016 * condition :
4017 * Suppress fib is enabled
4018 * BGP_OPT_NO_FIB is not enabled
4019 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4020 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4021 */
4022 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4023 && (sub_type == BGP_ROUTE_NORMAL)
4024 && (!bgp_option_check(BGP_OPT_NO_FIB))
4025 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4026 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4027
9cbd06e0
DA
4028 /* If maximum prefix count is configured and current prefix
4029 * count exeed it.
4030 */
4dbf2038
IR
4031 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4032 bgp_attr_flush(&new_attr);
9cbd06e0 4033 return -1;
4dbf2038
IR
4034 }
4035
4036 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4037
d62a17ae 4038 /* If the update is implicit withdraw. */
40381db7
DS
4039 if (pi) {
4040 pi->uptime = bgp_clock();
4041 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4042
9bcb3eef 4043 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4044
d62a17ae 4045 /* Same attribute comes in. */
40381db7 4046 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4047 && same_attr
d62a17ae 4048 && (!has_valid_label
40381db7 4049 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4050 num_labels * sizeof(mpls_label_t))
66ff6089 4051 == 0)) {
b4f7f45b
IR
4052 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4053 BGP_CONFIG_DAMPENING)
d62a17ae 4054 && peer->sort == BGP_PEER_EBGP
40381db7 4055 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4056 if (bgp_debug_update(peer, p, NULL, 1)) {
4057 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4058 afi, safi, prd, p, label,
4059 num_labels, addpath_id ? 1 : 0,
66ff6089 4060 addpath_id, evpn, pfx_buf,
a4d82a8a 4061 sizeof(pfx_buf));
f70c91dc 4062 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4063 pfx_buf);
4064 }
4065
9bcb3eef 4066 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4067 != BGP_DAMP_SUPPRESSED) {
40381db7 4068 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4069 safi);
9bcb3eef 4070 bgp_process(bgp, dest, afi, safi);
d62a17ae 4071 }
4072 } else /* Duplicate - odd */
4073 {
4074 if (bgp_debug_update(peer, p, NULL, 1)) {
4075 if (!peer->rcvd_attr_printed) {
4076 zlog_debug(
f70c91dc
DA
4077 "%pBP rcvd UPDATE w/ attr: %s",
4078 peer,
d62a17ae 4079 peer->rcvd_attr_str);
4080 peer->rcvd_attr_printed = 1;
4081 }
4082
4083 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4084 afi, safi, prd, p, label,
4085 num_labels, addpath_id ? 1 : 0,
66ff6089 4086 addpath_id, evpn, pfx_buf,
a4d82a8a 4087 sizeof(pfx_buf));
d62a17ae 4088 zlog_debug(
f70c91dc
DA
4089 "%pBP rcvd %s...duplicate ignored",
4090 peer, pfx_buf);
d62a17ae 4091 }
4092
4093 /* graceful restart STALE flag unset. */
40381db7 4094 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4095 bgp_path_info_unset_flag(
9bcb3eef
DS
4096 dest, pi, BGP_PATH_STALE);
4097 bgp_dest_set_defer_flag(dest, false);
4098 bgp_process(bgp, dest, afi, safi);
d62a17ae 4099 }
4100 }
4101
9bcb3eef 4102 bgp_dest_unlock_node(dest);
d62a17ae 4103 bgp_attr_unintern(&attr_new);
4104
4105 return 0;
4106 }
718e3744 4107
d62a17ae 4108 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4109 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4110 if (bgp_debug_update(peer, p, NULL, 1)) {
4111 bgp_debug_rdpfxpath2str(
a4d82a8a 4112 afi, safi, prd, p, label, num_labels,
66ff6089 4113 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4114 pfx_buf, sizeof(pfx_buf));
d62a17ae 4115 zlog_debug(
f70c91dc
DA
4116 "%pBP rcvd %s, flapped quicker than processing",
4117 peer, pfx_buf);
d62a17ae 4118 }
4119
9bcb3eef 4120 bgp_path_info_restore(dest, pi);
9146341f 4121
4122 /*
4123 * If the BGP_PATH_REMOVED flag is set, then EVPN
4124 * routes would have been unimported already when a
4125 * prior BGP withdraw processing happened. Such routes
4126 * need to be imported again, so flag accordingly.
4127 */
4128 force_evpn_import = true;
d62a17ae 4129 }
718e3744 4130
d62a17ae 4131 /* Received Logging. */
4132 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4133 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4134 num_labels, addpath_id ? 1 : 0,
66ff6089 4135 addpath_id, evpn, pfx_buf,
a4d82a8a 4136 sizeof(pfx_buf));
f70c91dc 4137 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4138 }
718e3744 4139
d62a17ae 4140 /* graceful restart STALE flag unset. */
f009ff26 4141 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4142 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4143 bgp_dest_set_defer_flag(dest, false);
f009ff26 4144 }
d62a17ae 4145
4146 /* The attribute is changed. */
9bcb3eef 4147 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4148
4149 /* implicit withdraw, decrement aggregate and pcount here.
4150 * only if update is accepted, they'll increment below.
4151 */
40381db7 4152 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4153
4154 /* Update bgp route dampening information. */
b4f7f45b 4155 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4156 && peer->sort == BGP_PEER_EBGP) {
4157 /* This is implicit withdraw so we should update
b4f7f45b
IR
4158 dampening
4159 information. */
40381db7 4160 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4161 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4162 }
49e5a4a0 4163#ifdef ENABLE_BGP_VNC
d62a17ae 4164 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4165 struct bgp_dest *pdest = NULL;
d62a17ae 4166 struct bgp_table *table = NULL;
4167
9bcb3eef
DS
4168 pdest = bgp_node_get(bgp->rib[afi][safi],
4169 (struct prefix *)prd);
4170 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4171 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4172
4173 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4174 bgp, prd, table, p, pi);
d62a17ae 4175 }
9bcb3eef 4176 bgp_dest_unlock_node(pdest);
d62a17ae 4177 }
4178 if ((afi == AFI_IP || afi == AFI_IP6)
4179 && (safi == SAFI_UNICAST)) {
40381db7 4180 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4181 /*
4182 * Implicit withdraw case.
4183 */
4184 ++vnc_implicit_withdraw;
40381db7
DS
4185 vnc_import_bgp_del_route(bgp, p, pi);
4186 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4187 }
4188 }
65efcfce 4189#endif
128ea8ab 4190
d62a17ae 4191 /* Special handling for EVPN update of an existing route. If the
4192 * extended community attribute has changed, we need to
4193 * un-import
4194 * the route using its existing extended community. It will be
4195 * subsequently processed for import with the new extended
4196 * community.
4197 */
6f8c9c11
PR
4198 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4199 && !same_attr) {
40381db7 4200 if ((pi->attr->flag
d62a17ae 4201 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4202 && (attr_new->flag
4203 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4204 int cmp;
4205
b53e67a3
DA
4206 cmp = ecommunity_cmp(
4207 bgp_attr_get_ecommunity(pi->attr),
4208 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4209 if (!cmp) {
4210 if (bgp_debug_update(peer, p, NULL, 1))
4211 zlog_debug(
4212 "Change in EXT-COMM, existing %s new %s",
4213 ecommunity_str(
b53e67a3
DA
4214 bgp_attr_get_ecommunity(
4215 pi->attr)),
d62a17ae 4216 ecommunity_str(
b53e67a3
DA
4217 bgp_attr_get_ecommunity(
4218 attr_new)));
6f8c9c11
PR
4219 if (safi == SAFI_EVPN)
4220 bgp_evpn_unimport_route(
4221 bgp, afi, safi, p, pi);
4222 else /* SAFI_MPLS_VPN */
4223 vpn_leak_to_vrf_withdraw(bgp,
4224 pi);
d62a17ae 4225 }
4226 }
4227 }
718e3744 4228
d62a17ae 4229 /* Update to new attribute. */
40381db7
DS
4230 bgp_attr_unintern(&pi->attr);
4231 pi->attr = attr_new;
d62a17ae 4232
4233 /* Update MPLS label */
4234 if (has_valid_label) {
40381db7 4235 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4236 if (extra->label != label) {
4237 memcpy(&extra->label, label,
dbd587da 4238 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4239 extra->num_labels = num_labels;
4240 }
b57ba6d2
MK
4241 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4242 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4243 }
718e3744 4244
e496b420
HS
4245 /* Update SRv6 SID */
4246 if (attr->srv6_l3vpn) {
4247 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4248 if (sid_diff(&extra->sid[0].sid,
4249 &attr->srv6_l3vpn->sid)) {
4250 sid_copy(&extra->sid[0].sid,
e496b420
HS
4251 &attr->srv6_l3vpn->sid);
4252 extra->num_sids = 1;
cc8f05df 4253
16f3db2d
RS
4254 extra->sid[0].loc_block_len = 0;
4255 extra->sid[0].loc_node_len = 0;
4256 extra->sid[0].func_len = 0;
4257 extra->sid[0].arg_len = 0;
ea7cd161
RS
4258 extra->sid[0].transposition_len = 0;
4259 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4260
4261 if (attr->srv6_l3vpn->loc_block_len != 0) {
4262 extra->sid[0].loc_block_len =
4263 attr->srv6_l3vpn->loc_block_len;
4264 extra->sid[0].loc_node_len =
4265 attr->srv6_l3vpn->loc_node_len;
4266 extra->sid[0].func_len =
4267 attr->srv6_l3vpn->func_len;
4268 extra->sid[0].arg_len =
4269 attr->srv6_l3vpn->arg_len;
ea7cd161 4270 extra->sid[0].transposition_len =
cc8f05df 4271 attr->srv6_l3vpn
ea7cd161
RS
4272 ->transposition_len;
4273 extra->sid[0].transposition_offset =
cc8f05df 4274 attr->srv6_l3vpn
ea7cd161
RS
4275 ->transposition_offset;
4276 }
e496b420
HS
4277 }
4278 } else if (attr->srv6_vpn) {
4279 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4280 if (sid_diff(&extra->sid[0].sid,
4281 &attr->srv6_vpn->sid)) {
4282 sid_copy(&extra->sid[0].sid,
4283 &attr->srv6_vpn->sid);
e496b420
HS
4284 extra->num_sids = 1;
4285 }
4286 }
4287
49e5a4a0 4288#ifdef ENABLE_BGP_VNC
d62a17ae 4289 if ((afi == AFI_IP || afi == AFI_IP6)
4290 && (safi == SAFI_UNICAST)) {
4291 if (vnc_implicit_withdraw) {
4292 /*
4293 * Add back the route with its new attributes
4294 * (e.g., nexthop).
4295 * The route is still selected, until the route
4296 * selection
4297 * queued by bgp_process actually runs. We have
4298 * to make this
4299 * update to the VNC side immediately to avoid
4300 * racing against
4301 * configuration changes (e.g., route-map
4302 * changes) which
4303 * trigger re-importation of the entire RIB.
4304 */
40381db7
DS
4305 vnc_import_bgp_add_route(bgp, p, pi);
4306 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4307 }
4308 }
65efcfce
LB
4309#endif
4310
d62a17ae 4311 /* Update bgp route dampening information. */
b4f7f45b 4312 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4313 && peer->sort == BGP_PEER_EBGP) {
4314 /* Now we do normal update dampening. */
9bcb3eef 4315 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4316 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4317 bgp_dest_unlock_node(dest);
d62a17ae 4318 return 0;
4319 }
4320 }
128ea8ab 4321
d62a17ae 4322 /* Nexthop reachability check - for unicast and
4323 * labeled-unicast.. */
7c312383
AD
4324 if (((afi == AFI_IP || afi == AFI_IP6)
4325 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4326 || (safi == SAFI_EVPN &&
4327 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4328 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4329 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4330 && !CHECK_FLAG(peer->flags,
4331 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4332 && !CHECK_FLAG(bgp->flags,
4333 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4334 connected = 1;
4335 else
4336 connected = 0;
4337
960035b2
PZ
4338 struct bgp *bgp_nexthop = bgp;
4339
40381db7
DS
4340 if (pi->extra && pi->extra->bgp_orig)
4341 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4342
7c312383
AD
4343 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4344
4345 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4346 safi, pi, NULL, connected,
4347 p)
a4d82a8a 4348 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4349 bgp_path_info_set_flag(dest, pi,
4350 BGP_PATH_VALID);
d62a17ae 4351 else {
4352 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4353 zlog_debug("%s(%pI4): NH unresolved",
4354 __func__,
4355 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4356 }
9bcb3eef 4357 bgp_path_info_unset_flag(dest, pi,
18ee8310 4358 BGP_PATH_VALID);
d62a17ae 4359 }
4360 } else
9bcb3eef 4361 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4362
49e5a4a0 4363#ifdef ENABLE_BGP_VNC
d62a17ae 4364 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4365 struct bgp_dest *pdest = NULL;
d62a17ae 4366 struct bgp_table *table = NULL;
4367
9bcb3eef
DS
4368 pdest = bgp_node_get(bgp->rib[afi][safi],
4369 (struct prefix *)prd);
4370 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4371 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4372
4373 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4374 bgp, prd, table, p, pi);
d62a17ae 4375 }
9bcb3eef 4376 bgp_dest_unlock_node(pdest);
d62a17ae 4377 }
4378#endif
718e3744 4379
d62a17ae 4380 /* If this is an EVPN route and some attribute has changed,
9146341f 4381 * or we are explicitly told to perform a route import, process
d62a17ae 4382 * route for import. If the extended community has changed, we
4383 * would
4384 * have done the un-import earlier and the import would result
4385 * in the
4386 * route getting injected into appropriate L2 VNIs. If it is
4387 * just
4388 * some other attribute change, the import will result in
4389 * updating
4390 * the attributes for the route in the VNI(s).
4391 */
9146341f 4392 if (safi == SAFI_EVPN &&
4393 (!same_attr || force_evpn_import) &&
7c312383 4394 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4395 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4396
4397 /* Process change. */
40381db7 4398 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4399
9bcb3eef
DS
4400 bgp_process(bgp, dest, afi, safi);
4401 bgp_dest_unlock_node(dest);
558d1fec 4402
ddb5b488
PZ
4403 if (SAFI_UNICAST == safi
4404 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4405 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4406
40381db7 4407 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4408 }
4409 if ((SAFI_MPLS_VPN == safi)
4410 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4411
a486300b 4412 leak_success = vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4413 }
4414
49e5a4a0 4415#ifdef ENABLE_BGP_VNC
d62a17ae 4416 if (SAFI_MPLS_VPN == safi) {
4417 mpls_label_t label_decoded = decode_label(label);
28070ee3 4418
d62a17ae 4419 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4420 type, sub_type, &label_decoded);
4421 }
4422 if (SAFI_ENCAP == safi) {
4423 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4424 type, sub_type, NULL);
4425 }
28070ee3 4426#endif
a486300b
PG
4427 if ((safi == SAFI_MPLS_VPN) &&
4428 !CHECK_FLAG(bgp->af_flags[afi][safi],
4429 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4430 !leak_success) {
4431 bgp_unlink_nexthop(pi);
4432 bgp_path_info_delete(dest, pi);
4433 }
d62a17ae 4434 return 0;
4435 } // End of implicit withdraw
718e3744 4436
d62a17ae 4437 /* Received Logging. */
4438 if (bgp_debug_update(peer, p, NULL, 1)) {
4439 if (!peer->rcvd_attr_printed) {
f70c91dc 4440 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4441 peer->rcvd_attr_str);
4442 peer->rcvd_attr_printed = 1;
4443 }
718e3744 4444
a4d82a8a 4445 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4446 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4447 pfx_buf, sizeof(pfx_buf));
f70c91dc 4448 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4449 }
718e3744 4450
d62a17ae 4451 /* Make new BGP info. */
9bcb3eef 4452 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4453
d62a17ae 4454 /* Update MPLS label */
4455 if (has_valid_label) {
18ee8310 4456 extra = bgp_path_info_extra_get(new);
8ba71050 4457 if (extra->label != label) {
dbd587da
QY
4458 memcpy(&extra->label, label,
4459 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4460 extra->num_labels = num_labels;
4461 }
b57ba6d2
MK
4462 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4463 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4464 }
718e3744 4465
e496b420
HS
4466 /* Update SRv6 SID */
4467 if (safi == SAFI_MPLS_VPN) {
4468 extra = bgp_path_info_extra_get(new);
4469 if (attr->srv6_l3vpn) {
16f3db2d 4470 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4471 extra->num_sids = 1;
cc8f05df 4472
16f3db2d
RS
4473 extra->sid[0].loc_block_len =
4474 attr->srv6_l3vpn->loc_block_len;
4475 extra->sid[0].loc_node_len =
4476 attr->srv6_l3vpn->loc_node_len;
4477 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4478 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4479 extra->sid[0].transposition_len =
4480 attr->srv6_l3vpn->transposition_len;
4481 extra->sid[0].transposition_offset =
4482 attr->srv6_l3vpn->transposition_offset;
e496b420 4483 } else if (attr->srv6_vpn) {
16f3db2d 4484 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4485 extra->num_sids = 1;
4486 }
4487 }
4488
d62a17ae 4489 /* Nexthop reachability check. */
7c312383
AD
4490 if (((afi == AFI_IP || afi == AFI_IP6)
4491 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4492 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4493 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4494 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4495 && !CHECK_FLAG(peer->flags,
4496 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4497 && !CHECK_FLAG(bgp->flags,
4498 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4499 connected = 1;
4500 else
4501 connected = 0;
4502
7c312383
AD
4503 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4504
4053e952 4505 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4506 connected, p)
a4d82a8a 4507 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4508 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4509 else {
4510 if (BGP_DEBUG(nht, NHT)) {
4511 char buf1[INET6_ADDRSTRLEN];
4512 inet_ntop(AF_INET,
4513 (const void *)&attr_new->nexthop,
4514 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4515 zlog_debug("%s(%s): NH unresolved", __func__,
4516 buf1);
d62a17ae 4517 }
9bcb3eef 4518 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4519 }
4520 } else
9bcb3eef 4521 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4522
d62a17ae 4523 /* Addpath ID */
4524 new->addpath_rx_id = addpath_id;
4525
4526 /* Increment prefix */
4527 bgp_aggregate_increment(bgp, p, new, afi, safi);
4528
4529 /* Register new BGP information. */
9bcb3eef 4530 bgp_path_info_add(dest, new);
d62a17ae 4531
4532 /* route_node_get lock */
9bcb3eef 4533 bgp_dest_unlock_node(dest);
558d1fec 4534
49e5a4a0 4535#ifdef ENABLE_BGP_VNC
d62a17ae 4536 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4537 struct bgp_dest *pdest = NULL;
d62a17ae 4538 struct bgp_table *table = NULL;
4539
9bcb3eef
DS
4540 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4541 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4542 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4543
4544 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4545 bgp, prd, table, p, new);
4546 }
9bcb3eef 4547 bgp_dest_unlock_node(pdest);
d62a17ae 4548 }
65efcfce
LB
4549#endif
4550
d62a17ae 4551 /* If this is an EVPN route, process for import. */
7c312383 4552 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4553 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4554
9bcb3eef 4555 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4556
d62a17ae 4557 /* Process change. */
9bcb3eef 4558 bgp_process(bgp, dest, afi, safi);
718e3744 4559
ddb5b488
PZ
4560 if (SAFI_UNICAST == safi
4561 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4562 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4563 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4564 }
4565 if ((SAFI_MPLS_VPN == safi)
4566 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
a486300b 4567 leak_success = vpn_leak_to_vrf_update(bgp, new);
ddb5b488 4568 }
49e5a4a0 4569#ifdef ENABLE_BGP_VNC
d62a17ae 4570 if (SAFI_MPLS_VPN == safi) {
4571 mpls_label_t label_decoded = decode_label(label);
28070ee3 4572
d62a17ae 4573 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4574 sub_type, &label_decoded);
4575 }
4576 if (SAFI_ENCAP == safi) {
4577 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4578 sub_type, NULL);
4579 }
28070ee3 4580#endif
a486300b
PG
4581 if ((safi == SAFI_MPLS_VPN) &&
4582 !CHECK_FLAG(bgp->af_flags[afi][safi],
4583 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4584 !leak_success) {
4585 bgp_unlink_nexthop(new);
4586 bgp_path_info_delete(dest, new);
4587 }
28070ee3 4588
d62a17ae 4589 return 0;
718e3744 4590
d62a17ae 4591/* This BGP update is filtered. Log the reason then update BGP
4592 entry. */
4593filtered:
9bcb3eef 4594 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4595
d62a17ae 4596 if (bgp_debug_update(peer, p, NULL, 1)) {
4597 if (!peer->rcvd_attr_printed) {
f70c91dc 4598 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4599 peer->rcvd_attr_str);
4600 peer->rcvd_attr_printed = 1;
4601 }
718e3744 4602
a4d82a8a 4603 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4604 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4605 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4606 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4607 peer, pfx_buf, reason);
d62a17ae 4608 }
128ea8ab 4609
40381db7 4610 if (pi) {
d62a17ae 4611 /* If this is an EVPN route, un-import it as it is now filtered.
4612 */
4613 if (safi == SAFI_EVPN)
40381db7 4614 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4615
ddb5b488
PZ
4616 if (SAFI_UNICAST == safi
4617 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4618 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4619
40381db7 4620 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4621 }
4622 if ((SAFI_MPLS_VPN == safi)
4623 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4624
40381db7 4625 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4626 }
4627
9bcb3eef 4628 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4629 }
4630
9bcb3eef 4631 bgp_dest_unlock_node(dest);
558d1fec 4632
49e5a4a0 4633#ifdef ENABLE_BGP_VNC
d62a17ae 4634 /*
4635 * Filtered update is treated as an implicit withdrawal (see
4636 * bgp_rib_remove()
4637 * a few lines above)
4638 */
4639 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4640 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4641 0);
4642 }
97736e32
PZ
4643#endif
4644
d62a17ae 4645 return 0;
718e3744 4646}
4647
26a3ffd6 4648int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4649 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4650 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4651 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4652{
d62a17ae 4653 struct bgp *bgp;
4654 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4655 struct bgp_dest *dest;
40381db7 4656 struct bgp_path_info *pi;
718e3744 4657
49e5a4a0 4658#ifdef ENABLE_BGP_VNC
d62a17ae 4659 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4660 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4661 0);
4662 }
28070ee3
PZ
4663#endif
4664
d62a17ae 4665 bgp = peer->bgp;
4666
4667 /* Lookup node. */
9bcb3eef 4668 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4669
4670 /* If peer is soft reconfiguration enabled. Record input packet for
4671 * further calculation.
4672 *
4673 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4674 * routes that are filtered. This tanks out Quagga RS pretty badly due
4675 * to
4676 * the iteration over all RS clients.
4677 * Since we need to remove the entry from adj_in anyway, do that first
4678 * and
4679 * if there was no entry, we don't need to do anything more.
4680 */
4681 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4682 && peer != bgp->peer_self)
9bcb3eef 4683 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4684 peer->stat_pfx_dup_withdraw++;
4685
d62a17ae 4686 if (bgp_debug_update(peer, p, NULL, 1)) {
4687 bgp_debug_rdpfxpath2str(
a4d82a8a 4688 afi, safi, prd, p, label, num_labels,
6c995628
AD
4689 addpath_id ? 1 : 0, addpath_id, NULL,
4690 pfx_buf, sizeof(pfx_buf));
d62a17ae 4691 zlog_debug(
4692 "%s withdrawing route %s not in adj-in",
4693 peer->host, pfx_buf);
4694 }
9bcb3eef 4695 bgp_dest_unlock_node(dest);
d62a17ae 4696 return 0;
4697 }
cd808e74 4698
d62a17ae 4699 /* Lookup withdrawn route. */
9bcb3eef 4700 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4701 if (pi->peer == peer && pi->type == type
4702 && pi->sub_type == sub_type
4703 && pi->addpath_rx_id == addpath_id)
d62a17ae 4704 break;
4705
4706 /* Logging. */
4707 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4708 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4709 addpath_id ? 1 : 0, addpath_id, NULL,
4710 pfx_buf, sizeof(pfx_buf));
f70c91dc 4711 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4712 pfx_buf);
4713 }
718e3744 4714
d62a17ae 4715 /* Withdraw specified route from routing table. */
40381db7 4716 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4717 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4718 if (SAFI_UNICAST == safi
4719 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4720 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4721 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4722 }
4723 if ((SAFI_MPLS_VPN == safi)
4724 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4725
40381db7 4726 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4727 }
4728 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4729 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4730 addpath_id ? 1 : 0, addpath_id, NULL,
4731 pfx_buf, sizeof(pfx_buf));
d62a17ae 4732 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4733 }
718e3744 4734
d62a17ae 4735 /* Unlock bgp_node_get() lock. */
9bcb3eef 4736 bgp_dest_unlock_node(dest);
d62a17ae 4737
4738 return 0;
718e3744 4739}
6b0655a2 4740
d62a17ae 4741void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4742 int withdraw)
718e3744 4743{
d62a17ae 4744 struct update_subgroup *subgrp;
4745 subgrp = peer_subgroup(peer, afi, safi);
4746 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4747}
6182d65b 4748
718e3744 4749
3f9c7369
DS
4750/*
4751 * bgp_stop_announce_route_timer
4752 */
d62a17ae 4753void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4754{
d62a17ae 4755 if (!paf->t_announce_route)
4756 return;
4757
c3aaa89a 4758 THREAD_OFF(paf->t_announce_route);
718e3744 4759}
6b0655a2 4760
3f9c7369
DS
4761/*
4762 * bgp_announce_route_timer_expired
4763 *
4764 * Callback that is invoked when the route announcement timer for a
4765 * peer_af expires.
4766 */
cc9f21da 4767static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4768{
d62a17ae 4769 struct peer_af *paf;
4770 struct peer *peer;
558d1fec 4771
d62a17ae 4772 paf = THREAD_ARG(t);
4773 peer = paf->peer;
718e3744 4774
feb17238 4775 if (!peer_established(peer))
cc9f21da 4776 return;
3f9c7369 4777
d62a17ae 4778 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4779 return;
3f9c7369 4780
d62a17ae 4781 peer_af_announce_route(paf, 1);
c5aec50b
MK
4782
4783 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4784 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4785}
4786
3f9c7369
DS
4787/*
4788 * bgp_announce_route
4789 *
4790 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4791 *
4792 * if force is true we will force an update even if the update
4793 * limiting code is attempted to kick in.
3f9c7369 4794 */
e1a32ec1 4795void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4796{
4797 struct peer_af *paf;
4798 struct update_subgroup *subgrp;
4799
4800 paf = peer_af_find(peer, afi, safi);
4801 if (!paf)
4802 return;
4803 subgrp = PAF_SUBGRP(paf);
4804
4805 /*
4806 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4807 * or a refresh has already been triggered.
4808 */
4809 if (!subgrp || paf->t_announce_route)
4810 return;
4811
e1a32ec1
DS
4812 if (force)
4813 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4814
d62a17ae 4815 /*
4816 * Start a timer to stagger/delay the announce. This serves
4817 * two purposes - announcement can potentially be combined for
4818 * multiple peers and the announcement doesn't happen in the
4819 * vty context.
4820 */
4821 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4822 (subgrp->peer_count == 1)
4823 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4824 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4825 &paf->t_announce_route);
3f9c7369
DS
4826}
4827
4828/*
4829 * Announce routes from all AF tables to a peer.
4830 *
4831 * This should ONLY be called when there is a need to refresh the
4832 * routes to the peer based on a policy change for this peer alone
4833 * or a route refresh request received from the peer.
4834 * The operation will result in splitting the peer from its existing
4835 * subgroups and putting it in new subgroups.
4836 */
d62a17ae 4837void bgp_announce_route_all(struct peer *peer)
718e3744 4838{
d62a17ae 4839 afi_t afi;
4840 safi_t safi;
4841
05c7a1cc 4842 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4843 bgp_announce_route(peer, afi, safi, false);
718e3744 4844}
6b0655a2 4845
46aeabed
LS
4846/* Flag or unflag bgp_dest to determine whether it should be treated by
4847 * bgp_soft_reconfig_table_task.
4848 * Flag if flag is true. Unflag if flag is false.
4849 */
4850static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4851{
4852 struct bgp_dest *dest;
4853 struct bgp_adj_in *ain;
4854
4855 if (!table)
4856 return;
4857
4858 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4859 for (ain = dest->adj_in; ain; ain = ain->next) {
4860 if (ain->peer != NULL)
4861 break;
4862 }
4863 if (flag && ain != NULL && ain->peer != NULL)
4864 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4865 else
4866 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4867 }
4868}
4869
4870static int bgp_soft_reconfig_table_update(struct peer *peer,
4871 struct bgp_dest *dest,
4872 struct bgp_adj_in *ain, afi_t afi,
4873 safi_t safi, struct prefix_rd *prd)
4874{
4875 struct bgp_path_info *pi;
4876 uint32_t num_labels = 0;
4877 mpls_label_t *label_pnt = NULL;
4878 struct bgp_route_evpn evpn;
4879
4880 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4881 if (pi->peer == peer)
4882 break;
4883
4884 if (pi && pi->extra)
4885 num_labels = pi->extra->num_labels;
4886 if (num_labels)
4887 label_pnt = &pi->extra->label[0];
4888 if (pi)
4889 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4890 sizeof(evpn));
4891 else
4892 memset(&evpn, 0, sizeof(evpn));
4893
4894 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4895 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4896 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4897 &evpn);
4898}
4899
d62a17ae 4900static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4901 struct bgp_table *table,
4902 struct prefix_rd *prd)
718e3744 4903{
d62a17ae 4904 int ret;
9bcb3eef 4905 struct bgp_dest *dest;
d62a17ae 4906 struct bgp_adj_in *ain;
718e3744 4907
d62a17ae 4908 if (!table)
4909 table = peer->bgp->rib[afi][safi];
718e3744 4910
9bcb3eef
DS
4911 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4912 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4913 if (ain->peer != peer)
4914 continue;
8692c506 4915
46aeabed
LS
4916 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4917 afi, safi, prd);
ea47320b
DL
4918
4919 if (ret < 0) {
9bcb3eef 4920 bgp_dest_unlock_node(dest);
ea47320b 4921 return;
d62a17ae 4922 }
4923 }
718e3744 4924}
4925
46aeabed
LS
4926/* Do soft reconfig table per bgp table.
4927 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4928 * when BGP_NODE_SOFT_RECONFIG is set,
4929 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4930 * Schedule a new thread to continue the job.
4931 * Without splitting the full job into several part,
4932 * vtysh waits for the job to finish before responding to a BGP command
4933 */
cc9f21da 4934static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4935{
4936 uint32_t iter, max_iter;
4937 int ret;
4938 struct bgp_dest *dest;
4939 struct bgp_adj_in *ain;
4940 struct peer *peer;
4941 struct bgp_table *table;
4942 struct prefix_rd *prd;
4943 struct listnode *node, *nnode;
4944
4945 table = THREAD_ARG(thread);
4946 prd = NULL;
4947
4948 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4949 if (table->soft_reconfig_init) {
4950 /* first call of the function with a new srta structure.
4951 * Don't do any treatment this time on nodes
4952 * in order vtysh to respond quickly
4953 */
4954 max_iter = 0;
4955 }
4956
4957 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4958 dest = bgp_route_next(dest)) {
4959 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4960 continue;
4961
4962 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4963
4964 for (ain = dest->adj_in; ain; ain = ain->next) {
4965 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4966 nnode, peer)) {
4967 if (ain->peer != peer)
4968 continue;
4969
4970 ret = bgp_soft_reconfig_table_update(
4971 peer, dest, ain, table->afi,
4972 table->safi, prd);
4973 iter++;
4974
4975 if (ret < 0) {
4976 bgp_dest_unlock_node(dest);
4977 listnode_delete(
4978 table->soft_reconfig_peers,
4979 peer);
4980 bgp_announce_route(peer, table->afi,
e1a32ec1 4981 table->safi, false);
46aeabed
LS
4982 if (list_isempty(
4983 table->soft_reconfig_peers)) {
4984 list_delete(
4985 &table->soft_reconfig_peers);
4986 bgp_soft_reconfig_table_flag(
4987 table, false);
cc9f21da 4988 return;
46aeabed
LS
4989 }
4990 }
4991 }
4992 }
4993 }
4994
4995 /* we're either starting the initial iteration,
4996 * or we're going to continue an ongoing iteration
4997 */
4998 if (dest || table->soft_reconfig_init) {
4999 table->soft_reconfig_init = false;
5000 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5001 table, 0, &table->soft_reconfig_thread);
cc9f21da 5002 return;
46aeabed
LS
5003 }
5004 /* we're done, clean up the background iteration context info and
5005 schedule route annoucement
5006 */
5007 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5008 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5009 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5010 }
5011
5012 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5013}
5014
5015
5016/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5017 * and peer.
5018 * - bgp cannot be NULL
5019 * - if table and peer are NULL, cancel all threads within the bgp instance
5020 * - if table is NULL and peer is not,
5021 * remove peer in all threads within the bgp instance
5022 * - if peer is NULL, cancel all threads matching table within the bgp instance
5023 */
5024void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5025 const struct bgp_table *table,
5026 const struct peer *peer)
5027{
5028 struct peer *npeer;
5029 struct listnode *node, *nnode;
5030 int afi, safi;
5031 struct bgp_table *ntable;
5032
5033 if (!bgp)
5034 return;
5035
5036 FOREACH_AFI_SAFI (afi, safi) {
5037 ntable = bgp->rib[afi][safi];
5038 if (!ntable)
5039 continue;
5040 if (table && table != ntable)
5041 continue;
5042
5043 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5044 npeer)) {
5045 if (peer && peer != npeer)
5046 continue;
5047 listnode_delete(ntable->soft_reconfig_peers, npeer);
5048 }
5049
5050 if (!ntable->soft_reconfig_peers
5051 || !list_isempty(ntable->soft_reconfig_peers))
5052 continue;
5053
5054 list_delete(&ntable->soft_reconfig_peers);
5055 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5056 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5057 }
5058}
5059
d62a17ae 5060void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5061{
9bcb3eef 5062 struct bgp_dest *dest;
d62a17ae 5063 struct bgp_table *table;
46aeabed
LS
5064 struct listnode *node, *nnode;
5065 struct peer *npeer;
5066 struct peer_af *paf;
718e3744 5067
feb17238 5068 if (!peer_established(peer))
d62a17ae 5069 return;
718e3744 5070
d62a17ae 5071 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5072 && (safi != SAFI_EVPN)) {
5073 table = peer->bgp->rib[afi][safi];
5074 if (!table)
5075 return;
5076
5077 table->soft_reconfig_init = true;
5078
5079 if (!table->soft_reconfig_peers)
5080 table->soft_reconfig_peers = list_new();
5081 npeer = NULL;
5082 /* add peer to the table soft_reconfig_peers if not already
5083 * there
5084 */
5085 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5086 npeer)) {
5087 if (peer == npeer)
5088 break;
5089 }
5090 if (peer != npeer)
5091 listnode_add(table->soft_reconfig_peers, peer);
5092
5093 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5094 * on table would start back at the beginning.
5095 */
5096 bgp_soft_reconfig_table_flag(table, true);
5097
5098 if (!table->soft_reconfig_thread)
5099 thread_add_event(bm->master,
5100 bgp_soft_reconfig_table_task, table, 0,
5101 &table->soft_reconfig_thread);
5102 /* Cancel bgp_announce_route_timer_expired threads.
5103 * bgp_announce_route_timer_expired threads have been scheduled
5104 * to announce routes as soon as the soft_reconfigure process
5105 * finishes.
5106 * In this case, soft_reconfigure is also scheduled by using
5107 * a thread but is planned after the
5108 * bgp_announce_route_timer_expired threads. It means that,
5109 * without cancelling the threads, the route announcement task
5110 * would run before the soft reconfiguration one. That would
5111 * useless and would block vtysh during several seconds. Route
5112 * announcements are rescheduled as soon as the soft_reconfigure
5113 * process finishes.
5114 */
5115 paf = peer_af_find(peer, afi, safi);
5116 if (paf)
5117 bgp_stop_announce_route_timer(paf);
5118 } else
9bcb3eef
DS
5119 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5120 dest = bgp_route_next(dest)) {
5121 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5122
b54892e0
DS
5123 if (table == NULL)
5124 continue;
8692c506 5125
9bcb3eef 5126 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5127 struct prefix_rd prd;
5128
5129 prd.family = AF_UNSPEC;
5130 prd.prefixlen = 64;
5131 memcpy(&prd.val, p->u.val, 8);
5132
5133 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5134 }
718e3744 5135}
6b0655a2 5136
228da428 5137
d62a17ae 5138struct bgp_clear_node_queue {
9bcb3eef 5139 struct bgp_dest *dest;
228da428
CC
5140};
5141
d62a17ae 5142static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5143{
d62a17ae 5144 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5145 struct bgp_dest *dest = cnq->dest;
d62a17ae 5146 struct peer *peer = wq->spec.data;
40381db7 5147 struct bgp_path_info *pi;
3103e8d2 5148 struct bgp *bgp;
9bcb3eef
DS
5149 afi_t afi = bgp_dest_table(dest)->afi;
5150 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5151
9bcb3eef 5152 assert(dest && peer);
3103e8d2 5153 bgp = peer->bgp;
d62a17ae 5154
5155 /* It is possible that we have multiple paths for a prefix from a peer
5156 * if that peer is using AddPath.
5157 */
9bcb3eef 5158 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5159 if (pi->peer != peer)
ea47320b
DL
5160 continue;
5161
5162 /* graceful restart STALE flag set. */
9af52ccf
DA
5163 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5164 && peer->nsf[afi][safi])
5165 || CHECK_FLAG(peer->af_sflags[afi][safi],
5166 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5167 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5168 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5169 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5170 else {
5171 /* If this is an EVPN route, process for
5172 * un-import. */
5173 if (safi == SAFI_EVPN)
9bcb3eef
DS
5174 bgp_evpn_unimport_route(
5175 bgp, afi, safi,
5176 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5177 /* Handle withdraw for VRF route-leaking and L3VPN */
5178 if (SAFI_UNICAST == safi
5179 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5180 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5181 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5182 bgp, pi);
960035b2 5183 }
3103e8d2 5184 if (SAFI_MPLS_VPN == safi &&
960035b2 5185 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5186 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5187 }
3103e8d2 5188
9bcb3eef 5189 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5190 }
ea47320b 5191 }
d62a17ae 5192 return WQ_SUCCESS;
200df115 5193}
5194
d62a17ae 5195static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5196{
d62a17ae 5197 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5198 struct bgp_dest *dest = cnq->dest;
5199 struct bgp_table *table = bgp_dest_table(dest);
228da428 5200
9bcb3eef 5201 bgp_dest_unlock_node(dest);
d62a17ae 5202 bgp_table_unlock(table);
5203 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5204}
5205
d62a17ae 5206static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5207{
d62a17ae 5208 struct peer *peer = wq->spec.data;
64e580a7 5209
d62a17ae 5210 /* Tickle FSM to start moving again */
5211 BGP_EVENT_ADD(peer, Clearing_Completed);
5212
5213 peer_unlock(peer); /* bgp_clear_route */
200df115 5214}
718e3744 5215
d62a17ae 5216static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5217{
d62a17ae 5218 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5219
5220 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5221#undef CLEAR_QUEUE_NAME_LEN
5222
0ce1ca80 5223 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5224 peer->clear_node_queue->spec.hold = 10;
5225 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5226 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5227 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5228 peer->clear_node_queue->spec.max_retries = 0;
5229
5230 /* we only 'lock' this peer reference when the queue is actually active
5231 */
5232 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5233}
5234
d62a17ae 5235static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5236 struct bgp_table *table)
65ca75e0 5237{
9bcb3eef 5238 struct bgp_dest *dest;
b6c386bb 5239 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5240
d62a17ae 5241 if (!table)
5242 table = peer->bgp->rib[afi][safi];
dc83d712 5243
d62a17ae 5244 /* If still no table => afi/safi isn't configured at all or smth. */
5245 if (!table)
5246 return;
dc83d712 5247
9bcb3eef 5248 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5249 struct bgp_path_info *pi, *next;
d62a17ae 5250 struct bgp_adj_in *ain;
5251 struct bgp_adj_in *ain_next;
5252
5253 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5254 * queued for every clearing peer, regardless of whether it is
5255 * relevant to the peer at hand.
5256 *
5257 * Overview: There are 3 different indices which need to be
5258 * scrubbed, potentially, when a peer is removed:
5259 *
5260 * 1 peer's routes visible via the RIB (ie accepted routes)
5261 * 2 peer's routes visible by the (optional) peer's adj-in index
5262 * 3 other routes visible by the peer's adj-out index
5263 *
5264 * 3 there is no hurry in scrubbing, once the struct peer is
5265 * removed from bgp->peer, we could just GC such deleted peer's
5266 * adj-outs at our leisure.
5267 *
5268 * 1 and 2 must be 'scrubbed' in some way, at least made
5269 * invisible via RIB index before peer session is allowed to be
5270 * brought back up. So one needs to know when such a 'search' is
5271 * complete.
5272 *
5273 * Ideally:
5274 *
5275 * - there'd be a single global queue or a single RIB walker
5276 * - rather than tracking which route_nodes still need to be
5277 * examined on a peer basis, we'd track which peers still
5278 * aren't cleared
5279 *
5280 * Given that our per-peer prefix-counts now should be reliable,
5281 * this may actually be achievable. It doesn't seem to be a huge
5282 * problem at this time,
5283 *
5284 * It is possible that we have multiple paths for a prefix from
5285 * a peer
5286 * if that peer is using AddPath.
5287 */
9bcb3eef 5288 ain = dest->adj_in;
d62a17ae 5289 while (ain) {
5290 ain_next = ain->next;
5291
6a840fd9 5292 if (ain->peer == peer)
9bcb3eef 5293 bgp_adj_in_remove(dest, ain);
d62a17ae 5294
5295 ain = ain_next;
5296 }
5297
9bcb3eef 5298 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5299 next = pi->next;
5300 if (pi->peer != peer)
d62a17ae 5301 continue;
5302
5303 if (force)
9bcb3eef 5304 bgp_path_info_reap(dest, pi);
d62a17ae 5305 else {
5306 struct bgp_clear_node_queue *cnq;
5307
5308 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5309 bgp_table_lock(bgp_dest_table(dest));
5310 bgp_dest_lock_node(dest);
d62a17ae 5311 cnq = XCALLOC(
5312 MTYPE_BGP_CLEAR_NODE_QUEUE,
5313 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5314 cnq->dest = dest;
d62a17ae 5315 work_queue_add(peer->clear_node_queue, cnq);
5316 break;
5317 }
5318 }
5319 }
5320 return;
5321}
5322
5323void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5324{
9bcb3eef 5325 struct bgp_dest *dest;
d62a17ae 5326 struct bgp_table *table;
5327
5328 if (peer->clear_node_queue == NULL)
5329 bgp_clear_node_queue_init(peer);
5330
5331 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5332 * Idle until it receives a Clearing_Completed event. This protects
5333 * against peers which flap faster than we can we clear, which could
5334 * lead to:
5335 *
5336 * a) race with routes from the new session being installed before
5337 * clear_route_node visits the node (to delete the route of that
5338 * peer)
5339 * b) resource exhaustion, clear_route_node likely leads to an entry
5340 * on the process_main queue. Fast-flapping could cause that queue
5341 * to grow and grow.
5342 */
5343
5344 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5345 * the unlock will happen upon work-queue completion; other wise, the
5346 * unlock happens at the end of this function.
5347 */
5348 if (!peer->clear_node_queue->thread)
5349 peer_lock(peer);
5350
5351 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5352 bgp_clear_route_table(peer, afi, safi, NULL);
5353 else
9bcb3eef
DS
5354 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5355 dest = bgp_route_next(dest)) {
5356 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5357 if (!table)
5358 continue;
5359
5360 bgp_clear_route_table(peer, afi, safi, table);
5361 }
d62a17ae 5362
5363 /* unlock if no nodes got added to the clear-node-queue. */
5364 if (!peer->clear_node_queue->thread)
5365 peer_unlock(peer);
718e3744 5366}
d62a17ae 5367
5368void bgp_clear_route_all(struct peer *peer)
718e3744 5369{
d62a17ae 5370 afi_t afi;
5371 safi_t safi;
718e3744 5372
05c7a1cc
QY
5373 FOREACH_AFI_SAFI (afi, safi)
5374 bgp_clear_route(peer, afi, safi);
65efcfce 5375
49e5a4a0 5376#ifdef ENABLE_BGP_VNC
d62a17ae 5377 rfapiProcessPeerDown(peer);
65efcfce 5378#endif
718e3744 5379}
5380
d62a17ae 5381void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5382{
d62a17ae 5383 struct bgp_table *table;
9bcb3eef 5384 struct bgp_dest *dest;
d62a17ae 5385 struct bgp_adj_in *ain;
5386 struct bgp_adj_in *ain_next;
718e3744 5387
d62a17ae 5388 table = peer->bgp->rib[afi][safi];
718e3744 5389
d62a17ae 5390 /* It is possible that we have multiple paths for a prefix from a peer
5391 * if that peer is using AddPath.
5392 */
9bcb3eef
DS
5393 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5394 ain = dest->adj_in;
43143c8f 5395
d62a17ae 5396 while (ain) {
5397 ain_next = ain->next;
43143c8f 5398
6a840fd9 5399 if (ain->peer == peer)
9bcb3eef 5400 bgp_adj_in_remove(dest, ain);
43143c8f 5401
d62a17ae 5402 ain = ain_next;
5403 }
5404 }
718e3744 5405}
93406d87 5406
1479ed2f
DA
5407/* If any of the routes from the peer have been marked with the NO_LLGR
5408 * community, either as sent by the peer, or as the result of a configured
5409 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5410 * operation of [RFC4271].
5411 */
d62a17ae 5412void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5413{
9bcb3eef 5414 struct bgp_dest *dest;
40381db7 5415 struct bgp_path_info *pi;
d62a17ae 5416 struct bgp_table *table;
5417
9af52ccf 5418 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5419 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5420 dest = bgp_route_next(dest)) {
5421 struct bgp_dest *rm;
d62a17ae 5422
5423 /* look for neighbor in tables */
9bcb3eef 5424 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5425 if (!table)
ea47320b
DL
5426 continue;
5427
5428 for (rm = bgp_table_top(table); rm;
5429 rm = bgp_route_next(rm))
9bcb3eef 5430 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5431 pi = pi->next) {
40381db7 5432 if (pi->peer != peer)
ea47320b 5433 continue;
1479ed2f
DA
5434 if (CHECK_FLAG(
5435 peer->af_sflags[afi][safi],
5436 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5437 bgp_attr_get_community(pi->attr) &&
1479ed2f 5438 !community_include(
9a706b42
DA
5439 bgp_attr_get_community(
5440 pi->attr),
1479ed2f 5441 COMMUNITY_NO_LLGR))
e3015d91 5442 continue;
40381db7 5443 if (!CHECK_FLAG(pi->flags,
1defdda8 5444 BGP_PATH_STALE))
e3015d91 5445 continue;
ea47320b 5446
641065d4
KM
5447 /*
5448 * If this is VRF leaked route
5449 * process for withdraw.
5450 */
5451 if (pi->sub_type ==
5452 BGP_ROUTE_IMPORTED &&
5453 peer->bgp->inst_type ==
5454 BGP_INSTANCE_TYPE_DEFAULT)
5455 vpn_leak_to_vrf_withdraw(
5456 peer->bgp, pi);
5457
40381db7 5458 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5459 break;
5460 }
d62a17ae 5461 }
5462 } else {
9bcb3eef
DS
5463 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5464 dest = bgp_route_next(dest))
5465 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5466 pi = pi->next) {
40381db7 5467 if (pi->peer != peer)
ea47320b 5468 continue;
1479ed2f
DA
5469 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5470 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5471 bgp_attr_get_community(pi->attr) &&
5472 !community_include(
5473 bgp_attr_get_community(pi->attr),
5474 COMMUNITY_NO_LLGR))
e3015d91 5475 continue;
40381db7 5476 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5477 continue;
641065d4
KM
5478 if (safi == SAFI_UNICAST &&
5479 (peer->bgp->inst_type ==
5480 BGP_INSTANCE_TYPE_VRF ||
5481 peer->bgp->inst_type ==
5482 BGP_INSTANCE_TYPE_DEFAULT))
5483 vpn_leak_from_vrf_withdraw(
5484 bgp_get_default(), peer->bgp,
5485 pi);
5486
9bcb3eef 5487 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5488 break;
5489 }
d62a17ae 5490 }
93406d87 5491}
6b0655a2 5492
9af52ccf
DA
5493void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5494{
5495 struct bgp_dest *dest, *ndest;
5496 struct bgp_path_info *pi;
5497 struct bgp_table *table;
5498
5499 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5500 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5501 dest = bgp_route_next(dest)) {
5502 table = bgp_dest_get_bgp_table_info(dest);
5503 if (!table)
5504 continue;
5505
5506 for (ndest = bgp_table_top(table); ndest;
5507 ndest = bgp_route_next(ndest)) {
5508 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5509 pi = pi->next) {
5510 if (pi->peer != peer)
5511 continue;
5512
5513 if ((CHECK_FLAG(
5514 peer->af_sflags[afi][safi],
5515 PEER_STATUS_ENHANCED_REFRESH))
5516 && !CHECK_FLAG(pi->flags,
5517 BGP_PATH_STALE)
5518 && !CHECK_FLAG(
5519 pi->flags,
5520 BGP_PATH_UNUSEABLE)) {
5521 if (bgp_debug_neighbor_events(
5522 peer))
5523 zlog_debug(
5524 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5525 peer->host,
5526 afi2str(afi),
5527 safi2str(safi),
5528 bgp_dest_get_prefix(
5529 ndest));
5530
5531 bgp_path_info_set_flag(
5532 ndest, pi,
5533 BGP_PATH_STALE);
5534 }
5535 }
5536 }
5537 }
5538 } else {
5539 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5540 dest = bgp_route_next(dest)) {
5541 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5542 pi = pi->next) {
5543 if (pi->peer != peer)
5544 continue;
5545
5546 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5547 PEER_STATUS_ENHANCED_REFRESH))
5548 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5549 && !CHECK_FLAG(pi->flags,
5550 BGP_PATH_UNUSEABLE)) {
5551 if (bgp_debug_neighbor_events(peer))
5552 zlog_debug(
5553 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5554 peer->host,
5555 afi2str(afi),
5556 safi2str(safi),
5557 bgp_dest_get_prefix(
5558 dest));
5559
5560 bgp_path_info_set_flag(dest, pi,
5561 BGP_PATH_STALE);
5562 }
5563 }
5564 }
5565 }
5566}
5567
3dc339cd 5568bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5569{
e0df4c04 5570 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5571 return true;
e0df4c04 5572
9dac9fc8
DA
5573 if (peer->sort == BGP_PEER_EBGP
5574 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5575 || FILTER_LIST_OUT_NAME(filter)
5576 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5577 return true;
5578 return false;
9dac9fc8
DA
5579}
5580
3dc339cd 5581bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5582{
e0df4c04 5583 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5584 return true;
e0df4c04 5585
9dac9fc8
DA
5586 if (peer->sort == BGP_PEER_EBGP
5587 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5588 || FILTER_LIST_IN_NAME(filter)
5589 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5590 return true;
5591 return false;
9dac9fc8
DA
5592}
5593
568e10ca 5594static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5595 safi_t safi)
bb86c601 5596{
9bcb3eef 5597 struct bgp_dest *dest;
40381db7 5598 struct bgp_path_info *pi;
4b7e6066 5599 struct bgp_path_info *next;
bb86c601 5600
9bcb3eef
DS
5601 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5602 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5603 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5604
40381db7 5605 next = pi->next;
1b7bb747
CS
5606
5607 /* Unimport EVPN routes from VRFs */
5608 if (safi == SAFI_EVPN)
5609 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5610 SAFI_EVPN, p, pi);
1b7bb747 5611
40381db7
DS
5612 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5613 && pi->type == ZEBRA_ROUTE_BGP
5614 && (pi->sub_type == BGP_ROUTE_NORMAL
5615 || pi->sub_type == BGP_ROUTE_AGGREGATE
5616 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5617
d62a17ae 5618 if (bgp_fibupd_safi(safi))
b54892e0 5619 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5620 }
9514b37d 5621
9bcb3eef 5622 bgp_path_info_reap(dest, pi);
d62a17ae 5623 }
bb86c601
LB
5624}
5625
718e3744 5626/* Delete all kernel routes. */
d62a17ae 5627void bgp_cleanup_routes(struct bgp *bgp)
5628{
5629 afi_t afi;
9bcb3eef 5630 struct bgp_dest *dest;
67009e22 5631 struct bgp_table *table;
d62a17ae 5632
5633 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5634 if (afi == AFI_L2VPN)
5635 continue;
568e10ca 5636 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5637 SAFI_UNICAST);
d62a17ae 5638 /*
5639 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5640 */
5641 if (afi != AFI_L2VPN) {
5642 safi_t safi;
5643 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5644 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5645 dest = bgp_route_next(dest)) {
5646 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5647 if (table != NULL) {
5648 bgp_cleanup_table(bgp, table, safi);
5649 bgp_table_finish(&table);
9bcb3eef
DS
5650 bgp_dest_set_bgp_table_info(dest, NULL);
5651 bgp_dest_unlock_node(dest);
d62a17ae 5652 }
5653 }
5654 safi = SAFI_ENCAP;
9bcb3eef
DS
5655 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5656 dest = bgp_route_next(dest)) {
5657 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5658 if (table != NULL) {
5659 bgp_cleanup_table(bgp, table, safi);
5660 bgp_table_finish(&table);
9bcb3eef
DS
5661 bgp_dest_set_bgp_table_info(dest, NULL);
5662 bgp_dest_unlock_node(dest);
d62a17ae 5663 }
5664 }
5665 }
5666 }
9bcb3eef
DS
5667 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5668 dest = bgp_route_next(dest)) {
5669 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5670 if (table != NULL) {
5671 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5672 bgp_table_finish(&table);
9bcb3eef
DS
5673 bgp_dest_set_bgp_table_info(dest, NULL);
5674 bgp_dest_unlock_node(dest);
d62a17ae 5675 }
bb86c601 5676 }
718e3744 5677}
5678
d62a17ae 5679void bgp_reset(void)
718e3744 5680{
d62a17ae 5681 vty_reset();
5682 bgp_zclient_reset();
5683 access_list_reset();
5684 prefix_list_reset();
718e3744 5685}
6b0655a2 5686
be92fc9f 5687bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5688{
d62a17ae 5689 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5690 && CHECK_FLAG(peer->af_cap[afi][safi],
5691 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5692}
5693
718e3744 5694/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5695 value. */
d62a17ae 5696int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5697 struct bgp_nlri *packet)
5698{
d7c0a89a
QY
5699 uint8_t *pnt;
5700 uint8_t *lim;
d62a17ae 5701 struct prefix p;
5702 int psize;
5703 int ret;
5704 afi_t afi;
5705 safi_t safi;
be92fc9f 5706 bool addpath_capable;
d7c0a89a 5707 uint32_t addpath_id;
d62a17ae 5708
d62a17ae 5709 pnt = packet->nlri;
5710 lim = pnt + packet->length;
5711 afi = packet->afi;
5712 safi = packet->safi;
5713 addpath_id = 0;
be92fc9f 5714 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5715
5716 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5717 syntactic validity. If the field is syntactically incorrect,
5718 then the Error Subcode is set to Invalid Network Field. */
5719 for (; pnt < lim; pnt += psize) {
5720 /* Clear prefix structure. */
6006b807 5721 memset(&p, 0, sizeof(p));
d62a17ae 5722
be92fc9f 5723 if (addpath_capable) {
d62a17ae 5724
5725 /* When packet overflow occurs return immediately. */
761ed665 5726 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5727 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5728
a3a850a1 5729 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5730 addpath_id = ntohl(addpath_id);
d62a17ae 5731 pnt += BGP_ADDPATH_ID_LEN;
5732 }
718e3744 5733
d62a17ae 5734 /* Fetch prefix length. */
5735 p.prefixlen = *pnt++;
5736 /* afi/safi validity already verified by caller,
5737 * bgp_update_receive */
5738 p.family = afi2family(afi);
5739
5740 /* Prefix length check. */
5741 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5742 flog_err(
e50f7cfd 5743 EC_BGP_UPDATE_RCV,
14454c9f 5744 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5745 peer->host, p.prefixlen, packet->afi);
513386b5 5746 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5747 }
6b0655a2 5748
d62a17ae 5749 /* Packet size overflow check. */
5750 psize = PSIZE(p.prefixlen);
5751
5752 /* When packet overflow occur return immediately. */
5753 if (pnt + psize > lim) {
af4c2728 5754 flog_err(
e50f7cfd 5755 EC_BGP_UPDATE_RCV,
d62a17ae 5756 "%s [Error] Update packet error (prefix length %d overflows packet)",
5757 peer->host, p.prefixlen);
513386b5 5758 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5759 }
5760
5761 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5762 * prefix for the v4 and v6 afi's and unicast/multicast */
5763 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5764 flog_err(
e50f7cfd 5765 EC_BGP_UPDATE_RCV,
d62a17ae 5766 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5767 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5768 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5769 }
5770
5771 /* Fetch prefix from NLRI packet. */
a85297a7 5772 memcpy(p.u.val, pnt, psize);
d62a17ae 5773
5774 /* Check address. */
5775 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5776 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5777 /* From RFC4271 Section 6.3:
5778 *
5779 * If a prefix in the NLRI field is semantically
5780 * incorrect
5781 * (e.g., an unexpected multicast IP address),
5782 * an error SHOULD
5783 * be logged locally, and the prefix SHOULD be
5784 * ignored.
a4d82a8a 5785 */
af4c2728 5786 flog_err(
e50f7cfd 5787 EC_BGP_UPDATE_RCV,
23d0a753
DA
5788 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5789 peer->host, &p.u.prefix4);
d62a17ae 5790 continue;
5791 }
5792 }
5793
5794 /* Check address. */
5795 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5796 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5797 flog_err(
e50f7cfd 5798 EC_BGP_UPDATE_RCV,
c0d72166
DS
5799 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5800 peer->host, &p.u.prefix6);
d62a17ae 5801
5802 continue;
5803 }
5804 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5805 flog_err(
e50f7cfd 5806 EC_BGP_UPDATE_RCV,
c0d72166
DS
5807 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5808 peer->host, &p.u.prefix6);
d62a17ae 5809
5810 continue;
5811 }
5812 }
5813
5814 /* Normal process. */
5815 if (attr)
5816 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5817 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5818 NULL, NULL, 0, 0, NULL);
d62a17ae 5819 else
5820 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5821 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5822 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5823 NULL);
d62a17ae 5824
513386b5
DA
5825 /* Do not send BGP notification twice when maximum-prefix count
5826 * overflow. */
5827 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5828 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5829
5830 /* Address family configuration mismatch. */
d62a17ae 5831 if (ret < 0)
513386b5 5832 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5833 }
5834
5835 /* Packet length consistency check. */
5836 if (pnt != lim) {
af4c2728 5837 flog_err(
e50f7cfd 5838 EC_BGP_UPDATE_RCV,
d62a17ae 5839 "%s [Error] Update packet error (prefix length mismatch with total length)",
5840 peer->host);
513386b5 5841 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5842 }
6b0655a2 5843
513386b5 5844 return BGP_NLRI_PARSE_OK;
718e3744 5845}
5846
d62a17ae 5847static struct bgp_static *bgp_static_new(void)
718e3744 5848{
d62a17ae 5849 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5850}
5851
d62a17ae 5852static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5853{
0a22ddfb 5854 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5855 route_map_counter_decrement(bgp_static->rmap.map);
5856
0a22ddfb 5857 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5858 XFREE(MTYPE_BGP_STATIC, bgp_static);
5859}
5860
5f040085 5861void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5862 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5863{
9bcb3eef 5864 struct bgp_dest *dest;
40381db7 5865 struct bgp_path_info *pi;
4b7e6066 5866 struct bgp_path_info *new;
40381db7 5867 struct bgp_path_info rmap_path;
d62a17ae 5868 struct attr attr;
5869 struct attr *attr_new;
b68885f9 5870 route_map_result_t ret;
49e5a4a0 5871#ifdef ENABLE_BGP_VNC
d62a17ae 5872 int vnc_implicit_withdraw = 0;
65efcfce 5873#endif
fee0f4c6 5874
d62a17ae 5875 assert(bgp_static);
dd8103a9 5876
9bcb3eef 5877 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5878
0f05ea43 5879 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5880
d62a17ae 5881 attr.nexthop = bgp_static->igpnexthop;
5882 attr.med = bgp_static->igpmetric;
5883 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5884
d62a17ae 5885 if (bgp_static->atomic)
5886 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5887
d62a17ae 5888 /* Store label index, if required. */
5889 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5890 attr.label_index = bgp_static->label_index;
5891 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5892 }
718e3744 5893
d62a17ae 5894 /* Apply route-map. */
5895 if (bgp_static->rmap.name) {
5896 struct attr attr_tmp = attr;
80ced710 5897
6006b807 5898 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5899 rmap_path.peer = bgp->peer_self;
5900 rmap_path.attr = &attr_tmp;
fee0f4c6 5901
d62a17ae 5902 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5903
1782514f 5904 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5905
d62a17ae 5906 bgp->peer_self->rmap_type = 0;
718e3744 5907
d62a17ae 5908 if (ret == RMAP_DENYMATCH) {
5909 /* Free uninterned attribute. */
5910 bgp_attr_flush(&attr_tmp);
718e3744 5911
d62a17ae 5912 /* Unintern original. */
5913 aspath_unintern(&attr.aspath);
5914 bgp_static_withdraw(bgp, p, afi, safi);
5915 return;
5916 }
7f323236 5917
637e5ba4 5918 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5919 bgp_attr_add_gshut_community(&attr_tmp);
5920
d62a17ae 5921 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5922 } else {
5923
637e5ba4 5924 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5925 bgp_attr_add_gshut_community(&attr);
5926
d62a17ae 5927 attr_new = bgp_attr_intern(&attr);
7f323236 5928 }
718e3744 5929
9bcb3eef 5930 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5931 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5932 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5933 break;
5934
40381db7
DS
5935 if (pi) {
5936 if (attrhash_cmp(pi->attr, attr_new)
5937 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5938 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5939 bgp_dest_unlock_node(dest);
d62a17ae 5940 bgp_attr_unintern(&attr_new);
5941 aspath_unintern(&attr.aspath);
5942 return;
5943 } else {
5944 /* The attribute is changed. */
9bcb3eef 5945 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5946
5947 /* Rewrite BGP route information. */
40381db7 5948 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5949 bgp_path_info_restore(dest, pi);
d62a17ae 5950 else
40381db7 5951 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5952#ifdef ENABLE_BGP_VNC
d62a17ae 5953 if ((afi == AFI_IP || afi == AFI_IP6)
5954 && (safi == SAFI_UNICAST)) {
40381db7 5955 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5956 /*
5957 * Implicit withdraw case.
40381db7 5958 * We have to do this before pi is
d62a17ae 5959 * changed
5960 */
5961 ++vnc_implicit_withdraw;
40381db7 5962 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5963 vnc_import_bgp_exterior_del_route(
40381db7 5964 bgp, p, pi);
d62a17ae 5965 }
5966 }
65efcfce 5967#endif
40381db7
DS
5968 bgp_attr_unintern(&pi->attr);
5969 pi->attr = attr_new;
5970 pi->uptime = bgp_clock();
49e5a4a0 5971#ifdef ENABLE_BGP_VNC
d62a17ae 5972 if ((afi == AFI_IP || afi == AFI_IP6)
5973 && (safi == SAFI_UNICAST)) {
5974 if (vnc_implicit_withdraw) {
40381db7 5975 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5976 vnc_import_bgp_exterior_add_route(
40381db7 5977 bgp, p, pi);
d62a17ae 5978 }
5979 }
65efcfce 5980#endif
718e3744 5981
d62a17ae 5982 /* Nexthop reachability check. */
892fedb6 5983 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5984 && (safi == SAFI_UNICAST
5985 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5986
5987 struct bgp *bgp_nexthop = bgp;
5988
40381db7
DS
5989 if (pi->extra && pi->extra->bgp_orig)
5990 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5991
5992 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5993 afi, safi, pi, NULL,
654a5978 5994 0, p))
9bcb3eef 5995 bgp_path_info_set_flag(dest, pi,
18ee8310 5996 BGP_PATH_VALID);
d62a17ae 5997 else {
5998 if (BGP_DEBUG(nht, NHT)) {
5999 char buf1[INET6_ADDRSTRLEN];
6000 inet_ntop(p->family,
6001 &p->u.prefix, buf1,
6002 INET6_ADDRSTRLEN);
6003 zlog_debug(
6004 "%s(%s): Route not in table, not advertising",
15569c58 6005 __func__, buf1);
d62a17ae 6006 }
18ee8310 6007 bgp_path_info_unset_flag(
9bcb3eef 6008 dest, pi, BGP_PATH_VALID);
d62a17ae 6009 }
6010 } else {
6011 /* Delete the NHT structure if any, if we're
6012 * toggling between
6013 * enabling/disabling import check. We
6014 * deregister the route
6015 * from NHT to avoid overloading NHT and the
6016 * process interaction
6017 */
40381db7 6018 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6019 bgp_path_info_set_flag(dest, pi,
6020 BGP_PATH_VALID);
d62a17ae 6021 }
6022 /* Process change. */
40381db7 6023 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6024 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6025
6026 if (SAFI_UNICAST == safi
6027 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6028 || bgp->inst_type
6029 == BGP_INSTANCE_TYPE_DEFAULT)) {
6030 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6031 pi);
ddb5b488
PZ
6032 }
6033
9bcb3eef 6034 bgp_dest_unlock_node(dest);
d62a17ae 6035 aspath_unintern(&attr.aspath);
6036 return;
6037 }
718e3744 6038 }
718e3744 6039
d62a17ae 6040 /* Make new BGP info. */
6041 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6042 attr_new, dest);
d62a17ae 6043 /* Nexthop reachability check. */
892fedb6 6044 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6045 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6046 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6047 p))
9bcb3eef 6048 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6049 else {
6050 if (BGP_DEBUG(nht, NHT)) {
6051 char buf1[INET6_ADDRSTRLEN];
6052 inet_ntop(p->family, &p->u.prefix, buf1,
6053 INET6_ADDRSTRLEN);
6054 zlog_debug(
6055 "%s(%s): Route not in table, not advertising",
15569c58 6056 __func__, buf1);
d62a17ae 6057 }
9bcb3eef 6058 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6059 }
6060 } else {
6061 /* Delete the NHT structure if any, if we're toggling between
6062 * enabling/disabling import check. We deregister the route
6063 * from NHT to avoid overloading NHT and the process interaction
6064 */
6065 bgp_unlink_nexthop(new);
6066
9bcb3eef 6067 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6068 }
078430f6 6069
d62a17ae 6070 /* Aggregate address increment. */
6071 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6072
d62a17ae 6073 /* Register new BGP information. */
9bcb3eef 6074 bgp_path_info_add(dest, new);
718e3744 6075
d62a17ae 6076 /* route_node_get lock */
9bcb3eef 6077 bgp_dest_unlock_node(dest);
d62a17ae 6078
6079 /* Process change. */
9bcb3eef 6080 bgp_process(bgp, dest, afi, safi);
d62a17ae 6081
ddb5b488
PZ
6082 if (SAFI_UNICAST == safi
6083 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6084 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6085 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6086 }
6087
d62a17ae 6088 /* Unintern original. */
6089 aspath_unintern(&attr.aspath);
718e3744 6090}
6091
5f040085 6092void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6093 safi_t safi)
718e3744 6094{
9bcb3eef 6095 struct bgp_dest *dest;
40381db7 6096 struct bgp_path_info *pi;
718e3744 6097
9bcb3eef 6098 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6099
d62a17ae 6100 /* Check selected route and self inserted route. */
9bcb3eef 6101 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6102 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6103 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6104 break;
6105
6106 /* Withdraw static BGP route from routing table. */
40381db7 6107 if (pi) {
ddb5b488
PZ
6108 if (SAFI_UNICAST == safi
6109 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6110 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6111 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6112 }
40381db7
DS
6113 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6114 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6115 bgp_path_info_delete(dest, pi);
6116 bgp_process(bgp, dest, afi, safi);
d62a17ae 6117 }
718e3744 6118
d62a17ae 6119 /* Unlock bgp_node_lookup. */
9bcb3eef 6120 bgp_dest_unlock_node(dest);
718e3744 6121}
6122
137446f9
LB
6123/*
6124 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6125 */
5f040085 6126static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6127 afi_t afi, safi_t safi,
6128 struct prefix_rd *prd)
718e3744 6129{
9bcb3eef 6130 struct bgp_dest *dest;
40381db7 6131 struct bgp_path_info *pi;
718e3744 6132
9bcb3eef 6133 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6134
d62a17ae 6135 /* Check selected route and self inserted route. */
9bcb3eef 6136 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6137 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6138 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6139 break;
718e3744 6140
d62a17ae 6141 /* Withdraw static BGP route from routing table. */
40381db7 6142 if (pi) {
49e5a4a0 6143#ifdef ENABLE_BGP_VNC
d62a17ae 6144 rfapiProcessWithdraw(
40381db7 6145 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6146 1); /* Kill, since it is an administrative change */
65efcfce 6147#endif
ddb5b488
PZ
6148 if (SAFI_MPLS_VPN == safi
6149 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6150 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6151 }
40381db7 6152 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6153 bgp_path_info_delete(dest, pi);
6154 bgp_process(bgp, dest, afi, safi);
d62a17ae 6155 }
718e3744 6156
d62a17ae 6157 /* Unlock bgp_node_lookup. */
9bcb3eef 6158 bgp_dest_unlock_node(dest);
718e3744 6159}
6160
5f040085 6161static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6162 struct bgp_static *bgp_static, afi_t afi,
6163 safi_t safi)
137446f9 6164{
9bcb3eef 6165 struct bgp_dest *dest;
4b7e6066 6166 struct bgp_path_info *new;
d62a17ae 6167 struct attr *attr_new;
6168 struct attr attr = {0};
40381db7 6169 struct bgp_path_info *pi;
49e5a4a0 6170#ifdef ENABLE_BGP_VNC
d62a17ae 6171 mpls_label_t label = 0;
65efcfce 6172#endif
d7c0a89a 6173 uint32_t num_labels = 0;
137446f9 6174
d62a17ae 6175 assert(bgp_static);
137446f9 6176
b57ba6d2
MK
6177 if (bgp_static->label != MPLS_INVALID_LABEL)
6178 num_labels = 1;
9bcb3eef
DS
6179 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6180 &bgp_static->prd);
137446f9 6181
0f05ea43 6182 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6183
d62a17ae 6184 attr.nexthop = bgp_static->igpnexthop;
6185 attr.med = bgp_static->igpmetric;
6186 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6187
d62a17ae 6188 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6189 || (safi == SAFI_ENCAP)) {
6190 if (afi == AFI_IP) {
6191 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6192 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6193 }
6194 }
6195 if (afi == AFI_L2VPN) {
b04c1e99
IR
6196 if (bgp_static->gatewayIp.family == AF_INET) {
6197 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6198 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6199 &bgp_static->gatewayIp.u.prefix4,
6200 IPV4_MAX_BYTELEN);
b04c1e99
IR
6201 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6202 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6203 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6204 &bgp_static->gatewayIp.u.prefix6,
6205 IPV6_MAX_BYTELEN);
b04c1e99 6206 }
0a50c248 6207 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6208 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6209 struct bgp_encap_type_vxlan bet;
6006b807 6210 memset(&bet, 0, sizeof(bet));
3714a385 6211 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6212 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6213 }
6214 if (bgp_static->router_mac) {
6215 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6216 }
6217 }
6218 /* Apply route-map. */
6219 if (bgp_static->rmap.name) {
6220 struct attr attr_tmp = attr;
40381db7 6221 struct bgp_path_info rmap_path;
b68885f9 6222 route_map_result_t ret;
137446f9 6223
40381db7
DS
6224 rmap_path.peer = bgp->peer_self;
6225 rmap_path.attr = &attr_tmp;
137446f9 6226
d62a17ae 6227 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6228
1782514f 6229 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6230
d62a17ae 6231 bgp->peer_self->rmap_type = 0;
137446f9 6232
d62a17ae 6233 if (ret == RMAP_DENYMATCH) {
6234 /* Free uninterned attribute. */
6235 bgp_attr_flush(&attr_tmp);
137446f9 6236
d62a17ae 6237 /* Unintern original. */
6238 aspath_unintern(&attr.aspath);
6239 bgp_static_withdraw_safi(bgp, p, afi, safi,
6240 &bgp_static->prd);
6241 return;
6242 }
137446f9 6243
d62a17ae 6244 attr_new = bgp_attr_intern(&attr_tmp);
6245 } else {
6246 attr_new = bgp_attr_intern(&attr);
6247 }
137446f9 6248
9bcb3eef 6249 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6250 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6251 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6252 break;
6253
40381db7 6254 if (pi) {
40381db7 6255 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6256 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6257 bgp_dest_unlock_node(dest);
d62a17ae 6258 bgp_attr_unintern(&attr_new);
6259 aspath_unintern(&attr.aspath);
6260 return;
6261 } else {
6262 /* The attribute is changed. */
9bcb3eef 6263 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6264
6265 /* Rewrite BGP route information. */
40381db7 6266 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6267 bgp_path_info_restore(dest, pi);
d62a17ae 6268 else
40381db7
DS
6269 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6270 bgp_attr_unintern(&pi->attr);
6271 pi->attr = attr_new;
6272 pi->uptime = bgp_clock();
49e5a4a0 6273#ifdef ENABLE_BGP_VNC
40381db7
DS
6274 if (pi->extra)
6275 label = decode_label(&pi->extra->label[0]);
65efcfce 6276#endif
137446f9 6277
d62a17ae 6278 /* Process change. */
40381db7 6279 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6280 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6281
6282 if (SAFI_MPLS_VPN == safi
6283 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6284 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6285 }
49e5a4a0 6286#ifdef ENABLE_BGP_VNC
40381db7
DS
6287 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6288 pi->attr, afi, safi, pi->type,
6289 pi->sub_type, &label);
65efcfce 6290#endif
9bcb3eef 6291 bgp_dest_unlock_node(dest);
d62a17ae 6292 aspath_unintern(&attr.aspath);
6293 return;
6294 }
6295 }
137446f9
LB
6296
6297
d62a17ae 6298 /* Make new BGP info. */
6299 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6300 attr_new, dest);
1defdda8 6301 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6302 bgp_path_info_extra_get(new);
b57ba6d2
MK
6303 if (num_labels) {
6304 new->extra->label[0] = bgp_static->label;
6305 new->extra->num_labels = num_labels;
6306 }
49e5a4a0 6307#ifdef ENABLE_BGP_VNC
d62a17ae 6308 label = decode_label(&bgp_static->label);
65efcfce 6309#endif
137446f9 6310
d62a17ae 6311 /* Aggregate address increment. */
6312 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6313
d62a17ae 6314 /* Register new BGP information. */
9bcb3eef 6315 bgp_path_info_add(dest, new);
d62a17ae 6316 /* route_node_get lock */
9bcb3eef 6317 bgp_dest_unlock_node(dest);
137446f9 6318
d62a17ae 6319 /* Process change. */
9bcb3eef 6320 bgp_process(bgp, dest, afi, safi);
137446f9 6321
ddb5b488
PZ
6322 if (SAFI_MPLS_VPN == safi
6323 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6324 vpn_leak_to_vrf_update(bgp, new);
6325 }
49e5a4a0 6326#ifdef ENABLE_BGP_VNC
d62a17ae 6327 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6328 safi, new->type, new->sub_type, &label);
65efcfce
LB
6329#endif
6330
d62a17ae 6331 /* Unintern original. */
6332 aspath_unintern(&attr.aspath);
137446f9
LB
6333}
6334
718e3744 6335/* Configure static BGP network. When user don't run zebra, static
6336 route should be installed as valid. */
585f1adc
IR
6337static int bgp_static_set(struct vty *vty, const char *negate,
6338 const char *ip_str, afi_t afi, safi_t safi,
6339 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6340{
585f1adc
IR
6341 VTY_DECLVAR_CONTEXT(bgp, bgp);
6342 int ret;
d62a17ae 6343 struct prefix p;
6344 struct bgp_static *bgp_static;
9bcb3eef 6345 struct bgp_dest *dest;
d7c0a89a 6346 uint8_t need_update = 0;
d62a17ae 6347
585f1adc
IR
6348 /* Convert IP prefix string to struct prefix. */
6349 ret = str2prefix(ip_str, &p);
6350 if (!ret) {
6351 vty_out(vty, "%% Malformed prefix\n");
6352 return CMD_WARNING_CONFIG_FAILED;
6353 }
6354 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6355 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6356 return CMD_WARNING_CONFIG_FAILED;
6357 }
6358
d62a17ae 6359 apply_mask(&p);
718e3744 6360
e2a86ad9 6361 if (negate) {
718e3744 6362
e2a86ad9 6363 /* Set BGP static route configuration. */
9bcb3eef 6364 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6365
9bcb3eef 6366 if (!dest) {
585f1adc
IR
6367 vty_out(vty, "%% Can't find static route specified\n");
6368 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6369 }
6370
9bcb3eef 6371 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6372
e2a86ad9
DS
6373 if ((label_index != BGP_INVALID_LABEL_INDEX)
6374 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6375 vty_out(vty,
6376 "%% label-index doesn't match static route\n");
70d9b134 6377 bgp_dest_unlock_node(dest);
585f1adc 6378 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6379 }
d62a17ae 6380
e2a86ad9
DS
6381 if ((rmap && bgp_static->rmap.name)
6382 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6383 vty_out(vty,
6384 "%% route-map name doesn't match static route\n");
70d9b134 6385 bgp_dest_unlock_node(dest);
585f1adc 6386 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6387 }
718e3744 6388
e2a86ad9
DS
6389 /* Update BGP RIB. */
6390 if (!bgp_static->backdoor)
6391 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6392
e2a86ad9
DS
6393 /* Clear configuration. */
6394 bgp_static_free(bgp_static);
9bcb3eef
DS
6395 bgp_dest_set_bgp_static_info(dest, NULL);
6396 bgp_dest_unlock_node(dest);
6397 bgp_dest_unlock_node(dest);
e2a86ad9 6398 } else {
718e3744 6399
e2a86ad9 6400 /* Set BGP static route configuration. */
9bcb3eef
DS
6401 dest = bgp_node_get(bgp->route[afi][safi], &p);
6402 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6403 if (bgp_static) {
e2a86ad9 6404 /* Configuration change. */
e2a86ad9
DS
6405 /* Label index cannot be changed. */
6406 if (bgp_static->label_index != label_index) {
585f1adc
IR
6407 vty_out(vty, "%% cannot change label-index\n");
6408 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6409 }
d62a17ae 6410
e2a86ad9 6411 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6412 if (bgp_static->valid
6413 && bgp_static->backdoor != backdoor)
e2a86ad9 6414 need_update = 1;
718e3744 6415
e2a86ad9 6416 bgp_static->backdoor = backdoor;
718e3744 6417
e2a86ad9 6418 if (rmap) {
0a22ddfb
QY
6419 XFREE(MTYPE_ROUTE_MAP_NAME,
6420 bgp_static->rmap.name);
b4897fa5 6421 route_map_counter_decrement(
6422 bgp_static->rmap.map);
e2a86ad9
DS
6423 bgp_static->rmap.name =
6424 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6425 bgp_static->rmap.map =
6426 route_map_lookup_by_name(rmap);
b4897fa5 6427 route_map_counter_increment(
6428 bgp_static->rmap.map);
e2a86ad9 6429 } else {
0a22ddfb
QY
6430 XFREE(MTYPE_ROUTE_MAP_NAME,
6431 bgp_static->rmap.name);
b4897fa5 6432 route_map_counter_decrement(
6433 bgp_static->rmap.map);
e2a86ad9
DS
6434 bgp_static->rmap.map = NULL;
6435 bgp_static->valid = 0;
6436 }
9bcb3eef 6437 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6438 } else {
6439 /* New configuration. */
6440 bgp_static = bgp_static_new();
6441 bgp_static->backdoor = backdoor;
6442 bgp_static->valid = 0;
6443 bgp_static->igpmetric = 0;
975a328e 6444 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6445 bgp_static->label_index = label_index;
718e3744 6446
e2a86ad9 6447 if (rmap) {
0a22ddfb
QY
6448 XFREE(MTYPE_ROUTE_MAP_NAME,
6449 bgp_static->rmap.name);
b4897fa5 6450 route_map_counter_decrement(
6451 bgp_static->rmap.map);
e2a86ad9
DS
6452 bgp_static->rmap.name =
6453 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6454 bgp_static->rmap.map =
6455 route_map_lookup_by_name(rmap);
b4897fa5 6456 route_map_counter_increment(
6457 bgp_static->rmap.map);
e2a86ad9 6458 }
9bcb3eef 6459 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6460 }
d62a17ae 6461
e2a86ad9
DS
6462 bgp_static->valid = 1;
6463 if (need_update)
6464 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6465
e2a86ad9
DS
6466 if (!bgp_static->backdoor)
6467 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6468 }
d62a17ae 6469
585f1adc 6470 return CMD_SUCCESS;
d62a17ae 6471}
6472
6473void bgp_static_add(struct bgp *bgp)
6474{
6475 afi_t afi;
6476 safi_t safi;
9bcb3eef
DS
6477 struct bgp_dest *dest;
6478 struct bgp_dest *rm;
d62a17ae 6479 struct bgp_table *table;
6480 struct bgp_static *bgp_static;
6481
47fc6261 6482 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6483 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6484 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6485 dest = bgp_route_next(dest)) {
6486 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6487 continue;
ea47320b 6488
05c7a1cc
QY
6489 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6490 || (safi == SAFI_EVPN)) {
9bcb3eef 6491 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6492
6493 for (rm = bgp_table_top(table); rm;
6494 rm = bgp_route_next(rm)) {
a78beeb5 6495 bgp_static =
9bcb3eef 6496 bgp_dest_get_bgp_static_info(
5a8ba9fc 6497 rm);
9bcb3eef
DS
6498 bgp_static_update_safi(
6499 bgp, bgp_dest_get_prefix(rm),
6500 bgp_static, afi, safi);
d62a17ae 6501 }
05c7a1cc 6502 } else {
5a8ba9fc 6503 bgp_static_update(
9bcb3eef
DS
6504 bgp, bgp_dest_get_prefix(dest),
6505 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6506 safi);
ea47320b 6507 }
05c7a1cc 6508 }
47fc6261 6509 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6510}
6511
718e3744 6512/* Called from bgp_delete(). Delete all static routes from the BGP
6513 instance. */
d62a17ae 6514void bgp_static_delete(struct bgp *bgp)
6515{
6516 afi_t afi;
6517 safi_t safi;
9bcb3eef
DS
6518 struct bgp_dest *dest;
6519 struct bgp_dest *rm;
d62a17ae 6520 struct bgp_table *table;
6521 struct bgp_static *bgp_static;
6522
05c7a1cc 6523 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6524 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6525 dest = bgp_route_next(dest)) {
6526 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6527 continue;
ea47320b 6528
05c7a1cc
QY
6529 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6530 || (safi == SAFI_EVPN)) {
9bcb3eef 6531 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6532
6533 for (rm = bgp_table_top(table); rm;
6534 rm = bgp_route_next(rm)) {
a78beeb5 6535 bgp_static =
9bcb3eef 6536 bgp_dest_get_bgp_static_info(
5a8ba9fc 6537 rm);
c7d14ba6
PG
6538 if (!bgp_static)
6539 continue;
6540
05c7a1cc 6541 bgp_static_withdraw_safi(
9bcb3eef 6542 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6543 AFI_IP, safi,
6544 (struct prefix_rd *)
9bcb3eef
DS
6545 bgp_dest_get_prefix(
6546 dest));
ea47320b 6547 bgp_static_free(bgp_static);
811c6797 6548 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6549 NULL);
811c6797 6550 bgp_dest_unlock_node(rm);
d62a17ae 6551 }
05c7a1cc 6552 } else {
9bcb3eef 6553 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6554 bgp_static_withdraw(bgp,
9bcb3eef 6555 bgp_dest_get_prefix(dest),
b54892e0 6556 afi, safi);
05c7a1cc 6557 bgp_static_free(bgp_static);
9bcb3eef
DS
6558 bgp_dest_set_bgp_static_info(dest, NULL);
6559 bgp_dest_unlock_node(dest);
ea47320b 6560 }
05c7a1cc 6561 }
d62a17ae 6562}
6563
6564void bgp_static_redo_import_check(struct bgp *bgp)
6565{
6566 afi_t afi;
6567 safi_t safi;
9bcb3eef
DS
6568 struct bgp_dest *dest;
6569 struct bgp_dest *rm;
d62a17ae 6570 struct bgp_table *table;
6571 struct bgp_static *bgp_static;
6572
6573 /* Use this flag to force reprocessing of the route */
892fedb6 6574 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6575 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6576 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6577 dest = bgp_route_next(dest)) {
6578 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6579 continue;
ea47320b 6580
05c7a1cc
QY
6581 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6582 || (safi == SAFI_EVPN)) {
9bcb3eef 6583 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6584
6585 for (rm = bgp_table_top(table); rm;
6586 rm = bgp_route_next(rm)) {
a78beeb5 6587 bgp_static =
9bcb3eef 6588 bgp_dest_get_bgp_static_info(
5a8ba9fc 6589 rm);
9bcb3eef
DS
6590 bgp_static_update_safi(
6591 bgp, bgp_dest_get_prefix(rm),
6592 bgp_static, afi, safi);
d62a17ae 6593 }
05c7a1cc 6594 } else {
9bcb3eef
DS
6595 bgp_static = bgp_dest_get_bgp_static_info(dest);
6596 bgp_static_update(bgp,
6597 bgp_dest_get_prefix(dest),
6598 bgp_static, afi, safi);
ea47320b 6599 }
05c7a1cc
QY
6600 }
6601 }
892fedb6 6602 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6603}
6604
6605static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6606 safi_t safi)
6607{
6608 struct bgp_table *table;
9bcb3eef 6609 struct bgp_dest *dest;
40381db7 6610 struct bgp_path_info *pi;
d62a17ae 6611
dfb6fd1d
NT
6612 /* Do not install the aggregate route if BGP is in the
6613 * process of termination.
6614 */
892fedb6
DA
6615 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6616 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6617 return;
6618
d62a17ae 6619 table = bgp->rib[afi][safi];
9bcb3eef
DS
6620 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6621 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6622 if (pi->peer == bgp->peer_self
6623 && ((pi->type == ZEBRA_ROUTE_BGP
6624 && pi->sub_type == BGP_ROUTE_STATIC)
6625 || (pi->type != ZEBRA_ROUTE_BGP
6626 && pi->sub_type
d62a17ae 6627 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6628 bgp_aggregate_decrement(
6629 bgp, bgp_dest_get_prefix(dest), pi, afi,
6630 safi);
40381db7 6631 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6632 bgp_path_info_delete(dest, pi);
6633 bgp_process(bgp, dest, afi, safi);
d62a17ae 6634 }
6635 }
6636 }
ad4cbda1 6637}
6638
6639/*
6640 * Purge all networks and redistributed routes from routing table.
6641 * Invoked upon the instance going down.
6642 */
d62a17ae 6643void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6644{
d62a17ae 6645 afi_t afi;
6646 safi_t safi;
ad4cbda1 6647
05c7a1cc
QY
6648 FOREACH_AFI_SAFI (afi, safi)
6649 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6650}
6651
137446f9
LB
6652/*
6653 * gpz 110624
6654 * Currently this is used to set static routes for VPN and ENCAP.
6655 * I think it can probably be factored with bgp_static_set.
6656 */
d62a17ae 6657int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6658 const char *ip_str, const char *rd_str,
6659 const char *label_str, const char *rmap_str,
6660 int evpn_type, const char *esi, const char *gwip,
6661 const char *ethtag, const char *routermac)
6662{
6663 VTY_DECLVAR_CONTEXT(bgp, bgp);
6664 int ret;
6665 struct prefix p;
6666 struct prefix_rd prd;
9bcb3eef
DS
6667 struct bgp_dest *pdest;
6668 struct bgp_dest *dest;
d62a17ae 6669 struct bgp_table *table;
6670 struct bgp_static *bgp_static;
6671 mpls_label_t label = MPLS_INVALID_LABEL;
6672 struct prefix gw_ip;
6673
6674 /* validate ip prefix */
6675 ret = str2prefix(ip_str, &p);
6676 if (!ret) {
6677 vty_out(vty, "%% Malformed prefix\n");
6678 return CMD_WARNING_CONFIG_FAILED;
6679 }
6680 apply_mask(&p);
6681 if ((afi == AFI_L2VPN)
6682 && (bgp_build_evpn_prefix(evpn_type,
6683 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6684 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6685 return CMD_WARNING_CONFIG_FAILED;
6686 }
718e3744 6687
d62a17ae 6688 ret = str2prefix_rd(rd_str, &prd);
6689 if (!ret) {
6690 vty_out(vty, "%% Malformed rd\n");
6691 return CMD_WARNING_CONFIG_FAILED;
6692 }
718e3744 6693
d62a17ae 6694 if (label_str) {
6695 unsigned long label_val;
6696 label_val = strtoul(label_str, NULL, 10);
6697 encode_label(label_val, &label);
6698 }
9bedbb1e 6699
d62a17ae 6700 if (safi == SAFI_EVPN) {
6701 if (esi && str2esi(esi, NULL) == 0) {
6702 vty_out(vty, "%% Malformed ESI\n");
6703 return CMD_WARNING_CONFIG_FAILED;
6704 }
6705 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6706 vty_out(vty, "%% Malformed Router MAC\n");
6707 return CMD_WARNING_CONFIG_FAILED;
6708 }
6709 if (gwip) {
6006b807 6710 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6711 ret = str2prefix(gwip, &gw_ip);
6712 if (!ret) {
6713 vty_out(vty, "%% Malformed GatewayIp\n");
6714 return CMD_WARNING_CONFIG_FAILED;
6715 }
6716 if ((gw_ip.family == AF_INET
3714a385 6717 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6718 (struct prefix_evpn *)&p))
6719 || (gw_ip.family == AF_INET6
3714a385 6720 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6721 (struct prefix_evpn *)&p))) {
6722 vty_out(vty,
6723 "%% GatewayIp family differs with IP prefix\n");
6724 return CMD_WARNING_CONFIG_FAILED;
6725 }
6726 }
6727 }
9bcb3eef
DS
6728 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6729 if (!bgp_dest_has_bgp_path_info_data(pdest))
6730 bgp_dest_set_bgp_table_info(pdest,
67009e22 6731 bgp_table_init(bgp, afi, safi));
9bcb3eef 6732 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6733
9bcb3eef 6734 dest = bgp_node_get(table, &p);
d62a17ae 6735
9bcb3eef 6736 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6737 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6738 bgp_dest_unlock_node(dest);
d62a17ae 6739 } else {
6740 /* New configuration. */
6741 bgp_static = bgp_static_new();
6742 bgp_static->backdoor = 0;
6743 bgp_static->valid = 0;
6744 bgp_static->igpmetric = 0;
975a328e 6745 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6746 bgp_static->label = label;
6747 bgp_static->prd = prd;
6748
6749 if (rmap_str) {
0a22ddfb 6750 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6751 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6752 bgp_static->rmap.name =
6753 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6754 bgp_static->rmap.map =
6755 route_map_lookup_by_name(rmap_str);
b4897fa5 6756 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6757 }
718e3744 6758
d62a17ae 6759 if (safi == SAFI_EVPN) {
6760 if (esi) {
6761 bgp_static->eth_s_id =
6762 XCALLOC(MTYPE_ATTR,
0a50c248 6763 sizeof(esi_t));
d62a17ae 6764 str2esi(esi, bgp_static->eth_s_id);
6765 }
6766 if (routermac) {
6767 bgp_static->router_mac =
28328ea9 6768 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6769 (void)prefix_str2mac(routermac,
6770 bgp_static->router_mac);
d62a17ae 6771 }
6772 if (gwip)
6773 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6774 }
9bcb3eef 6775 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6776
d62a17ae 6777 bgp_static->valid = 1;
6778 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6779 }
718e3744 6780
d62a17ae 6781 return CMD_SUCCESS;
718e3744 6782}
6783
6784/* Configure static BGP network. */
d62a17ae 6785int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6786 const char *ip_str, const char *rd_str,
6787 const char *label_str, int evpn_type, const char *esi,
6788 const char *gwip, const char *ethtag)
6789{
6790 VTY_DECLVAR_CONTEXT(bgp, bgp);
6791 int ret;
6792 struct prefix p;
6793 struct prefix_rd prd;
9bcb3eef
DS
6794 struct bgp_dest *pdest;
6795 struct bgp_dest *dest;
d62a17ae 6796 struct bgp_table *table;
6797 struct bgp_static *bgp_static;
6798 mpls_label_t label = MPLS_INVALID_LABEL;
6799
6800 /* Convert IP prefix string to struct prefix. */
6801 ret = str2prefix(ip_str, &p);
6802 if (!ret) {
6803 vty_out(vty, "%% Malformed prefix\n");
6804 return CMD_WARNING_CONFIG_FAILED;
6805 }
6806 apply_mask(&p);
6807 if ((afi == AFI_L2VPN)
6808 && (bgp_build_evpn_prefix(evpn_type,
6809 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6810 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6811 return CMD_WARNING_CONFIG_FAILED;
6812 }
6813 ret = str2prefix_rd(rd_str, &prd);
6814 if (!ret) {
6815 vty_out(vty, "%% Malformed rd\n");
6816 return CMD_WARNING_CONFIG_FAILED;
6817 }
718e3744 6818
d62a17ae 6819 if (label_str) {
6820 unsigned long label_val;
6821 label_val = strtoul(label_str, NULL, 10);
6822 encode_label(label_val, &label);
6823 }
718e3744 6824
9bcb3eef
DS
6825 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6826 if (!bgp_dest_has_bgp_path_info_data(pdest))
6827 bgp_dest_set_bgp_table_info(pdest,
67009e22 6828 bgp_table_init(bgp, afi, safi));
d62a17ae 6829 else
9bcb3eef
DS
6830 bgp_dest_unlock_node(pdest);
6831 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6832
9bcb3eef 6833 dest = bgp_node_lookup(table, &p);
6b0655a2 6834
9bcb3eef 6835 if (dest) {
d62a17ae 6836 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6837
9bcb3eef 6838 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6839 bgp_static_free(bgp_static);
9bcb3eef
DS
6840 bgp_dest_set_bgp_static_info(dest, NULL);
6841 bgp_dest_unlock_node(dest);
6842 bgp_dest_unlock_node(dest);
d62a17ae 6843 } else
6844 vty_out(vty, "%% Can't find the route\n");
6845
6846 return CMD_SUCCESS;
6847}
6848
6849static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6850 const char *rmap_name)
6851{
6852 VTY_DECLVAR_CONTEXT(bgp, bgp);
6853 struct bgp_rmap *rmap;
6854
6855 rmap = &bgp->table_map[afi][safi];
6856 if (rmap_name) {
0a22ddfb 6857 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6858 route_map_counter_decrement(rmap->map);
d62a17ae 6859 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6860 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6861 route_map_counter_increment(rmap->map);
d62a17ae 6862 } else {
0a22ddfb 6863 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6864 route_map_counter_decrement(rmap->map);
d62a17ae 6865 rmap->map = NULL;
6866 }
73ac8160 6867
d62a17ae 6868 if (bgp_fibupd_safi(safi))
6869 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6870
d62a17ae 6871 return CMD_SUCCESS;
73ac8160
DS
6872}
6873
d62a17ae 6874static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6875 const char *rmap_name)
73ac8160 6876{
d62a17ae 6877 VTY_DECLVAR_CONTEXT(bgp, bgp);
6878 struct bgp_rmap *rmap;
73ac8160 6879
d62a17ae 6880 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6881 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6882 route_map_counter_decrement(rmap->map);
d62a17ae 6883 rmap->map = NULL;
73ac8160 6884
d62a17ae 6885 if (bgp_fibupd_safi(safi))
6886 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6887
d62a17ae 6888 return CMD_SUCCESS;
73ac8160
DS
6889}
6890
2b791107 6891void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6892 safi_t safi)
73ac8160 6893{
d62a17ae 6894 if (bgp->table_map[afi][safi].name) {
d62a17ae 6895 vty_out(vty, " table-map %s\n",
6896 bgp->table_map[afi][safi].name);
6897 }
73ac8160
DS
6898}
6899
73ac8160
DS
6900DEFUN (bgp_table_map,
6901 bgp_table_map_cmd,
6902 "table-map WORD",
6903 "BGP table to RIB route download filter\n"
6904 "Name of the route map\n")
6905{
d62a17ae 6906 int idx_word = 1;
6907 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6908 argv[idx_word]->arg);
73ac8160
DS
6909}
6910DEFUN (no_bgp_table_map,
6911 no_bgp_table_map_cmd,
6912 "no table-map WORD",
3a2d747c 6913 NO_STR
73ac8160
DS
6914 "BGP table to RIB route download filter\n"
6915 "Name of the route map\n")
6916{
d62a17ae 6917 int idx_word = 2;
6918 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6919 argv[idx_word]->arg);
73ac8160
DS
6920}
6921
585f1adc
IR
6922DEFPY(bgp_network,
6923 bgp_network_cmd,
6924 "[no] network \
6925 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 6926 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
6927 backdoor$backdoor}]",
6928 NO_STR
6929 "Specify a network to announce via BGP\n"
6930 "IPv4 prefix\n"
6931 "Network number\n"
6932 "Network mask\n"
6933 "Network mask\n"
6934 "Route-map to modify the attributes\n"
6935 "Name of the route map\n"
6936 "Label index to associate with the prefix\n"
6937 "Label index value\n"
6938 "Specify a BGP backdoor route\n")
6939{
6940 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6941
6942 if (address_str) {
6943 int ret;
718e3744 6944
e2a86ad9 6945 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6946 addr_prefix_str,
6947 sizeof(addr_prefix_str));
e2a86ad9
DS
6948 if (!ret) {
6949 vty_out(vty, "%% Inconsistent address and mask\n");
6950 return CMD_WARNING_CONFIG_FAILED;
6951 }
d62a17ae 6952 }
718e3744 6953
585f1adc
IR
6954 return bgp_static_set(
6955 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6956 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6957 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6958}
6959
585f1adc
IR
6960DEFPY(ipv6_bgp_network,
6961 ipv6_bgp_network_cmd,
6962 "[no] network X:X::X:X/M$prefix \
70dd370f 6963 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
6964 NO_STR
6965 "Specify a network to announce via BGP\n"
6966 "IPv6 prefix\n"
6967 "Route-map to modify the attributes\n"
6968 "Name of the route map\n"
6969 "Label index to associate with the prefix\n"
6970 "Label index value\n")
37a87b8f 6971{
585f1adc
IR
6972 return bgp_static_set(
6973 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6974 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6975}
6976
d62a17ae 6977static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6978{
d62a17ae 6979 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6980}
6981
d62a17ae 6982static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6983{
365ab2e7
RZ
6984 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6985 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6986 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6987 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6988 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6989}
718e3744 6990
365ab2e7
RZ
6991/**
6992 * Helper function to avoid repeated code: prepare variables for a
6993 * `route_map_apply` call.
6994 *
6995 * \returns `true` on route map match, otherwise `false`.
6996 */
6997static bool aggr_suppress_map_test(struct bgp *bgp,
6998 struct bgp_aggregate *aggregate,
6999 struct bgp_path_info *pi)
7000{
7001 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7002 route_map_result_t rmr = RMAP_DENYMATCH;
7003 struct bgp_path_info rmap_path = {};
7004 struct attr attr = {};
7005
7006 /* No route map entries created, just don't match. */
7007 if (aggregate->suppress_map == NULL)
7008 return false;
7009
7010 /* Call route map matching and return result. */
7011 attr.aspath = aspath_empty();
7012 rmap_path.peer = bgp->peer_self;
7013 rmap_path.attr = &attr;
7014
7015 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7016 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7017 bgp->peer_self->rmap_type = 0;
7018
7019 bgp_attr_flush(&attr);
afb254d7 7020 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7021
7022 return rmr == RMAP_PERMITMATCH;
7023}
7024
4056a5f6
RZ
7025/** Test whether the aggregation has suppressed this path or not. */
7026static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7027 struct bgp_path_info *pi)
7028{
7029 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7030 return false;
7031
7032 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7033}
7034
7035/**
7036 * Suppress this path and keep the reference.
7037 *
7038 * \returns `true` if needs processing otherwise `false`.
7039 */
7040static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7041 struct bgp_path_info *pi)
7042{
7043 struct bgp_path_info_extra *pie;
7044
7045 /* Path is already suppressed by this aggregation. */
7046 if (aggr_suppress_exists(aggregate, pi))
7047 return false;
7048
7049 pie = bgp_path_info_extra_get(pi);
7050
7051 /* This is the first suppression, allocate memory and list it. */
7052 if (pie->aggr_suppressors == NULL)
7053 pie->aggr_suppressors = list_new();
7054
7055 listnode_add(pie->aggr_suppressors, aggregate);
7056
7057 /* Only mark for processing if suppressed. */
7058 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7059 if (BGP_DEBUG(update, UPDATE_OUT))
7060 zlog_debug("aggregate-address suppressing: %pFX",
7061 bgp_dest_get_prefix(pi->net));
7062
4056a5f6
RZ
7063 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7064 return true;
7065 }
7066
7067 return false;
7068}
7069
7070/**
7071 * Unsuppress this path and remove the reference.
7072 *
7073 * \returns `true` if needs processing otherwise `false`.
7074 */
7075static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7076 struct bgp_path_info *pi)
7077{
7078 /* Path wasn't suppressed. */
7079 if (!aggr_suppress_exists(aggregate, pi))
7080 return false;
7081
7082 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7083
7084 /* Unsuppress and free extra memory if last item. */
7085 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7086 if (BGP_DEBUG(update, UPDATE_OUT))
7087 zlog_debug("aggregate-address unsuppressing: %pFX",
7088 bgp_dest_get_prefix(pi->net));
7089
4056a5f6
RZ
7090 list_delete(&pi->extra->aggr_suppressors);
7091 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7092 return true;
7093 }
7094
7095 return false;
7096}
7097
3dc339cd
DA
7098static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7099 struct aspath *aspath,
7100 struct community *comm,
7101 struct ecommunity *ecomm,
7102 struct lcommunity *lcomm)
eaaf8adb
DS
7103{
7104 static struct aspath *ae = NULL;
7105
7106 if (!ae)
7107 ae = aspath_empty();
7108
40381db7 7109 if (!pi)
3dc339cd 7110 return false;
eaaf8adb 7111
40381db7 7112 if (origin != pi->attr->origin)
3dc339cd 7113 return false;
eaaf8adb 7114
40381db7 7115 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7116 return false;
29f7d023 7117
9a706b42 7118 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7119 return false;
eaaf8adb 7120
b53e67a3 7121 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7122 return false;
eaaf8adb 7123
1bcf3a96 7124 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7125 return false;
dd18c5a9 7126
40381db7 7127 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7128 return false;
7ce8a8e0 7129
3dc339cd 7130 return true;
eaaf8adb
DS
7131}
7132
5f040085
DS
7133static void bgp_aggregate_install(
7134 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7135 uint8_t origin, struct aspath *aspath, struct community *community,
7136 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7137 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7138{
9bcb3eef 7139 struct bgp_dest *dest;
c701010e 7140 struct bgp_table *table;
6f94b685 7141 struct bgp_path_info *pi, *orig, *new;
20894f50 7142 struct attr *attr;
c701010e
DS
7143
7144 table = bgp->rib[afi][safi];
7145
9bcb3eef 7146 dest = bgp_node_get(table, p);
eaaf8adb 7147
9bcb3eef 7148 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7149 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7150 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7151 break;
7152
6aabb15d
RZ
7153 /*
7154 * If we have paths with different MEDs, then don't install
7155 * (or uninstall) the aggregate route.
7156 */
7157 if (aggregate->match_med && aggregate->med_mismatched)
7158 goto uninstall_aggregate_route;
7159
c701010e 7160 if (aggregate->count > 0) {
eaaf8adb
DS
7161 /*
7162 * If the aggregate information has not changed
7163 * no need to re-install it again.
7164 */
6f94b685 7165 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7166 ecommunity, lcommunity)) {
9bcb3eef 7167 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7168
7169 if (aspath)
7170 aspath_free(aspath);
7171 if (community)
3c1f53de 7172 community_free(&community);
3da2cc32
DS
7173 if (ecommunity)
7174 ecommunity_free(&ecommunity);
dd18c5a9
DS
7175 if (lcommunity)
7176 lcommunity_free(&lcommunity);
eaaf8adb
DS
7177
7178 return;
7179 }
7180
7181 /*
7182 * Mark the old as unusable
7183 */
40381db7 7184 if (pi)
9bcb3eef 7185 bgp_path_info_delete(dest, pi);
eaaf8adb 7186
20894f50
DA
7187 attr = bgp_attr_aggregate_intern(
7188 bgp, origin, aspath, community, ecommunity, lcommunity,
7189 aggregate, atomic_aggregate, p);
7190
7191 if (!attr) {
7192 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7193 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7194 zlog_debug("%s: %pFX null attribute", __func__,
7195 p);
20894f50
DA
7196 return;
7197 }
7198
3da2cc32 7199 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7200 bgp->peer_self, attr, dest);
20894f50 7201
1defdda8 7202 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7203
9bcb3eef
DS
7204 bgp_path_info_add(dest, new);
7205 bgp_process(bgp, dest, afi, safi);
c701010e 7206 } else {
6aabb15d 7207 uninstall_aggregate_route:
6f94b685 7208 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7209 if (pi->peer == bgp->peer_self
7210 && pi->type == ZEBRA_ROUTE_BGP
7211 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7212 break;
7213
7214 /* Withdraw static BGP route from routing table. */
40381db7 7215 if (pi) {
9bcb3eef
DS
7216 bgp_path_info_delete(dest, pi);
7217 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7218 }
7219 }
7220
9bcb3eef 7221 bgp_dest_unlock_node(dest);
c701010e
DS
7222}
7223
6aabb15d
RZ
7224/**
7225 * Check if the current path has different MED than other known paths.
7226 *
7227 * \returns `true` if the MED matched the others else `false`.
7228 */
7229static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7230 struct bgp *bgp, struct bgp_path_info *pi)
7231{
7232 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7233
7234 /* This is the first route being analyzed. */
7235 if (!aggregate->med_initialized) {
7236 aggregate->med_initialized = true;
7237 aggregate->med_mismatched = false;
7238 aggregate->med_matched_value = cur_med;
7239 } else {
7240 /* Check if routes with different MED showed up. */
7241 if (cur_med != aggregate->med_matched_value)
7242 aggregate->med_mismatched = true;
7243 }
7244
7245 return !aggregate->med_mismatched;
7246}
7247
7248/**
7249 * Initializes and tests all routes in the aggregate address path for MED
7250 * values.
7251 *
7252 * \returns `true` if all MEDs are the same otherwise `false`.
7253 */
7254static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7255 struct bgp *bgp, const struct prefix *p,
7256 afi_t afi, safi_t safi)
7257{
7258 struct bgp_table *table = bgp->rib[afi][safi];
7259 const struct prefix *dest_p;
7260 struct bgp_dest *dest, *top;
7261 struct bgp_path_info *pi;
7262 bool med_matched = true;
7263
7264 aggregate->med_initialized = false;
7265
7266 top = bgp_node_get(table, p);
7267 for (dest = bgp_node_get(table, p); dest;
7268 dest = bgp_route_next_until(dest, top)) {
7269 dest_p = bgp_dest_get_prefix(dest);
7270 if (dest_p->prefixlen <= p->prefixlen)
7271 continue;
7272
7273 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7274 if (BGP_PATH_HOLDDOWN(pi))
7275 continue;
7276 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7277 continue;
7278 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7279 med_matched = false;
7280 break;
7281 }
7282 }
7283 if (!med_matched)
7284 break;
7285 }
7286 bgp_dest_unlock_node(top);
7287
7288 return med_matched;
7289}
7290
7291/**
7292 * Toggles the route suppression status for this aggregate address
7293 * configuration.
7294 */
4056a5f6
RZ
7295void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7296 struct bgp *bgp, const struct prefix *p,
7297 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7298{
7299 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7300 const struct prefix *dest_p;
7301 struct bgp_dest *dest, *top;
7302 struct bgp_path_info *pi;
7303 bool toggle_suppression;
7304
7305 /* We've found a different MED we must revert any suppressed routes. */
7306 top = bgp_node_get(table, p);
7307 for (dest = bgp_node_get(table, p); dest;
7308 dest = bgp_route_next_until(dest, top)) {
7309 dest_p = bgp_dest_get_prefix(dest);
7310 if (dest_p->prefixlen <= p->prefixlen)
7311 continue;
7312
7313 toggle_suppression = false;
7314 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7315 if (BGP_PATH_HOLDDOWN(pi))
7316 continue;
7317 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7318 continue;
7319
6aabb15d
RZ
7320 /* We are toggling suppression back. */
7321 if (suppress) {
6aabb15d 7322 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7323 if (aggr_suppress_path(aggregate, pi))
7324 toggle_suppression = true;
6aabb15d
RZ
7325 continue;
7326 }
7327
6aabb15d 7328 /* Install route if there is no more suppression. */
4056a5f6 7329 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7330 toggle_suppression = true;
6aabb15d
RZ
7331 }
7332
7333 if (toggle_suppression)
7334 bgp_process(bgp, dest, afi, safi);
7335 }
7336 bgp_dest_unlock_node(top);
7337}
7338
7339/**
7340 * Aggregate address MED matching incremental test: this function is called
7341 * when the initial aggregation occurred and we are only testing a single
7342 * new path.
7343 *
7344 * In addition to testing and setting the MED validity it also installs back
7345 * suppressed routes (if summary is configured).
7346 *
7347 * Must not be called in `bgp_aggregate_route`.
7348 */
7349static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7350 struct bgp *bgp, const struct prefix *p,
7351 afi_t afi, safi_t safi,
7352 struct bgp_path_info *pi, bool is_adding)
7353{
7354 /* MED matching disabled. */
7355 if (!aggregate->match_med)
7356 return;
7357
7358 /* Aggregation with different MED, nothing to do. */
7359 if (aggregate->med_mismatched)
7360 return;
7361
7362 /*
7363 * Test the current entry:
7364 *
7365 * is_adding == true: if the new entry doesn't match then we must
7366 * install all suppressed routes.
7367 *
7368 * is_adding == false: if the entry being removed was the last
7369 * unmatching entry then we can suppress all routes.
7370 */
7371 if (!is_adding) {
7372 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7373 && aggregate->summary_only)
7374 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7375 safi, true);
7376 } else
7377 bgp_aggregate_med_match(aggregate, bgp, pi);
7378
7379 /* No mismatches, just quit. */
7380 if (!aggregate->med_mismatched)
7381 return;
7382
7383 /* Route summarization is disabled. */
7384 if (!aggregate->summary_only)
7385 return;
7386
7387 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7388}
7389
b5d58c32 7390/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7391void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7392 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7393{
7394 struct bgp_table *table;
9bcb3eef
DS
7395 struct bgp_dest *top;
7396 struct bgp_dest *dest;
d7c0a89a 7397 uint8_t origin;
d62a17ae 7398 struct aspath *aspath = NULL;
d62a17ae 7399 struct community *community = NULL;
3da2cc32 7400 struct ecommunity *ecommunity = NULL;
dd18c5a9 7401 struct lcommunity *lcommunity = NULL;
40381db7 7402 struct bgp_path_info *pi;
d62a17ae 7403 unsigned long match = 0;
d7c0a89a 7404 uint8_t atomic_aggregate = 0;
d62a17ae 7405
9f822fa2
S
7406 /* If the bgp instance is being deleted or self peer is deleted
7407 * then do not create aggregate route
7408 */
892fedb6
DA
7409 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7410 || (bgp->peer_self == NULL))
9f822fa2
S
7411 return;
7412
6aabb15d
RZ
7413 /* Initialize and test routes for MED difference. */
7414 if (aggregate->match_med)
7415 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7416
4056a5f6
RZ
7417 /*
7418 * Reset aggregate count: we might've been called from route map
7419 * update so in that case we must retest all more specific routes.
7420 *
7421 * \see `bgp_route_map_process_update`.
7422 */
7423 aggregate->count = 0;
7424 aggregate->incomplete_origin_count = 0;
7425 aggregate->incomplete_origin_count = 0;
7426 aggregate->egp_origin_count = 0;
7427
d62a17ae 7428 /* ORIGIN attribute: If at least one route among routes that are
7429 aggregated has ORIGIN with the value INCOMPLETE, then the
7430 aggregated route must have the ORIGIN attribute with the value
7431 INCOMPLETE. Otherwise, if at least one route among routes that
7432 are aggregated has ORIGIN with the value EGP, then the aggregated
7433 route must have the origin attribute with the value EGP. In all
7434 other case the value of the ORIGIN attribute of the aggregated
7435 route is INTERNAL. */
7436 origin = BGP_ORIGIN_IGP;
718e3744 7437
d62a17ae 7438 table = bgp->rib[afi][safi];
718e3744 7439
d62a17ae 7440 top = bgp_node_get(table, p);
9bcb3eef
DS
7441 for (dest = bgp_node_get(table, p); dest;
7442 dest = bgp_route_next_until(dest, top)) {
7443 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7444
9bcb3eef 7445 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7446 continue;
d62a17ae 7447
a77e2f4b
S
7448 /* If suppress fib is enabled and route not installed
7449 * in FIB, skip the route
7450 */
7451 if (!bgp_check_advertise(bgp, dest))
7452 continue;
7453
c2ff8b3e 7454 match = 0;
d62a17ae 7455
9bcb3eef 7456 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7457 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7458 continue;
718e3744 7459
40381db7 7460 if (pi->attr->flag
c2ff8b3e
DS
7461 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7462 atomic_aggregate = 1;
d62a17ae 7463
40381db7 7464 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7465 continue;
d62a17ae 7466
f273fef1
DS
7467 /*
7468 * summary-only aggregate route suppress
7469 * aggregated route announcements.
6aabb15d
RZ
7470 *
7471 * MED matching:
7472 * Don't create summaries if MED didn't match
7473 * otherwise neither the specific routes and the
7474 * aggregation will be announced.
f273fef1 7475 */
6aabb15d
RZ
7476 if (aggregate->summary_only
7477 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7478 if (aggr_suppress_path(aggregate, pi))
7479 match++;
d62a17ae 7480 }
c2ff8b3e 7481
365ab2e7
RZ
7482 /*
7483 * Suppress more specific routes that match the route
7484 * map results.
7485 *
7486 * MED matching:
7487 * Don't suppress routes if MED matching is enabled and
7488 * it mismatched otherwise we might end up with no
7489 * routes for this path.
7490 */
7491 if (aggregate->suppress_map_name
7492 && AGGREGATE_MED_VALID(aggregate)
7493 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7494 if (aggr_suppress_path(aggregate, pi))
7495 match++;
d62a17ae 7496 }
c2ff8b3e
DS
7497
7498 aggregate->count++;
7499
f273fef1
DS
7500 /*
7501 * If at least one route among routes that are
7502 * aggregated has ORIGIN with the value INCOMPLETE,
7503 * then the aggregated route MUST have the ORIGIN
7504 * attribute with the value INCOMPLETE. Otherwise, if
7505 * at least one route among routes that are aggregated
7506 * has ORIGIN with the value EGP, then the aggregated
7507 * route MUST have the ORIGIN attribute with the value
7508 * EGP.
7509 */
fc968841
NT
7510 switch (pi->attr->origin) {
7511 case BGP_ORIGIN_INCOMPLETE:
7512 aggregate->incomplete_origin_count++;
7513 break;
7514 case BGP_ORIGIN_EGP:
7515 aggregate->egp_origin_count++;
7516 break;
7517 default:
7518 /*Do nothing.
7519 */
7520 break;
7521 }
c2ff8b3e
DS
7522
7523 if (!aggregate->as_set)
7524 continue;
7525
f273fef1
DS
7526 /*
7527 * as-set aggregate route generate origin, as path,
7528 * and community aggregation.
7529 */
fc968841
NT
7530 /* Compute aggregate route's as-path.
7531 */
ef51a7d8 7532 bgp_compute_aggregate_aspath_hash(aggregate,
7533 pi->attr->aspath);
c2ff8b3e 7534
fc968841
NT
7535 /* Compute aggregate route's community.
7536 */
9a706b42 7537 if (bgp_attr_get_community(pi->attr))
21fec674 7538 bgp_compute_aggregate_community_hash(
9a706b42
DA
7539 aggregate,
7540 bgp_attr_get_community(pi->attr));
dd18c5a9 7541
fc968841
NT
7542 /* Compute aggregate route's extended community.
7543 */
b53e67a3 7544 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7545 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7546 aggregate,
7547 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7548
7549 /* Compute aggregate route's large community.
7550 */
1bcf3a96 7551 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7552 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7553 aggregate,
7554 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7555 }
c2ff8b3e 7556 if (match)
9bcb3eef 7557 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7558 }
21fec674 7559 if (aggregate->as_set) {
ef51a7d8 7560 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7561 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7562 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7563 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7564 }
7565
f1eb1f05 7566
9bcb3eef 7567 bgp_dest_unlock_node(top);
718e3744 7568
718e3744 7569
fc968841
NT
7570 if (aggregate->incomplete_origin_count > 0)
7571 origin = BGP_ORIGIN_INCOMPLETE;
7572 else if (aggregate->egp_origin_count > 0)
7573 origin = BGP_ORIGIN_EGP;
d62a17ae 7574
229757f1
DA
7575 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7576 origin = aggregate->origin;
7577
fc968841
NT
7578 if (aggregate->as_set) {
7579 if (aggregate->aspath)
7580 /* Retrieve aggregate route's as-path.
7581 */
7582 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7583
fc968841
NT
7584 if (aggregate->community)
7585 /* Retrieve aggregate route's community.
7586 */
7587 community = community_dup(aggregate->community);
3da2cc32 7588
fc968841
NT
7589 if (aggregate->ecommunity)
7590 /* Retrieve aggregate route's ecommunity.
7591 */
7592 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7593
fc968841
NT
7594 if (aggregate->lcommunity)
7595 /* Retrieve aggregate route's lcommunity.
7596 */
7597 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7598 }
718e3744 7599
c701010e 7600 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7601 ecommunity, lcommunity, atomic_aggregate,
7602 aggregate);
718e3744 7603}
7604
5f040085
DS
7605void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7606 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7607{
7608 struct bgp_table *table;
9bcb3eef
DS
7609 struct bgp_dest *top;
7610 struct bgp_dest *dest;
40381db7 7611 struct bgp_path_info *pi;
3b7db173
DS
7612 unsigned long match;
7613
7614 table = bgp->rib[afi][safi];
7615
7616 /* If routes exists below this node, generate aggregate routes. */
7617 top = bgp_node_get(table, p);
9bcb3eef
DS
7618 for (dest = bgp_node_get(table, p); dest;
7619 dest = bgp_route_next_until(dest, top)) {
7620 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7621
9bcb3eef 7622 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7623 continue;
7624 match = 0;
7625
9bcb3eef 7626 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7627 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7628 continue;
7629
40381db7 7630 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7631 continue;
7632
92b175bd
RZ
7633 /*
7634 * This route is suppressed: attempt to unsuppress it.
7635 *
7636 * `aggr_unsuppress_path` will fail if this particular
7637 * aggregate route was not the suppressor.
7638 */
7639 if (pi->extra && pi->extra->aggr_suppressors &&
7640 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7641 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7642 match++;
3b7db173 7643 }
365ab2e7 7644
3b7db173 7645 aggregate->count--;
fc968841
NT
7646
7647 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7648 aggregate->incomplete_origin_count--;
7649 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7650 aggregate->egp_origin_count--;
7651
7652 if (aggregate->as_set) {
7653 /* Remove as-path from aggregate.
7654 */
ef51a7d8 7655 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7656 aggregate,
7657 pi->attr->aspath);
7658
9a706b42 7659 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7660 /* Remove community from aggregate.
7661 */
21fec674 7662 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7663 aggregate,
7664 bgp_attr_get_community(
7665 pi->attr));
fc968841 7666
b53e67a3 7667 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7668 /* Remove ecommunity from aggregate.
7669 */
4edd83f9 7670 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7671 aggregate,
7672 bgp_attr_get_ecommunity(
7673 pi->attr));
fc968841 7674
1bcf3a96 7675 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7676 /* Remove lcommunity from aggregate.
7677 */
f1eb1f05 7678 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7679 aggregate,
7680 bgp_attr_get_lcommunity(
7681 pi->attr));
fc968841 7682 }
3b7db173
DS
7683 }
7684
7685 /* If this node was suppressed, process the change. */
7686 if (match)
9bcb3eef 7687 bgp_process(bgp, dest, afi, safi);
3b7db173 7688 }
f1eb1f05 7689 if (aggregate->as_set) {
ef51a7d8 7690 aspath_free(aggregate->aspath);
7691 aggregate->aspath = NULL;
21fec674 7692 if (aggregate->community)
7693 community_free(&aggregate->community);
4edd83f9 7694 if (aggregate->ecommunity)
7695 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7696 if (aggregate->lcommunity)
7697 lcommunity_free(&aggregate->lcommunity);
7698 }
7699
9bcb3eef 7700 bgp_dest_unlock_node(top);
3b7db173 7701}
718e3744 7702
5f040085
DS
7703static void bgp_add_route_to_aggregate(struct bgp *bgp,
7704 const struct prefix *aggr_p,
fc968841
NT
7705 struct bgp_path_info *pinew, afi_t afi,
7706 safi_t safi,
7707 struct bgp_aggregate *aggregate)
7708{
7709 uint8_t origin;
7710 struct aspath *aspath = NULL;
7711 uint8_t atomic_aggregate = 0;
7712 struct community *community = NULL;
7713 struct ecommunity *ecommunity = NULL;
7714 struct lcommunity *lcommunity = NULL;
7715
a4559740 7716 /* If the bgp instance is being deleted or self peer is deleted
7717 * then do not create aggregate route
7718 */
7719 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7720 || (bgp->peer_self == NULL))
7721 return;
7722
fc968841
NT
7723 /* ORIGIN attribute: If at least one route among routes that are
7724 * aggregated has ORIGIN with the value INCOMPLETE, then the
7725 * aggregated route must have the ORIGIN attribute with the value
7726 * INCOMPLETE. Otherwise, if at least one route among routes that
7727 * are aggregated has ORIGIN with the value EGP, then the aggregated
7728 * route must have the origin attribute with the value EGP. In all
7729 * other case the value of the ORIGIN attribute of the aggregated
7730 * route is INTERNAL.
7731 */
7732 origin = BGP_ORIGIN_IGP;
7733
7734 aggregate->count++;
7735
6aabb15d
RZ
7736 /*
7737 * This must be called before `summary` check to avoid
7738 * "suppressing" twice.
7739 */
7740 if (aggregate->match_med)
7741 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7742 pinew, true);
7743
7744 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7745 aggr_suppress_path(aggregate, pinew);
fc968841 7746
365ab2e7
RZ
7747 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7748 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7749 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7750
7751 switch (pinew->attr->origin) {
7752 case BGP_ORIGIN_INCOMPLETE:
7753 aggregate->incomplete_origin_count++;
7754 break;
7755 case BGP_ORIGIN_EGP:
7756 aggregate->egp_origin_count++;
7757 break;
7758 default:
7759 /* Do nothing.
7760 */
7761 break;
7762 }
7763
7764 if (aggregate->incomplete_origin_count > 0)
7765 origin = BGP_ORIGIN_INCOMPLETE;
7766 else if (aggregate->egp_origin_count > 0)
7767 origin = BGP_ORIGIN_EGP;
7768
229757f1
DA
7769 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7770 origin = aggregate->origin;
7771
fc968841
NT
7772 if (aggregate->as_set) {
7773 /* Compute aggregate route's as-path.
7774 */
7775 bgp_compute_aggregate_aspath(aggregate,
7776 pinew->attr->aspath);
7777
7778 /* Compute aggregate route's community.
7779 */
9a706b42 7780 if (bgp_attr_get_community(pinew->attr))
fc968841 7781 bgp_compute_aggregate_community(
9a706b42 7782 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7783
7784 /* Compute aggregate route's extended community.
7785 */
b53e67a3 7786 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7787 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7788 aggregate,
7789 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7790
7791 /* Compute aggregate route's large community.
7792 */
1bcf3a96 7793 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7794 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7795 aggregate,
7796 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7797
7798 /* Retrieve aggregate route's as-path.
7799 */
7800 if (aggregate->aspath)
7801 aspath = aspath_dup(aggregate->aspath);
7802
7803 /* Retrieve aggregate route's community.
7804 */
7805 if (aggregate->community)
7806 community = community_dup(aggregate->community);
7807
7808 /* Retrieve aggregate route's ecommunity.
7809 */
7810 if (aggregate->ecommunity)
7811 ecommunity = ecommunity_dup(aggregate->ecommunity);
7812
7813 /* Retrieve aggregate route's lcommunity.
7814 */
7815 if (aggregate->lcommunity)
7816 lcommunity = lcommunity_dup(aggregate->lcommunity);
7817 }
7818
7819 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7820 aspath, community, ecommunity,
7821 lcommunity, atomic_aggregate, aggregate);
7822}
7823
7824static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7825 safi_t safi,
7826 struct bgp_path_info *pi,
7827 struct bgp_aggregate *aggregate,
5f040085 7828 const struct prefix *aggr_p)
fc968841
NT
7829{
7830 uint8_t origin;
7831 struct aspath *aspath = NULL;
7832 uint8_t atomic_aggregate = 0;
7833 struct community *community = NULL;
7834 struct ecommunity *ecommunity = NULL;
7835 struct lcommunity *lcommunity = NULL;
7836 unsigned long match = 0;
7837
a4559740 7838 /* If the bgp instance is being deleted or self peer is deleted
7839 * then do not create aggregate route
7840 */
7841 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7842 || (bgp->peer_self == NULL))
7843 return;
7844
fc968841
NT
7845 if (BGP_PATH_HOLDDOWN(pi))
7846 return;
7847
7848 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7849 return;
7850
4056a5f6
RZ
7851 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7852 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7853 match++;
fc968841 7854
365ab2e7 7855 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7856 && aggr_suppress_map_test(bgp, aggregate, pi))
7857 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7858 match++;
fc968841 7859
6aabb15d 7860 /*
365ab2e7 7861 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7862 * "unsuppressing" twice.
7863 */
7864 if (aggregate->match_med)
7865 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7866 true);
7867
fc968841
NT
7868 if (aggregate->count > 0)
7869 aggregate->count--;
7870
7871 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7872 aggregate->incomplete_origin_count--;
7873 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7874 aggregate->egp_origin_count--;
7875
7876 if (aggregate->as_set) {
7877 /* Remove as-path from aggregate.
7878 */
7879 bgp_remove_aspath_from_aggregate(aggregate,
7880 pi->attr->aspath);
7881
9a706b42 7882 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7883 /* Remove community from aggregate.
7884 */
7885 bgp_remove_community_from_aggregate(
9a706b42 7886 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7887
b53e67a3 7888 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7889 /* Remove ecommunity from aggregate.
7890 */
7891 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7892 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7893
1bcf3a96 7894 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7895 /* Remove lcommunity from aggregate.
7896 */
7897 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7898 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7899 }
7900
7901 /* If this node was suppressed, process the change. */
7902 if (match)
7903 bgp_process(bgp, pi->net, afi, safi);
7904
7905 origin = BGP_ORIGIN_IGP;
7906 if (aggregate->incomplete_origin_count > 0)
7907 origin = BGP_ORIGIN_INCOMPLETE;
7908 else if (aggregate->egp_origin_count > 0)
7909 origin = BGP_ORIGIN_EGP;
7910
229757f1
DA
7911 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7912 origin = aggregate->origin;
7913
fc968841
NT
7914 if (aggregate->as_set) {
7915 /* Retrieve aggregate route's as-path.
7916 */
7917 if (aggregate->aspath)
7918 aspath = aspath_dup(aggregate->aspath);
7919
7920 /* Retrieve aggregate route's community.
7921 */
7922 if (aggregate->community)
7923 community = community_dup(aggregate->community);
7924
7925 /* Retrieve aggregate route's ecommunity.
7926 */
7927 if (aggregate->ecommunity)
7928 ecommunity = ecommunity_dup(aggregate->ecommunity);
7929
7930 /* Retrieve aggregate route's lcommunity.
7931 */
7932 if (aggregate->lcommunity)
7933 lcommunity = lcommunity_dup(aggregate->lcommunity);
7934 }
7935
7936 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7937 aspath, community, ecommunity,
7938 lcommunity, atomic_aggregate, aggregate);
7939}
7940
5a1ae2c2 7941void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7942 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7943{
9bcb3eef
DS
7944 struct bgp_dest *child;
7945 struct bgp_dest *dest;
d62a17ae 7946 struct bgp_aggregate *aggregate;
7947 struct bgp_table *table;
718e3744 7948
d62a17ae 7949 table = bgp->aggregate[afi][safi];
f018db83 7950
d62a17ae 7951 /* No aggregates configured. */
7952 if (bgp_table_top_nolock(table) == NULL)
7953 return;
f018db83 7954
d62a17ae 7955 if (p->prefixlen == 0)
7956 return;
718e3744 7957
40381db7 7958 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7959 return;
718e3744 7960
a77e2f4b
S
7961 /* If suppress fib is enabled and route not installed
7962 * in FIB, do not update the aggregate route
7963 */
7964 if (!bgp_check_advertise(bgp, pi->net))
7965 return;
7966
d62a17ae 7967 child = bgp_node_get(table, p);
718e3744 7968
d62a17ae 7969 /* Aggregate address configuration check. */
9bcb3eef
DS
7970 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7971 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7972
9bcb3eef
DS
7973 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7974 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7975 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7976 aggregate);
d62a17ae 7977 }
b1e62edd 7978 }
9bcb3eef 7979 bgp_dest_unlock_node(child);
718e3744 7980}
7981
5a1ae2c2 7982void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7983 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7984{
9bcb3eef
DS
7985 struct bgp_dest *child;
7986 struct bgp_dest *dest;
d62a17ae 7987 struct bgp_aggregate *aggregate;
7988 struct bgp_table *table;
718e3744 7989
d62a17ae 7990 table = bgp->aggregate[afi][safi];
718e3744 7991
d62a17ae 7992 /* No aggregates configured. */
7993 if (bgp_table_top_nolock(table) == NULL)
7994 return;
718e3744 7995
d62a17ae 7996 if (p->prefixlen == 0)
7997 return;
718e3744 7998
d62a17ae 7999 child = bgp_node_get(table, p);
718e3744 8000
d62a17ae 8001 /* Aggregate address configuration check. */
9bcb3eef
DS
8002 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8003 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8004
9bcb3eef
DS
8005 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8006 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8007 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8008 aggregate, dest_p);
d62a17ae 8009 }
b1e62edd 8010 }
9bcb3eef 8011 bgp_dest_unlock_node(child);
d62a17ae 8012}
718e3744 8013
718e3744 8014/* Aggregate route attribute. */
8015#define AGGREGATE_SUMMARY_ONLY 1
8016#define AGGREGATE_AS_SET 1
fb29348a 8017#define AGGREGATE_AS_UNSET 0
718e3744 8018
229757f1
DA
8019static const char *bgp_origin2str(uint8_t origin)
8020{
8021 switch (origin) {
8022 case BGP_ORIGIN_IGP:
8023 return "igp";
8024 case BGP_ORIGIN_EGP:
8025 return "egp";
8026 case BGP_ORIGIN_INCOMPLETE:
8027 return "incomplete";
8028 }
8029 return "n/a";
8030}
8031
fdeb5a81 8032static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8033{
8034 switch (v_state) {
fdeb5a81
DS
8035 case RPKI_NOT_BEING_USED:
8036 return "not used";
8037 case RPKI_VALID:
b5b99af8 8038 return "valid";
fdeb5a81 8039 case RPKI_NOTFOUND:
b5b99af8 8040 return "not found";
fdeb5a81 8041 case RPKI_INVALID:
b5b99af8 8042 return "invalid";
b5b99af8 8043 }
fdeb5a81
DS
8044
8045 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8046 return "ERROR";
8047}
8048
585f1adc
IR
8049static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8050 afi_t afi, safi_t safi)
718e3744 8051{
585f1adc
IR
8052 VTY_DECLVAR_CONTEXT(bgp, bgp);
8053 int ret;
8054 struct prefix p;
9bcb3eef 8055 struct bgp_dest *dest;
d62a17ae 8056 struct bgp_aggregate *aggregate;
718e3744 8057
585f1adc
IR
8058 /* Convert string to prefix structure. */
8059 ret = str2prefix(prefix_str, &p);
8060 if (!ret) {
8061 vty_out(vty, "Malformed prefix\n");
8062 return CMD_WARNING_CONFIG_FAILED;
8063 }
8064 apply_mask(&p);
a4559740 8065
d62a17ae 8066 /* Old configuration check. */
585f1adc 8067 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8068 if (!dest) {
585f1adc
IR
8069 vty_out(vty,
8070 "%% There is no aggregate-address configuration.\n");
8071 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8072 }
f6269b4f 8073
9bcb3eef 8074 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8075 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8076 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8077 NULL, NULL, 0, aggregate);
d62a17ae 8078
8079 /* Unlock aggregate address configuration. */
9bcb3eef 8080 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8081
8082 if (aggregate->community)
8083 community_free(&aggregate->community);
8084
8085 if (aggregate->community_hash) {
8086 /* Delete all communities in the hash.
8087 */
8088 hash_clean(aggregate->community_hash,
8089 bgp_aggr_community_remove);
8090 /* Free up the community_hash.
8091 */
8092 hash_free(aggregate->community_hash);
8093 }
8094
8095 if (aggregate->ecommunity)
8096 ecommunity_free(&aggregate->ecommunity);
8097
8098 if (aggregate->ecommunity_hash) {
8099 /* Delete all ecommunities in the hash.
8100 */
8101 hash_clean(aggregate->ecommunity_hash,
8102 bgp_aggr_ecommunity_remove);
8103 /* Free up the ecommunity_hash.
8104 */
8105 hash_free(aggregate->ecommunity_hash);
8106 }
8107
8108 if (aggregate->lcommunity)
8109 lcommunity_free(&aggregate->lcommunity);
8110
8111 if (aggregate->lcommunity_hash) {
8112 /* Delete all lcommunities in the hash.
8113 */
8114 hash_clean(aggregate->lcommunity_hash,
8115 bgp_aggr_lcommunity_remove);
8116 /* Free up the lcommunity_hash.
8117 */
8118 hash_free(aggregate->lcommunity_hash);
8119 }
8120
8121 if (aggregate->aspath)
8122 aspath_free(aggregate->aspath);
8123
8124 if (aggregate->aspath_hash) {
8125 /* Delete all as-paths in the hash.
8126 */
8127 hash_clean(aggregate->aspath_hash,
8128 bgp_aggr_aspath_remove);
8129 /* Free up the aspath_hash.
8130 */
8131 hash_free(aggregate->aspath_hash);
8132 }
8133
d62a17ae 8134 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8135 bgp_dest_unlock_node(dest);
8136 bgp_dest_unlock_node(dest);
d62a17ae 8137
585f1adc 8138 return CMD_SUCCESS;
d62a17ae 8139}
8140
585f1adc
IR
8141static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8142 safi_t safi, const char *rmap,
8143 uint8_t summary_only, uint8_t as_set,
8144 uint8_t origin, bool match_med,
8145 const char *suppress_map)
d62a17ae 8146{
585f1adc 8147 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8148 int ret;
585f1adc 8149 struct prefix p;
9bcb3eef 8150 struct bgp_dest *dest;
d62a17ae 8151 struct bgp_aggregate *aggregate;
fb29348a 8152 uint8_t as_set_new = as_set;
d62a17ae 8153
365ab2e7 8154 if (suppress_map && summary_only) {
585f1adc 8155 vty_out(vty,
365ab2e7 8156 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8157 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8158 }
8159
585f1adc
IR
8160 /* Convert string to prefix structure. */
8161 ret = str2prefix(prefix_str, &p);
8162 if (!ret) {
8163 vty_out(vty, "Malformed prefix\n");
8164 return CMD_WARNING_CONFIG_FAILED;
8165 }
8166 apply_mask(&p);
d62a17ae 8167
585f1adc
IR
8168 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8169 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8170 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8171 prefix_str);
8172 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8173 }
8174
d62a17ae 8175 /* Old configuration check. */
585f1adc 8176 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8177 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8178
20894f50 8179 if (aggregate) {
585f1adc 8180 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8181 /* try to remove the old entry */
585f1adc 8182 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8183 if (ret) {
585f1adc 8184 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8185 bgp_dest_unlock_node(dest);
585f1adc 8186 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8187 }
8188 }
718e3744 8189
d62a17ae 8190 /* Make aggregate address structure. */
8191 aggregate = bgp_aggregate_new();
8192 aggregate->summary_only = summary_only;
6aabb15d 8193 aggregate->match_med = match_med;
fb29348a
DA
8194
8195 /* Network operators MUST NOT locally generate any new
8196 * announcements containing AS_SET or AS_CONFED_SET. If they have
8197 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8198 * SHOULD withdraw those routes and re-announce routes for the
8199 * aggregate or component prefixes (i.e., the more-specific routes
8200 * subsumed by the previously aggregated route) without AS_SET
8201 * or AS_CONFED_SET in the updates.
8202 */
7f972cd8 8203 if (bgp->reject_as_sets) {
fb29348a
DA
8204 if (as_set == AGGREGATE_AS_SET) {
8205 as_set_new = AGGREGATE_AS_UNSET;
8206 zlog_warn(
63efca0e 8207 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8208 __func__);
585f1adc 8209 vty_out(vty,
fb29348a
DA
8210 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8211 }
8212 }
8213
8214 aggregate->as_set = as_set_new;
d62a17ae 8215 aggregate->safi = safi;
229757f1
DA
8216 /* Override ORIGIN attribute if defined.
8217 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8218 * to IGP which is not what rfc4271 says.
8219 * This enables the same behavior, optionally.
8220 */
8221 aggregate->origin = origin;
20894f50
DA
8222
8223 if (rmap) {
8224 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8225 route_map_counter_decrement(aggregate->rmap.map);
8226 aggregate->rmap.name =
8227 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8228 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8229 route_map_counter_increment(aggregate->rmap.map);
8230 }
365ab2e7
RZ
8231
8232 if (suppress_map) {
8233 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8234 route_map_counter_decrement(aggregate->suppress_map);
8235
8236 aggregate->suppress_map_name =
8237 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8238 aggregate->suppress_map =
8239 route_map_lookup_by_name(aggregate->suppress_map_name);
8240 route_map_counter_increment(aggregate->suppress_map);
8241 }
8242
9bcb3eef 8243 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8244
d62a17ae 8245 /* Aggregate address insert into BGP routing table. */
585f1adc 8246 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8247
585f1adc 8248 return CMD_SUCCESS;
718e3744 8249}
8250
585f1adc
IR
8251DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8252 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8253 "as-set$as_set_s"
8254 "|summary-only$summary_only"
cacba915 8255 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8256 "|origin <egp|igp|incomplete>$origin_s"
8257 "|matching-MED-only$match_med"
cacba915 8258 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8259 "}]",
8260 NO_STR
8261 "Configure BGP aggregate entries\n"
764402fe
DA
8262 "Aggregate prefix\n"
8263 "Aggregate address\n"
8264 "Aggregate mask\n"
585f1adc
IR
8265 "Generate AS set path information\n"
8266 "Filter more specific routes from updates\n"
8267 "Apply route map to aggregate network\n"
8268 "Route map name\n"
8269 "BGP origin code\n"
8270 "Remote EGP\n"
8271 "Local IGP\n"
8272 "Unknown heritage\n"
8273 "Only aggregate routes with matching MED\n"
8274 "Suppress the selected more specific routes\n"
8275 "Route map with the route selectors\n")
8276{
8277 const char *prefix_s = NULL;
554b3b10 8278 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8279 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8280 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8281 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8282
554b3b10 8283 if (addr_str) {
7533cad7
QY
8284 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8285 sizeof(prefix_buf))
554b3b10
RZ
8286 == 0) {
8287 vty_out(vty, "%% Inconsistent address and mask\n");
8288 return CMD_WARNING_CONFIG_FAILED;
8289 }
585f1adc
IR
8290 prefix_s = prefix_buf;
8291 } else
8292 prefix_s = prefix_str;
37a87b8f 8293
585f1adc
IR
8294 if (origin_s) {
8295 if (strcmp(origin_s, "egp") == 0)
8296 origin = BGP_ORIGIN_EGP;
8297 else if (strcmp(origin_s, "igp") == 0)
8298 origin = BGP_ORIGIN_IGP;
8299 else if (strcmp(origin_s, "incomplete") == 0)
8300 origin = BGP_ORIGIN_INCOMPLETE;
8301 }
90e21f35 8302
585f1adc
IR
8303 if (as_set_s)
8304 as_set = AGGREGATE_AS_SET;
554b3b10 8305
585f1adc 8306 /* Handle configuration removal, otherwise installation. */
554b3b10 8307 if (no)
585f1adc
IR
8308 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8309
8310 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8311 summary_only != NULL, as_set, origin,
8312 match_med != NULL, suppress_map);
8313}
8314
8315DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8316 "[no] aggregate-address X:X::X:X/M$prefix [{"
8317 "as-set$as_set_s"
8318 "|summary-only$summary_only"
cacba915 8319 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8320 "|origin <egp|igp|incomplete>$origin_s"
8321 "|matching-MED-only$match_med"
cacba915 8322 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8323 "}]",
8324 NO_STR
8325 "Configure BGP aggregate entries\n"
8326 "Aggregate prefix\n"
8327 "Generate AS set path information\n"
8328 "Filter more specific routes from updates\n"
8329 "Apply route map to aggregate network\n"
8330 "Route map name\n"
8331 "BGP origin code\n"
8332 "Remote EGP\n"
8333 "Local IGP\n"
8334 "Unknown heritage\n"
8335 "Only aggregate routes with matching MED\n"
8336 "Suppress the selected more specific routes\n"
8337 "Route map with the route selectors\n")
8338{
8339 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8340 int as_set = AGGREGATE_AS_UNSET;
8341
8342 if (origin_s) {
8343 if (strcmp(origin_s, "egp") == 0)
8344 origin = BGP_ORIGIN_EGP;
8345 else if (strcmp(origin_s, "igp") == 0)
8346 origin = BGP_ORIGIN_IGP;
8347 else if (strcmp(origin_s, "incomplete") == 0)
8348 origin = BGP_ORIGIN_INCOMPLETE;
8349 }
8350
8351 if (as_set_s)
8352 as_set = AGGREGATE_AS_SET;
8353
8354 /* Handle configuration removal, otherwise installation. */
554b3b10 8355 if (no)
585f1adc
IR
8356 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8357 SAFI_UNICAST);
554b3b10 8358
585f1adc
IR
8359 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8360 rmap_name, summary_only != NULL, as_set,
8361 origin, match_med != NULL, suppress_map);
718e3744 8362}
8363
718e3744 8364/* Redistribute route treatment. */
d62a17ae 8365void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8366 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8367 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8368 enum blackhole_type bhtype, uint32_t metric,
8369 uint8_t type, unsigned short instance,
8370 route_tag_t tag)
d62a17ae 8371{
4b7e6066 8372 struct bgp_path_info *new;
40381db7
DS
8373 struct bgp_path_info *bpi;
8374 struct bgp_path_info rmap_path;
9bcb3eef 8375 struct bgp_dest *bn;
d62a17ae 8376 struct attr attr;
8377 struct attr *new_attr;
8378 afi_t afi;
b68885f9 8379 route_map_result_t ret;
d62a17ae 8380 struct bgp_redist *red;
8381
8382 /* Make default attribute. */
0f05ea43 8383 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8384 /*
8385 * This must not be NULL to satisfy Coverity SA
8386 */
8387 assert(attr.aspath);
9de1f7ff 8388
a4d82a8a 8389 switch (nhtype) {
9de1f7ff
DS
8390 case NEXTHOP_TYPE_IFINDEX:
8391 break;
8392 case NEXTHOP_TYPE_IPV4:
8393 case NEXTHOP_TYPE_IPV4_IFINDEX:
8394 attr.nexthop = nexthop->ipv4;
8395 break;
8396 case NEXTHOP_TYPE_IPV6:
8397 case NEXTHOP_TYPE_IPV6_IFINDEX:
8398 attr.mp_nexthop_global = nexthop->ipv6;
8399 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8400 break;
8401 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8402 switch (p->family) {
8403 case AF_INET:
9de1f7ff 8404 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8405 break;
8406 case AF_INET6:
9de1f7ff
DS
8407 memset(&attr.mp_nexthop_global, 0,
8408 sizeof(attr.mp_nexthop_global));
74489921 8409 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8410 break;
74489921 8411 }
0789eb69 8412 attr.bh_type = bhtype;
9de1f7ff 8413 break;
d62a17ae 8414 }
0789eb69 8415 attr.nh_type = nhtype;
74489921 8416 attr.nh_ifindex = ifindex;
f04a80a5 8417
d62a17ae 8418 attr.med = metric;
957f74c3 8419 attr.distance = distance;
d62a17ae 8420 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8421 attr.tag = tag;
718e3744 8422
d62a17ae 8423 afi = family2afi(p->family);
6aeb9e78 8424
d62a17ae 8425 red = bgp_redist_lookup(bgp, afi, type, instance);
8426 if (red) {
8427 struct attr attr_new;
718e3744 8428
d62a17ae 8429 /* Copy attribute for modification. */
6f4f49b2 8430 attr_new = attr;
718e3744 8431
d62a17ae 8432 if (red->redist_metric_flag)
8433 attr_new.med = red->redist_metric;
718e3744 8434
d62a17ae 8435 /* Apply route-map. */
8436 if (red->rmap.name) {
6006b807 8437 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8438 rmap_path.peer = bgp->peer_self;
8439 rmap_path.attr = &attr_new;
718e3744 8440
d62a17ae 8441 SET_FLAG(bgp->peer_self->rmap_type,
8442 PEER_RMAP_TYPE_REDISTRIBUTE);
8443
1782514f 8444 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8445
8446 bgp->peer_self->rmap_type = 0;
8447
8448 if (ret == RMAP_DENYMATCH) {
8449 /* Free uninterned attribute. */
8450 bgp_attr_flush(&attr_new);
8451
8452 /* Unintern original. */
8453 aspath_unintern(&attr.aspath);
8454 bgp_redistribute_delete(bgp, p, type, instance);
8455 return;
8456 }
8457 }
8458
637e5ba4 8459 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8460 bgp_attr_add_gshut_community(&attr_new);
8461
d62a17ae 8462 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8463 SAFI_UNICAST, p, NULL);
8464
8465 new_attr = bgp_attr_intern(&attr_new);
8466
9bcb3eef 8467 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8468 if (bpi->peer == bgp->peer_self
8469 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8470 break;
8471
40381db7 8472 if (bpi) {
d62a17ae 8473 /* Ensure the (source route) type is updated. */
40381db7
DS
8474 bpi->type = type;
8475 if (attrhash_cmp(bpi->attr, new_attr)
8476 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8477 bgp_attr_unintern(&new_attr);
8478 aspath_unintern(&attr.aspath);
9bcb3eef 8479 bgp_dest_unlock_node(bn);
d62a17ae 8480 return;
8481 } else {
8482 /* The attribute is changed. */
40381db7 8483 bgp_path_info_set_flag(bn, bpi,
18ee8310 8484 BGP_PATH_ATTR_CHANGED);
d62a17ae 8485
8486 /* Rewrite BGP route information. */
40381db7
DS
8487 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8488 bgp_path_info_restore(bn, bpi);
d62a17ae 8489 else
40381db7
DS
8490 bgp_aggregate_decrement(
8491 bgp, p, bpi, afi, SAFI_UNICAST);
8492 bgp_attr_unintern(&bpi->attr);
8493 bpi->attr = new_attr;
8494 bpi->uptime = bgp_clock();
d62a17ae 8495
8496 /* Process change. */
40381db7 8497 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8498 SAFI_UNICAST);
8499 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8500 bgp_dest_unlock_node(bn);
d62a17ae 8501 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8502
8503 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8504 || (bgp->inst_type
8505 == BGP_INSTANCE_TYPE_DEFAULT)) {
8506
8507 vpn_leak_from_vrf_update(
40381db7 8508 bgp_get_default(), bgp, bpi);
ddb5b488 8509 }
d62a17ae 8510 return;
8511 }
8512 }
8513
8514 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8515 bgp->peer_self, new_attr, bn);
1defdda8 8516 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8517
8518 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8519 bgp_path_info_add(bn, new);
9bcb3eef 8520 bgp_dest_unlock_node(bn);
be785e35 8521 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8522 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8523
8524 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8525 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8526
8527 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8528 }
d62a17ae 8529 }
8530
8531 /* Unintern original. */
8532 aspath_unintern(&attr.aspath);
718e3744 8533}
8534
d7c0a89a
QY
8535void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8536 unsigned short instance)
718e3744 8537{
d62a17ae 8538 afi_t afi;
9bcb3eef 8539 struct bgp_dest *dest;
40381db7 8540 struct bgp_path_info *pi;
d62a17ae 8541 struct bgp_redist *red;
718e3744 8542
d62a17ae 8543 afi = family2afi(p->family);
718e3744 8544
d62a17ae 8545 red = bgp_redist_lookup(bgp, afi, type, instance);
8546 if (red) {
9bcb3eef
DS
8547 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8548 SAFI_UNICAST, p, NULL);
d62a17ae 8549
9bcb3eef 8550 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8551 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8552 break;
8553
40381db7 8554 if (pi) {
ddb5b488
PZ
8555 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8556 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8557
8558 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8559 bgp, pi);
ddb5b488 8560 }
40381db7 8561 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8562 bgp_path_info_delete(dest, pi);
8563 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8564 }
9bcb3eef 8565 bgp_dest_unlock_node(dest);
d62a17ae 8566 }
8567}
8568
8569/* Withdraw specified route type's route. */
8570void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8571 unsigned short instance)
d62a17ae 8572{
9bcb3eef 8573 struct bgp_dest *dest;
40381db7 8574 struct bgp_path_info *pi;
d62a17ae 8575 struct bgp_table *table;
8576
8577 table = bgp->rib[afi][SAFI_UNICAST];
8578
9bcb3eef
DS
8579 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8580 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8581 if (pi->peer == bgp->peer_self && pi->type == type
8582 && pi->instance == instance)
d62a17ae 8583 break;
8584
40381db7 8585 if (pi) {
ddb5b488
PZ
8586 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8587 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8588
8589 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8590 bgp, pi);
ddb5b488 8591 }
9bcb3eef 8592 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8593 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8594 bgp_path_info_delete(dest, pi);
8595 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8596 }
718e3744 8597 }
718e3744 8598}
6b0655a2 8599
718e3744 8600/* Static function to display route. */
7d3cae70
DA
8601static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8602 struct vty *vty, json_object *json, bool wide)
718e3744 8603{
be054588 8604 int len = 0;
d62a17ae 8605 char buf[BUFSIZ];
718e3744 8606
d62a17ae 8607 if (p->family == AF_INET) {
c6462ff4 8608 if (!json) {
8228a9a7 8609 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8610 } else {
8611 json_object_string_add(json, "prefix",
8612 inet_ntop(p->family,
8613 &p->u.prefix, buf,
8614 BUFSIZ));
8615 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8616 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8617 json_object_int_add(json, "version", dest->version);
c6462ff4 8618 }
d62a17ae 8619 } else if (p->family == AF_ETHERNET) {
8228a9a7 8620 len = vty_out(vty, "%pFX", p);
b03b8898 8621 } else if (p->family == AF_EVPN) {
57f7feb6 8622 if (!json)
2dbe669b 8623 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8624 else
60466a63 8625 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8626 } else if (p->family == AF_FLOWSPEC) {
8627 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8628 json ?
8629 NLRI_STRING_FORMAT_JSON_SIMPLE :
8630 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8631 } else {
c6462ff4 8632 if (!json)
8228a9a7 8633 len = vty_out(vty, "%pFX", p);
50e05855
AD
8634 else {
8635 json_object_string_add(json, "prefix",
8636 inet_ntop(p->family,
8637 &p->u.prefix, buf,
8638 BUFSIZ));
8639 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8640 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8641 json_object_int_add(json, "version", dest->version);
37d4e0df 8642 }
9c92b5f7 8643 }
d62a17ae 8644
9c92b5f7 8645 if (!json) {
ae248832 8646 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8647 if (len < 1)
8648 vty_out(vty, "\n%*s", 20, " ");
8649 else
8650 vty_out(vty, "%*s", len, " ");
8651 }
718e3744 8652}
8653
d62a17ae 8654enum bgp_display_type {
8655 normal_list,
718e3744 8656};
8657
1d7260a1 8658const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8659{
8660 switch (reason) {
8661 case bgp_path_selection_none:
8662 return "Nothing to Select";
8663 case bgp_path_selection_first:
8664 return "First path received";
8665 case bgp_path_selection_evpn_sticky_mac:
8666 return "EVPN Sticky Mac";
8667 case bgp_path_selection_evpn_seq:
8668 return "EVPN sequence number";
8669 case bgp_path_selection_evpn_lower_ip:
8670 return "EVPN lower IP";
8671 case bgp_path_selection_evpn_local_path:
8672 return "EVPN local ES path";
8673 case bgp_path_selection_evpn_non_proxy:
8674 return "EVPN non proxy";
8675 case bgp_path_selection_weight:
8676 return "Weight";
8677 case bgp_path_selection_local_pref:
8678 return "Local Pref";
8679 case bgp_path_selection_local_route:
8680 return "Local Route";
8681 case bgp_path_selection_confed_as_path:
8682 return "Confederation based AS Path";
8683 case bgp_path_selection_as_path:
8684 return "AS Path";
8685 case bgp_path_selection_origin:
8686 return "Origin";
8687 case bgp_path_selection_med:
8688 return "MED";
8689 case bgp_path_selection_peer:
8690 return "Peer Type";
8691 case bgp_path_selection_confed:
8692 return "Confed Peer Type";
8693 case bgp_path_selection_igp_metric:
8694 return "IGP Metric";
8695 case bgp_path_selection_older:
8696 return "Older Path";
8697 case bgp_path_selection_router_id:
8698 return "Router ID";
8699 case bgp_path_selection_cluster_length:
bcab253c 8700 return "Cluster length";
bbb46eb5
DA
8701 case bgp_path_selection_stale:
8702 return "Path Staleness";
8703 case bgp_path_selection_local_configured:
8704 return "Locally configured route";
8705 case bgp_path_selection_neighbor_ip:
8706 return "Neighbor IP";
8707 case bgp_path_selection_default:
8708 return "Nothing left to compare";
8709 }
8710 return "Invalid (internal error)";
8711}
8712
18ee8310 8713/* Print the short form route status for a bgp_path_info */
4b7e6066 8714static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8715 struct bgp_path_info *path,
82c298be 8716 const struct prefix *p,
d62a17ae 8717 json_object *json_path)
718e3744 8718{
82c298be
DA
8719 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8720
d62a17ae 8721 if (json_path) {
b05a1c8b 8722
d62a17ae 8723 /* Route status display. */
9b6d8fcf 8724 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8725 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8726
9b6d8fcf 8727 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8728 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8729
4056a5f6 8730 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8731 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8732
9b6d8fcf
DS
8733 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8734 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8735 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8736
d62a17ae 8737 /* Selected */
9b6d8fcf 8738 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8739 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8740
9b6d8fcf 8741 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8742 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8743
bbb46eb5 8744 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8745 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8746 json_object_string_add(json_path, "selectionReason",
8747 bgp_path_selection_reason2str(
8748 path->net->reason));
8749 }
b05a1c8b 8750
9b6d8fcf 8751 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8752 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8753
d62a17ae 8754 /* Internal route. */
9b6d8fcf
DS
8755 if ((path->peer->as)
8756 && (path->peer->as == path->peer->local_as))
d62a17ae 8757 json_object_string_add(json_path, "pathFrom",
8758 "internal");
8759 else
8760 json_object_string_add(json_path, "pathFrom",
8761 "external");
b05a1c8b 8762
d62a17ae 8763 return;
8764 }
b05a1c8b 8765
82c298be
DA
8766 /* RPKI validation state */
8767 rpki_state =
8768 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8769
8770 if (rpki_state == RPKI_VALID)
8771 vty_out(vty, "V");
8772 else if (rpki_state == RPKI_INVALID)
8773 vty_out(vty, "I");
8774 else if (rpki_state == RPKI_NOTFOUND)
8775 vty_out(vty, "N");
8776
d62a17ae 8777 /* Route status display. */
9b6d8fcf 8778 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8779 vty_out(vty, "R");
9b6d8fcf 8780 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8781 vty_out(vty, "S");
4056a5f6 8782 else if (bgp_path_suppressed(path))
d62a17ae 8783 vty_out(vty, "s");
9b6d8fcf
DS
8784 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8785 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8786 vty_out(vty, "*");
8787 else
8788 vty_out(vty, " ");
8789
8790 /* Selected */
9b6d8fcf 8791 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8792 vty_out(vty, "h");
9b6d8fcf 8793 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8794 vty_out(vty, "d");
9b6d8fcf 8795 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8796 vty_out(vty, ">");
9b6d8fcf 8797 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8798 vty_out(vty, "=");
8799 else
8800 vty_out(vty, " ");
718e3744 8801
d62a17ae 8802 /* Internal route. */
9b6d8fcf
DS
8803 if (path->peer && (path->peer->as)
8804 && (path->peer->as == path->peer->local_as))
d62a17ae 8805 vty_out(vty, "i");
8806 else
8807 vty_out(vty, " ");
b40d939b 8808}
8809
2ba93fd6
DA
8810static char *bgp_nexthop_hostname(struct peer *peer,
8811 struct bgp_nexthop_cache *bnc)
25b5da8d 8812{
892fedb6 8813 if (peer->hostname
aef999a2 8814 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8815 return peer->hostname;
8816 return NULL;
8817}
8818
b40d939b 8819/* called from terminal list command */
bd494ec5 8820void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8821 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8822 json_object *json_paths, bool wide)
d62a17ae 8823{
aef999a2 8824 int len;
515c2602 8825 struct attr *attr = path->attr;
d62a17ae 8826 json_object *json_path = NULL;
8827 json_object *json_nexthops = NULL;
8828 json_object *json_nexthop_global = NULL;
8829 json_object *json_nexthop_ll = NULL;
6f214dd3 8830 json_object *json_ext_community = NULL;
9df8b37c 8831 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8832 bool nexthop_self =
9b6d8fcf 8833 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8834 bool nexthop_othervrf = false;
43089216 8835 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8836 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8837 char *nexthop_hostname =
8838 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8839 char esi_buf[ESI_STR_LEN];
d62a17ae 8840
8841 if (json_paths)
8842 json_path = json_object_new_object();
8843
8844 /* short status lead text */
82c298be 8845 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8846
8847 if (!json_paths) {
8848 /* print prefix and mask */
8849 if (!display)
7d3cae70 8850 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8851 else
ae248832 8852 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8853 } else {
7d3cae70 8854 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8855 }
47fc97cc 8856
9df8b37c
PZ
8857 /*
8858 * If vrf id of nexthop is different from that of prefix,
8859 * set up printable string to append
8860 */
9b6d8fcf 8861 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8862 const char *self = "";
8863
8864 if (nexthop_self)
8865 self = "<";
8866
8867 nexthop_othervrf = true;
9b6d8fcf 8868 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8869
9b6d8fcf 8870 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8871 snprintf(vrf_id_str, sizeof(vrf_id_str),
8872 "@%s%s", VRFID_NONE_STR, self);
8873 else
8874 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8875 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8876
9b6d8fcf
DS
8877 if (path->extra->bgp_orig->inst_type
8878 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8879
9b6d8fcf 8880 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8881 } else {
8882 const char *self = "";
8883
8884 if (nexthop_self)
8885 self = "<";
8886
8887 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8888 }
8889
445c2480
DS
8890 /*
8891 * For ENCAP and EVPN routes, nexthop address family is not
8892 * neccessarily the same as the prefix address family.
8893 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8894 * EVPN routes are also exchanged with a MP nexthop. Currently,
8895 * this
8896 * is only IPv4, the value will be present in either
8897 * attr->nexthop or
8898 * attr->mp_nexthop_global_in
8899 */
8900 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8901 char buf[BUFSIZ];
8902 char nexthop[128];
8903 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8904
8905 switch (af) {
8906 case AF_INET:
772270f3
QY
8907 snprintf(nexthop, sizeof(nexthop), "%s",
8908 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8909 BUFSIZ));
445c2480
DS
8910 break;
8911 case AF_INET6:
772270f3
QY
8912 snprintf(nexthop, sizeof(nexthop), "%s",
8913 inet_ntop(af, &attr->mp_nexthop_global, buf,
8914 BUFSIZ));
445c2480
DS
8915 break;
8916 default:
772270f3 8917 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8918 break;
d62a17ae 8919 }
d62a17ae 8920
445c2480
DS
8921 if (json_paths) {
8922 json_nexthop_global = json_object_new_object();
8923
515c2602
DA
8924 json_object_string_add(json_nexthop_global, "ip",
8925 nexthop);
8926
939a97f4 8927 if (path->peer->hostname)
515c2602
DA
8928 json_object_string_add(json_nexthop_global,
8929 "hostname",
939a97f4 8930 path->peer->hostname);
515c2602
DA
8931
8932 json_object_string_add(json_nexthop_global, "afi",
8933 (af == AF_INET) ? "ipv4"
8934 : "ipv6");
445c2480
DS
8935 json_object_boolean_true_add(json_nexthop_global,
8936 "used");
aef999a2
DA
8937 } else {
8938 if (nexthop_hostname)
8939 len = vty_out(vty, "%s(%s)%s", nexthop,
8940 nexthop_hostname, vrf_id_str);
8941 else
8942 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8943
ae248832 8944 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8945 if (len < 1)
8946 vty_out(vty, "\n%*s", 36, " ");
8947 else
8948 vty_out(vty, "%*s", len, " ");
8949 }
445c2480
DS
8950 } else if (safi == SAFI_EVPN) {
8951 if (json_paths) {
8952 json_nexthop_global = json_object_new_object();
8953
c949c771
DA
8954 json_object_string_addf(json_nexthop_global, "ip",
8955 "%pI4", &attr->nexthop);
515c2602 8956
939a97f4 8957 if (path->peer->hostname)
515c2602
DA
8958 json_object_string_add(json_nexthop_global,
8959 "hostname",
939a97f4 8960 path->peer->hostname);
515c2602 8961
a4d82a8a
PZ
8962 json_object_string_add(json_nexthop_global, "afi",
8963 "ipv4");
445c2480
DS
8964 json_object_boolean_true_add(json_nexthop_global,
8965 "used");
aef999a2
DA
8966 } else {
8967 if (nexthop_hostname)
8968 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8969 nexthop_hostname, vrf_id_str);
8970 else
8971 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8972 vrf_id_str);
8973
ae248832 8974 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8975 if (len < 1)
8976 vty_out(vty, "\n%*s", 36, " ");
8977 else
8978 vty_out(vty, "%*s", len, " ");
8979 }
d33fc23b 8980 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8981 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8982 if (json_paths) {
8983 json_nexthop_global = json_object_new_object();
515c2602 8984
026b914a
PG
8985 json_object_string_add(json_nexthop_global,
8986 "afi", "ipv4");
c949c771
DA
8987 json_object_string_addf(json_nexthop_global,
8988 "ip", "%pI4",
8989 &attr->nexthop);
515c2602 8990
939a97f4 8991 if (path->peer->hostname)
515c2602
DA
8992 json_object_string_add(
8993 json_nexthop_global, "hostname",
939a97f4 8994 path->peer->hostname);
515c2602 8995
50e05855
AD
8996 json_object_boolean_true_add(
8997 json_nexthop_global,
026b914a
PG
8998 "used");
8999 } else {
aef999a2
DA
9000 if (nexthop_hostname)
9001 len = vty_out(vty, "%pI4(%s)%s",
9002 &attr->nexthop,
9003 nexthop_hostname,
9004 vrf_id_str);
9005 else
9006 len = vty_out(vty, "%pI4%s",
9007 &attr->nexthop,
9008 vrf_id_str);
9009
ae248832 9010 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9011 if (len < 1)
9012 vty_out(vty, "\n%*s", 36, " ");
9013 else
9014 vty_out(vty, "%*s", len, " ");
026b914a
PG
9015 }
9016 }
d33fc23b 9017 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
9018 if (json_paths) {
9019 json_nexthop_global = json_object_new_object();
d62a17ae 9020
c949c771
DA
9021 json_object_string_addf(json_nexthop_global, "ip",
9022 "%pI4", &attr->nexthop);
515c2602 9023
939a97f4 9024 if (path->peer->hostname)
515c2602
DA
9025 json_object_string_add(json_nexthop_global,
9026 "hostname",
939a97f4 9027 path->peer->hostname);
445c2480 9028
a4d82a8a
PZ
9029 json_object_string_add(json_nexthop_global, "afi",
9030 "ipv4");
445c2480
DS
9031 json_object_boolean_true_add(json_nexthop_global,
9032 "used");
9033 } else {
aef999a2
DA
9034 if (nexthop_hostname)
9035 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9036 nexthop_hostname, vrf_id_str);
9037 else
9038 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9039 vrf_id_str);
9df8b37c 9040
ae248832 9041 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9042 if (len < 1)
9043 vty_out(vty, "\n%*s", 36, " ");
9044 else
9045 vty_out(vty, "%*s", len, " ");
d62a17ae 9046 }
445c2480 9047 }
b05a1c8b 9048
445c2480 9049 /* IPv6 Next Hop */
a4d82a8a 9050 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
9051 if (json_paths) {
9052 json_nexthop_global = json_object_new_object();
c949c771
DA
9053 json_object_string_addf(json_nexthop_global, "ip",
9054 "%pI6",
9055 &attr->mp_nexthop_global);
515c2602 9056
939a97f4 9057 if (path->peer->hostname)
515c2602
DA
9058 json_object_string_add(json_nexthop_global,
9059 "hostname",
939a97f4 9060 path->peer->hostname);
515c2602 9061
a4d82a8a
PZ
9062 json_object_string_add(json_nexthop_global, "afi",
9063 "ipv6");
9064 json_object_string_add(json_nexthop_global, "scope",
9065 "global");
445c2480
DS
9066
9067 /* We display both LL & GL if both have been
9068 * received */
0606039c
DA
9069 if ((attr->mp_nexthop_len
9070 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9071 || (path->peer->conf_if)) {
a4d82a8a 9072 json_nexthop_ll = json_object_new_object();
c949c771
DA
9073 json_object_string_addf(
9074 json_nexthop_ll, "ip", "%pI6",
9075 &attr->mp_nexthop_local);
515c2602 9076
939a97f4 9077 if (path->peer->hostname)
515c2602
DA
9078 json_object_string_add(
9079 json_nexthop_ll, "hostname",
939a97f4 9080 path->peer->hostname);
515c2602 9081
a4d82a8a
PZ
9082 json_object_string_add(json_nexthop_ll, "afi",
9083 "ipv6");
9084 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9085 "link-local");
d62a17ae 9086
a4d82a8a
PZ
9087 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9088 &attr->mp_nexthop_local)
445c2480
DS
9089 != 0)
9090 && !attr->mp_nexthop_prefer_global)
d62a17ae 9091 json_object_boolean_true_add(
a4d82a8a 9092 json_nexthop_ll, "used");
445c2480
DS
9093 else
9094 json_object_boolean_true_add(
a4d82a8a 9095 json_nexthop_global, "used");
445c2480
DS
9096 } else
9097 json_object_boolean_true_add(
9098 json_nexthop_global, "used");
9099 } else {
9100 /* Display LL if LL/Global both in table unless
9101 * prefer-global is set */
0606039c
DA
9102 if (((attr->mp_nexthop_len
9103 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9104 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9105 || (path->peer->conf_if)) {
9106 if (path->peer->conf_if) {
a4d82a8a 9107 len = vty_out(vty, "%s",
9b6d8fcf 9108 path->peer->conf_if);
ae248832
MK
9109 /* len of IPv6 addr + max len of def
9110 * ifname */
9111 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9112
9113 if (len < 1)
a4d82a8a 9114 vty_out(vty, "\n%*s", 36, " ");
445c2480 9115 else
a4d82a8a 9116 vty_out(vty, "%*s", len, " ");
d62a17ae 9117 } else {
aef999a2
DA
9118 if (nexthop_hostname)
9119 len = vty_out(
9120 vty, "%pI6(%s)%s",
9121 &attr->mp_nexthop_local,
9122 nexthop_hostname,
9123 vrf_id_str);
9124 else
9125 len = vty_out(
9126 vty, "%pI6%s",
9127 &attr->mp_nexthop_local,
9128 vrf_id_str);
9129
ae248832 9130 len = wide ? (41 - len) : (16 - len);
d62a17ae 9131
9132 if (len < 1)
a4d82a8a 9133 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9134 else
a4d82a8a 9135 vty_out(vty, "%*s", len, " ");
d62a17ae 9136 }
445c2480 9137 } else {
aef999a2
DA
9138 if (nexthop_hostname)
9139 len = vty_out(vty, "%pI6(%s)%s",
9140 &attr->mp_nexthop_global,
9141 nexthop_hostname,
9142 vrf_id_str);
9143 else
9144 len = vty_out(vty, "%pI6%s",
9145 &attr->mp_nexthop_global,
9146 vrf_id_str);
9147
ae248832 9148 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9149
9150 if (len < 1)
9151 vty_out(vty, "\n%*s", 36, " ");
9152 else
9153 vty_out(vty, "%*s", len, " ");
d62a17ae 9154 }
9155 }
445c2480 9156 }
718e3744 9157
445c2480
DS
9158 /* MED/Metric */
9159 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9160 if (json_paths)
50e05855 9161 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9162 else if (wide)
9163 vty_out(vty, "%7u", attr->med);
0fbac0b4 9164 else
445c2480 9165 vty_out(vty, "%10u", attr->med);
ae248832
MK
9166 else if (!json_paths) {
9167 if (wide)
9168 vty_out(vty, "%*s", 7, " ");
9169 else
9170 vty_out(vty, "%*s", 10, " ");
9171 }
d62a17ae 9172
445c2480
DS
9173 /* Local Pref */
9174 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9175 if (json_paths)
50e05855 9176 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9177 attr->local_pref);
9178 else
445c2480
DS
9179 vty_out(vty, "%7u", attr->local_pref);
9180 else if (!json_paths)
9181 vty_out(vty, " ");
d62a17ae 9182
445c2480
DS
9183 if (json_paths)
9184 json_object_int_add(json_path, "weight", attr->weight);
9185 else
9186 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9187
47e12884
DA
9188 if (json_paths)
9189 json_object_string_addf(json_path, "peerId", "%pSU",
9190 &path->peer->su);
b05a1c8b 9191
445c2480
DS
9192 /* Print aspath */
9193 if (attr->aspath) {
0fbac0b4 9194 if (json_paths)
50e05855 9195 json_object_string_add(json_path, "path",
0fbac0b4
DA
9196 attr->aspath->str);
9197 else
445c2480 9198 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9199 }
f1aa5d8a 9200
445c2480
DS
9201 /* Print origin */
9202 if (json_paths)
a4d82a8a
PZ
9203 json_object_string_add(json_path, "origin",
9204 bgp_origin_long_str[attr->origin]);
445c2480
DS
9205 else
9206 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9207
9df8b37c 9208 if (json_paths) {
d071f237 9209 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9210 json_object_string_add(json_path, "esi",
9211 esi_to_str(&attr->esi,
9212 esi_buf, sizeof(esi_buf)));
9213 }
6f214dd3
CS
9214 if (safi == SAFI_EVPN &&
9215 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9216 json_ext_community = json_object_new_object();
b53e67a3
DA
9217 json_object_string_add(
9218 json_ext_community, "string",
9219 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9220 json_object_object_add(json_path,
9221 "extendedCommunity",
9222 json_ext_community);
9223 }
9224
9df8b37c
PZ
9225 if (nexthop_self)
9226 json_object_boolean_true_add(json_path,
9227 "announceNexthopSelf");
9228 if (nexthop_othervrf) {
9229 json_object_string_add(json_path, "nhVrfName",
9230 nexthop_vrfname);
9231
9232 json_object_int_add(json_path, "nhVrfId",
9233 ((nexthop_vrfid == VRF_UNKNOWN)
9234 ? -1
9235 : (int)nexthop_vrfid));
9236 }
9237 }
9238
d62a17ae 9239 if (json_paths) {
9240 if (json_nexthop_global || json_nexthop_ll) {
9241 json_nexthops = json_object_new_array();
f1aa5d8a 9242
d62a17ae 9243 if (json_nexthop_global)
9244 json_object_array_add(json_nexthops,
9245 json_nexthop_global);
f1aa5d8a 9246
d62a17ae 9247 if (json_nexthop_ll)
9248 json_object_array_add(json_nexthops,
9249 json_nexthop_ll);
f1aa5d8a 9250
d62a17ae 9251 json_object_object_add(json_path, "nexthops",
9252 json_nexthops);
9253 }
9254
9255 json_object_array_add(json_paths, json_path);
9256 } else {
9257 vty_out(vty, "\n");
6f214dd3 9258
b5e140c8 9259 if (safi == SAFI_EVPN) {
d071f237 9260 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9261 /* XXX - add these params to the json out */
b5e140c8 9262 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9263 vty_out(vty, "ESI:%s",
9264 esi_to_str(&attr->esi, esi_buf,
9265 sizeof(esi_buf)));
60605cbc 9266
229587fb 9267 vty_out(vty, "\n");
b5e140c8
AK
9268 }
9269 if (attr->flag &
9270 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9271 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9272 vty_out(vty, "%s\n",
9273 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9274 }
6f214dd3
CS
9275 }
9276
49e5a4a0 9277#ifdef ENABLE_BGP_VNC
d62a17ae 9278 /* prints an additional line, indented, with VNC info, if
9279 * present */
9280 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9281 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9282#endif
d62a17ae 9283 }
9284}
718e3744 9285
9286/* called from terminal list command */
7d3cae70
DA
9287void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9288 const struct prefix *p, struct attr *attr, safi_t safi,
9289 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9290{
9291 json_object *json_status = NULL;
9292 json_object *json_net = NULL;
aef999a2 9293 int len;
d62a17ae 9294 char buff[BUFSIZ];
dc387b0f 9295
d62a17ae 9296 /* Route status display. */
9297 if (use_json) {
9298 json_status = json_object_new_object();
9299 json_net = json_object_new_object();
9300 } else {
9301 vty_out(vty, "*");
9302 vty_out(vty, ">");
9303 vty_out(vty, " ");
9304 }
718e3744 9305
d62a17ae 9306 /* print prefix and mask */
50e05855 9307 if (use_json) {
dc387b0f
LK
9308 if (safi == SAFI_EVPN)
9309 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9310 else if (p->family == AF_INET || p->family == AF_INET6) {
9311 json_object_string_add(
9312 json_net, "addrPrefix",
9313 inet_ntop(p->family, &p->u.prefix, buff,
9314 BUFSIZ));
9315 json_object_int_add(json_net, "prefixLen",
9316 p->prefixlen);
67d7e256 9317 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9318 }
50e05855 9319 } else
7d3cae70 9320 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9321
9322 /* Print attribute */
9323 if (attr) {
9324 if (use_json) {
9325 if (p->family == AF_INET
9326 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9327 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9328 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9329 json_object_string_addf(
9330 json_net, "nextHop", "%pI4",
9331 &attr->mp_nexthop_global_in);
d62a17ae 9332 else
c949c771
DA
9333 json_object_string_addf(
9334 json_net, "nextHop", "%pI4",
9335 &attr->nexthop);
d62a17ae 9336 } else if (p->family == AF_INET6
9337 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9338 json_object_string_addf(
9339 json_net, "nextHopGlobal", "%pI6",
9340 &attr->mp_nexthop_global);
23d0a753
DA
9341 } else if (p->family == AF_EVPN
9342 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9343 json_object_string_addf(
9344 json_net, "nextHop", "%pI4",
9345 &attr->mp_nexthop_global_in);
23d0a753 9346 }
d62a17ae 9347
9348 if (attr->flag
9349 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9350 json_object_int_add(json_net, "metric",
9351 attr->med);
9352
0fbac0b4 9353 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9354 json_object_int_add(json_net, "locPrf",
0fbac0b4 9355 attr->local_pref);
d62a17ae 9356
9357 json_object_int_add(json_net, "weight", attr->weight);
9358
9359 /* Print aspath */
0fbac0b4 9360 if (attr->aspath)
50e05855 9361 json_object_string_add(json_net, "path",
0fbac0b4 9362 attr->aspath->str);
d62a17ae 9363
9364 /* Print origin */
9365 json_object_string_add(json_net, "bgpOriginCode",
9366 bgp_origin_str[attr->origin]);
9367 } else {
9368 if (p->family == AF_INET
9369 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9370 || safi == SAFI_EVPN
9371 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9372 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9373 || safi == SAFI_EVPN)
23d0a753
DA
9374 vty_out(vty, "%-16pI4",
9375 &attr->mp_nexthop_global_in);
ae248832 9376 else if (wide)
23d0a753 9377 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9378 else
23d0a753 9379 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9380 } else if (p->family == AF_INET6
9381 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9382 char buf[BUFSIZ];
9383
9384 len = vty_out(
9385 vty, "%s",
9386 inet_ntop(AF_INET6,
9387 &attr->mp_nexthop_global, buf,
9388 BUFSIZ));
ae248832 9389 len = wide ? (41 - len) : (16 - len);
d62a17ae 9390 if (len < 1)
9391 vty_out(vty, "\n%*s", 36, " ");
9392 else
9393 vty_out(vty, "%*s", len, " ");
9394 }
9395 if (attr->flag
9396 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9397 if (wide)
9398 vty_out(vty, "%7u", attr->med);
9399 else
9400 vty_out(vty, "%10u", attr->med);
9401 else if (wide)
9402 vty_out(vty, " ");
d62a17ae 9403 else
9404 vty_out(vty, " ");
718e3744 9405
d62a17ae 9406 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9407 vty_out(vty, "%7u", attr->local_pref);
9408 else
9409 vty_out(vty, " ");
9410
9411 vty_out(vty, "%7u ", attr->weight);
9412
9413 /* Print aspath */
9414 if (attr->aspath)
9415 aspath_print_vty(vty, "%s", attr->aspath, " ");
9416
9417 /* Print origin */
9418 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9419 }
9420 }
9421 if (use_json) {
9422 json_object_boolean_true_add(json_status, "*");
9423 json_object_boolean_true_add(json_status, ">");
9424 json_object_object_add(json_net, "appliedStatusSymbols",
9425 json_status);
1608ff77 9426
dc387b0f
LK
9427 prefix2str(p, buff, PREFIX_STRLEN);
9428 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9429 } else
9430 vty_out(vty, "\n");
9431}
9432
bd494ec5 9433void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9434 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9435 json_object *json)
9436{
9437 json_object *json_out = NULL;
9438 struct attr *attr;
9439 mpls_label_t label = MPLS_INVALID_LABEL;
9440
9b6d8fcf 9441 if (!path->extra)
d62a17ae 9442 return;
9443
9444 if (json)
9445 json_out = json_object_new_object();
9446
9447 /* short status lead text */
82c298be 9448 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9449
9450 /* print prefix and mask */
9451 if (json == NULL) {
9452 if (!display)
7d3cae70 9453 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9454 else
9455 vty_out(vty, "%*s", 17, " ");
9456 }
9457
9458 /* Print attribute */
9b6d8fcf 9459 attr = path->attr;
05864da7
DS
9460 if (((p->family == AF_INET)
9461 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9462 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9463 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9464 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9465 || safi == SAFI_EVPN) {
9466 if (json)
c949c771
DA
9467 json_object_string_addf(
9468 json_out, "mpNexthopGlobalIn", "%pI4",
9469 &attr->mp_nexthop_global_in);
05864da7 9470 else
23d0a753
DA
9471 vty_out(vty, "%-16pI4",
9472 &attr->mp_nexthop_global_in);
05864da7
DS
9473 } else {
9474 if (json)
c949c771
DA
9475 json_object_string_addf(json_out, "nexthop",
9476 "%pI4", &attr->nexthop);
05864da7 9477 else
23d0a753 9478 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9479 }
9480 } else if (((p->family == AF_INET6)
9481 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9482 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9483 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9484 char buf_a[512];
9485
9486 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9487 if (json)
c949c771
DA
9488 json_object_string_addf(
9489 json_out, "mpNexthopGlobalIn", "%pI6",
9490 &attr->mp_nexthop_global);
05864da7
DS
9491 else
9492 vty_out(vty, "%s",
9493 inet_ntop(AF_INET6,
9494 &attr->mp_nexthop_global,
9495 buf_a, sizeof(buf_a)));
9496 } else if (attr->mp_nexthop_len
9497 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9498 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9499 &attr->mp_nexthop_global,
9500 &attr->mp_nexthop_local);
9501 if (json)
9502 json_object_string_add(json_out,
9503 "mpNexthopGlobalLocal",
9504 buf_a);
9505 else
9506 vty_out(vty, "%s", buf_a);
d62a17ae 9507 }
9508 }
9509
9b6d8fcf 9510 label = decode_label(&path->extra->label[0]);
d62a17ae 9511
9512 if (bgp_is_valid_label(&label)) {
9513 if (json) {
9514 json_object_int_add(json_out, "notag", label);
9515 json_object_array_add(json, json_out);
9516 } else {
9517 vty_out(vty, "notag/%d", label);
9518 vty_out(vty, "\n");
9519 }
700ddfed
PG
9520 } else if (!json)
9521 vty_out(vty, "\n");
d62a17ae 9522}
718e3744 9523
bd494ec5 9524void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9525 struct bgp_path_info *path, int display,
d62a17ae 9526 json_object *json_paths)
718e3744 9527{
d62a17ae 9528 struct attr *attr;
d62a17ae 9529 json_object *json_path = NULL;
14f51eba
LK
9530 json_object *json_nexthop = NULL;
9531 json_object *json_overlay = NULL;
856ca177 9532
9b6d8fcf 9533 if (!path->extra)
d62a17ae 9534 return;
718e3744 9535
14f51eba
LK
9536 if (json_paths) {
9537 json_path = json_object_new_object();
9538 json_overlay = json_object_new_object();
9539 json_nexthop = json_object_new_object();
9540 }
9541
d62a17ae 9542 /* short status lead text */
82c298be 9543 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9544
d62a17ae 9545 /* print prefix and mask */
9546 if (!display)
7d3cae70 9547 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9548 else
9549 vty_out(vty, "%*s", 17, " ");
9550
9551 /* Print attribute */
9b6d8fcf 9552 attr = path->attr;
05864da7 9553 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9554
05864da7
DS
9555 switch (af) {
9556 case AF_INET:
05864da7 9557 if (!json_path) {
db66cf7c 9558 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9559 } else {
db66cf7c
DA
9560 json_object_string_addf(json_nexthop, "ip", "%pI4",
9561 &attr->mp_nexthop_global_in);
14f51eba 9562
05864da7 9563 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9564
05864da7
DS
9565 json_object_object_add(json_path, "nexthop",
9566 json_nexthop);
9567 }
9568 break;
9569 case AF_INET6:
05864da7 9570 if (!json_path) {
db66cf7c
DA
9571 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9572 &attr->mp_nexthop_local);
05864da7 9573 } else {
db66cf7c
DA
9574 json_object_string_addf(json_nexthop, "ipv6Global",
9575 "%pI6",
9576 &attr->mp_nexthop_global);
14f51eba 9577
db66cf7c
DA
9578 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9579 "%pI6",
9580 &attr->mp_nexthop_local);
14f51eba 9581
05864da7 9582 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9583
05864da7
DS
9584 json_object_object_add(json_path, "nexthop",
9585 json_nexthop);
9586 }
9587 break;
9588 default:
9589 if (!json_path) {
9590 vty_out(vty, "?");
9591 } else {
9592 json_object_string_add(json_nexthop, "Error",
9593 "Unsupported address-family");
77a2f8e5
DA
9594 json_object_string_add(json_nexthop, "error",
9595 "Unsupported address-family");
d62a17ae 9596 }
05864da7 9597 }
988258b4 9598
6c924775
DS
9599 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9600
05864da7 9601 if (!json_path)
db66cf7c 9602 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9603 else
db66cf7c 9604 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9605
b53e67a3 9606 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9607 char *mac = NULL;
9608 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9609 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9610 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9611
9612 if (routermac)
9613 mac = ecom_mac2str((char *)routermac->val);
9614 if (mac) {
9615 if (!json_path) {
c4efd0f4 9616 vty_out(vty, "/%s", mac);
05864da7
DS
9617 } else {
9618 json_object_string_add(json_overlay, "rmac",
9619 mac);
988258b4 9620 }
05864da7 9621 XFREE(MTYPE_TMP, mac);
988258b4 9622 }
05864da7 9623 }
718e3744 9624
05864da7
DS
9625 if (!json_path) {
9626 vty_out(vty, "\n");
9627 } else {
9628 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9629
05864da7 9630 json_object_array_add(json_paths, json_path);
14f51eba 9631 }
d62a17ae 9632}
718e3744 9633
d62a17ae 9634/* dampening route */
5f040085
DS
9635static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9636 struct bgp_path_info *path, int display,
9637 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9638 json_object *json_paths)
d62a17ae 9639{
e5be8c1d 9640 struct attr *attr = path->attr;
d62a17ae 9641 int len;
9642 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9643 json_object *json_path = NULL;
9644
9645 if (use_json)
9646 json_path = json_object_new_object();
d62a17ae 9647
9648 /* short status lead text */
e5be8c1d 9649 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9650
9651 /* print prefix and mask */
9652 if (!use_json) {
9653 if (!display)
7d3cae70 9654 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9655 else
9656 vty_out(vty, "%*s", 17, " ");
d62a17ae 9657
e5be8c1d
DA
9658 len = vty_out(vty, "%s", path->peer->host);
9659 len = 17 - len;
9660
9661 if (len < 1)
d62a17ae 9662 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9663 else
9664 vty_out(vty, "%*s", len, " ");
d62a17ae 9665
9b6d8fcf
DS
9666 vty_out(vty, "%s ",
9667 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9668 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9669 use_json, NULL));
d62a17ae 9670
e5be8c1d 9671 if (attr->aspath)
05864da7 9672 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9673
05864da7
DS
9674 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9675
d62a17ae 9676 vty_out(vty, "\n");
e5be8c1d
DA
9677 } else {
9678 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9679 safi, use_json, json_path);
9680
9681 if (attr->aspath)
9682 json_object_string_add(json_path, "asPath",
9683 attr->aspath->str);
9684
9685 json_object_string_add(json_path, "origin",
9686 bgp_origin_str[attr->origin]);
9687 json_object_string_add(json_path, "peerHost", path->peer->host);
9688
9689 json_object_array_add(json_paths, json_path);
9690 }
d62a17ae 9691}
718e3744 9692
d62a17ae 9693/* flap route */
5f040085
DS
9694static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9695 struct bgp_path_info *path, int display,
9696 afi_t afi, safi_t safi, bool use_json,
31258046 9697 json_object *json_paths)
784d3a42 9698{
31258046 9699 struct attr *attr = path->attr;
d62a17ae 9700 struct bgp_damp_info *bdi;
9701 char timebuf[BGP_UPTIME_LEN];
9702 int len;
31258046 9703 json_object *json_path = NULL;
784d3a42 9704
9b6d8fcf 9705 if (!path->extra)
d62a17ae 9706 return;
784d3a42 9707
31258046
DA
9708 if (use_json)
9709 json_path = json_object_new_object();
9710
9b6d8fcf 9711 bdi = path->extra->damp_info;
784d3a42 9712
d62a17ae 9713 /* short status lead text */
31258046 9714 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9715
d62a17ae 9716 if (!use_json) {
9717 if (!display)
7d3cae70 9718 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9719 else
9720 vty_out(vty, "%*s", 17, " ");
784d3a42 9721
31258046
DA
9722 len = vty_out(vty, "%s", path->peer->host);
9723 len = 16 - len;
9724 if (len < 1)
d62a17ae 9725 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9726 else
9727 vty_out(vty, "%*s", len, " ");
784d3a42 9728
31258046
DA
9729 len = vty_out(vty, "%d", bdi->flap);
9730 len = 5 - len;
9731 if (len < 1)
d62a17ae 9732 vty_out(vty, " ");
d62a17ae 9733 else
9734 vty_out(vty, "%*s", len, " ");
d62a17ae 9735
996c9314
LB
9736 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9737 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9738
31258046
DA
9739 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9740 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9741 vty_out(vty, "%s ",
9b6d8fcf 9742 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9743 BGP_UPTIME_LEN, afi,
31258046
DA
9744 safi, use_json, NULL));
9745 else
d62a17ae 9746 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9747
31258046 9748 if (attr->aspath)
05864da7 9749 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9750
05864da7
DS
9751 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9752
d62a17ae 9753 vty_out(vty, "\n");
31258046
DA
9754 } else {
9755 json_object_string_add(json_path, "peerHost", path->peer->host);
9756 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9757
9758 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9759 json_path);
9760
9761 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9762 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9763 bgp_damp_reuse_time_vty(vty, path, timebuf,
9764 BGP_UPTIME_LEN, afi, safi,
9765 use_json, json_path);
9766
9767 if (attr->aspath)
9768 json_object_string_add(json_path, "asPath",
9769 attr->aspath->str);
9770
9771 json_object_string_add(json_path, "origin",
9772 bgp_origin_str[attr->origin]);
9773
9774 json_object_array_add(json_paths, json_path);
9775 }
d62a17ae 9776}
9777
9778static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9779 int *first, const char *header,
9780 json_object *json_adv_to)
9781{
d62a17ae 9782 json_object *json_peer = NULL;
9783
9784 if (json_adv_to) {
9785 /* 'advertised-to' is a dictionary of peers we have advertised
9786 * this
9787 * prefix too. The key is the peer's IP or swpX, the value is
9788 * the
9789 * hostname if we know it and "" if not.
9790 */
9791 json_peer = json_object_new_object();
9792
9793 if (peer->hostname)
9794 json_object_string_add(json_peer, "hostname",
9795 peer->hostname);
9796
9797 if (peer->conf_if)
9798 json_object_object_add(json_adv_to, peer->conf_if,
9799 json_peer);
9800 else
47e12884
DA
9801 json_object_object_addf(json_adv_to, json_peer, "%pSU",
9802 &peer->su);
d62a17ae 9803 } else {
9804 if (*first) {
9805 vty_out(vty, "%s", header);
9806 *first = 0;
9807 }
9808
9809 if (peer->hostname
892fedb6 9810 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9811 if (peer->conf_if)
9812 vty_out(vty, " %s(%s)", peer->hostname,
9813 peer->conf_if);
9814 else
47e12884
DA
9815 vty_out(vty, " %s(%pSU)", peer->hostname,
9816 &peer->su);
d62a17ae 9817 } else {
9818 if (peer->conf_if)
9819 vty_out(vty, " %s", peer->conf_if);
9820 else
47e12884 9821 vty_out(vty, " %pSU", &peer->su);
d62a17ae 9822 }
9823 }
784d3a42
PG
9824}
9825
dcc68b5e
MS
9826static void route_vty_out_tx_ids(struct vty *vty,
9827 struct bgp_addpath_info_data *d)
9828{
9829 int i;
9830
9831 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9832 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9833 d->addpath_tx_id[i],
9834 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9835 }
9836}
9837
5e4d4c8a 9838static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9839 struct bgp_path_info *pi,
9840 struct attr *attr,
9841 json_object *json_path)
5e4d4c8a
AK
9842{
9843 char esi_buf[ESI_STR_LEN];
9844 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9845 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9846 ATTR_ES_PEER_ROUTER);
9847 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9848 ATTR_ES_PEER_ACTIVE);
9849 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9850 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9851 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9852 if (json_path) {
9853 json_object *json_es_info = NULL;
9854
9855 json_object_string_add(
9856 json_path, "esi",
9857 esi_buf);
9858 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9859 json_es_info = json_object_new_object();
9860 if (es_local)
9861 json_object_boolean_true_add(
9862 json_es_info, "localEs");
9863 if (peer_active)
9864 json_object_boolean_true_add(
9865 json_es_info, "peerActive");
9866 if (peer_proxy)
9867 json_object_boolean_true_add(
9868 json_es_info, "peerProxy");
9869 if (peer_router)
9870 json_object_boolean_true_add(
9871 json_es_info, "peerRouter");
9872 if (attr->mm_sync_seqnum)
9873 json_object_int_add(
9874 json_es_info, "peerSeq",
9875 attr->mm_sync_seqnum);
9876 json_object_object_add(
9877 json_path, "es_info",
9878 json_es_info);
9879 }
9880 } else {
9881 if (bgp_evpn_attr_is_sync(attr))
9882 vty_out(vty,
9883 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9884 esi_buf,
9885 es_local ? "local-es":"",
9886 peer_proxy ? "proxy " : "",
9887 peer_active ? "active ":"",
9888 peer_router ? "router ":"",
9889 attr->mm_sync_seqnum);
9890 else
9891 vty_out(vty, " ESI %s %s\n",
9892 esi_buf,
9893 es_local ? "local-es":"");
9894 }
9895}
9896
4933eaaf
DS
9897void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9898 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9899 enum rpki_states rpki_curr_state,
9900 json_object *json_paths)
d62a17ae 9901{
9902 char buf[INET6_ADDRSTRLEN];
9903 char buf1[BUFSIZ];
515c2602 9904 struct attr *attr = path->attr;
d62a17ae 9905 time_t tbuf;
9906 json_object *json_bestpath = NULL;
9907 json_object *json_cluster_list = NULL;
9908 json_object *json_cluster_list_list = NULL;
9909 json_object *json_ext_community = NULL;
9910 json_object *json_last_update = NULL;
7fd077aa 9911 json_object *json_pmsi = NULL;
d62a17ae 9912 json_object *json_nexthop_global = NULL;
9913 json_object *json_nexthop_ll = NULL;
9914 json_object *json_nexthops = NULL;
9915 json_object *json_path = NULL;
9916 json_object *json_peer = NULL;
9917 json_object *json_string = NULL;
9918 json_object *json_adv_to = NULL;
9919 int first = 0;
9920 struct listnode *node, *nnode;
9921 struct peer *peer;
be92fc9f 9922 bool addpath_capable;
d62a17ae 9923 int has_adj;
9924 unsigned int first_as;
1defdda8 9925 bool nexthop_self =
9b6d8fcf 9926 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9927 int i;
2ba93fd6
DA
9928 char *nexthop_hostname =
9929 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
9930 uint32_t ttl = 0;
9931 uint32_t bos = 0;
9932 uint32_t exp = 0;
9933 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 9934
9935 if (json_paths) {
9936 json_path = json_object_new_object();
9937 json_peer = json_object_new_object();
9938 json_nexthop_global = json_object_new_object();
9939 }
9940
8304dabf
AD
9941 if (safi == SAFI_EVPN) {
9942 if (!json_paths)
9943 vty_out(vty, " Route %pRN", bn);
9944 }
9945
44c69747 9946 if (path->extra) {
b57ba6d2 9947 char tag_buf[30];
d62a17ae 9948
d62a17ae 9949 tag_buf[0] = '\0';
9b6d8fcf
DS
9950 if (path->extra && path->extra->num_labels) {
9951 bgp_evpn_label2str(path->extra->label,
9952 path->extra->num_labels, tag_buf,
a4d82a8a 9953 sizeof(tag_buf));
d62a17ae 9954 }
d7325ee7 9955 if (safi == SAFI_EVPN) {
44c69747 9956 if (!json_paths) {
44c69747
LK
9957 if (tag_buf[0] != '\0')
9958 vty_out(vty, " VNI %s", tag_buf);
44c69747 9959 } else {
77a2f8e5 9960 if (tag_buf[0]) {
44c69747
LK
9961 json_object_string_add(json_path, "VNI",
9962 tag_buf);
77a2f8e5
DA
9963 json_object_string_add(json_path, "vni",
9964 tag_buf);
9965 }
44c69747 9966 }
d7325ee7
DD
9967 }
9968
44c69747 9969 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9970 struct bgp_path_info *parent_ri;
9bcb3eef 9971 struct bgp_dest *dest, *pdest;
d62a17ae 9972
9b6d8fcf 9973 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9974 dest = parent_ri->net;
9975 if (dest && dest->pdest) {
9976 pdest = dest->pdest;
9977 prefix_rd2str(
9978 (struct prefix_rd *)bgp_dest_get_prefix(
9979 pdest),
9980 buf1, sizeof(buf1));
d7325ee7 9981 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9982 vty_out(vty,
58bff4d1 9983 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9984 buf1,
9985 (struct prefix_evpn *)
9986 bgp_dest_get_prefix(
9987 dest),
9988 tag_buf);
58bff4d1
AK
9989 if (attr->es_flags & ATTR_ES_L3_NHG)
9990 vty_out(vty, ", L3NHG %s",
9991 (attr->es_flags
9992 & ATTR_ES_L3_NHG_ACTIVE)
9993 ? "active"
9994 : "inactive");
9995 vty_out(vty, "\n");
9996
d7325ee7 9997 } else
2dbe669b
DA
9998 vty_out(vty,
9999 " Imported from %s:%pFX\n",
10000 buf1,
10001 (struct prefix_evpn *)
10002 bgp_dest_get_prefix(
10003 dest));
d62a17ae 10004 }
10005 }
10006 }
d62a17ae 10007
8304dabf
AD
10008 if (safi == SAFI_EVPN
10009 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10010 char gwip_buf[INET6_ADDRSTRLEN];
10011
860e740b
IR
10012 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10013 sizeof(gwip_buf));
8304dabf
AD
10014
10015 if (json_paths)
10016 json_object_string_add(json_path, "gatewayIP",
10017 gwip_buf);
10018 else
10019 vty_out(vty, " Gateway IP %s", gwip_buf);
10020 }
10021
10022 if (safi == SAFI_EVPN)
10023 vty_out(vty, "\n");
10024
05864da7
DS
10025 /* Line1 display AS-path, Aggregator */
10026 if (attr->aspath) {
10027 if (json_paths) {
10028 if (!attr->aspath->json)
10029 aspath_str_update(attr->aspath, true);
10030 json_object_lock(attr->aspath->json);
10031 json_object_object_add(json_path, "aspath",
10032 attr->aspath->json);
10033 } else {
10034 if (attr->aspath->segments)
10035 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10036 else
05864da7 10037 vty_out(vty, " Local");
d62a17ae 10038 }
05864da7 10039 }
d62a17ae 10040
05864da7
DS
10041 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10042 if (json_paths)
10043 json_object_boolean_true_add(json_path, "removed");
10044 else
10045 vty_out(vty, ", (removed)");
10046 }
d62a17ae 10047
05864da7
DS
10048 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10049 if (json_paths)
10050 json_object_boolean_true_add(json_path, "stale");
10051 else
10052 vty_out(vty, ", (stale)");
10053 }
d62a17ae 10054
05864da7
DS
10055 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10056 if (json_paths) {
10057 json_object_int_add(json_path, "aggregatorAs",
10058 attr->aggregator_as);
c949c771
DA
10059 json_object_string_addf(json_path, "aggregatorId",
10060 "%pI4", &attr->aggregator_addr);
05864da7 10061 } else {
88d495a9
DA
10062 vty_out(vty, ", (aggregated by %u %pI4)",
10063 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10064 }
05864da7 10065 }
d62a17ae 10066
05864da7
DS
10067 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10068 PEER_FLAG_REFLECTOR_CLIENT)) {
10069 if (json_paths)
10070 json_object_boolean_true_add(json_path,
10071 "rxedFromRrClient");
10072 else
10073 vty_out(vty, ", (Received from a RR-client)");
10074 }
d62a17ae 10075
05864da7
DS
10076 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10077 PEER_FLAG_RSERVER_CLIENT)) {
10078 if (json_paths)
10079 json_object_boolean_true_add(json_path,
10080 "rxedFromRsClient");
10081 else
10082 vty_out(vty, ", (Received from a RS-client)");
10083 }
d62a17ae 10084
05864da7
DS
10085 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10086 if (json_paths)
10087 json_object_boolean_true_add(json_path,
10088 "dampeningHistoryEntry");
10089 else
10090 vty_out(vty, ", (history entry)");
10091 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10092 if (json_paths)
10093 json_object_boolean_true_add(json_path,
10094 "dampeningSuppressed");
10095 else
10096 vty_out(vty, ", (suppressed due to dampening)");
10097 }
d62a17ae 10098
05864da7
DS
10099 if (!json_paths)
10100 vty_out(vty, "\n");
d62a17ae 10101
05864da7
DS
10102 /* Line2 display Next-hop, Neighbor, Router-id */
10103 /* Display the nexthop */
9bcb3eef 10104 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10105
10106 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10107 || bn_p->family == AF_EVPN)
05864da7
DS
10108 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10109 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10110 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10111 || safi == SAFI_EVPN) {
515c2602 10112 if (json_paths) {
c949c771
DA
10113 json_object_string_addf(
10114 json_nexthop_global, "ip", "%pI4",
10115 &attr->mp_nexthop_global_in);
515c2602 10116
939a97f4 10117 if (path->peer->hostname)
515c2602
DA
10118 json_object_string_add(
10119 json_nexthop_global, "hostname",
939a97f4 10120 path->peer->hostname);
aef999a2
DA
10121 } else {
10122 if (nexthop_hostname)
10123 vty_out(vty, " %pI4(%s)",
10124 &attr->mp_nexthop_global_in,
10125 nexthop_hostname);
10126 else
10127 vty_out(vty, " %pI4",
10128 &attr->mp_nexthop_global_in);
10129 }
d62a17ae 10130 } else {
515c2602 10131 if (json_paths) {
c949c771
DA
10132 json_object_string_addf(json_nexthop_global,
10133 "ip", "%pI4",
10134 &attr->nexthop);
515c2602 10135
939a97f4 10136 if (path->peer->hostname)
515c2602
DA
10137 json_object_string_add(
10138 json_nexthop_global, "hostname",
939a97f4 10139 path->peer->hostname);
aef999a2
DA
10140 } else {
10141 if (nexthop_hostname)
10142 vty_out(vty, " %pI4(%s)",
10143 &attr->nexthop,
10144 nexthop_hostname);
10145 else
10146 vty_out(vty, " %pI4",
10147 &attr->nexthop);
10148 }
d62a17ae 10149 }
10150
05864da7
DS
10151 if (json_paths)
10152 json_object_string_add(json_nexthop_global, "afi",
10153 "ipv4");
10154 } else {
10155 if (json_paths) {
c949c771
DA
10156 json_object_string_addf(json_nexthop_global, "ip",
10157 "%pI6",
10158 &attr->mp_nexthop_global);
515c2602 10159
939a97f4 10160 if (path->peer->hostname)
515c2602
DA
10161 json_object_string_add(json_nexthop_global,
10162 "hostname",
939a97f4 10163 path->peer->hostname);
515c2602 10164
05864da7
DS
10165 json_object_string_add(json_nexthop_global, "afi",
10166 "ipv6");
10167 json_object_string_add(json_nexthop_global, "scope",
10168 "global");
10169 } else {
aef999a2
DA
10170 if (nexthop_hostname)
10171 vty_out(vty, " %pI6(%s)",
10172 &attr->mp_nexthop_global,
10173 nexthop_hostname);
10174 else
10175 vty_out(vty, " %pI6",
10176 &attr->mp_nexthop_global);
d62a17ae 10177 }
05864da7 10178 }
d62a17ae 10179
05864da7
DS
10180 /* Display the IGP cost or 'inaccessible' */
10181 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10182 if (json_paths)
10183 json_object_boolean_false_add(json_nexthop_global,
10184 "accessible");
10185 else
10186 vty_out(vty, " (inaccessible)");
10187 } else {
10188 if (path->extra && path->extra->igpmetric) {
d62a17ae 10189 if (json_paths)
05864da7
DS
10190 json_object_int_add(json_nexthop_global,
10191 "metric",
10192 path->extra->igpmetric);
d62a17ae 10193 else
05864da7
DS
10194 vty_out(vty, " (metric %u)",
10195 path->extra->igpmetric);
d62a17ae 10196 }
10197
05864da7 10198 /* IGP cost is 0, display this only for json */
d62a17ae 10199 else {
d62a17ae 10200 if (json_paths)
05864da7
DS
10201 json_object_int_add(json_nexthop_global,
10202 "metric", 0);
d62a17ae 10203 }
d62a17ae 10204
05864da7
DS
10205 if (json_paths)
10206 json_object_boolean_true_add(json_nexthop_global,
10207 "accessible");
10208 }
d62a17ae 10209
05864da7
DS
10210 /* Display peer "from" output */
10211 /* This path was originated locally */
10212 if (path->peer == bgp->peer_self) {
d62a17ae 10213
05864da7 10214 if (safi == SAFI_EVPN
b54892e0 10215 || (bn_p->family == AF_INET
05864da7 10216 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10217 if (json_paths)
05864da7
DS
10218 json_object_string_add(json_peer, "peerId",
10219 "0.0.0.0");
d62a17ae 10220 else
05864da7
DS
10221 vty_out(vty, " from 0.0.0.0 ");
10222 } else {
d62a17ae 10223 if (json_paths)
05864da7
DS
10224 json_object_string_add(json_peer, "peerId",
10225 "::");
d62a17ae 10226 else
05864da7 10227 vty_out(vty, " from :: ");
d62a17ae 10228 }
d62a17ae 10229
4e9a9863 10230 if (json_paths)
c949c771
DA
10231 json_object_string_addf(json_peer, "routerId", "%pI4",
10232 &bgp->router_id);
4e9a9863 10233 else
23d0a753 10234 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10235 }
d62a17ae 10236
05864da7
DS
10237 /* We RXed this path from one of our peers */
10238 else {
10239
10240 if (json_paths) {
47e12884
DA
10241 json_object_string_addf(json_peer, "peerId", "%pSU",
10242 &path->peer->su);
c949c771
DA
10243 json_object_string_addf(json_peer, "routerId", "%pI4",
10244 &path->peer->remote_id);
05864da7
DS
10245
10246 if (path->peer->hostname)
10247 json_object_string_add(json_peer, "hostname",
10248 path->peer->hostname);
10249
10250 if (path->peer->domainname)
10251 json_object_string_add(json_peer, "domainname",
10252 path->peer->domainname);
10253
10254 if (path->peer->conf_if)
10255 json_object_string_add(json_peer, "interface",
10256 path->peer->conf_if);
10257 } else {
10258 if (path->peer->conf_if) {
10259 if (path->peer->hostname
892fedb6
DA
10260 && CHECK_FLAG(path->peer->bgp->flags,
10261 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10262 vty_out(vty, " from %s(%s)",
10263 path->peer->hostname,
10264 path->peer->conf_if);
d62a17ae 10265 else
05864da7 10266 vty_out(vty, " from %s",
9b6d8fcf 10267 path->peer->conf_if);
d62a17ae 10268 } else {
05864da7 10269 if (path->peer->hostname
892fedb6
DA
10270 && CHECK_FLAG(path->peer->bgp->flags,
10271 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10272 vty_out(vty, " from %s(%s)",
10273 path->peer->hostname,
10274 path->peer->host);
d62a17ae 10275 else
47e12884
DA
10276 vty_out(vty, " from %pSU",
10277 &path->peer->su);
d62a17ae 10278 }
d62a17ae 10279
05864da7 10280 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10281 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10282 else
10283 vty_out(vty, " (%s)",
10284 inet_ntop(AF_INET,
10285 &path->peer->remote_id, buf1,
10286 sizeof(buf1)));
d62a17ae 10287 }
05864da7 10288 }
9df8b37c 10289
05864da7
DS
10290 /*
10291 * Note when vrfid of nexthop is different from that of prefix
10292 */
10293 if (path->extra && path->extra->bgp_orig) {
10294 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10295
05864da7
DS
10296 if (json_paths) {
10297 const char *vn;
9df8b37c 10298
05864da7
DS
10299 if (path->extra->bgp_orig->inst_type
10300 == BGP_INSTANCE_TYPE_DEFAULT)
10301 vn = VRF_DEFAULT_NAME;
10302 else
10303 vn = path->extra->bgp_orig->name;
9df8b37c 10304
05864da7 10305 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10306
05864da7
DS
10307 if (nexthop_vrfid == VRF_UNKNOWN) {
10308 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10309 } else {
05864da7
DS
10310 json_object_int_add(json_path, "nhVrfId",
10311 (int)nexthop_vrfid);
9df8b37c 10312 }
05864da7
DS
10313 } else {
10314 if (nexthop_vrfid == VRF_UNKNOWN)
10315 vty_out(vty, " vrf ?");
137147c6
DS
10316 else {
10317 struct vrf *vrf;
10318
10319 vrf = vrf_lookup_by_id(nexthop_vrfid);
10320 vty_out(vty, " vrf %s(%u)",
10321 VRF_LOGNAME(vrf), nexthop_vrfid);
10322 }
9df8b37c 10323 }
05864da7 10324 }
9df8b37c 10325
05864da7
DS
10326 if (nexthop_self) {
10327 if (json_paths) {
10328 json_object_boolean_true_add(json_path,
10329 "announceNexthopSelf");
10330 } else {
10331 vty_out(vty, " announce-nh-self");
9df8b37c 10332 }
05864da7 10333 }
9df8b37c 10334
05864da7
DS
10335 if (!json_paths)
10336 vty_out(vty, "\n");
d62a17ae 10337
05864da7
DS
10338 /* display the link-local nexthop */
10339 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10340 if (json_paths) {
10341 json_nexthop_ll = json_object_new_object();
c949c771
DA
10342 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10343 &attr->mp_nexthop_local);
515c2602 10344
939a97f4 10345 if (path->peer->hostname)
515c2602
DA
10346 json_object_string_add(json_nexthop_ll,
10347 "hostname",
939a97f4 10348 path->peer->hostname);
515c2602 10349
05864da7
DS
10350 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10351 json_object_string_add(json_nexthop_ll, "scope",
10352 "link-local");
d62a17ae 10353
05864da7
DS
10354 json_object_boolean_true_add(json_nexthop_ll,
10355 "accessible");
d62a17ae 10356
05864da7 10357 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10358 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10359 "used");
10360 else
10361 json_object_boolean_true_add(
10362 json_nexthop_global, "used");
10363 } else {
10364 vty_out(vty, " (%s) %s\n",
10365 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10366 buf, INET6_ADDRSTRLEN),
10367 attr->mp_nexthop_prefer_global
10368 ? "(prefer-global)"
10369 : "(used)");
d62a17ae 10370 }
05864da7
DS
10371 }
10372 /* If we do not have a link-local nexthop then we must flag the
10373 global as "used" */
10374 else {
10375 if (json_paths)
10376 json_object_boolean_true_add(json_nexthop_global,
10377 "used");
10378 }
d62a17ae 10379
b5e140c8 10380 if (safi == SAFI_EVPN &&
5e4d4c8a 10381 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10382 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10383 }
10384
05864da7
DS
10385 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10386 * Int/Ext/Local, Atomic, best */
10387 if (json_paths)
10388 json_object_string_add(json_path, "origin",
10389 bgp_origin_long_str[attr->origin]);
10390 else
10391 vty_out(vty, " Origin %s",
10392 bgp_origin_long_str[attr->origin]);
9df8b37c 10393
05864da7 10394 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10395 if (json_paths)
05864da7 10396 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10397 else
05864da7
DS
10398 vty_out(vty, ", metric %u", attr->med);
10399 }
9df8b37c 10400
05864da7
DS
10401 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10402 if (json_paths)
0fbac0b4 10403 json_object_int_add(json_path, "locPrf",
05864da7
DS
10404 attr->local_pref);
10405 else
10406 vty_out(vty, ", localpref %u", attr->local_pref);
10407 }
9df8b37c 10408
05864da7
DS
10409 if (attr->weight != 0) {
10410 if (json_paths)
10411 json_object_int_add(json_path, "weight", attr->weight);
10412 else
10413 vty_out(vty, ", weight %u", attr->weight);
10414 }
9df8b37c 10415
05864da7
DS
10416 if (attr->tag != 0) {
10417 if (json_paths)
10418 json_object_int_add(json_path, "tag", attr->tag);
10419 else
10420 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10421 }
9df8b37c 10422
05864da7
DS
10423 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10424 if (json_paths)
10425 json_object_boolean_false_add(json_path, "valid");
10426 else
10427 vty_out(vty, ", invalid");
10428 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10429 if (json_paths)
10430 json_object_boolean_true_add(json_path, "valid");
10431 else
10432 vty_out(vty, ", valid");
10433 }
9df8b37c 10434
7d3cae70
DA
10435 if (json_paths)
10436 json_object_int_add(json_path, "version", bn->version);
10437
05864da7
DS
10438 if (path->peer != bgp->peer_self) {
10439 if (path->peer->as == path->peer->local_as) {
10440 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10441 if (json_paths)
10442 json_object_string_add(
10443 json_peer, "type",
10444 "confed-internal");
d62a17ae 10445 else
05864da7 10446 vty_out(vty, ", confed-internal");
d62a17ae 10447 } else {
05864da7
DS
10448 if (json_paths)
10449 json_object_string_add(
10450 json_peer, "type", "internal");
10451 else
10452 vty_out(vty, ", internal");
9df8b37c 10453 }
05864da7
DS
10454 } else {
10455 if (bgp_confederation_peers_check(bgp,
10456 path->peer->as)) {
10457 if (json_paths)
10458 json_object_string_add(
10459 json_peer, "type",
10460 "confed-external");
d62a17ae 10461 else
05864da7 10462 vty_out(vty, ", confed-external");
d62a17ae 10463 } else {
05864da7
DS
10464 if (json_paths)
10465 json_object_string_add(
10466 json_peer, "type", "external");
10467 else
10468 vty_out(vty, ", external");
d62a17ae 10469 }
10470 }
05864da7
DS
10471 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10472 if (json_paths) {
10473 json_object_boolean_true_add(json_path, "aggregated");
10474 json_object_boolean_true_add(json_path, "local");
10475 } else {
10476 vty_out(vty, ", aggregated, local");
10477 }
10478 } else if (path->type != ZEBRA_ROUTE_BGP) {
10479 if (json_paths)
10480 json_object_boolean_true_add(json_path, "sourced");
10481 else
10482 vty_out(vty, ", sourced");
10483 } else {
10484 if (json_paths) {
10485 json_object_boolean_true_add(json_path, "sourced");
10486 json_object_boolean_true_add(json_path, "local");
10487 } else {
10488 vty_out(vty, ", sourced, local");
d62a17ae 10489 }
05864da7 10490 }
718e3744 10491
05864da7 10492 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10493 if (json_paths)
05864da7
DS
10494 json_object_boolean_true_add(json_path,
10495 "atomicAggregate");
d62a17ae 10496 else
05864da7
DS
10497 vty_out(vty, ", atomic-aggregate");
10498 }
d62a17ae 10499
d864dd9e
EB
10500 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10501 if (json_paths)
10502 json_object_int_add(json_path, "otc", attr->otc);
10503 else
10504 vty_out(vty, ", otc %u", attr->otc);
10505 }
10506
05864da7
DS
10507 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10508 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10509 && bgp_path_info_mpath_count(path))) {
10510 if (json_paths)
10511 json_object_boolean_true_add(json_path, "multipath");
10512 else
10513 vty_out(vty, ", multipath");
10514 }
50e05855 10515
05864da7
DS
10516 // Mark the bestpath(s)
10517 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10518 first_as = aspath_get_first_as(attr->aspath);
718e3744 10519
05864da7
DS
10520 if (json_paths) {
10521 if (!json_bestpath)
10522 json_bestpath = json_object_new_object();
10523 json_object_int_add(json_bestpath, "bestpathFromAs",
10524 first_as);
10525 } else {
10526 if (first_as)
10527 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10528 else
05864da7 10529 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10530 }
05864da7 10531 }
718e3744 10532
05864da7
DS
10533 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10534 if (json_paths) {
10535 if (!json_bestpath)
10536 json_bestpath = json_object_new_object();
10537 json_object_boolean_true_add(json_bestpath, "overall");
10538 json_object_string_add(
10539 json_bestpath, "selectionReason",
10540 bgp_path_selection_reason2str(bn->reason));
10541 } else {
10542 vty_out(vty, ", best");
10543 vty_out(vty, " (%s)",
10544 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10545 }
05864da7 10546 }
718e3744 10547
4027d19b 10548 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10549 if (json_paths)
10550 json_object_string_add(
10551 json_path, "rpkiValidationState",
4027d19b 10552 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10553 else
1d327209 10554 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10555 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10556 }
10557
05864da7
DS
10558 if (json_bestpath)
10559 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10560
05864da7
DS
10561 if (!json_paths)
10562 vty_out(vty, "\n");
10563
10564 /* Line 4 display Community */
29e72930 10565 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10566 if (json_paths) {
9a706b42
DA
10567 if (!bgp_attr_get_community(attr)->json)
10568 community_str(bgp_attr_get_community(attr),
c0945b78 10569 true, true);
9a706b42
DA
10570 json_object_lock(bgp_attr_get_community(attr)->json);
10571 json_object_object_add(
10572 json_path, "community",
10573 bgp_attr_get_community(attr)->json);
05864da7
DS
10574 } else {
10575 vty_out(vty, " Community: %s\n",
9a706b42 10576 bgp_attr_get_community(attr)->str);
d62a17ae 10577 }
05864da7 10578 }
718e3744 10579
05864da7
DS
10580 /* Line 5 display Extended-community */
10581 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10582 if (json_paths) {
10583 json_ext_community = json_object_new_object();
b53e67a3
DA
10584 json_object_string_add(
10585 json_ext_community, "string",
10586 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10587 json_object_object_add(json_path, "extendedCommunity",
10588 json_ext_community);
d62a17ae 10589 } else {
05864da7 10590 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10591 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10592 }
05864da7 10593 }
718e3744 10594
05864da7
DS
10595 /* Line 6 display Large community */
10596 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10597 if (json_paths) {
1bcf3a96
DA
10598 if (!bgp_attr_get_lcommunity(attr)->json)
10599 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10600 true, true);
1bcf3a96
DA
10601 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10602 json_object_object_add(
10603 json_path, "largeCommunity",
10604 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10605 } else {
10606 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10607 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10608 }
05864da7 10609 }
718e3744 10610
05864da7
DS
10611 /* Line 7 display Originator, Cluster-id */
10612 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10613 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10614 char buf[BUFSIZ] = {0};
10615
05864da7 10616 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10617 if (json_paths)
c949c771
DA
10618 json_object_string_addf(json_path,
10619 "originatorId", "%pI4",
10620 &attr->originator_id);
d62a17ae 10621 else
23d0a753
DA
10622 vty_out(vty, " Originator: %pI4",
10623 &attr->originator_id);
d62a17ae 10624 }
856ca177 10625
05864da7 10626 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10627 struct cluster_list *cluster =
10628 bgp_attr_get_cluster(attr);
05864da7 10629 int i;
d62a17ae 10630
10631 if (json_paths) {
05864da7
DS
10632 json_cluster_list = json_object_new_object();
10633 json_cluster_list_list =
10634 json_object_new_array();
10635
779fee93 10636 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10637 json_string = json_object_new_string(
779fee93
DS
10638 inet_ntop(AF_INET,
10639 &cluster->list[i],
10640 buf, sizeof(buf)));
05864da7
DS
10641 json_object_array_add(
10642 json_cluster_list_list,
10643 json_string);
10644 }
718e3744 10645
05864da7
DS
10646 /*
10647 * struct cluster_list does not have
10648 * "str" variable like aspath and community
10649 * do. Add this someday if someone asks
10650 * for it.
10651 * json_object_string_add(json_cluster_list,
779fee93 10652 * "string", cluster->str);
05864da7
DS
10653 */
10654 json_object_object_add(json_cluster_list,
10655 "list",
10656 json_cluster_list_list);
10657 json_object_object_add(json_path, "clusterList",
10658 json_cluster_list);
0dc8ee70 10659 } else {
05864da7
DS
10660 vty_out(vty, ", Cluster list: ");
10661
779fee93 10662 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10663 vty_out(vty, "%pI4 ",
779fee93 10664 &cluster->list[i]);
05864da7 10665 }
0dc8ee70 10666 }
d62a17ae 10667 }
718e3744 10668
d62a17ae 10669 if (!json_paths)
10670 vty_out(vty, "\n");
05864da7 10671 }
d62a17ae 10672
05864da7 10673 if (path->extra && path->extra->damp_info)
b4f7f45b 10674 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10675
05864da7
DS
10676 /* Remote Label */
10677 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10678 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10679 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10680 &bos);
d62a17ae 10681
05864da7
DS
10682 if (json_paths)
10683 json_object_int_add(json_path, "remoteLabel", label);
10684 else
10685 vty_out(vty, " Remote label: %d\n", label);
10686 }
d62a17ae 10687
e496b420
HS
10688 /* Remote SID */
10689 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10690 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10691 if (json_paths)
10692 json_object_string_add(json_path, "remoteSid", buf);
10693 else
10694 vty_out(vty, " Remote SID: %s\n", buf);
10695 }
10696
05864da7
DS
10697 /* Label Index */
10698 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10699 if (json_paths)
10700 json_object_int_add(json_path, "labelIndex",
10701 attr->label_index);
10702 else
10703 vty_out(vty, " Label Index: %d\n",
10704 attr->label_index);
10705 }
d62a17ae 10706
05864da7
DS
10707 /* Line 8 display Addpath IDs */
10708 if (path->addpath_rx_id
10709 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10710 if (json_paths) {
10711 json_object_int_add(json_path, "addpathRxId",
10712 path->addpath_rx_id);
d62a17ae 10713
05864da7
DS
10714 /* Keep backwards compatibility with the old API
10715 * by putting TX All's ID in the old field
10716 */
10717 json_object_int_add(
10718 json_path, "addpathTxId",
10719 path->tx_addpath
10720 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10721
05864da7
DS
10722 /* ... but create a specific field for each
10723 * strategy
10724 */
10725 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10726 json_object_int_add(
10727 json_path,
10728 bgp_addpath_names(i)->id_json_name,
10729 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10730 }
05864da7
DS
10731 } else {
10732 vty_out(vty, " AddPath ID: RX %u, ",
10733 path->addpath_rx_id);
d62a17ae 10734
05864da7 10735 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10736 }
05864da7 10737 }
520d5d76 10738
05864da7
DS
10739 /* If we used addpath to TX a non-bestpath we need to display
10740 * "Advertised to" on a path-by-path basis
10741 */
10742 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10743 first = 1;
dcc68b5e 10744
05864da7
DS
10745 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10746 addpath_capable =
10747 bgp_addpath_encode_tx(peer, afi, safi);
10748 has_adj = bgp_adj_out_lookup(
10749 peer, path->net,
10750 bgp_addpath_id_for_peer(peer, afi, safi,
10751 &path->tx_addpath));
10752
10753 if ((addpath_capable && has_adj)
10754 || (!addpath_capable && has_adj
10755 && CHECK_FLAG(path->flags,
10756 BGP_PATH_SELECTED))) {
10757 if (json_path && !json_adv_to)
10758 json_adv_to = json_object_new_object();
dcc68b5e 10759
05864da7
DS
10760 route_vty_out_advertised_to(
10761 vty, peer, &first,
10762 " Advertised to:", json_adv_to);
d62a17ae 10763 }
10764 }
718e3744 10765
05864da7
DS
10766 if (json_path) {
10767 if (json_adv_to) {
10768 json_object_object_add(
10769 json_path, "advertisedTo", json_adv_to);
d62a17ae 10770 }
05864da7
DS
10771 } else {
10772 if (!first) {
10773 vty_out(vty, "\n");
d62a17ae 10774 }
10775 }
05864da7 10776 }
b05a1c8b 10777
05864da7
DS
10778 /* Line 9 display Uptime */
10779 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10780 if (json_paths) {
10781 json_last_update = json_object_new_object();
10782 json_object_int_add(json_last_update, "epoch", tbuf);
10783 json_object_string_add(json_last_update, "string",
10784 ctime(&tbuf));
10785 json_object_object_add(json_path, "lastUpdate",
10786 json_last_update);
10787 } else
10788 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10789
05864da7
DS
10790 /* Line 10 display PMSI tunnel attribute, if present */
10791 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10792 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10793 bgp_attr_get_pmsi_tnl_type(attr),
10794 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10795
05864da7
DS
10796 if (json_paths) {
10797 json_pmsi = json_object_new_object();
10798 json_object_string_add(json_pmsi, "tunnelType", str);
10799 json_object_int_add(json_pmsi, "label",
10800 label2vni(&attr->label));
10801 json_object_object_add(json_path, "pmsi", json_pmsi);
10802 } else
10803 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10804 str, label2vni(&attr->label));
d62a17ae 10805 }
f1aa5d8a 10806
848e8cf6
DA
10807 if (path->peer->t_gr_restart &&
10808 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10809 unsigned long gr_remaining =
10810 thread_timer_remain_second(path->peer->t_gr_restart);
10811
10812 if (json_paths) {
10813 json_object_int_add(json_path,
10814 "gracefulRestartSecondsRemaining",
10815 gr_remaining);
10816 } else
10817 vty_out(vty,
10818 " Time until Graceful Restart stale route deleted: %lu\n",
10819 gr_remaining);
10820 }
10821
9a706b42
DA
10822 if (path->peer->t_llgr_stale[afi][safi] &&
10823 bgp_attr_get_community(attr) &&
10824 community_include(bgp_attr_get_community(attr),
10825 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10826 unsigned long llgr_remaining = thread_timer_remain_second(
10827 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10828
48ebba04
DA
10829 if (json_paths) {
10830 json_object_int_add(json_path, "llgrSecondsRemaining",
10831 llgr_remaining);
10832 } else
10833 vty_out(vty,
10834 " Time until Long-lived stale route deleted: %lu\n",
10835 llgr_remaining);
10836 }
10837
92269aa2
DS
10838 /* Output some debug about internal state of the dest flags */
10839 if (json_paths) {
10840 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10841 json_object_boolean_true_add(json_path, "processScheduled");
10842 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10843 json_object_boolean_true_add(json_path, "userCleared");
10844 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10845 json_object_boolean_true_add(json_path, "labelChanged");
10846 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10847 json_object_boolean_true_add(json_path, "registeredForLabel");
10848 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10849 json_object_boolean_true_add(json_path, "selectDefered");
10850 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10851 json_object_boolean_true_add(json_path, "fibInstalled");
10852 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10853 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10854
d62a17ae 10855 if (json_nexthop_global || json_nexthop_ll) {
10856 json_nexthops = json_object_new_array();
f1aa5d8a 10857
d62a17ae 10858 if (json_nexthop_global)
10859 json_object_array_add(json_nexthops,
10860 json_nexthop_global);
f1aa5d8a 10861
d62a17ae 10862 if (json_nexthop_ll)
10863 json_object_array_add(json_nexthops,
10864 json_nexthop_ll);
f1aa5d8a 10865
d62a17ae 10866 json_object_object_add(json_path, "nexthops",
10867 json_nexthops);
10868 }
10869
10870 json_object_object_add(json_path, "peer", json_peer);
10871 json_object_array_add(json_paths, json_path);
05864da7 10872 }
b366b518
BB
10873}
10874
96ade3ed 10875#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10876#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10877#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10878
a4d82a8a 10879static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10880 afi_t afi, safi_t safi, enum bgp_show_type type,
10881 bool use_json);
7f323236
DW
10882static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10883 const char *comstr, int exact, afi_t afi,
96c81f66 10884 safi_t safi, uint16_t show_flags);
d62a17ae 10885
1ae44dfc 10886static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10887 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10888 void *output_arg, const char *rd, int is_last,
96f3485c 10889 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10890 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10891 enum rpki_states rpki_target_state)
d62a17ae 10892{
40381db7 10893 struct bgp_path_info *pi;
9bcb3eef 10894 struct bgp_dest *dest;
2aad8c42
MS
10895 bool header = true;
10896 bool json_detail_header = false;
d62a17ae 10897 int display;
1ae44dfc
LB
10898 unsigned long output_count = 0;
10899 unsigned long total_count = 0;
d62a17ae 10900 struct prefix *p;
d62a17ae 10901 json_object *json_paths = NULL;
10902 int first = 1;
96f3485c
MK
10903 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10904 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10905 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10906
1ae44dfc 10907 if (output_cum && *output_cum != 0)
2aad8c42 10908 header = false;
1ae44dfc 10909
9386b588 10910 if (use_json && !*json_header_depth) {
96f3485c
MK
10911 if (all)
10912 *json_header_depth = 1;
10913 else {
10914 vty_out(vty, "{\n");
10915 *json_header_depth = 2;
10916 }
10917
d62a17ae 10918 vty_out(vty,
23d0a753
DA
10919 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10920 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10921 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10922 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10923 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10924 ? VRF_DEFAULT_NAME
10925 : bgp->name,
10926 table->version, &bgp->router_id,
01eced22 10927 bgp->default_local_pref, bgp->as);
9386b588 10928 if (rd) {
445c2480 10929 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10930 ++*json_header_depth;
10931 }
d62a17ae 10932 }
718e3744 10933
445c2480
DS
10934 if (use_json && rd) {
10935 vty_out(vty, " \"%s\" : { ", rd);
10936 }
10937
2aad8c42
MS
10938 /* Check for 'json detail', where we need header output once per dest */
10939 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10940 type != bgp_show_type_dampend_paths &&
10941 type != bgp_show_type_damp_neighbor &&
10942 type != bgp_show_type_flap_statistics &&
10943 type != bgp_show_type_flap_neighbor)
10944 json_detail_header = true;
10945
d62a17ae 10946 /* Start processing of routes. */
9bcb3eef
DS
10947 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10948 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10949 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10950 bool json_detail = json_detail_header;
b54892e0 10951
9bcb3eef 10952 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10953 if (pi == NULL)
98ce9a06 10954 continue;
d62a17ae 10955
98ce9a06 10956 display = 0;
98ce9a06
DS
10957 if (use_json)
10958 json_paths = json_object_new_array();
10959 else
10960 json_paths = NULL;
d62a17ae 10961
6f94b685 10962 for (; pi; pi = pi->next) {
9a706b42
DA
10963 struct community *picomm = NULL;
10964
10965 picomm = bgp_attr_get_community(pi->attr);
10966
98ce9a06 10967 total_count++;
1e2ce4f1 10968
7d3cae70
DA
10969 if (type == bgp_show_type_prefix_version) {
10970 uint32_t version =
10971 strtoul(output_arg, NULL, 10);
10972 if (dest->version < version)
10973 continue;
10974 }
10975
a70a28a5
DA
10976 if (type == bgp_show_type_community_alias) {
10977 char *alias = output_arg;
10978 char **communities;
10979 int num;
10980 bool found = false;
10981
9a706b42
DA
10982 if (picomm) {
10983 frrstr_split(picomm->str, " ",
10984 &communities, &num);
a70a28a5
DA
10985 for (int i = 0; i < num; i++) {
10986 const char *com2alias =
10987 bgp_community2alias(
10988 communities[i]);
cd9cc0e6
IR
10989 if (!found
10990 && strcmp(alias, com2alias)
10991 == 0)
a70a28a5 10992 found = true;
cd9cc0e6
IR
10993 XFREE(MTYPE_TMP,
10994 communities[i]);
a70a28a5 10995 }
cd9cc0e6 10996 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10997 }
10998
1bcf3a96
DA
10999 if (!found &&
11000 bgp_attr_get_lcommunity(pi->attr)) {
11001 frrstr_split(bgp_attr_get_lcommunity(
11002 pi->attr)
11003 ->str,
a70a28a5
DA
11004 " ", &communities, &num);
11005 for (int i = 0; i < num; i++) {
11006 const char *com2alias =
11007 bgp_community2alias(
11008 communities[i]);
cd9cc0e6
IR
11009 if (!found
11010 && strcmp(alias, com2alias)
11011 == 0)
a70a28a5 11012 found = true;
cd9cc0e6
IR
11013 XFREE(MTYPE_TMP,
11014 communities[i]);
a70a28a5 11015 }
cd9cc0e6 11016 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11017 }
11018
11019 if (!found)
11020 continue;
11021 }
11022
1e2ce4f1
DS
11023 if (type == bgp_show_type_rpki) {
11024 if (dest_p->family == AF_INET
11025 || dest_p->family == AF_INET6)
4027d19b 11026 rpki_curr_state = hook_call(
1e2ce4f1
DS
11027 bgp_rpki_prefix_status,
11028 pi->peer, pi->attr, dest_p);
4027d19b
DS
11029 if (rpki_target_state != RPKI_NOT_BEING_USED
11030 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11031 continue;
11032 }
11033
98ce9a06
DS
11034 if (type == bgp_show_type_flap_statistics
11035 || type == bgp_show_type_flap_neighbor
11036 || type == bgp_show_type_dampend_paths
11037 || type == bgp_show_type_damp_neighbor) {
40381db7 11038 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11039 continue;
11040 }
11041 if (type == bgp_show_type_regexp) {
11042 regex_t *regex = output_arg;
d62a17ae 11043
40381db7 11044 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11045 == REG_NOMATCH)
11046 continue;
11047 }
11048 if (type == bgp_show_type_prefix_list) {
11049 struct prefix_list *plist = output_arg;
d62a17ae 11050
9bcb3eef 11051 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11052 != PREFIX_PERMIT)
11053 continue;
11054 }
11055 if (type == bgp_show_type_filter_list) {
11056 struct as_list *as_list = output_arg;
d62a17ae 11057
40381db7 11058 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11059 != AS_FILTER_PERMIT)
11060 continue;
11061 }
11062 if (type == bgp_show_type_route_map) {
11063 struct route_map *rmap = output_arg;
9b6d8fcf 11064 struct bgp_path_info path;
98ce9a06 11065 struct attr dummy_attr;
b68885f9 11066 route_map_result_t ret;
d62a17ae 11067
6f4f49b2 11068 dummy_attr = *pi->attr;
d62a17ae 11069
40381db7 11070 path.peer = pi->peer;
9b6d8fcf 11071 path.attr = &dummy_attr;
d62a17ae 11072
1782514f 11073 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11074 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11075 if (ret == RMAP_DENYMATCH)
11076 continue;
11077 }
11078 if (type == bgp_show_type_neighbor
11079 || type == bgp_show_type_flap_neighbor
11080 || type == bgp_show_type_damp_neighbor) {
11081 union sockunion *su = output_arg;
11082
40381db7
DS
11083 if (pi->peer == NULL
11084 || pi->peer->su_remote == NULL
11085 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11086 continue;
11087 }
11088 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11089 uint32_t destination;
d62a17ae 11090
9bcb3eef 11091 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11092 if (IN_CLASSC(destination)
9bcb3eef 11093 && dest_p->prefixlen == 24)
98ce9a06
DS
11094 continue;
11095 if (IN_CLASSB(destination)
9bcb3eef 11096 && dest_p->prefixlen == 16)
98ce9a06
DS
11097 continue;
11098 if (IN_CLASSA(destination)
9bcb3eef 11099 && dest_p->prefixlen == 8)
98ce9a06
DS
11100 continue;
11101 }
11102 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11103 p = output_arg;
9bcb3eef 11104 if (!prefix_match(p, dest_p))
98ce9a06
DS
11105 continue;
11106 }
11107 if (type == bgp_show_type_community_all) {
9a706b42 11108 if (!picomm)
98ce9a06
DS
11109 continue;
11110 }
11111 if (type == bgp_show_type_community) {
11112 struct community *com = output_arg;
d62a17ae 11113
9a706b42 11114 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11115 continue;
11116 }
11117 if (type == bgp_show_type_community_exact) {
11118 struct community *com = output_arg;
d62a17ae 11119
9a706b42 11120 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11121 continue;
11122 }
11123 if (type == bgp_show_type_community_list) {
11124 struct community_list *list = output_arg;
d62a17ae 11125
9a706b42 11126 if (!community_list_match(picomm, list))
98ce9a06
DS
11127 continue;
11128 }
a4d82a8a 11129 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11130 struct community_list *list = output_arg;
d62a17ae 11131
9a706b42 11132 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11133 continue;
11134 }
11135 if (type == bgp_show_type_lcommunity) {
11136 struct lcommunity *lcom = output_arg;
d62a17ae 11137
1bcf3a96
DA
11138 if (!bgp_attr_get_lcommunity(pi->attr) ||
11139 !lcommunity_match(
11140 bgp_attr_get_lcommunity(pi->attr),
11141 lcom))
98ce9a06
DS
11142 continue;
11143 }
36a206db 11144
11145 if (type == bgp_show_type_lcommunity_exact) {
11146 struct lcommunity *lcom = output_arg;
11147
1bcf3a96
DA
11148 if (!bgp_attr_get_lcommunity(pi->attr) ||
11149 !lcommunity_cmp(
11150 bgp_attr_get_lcommunity(pi->attr),
11151 lcom))
36a206db 11152 continue;
11153 }
98ce9a06
DS
11154 if (type == bgp_show_type_lcommunity_list) {
11155 struct community_list *list = output_arg;
d62a17ae 11156
1bcf3a96
DA
11157 if (!lcommunity_list_match(
11158 bgp_attr_get_lcommunity(pi->attr),
11159 list))
98ce9a06
DS
11160 continue;
11161 }
36a206db 11162 if (type
11163 == bgp_show_type_lcommunity_list_exact) {
11164 struct community_list *list = output_arg;
11165
11166 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11167 bgp_attr_get_lcommunity(pi->attr),
11168 list))
36a206db 11169 continue;
11170 }
98ce9a06 11171 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11172 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11173 continue;
11174 }
11175 if (type == bgp_show_type_dampend_paths
11176 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11177 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11178 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11179 continue;
11180 }
11181
11182 if (!use_json && header) {
23d0a753
DA
11183 vty_out(vty,
11184 "BGP table version is %" PRIu64
11185 ", local router ID is %pI4, vrf id ",
11186 table->version, &bgp->router_id);
9df8b37c
PZ
11187 if (bgp->vrf_id == VRF_UNKNOWN)
11188 vty_out(vty, "%s", VRFID_NONE_STR);
11189 else
11190 vty_out(vty, "%u", bgp->vrf_id);
11191 vty_out(vty, "\n");
01eced22
AD
11192 vty_out(vty, "Default local pref %u, ",
11193 bgp->default_local_pref);
11194 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11195 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11196 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11197 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11198 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11199 if (type == bgp_show_type_dampend_paths
11200 || type == bgp_show_type_damp_neighbor)
98ce9a06 11201 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11202 else if (type == bgp_show_type_flap_statistics
11203 || type == bgp_show_type_flap_neighbor)
98ce9a06 11204 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11205 else
ae248832
MK
11206 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11207 : BGP_SHOW_HEADER));
2aad8c42
MS
11208 header = false;
11209
11210 } else if (json_detail && json_paths != NULL) {
11211 const struct prefix_rd *prd;
11212 json_object *jtemp;
11213
11214 /* Use common detail header, for most types;
11215 * need a json 'object'.
11216 */
11217
11218 jtemp = json_object_new_object();
11219 prd = bgp_rd_from_dest(dest, safi);
11220
11221 route_vty_out_detail_header(
11222 vty, bgp, dest, prd, table->afi,
11223 safi, jtemp);
11224
11225 json_object_array_add(json_paths, jtemp);
11226
11227 json_detail = false;
d62a17ae 11228 }
2aad8c42 11229
98ce9a06
DS
11230 if (rd != NULL && !display && !output_count) {
11231 if (!use_json)
11232 vty_out(vty,
11233 "Route Distinguisher: %s\n",
11234 rd);
d62a17ae 11235 }
98ce9a06
DS
11236 if (type == bgp_show_type_dampend_paths
11237 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11238 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11239 AFI_IP, safi, use_json,
11240 json_paths);
98ce9a06
DS
11241 else if (type == bgp_show_type_flap_statistics
11242 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11243 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11244 AFI_IP, safi, use_json,
11245 json_paths);
f280c93b
DA
11246 else {
11247 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11248 route_vty_out_detail(
11249 vty, bgp, dest, pi,
11250 family2afi(dest_p->family),
11251 safi, RPKI_NOT_BEING_USED,
11252 json_paths);
11253 else
11254 route_vty_out(vty, dest_p, pi, display,
11255 safi, json_paths, wide);
11256 }
98ce9a06 11257 display++;
d62a17ae 11258 }
11259
98ce9a06
DS
11260 if (display) {
11261 output_count++;
11262 if (!use_json)
11263 continue;
11264
625d2931 11265 /* encode prefix */
9bcb3eef 11266 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11267 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11268
1840384b 11269
b54892e0
DS
11270 bgp_fs_nlri_get_string(
11271 (unsigned char *)
9bcb3eef
DS
11272 dest_p->u.prefix_flowspec.ptr,
11273 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11274 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11275 family2afi(dest_p->u
11276 .prefix_flowspec.family));
625d2931 11277 if (first)
b54892e0 11278 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11279 dest_p->u.prefix_flowspec
b54892e0 11280 .prefixlen);
625d2931 11281 else
b54892e0 11282 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11283 dest_p->u.prefix_flowspec
b54892e0 11284 .prefixlen);
625d2931 11285 } else {
625d2931 11286 if (first)
1b78780b 11287 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11288 else
1b78780b 11289 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11290 }
3757f964 11291 vty_json(vty, json_paths);
449feb8e 11292 json_paths = NULL;
98ce9a06 11293 first = 0;
1f83ed02
DS
11294 } else
11295 json_object_free(json_paths);
98ce9a06
DS
11296 }
11297
1ae44dfc
LB
11298 if (output_cum) {
11299 output_count += *output_cum;
11300 *output_cum = output_count;
11301 }
11302 if (total_cum) {
11303 total_count += *total_cum;
11304 *total_cum = total_count;
11305 }
d62a17ae 11306 if (use_json) {
9386b588 11307 if (rd) {
a4d82a8a 11308 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11309 }
11310 if (is_last) {
a4d82a8a
PZ
11311 unsigned long i;
11312 for (i = 0; i < *json_header_depth; ++i)
11313 vty_out(vty, " } ");
96f3485c
MK
11314 if (!all)
11315 vty_out(vty, "\n");
9386b588 11316 }
d62a17ae 11317 } else {
1ae44dfc
LB
11318 if (is_last) {
11319 /* No route is displayed */
11320 if (output_count == 0) {
11321 if (type == bgp_show_type_normal)
11322 vty_out(vty,
11323 "No BGP prefixes displayed, %ld exist\n",
11324 total_count);
11325 } else
d62a17ae 11326 vty_out(vty,
1ae44dfc
LB
11327 "\nDisplayed %ld routes and %ld total paths\n",
11328 output_count, total_count);
11329 }
d62a17ae 11330 }
718e3744 11331
d62a17ae 11332 return CMD_SUCCESS;
718e3744 11333}
11334
1ae44dfc
LB
11335int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11336 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11337 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11338{
9bcb3eef 11339 struct bgp_dest *dest, *next;
1ae44dfc
LB
11340 unsigned long output_cum = 0;
11341 unsigned long total_cum = 0;
9386b588 11342 unsigned long json_header_depth = 0;
67009e22 11343 struct bgp_table *itable;
0136788c 11344 bool show_msg;
96c81f66 11345 uint16_t show_flags = 0;
0136788c
LB
11346
11347 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11348
96f3485c
MK
11349 if (use_json)
11350 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11351
9bcb3eef
DS
11352 for (dest = bgp_table_top(table); dest; dest = next) {
11353 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11354
9bcb3eef
DS
11355 next = bgp_route_next(dest);
11356 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11357 continue;
67009e22 11358
9bcb3eef 11359 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11360 if (itable != NULL) {
1ae44dfc 11361 struct prefix_rd prd;
06b9f471 11362 char rd[RD_ADDRSTRLEN];
1ae44dfc 11363
9bcb3eef 11364 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11365 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11366 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11367 rd, next == NULL, &output_cum,
11368 &total_cum, &json_header_depth,
1e2ce4f1 11369 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11370 if (next == NULL)
11371 show_msg = false;
1ae44dfc
LB
11372 }
11373 }
0136788c
LB
11374 if (show_msg) {
11375 if (output_cum == 0)
11376 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11377 total_cum);
11378 else
11379 vty_out(vty,
11380 "\nDisplayed %ld routes and %ld total paths\n",
11381 output_cum, total_cum);
11382 }
1ae44dfc
LB
11383 return CMD_SUCCESS;
11384}
2aad8c42 11385
d62a17ae 11386static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11387 enum bgp_show_type type, void *output_arg,
96c81f66 11388 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11389{
d62a17ae 11390 struct bgp_table *table;
9386b588 11391 unsigned long json_header_depth = 0;
96f3485c 11392 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11393
d62a17ae 11394 if (bgp == NULL) {
11395 bgp = bgp_get_default();
11396 }
fee0f4c6 11397
d62a17ae 11398 if (bgp == NULL) {
11399 if (!use_json)
11400 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11401 else
11402 vty_out(vty, "{}\n");
d62a17ae 11403 return CMD_WARNING;
11404 }
4dd6177e 11405
cd8c2a27
MS
11406 /* Labeled-unicast routes live in the unicast table. */
11407 if (safi == SAFI_LABELED_UNICAST)
11408 safi = SAFI_UNICAST;
11409
1ae44dfc 11410 table = bgp->rib[afi][safi];
d62a17ae 11411 /* use MPLS and ENCAP specific shows until they are merged */
11412 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11413 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11414 output_arg, use_json);
d62a17ae 11415 }
dba3c1d3
PG
11416
11417 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11418 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11419 output_arg, use_json,
11420 1, NULL, NULL);
11421 }
fee0f4c6 11422
96f3485c 11423 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11424 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11425 rpki_target_state);
fee0f4c6 11426}
11427
d62a17ae 11428static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11429 safi_t safi, uint16_t show_flags)
f186de26 11430{
d62a17ae 11431 struct listnode *node, *nnode;
11432 struct bgp *bgp;
11433 int is_first = 1;
9f049418 11434 bool route_output = false;
96f3485c 11435 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11436
d62a17ae 11437 if (use_json)
11438 vty_out(vty, "{\n");
9f689658 11439
d62a17ae 11440 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11441 route_output = true;
d62a17ae 11442 if (use_json) {
11443 if (!is_first)
11444 vty_out(vty, ",\n");
11445 else
11446 is_first = 0;
11447
11448 vty_out(vty, "\"%s\":",
11449 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11450 ? VRF_DEFAULT_NAME
d62a17ae 11451 : bgp->name);
11452 } else {
11453 vty_out(vty, "\nInstance %s:\n",
11454 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11455 ? VRF_DEFAULT_NAME
d62a17ae 11456 : bgp->name);
11457 }
11458 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11459 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11460 }
9f689658 11461
d62a17ae 11462 if (use_json)
11463 vty_out(vty, "}\n");
9f049418
DS
11464 else if (!route_output)
11465 vty_out(vty, "%% BGP instance not found\n");
f186de26 11466}
11467
718e3744 11468/* Header of detailed BGP route information */
d62a17ae 11469void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11470 struct bgp_dest *dest,
11471 const struct prefix_rd *prd,
d62a17ae 11472 afi_t afi, safi_t safi, json_object *json)
11473{
40381db7 11474 struct bgp_path_info *pi;
b54892e0 11475 const struct prefix *p;
d62a17ae 11476 struct peer *peer;
11477 struct listnode *node, *nnode;
06b9f471 11478 char buf1[RD_ADDRSTRLEN];
d62a17ae 11479 int count = 0;
11480 int best = 0;
11481 int suppress = 0;
c5f1e1b2
C
11482 int accept_own = 0;
11483 int route_filter_translated_v4 = 0;
11484 int route_filter_v4 = 0;
11485 int route_filter_translated_v6 = 0;
11486 int route_filter_v6 = 0;
11487 int llgr_stale = 0;
11488 int no_llgr = 0;
11489 int accept_own_nexthop = 0;
11490 int blackhole = 0;
d62a17ae 11491 int no_export = 0;
11492 int no_advertise = 0;
11493 int local_as = 0;
c5f1e1b2 11494 int no_peer = 0;
d62a17ae 11495 int first = 1;
11496 int has_valid_label = 0;
11497 mpls_label_t label = 0;
11498 json_object *json_adv_to = NULL;
67f67ba4
DA
11499 uint32_t ttl = 0;
11500 uint32_t bos = 0;
11501 uint32_t exp = 0;
9bedbb1e 11502
67f67ba4 11503 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11504
67f67ba4
DA
11505 p = bgp_dest_get_prefix(dest);
11506 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11507
44c69747 11508 if (safi == SAFI_EVPN) {
d62a17ae 11509
44c69747 11510 if (!json) {
2dbe669b 11511 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11512 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11513 : "",
2dbe669b 11514 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11515 } else {
11516 json_object_string_add(json, "rd",
11517 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11518 "");
11519 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11520 }
11521 } else {
11522 if (!json) {
9119ef3a
DA
11523 vty_out(vty,
11524 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11525 "\n",
d62a17ae 11526 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11527 ? prefix_rd2str(prd, buf1,
11528 sizeof(buf1))
11529 : ""),
9119ef3a
DA
11530 safi == SAFI_MPLS_VPN ? ":" : "", p,
11531 dest->version);
cd1964ff 11532
9119ef3a 11533 } else {
67d7e256 11534 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11535 json_object_int_add(json, "version", dest->version);
11536
11537 }
44c69747
LK
11538 }
11539
11540 if (has_valid_label) {
11541 if (json)
11542 json_object_int_add(json, "localLabel", label);
11543 else
d62a17ae 11544 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11545 }
11546
11547 if (!json)
d62a17ae 11548 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11549 vty_out(vty, "not allocated\n");
718e3744 11550
9bcb3eef 11551 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11552 struct community *picomm = NULL;
11553
11554 picomm = bgp_attr_get_community(pi->attr);
11555
d62a17ae 11556 count++;
40381db7 11557 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11558 best = count;
4056a5f6 11559 if (bgp_path_suppressed(pi))
d62a17ae 11560 suppress = 1;
cee9c031 11561
9a706b42 11562 if (!picomm)
cee9c031
QY
11563 continue;
11564
11565 no_advertise += community_include(
9a706b42
DA
11566 picomm, COMMUNITY_NO_ADVERTISE);
11567 no_export +=
11568 community_include(picomm, COMMUNITY_NO_EXPORT);
11569 local_as +=
11570 community_include(picomm, COMMUNITY_LOCAL_AS);
11571 accept_own +=
11572 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11573 route_filter_translated_v4 += community_include(
9a706b42 11574 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11575 route_filter_translated_v6 += community_include(
9a706b42 11576 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11577 route_filter_v4 += community_include(
9a706b42 11578 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11579 route_filter_v6 += community_include(
9a706b42
DA
11580 picomm, COMMUNITY_ROUTE_FILTER_v6);
11581 llgr_stale +=
11582 community_include(picomm, COMMUNITY_LLGR_STALE);
11583 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11584 accept_own_nexthop += community_include(
11585 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11586 blackhole +=
11587 community_include(picomm, COMMUNITY_BLACKHOLE);
11588 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11589 }
718e3744 11590 }
718e3744 11591
d62a17ae 11592 if (!json) {
11593 vty_out(vty, "Paths: (%d available", count);
11594 if (best) {
11595 vty_out(vty, ", best #%d", best);
b84060bb
PG
11596 if (safi == SAFI_UNICAST) {
11597 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11598 vty_out(vty, ", table %s",
11599 VRF_DEFAULT_NAME);
11600 else
11601 vty_out(vty, ", vrf %s",
11602 bgp->name);
11603 }
d62a17ae 11604 } else
11605 vty_out(vty, ", no best path");
11606
c5f1e1b2
C
11607 if (accept_own)
11608 vty_out(vty,
11609 ", accept own local route exported and imported in different VRF");
11610 else if (route_filter_translated_v4)
11611 vty_out(vty,
11612 ", mark translated RTs for VPNv4 route filtering");
11613 else if (route_filter_v4)
11614 vty_out(vty,
11615 ", attach RT as-is for VPNv4 route filtering");
11616 else if (route_filter_translated_v6)
11617 vty_out(vty,
11618 ", mark translated RTs for VPNv6 route filtering");
11619 else if (route_filter_v6)
11620 vty_out(vty,
11621 ", attach RT as-is for VPNv6 route filtering");
11622 else if (llgr_stale)
11623 vty_out(vty,
1479ed2f 11624 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11625 else if (no_llgr)
11626 vty_out(vty,
11627 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11628 else if (accept_own_nexthop)
11629 vty_out(vty,
11630 ", accept local nexthop");
11631 else if (blackhole)
11632 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11633 else if (no_export)
11634 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11635 else if (no_advertise)
11636 vty_out(vty, ", not advertised to any peer");
d62a17ae 11637 else if (local_as)
11638 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11639 else if (no_peer)
11640 vty_out(vty,
11641 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11642
11643 if (suppress)
11644 vty_out(vty,
11645 ", Advertisements suppressed by an aggregate.");
11646 vty_out(vty, ")\n");
11647 }
718e3744 11648
d62a17ae 11649 /* If we are not using addpath then we can display Advertised to and
11650 * that will
11651 * show what peers we advertised the bestpath to. If we are using
11652 * addpath
11653 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11654 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11655 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11656 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11657 if (json && !json_adv_to)
11658 json_adv_to = json_object_new_object();
11659
11660 route_vty_out_advertised_to(
11661 vty, peer, &first,
11662 " Advertised to non peer-group peers:\n ",
11663 json_adv_to);
11664 }
11665 }
11666
11667 if (json) {
11668 if (json_adv_to) {
11669 json_object_object_add(json, "advertisedTo",
11670 json_adv_to);
11671 }
11672 } else {
11673 if (first)
11674 vty_out(vty, " Not advertised to any peer");
11675 vty_out(vty, "\n");
11676 }
11677 }
718e3744 11678}
11679
edfee30d 11680static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11681 struct bgp_dest *bgp_node, struct vty *vty,
11682 struct bgp *bgp, afi_t afi, safi_t safi,
11683 json_object *json, enum bgp_path_type pathtype,
4027d19b 11684 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11685{
11686 struct bgp_path_info *pi;
11687 int header = 1;
11688 char rdbuf[RD_ADDRSTRLEN];
11689 json_object *json_header = NULL;
11690 json_object *json_paths = NULL;
4933eaaf 11691 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11692
9bcb3eef 11693 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11694 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11695
11696 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11697 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11698 pi->peer, pi->attr, p);
4933eaaf 11699
4027d19b
DS
11700 if (rpki_target_state != RPKI_NOT_BEING_USED
11701 && rpki_curr_state != rpki_target_state)
4933eaaf 11702 continue;
44c69747
LK
11703
11704 if (json && !json_paths) {
11705 /* Instantiate json_paths only if path is valid */
11706 json_paths = json_object_new_array();
11707 if (pfx_rd) {
11708 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11709 json_header = json_object_new_object();
11710 } else
11711 json_header = json;
11712 }
11713
11714 if (header) {
11715 route_vty_out_detail_header(
11716 vty, bgp, bgp_node, pfx_rd,
11717 AFI_IP, safi, json_header);
11718 header = 0;
11719 }
11720 (*display)++;
11721
11722 if (pathtype == BGP_PATH_SHOW_ALL
11723 || (pathtype == BGP_PATH_SHOW_BESTPATH
11724 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11725 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11726 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11727 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11728 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11729 safi, rpki_curr_state, json_paths);
44c69747
LK
11730 }
11731
11732 if (json && json_paths) {
11733 json_object_object_add(json_header, "paths", json_paths);
11734
11735 if (pfx_rd)
11736 json_object_object_add(json, rdbuf, json_header);
11737 }
11738}
11739
2aad8c42
MS
11740/*
11741 * Return rd based on safi
11742 */
11743static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11744 safi_t safi)
11745{
11746 switch (safi) {
11747 case SAFI_MPLS_VPN:
11748 case SAFI_ENCAP:
11749 case SAFI_EVPN:
11750 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11751 default:
11752 return NULL;
11753
11754 }
11755}
11756
718e3744 11757/* Display specified route of BGP table. */
d62a17ae 11758static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11759 struct bgp_table *rib, const char *ip_str,
11760 afi_t afi, safi_t safi,
4027d19b 11761 enum rpki_states rpki_target_state,
d62a17ae 11762 struct prefix_rd *prd, int prefix_check,
9f049418 11763 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11764{
11765 int ret;
d62a17ae 11766 int display = 0;
11767 struct prefix match;
9bcb3eef
DS
11768 struct bgp_dest *dest;
11769 struct bgp_dest *rm;
d62a17ae 11770 struct bgp_table *table;
11771 json_object *json = NULL;
11772 json_object *json_paths = NULL;
11773
11774 /* Check IP address argument. */
11775 ret = str2prefix(ip_str, &match);
11776 if (!ret) {
11777 vty_out(vty, "address is malformed\n");
11778 return CMD_WARNING;
11779 }
718e3744 11780
d62a17ae 11781 match.family = afi2family(afi);
b05a1c8b 11782
44c69747 11783 if (use_json)
d62a17ae 11784 json = json_object_new_object();
718e3744 11785
44c69747 11786 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11787 for (dest = bgp_table_top(rib); dest;
11788 dest = bgp_route_next(dest)) {
11789 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11790
9bcb3eef 11791 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11792 continue;
9bcb3eef 11793 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11794 if (!table)
ea47320b 11795 continue;
d62a17ae 11796
4953391b
DA
11797 rm = bgp_node_match(table, &match);
11798 if (rm == NULL)
ea47320b 11799 continue;
d62a17ae 11800
9bcb3eef 11801 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11802 if (prefix_check
b54892e0 11803 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11804 bgp_dest_unlock_node(rm);
ea47320b
DL
11805 continue;
11806 }
d62a17ae 11807
9bcb3eef 11808 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11809 bgp, afi, safi, json, pathtype,
4027d19b 11810 &display, rpki_target_state);
44c69747 11811
9bcb3eef 11812 bgp_dest_unlock_node(rm);
44c69747
LK
11813 }
11814 } else if (safi == SAFI_EVPN) {
9bcb3eef 11815 struct bgp_dest *longest_pfx;
cded3b72 11816 bool is_exact_pfxlen_match = false;
44c69747 11817
9bcb3eef
DS
11818 for (dest = bgp_table_top(rib); dest;
11819 dest = bgp_route_next(dest)) {
11820 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11821
9bcb3eef 11822 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11823 continue;
9bcb3eef 11824 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11825 if (!table)
11826 continue;
11827
11828 longest_pfx = NULL;
cded3b72 11829 is_exact_pfxlen_match = false;
44c69747
LK
11830 /*
11831 * Search through all the prefixes for a match. The
11832 * pfx's are enumerated in ascending order of pfxlens.
11833 * So, the last pfx match is the longest match. Set
11834 * is_exact_pfxlen_match when we get exact pfxlen match
11835 */
11836 for (rm = bgp_table_top(table); rm;
11837 rm = bgp_route_next(rm)) {
b54892e0 11838 const struct prefix *rm_p =
9bcb3eef 11839 bgp_dest_get_prefix(rm);
44c69747
LK
11840 /*
11841 * Get prefixlen of the ip-prefix within type5
11842 * evpn route
11843 */
b54892e0
DS
11844 if (evpn_type5_prefix_match(rm_p, &match)
11845 && rm->info) {
44c69747
LK
11846 longest_pfx = rm;
11847 int type5_pfxlen =
b54892e0
DS
11848 bgp_evpn_get_type5_prefixlen(
11849 rm_p);
44c69747 11850 if (type5_pfxlen == match.prefixlen) {
cded3b72 11851 is_exact_pfxlen_match = true;
9bcb3eef 11852 bgp_dest_unlock_node(rm);
44c69747
LK
11853 break;
11854 }
d62a17ae 11855 }
11856 }
ea47320b 11857
44c69747
LK
11858 if (!longest_pfx)
11859 continue;
11860
11861 if (prefix_check && !is_exact_pfxlen_match)
11862 continue;
11863
11864 rm = longest_pfx;
9bcb3eef 11865 bgp_dest_lock_node(rm);
44c69747 11866
9bcb3eef 11867 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11868 bgp, afi, safi, json, pathtype,
4027d19b 11869 &display, rpki_target_state);
44c69747 11870
9bcb3eef 11871 bgp_dest_unlock_node(rm);
d62a17ae 11872 }
98a9dbc7 11873 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11874 if (use_json)
11875 json_paths = json_object_new_array();
11876
63a0b7a9
PG
11877 display = bgp_flowspec_display_match_per_ip(afi, rib,
11878 &match, prefix_check,
11879 vty,
11880 use_json,
11881 json_paths);
d5f20468
SP
11882 if (use_json) {
11883 if (display)
11884 json_object_object_add(json, "paths",
11885 json_paths);
11886 else
11887 json_object_free(json_paths);
11888 }
d62a17ae 11889 } else {
4953391b
DA
11890 dest = bgp_node_match(rib, &match);
11891 if (dest != NULL) {
9bcb3eef 11892 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11893 if (!prefix_check
9bcb3eef
DS
11894 || dest_p->prefixlen == match.prefixlen) {
11895 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11896 safi, json, pathtype,
4027d19b 11897 &display, rpki_target_state);
d62a17ae 11898 }
11899
9bcb3eef 11900 bgp_dest_unlock_node(dest);
d62a17ae 11901 }
11902 }
e5eee9af 11903
d62a17ae 11904 if (use_json) {
75eeda93 11905 vty_json(vty, json);
d62a17ae 11906 } else {
11907 if (!display) {
11908 vty_out(vty, "%% Network not in table\n");
11909 return CMD_WARNING;
11910 }
11911 }
b05a1c8b 11912
d62a17ae 11913 return CMD_SUCCESS;
718e3744 11914}
11915
fee0f4c6 11916/* Display specified route of Main RIB */
d62a17ae 11917static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11918 afi_t afi, safi_t safi, struct prefix_rd *prd,
11919 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11920 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11921{
9b86009a 11922 if (!bgp) {
d62a17ae 11923 bgp = bgp_get_default();
9b86009a
RW
11924 if (!bgp) {
11925 if (!use_json)
11926 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11927 else
11928 vty_out(vty, "{}\n");
9b86009a
RW
11929 return CMD_WARNING;
11930 }
11931 }
d62a17ae 11932
11933 /* labeled-unicast routes live in the unicast table */
11934 if (safi == SAFI_LABELED_UNICAST)
11935 safi = SAFI_UNICAST;
11936
11937 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11938 afi, safi, rpki_target_state, prd,
8aa22bbb 11939 prefix_check, pathtype, use_json);
d62a17ae 11940}
11941
11942static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11943 struct cmd_token **argv, bool exact, afi_t afi,
11944 safi_t safi, bool uj)
d62a17ae 11945{
11946 struct lcommunity *lcom;
11947 struct buffer *b;
11948 int i;
11949 char *str;
11950 int first = 0;
96c81f66 11951 uint16_t show_flags = 0;
4f28b2b5 11952 int ret;
96f3485c
MK
11953
11954 if (uj)
11955 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11956
11957 b = buffer_new(1024);
11958 for (i = 0; i < argc; i++) {
11959 if (first)
11960 buffer_putc(b, ' ');
11961 else {
11962 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11963 first = 1;
11964 buffer_putstr(b, argv[i]->arg);
11965 }
11966 }
11967 }
11968 buffer_putc(b, '\0');
57d187bc 11969
d62a17ae 11970 str = buffer_getstr(b);
11971 buffer_free(b);
57d187bc 11972
d62a17ae 11973 lcom = lcommunity_str2com(str);
11974 XFREE(MTYPE_TMP, str);
11975 if (!lcom) {
11976 vty_out(vty, "%% Large-community malformed\n");
11977 return CMD_WARNING;
11978 }
57d187bc 11979
4f28b2b5 11980 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11981 (exact ? bgp_show_type_lcommunity_exact
11982 : bgp_show_type_lcommunity),
11983 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11984
11985 lcommunity_free(&lcom);
11986 return ret;
57d187bc
JS
11987}
11988
d62a17ae 11989static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11990 const char *lcom, bool exact, afi_t afi,
11991 safi_t safi, bool uj)
57d187bc 11992{
d62a17ae 11993 struct community_list *list;
96c81f66 11994 uint16_t show_flags = 0;
96f3485c
MK
11995
11996 if (uj)
11997 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11998
57d187bc 11999
e237b0d2 12000 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12001 LARGE_COMMUNITY_LIST_MASTER);
12002 if (list == NULL) {
12003 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12004 lcom);
12005 return CMD_WARNING;
12006 }
57d187bc 12007
36a206db 12008 return bgp_show(vty, bgp, afi, safi,
12009 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12010 : bgp_show_type_lcommunity_list),
1e2ce4f1 12011 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12012}
12013
52951b63
DS
12014DEFUN (show_ip_bgp_large_community_list,
12015 show_ip_bgp_large_community_list_cmd,
77a3a95e 12016 "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
12017 SHOW_STR
12018 IP_STR
12019 BGP_STR
12020 BGP_INSTANCE_HELP_STR
9bedbb1e 12021 BGP_AFI_HELP_STR
4dd6177e 12022 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12023 "Display routes matching the large-community-list\n"
12024 "large-community-list number\n"
12025 "large-community-list name\n"
36a206db 12026 "Exact match of the large-communities\n"
52951b63
DS
12027 JSON_STR)
12028{
d62a17ae 12029 afi_t afi = AFI_IP6;
12030 safi_t safi = SAFI_UNICAST;
12031 int idx = 0;
36a206db 12032 bool exact_match = 0;
4d678463 12033 struct bgp *bgp = NULL;
9f049418 12034 bool uj = use_json(argc, argv);
d62a17ae 12035
ef3364f0
DA
12036 if (uj)
12037 argc--;
4d678463 12038
ef3364f0
DA
12039 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12040 &bgp, uj);
12041 if (!idx)
12042 return CMD_WARNING;
d62a17ae 12043
12044 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12045
12046 const char *clist_number_or_name = argv[++idx]->arg;
12047
12048 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12049 exact_match = 1;
12050
12051 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12052 exact_match, afi, safi, uj);
52951b63
DS
12053}
12054DEFUN (show_ip_bgp_large_community,
12055 show_ip_bgp_large_community_cmd,
36a206db 12056 "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
12057 SHOW_STR
12058 IP_STR
12059 BGP_STR
12060 BGP_INSTANCE_HELP_STR
9bedbb1e 12061 BGP_AFI_HELP_STR
4dd6177e 12062 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12063 "Display routes matching the large-communities\n"
12064 "List of large-community numbers\n"
36a206db 12065 "Exact match of the large-communities\n"
52951b63
DS
12066 JSON_STR)
12067{
d62a17ae 12068 afi_t afi = AFI_IP6;
12069 safi_t safi = SAFI_UNICAST;
12070 int idx = 0;
36a206db 12071 bool exact_match = 0;
4d678463 12072 struct bgp *bgp = NULL;
9f049418 12073 bool uj = use_json(argc, argv);
96c81f66 12074 uint16_t show_flags = 0;
d62a17ae 12075
96f3485c
MK
12076 if (uj) {
12077 argc--;
12078 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12079 }
4d678463 12080
96f3485c
MK
12081 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12082 &bgp, uj);
12083 if (!idx)
12084 return CMD_WARNING;
d62a17ae 12085
36a206db 12086 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12087 if (argv_find(argv, argc, "exact-match", &idx))
12088 exact_match = 1;
12089 return bgp_show_lcommunity(vty, bgp, argc, argv,
12090 exact_match, afi, safi, uj);
12091 } else
d62a17ae 12092 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12093 bgp_show_type_lcommunity_all, NULL, show_flags,
12094 RPKI_NOT_BEING_USED);
52951b63
DS
12095}
12096
71f1613a
DA
12097static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12098 safi_t safi, struct json_object *json_array);
d62a17ae 12099static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12100 safi_t safi, struct json_object *json);
e01ca200 12101
7b2ff250 12102
9ab0cf58
PG
12103DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12104 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12105 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12106 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12107{
12108 bool uj = use_json(argc, argv);
12109 struct bgp *bgp = NULL;
ec76a1d1
DA
12110 safi_t safi = SAFI_UNICAST;
12111 afi_t afi = AFI_IP6;
4265b261 12112 int idx = 0;
6c9d22e2
PG
12113 struct json_object *json_all = NULL;
12114 struct json_object *json_afi_safi = NULL;
4265b261
PG
12115
12116 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12117 &bgp, false);
71f1613a 12118 if (!idx)
4265b261 12119 return CMD_WARNING;
6c9d22e2 12120
4265b261 12121 if (uj)
6c9d22e2 12122 json_all = json_object_new_object();
4265b261 12123
9ab0cf58
PG
12124 FOREACH_AFI_SAFI (afi, safi) {
12125 /*
12126 * So limit output to those afi/safi pairs that
12127 * actually have something interesting in them
12128 */
12129 if (strmatch(get_afi_safi_str(afi, safi, true),
12130 "Unknown")) {
12131 continue;
12132 }
12133 if (uj) {
12134 json_afi_safi = json_object_new_array();
12135 json_object_object_add(
12136 json_all,
12137 get_afi_safi_str(afi, safi, true),
12138 json_afi_safi);
12139 } else {
12140 json_afi_safi = NULL;
6c9d22e2 12141 }
9ab0cf58
PG
12142
12143 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12144 }
6c9d22e2 12145
3757f964
DA
12146 if (uj)
12147 vty_json(vty, json_all);
6c9d22e2 12148
4265b261
PG
12149 return CMD_SUCCESS;
12150}
12151
7b2ff250 12152/* BGP route print out function without JSON */
14718643
PG
12153DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12154 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12155 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12156 SHOW_STR
12157 IP_STR
12158 BGP_STR
12159 BGP_INSTANCE_HELP_STR
12160 L2VPN_HELP_STR
12161 EVPN_HELP_STR
12162 "BGP RIB advertisement statistics\n"
12163 JSON_STR)
12164{
ec76a1d1
DA
12165 afi_t afi = AFI_IP6;
12166 safi_t safi = SAFI_UNICAST;
14718643
PG
12167 struct bgp *bgp = NULL;
12168 int idx = 0, ret;
12169 bool uj = use_json(argc, argv);
12170 struct json_object *json_afi_safi = NULL, *json = NULL;
12171
12172 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12173 &bgp, false);
12174 if (!idx)
12175 return CMD_WARNING;
12176
12177 if (uj)
12178 json_afi_safi = json_object_new_array();
12179 else
12180 json_afi_safi = NULL;
12181
12182 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12183
12184 if (uj) {
12185 json = json_object_new_object();
12186 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12187 json_afi_safi);
3757f964 12188 vty_json(vty, json);
14718643
PG
12189 }
12190 return ret;
12191}
12192
893cccd0 12193/* BGP route print out function without JSON */
9ab0cf58
PG
12194DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12195 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12196 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12197 "]]\
893cccd0 12198 statistics [json]",
9ab0cf58
PG
12199 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12200 BGP_SAFI_WITH_LABEL_HELP_STR
12201 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12202{
ec76a1d1
DA
12203 afi_t afi = AFI_IP6;
12204 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12205 struct bgp *bgp = NULL;
12206 int idx = 0, ret;
12207 bool uj = use_json(argc, argv);
6c9d22e2 12208 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12209
12210 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12211 &bgp, false);
12212 if (!idx)
12213 return CMD_WARNING;
6c9d22e2 12214
893cccd0 12215 if (uj)
6c9d22e2
PG
12216 json_afi_safi = json_object_new_array();
12217 else
12218 json_afi_safi = NULL;
12219
12220 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12221
12222 if (uj) {
12223 json = json_object_new_object();
12224 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12225 json_afi_safi);
3757f964 12226 vty_json(vty, json);
893cccd0
PG
12227 }
12228 return ret;
893cccd0 12229}
7b2ff250 12230
fe0f234d 12231DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12232 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12233 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12234 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12235 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12236 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12237 "Display the entries for all address families\n"
9ab0cf58
PG
12238 "Display detailed information about dampening\n"
12239 "Display detail of configured dampening parameters\n"
fe0f234d 12240 JSON_STR)
718e3744 12241{
d62a17ae 12242 afi_t afi = AFI_IP6;
12243 safi_t safi = SAFI_UNICAST;
d62a17ae 12244 struct bgp *bgp = NULL;
12245 int idx = 0;
96c81f66 12246 uint16_t show_flags = 0;
fe0f234d
RW
12247 bool uj = use_json(argc, argv);
12248
12249 if (uj) {
12250 argc--;
12251 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12252 }
96f3485c
MK
12253
12254 /* [<ipv4|ipv6> [all]] */
12255 if (all) {
12256 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12257 if (argv_find(argv, argc, "ipv4", &idx))
12258 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12259
12260 if (argv_find(argv, argc, "ipv6", &idx))
12261 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12262 }
d62a17ae 12263
12264 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12265 &bgp, false);
d62a17ae 12266 if (!idx)
12267 return CMD_WARNING;
12268
fe0f234d 12269 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12270}
12271
fe0f234d
RW
12272/* BGP route print out function */
12273DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12274 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12275 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12276 "]]\
96f3485c 12277 [all$all]\
cf4898bc
QY
12278 [cidr-only\
12279 |dampening <flap-statistics|dampened-paths>\
12280 |community [AA:NN|local-AS|no-advertise|no-export\
12281 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12282 |accept-own|accept-own-nexthop|route-filter-v6\
12283 |route-filter-v4|route-filter-translated-v6\
12284 |route-filter-translated-v4] [exact-match]\
70799983 12285 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12286 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12287 |prefix-list WORD\
70dd370f 12288 |route-map RMAP_NAME\
1e2ce4f1 12289 |rpki <invalid|valid|notfound>\
7d3cae70 12290 |version (1-4294967295)\
b4ad2fae 12291 |alias ALIAS_NAME\
39c3c736
RW
12292 |A.B.C.D/M longer-prefixes\
12293 |X:X::X:X/M longer-prefixes\
f280c93b 12294 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12295 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12296 BGP_SAFI_WITH_LABEL_HELP_STR
12297 "Display the entries for all address families\n"
12298 "Display only routes with non-natural netmasks\n"
12299 "Display detailed information about dampening\n"
12300 "Display flap statistics of routes\n"
12301 "Display paths suppressed due to dampening\n"
12302 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12303 "Do not send outside local AS (well-known community)\n"
12304 "Do not advertise to any peer (well-known community)\n"
12305 "Do not export to next AS (well-known community)\n"
12306 "Graceful shutdown (well-known community)\n"
12307 "Do not export to any peer (well-known community)\n"
12308 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12309 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12310 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12311 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12312 "Should accept VPN route with local nexthop (well-known community)\n"
12313 "RT VPNv6 route filtering (well-known community)\n"
12314 "RT VPNv4 route filtering (well-known community)\n"
12315 "RT translated VPNv6 route filtering (well-known community)\n"
12316 "RT translated VPNv4 route filtering (well-known community)\n"
12317 "Exact match of the communities\n"
70799983
RW
12318 "Community-list number\n"
12319 "Community-list name\n"
12320 "Display routes matching the community-list\n"
12321 "Exact match of the communities\n"
a7129347
RW
12322 "Display routes conforming to the filter-list\n"
12323 "Regular expression access list name\n"
6deaf579
RW
12324 "Display routes conforming to the prefix-list\n"
12325 "Prefix-list name\n"
bf1a944a
RW
12326 "Display routes matching the route-map\n"
12327 "A route-map to match on\n"
a70a28a5
DA
12328 "RPKI route types\n"
12329 "A valid path as determined by rpki\n"
12330 "A invalid path as determined by rpki\n"
12331 "A path that has no rpki data\n"
12332 "Display prefixes with matching version numbers\n"
12333 "Version number and above\n"
12334 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12335 "BGP community alias\n"
12336 "IPv4 prefix\n"
12337 "Display route and more specific routes\n"
12338 "IPv6 prefix\n"
12339 "Display route and more specific routes\n"
12340 JSON_STR
a70a28a5
DA
12341 "Display detailed version of JSON output\n"
12342 "Increase table width for longer prefixes\n")
7b2ff250
DW
12343{
12344 afi_t afi = AFI_IP6;
12345 safi_t safi = SAFI_UNICAST;
12346 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12347 void *output_arg = NULL;
7b2ff250
DW
12348 struct bgp *bgp = NULL;
12349 int idx = 0;
d0086e8e 12350 int exact_match = 0;
96f3485c
MK
12351 char *community = NULL;
12352 bool first = true;
96c81f66 12353 uint16_t show_flags = 0;
4027d19b 12354 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12355 struct prefix p;
96f3485c
MK
12356
12357 if (uj) {
9f049418 12358 argc--;
96f3485c
MK
12359 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12360 }
12361
f280c93b
DA
12362 if (detail)
12363 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12364
96f3485c
MK
12365 /* [<ipv4|ipv6> [all]] */
12366 if (all) {
12367 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12368
12369 if (argv_find(argv, argc, "ipv4", &idx))
12370 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12371
12372 if (argv_find(argv, argc, "ipv6", &idx))
12373 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12374 }
12375
12376 if (wide)
12377 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12378
12379 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12380 &bgp, uj);
7b2ff250
DW
12381 if (!idx)
12382 return CMD_WARNING;
12383
7b2ff250 12384 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12385 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12386
12387 if (argv_find(argv, argc, "dampening", &idx)) {
12388 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12389 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12390 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12391 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12392 }
12393
12394 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12395 char *maybecomm = NULL;
d0086e8e 12396
79bc257a
RW
12397 if (idx + 1 < argc) {
12398 if (argv[idx + 1]->type == VARIABLE_TKN)
12399 maybecomm = argv[idx + 1]->arg;
12400 else
12401 maybecomm = argv[idx + 1]->text;
12402 }
12403
cf4898bc
QY
12404 if (maybecomm && !strmatch(maybecomm, "json")
12405 && !strmatch(maybecomm, "exact-match"))
12406 community = maybecomm;
d0086e8e 12407
cf4898bc
QY
12408 if (argv_find(argv, argc, "exact-match", &idx))
12409 exact_match = 1;
d0086e8e 12410
96f3485c
MK
12411 if (!community)
12412 sh_type = bgp_show_type_community_all;
12413 }
12414
70799983
RW
12415 if (argv_find(argv, argc, "community-list", &idx)) {
12416 const char *clist_number_or_name = argv[++idx]->arg;
12417 struct community_list *list;
12418
12419 if (argv_find(argv, argc, "exact-match", &idx))
12420 exact_match = 1;
12421
12422 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12423 COMMUNITY_LIST_MASTER);
12424 if (list == NULL) {
12425 vty_out(vty,
12426 "%% %s is not a valid community-list name\n",
12427 clist_number_or_name);
12428 return CMD_WARNING;
12429 }
12430
12431 if (exact_match)
12432 sh_type = bgp_show_type_community_list_exact;
12433 else
12434 sh_type = bgp_show_type_community_list;
12435 output_arg = list;
12436 }
12437
a7129347
RW
12438 if (argv_find(argv, argc, "filter-list", &idx)) {
12439 const char *filter = argv[++idx]->arg;
12440 struct as_list *as_list;
12441
12442 as_list = as_list_lookup(filter);
12443 if (as_list == NULL) {
12444 vty_out(vty,
12445 "%% %s is not a valid AS-path access-list name\n",
12446 filter);
12447 return CMD_WARNING;
12448 }
12449
12450 sh_type = bgp_show_type_filter_list;
12451 output_arg = as_list;
12452 }
12453
6deaf579
RW
12454 if (argv_find(argv, argc, "prefix-list", &idx)) {
12455 const char *prefix_list_str = argv[++idx]->arg;
12456 struct prefix_list *plist;
12457
12458 plist = prefix_list_lookup(afi, prefix_list_str);
12459 if (plist == NULL) {
12460 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12461 prefix_list_str);
12462 return CMD_WARNING;
12463 }
12464
12465 sh_type = bgp_show_type_prefix_list;
12466 output_arg = plist;
12467 }
12468
bf1a944a
RW
12469 if (argv_find(argv, argc, "route-map", &idx)) {
12470 const char *rmap_str = argv[++idx]->arg;
12471 struct route_map *rmap;
12472
12473 rmap = route_map_lookup_by_name(rmap_str);
12474 if (!rmap) {
12475 vty_out(vty, "%% %s is not a valid route-map name\n",
12476 rmap_str);
12477 return CMD_WARNING;
12478 }
12479
12480 sh_type = bgp_show_type_route_map;
12481 output_arg = rmap;
12482 }
12483
1e2ce4f1
DS
12484 if (argv_find(argv, argc, "rpki", &idx)) {
12485 sh_type = bgp_show_type_rpki;
12486 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12487 rpki_target_state = RPKI_VALID;
1e2ce4f1 12488 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12489 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12490 }
12491
7d3cae70
DA
12492 /* Display prefixes with matching version numbers */
12493 if (argv_find(argv, argc, "version", &idx)) {
12494 sh_type = bgp_show_type_prefix_version;
2391833e 12495 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12496 }
12497
a70a28a5
DA
12498 /* Display prefixes with matching BGP community alias */
12499 if (argv_find(argv, argc, "alias", &idx)) {
12500 sh_type = bgp_show_type_community_alias;
2391833e 12501 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12502 }
12503
39c3c736
RW
12504 /* prefix-longer */
12505 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12506 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12507 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12508
12509 if (!str2prefix(prefix_str, &p)) {
12510 vty_out(vty, "%% Malformed Prefix\n");
12511 return CMD_WARNING;
12512 }
12513
12514 sh_type = bgp_show_type_prefix_longer;
12515 output_arg = &p;
a70a28a5
DA
12516 }
12517
96f3485c
MK
12518 if (!all) {
12519 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12520 if (community)
12521 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12522 exact_match, afi, safi,
12523 show_flags);
2391833e 12524 else
a70a28a5 12525 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12526 output_arg, show_flags,
a70a28a5 12527 rpki_target_state);
96f3485c 12528 } else {
fa5ac378
DA
12529 struct listnode *node;
12530 struct bgp *abgp;
96f3485c
MK
12531 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12532 * AFI_IP6 */
12533
12534 if (uj)
12535 vty_out(vty, "{\n");
12536
12537 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12538 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12539 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12540 ? AFI_IP
12541 : AFI_IP6;
fa5ac378
DA
12542 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12543 FOREACH_SAFI (safi) {
12544 if (!bgp_afi_safi_peer_exists(abgp, afi,
12545 safi))
12546 continue;
96f3485c 12547
fa5ac378
DA
12548 if (uj) {
12549 if (first)
12550 first = false;
12551 else
12552 vty_out(vty, ",\n");
12553 vty_out(vty, "\"%s\":{\n",
12554 get_afi_safi_str(afi,
12555 safi,
12556 true));
12557 } else
12558 vty_out(vty,
12559 "\nFor address family: %s\n",
12560 get_afi_safi_str(
12561 afi, safi,
12562 false));
12563
12564 if (community)
12565 bgp_show_community(
12566 vty, abgp, community,
12567 exact_match, afi, safi,
12568 show_flags);
96f3485c 12569 else
fa5ac378
DA
12570 bgp_show(vty, abgp, afi, safi,
12571 sh_type, output_arg,
12572 show_flags,
12573 rpki_target_state);
12574 if (uj)
12575 vty_out(vty, "}\n");
12576 }
96f3485c
MK
12577 }
12578 } else {
12579 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12580 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12581 FOREACH_AFI_SAFI (afi, safi) {
12582 if (!bgp_afi_safi_peer_exists(abgp, afi,
12583 safi))
12584 continue;
96f3485c 12585
fa5ac378
DA
12586 if (uj) {
12587 if (first)
12588 first = false;
12589 else
12590 vty_out(vty, ",\n");
12591
12592 vty_out(vty, "\"%s\":{\n",
12593 get_afi_safi_str(afi,
12594 safi,
12595 true));
12596 } else
12597 vty_out(vty,
12598 "\nFor address family: %s\n",
12599 get_afi_safi_str(
12600 afi, safi,
12601 false));
12602
12603 if (community)
12604 bgp_show_community(
12605 vty, abgp, community,
12606 exact_match, afi, safi,
12607 show_flags);
96f3485c 12608 else
fa5ac378
DA
12609 bgp_show(vty, abgp, afi, safi,
12610 sh_type, output_arg,
12611 show_flags,
12612 rpki_target_state);
12613 if (uj)
12614 vty_out(vty, "}\n");
12615 }
96f3485c
MK
12616 }
12617 }
12618 if (uj)
12619 vty_out(vty, "}\n");
12620 }
12621 return CMD_SUCCESS;
a636c635 12622}
47fc97cc 12623
718e3744 12624DEFUN (show_ip_bgp_route,
12625 show_ip_bgp_route_cmd,
8aa22bbb 12626 "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 12627 SHOW_STR
12628 IP_STR
12629 BGP_STR
a636c635 12630 BGP_INSTANCE_HELP_STR
4f280b15 12631 BGP_AFI_HELP_STR
4dd6177e 12632 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12633 "Network in the BGP routing table to display\n"
0c7b1b01 12634 "IPv4 prefix\n"
8c3deaae 12635 "Network in the BGP routing table to display\n"
0c7b1b01 12636 "IPv6 prefix\n"
4092b06c 12637 "Display only the bestpath\n"
b05a1c8b 12638 "Display only multipaths\n"
8aa22bbb
DS
12639 "Display only paths that match the specified rpki state\n"
12640 "A valid path as determined by rpki\n"
12641 "A invalid path as determined by rpki\n"
12642 "A path that has no rpki data\n"
9973d184 12643 JSON_STR)
4092b06c 12644{
d62a17ae 12645 int prefix_check = 0;
ae19d7dd 12646
d62a17ae 12647 afi_t afi = AFI_IP6;
12648 safi_t safi = SAFI_UNICAST;
12649 char *prefix = NULL;
12650 struct bgp *bgp = NULL;
12651 enum bgp_path_type path_type;
9f049418 12652 bool uj = use_json(argc, argv);
b05a1c8b 12653
d62a17ae 12654 int idx = 0;
ae19d7dd 12655
d62a17ae 12656 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12657 &bgp, uj);
d62a17ae 12658 if (!idx)
12659 return CMD_WARNING;
c41247f5 12660
d62a17ae 12661 if (!bgp) {
12662 vty_out(vty,
12663 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12664 return CMD_WARNING;
12665 }
a636c635 12666
d62a17ae 12667 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12668 if (argv_find(argv, argc, "A.B.C.D", &idx)
12669 || argv_find(argv, argc, "X:X::X:X", &idx))
12670 prefix_check = 0;
12671 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12672 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12673 prefix_check = 1;
12674
12675 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12676 && afi != AFI_IP6) {
12677 vty_out(vty,
12678 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12679 return CMD_WARNING;
12680 }
12681 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12682 && afi != AFI_IP) {
12683 vty_out(vty,
12684 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12685 return CMD_WARNING;
12686 }
12687
12688 prefix = argv[idx]->arg;
12689
12690 /* [<bestpath|multipath>] */
12691 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12692 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12693 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12694 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12695 else
360660c6 12696 path_type = BGP_PATH_SHOW_ALL;
a636c635 12697
d62a17ae 12698 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12699 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12700}
12701
8c3deaae
QY
12702DEFUN (show_ip_bgp_regexp,
12703 show_ip_bgp_regexp_cmd,
3e5b31b3 12704 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12705 SHOW_STR
12706 IP_STR
12707 BGP_STR
b00b230a 12708 BGP_INSTANCE_HELP_STR
4f280b15 12709 BGP_AFI_HELP_STR
4dd6177e 12710 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12711 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12712 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12713 JSON_STR)
8c3deaae 12714{
d62a17ae 12715 afi_t afi = AFI_IP6;
12716 safi_t safi = SAFI_UNICAST;
12717 struct bgp *bgp = NULL;
3e5b31b3
DA
12718 bool uj = use_json(argc, argv);
12719 char *regstr = NULL;
8c3deaae 12720
d62a17ae 12721 int idx = 0;
12722 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12723 &bgp, false);
d62a17ae 12724 if (!idx)
12725 return CMD_WARNING;
8c3deaae 12726
d62a17ae 12727 // get index of regex
3e5b31b3
DA
12728 if (argv_find(argv, argc, "REGEX", &idx))
12729 regstr = argv[idx]->arg;
8c3deaae 12730
5f71d11c 12731 assert(regstr);
3e5b31b3
DA
12732 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12733 bgp_show_type_regexp, uj);
8c3deaae
QY
12734}
12735
ae248832 12736DEFPY (show_ip_bgp_instance_all,
a636c635 12737 show_ip_bgp_instance_all_cmd,
ae248832 12738 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12739 SHOW_STR
a636c635 12740 IP_STR
4092b06c 12741 BGP_STR
a636c635 12742 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12743 BGP_AFI_HELP_STR
4dd6177e 12744 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12745 JSON_STR
12746 "Increase table width for longer prefixes\n")
4092b06c 12747{
54d05dea 12748 afi_t afi = AFI_IP6;
d62a17ae 12749 safi_t safi = SAFI_UNICAST;
12750 struct bgp *bgp = NULL;
d62a17ae 12751 int idx = 0;
96c81f66 12752 uint16_t show_flags = 0;
ae19d7dd 12753
96f3485c 12754 if (uj) {
d62a17ae 12755 argc--;
96f3485c
MK
12756 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12757 }
12758
12759 if (wide)
12760 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12761
9f049418
DS
12762 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12763 &bgp, uj);
12764 if (!idx)
12765 return CMD_WARNING;
12766
96f3485c 12767 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12768 return CMD_SUCCESS;
e3e29b32
LB
12769}
12770
a4d82a8a 12771static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12772 afi_t afi, safi_t safi, enum bgp_show_type type,
12773 bool use_json)
718e3744 12774{
d62a17ae 12775 regex_t *regex;
12776 int rc;
96c81f66 12777 uint16_t show_flags = 0;
96f3485c
MK
12778
12779 if (use_json)
12780 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12781
c3900853 12782 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12783 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12784 regstr);
12785 return CMD_WARNING_CONFIG_FAILED;
12786 }
12787
d62a17ae 12788 regex = bgp_regcomp(regstr);
12789 if (!regex) {
12790 vty_out(vty, "Can't compile regexp %s\n", regstr);
12791 return CMD_WARNING;
12792 }
a636c635 12793
1e2ce4f1
DS
12794 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12795 RPKI_NOT_BEING_USED);
d62a17ae 12796 bgp_regex_free(regex);
12797 return rc;
e3e29b32
LB
12798}
12799
7f323236
DW
12800static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12801 const char *comstr, int exact, afi_t afi,
96c81f66 12802 safi_t safi, uint16_t show_flags)
d62a17ae 12803{
12804 struct community *com;
d62a17ae 12805 int ret = 0;
12806
7f323236 12807 com = community_str2com(comstr);
d62a17ae 12808 if (!com) {
7f323236 12809 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12810 return CMD_WARNING;
12811 }
12812
12813 ret = bgp_show(vty, bgp, afi, safi,
12814 (exact ? bgp_show_type_community_exact
12815 : bgp_show_type_community),
1e2ce4f1 12816 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12817 community_free(&com);
46c3ce83 12818
d62a17ae 12819 return ret;
718e3744 12820}
12821
d62a17ae 12822enum bgp_stats {
12823 BGP_STATS_MAXBITLEN = 0,
12824 BGP_STATS_RIB,
12825 BGP_STATS_PREFIXES,
12826 BGP_STATS_TOTPLEN,
12827 BGP_STATS_UNAGGREGATEABLE,
12828 BGP_STATS_MAX_AGGREGATEABLE,
12829 BGP_STATS_AGGREGATES,
12830 BGP_STATS_SPACE,
12831 BGP_STATS_ASPATH_COUNT,
12832 BGP_STATS_ASPATH_MAXHOPS,
12833 BGP_STATS_ASPATH_TOTHOPS,
12834 BGP_STATS_ASPATH_MAXSIZE,
12835 BGP_STATS_ASPATH_TOTSIZE,
12836 BGP_STATS_ASN_HIGHEST,
12837 BGP_STATS_MAX,
a636c635 12838};
2815e61f 12839
9ab0cf58 12840#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12841#define TABLE_STATS_IDX_JSON 1
12842
12843static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12844 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12845 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12846 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12847 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12848 "unaggregateablePrefixes"},
12849 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12850 "maximumAggregateablePrefixes"},
12851 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12852 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12853 [BGP_STATS_SPACE] = {"Address space advertised",
12854 "addressSpaceAdvertised"},
9ab0cf58
PG
12855 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12856 "advertisementsWithPaths"},
12857 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12858 "longestAsPath"},
12859 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12860 "largestAsPath"},
12861 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12862 "averageAsPathLengthHops"},
12863 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12864 "averageAsPathSizeBytes"},
12865 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12866 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12867};
2815e61f 12868
d62a17ae 12869struct bgp_table_stats {
12870 struct bgp_table *table;
12871 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
12872
12873 unsigned long long
12874 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
12875 1];
12876
8d0ab76d 12877 double total_space;
ff7924f6
PJ
12878};
12879
9bcb3eef 12880static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12881 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12882{
9bcb3eef 12883 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12884 struct bgp_path_info *pi;
b54892e0 12885 const struct prefix *rn_p;
d62a17ae 12886
9bcb3eef 12887 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12888 return;
d62a17ae 12889
9bcb3eef 12890 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12891 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12892 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12893
0747643e 12894 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 12895 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12896 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12897 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12898
9bcb3eef 12899 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12900 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12901 /* announced address space */
12902 if (space)
b54892e0 12903 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12904 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12905 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12906
9c14ec72 12907
9bcb3eef 12908 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12909 ts->counts[BGP_STATS_RIB]++;
12910
05864da7
DS
12911 if (CHECK_FLAG(pi->attr->flag,
12912 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12913 ts->counts[BGP_STATS_AGGREGATES]++;
12914
12915 /* as-path stats */
05864da7 12916 if (pi->attr->aspath) {
9c14ec72
RW
12917 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12918 unsigned int size = aspath_size(pi->attr->aspath);
12919 as_t highest = aspath_highest(pi->attr->aspath);
12920
12921 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12922
12923 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12924 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12925
12926 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12927 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12928
12929 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12930 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12931 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12932 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12933 }
12934 }
12935}
12936
cc9f21da 12937static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12938{
9bcb3eef
DS
12939 struct bgp_dest *dest, *ndest;
12940 struct bgp_dest *top;
9c14ec72
RW
12941 struct bgp_table_stats *ts = THREAD_ARG(t);
12942 unsigned int space = 0;
12943
12944 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12945 return;
9c14ec72
RW
12946
12947 switch (ts->table->afi) {
12948 case AFI_IP:
12949 space = IPV4_MAX_BITLEN;
12950 break;
12951 case AFI_IP6:
12952 space = IPV6_MAX_BITLEN;
12953 break;
3ba7b4af
TA
12954 case AFI_L2VPN:
12955 space = EVPN_ROUTE_PREFIXLEN;
12956 break;
9c14ec72 12957 default:
cc9f21da 12958 return;
9c14ec72
RW
12959 }
12960
12961 ts->counts[BGP_STATS_MAXBITLEN] = space;
12962
9bcb3eef 12963 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12964 if (ts->table->safi == SAFI_MPLS_VPN
12965 || ts->table->safi == SAFI_ENCAP
12966 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12967 struct bgp_table *table;
12968
9bcb3eef 12969 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12970 if (!table)
12971 continue;
12972
12973 top = bgp_table_top(table);
9bcb3eef
DS
12974 for (ndest = bgp_table_top(table); ndest;
12975 ndest = bgp_route_next(ndest))
12976 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12977 } else {
9bcb3eef 12978 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12979 }
12980 }
2815e61f 12981}
ff7924f6 12982
71f1613a
DA
12983static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12984 struct json_object *json_array)
12985{
12986 struct listnode *node, *nnode;
12987 struct bgp *bgp;
12988
12989 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12990 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12991}
12992
12993static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12994 safi_t safi, struct json_object *json_array)
2815e61f 12995{
d62a17ae 12996 struct bgp_table_stats ts;
12997 unsigned int i;
893cccd0
PG
12998 int ret = CMD_SUCCESS;
12999 char temp_buf[20];
6c9d22e2 13000 struct json_object *json = NULL;
0747643e
AQ
13001 uint32_t bitlen = 0;
13002 struct json_object *json_bitlen;
6c9d22e2
PG
13003
13004 if (json_array)
13005 json = json_object_new_object();
019386c2 13006
d62a17ae 13007 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13008 char warning_msg[50];
13009
13010 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13011 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13012 safi);
6c9d22e2
PG
13013
13014 if (!json)
893cccd0
PG
13015 vty_out(vty, "%s\n", warning_msg);
13016 else
9ab0cf58 13017 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13018
893cccd0
PG
13019 ret = CMD_WARNING;
13020 goto end_table_stats;
d62a17ae 13021 }
019386c2 13022
893cccd0 13023 if (!json)
5290ceab
DA
13024 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13025 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13026 else
13027 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13028
d62a17ae 13029 /* labeled-unicast routes live in the unicast table */
13030 if (safi == SAFI_LABELED_UNICAST)
13031 safi = SAFI_UNICAST;
019386c2 13032
d62a17ae 13033 memset(&ts, 0, sizeof(ts));
13034 ts.table = bgp->rib[afi][safi];
13035 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13036
d62a17ae 13037 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13038 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13039 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13040 continue;
13041
13042 switch (i) {
d62a17ae 13043 case BGP_STATS_ASPATH_TOTHOPS:
13044 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13045 if (!json) {
9ab0cf58
PG
13046 snprintf(
13047 temp_buf, sizeof(temp_buf), "%12.2f",
13048 ts.counts[i]
13049 ? (float)ts.counts[i]
13050 / (float)ts.counts
13051 [BGP_STATS_ASPATH_COUNT]
13052 : 0);
893cccd0 13053 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13054 table_stats_strs[i]
13055 [TABLE_STATS_IDX_VTY],
893cccd0 13056 temp_buf);
9ab0cf58
PG
13057 } else {
13058 json_object_double_add(
13059 json,
13060 table_stats_strs[i]
13061 [TABLE_STATS_IDX_JSON],
13062 ts.counts[i]
13063 ? (double)ts.counts[i]
13064 / (double)ts.counts
d62a17ae 13065 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13066 : 0);
13067 }
d62a17ae 13068 break;
13069 case BGP_STATS_TOTPLEN:
6c9d22e2 13070 if (!json) {
9ab0cf58
PG
13071 snprintf(
13072 temp_buf, sizeof(temp_buf), "%12.2f",
13073 ts.counts[i]
13074 ? (float)ts.counts[i]
13075 / (float)ts.counts
13076 [BGP_STATS_PREFIXES]
13077 : 0);
893cccd0 13078 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13079 table_stats_strs[i]
13080 [TABLE_STATS_IDX_VTY],
893cccd0 13081 temp_buf);
9ab0cf58
PG
13082 } else {
13083 json_object_double_add(
13084 json,
13085 table_stats_strs[i]
13086 [TABLE_STATS_IDX_JSON],
13087 ts.counts[i]
13088 ? (double)ts.counts[i]
13089 / (double)ts.counts
d62a17ae 13090 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13091 : 0);
13092 }
d62a17ae 13093 break;
13094 case BGP_STATS_SPACE:
6c9d22e2
PG
13095 if (!json) {
13096 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13097 ts.total_space);
893cccd0 13098 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13099 table_stats_strs[i]
13100 [TABLE_STATS_IDX_VTY],
893cccd0 13101 temp_buf);
9ab0cf58
PG
13102 } else {
13103 json_object_double_add(
13104 json,
13105 table_stats_strs[i]
13106 [TABLE_STATS_IDX_JSON],
13107 (double)ts.total_space);
13108 }
8d0ab76d 13109 if (afi == AFI_IP6) {
6c9d22e2
PG
13110 if (!json) {
13111 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13112 "%12g",
13113 ts.total_space
13114 * pow(2.0, -128 + 32));
6c9d22e2
PG
13115 vty_out(vty, "%30s: %s\n",
13116 "/32 equivalent %s\n",
13117 temp_buf);
9ab0cf58
PG
13118 } else {
13119 json_object_double_add(
13120 json, "/32equivalent",
13121 (double)(ts.total_space
13122 * pow(2.0,
13123 -128 + 32)));
13124 }
6c9d22e2
PG
13125 if (!json) {
13126 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13127 "%12g",
13128 ts.total_space
13129 * pow(2.0, -128 + 48));
6c9d22e2
PG
13130 vty_out(vty, "%30s: %s\n",
13131 "/48 equivalent %s\n",
13132 temp_buf);
9ab0cf58
PG
13133 } else {
13134 json_object_double_add(
13135 json, "/48equivalent",
13136 (double)(ts.total_space
13137 * pow(2.0,
13138 -128 + 48)));
13139 }
8d0ab76d 13140 } else {
6c9d22e2
PG
13141 if (!json) {
13142 snprintf(temp_buf, sizeof(temp_buf),
13143 "%12.2f",
9ab0cf58
PG
13144 ts.total_space * 100.
13145 * pow(2.0, -32));
6c9d22e2 13146 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13147 "% announced ", temp_buf);
13148 } else {
13149 json_object_double_add(
13150 json, "%announced",
13151 (double)(ts.total_space * 100.
13152 * pow(2.0, -32)));
13153 }
6c9d22e2
PG
13154 if (!json) {
13155 snprintf(temp_buf, sizeof(temp_buf),
13156 "%12.2f",
9ab0cf58
PG
13157 ts.total_space
13158 * pow(2.0, -32 + 8));
6c9d22e2
PG
13159 vty_out(vty, "%30s: %s\n",
13160 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13161 } else {
13162 json_object_double_add(
13163 json, "/8equivalent",
13164 (double)(ts.total_space
13165 * pow(2.0, -32 + 8)));
13166 }
6c9d22e2
PG
13167 if (!json) {
13168 snprintf(temp_buf, sizeof(temp_buf),
13169 "%12.2f",
9ab0cf58
PG
13170 ts.total_space
13171 * pow(2.0, -32 + 24));
6c9d22e2 13172 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13173 "/24 equivalent ", temp_buf);
13174 } else {
13175 json_object_double_add(
13176 json, "/24equivalent",
13177 (double)(ts.total_space
13178 * pow(2.0, -32 + 24)));
13179 }
8d0ab76d 13180 }
d62a17ae 13181 break;
13182 default:
6c9d22e2
PG
13183 if (!json) {
13184 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13185 ts.counts[i]);
893cccd0 13186 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13187 table_stats_strs[i]
13188 [TABLE_STATS_IDX_VTY],
13189 temp_buf);
13190 } else {
13191 json_object_int_add(
13192 json,
13193 table_stats_strs[i]
13194 [TABLE_STATS_IDX_JSON],
13195 ts.counts[i]);
13196 }
d62a17ae 13197 }
893cccd0
PG
13198 if (!json)
13199 vty_out(vty, "\n");
d62a17ae 13200 }
0747643e
AQ
13201
13202 switch (afi) {
13203 case AFI_IP:
13204 bitlen = IPV4_MAX_BITLEN;
13205 break;
13206 case AFI_IP6:
13207 bitlen = IPV6_MAX_BITLEN;
13208 break;
13209 case AFI_L2VPN:
13210 bitlen = EVPN_ROUTE_PREFIXLEN;
13211 break;
13212 default:
13213 break;
13214 }
13215
13216 if (json) {
13217 json_bitlen = json_object_new_array();
13218
13219 for (i = 0; i <= bitlen; i++) {
13220 struct json_object *ind_bit = json_object_new_object();
13221
13222 if (!ts.prefix_len_count[i])
13223 continue;
13224
13225 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13226 json_object_int_add(ind_bit, temp_buf,
13227 ts.prefix_len_count[i]);
13228 json_object_array_add(json_bitlen, ind_bit);
13229 }
13230 json_object_object_add(json, "prefixLength", json_bitlen);
13231 }
13232
9ab0cf58 13233end_table_stats:
6c9d22e2
PG
13234 if (json)
13235 json_object_array_add(json_array, json);
893cccd0 13236 return ret;
d62a17ae 13237}
13238
71f1613a
DA
13239static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13240 safi_t safi, struct json_object *json_array)
13241{
13242 if (!bgp) {
13243 bgp_table_stats_all(vty, afi, safi, json_array);
13244 return CMD_SUCCESS;
13245 }
13246
13247 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13248}
13249
d62a17ae 13250enum bgp_pcounts {
13251 PCOUNT_ADJ_IN = 0,
13252 PCOUNT_DAMPED,
13253 PCOUNT_REMOVED,
13254 PCOUNT_HISTORY,
13255 PCOUNT_STALE,
13256 PCOUNT_VALID,
13257 PCOUNT_ALL,
13258 PCOUNT_COUNTED,
7e3d9632 13259 PCOUNT_BPATH_SELECTED,
d62a17ae 13260 PCOUNT_PFCNT, /* the figure we display to users */
13261 PCOUNT_MAX,
a636c635 13262};
718e3744 13263
2b64873d 13264static const char *const pcount_strs[] = {
9d303b37
DL
13265 [PCOUNT_ADJ_IN] = "Adj-in",
13266 [PCOUNT_DAMPED] = "Damped",
13267 [PCOUNT_REMOVED] = "Removed",
13268 [PCOUNT_HISTORY] = "History",
13269 [PCOUNT_STALE] = "Stale",
13270 [PCOUNT_VALID] = "Valid",
13271 [PCOUNT_ALL] = "All RIB",
13272 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13273 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13274 [PCOUNT_PFCNT] = "Useable",
13275 [PCOUNT_MAX] = NULL,
a636c635 13276};
718e3744 13277
d62a17ae 13278struct peer_pcounts {
13279 unsigned int count[PCOUNT_MAX];
13280 const struct peer *peer;
13281 const struct bgp_table *table;
54317cba 13282 safi_t safi;
a636c635 13283};
47fc97cc 13284
9bcb3eef 13285static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13286{
54317cba
JW
13287 const struct bgp_adj_in *ain;
13288 const struct bgp_path_info *pi;
d62a17ae 13289 const struct peer *peer = pc->peer;
13290
54317cba
JW
13291 for (ain = rn->adj_in; ain; ain = ain->next)
13292 if (ain->peer == peer)
13293 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13294
9bcb3eef 13295 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13296
54317cba
JW
13297 if (pi->peer != peer)
13298 continue;
d62a17ae 13299
54317cba 13300 pc->count[PCOUNT_ALL]++;
d62a17ae 13301
54317cba
JW
13302 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13303 pc->count[PCOUNT_DAMPED]++;
13304 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13305 pc->count[PCOUNT_HISTORY]++;
13306 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13307 pc->count[PCOUNT_REMOVED]++;
13308 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13309 pc->count[PCOUNT_STALE]++;
13310 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13311 pc->count[PCOUNT_VALID]++;
13312 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13313 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13314 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13315 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13316
13317 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13318 pc->count[PCOUNT_COUNTED]++;
13319 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13320 flog_err(
13321 EC_LIB_DEVELOPMENT,
13322 "Attempting to count but flags say it is unusable");
13323 } else {
40381db7 13324 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13325 flog_err(
13326 EC_LIB_DEVELOPMENT,
13327 "Not counted but flags say we should");
d62a17ae 13328 }
13329 }
54317cba
JW
13330}
13331
cc9f21da 13332static void bgp_peer_count_walker(struct thread *t)
54317cba 13333{
9bcb3eef 13334 struct bgp_dest *rn, *rm;
54317cba
JW
13335 const struct bgp_table *table;
13336 struct peer_pcounts *pc = THREAD_ARG(t);
13337
13338 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13339 || pc->safi == SAFI_EVPN) {
13340 /* Special handling for 2-level routing tables. */
13341 for (rn = bgp_table_top(pc->table); rn;
13342 rn = bgp_route_next(rn)) {
9bcb3eef 13343 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13344 if (table != NULL)
13345 for (rm = bgp_table_top(table); rm;
13346 rm = bgp_route_next(rm))
13347 bgp_peer_count_proc(rm, pc);
13348 }
13349 } else
13350 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13351 bgp_peer_count_proc(rn, pc);
718e3744 13352}
13353
d62a17ae 13354static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13355 safi_t safi, bool use_json)
856ca177 13356{
d62a17ae 13357 struct peer_pcounts pcounts = {.peer = peer};
13358 unsigned int i;
13359 json_object *json = NULL;
13360 json_object *json_loop = NULL;
856ca177 13361
d62a17ae 13362 if (use_json) {
13363 json = json_object_new_object();
13364 json_loop = json_object_new_object();
13365 }
718e3744 13366
d62a17ae 13367 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13368 || !peer->bgp->rib[afi][safi]) {
13369 if (use_json) {
13370 json_object_string_add(
13371 json, "warning",
13372 "No such neighbor or address family");
13373 vty_out(vty, "%s\n", json_object_to_json_string(json));
13374 json_object_free(json);
d5f20468 13375 json_object_free(json_loop);
d62a17ae 13376 } else
13377 vty_out(vty, "%% No such neighbor or address family\n");
13378
13379 return CMD_WARNING;
13380 }
2a71e9ce 13381
d62a17ae 13382 memset(&pcounts, 0, sizeof(pcounts));
13383 pcounts.peer = peer;
13384 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13385 pcounts.safi = safi;
d62a17ae 13386
13387 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13388 * stats for the thread-walk (i.e. ensure this can't be blamed on
13389 * on just vty_read()).
13390 */
d62a17ae 13391 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13392
13393 if (use_json) {
13394 json_object_string_add(json, "prefixCountsFor", peer->host);
13395 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13396 get_afi_safi_str(afi, safi, true));
d62a17ae 13397 json_object_int_add(json, "pfxCounter",
13398 peer->pcount[afi][safi]);
13399
13400 for (i = 0; i < PCOUNT_MAX; i++)
13401 json_object_int_add(json_loop, pcount_strs[i],
13402 pcounts.count[i]);
13403
13404 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13405
13406 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13407 json_object_string_add(json, "pfxctDriftFor",
13408 peer->host);
13409 json_object_string_add(
13410 json, "recommended",
13411 "Please report this bug, with the above command output");
13412 }
75eeda93 13413 vty_json(vty, json);
d62a17ae 13414 } else {
13415
13416 if (peer->hostname
892fedb6 13417 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13418 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13419 peer->hostname, peer->host,
5cb5f4d0 13420 get_afi_safi_str(afi, safi, false));
d62a17ae 13421 } else {
13422 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13423 get_afi_safi_str(afi, safi, false));
d62a17ae 13424 }
13425
6cde4b45 13426 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13427 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13428
13429 for (i = 0; i < PCOUNT_MAX; i++)
13430 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13431 pcounts.count[i]);
13432
13433 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13434 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13435 vty_out(vty,
13436 "Please report this bug, with the above command output\n");
13437 }
13438 }
13439
13440 return CMD_SUCCESS;
718e3744 13441}
13442
a636c635
DW
13443DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13444 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13445 "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 13446 SHOW_STR
13447 IP_STR
13448 BGP_STR
8386ac43 13449 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13450 BGP_AFI_HELP_STR
13451 BGP_SAFI_HELP_STR
0b16f239
DS
13452 "Detailed information on TCP and BGP neighbor connections\n"
13453 "Neighbor to display information about\n"
13454 "Neighbor to display information about\n"
91d37724 13455 "Neighbor on BGP configured interface\n"
a636c635 13456 "Display detailed prefix count information\n"
9973d184 13457 JSON_STR)
0b16f239 13458{
d62a17ae 13459 afi_t afi = AFI_IP6;
13460 safi_t safi = SAFI_UNICAST;
13461 struct peer *peer;
13462 int idx = 0;
13463 struct bgp *bgp = NULL;
9f049418
DS
13464 bool uj = use_json(argc, argv);
13465
13466 if (uj)
13467 argc--;
856ca177 13468
d62a17ae 13469 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13470 &bgp, uj);
d62a17ae 13471 if (!idx)
13472 return CMD_WARNING;
0b16f239 13473
d62a17ae 13474 argv_find(argv, argc, "neighbors", &idx);
13475 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13476 if (!peer)
13477 return CMD_WARNING;
bb46e94f 13478
29c8d9da 13479 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13480}
0b16f239 13481
d6902373
PG
13482#ifdef KEEP_OLD_VPN_COMMANDS
13483DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13484 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13485 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13486 SHOW_STR
13487 IP_STR
13488 BGP_STR
d6902373 13489 BGP_VPNVX_HELP_STR
91d37724 13490 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13491 "Detailed information on TCP and BGP neighbor connections\n"
13492 "Neighbor to display information about\n"
13493 "Neighbor to display information about\n"
91d37724 13494 "Neighbor on BGP configured interface\n"
a636c635 13495 "Display detailed prefix count information\n"
9973d184 13496 JSON_STR)
a636c635 13497{
d62a17ae 13498 int idx_peer = 6;
13499 struct peer *peer;
9f049418 13500 bool uj = use_json(argc, argv);
a636c635 13501
d62a17ae 13502 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13503 if (!peer)
13504 return CMD_WARNING;
13505
13506 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13507}
13508
d6902373
PG
13509DEFUN (show_ip_bgp_vpn_all_route_prefix,
13510 show_ip_bgp_vpn_all_route_prefix_cmd,
13511 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13512 SHOW_STR
13513 IP_STR
13514 BGP_STR
d6902373 13515 BGP_VPNVX_HELP_STR
91d37724
QY
13516 "Display information about all VPNv4 NLRIs\n"
13517 "Network in the BGP routing table to display\n"
3a2d747c 13518 "Network in the BGP routing table to display\n"
9973d184 13519 JSON_STR)
91d37724 13520{
d62a17ae 13521 int idx = 0;
13522 char *network = NULL;
13523 struct bgp *bgp = bgp_get_default();
13524 if (!bgp) {
13525 vty_out(vty, "Can't find default instance\n");
13526 return CMD_WARNING;
13527 }
87e34b58 13528
d62a17ae 13529 if (argv_find(argv, argc, "A.B.C.D", &idx))
13530 network = argv[idx]->arg;
13531 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13532 network = argv[idx]->arg;
13533 else {
13534 vty_out(vty, "Unable to figure out Network\n");
13535 return CMD_WARNING;
13536 }
87e34b58 13537
d62a17ae 13538 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13539 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13540 use_json(argc, argv));
91d37724 13541}
d6902373 13542#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13543
44c69747
LK
13544DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13545 show_bgp_l2vpn_evpn_route_prefix_cmd,
13546 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13547 SHOW_STR
4c63a661
PG
13548 BGP_STR
13549 L2VPN_HELP_STR
13550 EVPN_HELP_STR
44c69747
LK
13551 "Network in the BGP routing table to display\n"
13552 "Network in the BGP routing table to display\n"
4c63a661
PG
13553 "Network in the BGP routing table to display\n"
13554 "Network in the BGP routing table to display\n"
13555 JSON_STR)
13556{
d62a17ae 13557 int idx = 0;
13558 char *network = NULL;
44c69747 13559 int prefix_check = 0;
a636c635 13560
44c69747
LK
13561 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13562 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13563 network = argv[idx]->arg;
44c69747 13564 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13565 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13566 network = argv[idx]->arg;
44c69747
LK
13567 prefix_check = 1;
13568 } else {
d62a17ae 13569 vty_out(vty, "Unable to figure out Network\n");
13570 return CMD_WARNING;
13571 }
44c69747
LK
13572 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13573 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13574 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13575}
13576
114fc229 13577static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13578 struct bgp_table *table, int *header1,
13579 int *header2, json_object *json,
13580 json_object *json_scode,
13581 json_object *json_ocode, bool wide)
13582{
13583 uint64_t version = table ? table->version : 0;
13584
13585 if (*header1) {
13586 if (json) {
13587 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13588 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13589 "%pI4", &peer->bgp->router_id);
2f9bc755 13590 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13591 peer->bgp->default_local_pref);
13592 json_object_int_add(json, "localAS",
13593 peer->change_local_as
13594 ? peer->change_local_as
13595 : peer->local_as);
2f9bc755
DS
13596 json_object_object_add(json, "bgpStatusCodes",
13597 json_scode);
13598 json_object_object_add(json, "bgpOriginCodes",
13599 json_ocode);
13600 } else {
13601 vty_out(vty,
23d0a753
DA
13602 "BGP table version is %" PRIu64
13603 ", local router ID is %pI4, vrf id ",
114fc229
DA
13604 version, &peer->bgp->router_id);
13605 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13606 vty_out(vty, "%s", VRFID_NONE_STR);
13607 else
114fc229 13608 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13609 vty_out(vty, "\n");
13610 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13611 peer->bgp->default_local_pref);
13612 vty_out(vty, "local AS %u\n",
13613 peer->change_local_as ? peer->change_local_as
13614 : peer->local_as);
2f9bc755
DS
13615 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13616 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13617 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13618 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13619 }
13620 *header1 = 0;
13621 }
13622 if (*header2) {
13623 if (!json)
13624 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13625 : BGP_SHOW_HEADER));
13626 *header2 = 0;
13627 }
13628}
13629
d9478df0
TA
13630static void
13631show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13632 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13633 const char *rmap_name, json_object *json, json_object *json_ar,
13634 json_object *json_scode, json_object *json_ocode,
96c81f66 13635 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13636 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13637{
d62a17ae 13638 struct bgp_adj_in *ain;
13639 struct bgp_adj_out *adj;
9bcb3eef 13640 struct bgp_dest *dest;
d62a17ae 13641 struct bgp *bgp;
d62a17ae 13642 struct attr attr;
13643 int ret;
13644 struct update_subgroup *subgrp;
d62a17ae 13645 struct peer_af *paf;
f99def61 13646 bool route_filtered;
96f3485c
MK
13647 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13648 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13649 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13650 || (safi == SAFI_EVPN))
13651 ? true
13652 : false;
a636c635 13653
d62a17ae 13654 bgp = peer->bgp;
a636c635 13655
d62a17ae 13656 subgrp = peer_subgroup(peer, afi, safi);
13657
6392aaa6 13658 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13659 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13660 if (use_json) {
13661 json_object_int_add(json, "bgpTableVersion",
13662 table->version);
c949c771
DA
13663 json_object_string_addf(json, "bgpLocalRouterId",
13664 "%pI4", &bgp->router_id);
01eced22
AD
13665 json_object_int_add(json, "defaultLocPrf",
13666 bgp->default_local_pref);
114fc229
DA
13667 json_object_int_add(json, "localAS",
13668 peer->change_local_as
13669 ? peer->change_local_as
13670 : peer->local_as);
d62a17ae 13671 json_object_object_add(json, "bgpStatusCodes",
13672 json_scode);
13673 json_object_object_add(json, "bgpOriginCodes",
13674 json_ocode);
07d0c4ed
DA
13675 json_object_string_add(
13676 json, "bgpOriginatingDefaultNetwork",
13677 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13678 } else {
23d0a753
DA
13679 vty_out(vty,
13680 "BGP table version is %" PRIu64
13681 ", local router ID is %pI4, vrf id ",
13682 table->version, &bgp->router_id);
9df8b37c
PZ
13683 if (bgp->vrf_id == VRF_UNKNOWN)
13684 vty_out(vty, "%s", VRFID_NONE_STR);
13685 else
13686 vty_out(vty, "%u", bgp->vrf_id);
13687 vty_out(vty, "\n");
01eced22
AD
13688 vty_out(vty, "Default local pref %u, ",
13689 bgp->default_local_pref);
114fc229
DA
13690 vty_out(vty, "local AS %u\n",
13691 peer->change_local_as ? peer->change_local_as
13692 : peer->local_as);
d62a17ae 13693 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13694 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13695 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13696 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13697
07d0c4ed
DA
13698 vty_out(vty, "Originating default network %s\n\n",
13699 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13700 }
d9478df0 13701 *header1 = 0;
d62a17ae 13702 }
a636c635 13703
9bcb3eef 13704 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13705 if (type == bgp_show_adj_route_received
13706 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13707 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13708 if (ain->peer != peer)
ea47320b 13709 continue;
6392aaa6 13710
114fc229 13711 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13712 header2, json, json_scode,
13713 json_ocode, wide);
13714
13715 if ((safi == SAFI_MPLS_VPN)
13716 || (safi == SAFI_ENCAP)
13717 || (safi == SAFI_EVPN)) {
13718 if (use_json)
13719 json_object_string_add(
13720 json_ar, "rd", rd_str);
13721 else if (show_rd && rd_str) {
13722 vty_out(vty,
13723 "Route Distinguisher: %s\n",
13724 rd_str);
13725 show_rd = false;
13726 }
13727 }
6392aaa6 13728
6f4f49b2 13729 attr = *ain->attr;
f99def61
AD
13730 route_filtered = false;
13731
13732 /* Filter prefix using distribute list,
13733 * filter list or prefix list
13734 */
b54892e0 13735 const struct prefix *rn_p =
9bcb3eef 13736 bgp_dest_get_prefix(dest);
b54892e0
DS
13737 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13738 safi))
13739 == FILTER_DENY)
f99def61
AD
13740 route_filtered = true;
13741
13742 /* Filter prefix using route-map */
b54892e0
DS
13743 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13744 safi, rmap_name, NULL,
13745 0, NULL);
6392aaa6 13746
13c8e163
AD
13747 if (type == bgp_show_adj_route_filtered &&
13748 !route_filtered && ret != RMAP_DENY) {
d498917e 13749 bgp_attr_flush(&attr);
6392aaa6 13750 continue;
d62a17ae 13751 }
6392aaa6 13752
d9478df0
TA
13753 if (type == bgp_show_adj_route_received
13754 && (route_filtered || ret == RMAP_DENY))
13755 (*filtered_count)++;
6392aaa6 13756
7d3cae70 13757 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13758 use_json, json_ar, wide);
d498917e 13759 bgp_attr_flush(&attr);
d9478df0 13760 (*output_count)++;
d62a17ae 13761 }
6392aaa6 13762 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13763 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13764 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13765 if (paf->peer != peer || !adj->attr)
924c3f6a 13766 continue;
d62a17ae 13767
114fc229 13768 show_adj_route_header(vty, peer, table,
d9478df0
TA
13769 header1, header2,
13770 json, json_scode,
13771 json_ocode, wide);
d62a17ae 13772
b54892e0 13773 const struct prefix *rn_p =
9bcb3eef 13774 bgp_dest_get_prefix(dest);
b54892e0 13775
6f4f49b2 13776 attr = *adj->attr;
b755861b 13777 ret = bgp_output_modifier(
b54892e0 13778 peer, rn_p, &attr, afi, safi,
b755861b 13779 rmap_name);
f46d8e1e 13780
b755861b 13781 if (ret != RMAP_DENY) {
d9478df0
TA
13782 if ((safi == SAFI_MPLS_VPN)
13783 || (safi == SAFI_ENCAP)
13784 || (safi == SAFI_EVPN)) {
13785 if (use_json)
13786 json_object_string_add(
13787 json_ar,
13788 "rd",
13789 rd_str);
13790 else if (show_rd
13791 && rd_str) {
13792 vty_out(vty,
13793 "Route Distinguisher: %s\n",
13794 rd_str);
13795 show_rd = false;
13796 }
13797 }
b54892e0 13798 route_vty_out_tmp(
7d3cae70
DA
13799 vty, dest, rn_p, &attr,
13800 safi, use_json, json_ar,
ae248832 13801 wide);
d9478df0 13802 (*output_count)++;
b755861b 13803 } else {
d9478df0 13804 (*filtered_count)++;
a2addae8 13805 }
b755861b 13806
d498917e 13807 bgp_attr_flush(&attr);
924c3f6a 13808 }
f20ce998
DS
13809 } else if (type == bgp_show_adj_route_bestpath) {
13810 struct bgp_path_info *pi;
13811
114fc229
DA
13812 show_adj_route_header(vty, peer, table, header1,
13813 header2, json, json_scode,
13814 json_ocode, wide);
f20ce998
DS
13815
13816 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13817 pi = pi->next) {
13818 if (pi->peer != peer)
13819 continue;
13820
13821 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13822 continue;
13823
7d3cae70 13824 route_vty_out_tmp(vty, dest,
f20ce998
DS
13825 bgp_dest_get_prefix(dest),
13826 pi->attr, safi, use_json,
13827 json_ar, wide);
d9478df0 13828 (*output_count)++;
f20ce998 13829 }
d62a17ae 13830 }
13831 }
a636c635 13832}
2a71e9ce 13833
d62a17ae 13834static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13835 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13836 const char *rmap_name, uint16_t show_flags)
0b16f239 13837{
d9478df0
TA
13838 struct bgp *bgp;
13839 struct bgp_table *table;
d62a17ae 13840 json_object *json = NULL;
d9478df0
TA
13841 json_object *json_scode = NULL;
13842 json_object *json_ocode = NULL;
13843 json_object *json_ar = NULL;
96f3485c 13844 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13845
d9478df0
TA
13846 /* Init BGP headers here so they're only displayed once
13847 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13848 */
13849 int header1 = 1;
13850 int header2 = 1;
13851
13852 /*
13853 * Initialize variables for each RD
13854 * All prefixes under an RD is aggregated within "json_routes"
13855 */
13856 char rd_str[BUFSIZ] = {0};
13857 json_object *json_routes = NULL;
13858
13859
13860 /* For 2-tier tables, prefix counts need to be
13861 * maintained across multiple runs of show_adj_route()
13862 */
13863 unsigned long output_count_per_rd;
13864 unsigned long filtered_count_per_rd;
13865 unsigned long output_count = 0;
13866 unsigned long filtered_count = 0;
13867
13868 if (use_json) {
d62a17ae 13869 json = json_object_new_object();
d9478df0
TA
13870 json_ar = json_object_new_object();
13871 json_scode = json_object_new_object();
13872 json_ocode = json_object_new_object();
13873
13874 json_object_string_add(json_scode, "suppressed", "s");
13875 json_object_string_add(json_scode, "damped", "d");
13876 json_object_string_add(json_scode, "history", "h");
13877 json_object_string_add(json_scode, "valid", "*");
13878 json_object_string_add(json_scode, "best", ">");
13879 json_object_string_add(json_scode, "multipath", "=");
13880 json_object_string_add(json_scode, "internal", "i");
13881 json_object_string_add(json_scode, "ribFailure", "r");
13882 json_object_string_add(json_scode, "stale", "S");
13883 json_object_string_add(json_scode, "removed", "R");
13884
13885 json_object_string_add(json_ocode, "igp", "i");
13886 json_object_string_add(json_ocode, "egp", "e");
13887 json_object_string_add(json_ocode, "incomplete", "?");
13888 }
0b16f239 13889
d62a17ae 13890 if (!peer || !peer->afc[afi][safi]) {
13891 if (use_json) {
13892 json_object_string_add(
13893 json, "warning",
13894 "No such neighbor or address family");
13895 vty_out(vty, "%s\n", json_object_to_json_string(json));
13896 json_object_free(json);
690c3134
MW
13897 json_object_free(json_ar);
13898 json_object_free(json_scode);
13899 json_object_free(json_ocode);
d62a17ae 13900 } else
13901 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13902
d62a17ae 13903 return CMD_WARNING;
13904 }
13905
6392aaa6
PM
13906 if ((type == bgp_show_adj_route_received
13907 || type == bgp_show_adj_route_filtered)
d62a17ae 13908 && !CHECK_FLAG(peer->af_flags[afi][safi],
13909 PEER_FLAG_SOFT_RECONFIG)) {
13910 if (use_json) {
13911 json_object_string_add(
13912 json, "warning",
13913 "Inbound soft reconfiguration not enabled");
13914 vty_out(vty, "%s\n", json_object_to_json_string(json));
13915 json_object_free(json);
690c3134
MW
13916 json_object_free(json_ar);
13917 json_object_free(json_scode);
13918 json_object_free(json_ocode);
d62a17ae 13919 } else
13920 vty_out(vty,
13921 "%% Inbound soft reconfiguration not enabled\n");
13922
13923 return CMD_WARNING;
13924 }
0b16f239 13925
d9478df0
TA
13926 bgp = peer->bgp;
13927
13928 /* labeled-unicast routes live in the unicast table */
13929 if (safi == SAFI_LABELED_UNICAST)
13930 table = bgp->rib[afi][SAFI_UNICAST];
13931 else
13932 table = bgp->rib[afi][safi];
13933
13934 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13935 || (safi == SAFI_EVPN)) {
13936
13937 struct bgp_dest *dest;
13938
13939 for (dest = bgp_table_top(table); dest;
13940 dest = bgp_route_next(dest)) {
13941 table = bgp_dest_get_bgp_table_info(dest);
13942 if (!table)
13943 continue;
13944
13945 output_count_per_rd = 0;
13946 filtered_count_per_rd = 0;
13947
13948 if (use_json)
13949 json_routes = json_object_new_object();
13950
13951 const struct prefix_rd *prd;
13952 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13953 dest);
13954
13955 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13956
13957 show_adj_route(vty, peer, table, afi, safi, type,
13958 rmap_name, json, json_routes, json_scode,
13959 json_ocode, show_flags, &header1,
13960 &header2, rd_str, &output_count_per_rd,
13961 &filtered_count_per_rd);
13962
13963 /* Don't include an empty RD in the output! */
13964 if (json_routes && (output_count_per_rd > 0))
13965 json_object_object_add(json_ar, rd_str,
13966 json_routes);
13967
13968 output_count += output_count_per_rd;
13969 filtered_count += filtered_count_per_rd;
13970 }
13971 } else
13972 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13973 json, json_ar, json_scode, json_ocode,
13974 show_flags, &header1, &header2, rd_str,
13975 &output_count, &filtered_count);
13976
13977 if (use_json) {
c1984955
TA
13978 if (type == bgp_show_adj_route_advertised)
13979 json_object_object_add(json, "advertisedRoutes",
13980 json_ar);
13981 else
13982 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
13983 json_object_int_add(json, "totalPrefixCounter", output_count);
13984 json_object_int_add(json, "filteredPrefixCounter",
13985 filtered_count);
13986
690c3134
MW
13987 /*
13988 * These fields only give up ownership to `json` when `header1`
13989 * is used (set to zero). See code in `show_adj_route` and
13990 * `show_adj_route_header`.
13991 */
13992 if (header1 == 1) {
d9478df0
TA
13993 json_object_free(json_scode);
13994 json_object_free(json_ocode);
13995 }
13996
75eeda93 13997 vty_json(vty, json);
d9478df0
TA
13998 } else if (output_count > 0) {
13999 if (filtered_count > 0)
14000 vty_out(vty,
14001 "\nTotal number of prefixes %ld (%ld filtered)\n",
14002 output_count, filtered_count);
14003 else
14004 vty_out(vty, "\nTotal number of prefixes %ld\n",
14005 output_count);
14006 }
0b16f239 14007
d62a17ae 14008 return CMD_SUCCESS;
a636c635 14009}
50ef26d4 14010
f20ce998
DS
14011DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14012 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14013 "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]",
14014 SHOW_STR
14015 IP_STR
14016 BGP_STR
14017 BGP_INSTANCE_HELP_STR
14018 BGP_AFI_HELP_STR
14019 BGP_SAFI_WITH_LABEL_HELP_STR
14020 "Detailed information on TCP and BGP neighbor connections\n"
14021 "Neighbor to display information about\n"
14022 "Neighbor to display information about\n"
14023 "Neighbor on BGP configured interface\n"
14024 "Display the routes selected by best path\n"
14025 JSON_STR
14026 "Increase table width for longer prefixes\n")
14027{
14028 afi_t afi = AFI_IP6;
14029 safi_t safi = SAFI_UNICAST;
14030 char *rmap_name = NULL;
14031 char *peerstr = NULL;
14032 struct bgp *bgp = NULL;
14033 struct peer *peer;
14034 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14035 int idx = 0;
96c81f66 14036 uint16_t show_flags = 0;
96f3485c
MK
14037
14038 if (uj)
14039 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14040
14041 if (wide)
14042 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14043
14044 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14045 &bgp, uj);
14046
14047 if (!idx)
14048 return CMD_WARNING;
14049
14050 argv_find(argv, argc, "neighbors", &idx);
14051 peerstr = argv[++idx]->arg;
14052
14053 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14054 if (!peer)
14055 return CMD_WARNING;
14056
96f3485c
MK
14057 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14058 show_flags);
f20ce998
DS
14059}
14060
ae248832 14061DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14062 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14063 "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 14064 SHOW_STR
14065 IP_STR
14066 BGP_STR
a636c635 14067 BGP_INSTANCE_HELP_STR
7395a2c9 14068 BGP_AFI_HELP_STR
4dd6177e 14069 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14070 "Display the entries for all address families\n"
718e3744 14071 "Detailed information on TCP and BGP neighbor connections\n"
14072 "Neighbor to display information about\n"
14073 "Neighbor to display information about\n"
91d37724 14074 "Neighbor on BGP configured interface\n"
a636c635 14075 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14076 "Display the received routes from neighbor\n"
14077 "Display the filtered routes received from neighbor\n"
a636c635
DW
14078 "Route-map to modify the attributes\n"
14079 "Name of the route map\n"
ae248832
MK
14080 JSON_STR
14081 "Increase table width for longer prefixes\n")
718e3744 14082{
d62a17ae 14083 afi_t afi = AFI_IP6;
14084 safi_t safi = SAFI_UNICAST;
d62a17ae 14085 char *peerstr = NULL;
d62a17ae 14086 struct bgp *bgp = NULL;
14087 struct peer *peer;
6392aaa6 14088 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14089 int idx = 0;
96f3485c 14090 bool first = true;
96c81f66 14091 uint16_t show_flags = 0;
75ce3b14
DA
14092 struct listnode *node;
14093 struct bgp *abgp;
6392aaa6 14094
96f3485c 14095 if (uj) {
d62a17ae 14096 argc--;
96f3485c
MK
14097 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14098 }
14099
14100 if (all) {
14101 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14102 if (argv_find(argv, argc, "ipv4", &idx))
14103 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14104
14105 if (argv_find(argv, argc, "ipv6", &idx))
14106 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14107 }
14108
14109 if (wide)
14110 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14111
9f049418
DS
14112 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14113 &bgp, uj);
14114 if (!idx)
14115 return CMD_WARNING;
14116
d62a17ae 14117 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14118 argv_find(argv, argc, "neighbors", &idx);
14119 peerstr = argv[++idx]->arg;
8c3deaae 14120
d62a17ae 14121 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14122 if (!peer)
14123 return CMD_WARNING;
856ca177 14124
d62a17ae 14125 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14126 type = bgp_show_adj_route_advertised;
14127 else if (argv_find(argv, argc, "received-routes", &idx))
14128 type = bgp_show_adj_route_received;
14129 else if (argv_find(argv, argc, "filtered-routes", &idx))
14130 type = bgp_show_adj_route_filtered;
14131
96f3485c 14132 if (!all)
70dd370f 14133 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14134 show_flags);
14135 if (uj)
14136 vty_out(vty, "{\n");
14137
14138 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14139 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14140 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14141 : AFI_IP6;
75ce3b14
DA
14142 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14143 FOREACH_SAFI (safi) {
14144 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14145 continue;
96f3485c 14146
75ce3b14
DA
14147 if (uj) {
14148 if (first)
14149 first = false;
14150 else
14151 vty_out(vty, ",\n");
14152 vty_out(vty, "\"%s\":",
14153 get_afi_safi_str(afi, safi,
14154 true));
14155 } else
14156 vty_out(vty,
14157 "\nFor address family: %s\n",
14158 get_afi_safi_str(afi, safi,
14159 false));
96f3485c 14160
75ce3b14 14161 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14162 route_map, show_flags);
75ce3b14 14163 }
96f3485c
MK
14164 }
14165 } else {
75ce3b14
DA
14166 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14167 FOREACH_AFI_SAFI (afi, safi) {
14168 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14169 continue;
96f3485c 14170
75ce3b14
DA
14171 if (uj) {
14172 if (first)
14173 first = false;
14174 else
14175 vty_out(vty, ",\n");
14176 vty_out(vty, "\"%s\":",
14177 get_afi_safi_str(afi, safi,
14178 true));
14179 } else
14180 vty_out(vty,
14181 "\nFor address family: %s\n",
14182 get_afi_safi_str(afi, safi,
14183 false));
96f3485c 14184
75ce3b14 14185 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14186 route_map, show_flags);
75ce3b14 14187 }
96f3485c
MK
14188 }
14189 }
14190 if (uj)
14191 vty_out(vty, "}\n");
14192
14193 return CMD_SUCCESS;
95cbbd2a
ML
14194}
14195
718e3744 14196DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14197 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14198 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14199 SHOW_STR
14200 IP_STR
14201 BGP_STR
d3120452 14202 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14203 BGP_AF_STR
14204 BGP_AF_STR
14205 BGP_AF_MODIFIER_STR
718e3744 14206 "Detailed information on TCP and BGP neighbor connections\n"
14207 "Neighbor to display information about\n"
14208 "Neighbor to display information about\n"
91d37724 14209 "Neighbor on BGP configured interface\n"
718e3744 14210 "Display information received from a BGP neighbor\n"
856ca177 14211 "Display the prefixlist filter\n"
9973d184 14212 JSON_STR)
718e3744 14213{
d62a17ae 14214 afi_t afi = AFI_IP6;
14215 safi_t safi = SAFI_UNICAST;
14216 char *peerstr = NULL;
d62a17ae 14217 char name[BUFSIZ];
d62a17ae 14218 struct peer *peer;
d3120452 14219 int count;
d62a17ae 14220 int idx = 0;
d3120452
IR
14221 struct bgp *bgp = NULL;
14222 bool uj = use_json(argc, argv);
14223
14224 if (uj)
14225 argc--;
14226
14227 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14228 &bgp, uj);
14229 if (!idx)
14230 return CMD_WARNING;
d62a17ae 14231
d62a17ae 14232 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14233 argv_find(argv, argc, "neighbors", &idx);
14234 peerstr = argv[++idx]->arg;
14235
d3120452
IR
14236 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14237 if (!peer)
14238 return CMD_WARNING;
718e3744 14239
4ced1a2c 14240 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14241 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14242 if (count) {
14243 if (!uj)
14244 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14245 get_afi_safi_str(afi, safi, false));
d62a17ae 14246 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14247 } else {
14248 if (uj)
14249 vty_out(vty, "{}\n");
14250 else
14251 vty_out(vty, "No functional output\n");
14252 }
718e3744 14253
d62a17ae 14254 return CMD_SUCCESS;
14255}
14256
14257static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14258 afi_t afi, safi_t safi,
9f049418 14259 enum bgp_show_type type, bool use_json)
d62a17ae 14260{
96c81f66 14261 uint16_t show_flags = 0;
96f3485c
MK
14262
14263 if (use_json)
14264 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14265
d62a17ae 14266 if (!peer || !peer->afc[afi][safi]) {
14267 if (use_json) {
14268 json_object *json_no = NULL;
14269 json_no = json_object_new_object();
14270 json_object_string_add(
14271 json_no, "warning",
14272 "No such neighbor or address family");
14273 vty_out(vty, "%s\n",
14274 json_object_to_json_string(json_no));
14275 json_object_free(json_no);
14276 } else
14277 vty_out(vty, "%% No such neighbor or address family\n");
14278 return CMD_WARNING;
14279 }
47fc97cc 14280
7daf25a3
TA
14281 /* labeled-unicast routes live in the unicast table */
14282 if (safi == SAFI_LABELED_UNICAST)
14283 safi = SAFI_UNICAST;
14284
1e2ce4f1
DS
14285 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14286 RPKI_NOT_BEING_USED);
718e3744 14287}
14288
dba3c1d3
PG
14289DEFUN (show_ip_bgp_flowspec_routes_detailed,
14290 show_ip_bgp_flowspec_routes_detailed_cmd,
14291 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14292 SHOW_STR
14293 IP_STR
14294 BGP_STR
14295 BGP_INSTANCE_HELP_STR
14296 BGP_AFI_HELP_STR
14297 "SAFI Flowspec\n"
14298 "Detailed information on flowspec entries\n"
14299 JSON_STR)
14300{
458c1475 14301 afi_t afi = AFI_IP6;
dba3c1d3
PG
14302 safi_t safi = SAFI_UNICAST;
14303 struct bgp *bgp = NULL;
14304 int idx = 0;
9f049418 14305 bool uj = use_json(argc, argv);
5be6fa9b 14306 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14307
96f3485c 14308 if (uj) {
9f049418 14309 argc--;
96f3485c
MK
14310 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14311 }
dba3c1d3
PG
14312
14313 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14314 &bgp, uj);
dba3c1d3
PG
14315 if (!idx)
14316 return CMD_WARNING;
14317
96f3485c 14318 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14319 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14320}
14321
718e3744 14322DEFUN (show_ip_bgp_neighbor_routes,
14323 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14324 "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 14325 SHOW_STR
14326 IP_STR
14327 BGP_STR
8386ac43 14328 BGP_INSTANCE_HELP_STR
4f280b15 14329 BGP_AFI_HELP_STR
4dd6177e 14330 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14331 "Detailed information on TCP and BGP neighbor connections\n"
14332 "Neighbor to display information about\n"
14333 "Neighbor to display information about\n"
91d37724 14334 "Neighbor on BGP configured interface\n"
2525cf39 14335 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14336 "Display the dampened routes received from neighbor\n"
14337 "Display routes learned from neighbor\n"
9973d184 14338 JSON_STR)
718e3744 14339{
d62a17ae 14340 char *peerstr = NULL;
14341 struct bgp *bgp = NULL;
14342 afi_t afi = AFI_IP6;
14343 safi_t safi = SAFI_UNICAST;
14344 struct peer *peer;
14345 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14346 int idx = 0;
9f049418
DS
14347 bool uj = use_json(argc, argv);
14348
14349 if (uj)
14350 argc--;
bb46e94f 14351
d62a17ae 14352 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14353 &bgp, uj);
d62a17ae 14354 if (!idx)
14355 return CMD_WARNING;
c493f2d8 14356
d62a17ae 14357 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14358 argv_find(argv, argc, "neighbors", &idx);
14359 peerstr = argv[++idx]->arg;
8c3deaae 14360
d62a17ae 14361 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14362 if (!peer)
d62a17ae 14363 return CMD_WARNING;
bb46e94f 14364
d62a17ae 14365 if (argv_find(argv, argc, "flap-statistics", &idx))
14366 sh_type = bgp_show_type_flap_neighbor;
14367 else if (argv_find(argv, argc, "dampened-routes", &idx))
14368 sh_type = bgp_show_type_damp_neighbor;
14369 else if (argv_find(argv, argc, "routes", &idx))
14370 sh_type = bgp_show_type_neighbor;
2525cf39 14371
d62a17ae 14372 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14373}
6b0655a2 14374
734b349e 14375struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14376
d62a17ae 14377struct bgp_distance {
14378 /* Distance value for the IP source prefix. */
d7c0a89a 14379 uint8_t distance;
718e3744 14380
d62a17ae 14381 /* Name of the access-list to be matched. */
14382 char *access_list;
718e3744 14383};
14384
4f280b15
LB
14385DEFUN (show_bgp_afi_vpn_rd_route,
14386 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14387 "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
14388 SHOW_STR
14389 BGP_STR
14390 BGP_AFI_HELP_STR
00e6edb9 14391 BGP_AF_MODIFIER_STR
4f280b15
LB
14392 "Display information for a route distinguisher\n"
14393 "Route Distinguisher\n"
a111dd97 14394 "All Route Distinguishers\n"
7395a2c9
DS
14395 "Network in the BGP routing table to display\n"
14396 "Network in the BGP routing table to display\n"
14397 JSON_STR)
4f280b15 14398{
d62a17ae 14399 int ret;
14400 struct prefix_rd prd;
14401 afi_t afi = AFI_MAX;
14402 int idx = 0;
4f280b15 14403
ff6566f3
DS
14404 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14405 vty_out(vty, "%% Malformed Address Family\n");
14406 return CMD_WARNING;
14407 }
14408
a111dd97
TA
14409 if (!strcmp(argv[5]->arg, "all"))
14410 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14411 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14412 RPKI_NOT_BEING_USED,
14413 use_json(argc, argv));
14414
d62a17ae 14415 ret = str2prefix_rd(argv[5]->arg, &prd);
14416 if (!ret) {
14417 vty_out(vty, "%% Malformed Route Distinguisher\n");
14418 return CMD_WARNING;
14419 }
ff6566f3 14420
d62a17ae 14421 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14422 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14423 use_json(argc, argv));
4f280b15
LB
14424}
14425
d62a17ae 14426static struct bgp_distance *bgp_distance_new(void)
718e3744 14427{
d62a17ae 14428 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14429}
14430
d62a17ae 14431static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14432{
d62a17ae 14433 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14434}
14435
585f1adc
IR
14436static int bgp_distance_set(struct vty *vty, const char *distance_str,
14437 const char *ip_str, const char *access_list_str)
718e3744 14438{
d62a17ae 14439 int ret;
585f1adc
IR
14440 afi_t afi;
14441 safi_t safi;
d62a17ae 14442 struct prefix p;
585f1adc 14443 uint8_t distance;
9bcb3eef 14444 struct bgp_dest *dest;
d62a17ae 14445 struct bgp_distance *bdistance;
718e3744 14446
585f1adc
IR
14447 afi = bgp_node_afi(vty);
14448 safi = bgp_node_safi(vty);
14449
d62a17ae 14450 ret = str2prefix(ip_str, &p);
14451 if (ret == 0) {
585f1adc 14452 vty_out(vty, "Malformed prefix\n");
d62a17ae 14453 return CMD_WARNING_CONFIG_FAILED;
14454 }
718e3744 14455
585f1adc
IR
14456 distance = atoi(distance_str);
14457
d62a17ae 14458 /* Get BGP distance node. */
9bcb3eef
DS
14459 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14460 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14461 if (bdistance)
9bcb3eef 14462 bgp_dest_unlock_node(dest);
ca2e160d 14463 else {
d62a17ae 14464 bdistance = bgp_distance_new();
9bcb3eef 14465 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14466 }
718e3744 14467
d62a17ae 14468 /* Set distance value. */
14469 bdistance->distance = distance;
718e3744 14470
d62a17ae 14471 /* Reset access-list configuration. */
e1b36e13 14472 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14473 if (access_list_str)
14474 bdistance->access_list =
14475 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14476
d62a17ae 14477 return CMD_SUCCESS;
718e3744 14478}
14479
585f1adc
IR
14480static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14481 const char *ip_str, const char *access_list_str)
718e3744 14482{
d62a17ae 14483 int ret;
585f1adc
IR
14484 afi_t afi;
14485 safi_t safi;
d62a17ae 14486 struct prefix p;
585f1adc 14487 int distance;
9bcb3eef 14488 struct bgp_dest *dest;
d62a17ae 14489 struct bgp_distance *bdistance;
718e3744 14490
585f1adc
IR
14491 afi = bgp_node_afi(vty);
14492 safi = bgp_node_safi(vty);
14493
d62a17ae 14494 ret = str2prefix(ip_str, &p);
14495 if (ret == 0) {
585f1adc 14496 vty_out(vty, "Malformed prefix\n");
d62a17ae 14497 return CMD_WARNING_CONFIG_FAILED;
14498 }
718e3744 14499
9bcb3eef
DS
14500 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14501 if (!dest) {
585f1adc 14502 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14503 return CMD_WARNING_CONFIG_FAILED;
14504 }
718e3744 14505
9bcb3eef 14506 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14507 distance = atoi(distance_str);
1f9a9fff 14508
d62a17ae 14509 if (bdistance->distance != distance) {
585f1adc 14510 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14511 bgp_dest_unlock_node(dest);
d62a17ae 14512 return CMD_WARNING_CONFIG_FAILED;
14513 }
718e3744 14514
0a22ddfb 14515 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14516 bgp_distance_free(bdistance);
718e3744 14517
9bcb3eef
DS
14518 bgp_dest_set_bgp_path_info(dest, NULL);
14519 bgp_dest_unlock_node(dest);
14520 bgp_dest_unlock_node(dest);
718e3744 14521
d62a17ae 14522 return CMD_SUCCESS;
718e3744 14523}
14524
718e3744 14525/* Apply BGP information to distance method. */
b8685f9b 14526uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14527 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14528{
9bcb3eef 14529 struct bgp_dest *dest;
801bb996 14530 struct prefix q = {0};
d62a17ae 14531 struct peer *peer;
14532 struct bgp_distance *bdistance;
14533 struct access_list *alist;
14534 struct bgp_static *bgp_static;
14535
14536 if (!bgp)
14537 return 0;
14538
40381db7 14539 peer = pinfo->peer;
d62a17ae 14540
7b7d48e5
DS
14541 if (pinfo->attr->distance)
14542 return pinfo->attr->distance;
14543
801bb996
CS
14544 /* Check source address.
14545 * Note: for aggregate route, peer can have unspec af type.
14546 */
14547 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14548 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14549 return 0;
14550
9bcb3eef
DS
14551 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14552 if (dest) {
14553 bdistance = bgp_dest_get_bgp_distance_info(dest);
14554 bgp_dest_unlock_node(dest);
d62a17ae 14555
14556 if (bdistance->access_list) {
14557 alist = access_list_lookup(afi, bdistance->access_list);
14558 if (alist
14559 && access_list_apply(alist, p) == FILTER_PERMIT)
14560 return bdistance->distance;
14561 } else
14562 return bdistance->distance;
718e3744 14563 }
718e3744 14564
d62a17ae 14565 /* Backdoor check. */
9bcb3eef
DS
14566 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14567 if (dest) {
14568 bgp_static = bgp_dest_get_bgp_static_info(dest);
14569 bgp_dest_unlock_node(dest);
718e3744 14570
d62a17ae 14571 if (bgp_static->backdoor) {
14572 if (bgp->distance_local[afi][safi])
14573 return bgp->distance_local[afi][safi];
14574 else
14575 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14576 }
718e3744 14577 }
718e3744 14578
d62a17ae 14579 if (peer->sort == BGP_PEER_EBGP) {
14580 if (bgp->distance_ebgp[afi][safi])
14581 return bgp->distance_ebgp[afi][safi];
14582 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14583 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14584 if (bgp->distance_ibgp[afi][safi])
14585 return bgp->distance_ibgp[afi][safi];
14586 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14587 } else {
14588 if (bgp->distance_local[afi][safi])
14589 return bgp->distance_local[afi][safi];
14590 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14591 }
718e3744 14592}
14593
a612fb77
DA
14594/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14595 * we should tell ZEBRA update the routes for a specific
14596 * AFI/SAFI to reflect changes in RIB.
14597 */
585f1adc
IR
14598static void bgp_announce_routes_distance_update(struct bgp *bgp,
14599 afi_t update_afi,
14600 safi_t update_safi)
a612fb77
DA
14601{
14602 afi_t afi;
14603 safi_t safi;
14604
14605 FOREACH_AFI_SAFI (afi, safi) {
14606 if (!bgp_fibupd_safi(safi))
14607 continue;
14608
8b54bc30
DA
14609 if (afi != update_afi && safi != update_safi)
14610 continue;
14611
14612 if (BGP_DEBUG(zebra, ZEBRA))
14613 zlog_debug(
14614 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14615 __func__, afi, safi);
14616 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14617 }
14618}
14619
585f1adc
IR
14620DEFUN (bgp_distance,
14621 bgp_distance_cmd,
14622 "distance bgp (1-255) (1-255) (1-255)",
14623 "Define an administrative distance\n"
14624 "BGP distance\n"
14625 "Distance for routes external to the AS\n"
14626 "Distance for routes internal to the AS\n"
14627 "Distance for local routes\n")
718e3744 14628{
585f1adc 14629 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14630 int idx_number = 2;
14631 int idx_number_2 = 3;
14632 int idx_number_3 = 4;
585f1adc
IR
14633 int distance_ebgp = atoi(argv[idx_number]->arg);
14634 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14635 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14636 afi_t afi;
14637 safi_t safi;
718e3744 14638
d62a17ae 14639 afi = bgp_node_afi(vty);
14640 safi = bgp_node_safi(vty);
718e3744 14641
585f1adc
IR
14642 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14643 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14644 || bgp->distance_local[afi][safi] != distance_local) {
14645 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14646 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14647 bgp->distance_local[afi][safi] = distance_local;
14648 bgp_announce_routes_distance_update(bgp, afi, safi);
14649 }
14650 return CMD_SUCCESS;
14651}
37a87b8f 14652
585f1adc
IR
14653DEFUN (no_bgp_distance,
14654 no_bgp_distance_cmd,
14655 "no distance bgp [(1-255) (1-255) (1-255)]",
14656 NO_STR
14657 "Define an administrative distance\n"
14658 "BGP distance\n"
14659 "Distance for routes external to the AS\n"
14660 "Distance for routes internal to the AS\n"
14661 "Distance for local routes\n")
718e3744 14662{
585f1adc 14663 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14664 afi_t afi;
14665 safi_t safi;
37a87b8f
CS
14666
14667 afi = bgp_node_afi(vty);
14668 safi = bgp_node_safi(vty);
14669
585f1adc
IR
14670 if (bgp->distance_ebgp[afi][safi] != 0
14671 || bgp->distance_ibgp[afi][safi] != 0
14672 || bgp->distance_local[afi][safi] != 0) {
14673 bgp->distance_ebgp[afi][safi] = 0;
14674 bgp->distance_ibgp[afi][safi] = 0;
14675 bgp->distance_local[afi][safi] = 0;
14676 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14677 }
585f1adc
IR
14678 return CMD_SUCCESS;
14679}
37a87b8f 14680
37a87b8f 14681
585f1adc
IR
14682DEFUN (bgp_distance_source,
14683 bgp_distance_source_cmd,
14684 "distance (1-255) A.B.C.D/M",
14685 "Define an administrative distance\n"
14686 "Administrative distance\n"
14687 "IP source prefix\n")
14688{
14689 int idx_number = 1;
14690 int idx_ipv4_prefixlen = 2;
14691 bgp_distance_set(vty, argv[idx_number]->arg,
14692 argv[idx_ipv4_prefixlen]->arg, NULL);
14693 return CMD_SUCCESS;
734b349e
MZ
14694}
14695
585f1adc
IR
14696DEFUN (no_bgp_distance_source,
14697 no_bgp_distance_source_cmd,
14698 "no distance (1-255) A.B.C.D/M",
14699 NO_STR
14700 "Define an administrative distance\n"
14701 "Administrative distance\n"
14702 "IP source prefix\n")
37a87b8f 14703{
585f1adc
IR
14704 int idx_number = 2;
14705 int idx_ipv4_prefixlen = 3;
14706 bgp_distance_unset(vty, argv[idx_number]->arg,
14707 argv[idx_ipv4_prefixlen]->arg, NULL);
14708 return CMD_SUCCESS;
37a87b8f
CS
14709}
14710
585f1adc
IR
14711DEFUN (bgp_distance_source_access_list,
14712 bgp_distance_source_access_list_cmd,
14713 "distance (1-255) A.B.C.D/M WORD",
14714 "Define an administrative distance\n"
14715 "Administrative distance\n"
14716 "IP source prefix\n"
14717 "Access list name\n")
37a87b8f 14718{
585f1adc
IR
14719 int idx_number = 1;
14720 int idx_ipv4_prefixlen = 2;
14721 int idx_word = 3;
14722 bgp_distance_set(vty, argv[idx_number]->arg,
14723 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14724 return CMD_SUCCESS;
14725}
718e3744 14726
585f1adc
IR
14727DEFUN (no_bgp_distance_source_access_list,
14728 no_bgp_distance_source_access_list_cmd,
14729 "no distance (1-255) A.B.C.D/M WORD",
14730 NO_STR
14731 "Define an administrative distance\n"
14732 "Administrative distance\n"
14733 "IP source prefix\n"
14734 "Access list name\n")
14735{
14736 int idx_number = 2;
14737 int idx_ipv4_prefixlen = 3;
14738 int idx_word = 4;
14739 bgp_distance_unset(vty, argv[idx_number]->arg,
14740 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14741 return CMD_SUCCESS;
14742}
37a87b8f 14743
585f1adc
IR
14744DEFUN (ipv6_bgp_distance_source,
14745 ipv6_bgp_distance_source_cmd,
14746 "distance (1-255) X:X::X:X/M",
14747 "Define an administrative distance\n"
14748 "Administrative distance\n"
14749 "IP source prefix\n")
14750{
14751 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14752 return CMD_SUCCESS;
14753}
7ebe9748 14754
585f1adc
IR
14755DEFUN (no_ipv6_bgp_distance_source,
14756 no_ipv6_bgp_distance_source_cmd,
14757 "no distance (1-255) X:X::X:X/M",
14758 NO_STR
14759 "Define an administrative distance\n"
14760 "Administrative distance\n"
14761 "IP source prefix\n")
14762{
14763 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14764 return CMD_SUCCESS;
14765}
37a87b8f 14766
585f1adc
IR
14767DEFUN (ipv6_bgp_distance_source_access_list,
14768 ipv6_bgp_distance_source_access_list_cmd,
14769 "distance (1-255) X:X::X:X/M WORD",
14770 "Define an administrative distance\n"
14771 "Administrative distance\n"
14772 "IP source prefix\n"
14773 "Access list name\n")
14774{
14775 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14776 return CMD_SUCCESS;
718e3744 14777}
14778
585f1adc
IR
14779DEFUN (no_ipv6_bgp_distance_source_access_list,
14780 no_ipv6_bgp_distance_source_access_list_cmd,
14781 "no distance (1-255) X:X::X:X/M WORD",
14782 NO_STR
14783 "Define an administrative distance\n"
14784 "Administrative distance\n"
14785 "IP source prefix\n"
14786 "Access list name\n")
718e3744 14787{
585f1adc
IR
14788 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14789 return CMD_SUCCESS;
14790}
37a87b8f 14791
585f1adc
IR
14792DEFUN (bgp_damp_set,
14793 bgp_damp_set_cmd,
a30fec23 14794 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14795 "BGP Specific commands\n"
14796 "Enable route-flap dampening\n"
14797 "Half-life time for the penalty\n"
14798 "Value to start reusing a route\n"
14799 "Value to start suppressing a route\n"
14800 "Maximum duration to suppress a stable route\n")
14801{
14802 VTY_DECLVAR_CONTEXT(bgp, bgp);
14803 int idx_half_life = 2;
14804 int idx_reuse = 3;
14805 int idx_suppress = 4;
14806 int idx_max_suppress = 5;
37a87b8f
CS
14807 int half = DEFAULT_HALF_LIFE * 60;
14808 int reuse = DEFAULT_REUSE;
14809 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14810 int max = 4 * half;
14811
14812 if (argc == 6) {
14813 half = atoi(argv[idx_half_life]->arg) * 60;
14814 reuse = atoi(argv[idx_reuse]->arg);
14815 suppress = atoi(argv[idx_suppress]->arg);
14816 max = atoi(argv[idx_max_suppress]->arg) * 60;
14817 } else if (argc == 3) {
14818 half = atoi(argv[idx_half_life]->arg) * 60;
14819 max = 4 * half;
14820 }
14821
14822 /*
14823 * These can't be 0 but our SA doesn't understand the
14824 * way our cli is constructed
14825 */
14826 assert(reuse);
14827 assert(half);
14828 if (suppress < reuse) {
14829 vty_out(vty,
14830 "Suppress value cannot be less than reuse value \n");
14831 return 0;
14832 }
14833
14834 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14835 reuse, suppress, max);
14836}
14837
14838DEFUN (bgp_damp_unset,
14839 bgp_damp_unset_cmd,
a30fec23 14840 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14841 NO_STR
14842 "BGP Specific commands\n"
14843 "Enable route-flap dampening\n"
14844 "Half-life time for the penalty\n"
14845 "Value to start reusing a route\n"
14846 "Value to start suppressing a route\n"
14847 "Maximum duration to suppress a stable route\n")
14848{
14849 VTY_DECLVAR_CONTEXT(bgp, bgp);
14850 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14851}
14852
718e3744 14853/* Display specified route of BGP table. */
d62a17ae 14854static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14855 const char *ip_str, afi_t afi, safi_t safi,
14856 struct prefix_rd *prd, int prefix_check)
14857{
14858 int ret;
14859 struct prefix match;
9bcb3eef
DS
14860 struct bgp_dest *dest;
14861 struct bgp_dest *rm;
40381db7
DS
14862 struct bgp_path_info *pi;
14863 struct bgp_path_info *pi_temp;
d62a17ae 14864 struct bgp *bgp;
14865 struct bgp_table *table;
14866
14867 /* BGP structure lookup. */
14868 if (view_name) {
14869 bgp = bgp_lookup_by_name(view_name);
14870 if (bgp == NULL) {
14871 vty_out(vty, "%% Can't find BGP instance %s\n",
14872 view_name);
14873 return CMD_WARNING;
14874 }
14875 } else {
14876 bgp = bgp_get_default();
14877 if (bgp == NULL) {
14878 vty_out(vty, "%% No BGP process is configured\n");
14879 return CMD_WARNING;
14880 }
718e3744 14881 }
718e3744 14882
d62a17ae 14883 /* Check IP address argument. */
14884 ret = str2prefix(ip_str, &match);
14885 if (!ret) {
14886 vty_out(vty, "%% address is malformed\n");
14887 return CMD_WARNING;
14888 }
718e3744 14889
d62a17ae 14890 match.family = afi2family(afi);
14891
14892 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14893 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14894 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14895 dest = bgp_route_next(dest)) {
14896 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14897
9bcb3eef 14898 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14899 continue;
9bcb3eef 14900 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14901 if (!table)
ea47320b 14902 continue;
4953391b
DA
14903 rm = bgp_node_match(table, &match);
14904 if (rm == NULL)
ea47320b 14905 continue;
d62a17ae 14906
9bcb3eef 14907 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14908
ea47320b 14909 if (!prefix_check
b54892e0 14910 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14911 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14912 while (pi) {
14913 if (pi->extra && pi->extra->damp_info) {
14914 pi_temp = pi->next;
ea47320b 14915 bgp_damp_info_free(
19971c9a 14916 pi->extra->damp_info,
5c8846f6 14917 1, afi, safi);
40381db7 14918 pi = pi_temp;
ea47320b 14919 } else
40381db7 14920 pi = pi->next;
d62a17ae 14921 }
ea47320b
DL
14922 }
14923
9bcb3eef 14924 bgp_dest_unlock_node(rm);
d62a17ae 14925 }
14926 } else {
4953391b
DA
14927 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14928 if (dest != NULL) {
9bcb3eef 14929 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14930
d62a17ae 14931 if (!prefix_check
9bcb3eef
DS
14932 || dest_p->prefixlen == match.prefixlen) {
14933 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14934 while (pi) {
14935 if (pi->extra && pi->extra->damp_info) {
14936 pi_temp = pi->next;
d62a17ae 14937 bgp_damp_info_free(
19971c9a 14938 pi->extra->damp_info,
5c8846f6 14939 1, afi, safi);
40381db7 14940 pi = pi_temp;
d62a17ae 14941 } else
40381db7 14942 pi = pi->next;
d62a17ae 14943 }
14944 }
14945
9bcb3eef 14946 bgp_dest_unlock_node(dest);
d62a17ae 14947 }
14948 }
718e3744 14949
d62a17ae 14950 return CMD_SUCCESS;
718e3744 14951}
14952
14953DEFUN (clear_ip_bgp_dampening,
14954 clear_ip_bgp_dampening_cmd,
14955 "clear ip bgp dampening",
14956 CLEAR_STR
14957 IP_STR
14958 BGP_STR
14959 "Clear route flap dampening information\n")
14960{
b4f7f45b 14961 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14962 return CMD_SUCCESS;
718e3744 14963}
14964
14965DEFUN (clear_ip_bgp_dampening_prefix,
14966 clear_ip_bgp_dampening_prefix_cmd,
14967 "clear ip bgp dampening A.B.C.D/M",
14968 CLEAR_STR
14969 IP_STR
14970 BGP_STR
14971 "Clear route flap dampening information\n"
0c7b1b01 14972 "IPv4 prefix\n")
718e3744 14973{
d62a17ae 14974 int idx_ipv4_prefixlen = 4;
14975 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14976 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14977}
14978
14979DEFUN (clear_ip_bgp_dampening_address,
14980 clear_ip_bgp_dampening_address_cmd,
14981 "clear ip bgp dampening A.B.C.D",
14982 CLEAR_STR
14983 IP_STR
14984 BGP_STR
14985 "Clear route flap dampening information\n"
14986 "Network to clear damping information\n")
14987{
d62a17ae 14988 int idx_ipv4 = 4;
14989 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14990 SAFI_UNICAST, NULL, 0);
718e3744 14991}
14992
14993DEFUN (clear_ip_bgp_dampening_address_mask,
14994 clear_ip_bgp_dampening_address_mask_cmd,
14995 "clear ip bgp dampening A.B.C.D A.B.C.D",
14996 CLEAR_STR
14997 IP_STR
14998 BGP_STR
14999 "Clear route flap dampening information\n"
15000 "Network to clear damping information\n"
15001 "Network mask\n")
15002{
d62a17ae 15003 int idx_ipv4 = 4;
15004 int idx_ipv4_2 = 5;
15005 int ret;
15006 char prefix_str[BUFSIZ];
718e3744 15007
d62a17ae 15008 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15009 prefix_str, sizeof(prefix_str));
d62a17ae 15010 if (!ret) {
15011 vty_out(vty, "%% Inconsistent address and mask\n");
15012 return CMD_WARNING;
15013 }
718e3744 15014
d62a17ae 15015 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15016 NULL, 0);
718e3744 15017}
6b0655a2 15018
e3b78da8 15019static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15020{
15021 struct vty *vty = arg;
e3b78da8 15022 struct peer *peer = bucket->data;
825d9834 15023
47e12884 15024 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15025}
15026
2a0e69ae
DS
15027DEFUN (show_bgp_listeners,
15028 show_bgp_listeners_cmd,
15029 "show bgp listeners",
15030 SHOW_STR
15031 BGP_STR
15032 "Display Listen Sockets and who created them\n")
15033{
15034 bgp_dump_listener_info(vty);
15035
15036 return CMD_SUCCESS;
15037}
15038
825d9834
DS
15039DEFUN (show_bgp_peerhash,
15040 show_bgp_peerhash_cmd,
15041 "show bgp peerhash",
15042 SHOW_STR
15043 BGP_STR
15044 "Display information about the BGP peerhash\n")
15045{
15046 struct list *instances = bm->bgp;
15047 struct listnode *node;
15048 struct bgp *bgp;
15049
15050 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15051 vty_out(vty, "BGP: %s\n", bgp->name);
15052 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15053 vty);
15054 }
15055
15056 return CMD_SUCCESS;
15057}
15058
587ff0fd 15059/* also used for encap safi */
2b791107
DL
15060static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15061 afi_t afi, safi_t safi)
d62a17ae 15062{
9bcb3eef
DS
15063 struct bgp_dest *pdest;
15064 struct bgp_dest *dest;
d62a17ae 15065 struct bgp_table *table;
b54892e0
DS
15066 const struct prefix *p;
15067 const struct prefix_rd *prd;
d62a17ae 15068 struct bgp_static *bgp_static;
15069 mpls_label_t label;
d62a17ae 15070 char rdbuf[RD_ADDRSTRLEN];
15071
15072 /* Network configuration. */
9bcb3eef
DS
15073 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15074 pdest = bgp_route_next(pdest)) {
15075 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15076 if (!table)
ea47320b 15077 continue;
d62a17ae 15078
9bcb3eef
DS
15079 for (dest = bgp_table_top(table); dest;
15080 dest = bgp_route_next(dest)) {
15081 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15082 if (bgp_static == NULL)
ea47320b 15083 continue;
d62a17ae 15084
9bcb3eef
DS
15085 p = bgp_dest_get_prefix(dest);
15086 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15087 pdest);
d62a17ae 15088
ea47320b 15089 /* "network" configuration display. */
06b9f471 15090 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
15091 label = decode_label(&bgp_static->label);
15092
8228a9a7 15093 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
15094 if (safi == SAFI_MPLS_VPN)
15095 vty_out(vty, " label %u", label);
15096
15097 if (bgp_static->rmap.name)
15098 vty_out(vty, " route-map %s",
15099 bgp_static->rmap.name);
e2a86ad9
DS
15100
15101 if (bgp_static->backdoor)
15102 vty_out(vty, " backdoor");
15103
ea47320b
DL
15104 vty_out(vty, "\n");
15105 }
15106 }
d62a17ae 15107}
15108
2b791107
DL
15109static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15110 afi_t afi, safi_t safi)
d62a17ae 15111{
9bcb3eef
DS
15112 struct bgp_dest *pdest;
15113 struct bgp_dest *dest;
d62a17ae 15114 struct bgp_table *table;
b54892e0
DS
15115 const struct prefix *p;
15116 const struct prefix_rd *prd;
d62a17ae 15117 struct bgp_static *bgp_static;
ff44f570 15118 char buf[PREFIX_STRLEN * 2];
d62a17ae 15119 char buf2[SU_ADDRSTRLEN];
15120 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15121 char esi_buf[ESI_STR_LEN];
d62a17ae 15122
15123 /* Network configuration. */
9bcb3eef
DS
15124 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15125 pdest = bgp_route_next(pdest)) {
15126 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15127 if (!table)
ea47320b 15128 continue;
d62a17ae 15129
9bcb3eef
DS
15130 for (dest = bgp_table_top(table); dest;
15131 dest = bgp_route_next(dest)) {
15132 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15133 if (bgp_static == NULL)
ea47320b 15134 continue;
d62a17ae 15135
ea47320b 15136 char *macrouter = NULL;
d62a17ae 15137
ea47320b
DL
15138 if (bgp_static->router_mac)
15139 macrouter = prefix_mac2str(
15140 bgp_static->router_mac, NULL, 0);
15141 if (bgp_static->eth_s_id)
0a50c248
AK
15142 esi_to_str(bgp_static->eth_s_id,
15143 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15144 p = bgp_dest_get_prefix(dest);
15145 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15146
ea47320b 15147 /* "network" configuration display. */
06b9f471 15148 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15149 if (p->u.prefix_evpn.route_type == 5) {
15150 char local_buf[PREFIX_STRLEN];
3714a385 15151 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15152 struct prefix_evpn *)p)
15153 ? AF_INET
15154 : AF_INET6;
3714a385 15155 inet_ntop(family,
15156 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15157 local_buf, PREFIX_STRLEN);
772270f3
QY
15158 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15159 p->u.prefix_evpn.prefix_addr
15160 .ip_prefix_length);
197cb530
PG
15161 } else {
15162 prefix2str(p, buf, sizeof(buf));
15163 }
ea47320b 15164
a4d82a8a
PZ
15165 if (bgp_static->gatewayIp.family == AF_INET
15166 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15167 inet_ntop(bgp_static->gatewayIp.family,
15168 &bgp_static->gatewayIp.u.prefix, buf2,
15169 sizeof(buf2));
ea47320b 15170 vty_out(vty,
7bcc8dac 15171 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15172 buf, rdbuf,
15173 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15174 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15175 macrouter);
15176
0a22ddfb 15177 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15178 }
15179 }
3da6fcd5
PG
15180}
15181
718e3744 15182/* Configuration of static route announcement and aggregate
15183 information. */
2b791107
DL
15184void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15185 safi_t safi)
d62a17ae 15186{
9bcb3eef 15187 struct bgp_dest *dest;
b54892e0 15188 const struct prefix *p;
d62a17ae 15189 struct bgp_static *bgp_static;
15190 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15191
2b791107
DL
15192 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15193 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15194 return;
15195 }
d62a17ae 15196
2b791107
DL
15197 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15198 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15199 return;
15200 }
d62a17ae 15201
15202 /* Network configuration. */
9bcb3eef
DS
15203 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15204 dest = bgp_route_next(dest)) {
15205 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15206 if (bgp_static == NULL)
ea47320b 15207 continue;
d62a17ae 15208
9bcb3eef 15209 p = bgp_dest_get_prefix(dest);
d62a17ae 15210
8228a9a7 15211 vty_out(vty, " network %pFX", p);
d62a17ae 15212
ea47320b
DL
15213 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15214 vty_out(vty, " label-index %u",
15215 bgp_static->label_index);
d62a17ae 15216
ea47320b
DL
15217 if (bgp_static->rmap.name)
15218 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15219
15220 if (bgp_static->backdoor)
15221 vty_out(vty, " backdoor");
718e3744 15222
ea47320b
DL
15223 vty_out(vty, "\n");
15224 }
15225
d62a17ae 15226 /* Aggregate-address configuration. */
9bcb3eef
DS
15227 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15228 dest = bgp_route_next(dest)) {
15229 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15230 if (bgp_aggregate == NULL)
ea47320b 15231 continue;
d62a17ae 15232
9bcb3eef 15233 p = bgp_dest_get_prefix(dest);
d62a17ae 15234
8228a9a7 15235 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15236
ea47320b
DL
15237 if (bgp_aggregate->as_set)
15238 vty_out(vty, " as-set");
d62a17ae 15239
ea47320b
DL
15240 if (bgp_aggregate->summary_only)
15241 vty_out(vty, " summary-only");
718e3744 15242
20894f50
DA
15243 if (bgp_aggregate->rmap.name)
15244 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15245
229757f1
DA
15246 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15247 vty_out(vty, " origin %s",
15248 bgp_origin2str(bgp_aggregate->origin));
15249
6aabb15d
RZ
15250 if (bgp_aggregate->match_med)
15251 vty_out(vty, " matching-MED-only");
15252
365ab2e7
RZ
15253 if (bgp_aggregate->suppress_map_name)
15254 vty_out(vty, " suppress-map %s",
15255 bgp_aggregate->suppress_map_name);
15256
ea47320b
DL
15257 vty_out(vty, "\n");
15258 }
d62a17ae 15259}
734b349e 15260
2b791107 15261void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15262 safi_t safi)
d62a17ae 15263{
9bcb3eef 15264 struct bgp_dest *dest;
d62a17ae 15265 struct bgp_distance *bdistance;
15266
15267 /* Distance configuration. */
15268 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15269 && bgp->distance_local[afi][safi]
15270 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15271 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15272 || bgp->distance_local[afi][safi]
15273 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15274 vty_out(vty, " distance bgp %d %d %d\n",
15275 bgp->distance_ebgp[afi][safi],
15276 bgp->distance_ibgp[afi][safi],
15277 bgp->distance_local[afi][safi]);
15278 }
734b349e 15279
9bcb3eef
DS
15280 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15281 dest = bgp_route_next(dest)) {
15282 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15283 if (bdistance != NULL)
56ca3b5b 15284 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15285 bdistance->distance, dest,
d62a17ae 15286 bdistance->access_list ? bdistance->access_list
15287 : "");
ca2e160d 15288 }
718e3744 15289}
15290
15291/* Allocate routing table structure and install commands. */
d62a17ae 15292void bgp_route_init(void)
15293{
15294 afi_t afi;
15295 safi_t safi;
15296
15297 /* Init BGP distance table. */
05c7a1cc 15298 FOREACH_AFI_SAFI (afi, safi)
960035b2 15299 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15300
15301 /* IPv4 BGP commands. */
15302 install_element(BGP_NODE, &bgp_table_map_cmd);
15303 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15304 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15305
554b3b10 15306 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15307
15308 /* IPv4 unicast configuration. */
15309 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15310 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15311 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15312
554b3b10 15313 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15314
15315 /* IPv4 multicast configuration. */
15316 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15317 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15318 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15319 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15320
15321 /* IPv4 labeled-unicast configuration. */
fb985e0c 15322 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15323 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15324
d62a17ae 15325 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15326 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15327 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15328 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15329 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15330 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15331 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15332 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15333
15334 install_element(VIEW_NODE,
15335 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15336 install_element(VIEW_NODE,
15337 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15338 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15339 install_element(VIEW_NODE,
15340 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15341#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15342 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15343#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15344 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15345 install_element(VIEW_NODE,
44c69747 15346 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15347
d62a17ae 15348 /* BGP dampening clear commands */
15349 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15350 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15351
d62a17ae 15352 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15353 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15354
15355 /* prefix count */
15356 install_element(ENABLE_NODE,
15357 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15358#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15359 install_element(ENABLE_NODE,
15360 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15361#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15362
d62a17ae 15363 /* New config IPv6 BGP commands. */
15364 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15365 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15366 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15367
554b3b10 15368 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15369
15370 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15371
fb985e0c
DA
15372 /* IPv6 labeled unicast address family. */
15373 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15374 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15375
d62a17ae 15376 install_element(BGP_NODE, &bgp_distance_cmd);
15377 install_element(BGP_NODE, &no_bgp_distance_cmd);
15378 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15379 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15380 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15381 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15382 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15383 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15384 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15385 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15386 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15387 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15388 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15389 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15390 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15391 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15392 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15393 install_element(BGP_IPV4M_NODE,
15394 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15395 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15396 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15397 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15398 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15399 install_element(BGP_IPV6_NODE,
15400 &ipv6_bgp_distance_source_access_list_cmd);
15401 install_element(BGP_IPV6_NODE,
15402 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15403 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15404 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15405 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15406 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15407 install_element(BGP_IPV6M_NODE,
15408 &ipv6_bgp_distance_source_access_list_cmd);
15409 install_element(BGP_IPV6M_NODE,
15410 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15411
ef5f4b23 15412 /* BGP dampening */
585f1adc
IR
15413 install_element(BGP_NODE, &bgp_damp_set_cmd);
15414 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15415 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15416 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15417 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15418 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15419 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15420 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15421 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15422 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15423 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15424 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15425 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15426 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15427
15428 /* Large Communities */
15429 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15430 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15431
15432 /* show bgp ipv4 flowspec detailed */
15433 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15434
2a0e69ae 15435 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15436 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15437}
15438
15439void bgp_route_finish(void)
15440{
15441 afi_t afi;
15442 safi_t safi;
15443
05c7a1cc
QY
15444 FOREACH_AFI_SAFI (afi, safi) {
15445 bgp_table_unlock(bgp_distance_table[afi][safi]);
15446 bgp_distance_table[afi][safi] = NULL;
15447 }
228da428 15448}