]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Print peer's hostname for BGP (filtering) messages
[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(
a9f3f4f5
DA
2028 "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
2029 onlypeer, 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(
a9f3f4f5
DA
2044 "%pBP [Update:SEND] %pFX is filtered via ORF",
2045 peer, 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))
a9f3f4f5
DA
2053 zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
2054 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(
a9f3f4f5
DA
2063 "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
2064 onlypeer, 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(
a9f3f4f5
DA
2073 "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
2074 peer, 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
0655090c
QY
2215 if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
2216 filter->advmap.aname &&
2217 route_map_lookup_by_name(filter->advmap.aname)) {
2218 struct bgp_path_info rmap_path = {0};
2219 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2220 struct attr dummy_attr = *attr;
2221
2222 /* Fill temp path_info */
2223 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2224 pi, peer, &dummy_attr);
2225
2226 struct route_map *amap =
2227 route_map_lookup_by_name(filter->advmap.aname);
2228
2229 ret = route_map_apply(amap, p, &rmap_path);
2230
2231 bgp_attr_flush(&dummy_attr);
2232
2233 /*
2234 * The conditional advertisement mode is Withdraw and this
2235 * prefix is a conditional prefix. Don't advertise it
2236 */
2237 if (ret == RMAP_PERMITMATCH)
2238 return false;
2239 }
2240
d62a17ae 2241 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2242 if (!post_attr &&
2243 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2244 struct bgp_path_info rmap_path = {0};
2245 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2246 struct attr dummy_attr = {0};
d62a17ae 2247
e34291b8 2248 /* Fill temp path_info */
9bcb3eef
DS
2249 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2250 pi, peer, attr);
16f7ce2b 2251
d62a17ae 2252 /* don't confuse inbound and outbound setting */
2253 RESET_FLAG(attr->rmap_change_flags);
2254
2255 /*
2256 * The route reflector is not allowed to modify the attributes
2257 * of the reflected IBGP routes unless explicitly allowed.
2258 */
2259 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2260 && !CHECK_FLAG(bgp->flags,
2261 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2262 dummy_attr = *attr;
40381db7 2263 rmap_path.attr = &dummy_attr;
d62a17ae 2264 }
3f9c7369 2265
d62a17ae 2266 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2267
4056a5f6 2268 if (bgp_path_suppressed(pi))
d62a17ae 2269 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2270 &rmap_path);
d62a17ae 2271 else
2272 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2273 &rmap_path);
d62a17ae 2274
7e7639f5 2275 bgp_attr_flush(&dummy_attr);
d62a17ae 2276 peer->rmap_type = 0;
2277
2278 if (ret == RMAP_DENYMATCH) {
778048bf 2279 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2280 zlog_debug(
a9f3f4f5
DA
2281 "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
2282 peer, p, ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2283 bgp_attr_flush(rmap_path.attr);
3dc339cd 2284 return false;
d62a17ae 2285 }
3f9c7369 2286 }
3f9c7369 2287
9dac9fc8
DA
2288 /* RFC 8212 to prevent route leaks.
2289 * This specification intends to improve this situation by requiring the
2290 * explicit configuration of both BGP Import and Export Policies for any
2291 * External BGP (EBGP) session such as customers, peers, or
2292 * confederation boundaries for all enabled address families. Through
2293 * codification of the aforementioned requirement, operators will
2294 * benefit from consistent behavior across different BGP
2295 * implementations.
2296 */
1d3fdccf 2297 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2298 if (!bgp_outbound_policy_exists(peer, filter)) {
2299 if (monotime_since(&bgp->ebgprequirespolicywarning,
2300 NULL) > FIFTEENMINUTE2USEC ||
2301 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2302 zlog_warn(
2303 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2304 monotime(&bgp->ebgprequirespolicywarning);
2305 }
3dc339cd 2306 return false;
b17826b7 2307 }
9dac9fc8 2308
fb29348a
DA
2309 /* draft-ietf-idr-deprecate-as-set-confed-set
2310 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2311 * Eventually, This document (if approved) updates RFC 4271
2312 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2313 * and obsoletes RFC 6472.
2314 */
7f972cd8 2315 if (peer->bgp->reject_as_sets)
fb29348a 2316 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2317 return false;
fb29348a 2318
33d022bc
DA
2319 /* Codification of AS 0 Processing */
2320 if (aspath_check_as_zero(attr->aspath))
e2369003 2321 return false;
33d022bc 2322
637e5ba4 2323 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2324 if (peer->sort == BGP_PEER_IBGP
2325 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2326 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2327 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2328 } else {
2329 bgp_attr_add_gshut_community(attr);
2330 }
2331 }
2332
1479ed2f
DA
2333 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2334 * Capability" to a neighbor MUST perform the following upon receiving
2335 * a route from that neighbor with the "LLGR_STALE" community, or upon
2336 * attaching the "LLGR_STALE" community itself per Section 4.2:
2337 *
2338 * The route SHOULD NOT be advertised to any neighbor from which the
2339 * Long-lived Graceful Restart Capability has not been received.
2340 */
9a706b42
DA
2341 if (bgp_attr_get_community(attr) &&
2342 community_include(bgp_attr_get_community(attr),
2343 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2344 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2345 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2346 return false;
2347
d62a17ae 2348 /* After route-map has been applied, we check to see if the nexthop to
2349 * be carried in the attribute (that is used for the announcement) can
2350 * be cleared off or not. We do this in all cases where we would be
2351 * setting the nexthop to "ourselves". For IPv6, we only need to
2352 * consider
2353 * the global nexthop here; the link-local nexthop would have been
2354 * cleared
2355 * already, and if not, it is required by the update formation code.
2356 * Also see earlier comments in this function.
2357 */
2358 /*
2359 * If route-map has performed some operation on the nexthop or the peer
2360 * configuration says to pass it unchanged, we cannot reset the nexthop
2361 * here, so only attempt to do it if these aren't true. Note that the
2362 * route-map handler itself might have cleared the nexthop, if for
2363 * example,
2364 * it is configured as 'peer-address'.
2365 */
2366 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2367 piattr->rmap_change_flags)
d62a17ae 2368 && !transparent
2369 && !CHECK_FLAG(peer->af_flags[afi][safi],
2370 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2371 /* We can reset the nexthop, if setting (or forcing) it to
2372 * 'self' */
2373 if (CHECK_FLAG(peer->af_flags[afi][safi],
2374 PEER_FLAG_NEXTHOP_SELF)
2375 || CHECK_FLAG(peer->af_flags[afi][safi],
2376 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2377 if (!reflect
2378 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2379 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2380 subgroup_announce_reset_nhop(
2381 (peer_cap_enhe(peer, afi, safi)
2382 ? AF_INET6
2383 : p->family),
2384 attr);
7b651a32 2385 nh_reset = true;
2386 }
d62a17ae 2387 } else if (peer->sort == BGP_PEER_EBGP) {
2388 /* Can also reset the nexthop if announcing to EBGP, but
2389 * only if
2390 * no peer in the subgroup is on a shared subnet.
2391 * Note: 3rd party nexthop currently implemented for
2392 * IPv4 only.
2393 */
737af885
BS
2394 if ((p->family == AF_INET) &&
2395 (!bgp_subgrp_multiaccess_check_v4(
2396 piattr->nexthop,
7b651a32 2397 subgrp, from))) {
d62a17ae 2398 subgroup_announce_reset_nhop(
2399 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2400 ? AF_INET6
2401 : p->family),
737af885 2402 attr);
7b651a32 2403 nh_reset = true;
2404 }
737af885
BS
2405
2406 if ((p->family == AF_INET6) &&
2407 (!bgp_subgrp_multiaccess_check_v6(
2408 piattr->mp_nexthop_global,
7b651a32 2409 subgrp, from))) {
737af885
BS
2410 subgroup_announce_reset_nhop(
2411 (peer_cap_enhe(peer, afi, safi)
2412 ? AF_INET6
2413 : p->family),
2414 attr);
7b651a32 2415 nh_reset = true;
2416 }
737af885
BS
2417
2418
2419
40381db7 2420 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2421 /*
2422 * This flag is used for leaked vpn-vrf routes
2423 */
2424 int family = p->family;
2425
2426 if (peer_cap_enhe(peer, afi, safi))
2427 family = AF_INET6;
2428
2429 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2430 zlog_debug(
1defdda8 2431 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2432 __func__, family2str(family));
2433 subgroup_announce_reset_nhop(family, attr);
7b651a32 2434 nh_reset = true;
d62a17ae 2435 }
63696f1d 2436 }
960035b2 2437
63696f1d 2438 /* If IPv6/MP and nexthop does not have any override and happens
2439 * to
2440 * be a link-local address, reset it so that we don't pass along
2441 * the
2442 * source's link-local IPv6 address to recipients who may not be
2443 * on
2444 * the same interface.
2445 */
2446 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2447 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2448 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2449 nh_reset = true;
2450 }
d62a17ae 2451 }
3f9c7369 2452
7b651a32 2453 /*
2454 * When the next hop is set to ourselves, if all multipaths have
2455 * link-bandwidth announce the cumulative bandwidth as that makes
2456 * the most sense. However, don't modify if the link-bandwidth has
2457 * been explicitly set by user policy.
2458 */
2459 if (nh_reset &&
f7e1c681 2460 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2461 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2462 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2463 bgp_attr_set_ecommunity(
2464 attr,
2465 ecommunity_replace_linkbw(
2466 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2467 CHECK_FLAG(
2468 peer->flags,
2469 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2470
3dc339cd 2471 return true;
3f9c7369
DS
2472}
2473
cc9f21da 2474static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2475{
2476 struct afi_safi_info *info;
2477 afi_t afi;
2478 safi_t safi;
2479 struct bgp *bgp;
2480
2481 info = THREAD_ARG(thread);
2482 afi = info->afi;
2483 safi = info->safi;
2484 bgp = info->bgp;
2485
2486 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2487 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2488 safi);
f009ff26 2489
2490 bgp->gr_info[afi][safi].t_route_select = NULL;
2491
2492 XFREE(MTYPE_TMP, info);
2493
2494 /* Best path selection */
cc9f21da 2495 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2496}
2497
9bcb3eef 2498void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2499 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2500 struct bgp_path_info_pair *result, afi_t afi,
2501 safi_t safi)
2502{
2503 struct bgp_path_info *new_select;
2504 struct bgp_path_info *old_select;
40381db7
DS
2505 struct bgp_path_info *pi;
2506 struct bgp_path_info *pi1;
2507 struct bgp_path_info *pi2;
2508 struct bgp_path_info *nextpi = NULL;
d62a17ae 2509 int paths_eq, do_mpath, debug;
2510 struct list mp_list;
2511 char pfx_buf[PREFIX2STR_BUFFER];
2512 char path_buf[PATH_ADDPATH_STR_BUFFER];
2513
2514 bgp_mp_list_init(&mp_list);
2515 do_mpath =
2516 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2517
9bcb3eef 2518 debug = bgp_debug_bestpath(dest);
d62a17ae 2519
2520 if (debug)
9bcb3eef 2521 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2522
9bcb3eef 2523 dest->reason = bgp_path_selection_none;
d62a17ae 2524 /* bgp deterministic-med */
2525 new_select = NULL;
892fedb6 2526 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2527
1defdda8 2528 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2529 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2530 pi1 = pi1->next)
9bcb3eef 2531 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2532 BGP_PATH_DMED_SELECTED);
d62a17ae 2533
9bcb3eef 2534 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2535 pi1 = pi1->next) {
40381db7 2536 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2537 continue;
40381db7 2538 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2539 continue;
ea8b2282 2540 if (pi1->peer != bgp->peer_self)
feb17238 2541 if (!peer_established(pi1->peer))
d62a17ae 2542 continue;
2543
40381db7
DS
2544 new_select = pi1;
2545 if (pi1->next) {
2546 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2547 if (CHECK_FLAG(pi2->flags,
1defdda8 2548 BGP_PATH_DMED_CHECK))
d62a17ae 2549 continue;
40381db7 2550 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2551 continue;
ea8b2282 2552 if (pi2->peer != bgp->peer_self
d62a17ae 2553 && !CHECK_FLAG(
ea8b2282
DS
2554 pi2->peer->sflags,
2555 PEER_STATUS_NSF_WAIT))
40381db7 2556 if (pi2->peer->status
d62a17ae 2557 != Established)
2558 continue;
2559
121e245d
DS
2560 if (!aspath_cmp_left(pi1->attr->aspath,
2561 pi2->attr->aspath)
2562 && !aspath_cmp_left_confed(
40381db7 2563 pi1->attr->aspath,
121e245d
DS
2564 pi2->attr->aspath))
2565 continue;
d62a17ae 2566
121e245d
DS
2567 if (bgp_path_info_cmp(
2568 bgp, pi2, new_select,
2569 &paths_eq, mpath_cfg, debug,
fdf81fa0 2570 pfx_buf, afi, safi,
9bcb3eef 2571 &dest->reason)) {
121e245d 2572 bgp_path_info_unset_flag(
9bcb3eef 2573 dest, new_select,
121e245d
DS
2574 BGP_PATH_DMED_SELECTED);
2575 new_select = pi2;
d62a17ae 2576 }
121e245d
DS
2577
2578 bgp_path_info_set_flag(
9bcb3eef 2579 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2580 }
2581 }
9bcb3eef 2582 bgp_path_info_set_flag(dest, new_select,
18ee8310 2583 BGP_PATH_DMED_CHECK);
9bcb3eef 2584 bgp_path_info_set_flag(dest, new_select,
18ee8310 2585 BGP_PATH_DMED_SELECTED);
d62a17ae 2586
2587 if (debug) {
18ee8310 2588 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2589 new_select, path_buf, sizeof(path_buf));
8228a9a7 2590 zlog_debug(
4378495a
DS
2591 "%pBD(%s): %s is the bestpath from AS %u",
2592 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2593 aspath_get_first_as(
2594 new_select->attr->aspath));
d62a17ae 2595 }
2596 }
2597 }
96450faf 2598
d62a17ae 2599 /* Check old selected route and new selected route. */
2600 old_select = NULL;
2601 new_select = NULL;
9bcb3eef 2602 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2603 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2604 enum bgp_path_selection_reason reason;
2605
40381db7
DS
2606 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2607 old_select = pi;
d62a17ae 2608
40381db7 2609 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2610 /* reap REMOVED routes, if needs be
2611 * selected route must stay for a while longer though
2612 */
40381db7
DS
2613 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2614 && (pi != old_select))
9bcb3eef 2615 bgp_path_info_reap(dest, pi);
d62a17ae 2616
ddb5b488 2617 if (debug)
40381db7
DS
2618 zlog_debug("%s: pi %p in holddown", __func__,
2619 pi);
ddb5b488 2620
d62a17ae 2621 continue;
2622 }
96450faf 2623
40381db7
DS
2624 if (pi->peer && pi->peer != bgp->peer_self
2625 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2626 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2627
2628 if (debug)
2629 zlog_debug(
40381db7
DS
2630 "%s: pi %p non self peer %s not estab state",
2631 __func__, pi, pi->peer->host);
ddb5b488 2632
d62a17ae 2633 continue;
ddb5b488 2634 }
9fbdd100 2635
892fedb6 2636 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2637 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2638 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2639 if (debug)
40381db7 2640 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2641 continue;
2642 }
9fbdd100 2643
9bcb3eef 2644 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2645
9bcb3eef 2646 reason = dest->reason;
40381db7 2647 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2648 debug, pfx_buf, afi, safi,
2649 &dest->reason)) {
19ea4cec
DS
2650 if (new_select == NULL &&
2651 reason != bgp_path_selection_none)
9bcb3eef 2652 dest->reason = reason;
40381db7 2653 new_select = pi;
d62a17ae 2654 }
2655 }
718e3744 2656
d62a17ae 2657 /* Now that we know which path is the bestpath see if any of the other
2658 * paths
2659 * qualify as multipaths
2660 */
2661 if (debug) {
2662 if (new_select)
7533cad7
QY
2663 bgp_path_info_path_with_addpath_rx_str(
2664 new_select, path_buf, sizeof(path_buf));
d62a17ae 2665 else
772270f3 2666 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2667 zlog_debug(
4378495a
DS
2668 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2669 dest, bgp->name_pretty, path_buf,
d62a17ae 2670 old_select ? old_select->peer->host : "NONE");
96450faf 2671 }
9fbdd100 2672
d62a17ae 2673 if (do_mpath && new_select) {
9bcb3eef 2674 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2675 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2676
2677 if (debug)
18ee8310 2678 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2679 pi, path_buf, sizeof(path_buf));
d62a17ae 2680
40381db7 2681 if (pi == new_select) {
d62a17ae 2682 if (debug)
2683 zlog_debug(
4378495a
DS
2684 "%pBD(%s): %s is the bestpath, add to the multipath list",
2685 dest, bgp->name_pretty,
2686 path_buf);
40381db7 2687 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2688 continue;
2689 }
2690
40381db7 2691 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2692 continue;
2693
40381db7
DS
2694 if (pi->peer && pi->peer != bgp->peer_self
2695 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2696 PEER_STATUS_NSF_WAIT))
feb17238 2697 if (!peer_established(pi->peer))
d62a17ae 2698 continue;
2699
40381db7 2700 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2701 if (debug)
2702 zlog_debug(
8228a9a7
DS
2703 "%pBD: %s has the same nexthop as the bestpath, skip it",
2704 dest, path_buf);
d62a17ae 2705 continue;
2706 }
2707
40381db7 2708 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2709 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2710 &dest->reason);
d62a17ae 2711
2712 if (paths_eq) {
2713 if (debug)
2714 zlog_debug(
8228a9a7
DS
2715 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2716 dest, path_buf);
40381db7 2717 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2718 }
2719 }
2720 }
fee0f4c6 2721
4378495a 2722 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2723 mpath_cfg);
2724 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2725 bgp_mp_list_clear(&mp_list);
96450faf 2726
9bcb3eef 2727 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2728
d62a17ae 2729 result->old = old_select;
2730 result->new = new_select;
96450faf 2731
d62a17ae 2732 return;
fee0f4c6 2733}
2734
3f9c7369
DS
2735/*
2736 * A new route/change in bestpath of an existing route. Evaluate the path
2737 * for advertisement to the subgroup.
2738 */
3dc339cd
DA
2739void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2740 struct bgp_path_info *selected,
9bcb3eef 2741 struct bgp_dest *dest,
3dc339cd 2742 uint32_t addpath_tx_id)
d62a17ae 2743{
b54892e0 2744 const struct prefix *p;
d62a17ae 2745 struct peer *onlypeer;
2746 struct attr attr;
2747 afi_t afi;
2748 safi_t safi;
a77e2f4b
S
2749 struct bgp *bgp;
2750 bool advertise;
adbac85e 2751
9bcb3eef 2752 p = bgp_dest_get_prefix(dest);
d62a17ae 2753 afi = SUBGRP_AFI(subgrp);
2754 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2755 bgp = SUBGRP_INST(subgrp);
d62a17ae 2756 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2757 : NULL);
2758
2dbe669b
DA
2759 if (BGP_DEBUG(update, UPDATE_OUT))
2760 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2761
d62a17ae 2762 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2763 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2764 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2765 return;
d62a17ae 2766
6006b807 2767 memset(&attr, 0, sizeof(attr));
d62a17ae 2768 /* It's initialized in bgp_announce_check() */
2769
a77e2f4b
S
2770 /* Announcement to the subgroup. If the route is filtered withdraw it.
2771 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2772 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2773 * route
d62a17ae 2774 */
a77e2f4b
S
2775 advertise = bgp_check_advertise(bgp, dest);
2776
d62a17ae 2777 if (selected) {
7f7940e6 2778 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2779 NULL)) {
a77e2f4b
S
2780 /* Route is selected, if the route is already installed
2781 * in FIB, then it is advertised
2782 */
be785e35
DS
2783 if (advertise) {
2784 if (!bgp_check_withdrawal(bgp, dest))
2785 bgp_adj_out_set_subgroup(
2786 dest, subgrp, &attr, selected);
2787 else
2788 bgp_adj_out_unset_subgroup(
2789 dest, subgrp, 1, addpath_tx_id);
2790 }
a77e2f4b 2791 } else
9bcb3eef 2792 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2793 addpath_tx_id);
d62a17ae 2794 }
2795
2796 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2797 else {
9bcb3eef 2798 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2799 }
200df115 2800}
fee0f4c6 2801
3064bf43 2802/*
e1072051 2803 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2804 * This is called at the end of route processing.
3064bf43 2805 */
9bcb3eef 2806void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2807{
40381db7 2808 struct bgp_path_info *pi;
3064bf43 2809
9bcb3eef 2810 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2811 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2812 continue;
40381db7
DS
2813 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2814 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2815 }
3064bf43 2816}
2817
2818/*
2819 * Has the route changed from the RIB's perspective? This is invoked only
2820 * if the route selection returns the same best route as earlier - to
2821 * determine if we need to update zebra or not.
2822 */
9bcb3eef 2823bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2824{
4b7e6066 2825 struct bgp_path_info *mpinfo;
d62a17ae 2826
2bb9eff4
DS
2827 /* If this is multipath, check all selected paths for any nexthop
2828 * change or attribute change. Some attribute changes (e.g., community)
2829 * aren't of relevance to the RIB, but we'll update zebra to ensure
2830 * we handle the case of BGP nexthop change. This is the behavior
2831 * when the best path has an attribute change anyway.
d62a17ae 2832 */
1defdda8 2833 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2834 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2835 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2836 return true;
d62a17ae 2837
2bb9eff4
DS
2838 /*
2839 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2840 */
18ee8310
DS
2841 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2842 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2843 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2844 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2845 return true;
d62a17ae 2846 }
3064bf43 2847
d62a17ae 2848 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2849 return false;
3064bf43 2850}
2851
d62a17ae 2852struct bgp_process_queue {
2853 struct bgp *bgp;
9bcb3eef 2854 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2855#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2856 unsigned int flags;
2857 unsigned int queued;
200df115 2858};
2859
3b0c17e1 2860static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2861 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2862 struct bgp_path_info *new_select,
2863 struct bgp_path_info *old_select)
2864{
9bcb3eef 2865 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2866
2867 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2868 return;
2869
2870 if (advertise_type5_routes(bgp, afi) && new_select
2871 && is_route_injectable_into_evpn(new_select)) {
2872
2873 /* apply the route-map */
2874 if (bgp->adv_cmd_rmap[afi][safi].map) {
2875 route_map_result_t ret;
2876 struct bgp_path_info rmap_path;
2877 struct bgp_path_info_extra rmap_path_extra;
2878 struct attr dummy_attr;
2879
2880 dummy_attr = *new_select->attr;
2881
2882 /* Fill temp path_info */
9bcb3eef 2883 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2884 new_select, new_select->peer,
2885 &dummy_attr);
2886
2887 RESET_FLAG(dummy_attr.rmap_change_flags);
2888
2889 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2890 p, &rmap_path);
3b0c17e1 2891
2892 if (ret == RMAP_DENYMATCH) {
2893 bgp_attr_flush(&dummy_attr);
2894 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2895 safi);
2896 } else
2897 bgp_evpn_advertise_type5_route(
2898 bgp, p, &dummy_attr, afi, safi);
2899 } else {
2900 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2901 afi, safi);
2902 }
2903 } else if (advertise_type5_routes(bgp, afi) && old_select
2904 && is_route_injectable_into_evpn(old_select))
2905 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2906}
2907
bb2ca692
MS
2908/*
2909 * Utility to determine whether a particular path_info should use
2910 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2911 * in a path where we basically _know_ this is a BGP-LU route.
2912 */
2913static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2914{
2915 /* Certain types get imp null; so do paths where the nexthop is
2916 * not labeled.
2917 */
2918 if (new_select->sub_type == BGP_ROUTE_STATIC
2919 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2920 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2921 return true;
2922 else if (new_select->extra == NULL ||
2923 !bgp_is_valid_label(&new_select->extra->label[0]))
2924 /* TODO -- should be configurable? */
2925 return true;
2926 else
2927 return false;
2928}
2929
3103e8d2
DS
2930/*
2931 * old_select = The old best path
2932 * new_select = the new best path
2933 *
2934 * if (!old_select && new_select)
2935 * We are sending new information on.
2936 *
2937 * if (old_select && new_select) {
2938 * if (new_select != old_select)
2939 * We have a new best path send a change
2940 * else
2941 * We've received a update with new attributes that needs
2942 * to be passed on.
2943 * }
2944 *
2945 * if (old_select && !new_select)
2946 * We have no eligible route that we can announce or the rn
2947 * is being removed.
2948 */
9bcb3eef 2949static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2950 afi_t afi, safi_t safi)
d62a17ae 2951{
4b7e6066
DS
2952 struct bgp_path_info *new_select;
2953 struct bgp_path_info *old_select;
2954 struct bgp_path_info_pair old_and_new;
ddb5b488 2955 int debug = 0;
d62a17ae 2956
892fedb6 2957 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2958 if (dest)
2959 debug = bgp_debug_bestpath(dest);
b54892e0 2960 if (debug)
f4c713ae 2961 zlog_debug(
56ca3b5b 2962 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2963 __func__, dest);
f4c713ae
LB
2964 return;
2965 }
d62a17ae 2966 /* Is it end of initial update? (after startup) */
9bcb3eef 2967 if (!dest) {
e36f61b5
DS
2968 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2969 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2970
2971 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2972 FOREACH_AFI_SAFI (afi, safi) {
2973 if (bgp_fibupd_safi(safi))
2974 bgp_zebra_announce_table(bgp, afi, safi);
2975 }
d62a17ae 2976 bgp->main_peers_update_hold = 0;
2977
2978 bgp_start_routeadv(bgp);
aac24838 2979 return;
d62a17ae 2980 }
cb1faec9 2981
9bcb3eef 2982 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2983
9bcb3eef 2984 debug = bgp_debug_bestpath(dest);
b54892e0 2985 if (debug)
4378495a
DS
2986 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2987 dest, bgp->name_pretty, afi2str(afi),
2988 safi2str(safi));
ddb5b488 2989
f009ff26 2990 /* The best path calculation for the route is deferred if
2991 * BGP_NODE_SELECT_DEFER is set
2992 */
9bcb3eef 2993 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2994 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2995 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2996 return;
2997 }
2998
d62a17ae 2999 /* Best path selection. */
9bcb3eef 3000 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3001 afi, safi);
3002 old_select = old_and_new.old;
3003 new_select = old_and_new.new;
3004
3005 /* Do we need to allocate or free labels?
3006 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3007 * necessary to do this upon changes to best path. Exceptions:
3008 * - label index has changed -> recalculate resulting label
3009 * - path_info sub_type changed -> switch to/from implicit-null
3010 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3011 */
318cac96 3012 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3013 if (new_select) {
3014 if (!old_select
3015 || bgp_label_index_differs(new_select, old_select)
57592a53 3016 || new_select->sub_type != old_select->sub_type
9bcb3eef 3017 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3018 /* Enforced penultimate hop popping:
3019 * implicit-null for local routes, aggregate
3020 * and redistributed routes
3021 */
bb2ca692 3022 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3023 if (CHECK_FLAG(
9bcb3eef 3024 dest->flags,
992dd67e
PR
3025 BGP_NODE_REGISTERED_FOR_LABEL)
3026 || CHECK_FLAG(
3027 dest->flags,
3028 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3029 bgp_unregister_for_label(dest);
67f67ba4
DA
3030 dest->local_label = mpls_lse_encode(
3031 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3032 1);
9bcb3eef 3033 bgp_set_valid_label(&dest->local_label);
d62a17ae 3034 } else
9bcb3eef
DS
3035 bgp_register_for_label(dest,
3036 new_select);
d62a17ae 3037 }
9bcb3eef 3038 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3039 BGP_NODE_REGISTERED_FOR_LABEL)
3040 || CHECK_FLAG(dest->flags,
3041 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3042 bgp_unregister_for_label(dest);
318cac96 3043 }
992dd67e
PR
3044 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3045 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3046 bgp_unregister_for_label(dest);
d62a17ae 3047 }
cd1964ff 3048
b54892e0 3049 if (debug)
ddb5b488 3050 zlog_debug(
4378495a
DS
3051 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3052 __func__, dest, bgp->name_pretty, afi2str(afi),
3053 safi2str(safi), old_select, new_select);
ddb5b488 3054
d62a17ae 3055 /* If best route remains the same and this is not due to user-initiated
3056 * clear, see exactly what needs to be done.
3057 */
d62a17ae 3058 if (old_select && old_select == new_select
9bcb3eef 3059 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3060 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3061 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3062 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3063#ifdef ENABLE_BGP_VNC
d62a17ae 3064 vnc_import_bgp_add_route(bgp, p, old_select);
3065 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3066#endif
bb744275 3067 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3068 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3069
be785e35
DS
3070 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3071 && new_select->sub_type == BGP_ROUTE_NORMAL)
3072 SET_FLAG(dest->flags,
3073 BGP_NODE_FIB_INSTALL_PENDING);
3074
ddb5b488
PZ
3075 if (new_select->type == ZEBRA_ROUTE_BGP
3076 && (new_select->sub_type == BGP_ROUTE_NORMAL
3077 || new_select->sub_type
3078 == BGP_ROUTE_IMPORTED))
3079
9bcb3eef 3080 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3081 bgp, afi, safi);
3082 }
d62a17ae 3083 }
d62a17ae 3084
3085 /* If there is a change of interest to peers, reannounce the
3086 * route. */
1defdda8 3087 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3088 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3089 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3090 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3091
3092 /* unicast routes must also be annouced to
3093 * labeled-unicast update-groups */
3094 if (safi == SAFI_UNICAST)
3095 group_announce_route(bgp, afi,
9bcb3eef 3096 SAFI_LABELED_UNICAST, dest,
d62a17ae 3097 new_select);
3098
1defdda8 3099 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3100 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3101 }
fee0f4c6 3102
3b0c17e1 3103 /* advertise/withdraw type-5 routes */
3104 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3105 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3106 bgp_process_evpn_route_injection(
9bcb3eef 3107 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3108
b1875e65 3109 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3110 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3111 bgp_zebra_clear_route_change_flags(dest);
3112 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3113 return;
d62a17ae 3114 }
8ad7271d 3115
d62a17ae 3116 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3117 */
9bcb3eef 3118 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3119
3120 /* bestpath has changed; bump version */
3121 if (old_select || new_select) {
9bcb3eef 3122 bgp_bump_version(dest);
d62a17ae 3123
3124 if (!bgp->t_rmap_def_originate_eval) {
3125 bgp_lock(bgp);
3126 thread_add_timer(
3127 bm->master,
3128 update_group_refresh_default_originate_route_map,
3129 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3130 &bgp->t_rmap_def_originate_eval);
3131 }
3132 }
3f9c7369 3133
d62a17ae 3134 if (old_select)
9bcb3eef 3135 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3136 if (new_select) {
ddb5b488
PZ
3137 if (debug)
3138 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3139 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3140 bgp_path_info_unset_flag(dest, new_select,
3141 BGP_PATH_ATTR_CHANGED);
1defdda8 3142 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3143 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3144 }
338b3424 3145
49e5a4a0 3146#ifdef ENABLE_BGP_VNC
d62a17ae 3147 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3148 if (old_select != new_select) {
3149 if (old_select) {
3150 vnc_import_bgp_exterior_del_route(bgp, p,
3151 old_select);
3152 vnc_import_bgp_del_route(bgp, p, old_select);
3153 }
3154 if (new_select) {
3155 vnc_import_bgp_exterior_add_route(bgp, p,
3156 new_select);
3157 vnc_import_bgp_add_route(bgp, p, new_select);
3158 }
3159 }
3160 }
65efcfce
LB
3161#endif
3162
9bcb3eef 3163 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3164
3165 /* unicast routes must also be annouced to labeled-unicast update-groups
3166 */
3167 if (safi == SAFI_UNICAST)
9bcb3eef 3168 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3169 new_select);
3170
3171 /* FIB update. */
3172 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3173 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3174
d62a17ae 3175 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3176 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3177 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3178 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3179
be785e35
DS
3180 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3181 SET_FLAG(dest->flags,
3182 BGP_NODE_FIB_INSTALL_PENDING);
3183
2b659f33
MK
3184 /* if this is an evpn imported type-5 prefix,
3185 * we need to withdraw the route first to clear
3186 * the nh neigh and the RMAC entry.
3187 */
3188 if (old_select &&
3189 is_route_parent_evpn(old_select))
3190 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3191
9bcb3eef 3192 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3193 } else {
d62a17ae 3194 /* Withdraw the route from the kernel. */
3195 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3196 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3197 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3198 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3199
568e10ca 3200 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3201 }
718e3744 3202 }
3064bf43 3203
9bcb3eef 3204 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3205 old_select);
5424b7ba 3206
d62a17ae 3207 /* Clear any route change flags. */
9bcb3eef 3208 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3209
18ee8310 3210 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3211 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3212 bgp_path_info_reap(dest, old_select);
d62a17ae 3213
9bcb3eef 3214 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3215 return;
718e3744 3216}
3217
f009ff26 3218/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3219void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3220{
9bcb3eef 3221 struct bgp_dest *dest;
f009ff26 3222 int cnt = 0;
3223 struct afi_safi_info *thread_info;
f009ff26 3224
56c226e7
DS
3225 if (bgp->gr_info[afi][safi].t_route_select) {
3226 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3227
3228 thread_info = THREAD_ARG(t);
3229 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3230 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3231 }
f009ff26 3232
3233 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3234 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3235 get_afi_safi_str(afi, safi, false),
26742171 3236 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3237 }
3238
3239 /* Process the route list */
6338d242 3240 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3241 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3242 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3243 dest = bgp_route_next(dest)) {
3244 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3245 continue;
3246
3247 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3248 bgp->gr_info[afi][safi].gr_deferred--;
3249 bgp_process_main_one(bgp, dest, afi, safi);
3250 cnt++;
067ea165
CB
3251 }
3252 /* If iteration stopped before the entire table was traversed then the
3253 * node needs to be unlocked.
3254 */
3255 if (dest) {
3256 bgp_dest_unlock_node(dest);
3257 dest = NULL;
f009ff26 3258 }
3259
9e3b51a7 3260 /* Send EOR message when all routes are processed */
6338d242 3261 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3262 bgp_send_delayed_eor(bgp);
8c48b3b6 3263 /* Send route processing complete message to RIB */
3264 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3265 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3266 return;
9e3b51a7 3267 }
f009ff26 3268
3269 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3270
3271 thread_info->afi = afi;
3272 thread_info->safi = safi;
3273 thread_info->bgp = bgp;
3274
3275 /* If there are more routes to be processed, start the
3276 * selection timer
3277 */
3278 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3279 BGP_ROUTE_SELECT_DELAY,
3280 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3281}
3282
aac24838 3283static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3284{
aac24838
JB
3285 struct bgp_process_queue *pqnode = data;
3286 struct bgp *bgp = pqnode->bgp;
d62a17ae 3287 struct bgp_table *table;
9bcb3eef 3288 struct bgp_dest *dest;
aac24838
JB
3289
3290 /* eoiu marker */
3291 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3292 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3293 /* should always have dedicated wq call */
3294 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3295 return WQ_SUCCESS;
3296 }
3297
ac021f40 3298 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3299 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3300 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3301 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3302 table = bgp_dest_table(dest);
3303 /* note, new DESTs may be added as part of processing */
3304 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3305
9bcb3eef 3306 bgp_dest_unlock_node(dest);
d62a17ae 3307 bgp_table_unlock(table);
3308 }
aac24838
JB
3309
3310 return WQ_SUCCESS;
3311}
3312
3313static void bgp_processq_del(struct work_queue *wq, void *data)
3314{
3315 struct bgp_process_queue *pqnode = data;
3316
3317 bgp_unlock(pqnode->bgp);
3318
3319 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3320}
3321
b6c386bb 3322void bgp_process_queue_init(struct bgp *bgp)
200df115 3323{
b6c386bb
DS
3324 if (!bgp->process_queue) {
3325 char name[BUFSIZ];
3326
3327 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3328 bgp->process_queue = work_queue_new(bm->master, name);
3329 }
3330
3331 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3332 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3333 bgp->process_queue->spec.max_retries = 0;
3334 bgp->process_queue->spec.hold = 50;
d62a17ae 3335 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3336 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3337}
3338
cfe8d15a 3339static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3340{
3341 struct bgp_process_queue *pqnode;
3342
a4d82a8a
PZ
3343 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3344 sizeof(struct bgp_process_queue));
aac24838
JB
3345
3346 /* unlocked in bgp_processq_del */
3347 pqnode->bgp = bgp_lock(bgp);
3348 STAILQ_INIT(&pqnode->pqueue);
3349
aac24838
JB
3350 return pqnode;
3351}
3352
9bcb3eef 3353void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3354{
aac24838 3355#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3356 struct work_queue *wq = bgp->process_queue;
d62a17ae 3357 struct bgp_process_queue *pqnode;
cfe8d15a 3358 int pqnode_reuse = 0;
495f0b13 3359
d62a17ae 3360 /* already scheduled for processing? */
9bcb3eef 3361 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3362 return;
2e02b9b2 3363
f009ff26 3364 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3365 * the workqueue
3366 */
9bcb3eef 3367 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3368 if (BGP_DEBUG(update, UPDATE_OUT))
3369 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3370 dest);
f009ff26 3371 return;
3372 }
3373
46aeabed
LS
3374 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3375 if (BGP_DEBUG(update, UPDATE_OUT))
3376 zlog_debug(
3377 "Soft reconfigure table in progress for route %p",
3378 dest);
3379 return;
3380 }
3381
aac24838 3382 if (wq == NULL)
d62a17ae 3383 return;
3384
aac24838 3385 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3386 limit only if is from the same BGP view and it's not an EOIU marker
3387 */
aac24838
JB
3388 if (work_queue_item_count(wq)) {
3389 struct work_queue_item *item = work_queue_last_item(wq);
3390 pqnode = item->data;
228da428 3391
a4d82a8a
PZ
3392 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3393 || pqnode->bgp != bgp
3394 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3395 pqnode = bgp_processq_alloc(bgp);
3396 else
3397 pqnode_reuse = 1;
aac24838 3398 } else
cfe8d15a 3399 pqnode = bgp_processq_alloc(bgp);
aac24838 3400 /* all unlocked in bgp_process_wq */
9bcb3eef 3401 bgp_table_lock(bgp_dest_table(dest));
aac24838 3402
9bcb3eef
DS
3403 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3404 bgp_dest_lock_node(dest);
aac24838 3405
60466a63 3406 /* can't be enqueued twice */
9bcb3eef
DS
3407 assert(STAILQ_NEXT(dest, pq) == NULL);
3408 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3409 pqnode->queued++;
3410
cfe8d15a
LB
3411 if (!pqnode_reuse)
3412 work_queue_add(wq, pqnode);
3413
d62a17ae 3414 return;
fee0f4c6 3415}
0a486e5f 3416
d62a17ae 3417void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3418{
d62a17ae 3419 struct bgp_process_queue *pqnode;
cb1faec9 3420
b6c386bb 3421 if (bgp->process_queue == NULL)
d62a17ae 3422 return;
2e02b9b2 3423
cfe8d15a 3424 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3425
aac24838 3426 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3427 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3428}
3429
cc9f21da 3430static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3431{
d62a17ae 3432 struct peer *peer;
0a486e5f 3433
d62a17ae 3434 peer = THREAD_ARG(thread);
3435 peer->t_pmax_restart = NULL;
0a486e5f 3436
d62a17ae 3437 if (bgp_debug_neighbor_events(peer))
3438 zlog_debug(
3439 "%s Maximum-prefix restart timer expired, restore peering",
3440 peer->host);
0a486e5f 3441
a9bafa95 3442 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3443 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3444}
3445
9cbd06e0
DA
3446static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3447 safi_t safi)
3448{
3449 uint32_t count = 0;
f41b0459 3450 bool filtered = false;
9cbd06e0
DA
3451 struct bgp_dest *dest;
3452 struct bgp_adj_in *ain;
40bb2ccf 3453 struct attr attr = {};
9cbd06e0
DA
3454 struct bgp_table *table = peer->bgp->rib[afi][safi];
3455
3456 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3457 for (ain = dest->adj_in; ain; ain = ain->next) {
3458 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3459
3460 attr = *ain->attr;
9cbd06e0
DA
3461
3462 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3463 == FILTER_DENY)
f41b0459
DA
3464 filtered = true;
3465
3466 if (bgp_input_modifier(
3467 peer, rn_p, &attr, afi, safi,
3468 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3469 NULL, 0, NULL)
3470 == RMAP_DENY)
3471 filtered = true;
3472
3473 if (filtered)
9cbd06e0 3474 count++;
f41b0459 3475
d498917e 3476 bgp_attr_flush(&attr);
9cbd06e0
DA
3477 }
3478 }
3479
3480 return count;
3481}
3482
3dc339cd
DA
3483bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3484 int always)
718e3744 3485{
d62a17ae 3486 iana_afi_t pkt_afi;
5c525538 3487 iana_safi_t pkt_safi;
9cbd06e0
DA
3488 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3489 PEER_FLAG_MAX_PREFIX_FORCE))
3490 ? bgp_filtered_routes_count(peer, afi, safi)
3491 + peer->pcount[afi][safi]
3492 : peer->pcount[afi][safi];
9cabb64b 3493
d62a17ae 3494 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3495 return false;
e0701b79 3496
9cbd06e0 3497 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3498 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3499 PEER_STATUS_PREFIX_LIMIT)
3500 && !always)
3dc339cd 3501 return false;
e0701b79 3502
d62a17ae 3503 zlog_info(
f70c91dc
DA
3504 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3505 get_afi_safi_str(afi, safi, false), peer, pcount,
3506 peer->pmax[afi][safi]);
d62a17ae 3507 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3508
3509 if (CHECK_FLAG(peer->af_flags[afi][safi],
3510 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3511 return false;
d62a17ae 3512
3513 /* Convert AFI, SAFI to values for packet. */
3514 pkt_afi = afi_int2iana(afi);
3515 pkt_safi = safi_int2iana(safi);
3516 {
d7c0a89a 3517 uint8_t ndata[7];
d62a17ae 3518
3519 ndata[0] = (pkt_afi >> 8);
3520 ndata[1] = pkt_afi;
3521 ndata[2] = pkt_safi;
3522 ndata[3] = (peer->pmax[afi][safi] >> 24);
3523 ndata[4] = (peer->pmax[afi][safi] >> 16);
3524 ndata[5] = (peer->pmax[afi][safi] >> 8);
3525 ndata[6] = (peer->pmax[afi][safi]);
3526
3527 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3528 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3529 BGP_NOTIFY_CEASE_MAX_PREFIX,
3530 ndata, 7);
3531 }
3532
3533 /* Dynamic peers will just close their connection. */
3534 if (peer_dynamic_neighbor(peer))
3dc339cd 3535 return true;
d62a17ae 3536
3537 /* restart timer start */
3538 if (peer->pmax_restart[afi][safi]) {
3539 peer->v_pmax_restart =
3540 peer->pmax_restart[afi][safi] * 60;
3541
3542 if (bgp_debug_neighbor_events(peer))
3543 zlog_debug(
f70c91dc
DA
3544 "%pBP Maximum-prefix restart timer started for %d secs",
3545 peer, peer->v_pmax_restart);
d62a17ae 3546
3547 BGP_TIMER_ON(peer->t_pmax_restart,
3548 bgp_maximum_prefix_restart_timer,
3549 peer->v_pmax_restart);
3550 }
3551
3dc339cd 3552 return true;
d62a17ae 3553 } else
3554 UNSET_FLAG(peer->af_sflags[afi][safi],
3555 PEER_STATUS_PREFIX_LIMIT);
3556
b1823b69
DS
3557 if (pcount
3558 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3559 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3560 PEER_STATUS_PREFIX_THRESHOLD)
3561 && !always)
3dc339cd 3562 return false;
d62a17ae 3563
3564 zlog_info(
f70c91dc
DA
3565 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3566 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3567 peer->pmax[afi][safi]);
d62a17ae 3568 SET_FLAG(peer->af_sflags[afi][safi],
3569 PEER_STATUS_PREFIX_THRESHOLD);
3570 } else
3571 UNSET_FLAG(peer->af_sflags[afi][safi],
3572 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3573 return false;
718e3744 3574}
3575
b40d939b 3576/* Unconditionally remove the route from the RIB, without taking
3577 * damping into consideration (eg, because the session went down)
3578 */
9bcb3eef 3579void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3580 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3581{
f009ff26 3582
3583 struct bgp *bgp = NULL;
3584 bool delete_route = false;
3585
9bcb3eef
DS
3586 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3587 safi);
d62a17ae 3588
f009ff26 3589 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3590 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3591
f009ff26 3592 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3593 * flag
3594 */
3595 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3596 delete_route = true;
9bcb3eef 3597 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3598 delete_route = true;
f009ff26 3599 if (delete_route) {
9bcb3eef
DS
3600 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3601 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3602 bgp = pi->peer->bgp;
26742171 3603 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3604 }
3605 }
3606 }
4a11bf2c 3607
9bcb3eef
DS
3608 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3609 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3610}
3611
9bcb3eef 3612static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3613 struct peer *peer, afi_t afi, safi_t safi,
3614 struct prefix_rd *prd)
3615{
9bcb3eef 3616 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3617
d62a17ae 3618 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3619 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3620 */
b4f7f45b
IR
3621 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3622 && peer->sort == BGP_PEER_EBGP)
3623 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3624 == BGP_DAMP_SUPPRESSED) {
3625 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3626 safi);
3627 return;
d62a17ae 3628 }
3629
49e5a4a0 3630#ifdef ENABLE_BGP_VNC
d62a17ae 3631 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3632 struct bgp_dest *pdest = NULL;
d62a17ae 3633 struct bgp_table *table = NULL;
3634
9bcb3eef
DS
3635 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3636 (struct prefix *)prd);
3637 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3638 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3639
3640 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3641 peer->bgp, prd, table, p, pi);
d62a17ae 3642 }
9bcb3eef 3643 bgp_dest_unlock_node(pdest);
d62a17ae 3644 }
3645 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3646 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3647
b54892e0
DS
3648 vnc_import_bgp_del_route(peer->bgp, p, pi);
3649 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3650 }
65efcfce 3651 }
d62a17ae 3652#endif
128ea8ab 3653
d62a17ae 3654 /* If this is an EVPN route, process for un-import. */
3655 if (safi == SAFI_EVPN)
b54892e0 3656 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3657
9bcb3eef 3658 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3659}
3660
4b7e6066
DS
3661struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3662 struct peer *peer, struct attr *attr,
9bcb3eef 3663 struct bgp_dest *dest)
fb018d25 3664{
4b7e6066 3665 struct bgp_path_info *new;
fb018d25 3666
d62a17ae 3667 /* Make new BGP info. */
4b7e6066 3668 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3669 new->type = type;
3670 new->instance = instance;
3671 new->sub_type = sub_type;
3672 new->peer = peer;
3673 new->attr = attr;
3674 new->uptime = bgp_clock();
9bcb3eef 3675 new->net = dest;
d62a17ae 3676 return new;
fb018d25
DS
3677}
3678
c265ee22 3679/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3680bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3681 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3682 struct bgp_dest *dest)
d62a17ae 3683{
2dbe3fa9 3684 bool ret = false;
b099a5c8
DA
3685 bool is_bgp_static_route =
3686 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3687 : false;
d62a17ae 3688
e8442016
DS
3689 /*
3690 * Only validated for unicast and multicast currently.
3691 * Also valid for EVPN where the nexthop is an IP address.
3692 * If we are a bgp static route being checked then there is
3693 * no need to check to see if the nexthop is martian as
3694 * that it should be ok.
3695 */
3696 if (is_bgp_static_route ||
3697 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3698 return false;
d62a17ae 3699
3700 /* If NEXT_HOP is present, validate it. */
3701 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3702 if (attr->nexthop.s_addr == INADDR_ANY ||
3703 !ipv4_unicast_valid(&attr->nexthop) ||
3704 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3705 return true;
d62a17ae 3706 }
c265ee22 3707
d62a17ae 3708 /* If MP_NEXTHOP is present, validate it. */
3709 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3710 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3711 * it is not an IPv6 link-local address.
0355b41d
DA
3712 *
3713 * If we receive an UPDATE with nexthop length set to 32 bytes
3714 * we shouldn't discard an UPDATE if it's set to (::).
3715 * The link-local (2st) is validated along the code path later.
d62a17ae 3716 */
3717 if (attr->mp_nexthop_len) {
3718 switch (attr->mp_nexthop_len) {
3719 case BGP_ATTR_NHLEN_IPV4:
3720 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3721 ret = (attr->mp_nexthop_global_in.s_addr ==
3722 INADDR_ANY ||
3723 !ipv4_unicast_valid(
3724 &attr->mp_nexthop_global_in) ||
3725 bgp_nexthop_self(bgp, afi, type, stype, attr,
3726 dest));
d62a17ae 3727 break;
3728
3729 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3730 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3731 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3732 &attr->mp_nexthop_global)
d62a17ae 3733 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3734 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3735 &attr->mp_nexthop_global)
3736 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3737 dest));
d62a17ae 3738 break;
0355b41d
DA
3739 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3740 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3741 || IN6_IS_ADDR_MULTICAST(
3742 &attr->mp_nexthop_global)
3743 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3744 dest));
0355b41d 3745 break;
d62a17ae 3746
3747 default:
3dc339cd 3748 ret = true;
d62a17ae 3749 break;
3750 }
3751 }
c265ee22 3752
d62a17ae 3753 return ret;
3754}
3755
aade37d7 3756static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3757{
3758 struct community *old;
3759 struct community *new;
3760 struct community *merge;
aade37d7 3761 struct community *no_export;
2721dd61 3762
9a706b42 3763 old = bgp_attr_get_community(attr);
aade37d7 3764 no_export = community_str2com("no-export");
2721dd61 3765
b4efa101
DA
3766 assert(no_export);
3767
2721dd61 3768 if (old) {
aade37d7 3769 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3770
3771 if (!old->refcnt)
3772 community_free(&old);
3773
3774 new = community_uniq_sort(merge);
3775 community_free(&merge);
3776 } else {
aade37d7 3777 new = community_dup(no_export);
2721dd61
DA
3778 }
3779
aade37d7 3780 community_free(&no_export);
2721dd61 3781
9a706b42 3782 bgp_attr_set_community(attr, new);
2721dd61
DA
3783}
3784
5a1ae2c2 3785int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3786 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3787 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3788 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3789 struct bgp_route_evpn *evpn)
d62a17ae 3790{
3791 int ret;
3792 int aspath_loop_count = 0;
9bcb3eef 3793 struct bgp_dest *dest;
d62a17ae 3794 struct bgp *bgp;
3795 struct attr new_attr;
3796 struct attr *attr_new;
40381db7 3797 struct bgp_path_info *pi;
4b7e6066
DS
3798 struct bgp_path_info *new;
3799 struct bgp_path_info_extra *extra;
d62a17ae 3800 const char *reason;
3801 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3802 int connected = 0;
3803 int do_loop_check = 1;
3804 int has_valid_label = 0;
7c312383 3805 afi_t nh_afi;
949b0f24 3806 uint8_t pi_type = 0;
3807 uint8_t pi_sub_type = 0;
9146341f 3808 bool force_evpn_import = false;
907707db 3809 safi_t orig_safi = safi;
a486300b 3810 bool leak_success = true;
949b0f24 3811
c7bb4f00 3812 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3813 char pfxprint[PREFIX2STR_BUFFER];
3814
3815 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3816 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3817 afi, safi, attr);
6401252f
QY
3818 }
3819
49e5a4a0 3820#ifdef ENABLE_BGP_VNC
d62a17ae 3821 int vnc_implicit_withdraw = 0;
65efcfce 3822#endif
d62a17ae 3823 int same_attr = 0;
718e3744 3824
907707db
MS
3825 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3826 if (orig_safi == SAFI_LABELED_UNICAST)
3827 safi = SAFI_UNICAST;
3828
6006b807 3829 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3830 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3831 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3832
d62a17ae 3833 bgp = peer->bgp;
9bcb3eef 3834 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3835 /* TODO: Check to see if we can get rid of "is_valid_label" */
3836 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3837 has_valid_label = (num_labels > 0) ? 1 : 0;
3838 else
3839 has_valid_label = bgp_is_valid_label(label);
718e3744 3840
28f66de2
MS
3841 if (has_valid_label)
3842 assert(label != NULL);
3843
66ff6089
AD
3844 /* Update overlay index of the attribute */
3845 if (afi == AFI_L2VPN && evpn)
3846 memcpy(&attr->evpn_overlay, evpn,
3847 sizeof(struct bgp_route_evpn));
3848
d62a17ae 3849 /* When peer's soft reconfiguration enabled. Record input packet in
3850 Adj-RIBs-In. */
3851 if (!soft_reconfig
3852 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3853 && peer != bgp->peer_self)
9bcb3eef 3854 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3855
3856 /* Check previously received route. */
9bcb3eef 3857 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3858 if (pi->peer == peer && pi->type == type
3859 && pi->sub_type == sub_type
3860 && pi->addpath_rx_id == addpath_id)
d62a17ae 3861 break;
3862
3863 /* AS path local-as loop check. */
3864 if (peer->change_local_as) {
c4368918
DW
3865 if (peer->allowas_in[afi][safi])
3866 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3867 else if (!CHECK_FLAG(peer->flags,
3868 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3869 aspath_loop_count = 1;
3870
3871 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3872 > aspath_loop_count) {
b4d46cc9 3873 peer->stat_pfx_aspath_loop++;
692174a1 3874 reason = "as-path contains our own AS;";
d62a17ae 3875 goto filtered;
3876 }
718e3744 3877 }
718e3744 3878
d62a17ae 3879 /* If the peer is configured for "allowas-in origin" and the last ASN in
3880 * the
3881 * as-path is our ASN then we do not need to call aspath_loop_check
3882 */
3883 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3884 if (aspath_get_last_as(attr->aspath) == bgp->as)
3885 do_loop_check = 0;
3886
3887 /* AS path loop check. */
3888 if (do_loop_check) {
3889 if (aspath_loop_check(attr->aspath, bgp->as)
3890 > peer->allowas_in[afi][safi]
3891 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3892 && aspath_loop_check(attr->aspath, bgp->confed_id)
3893 > peer->allowas_in[afi][safi])) {
b4d46cc9 3894 peer->stat_pfx_aspath_loop++;
d62a17ae 3895 reason = "as-path contains our own AS;";
3896 goto filtered;
3897 }
3898 }
aac9ef6c 3899
d62a17ae 3900 /* Route reflector originator ID check. */
3901 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3902 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3903 peer->stat_pfx_originator_loop++;
d62a17ae 3904 reason = "originator is us;";
3905 goto filtered;
3906 }
718e3744 3907
d62a17ae 3908 /* Route reflector cluster ID check. */
3909 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3910 peer->stat_pfx_cluster_loop++;
d62a17ae 3911 reason = "reflected from the same cluster;";
3912 goto filtered;
3913 }
718e3744 3914
d62a17ae 3915 /* Apply incoming filter. */
907707db 3916 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3917 peer->stat_pfx_filter++;
d62a17ae 3918 reason = "filter;";
3919 goto filtered;
3920 }
718e3744 3921
a8b72dc6
DA
3922 /* RFC 8212 to prevent route leaks.
3923 * This specification intends to improve this situation by requiring the
3924 * explicit configuration of both BGP Import and Export Policies for any
3925 * External BGP (EBGP) session such as customers, peers, or
3926 * confederation boundaries for all enabled address families. Through
3927 * codification of the aforementioned requirement, operators will
3928 * benefit from consistent behavior across different BGP
3929 * implementations.
3930 */
1d3fdccf 3931 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3932 if (!bgp_inbound_policy_exists(peer,
3933 &peer->filter[afi][safi])) {
3934 reason = "inbound policy missing";
b17826b7
DS
3935 if (monotime_since(&bgp->ebgprequirespolicywarning,
3936 NULL) > FIFTEENMINUTE2USEC ||
3937 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3938 zlog_warn(
3939 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3940 monotime(&bgp->ebgprequirespolicywarning);
3941 }
a8b72dc6
DA
3942 goto filtered;
3943 }
3944
fb29348a
DA
3945 /* draft-ietf-idr-deprecate-as-set-confed-set
3946 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3947 * Eventually, This document (if approved) updates RFC 4271
3948 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3949 * and obsoletes RFC 6472.
3950 */
7f972cd8 3951 if (peer->bgp->reject_as_sets)
fb29348a
DA
3952 if (aspath_check_as_sets(attr->aspath)) {
3953 reason =
3954 "as-path contains AS_SET or AS_CONFED_SET type;";
3955 goto filtered;
3956 }
3957
6f4f49b2 3958 new_attr = *attr;
d62a17ae 3959
3960 /* Apply incoming route-map.
3961 * NB: new_attr may now contain newly allocated values from route-map
3962 * "set"
3963 * commands, so we need bgp_attr_flush in the error paths, until we
3964 * intern
3965 * the attr (which takes over the memory references) */
907707db 3966 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3967 num_labels, dest)
3968 == RMAP_DENY) {
b4d46cc9 3969 peer->stat_pfx_filter++;
d62a17ae 3970 reason = "route-map;";
3971 bgp_attr_flush(&new_attr);
3972 goto filtered;
3973 }
718e3744 3974
05864da7 3975 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3976 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3977 /* remove from RIB previous entry */
3978 bgp_zebra_withdraw(p, pi, bgp, safi);
3979 }
3980
7f323236
DW
3981 if (peer->sort == BGP_PEER_EBGP) {
3982
2721dd61
DA
3983 /* rfc7999:
3984 * A BGP speaker receiving an announcement tagged with the
3985 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3986 * NO_EXPORT community as defined in RFC1997, or a
3987 * similar community, to prevent propagation of the
3988 * prefix outside the local AS. The community to prevent
3989 * propagation SHOULD be chosen according to the operator's
3990 * routing policy.
3991 */
9a706b42
DA
3992 if (bgp_attr_get_community(&new_attr) &&
3993 community_include(bgp_attr_get_community(&new_attr),
3994 COMMUNITY_BLACKHOLE))
aade37d7 3995 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3996
a4d82a8a
PZ
3997 /* If we receive the graceful-shutdown community from an eBGP
3998 * peer we must lower local-preference */
9a706b42
DA
3999 if (bgp_attr_get_community(&new_attr) &&
4000 community_include(bgp_attr_get_community(&new_attr),
4001 COMMUNITY_GSHUT)) {
7f323236
DW
4002 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4003 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4004
a4d82a8a
PZ
4005 /* If graceful-shutdown is configured then add the GSHUT
4006 * community to all paths received from eBGP peers */
637e5ba4 4007 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4008 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4009 }
4010
949b0f24 4011 if (pi) {
4012 pi_type = pi->type;
4013 pi_sub_type = pi->sub_type;
4014 }
4015
d62a17ae 4016 /* next hop check. */
a4d82a8a 4017 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
4018 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
4019 &new_attr, dest)) {
b4d46cc9 4020 peer->stat_pfx_nh_invalid++;
d62a17ae 4021 reason = "martian or self next-hop;";
4022 bgp_attr_flush(&new_attr);
4023 goto filtered;
4024 }
718e3744 4025
5c14a191 4026 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4027 peer->stat_pfx_nh_invalid++;
4e802e66 4028 reason = "self mac;";
4dbf2038 4029 bgp_attr_flush(&new_attr);
4e802e66
DS
4030 goto filtered;
4031 }
4032
5a78f2bc
EB
4033 if (bgp_check_role_applicability(afi, safi) &&
4034 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4035 reason = "failing otc validation";
4036 bgp_attr_flush(&new_attr);
4037 goto filtered;
4038 }
a1b773e2
DS
4039 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4040 * condition :
4041 * Suppress fib is enabled
4042 * BGP_OPT_NO_FIB is not enabled
4043 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4044 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4045 */
4046 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4047 && (sub_type == BGP_ROUTE_NORMAL)
4048 && (!bgp_option_check(BGP_OPT_NO_FIB))
4049 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4050 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4051
9cbd06e0
DA
4052 /* If maximum prefix count is configured and current prefix
4053 * count exeed it.
4054 */
4dbf2038
IR
4055 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4056 bgp_attr_flush(&new_attr);
9cbd06e0 4057 return -1;
4dbf2038
IR
4058 }
4059
4060 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4061
d62a17ae 4062 /* If the update is implicit withdraw. */
40381db7
DS
4063 if (pi) {
4064 pi->uptime = bgp_clock();
4065 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4066
9bcb3eef 4067 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4068
d62a17ae 4069 /* Same attribute comes in. */
40381db7 4070 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4071 && same_attr
d62a17ae 4072 && (!has_valid_label
40381db7 4073 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4074 num_labels * sizeof(mpls_label_t))
66ff6089 4075 == 0)) {
b4f7f45b
IR
4076 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4077 BGP_CONFIG_DAMPENING)
d62a17ae 4078 && peer->sort == BGP_PEER_EBGP
40381db7 4079 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4080 if (bgp_debug_update(peer, p, NULL, 1)) {
4081 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4082 afi, safi, prd, p, label,
4083 num_labels, addpath_id ? 1 : 0,
66ff6089 4084 addpath_id, evpn, pfx_buf,
a4d82a8a 4085 sizeof(pfx_buf));
f70c91dc 4086 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4087 pfx_buf);
4088 }
4089
9bcb3eef 4090 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4091 != BGP_DAMP_SUPPRESSED) {
40381db7 4092 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4093 safi);
9bcb3eef 4094 bgp_process(bgp, dest, afi, safi);
d62a17ae 4095 }
4096 } else /* Duplicate - odd */
4097 {
4098 if (bgp_debug_update(peer, p, NULL, 1)) {
4099 if (!peer->rcvd_attr_printed) {
4100 zlog_debug(
f70c91dc
DA
4101 "%pBP rcvd UPDATE w/ attr: %s",
4102 peer,
d62a17ae 4103 peer->rcvd_attr_str);
4104 peer->rcvd_attr_printed = 1;
4105 }
4106
4107 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4108 afi, safi, prd, p, label,
4109 num_labels, addpath_id ? 1 : 0,
66ff6089 4110 addpath_id, evpn, pfx_buf,
a4d82a8a 4111 sizeof(pfx_buf));
d62a17ae 4112 zlog_debug(
f70c91dc
DA
4113 "%pBP rcvd %s...duplicate ignored",
4114 peer, pfx_buf);
d62a17ae 4115 }
4116
4117 /* graceful restart STALE flag unset. */
40381db7 4118 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4119 bgp_path_info_unset_flag(
9bcb3eef
DS
4120 dest, pi, BGP_PATH_STALE);
4121 bgp_dest_set_defer_flag(dest, false);
4122 bgp_process(bgp, dest, afi, safi);
d62a17ae 4123 }
4124 }
4125
9bcb3eef 4126 bgp_dest_unlock_node(dest);
d62a17ae 4127 bgp_attr_unintern(&attr_new);
4128
4129 return 0;
4130 }
718e3744 4131
d62a17ae 4132 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4133 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4134 if (bgp_debug_update(peer, p, NULL, 1)) {
4135 bgp_debug_rdpfxpath2str(
a4d82a8a 4136 afi, safi, prd, p, label, num_labels,
66ff6089 4137 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4138 pfx_buf, sizeof(pfx_buf));
d62a17ae 4139 zlog_debug(
f70c91dc
DA
4140 "%pBP rcvd %s, flapped quicker than processing",
4141 peer, pfx_buf);
d62a17ae 4142 }
4143
9bcb3eef 4144 bgp_path_info_restore(dest, pi);
9146341f 4145
4146 /*
4147 * If the BGP_PATH_REMOVED flag is set, then EVPN
4148 * routes would have been unimported already when a
4149 * prior BGP withdraw processing happened. Such routes
4150 * need to be imported again, so flag accordingly.
4151 */
4152 force_evpn_import = true;
d62a17ae 4153 }
718e3744 4154
d62a17ae 4155 /* Received Logging. */
4156 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4157 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4158 num_labels, addpath_id ? 1 : 0,
66ff6089 4159 addpath_id, evpn, pfx_buf,
a4d82a8a 4160 sizeof(pfx_buf));
f70c91dc 4161 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4162 }
718e3744 4163
d62a17ae 4164 /* graceful restart STALE flag unset. */
f009ff26 4165 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4166 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4167 bgp_dest_set_defer_flag(dest, false);
f009ff26 4168 }
d62a17ae 4169
4170 /* The attribute is changed. */
9bcb3eef 4171 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4172
4173 /* implicit withdraw, decrement aggregate and pcount here.
4174 * only if update is accepted, they'll increment below.
4175 */
40381db7 4176 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4177
4178 /* Update bgp route dampening information. */
b4f7f45b 4179 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4180 && peer->sort == BGP_PEER_EBGP) {
4181 /* This is implicit withdraw so we should update
b4f7f45b
IR
4182 dampening
4183 information. */
40381db7 4184 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4185 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4186 }
49e5a4a0 4187#ifdef ENABLE_BGP_VNC
d62a17ae 4188 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4189 struct bgp_dest *pdest = NULL;
d62a17ae 4190 struct bgp_table *table = NULL;
4191
9bcb3eef
DS
4192 pdest = bgp_node_get(bgp->rib[afi][safi],
4193 (struct prefix *)prd);
4194 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4195 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4196
4197 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4198 bgp, prd, table, p, pi);
d62a17ae 4199 }
9bcb3eef 4200 bgp_dest_unlock_node(pdest);
d62a17ae 4201 }
4202 if ((afi == AFI_IP || afi == AFI_IP6)
4203 && (safi == SAFI_UNICAST)) {
40381db7 4204 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4205 /*
4206 * Implicit withdraw case.
4207 */
4208 ++vnc_implicit_withdraw;
40381db7
DS
4209 vnc_import_bgp_del_route(bgp, p, pi);
4210 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4211 }
4212 }
65efcfce 4213#endif
128ea8ab 4214
d62a17ae 4215 /* Special handling for EVPN update of an existing route. If the
4216 * extended community attribute has changed, we need to
4217 * un-import
4218 * the route using its existing extended community. It will be
4219 * subsequently processed for import with the new extended
4220 * community.
4221 */
6f8c9c11
PR
4222 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4223 && !same_attr) {
40381db7 4224 if ((pi->attr->flag
d62a17ae 4225 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4226 && (attr_new->flag
4227 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4228 int cmp;
4229
b53e67a3
DA
4230 cmp = ecommunity_cmp(
4231 bgp_attr_get_ecommunity(pi->attr),
4232 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4233 if (!cmp) {
4234 if (bgp_debug_update(peer, p, NULL, 1))
4235 zlog_debug(
4236 "Change in EXT-COMM, existing %s new %s",
4237 ecommunity_str(
b53e67a3
DA
4238 bgp_attr_get_ecommunity(
4239 pi->attr)),
d62a17ae 4240 ecommunity_str(
b53e67a3
DA
4241 bgp_attr_get_ecommunity(
4242 attr_new)));
6f8c9c11
PR
4243 if (safi == SAFI_EVPN)
4244 bgp_evpn_unimport_route(
4245 bgp, afi, safi, p, pi);
4246 else /* SAFI_MPLS_VPN */
4247 vpn_leak_to_vrf_withdraw(bgp,
4248 pi);
d62a17ae 4249 }
4250 }
4251 }
718e3744 4252
d62a17ae 4253 /* Update to new attribute. */
40381db7
DS
4254 bgp_attr_unintern(&pi->attr);
4255 pi->attr = attr_new;
d62a17ae 4256
4257 /* Update MPLS label */
4258 if (has_valid_label) {
40381db7 4259 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4260 if (extra->label != label) {
4261 memcpy(&extra->label, label,
dbd587da 4262 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4263 extra->num_labels = num_labels;
4264 }
b57ba6d2
MK
4265 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4266 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4267 }
718e3744 4268
e496b420
HS
4269 /* Update SRv6 SID */
4270 if (attr->srv6_l3vpn) {
4271 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4272 if (sid_diff(&extra->sid[0].sid,
4273 &attr->srv6_l3vpn->sid)) {
4274 sid_copy(&extra->sid[0].sid,
e496b420
HS
4275 &attr->srv6_l3vpn->sid);
4276 extra->num_sids = 1;
cc8f05df 4277
16f3db2d
RS
4278 extra->sid[0].loc_block_len = 0;
4279 extra->sid[0].loc_node_len = 0;
4280 extra->sid[0].func_len = 0;
4281 extra->sid[0].arg_len = 0;
ea7cd161
RS
4282 extra->sid[0].transposition_len = 0;
4283 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4284
4285 if (attr->srv6_l3vpn->loc_block_len != 0) {
4286 extra->sid[0].loc_block_len =
4287 attr->srv6_l3vpn->loc_block_len;
4288 extra->sid[0].loc_node_len =
4289 attr->srv6_l3vpn->loc_node_len;
4290 extra->sid[0].func_len =
4291 attr->srv6_l3vpn->func_len;
4292 extra->sid[0].arg_len =
4293 attr->srv6_l3vpn->arg_len;
ea7cd161 4294 extra->sid[0].transposition_len =
cc8f05df 4295 attr->srv6_l3vpn
ea7cd161
RS
4296 ->transposition_len;
4297 extra->sid[0].transposition_offset =
cc8f05df 4298 attr->srv6_l3vpn
ea7cd161
RS
4299 ->transposition_offset;
4300 }
e496b420
HS
4301 }
4302 } else if (attr->srv6_vpn) {
4303 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4304 if (sid_diff(&extra->sid[0].sid,
4305 &attr->srv6_vpn->sid)) {
4306 sid_copy(&extra->sid[0].sid,
4307 &attr->srv6_vpn->sid);
e496b420
HS
4308 extra->num_sids = 1;
4309 }
4310 }
4311
49e5a4a0 4312#ifdef ENABLE_BGP_VNC
d62a17ae 4313 if ((afi == AFI_IP || afi == AFI_IP6)
4314 && (safi == SAFI_UNICAST)) {
4315 if (vnc_implicit_withdraw) {
4316 /*
4317 * Add back the route with its new attributes
4318 * (e.g., nexthop).
4319 * The route is still selected, until the route
4320 * selection
4321 * queued by bgp_process actually runs. We have
4322 * to make this
4323 * update to the VNC side immediately to avoid
4324 * racing against
4325 * configuration changes (e.g., route-map
4326 * changes) which
4327 * trigger re-importation of the entire RIB.
4328 */
40381db7
DS
4329 vnc_import_bgp_add_route(bgp, p, pi);
4330 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4331 }
4332 }
65efcfce
LB
4333#endif
4334
d62a17ae 4335 /* Update bgp route dampening information. */
b4f7f45b 4336 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4337 && peer->sort == BGP_PEER_EBGP) {
4338 /* Now we do normal update dampening. */
9bcb3eef 4339 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4340 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4341 bgp_dest_unlock_node(dest);
d62a17ae 4342 return 0;
4343 }
4344 }
128ea8ab 4345
d62a17ae 4346 /* Nexthop reachability check - for unicast and
4347 * labeled-unicast.. */
7c312383
AD
4348 if (((afi == AFI_IP || afi == AFI_IP6)
4349 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4350 || (safi == SAFI_EVPN &&
4351 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4352 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4353 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4354 && !CHECK_FLAG(peer->flags,
4355 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4356 && !CHECK_FLAG(bgp->flags,
4357 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4358 connected = 1;
4359 else
4360 connected = 0;
4361
960035b2
PZ
4362 struct bgp *bgp_nexthop = bgp;
4363
40381db7
DS
4364 if (pi->extra && pi->extra->bgp_orig)
4365 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4366
7c312383
AD
4367 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4368
4369 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4370 safi, pi, NULL, connected,
4371 p)
a4d82a8a 4372 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4373 bgp_path_info_set_flag(dest, pi,
4374 BGP_PATH_VALID);
d62a17ae 4375 else {
4376 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4377 zlog_debug("%s(%pI4): NH unresolved",
4378 __func__,
4379 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4380 }
9bcb3eef 4381 bgp_path_info_unset_flag(dest, pi,
18ee8310 4382 BGP_PATH_VALID);
d62a17ae 4383 }
4384 } else
9bcb3eef 4385 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4386
49e5a4a0 4387#ifdef ENABLE_BGP_VNC
d62a17ae 4388 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4389 struct bgp_dest *pdest = NULL;
d62a17ae 4390 struct bgp_table *table = NULL;
4391
9bcb3eef
DS
4392 pdest = bgp_node_get(bgp->rib[afi][safi],
4393 (struct prefix *)prd);
4394 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4395 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4396
4397 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4398 bgp, prd, table, p, pi);
d62a17ae 4399 }
9bcb3eef 4400 bgp_dest_unlock_node(pdest);
d62a17ae 4401 }
4402#endif
718e3744 4403
d62a17ae 4404 /* If this is an EVPN route and some attribute has changed,
9146341f 4405 * or we are explicitly told to perform a route import, process
d62a17ae 4406 * route for import. If the extended community has changed, we
4407 * would
4408 * have done the un-import earlier and the import would result
4409 * in the
4410 * route getting injected into appropriate L2 VNIs. If it is
4411 * just
4412 * some other attribute change, the import will result in
4413 * updating
4414 * the attributes for the route in the VNI(s).
4415 */
9146341f 4416 if (safi == SAFI_EVPN &&
4417 (!same_attr || force_evpn_import) &&
7c312383 4418 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4419 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4420
4421 /* Process change. */
40381db7 4422 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4423
9bcb3eef
DS
4424 bgp_process(bgp, dest, afi, safi);
4425 bgp_dest_unlock_node(dest);
558d1fec 4426
ddb5b488
PZ
4427 if (SAFI_UNICAST == safi
4428 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4429 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4430
40381db7 4431 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4432 }
4433 if ((SAFI_MPLS_VPN == safi)
4434 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4435
a486300b 4436 leak_success = vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4437 }
4438
49e5a4a0 4439#ifdef ENABLE_BGP_VNC
d62a17ae 4440 if (SAFI_MPLS_VPN == safi) {
4441 mpls_label_t label_decoded = decode_label(label);
28070ee3 4442
d62a17ae 4443 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4444 type, sub_type, &label_decoded);
4445 }
4446 if (SAFI_ENCAP == safi) {
4447 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4448 type, sub_type, NULL);
4449 }
28070ee3 4450#endif
a486300b
PG
4451 if ((safi == SAFI_MPLS_VPN) &&
4452 !CHECK_FLAG(bgp->af_flags[afi][safi],
4453 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4454 !leak_success) {
4455 bgp_unlink_nexthop(pi);
4456 bgp_path_info_delete(dest, pi);
4457 }
d62a17ae 4458 return 0;
4459 } // End of implicit withdraw
718e3744 4460
d62a17ae 4461 /* Received Logging. */
4462 if (bgp_debug_update(peer, p, NULL, 1)) {
4463 if (!peer->rcvd_attr_printed) {
f70c91dc 4464 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4465 peer->rcvd_attr_str);
4466 peer->rcvd_attr_printed = 1;
4467 }
718e3744 4468
a4d82a8a 4469 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4470 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4471 pfx_buf, sizeof(pfx_buf));
f70c91dc 4472 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4473 }
718e3744 4474
d62a17ae 4475 /* Make new BGP info. */
9bcb3eef 4476 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4477
d62a17ae 4478 /* Update MPLS label */
4479 if (has_valid_label) {
18ee8310 4480 extra = bgp_path_info_extra_get(new);
8ba71050 4481 if (extra->label != label) {
dbd587da
QY
4482 memcpy(&extra->label, label,
4483 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4484 extra->num_labels = num_labels;
4485 }
b57ba6d2
MK
4486 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4487 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4488 }
718e3744 4489
e496b420
HS
4490 /* Update SRv6 SID */
4491 if (safi == SAFI_MPLS_VPN) {
4492 extra = bgp_path_info_extra_get(new);
4493 if (attr->srv6_l3vpn) {
16f3db2d 4494 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4495 extra->num_sids = 1;
cc8f05df 4496
16f3db2d
RS
4497 extra->sid[0].loc_block_len =
4498 attr->srv6_l3vpn->loc_block_len;
4499 extra->sid[0].loc_node_len =
4500 attr->srv6_l3vpn->loc_node_len;
4501 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4502 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4503 extra->sid[0].transposition_len =
4504 attr->srv6_l3vpn->transposition_len;
4505 extra->sid[0].transposition_offset =
4506 attr->srv6_l3vpn->transposition_offset;
e496b420 4507 } else if (attr->srv6_vpn) {
16f3db2d 4508 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4509 extra->num_sids = 1;
4510 }
4511 }
4512
d62a17ae 4513 /* Nexthop reachability check. */
7c312383
AD
4514 if (((afi == AFI_IP || afi == AFI_IP6)
4515 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4516 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4517 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4518 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4519 && !CHECK_FLAG(peer->flags,
4520 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4521 && !CHECK_FLAG(bgp->flags,
4522 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4523 connected = 1;
4524 else
4525 connected = 0;
4526
7c312383
AD
4527 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4528
4053e952 4529 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4530 connected, p)
a4d82a8a 4531 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4532 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4533 else {
4534 if (BGP_DEBUG(nht, NHT)) {
4535 char buf1[INET6_ADDRSTRLEN];
4536 inet_ntop(AF_INET,
4537 (const void *)&attr_new->nexthop,
4538 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4539 zlog_debug("%s(%s): NH unresolved", __func__,
4540 buf1);
d62a17ae 4541 }
9bcb3eef 4542 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4543 }
4544 } else
9bcb3eef 4545 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4546
d62a17ae 4547 /* Addpath ID */
4548 new->addpath_rx_id = addpath_id;
4549
4550 /* Increment prefix */
4551 bgp_aggregate_increment(bgp, p, new, afi, safi);
4552
4553 /* Register new BGP information. */
9bcb3eef 4554 bgp_path_info_add(dest, new);
d62a17ae 4555
4556 /* route_node_get lock */
9bcb3eef 4557 bgp_dest_unlock_node(dest);
558d1fec 4558
49e5a4a0 4559#ifdef ENABLE_BGP_VNC
d62a17ae 4560 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4561 struct bgp_dest *pdest = NULL;
d62a17ae 4562 struct bgp_table *table = NULL;
4563
9bcb3eef
DS
4564 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4565 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4566 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4567
4568 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4569 bgp, prd, table, p, new);
4570 }
9bcb3eef 4571 bgp_dest_unlock_node(pdest);
d62a17ae 4572 }
65efcfce
LB
4573#endif
4574
d62a17ae 4575 /* If this is an EVPN route, process for import. */
7c312383 4576 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4577 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4578
9bcb3eef 4579 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4580
d62a17ae 4581 /* Process change. */
9bcb3eef 4582 bgp_process(bgp, dest, afi, safi);
718e3744 4583
ddb5b488
PZ
4584 if (SAFI_UNICAST == safi
4585 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4586 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4587 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4588 }
4589 if ((SAFI_MPLS_VPN == safi)
4590 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
a486300b 4591 leak_success = vpn_leak_to_vrf_update(bgp, new);
ddb5b488 4592 }
49e5a4a0 4593#ifdef ENABLE_BGP_VNC
d62a17ae 4594 if (SAFI_MPLS_VPN == safi) {
4595 mpls_label_t label_decoded = decode_label(label);
28070ee3 4596
d62a17ae 4597 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4598 sub_type, &label_decoded);
4599 }
4600 if (SAFI_ENCAP == safi) {
4601 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4602 sub_type, NULL);
4603 }
28070ee3 4604#endif
a486300b
PG
4605 if ((safi == SAFI_MPLS_VPN) &&
4606 !CHECK_FLAG(bgp->af_flags[afi][safi],
4607 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4608 !leak_success) {
4609 bgp_unlink_nexthop(new);
4610 bgp_path_info_delete(dest, new);
4611 }
28070ee3 4612
d62a17ae 4613 return 0;
718e3744 4614
d62a17ae 4615/* This BGP update is filtered. Log the reason then update BGP
4616 entry. */
4617filtered:
9bcb3eef 4618 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4619
d62a17ae 4620 if (bgp_debug_update(peer, p, NULL, 1)) {
4621 if (!peer->rcvd_attr_printed) {
f70c91dc 4622 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4623 peer->rcvd_attr_str);
4624 peer->rcvd_attr_printed = 1;
4625 }
718e3744 4626
a4d82a8a 4627 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4628 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4629 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4630 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4631 peer, pfx_buf, reason);
d62a17ae 4632 }
128ea8ab 4633
40381db7 4634 if (pi) {
d62a17ae 4635 /* If this is an EVPN route, un-import it as it is now filtered.
4636 */
4637 if (safi == SAFI_EVPN)
40381db7 4638 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4639
ddb5b488
PZ
4640 if (SAFI_UNICAST == safi
4641 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4642 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4643
40381db7 4644 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4645 }
4646 if ((SAFI_MPLS_VPN == safi)
4647 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4648
40381db7 4649 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4650 }
4651
9bcb3eef 4652 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4653 }
4654
9bcb3eef 4655 bgp_dest_unlock_node(dest);
558d1fec 4656
49e5a4a0 4657#ifdef ENABLE_BGP_VNC
d62a17ae 4658 /*
4659 * Filtered update is treated as an implicit withdrawal (see
4660 * bgp_rib_remove()
4661 * a few lines above)
4662 */
4663 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4664 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4665 0);
4666 }
97736e32
PZ
4667#endif
4668
d62a17ae 4669 return 0;
718e3744 4670}
4671
26a3ffd6 4672int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4673 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4674 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4675 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4676{
d62a17ae 4677 struct bgp *bgp;
4678 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4679 struct bgp_dest *dest;
40381db7 4680 struct bgp_path_info *pi;
718e3744 4681
49e5a4a0 4682#ifdef ENABLE_BGP_VNC
d62a17ae 4683 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4684 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4685 0);
4686 }
28070ee3
PZ
4687#endif
4688
d62a17ae 4689 bgp = peer->bgp;
4690
4691 /* Lookup node. */
9bcb3eef 4692 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4693
4694 /* If peer is soft reconfiguration enabled. Record input packet for
4695 * further calculation.
4696 *
4697 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4698 * routes that are filtered. This tanks out Quagga RS pretty badly due
4699 * to
4700 * the iteration over all RS clients.
4701 * Since we need to remove the entry from adj_in anyway, do that first
4702 * and
4703 * if there was no entry, we don't need to do anything more.
4704 */
4705 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4706 && peer != bgp->peer_self)
9bcb3eef 4707 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4708 peer->stat_pfx_dup_withdraw++;
4709
d62a17ae 4710 if (bgp_debug_update(peer, p, NULL, 1)) {
4711 bgp_debug_rdpfxpath2str(
a4d82a8a 4712 afi, safi, prd, p, label, num_labels,
6c995628
AD
4713 addpath_id ? 1 : 0, addpath_id, NULL,
4714 pfx_buf, sizeof(pfx_buf));
d62a17ae 4715 zlog_debug(
4716 "%s withdrawing route %s not in adj-in",
4717 peer->host, pfx_buf);
4718 }
9bcb3eef 4719 bgp_dest_unlock_node(dest);
d62a17ae 4720 return 0;
4721 }
cd808e74 4722
d62a17ae 4723 /* Lookup withdrawn route. */
9bcb3eef 4724 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4725 if (pi->peer == peer && pi->type == type
4726 && pi->sub_type == sub_type
4727 && pi->addpath_rx_id == addpath_id)
d62a17ae 4728 break;
4729
4730 /* Logging. */
4731 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4732 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4733 addpath_id ? 1 : 0, addpath_id, NULL,
4734 pfx_buf, sizeof(pfx_buf));
f70c91dc 4735 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4736 pfx_buf);
4737 }
718e3744 4738
d62a17ae 4739 /* Withdraw specified route from routing table. */
40381db7 4740 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4741 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4742 if (SAFI_UNICAST == safi
4743 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4744 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4745 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4746 }
4747 if ((SAFI_MPLS_VPN == safi)
4748 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4749
40381db7 4750 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4751 }
4752 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4753 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4754 addpath_id ? 1 : 0, addpath_id, NULL,
4755 pfx_buf, sizeof(pfx_buf));
d62a17ae 4756 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4757 }
718e3744 4758
d62a17ae 4759 /* Unlock bgp_node_get() lock. */
9bcb3eef 4760 bgp_dest_unlock_node(dest);
d62a17ae 4761
4762 return 0;
718e3744 4763}
6b0655a2 4764
d62a17ae 4765void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4766 int withdraw)
718e3744 4767{
d62a17ae 4768 struct update_subgroup *subgrp;
4769 subgrp = peer_subgroup(peer, afi, safi);
4770 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4771}
6182d65b 4772
718e3744 4773
3f9c7369
DS
4774/*
4775 * bgp_stop_announce_route_timer
4776 */
d62a17ae 4777void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4778{
d62a17ae 4779 if (!paf->t_announce_route)
4780 return;
4781
c3aaa89a 4782 THREAD_OFF(paf->t_announce_route);
718e3744 4783}
6b0655a2 4784
3f9c7369
DS
4785/*
4786 * bgp_announce_route_timer_expired
4787 *
4788 * Callback that is invoked when the route announcement timer for a
4789 * peer_af expires.
4790 */
cc9f21da 4791static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4792{
d62a17ae 4793 struct peer_af *paf;
4794 struct peer *peer;
558d1fec 4795
d62a17ae 4796 paf = THREAD_ARG(t);
4797 peer = paf->peer;
718e3744 4798
feb17238 4799 if (!peer_established(peer))
cc9f21da 4800 return;
3f9c7369 4801
d62a17ae 4802 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4803 return;
3f9c7369 4804
d62a17ae 4805 peer_af_announce_route(paf, 1);
c5aec50b
MK
4806
4807 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4808 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4809}
4810
3f9c7369
DS
4811/*
4812 * bgp_announce_route
4813 *
4814 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4815 *
4816 * if force is true we will force an update even if the update
4817 * limiting code is attempted to kick in.
3f9c7369 4818 */
e1a32ec1 4819void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4820{
4821 struct peer_af *paf;
4822 struct update_subgroup *subgrp;
4823
4824 paf = peer_af_find(peer, afi, safi);
4825 if (!paf)
4826 return;
4827 subgrp = PAF_SUBGRP(paf);
4828
4829 /*
4830 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4831 * or a refresh has already been triggered.
4832 */
4833 if (!subgrp || paf->t_announce_route)
4834 return;
4835
e1a32ec1
DS
4836 if (force)
4837 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4838
d62a17ae 4839 /*
4840 * Start a timer to stagger/delay the announce. This serves
4841 * two purposes - announcement can potentially be combined for
4842 * multiple peers and the announcement doesn't happen in the
4843 * vty context.
4844 */
4845 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4846 (subgrp->peer_count == 1)
4847 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4848 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4849 &paf->t_announce_route);
3f9c7369
DS
4850}
4851
4852/*
4853 * Announce routes from all AF tables to a peer.
4854 *
4855 * This should ONLY be called when there is a need to refresh the
4856 * routes to the peer based on a policy change for this peer alone
4857 * or a route refresh request received from the peer.
4858 * The operation will result in splitting the peer from its existing
4859 * subgroups and putting it in new subgroups.
4860 */
d62a17ae 4861void bgp_announce_route_all(struct peer *peer)
718e3744 4862{
d62a17ae 4863 afi_t afi;
4864 safi_t safi;
4865
05c7a1cc 4866 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4867 bgp_announce_route(peer, afi, safi, false);
718e3744 4868}
6b0655a2 4869
46aeabed
LS
4870/* Flag or unflag bgp_dest to determine whether it should be treated by
4871 * bgp_soft_reconfig_table_task.
4872 * Flag if flag is true. Unflag if flag is false.
4873 */
4874static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4875{
4876 struct bgp_dest *dest;
4877 struct bgp_adj_in *ain;
4878
4879 if (!table)
4880 return;
4881
4882 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4883 for (ain = dest->adj_in; ain; ain = ain->next) {
4884 if (ain->peer != NULL)
4885 break;
4886 }
4887 if (flag && ain != NULL && ain->peer != NULL)
4888 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4889 else
4890 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4891 }
4892}
4893
4894static int bgp_soft_reconfig_table_update(struct peer *peer,
4895 struct bgp_dest *dest,
4896 struct bgp_adj_in *ain, afi_t afi,
4897 safi_t safi, struct prefix_rd *prd)
4898{
4899 struct bgp_path_info *pi;
4900 uint32_t num_labels = 0;
4901 mpls_label_t *label_pnt = NULL;
4902 struct bgp_route_evpn evpn;
4903
4904 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4905 if (pi->peer == peer)
4906 break;
4907
4908 if (pi && pi->extra)
4909 num_labels = pi->extra->num_labels;
4910 if (num_labels)
4911 label_pnt = &pi->extra->label[0];
4912 if (pi)
4913 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4914 sizeof(evpn));
4915 else
4916 memset(&evpn, 0, sizeof(evpn));
4917
4918 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4919 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4920 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4921 &evpn);
4922}
4923
d62a17ae 4924static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4925 struct bgp_table *table,
4926 struct prefix_rd *prd)
718e3744 4927{
d62a17ae 4928 int ret;
9bcb3eef 4929 struct bgp_dest *dest;
d62a17ae 4930 struct bgp_adj_in *ain;
718e3744 4931
d62a17ae 4932 if (!table)
4933 table = peer->bgp->rib[afi][safi];
718e3744 4934
9bcb3eef
DS
4935 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4936 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4937 if (ain->peer != peer)
4938 continue;
8692c506 4939
46aeabed
LS
4940 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4941 afi, safi, prd);
ea47320b
DL
4942
4943 if (ret < 0) {
9bcb3eef 4944 bgp_dest_unlock_node(dest);
ea47320b 4945 return;
d62a17ae 4946 }
4947 }
718e3744 4948}
4949
46aeabed
LS
4950/* Do soft reconfig table per bgp table.
4951 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4952 * when BGP_NODE_SOFT_RECONFIG is set,
4953 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4954 * Schedule a new thread to continue the job.
4955 * Without splitting the full job into several part,
4956 * vtysh waits for the job to finish before responding to a BGP command
4957 */
cc9f21da 4958static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4959{
4960 uint32_t iter, max_iter;
4961 int ret;
4962 struct bgp_dest *dest;
4963 struct bgp_adj_in *ain;
4964 struct peer *peer;
4965 struct bgp_table *table;
4966 struct prefix_rd *prd;
4967 struct listnode *node, *nnode;
4968
4969 table = THREAD_ARG(thread);
4970 prd = NULL;
4971
4972 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4973 if (table->soft_reconfig_init) {
4974 /* first call of the function with a new srta structure.
4975 * Don't do any treatment this time on nodes
4976 * in order vtysh to respond quickly
4977 */
4978 max_iter = 0;
4979 }
4980
4981 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4982 dest = bgp_route_next(dest)) {
4983 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4984 continue;
4985
4986 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4987
4988 for (ain = dest->adj_in; ain; ain = ain->next) {
4989 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4990 nnode, peer)) {
4991 if (ain->peer != peer)
4992 continue;
4993
4994 ret = bgp_soft_reconfig_table_update(
4995 peer, dest, ain, table->afi,
4996 table->safi, prd);
4997 iter++;
4998
4999 if (ret < 0) {
5000 bgp_dest_unlock_node(dest);
5001 listnode_delete(
5002 table->soft_reconfig_peers,
5003 peer);
5004 bgp_announce_route(peer, table->afi,
e1a32ec1 5005 table->safi, false);
46aeabed
LS
5006 if (list_isempty(
5007 table->soft_reconfig_peers)) {
5008 list_delete(
5009 &table->soft_reconfig_peers);
5010 bgp_soft_reconfig_table_flag(
5011 table, false);
cc9f21da 5012 return;
46aeabed
LS
5013 }
5014 }
5015 }
5016 }
5017 }
5018
5019 /* we're either starting the initial iteration,
5020 * or we're going to continue an ongoing iteration
5021 */
5022 if (dest || table->soft_reconfig_init) {
5023 table->soft_reconfig_init = false;
5024 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5025 table, 0, &table->soft_reconfig_thread);
cc9f21da 5026 return;
46aeabed
LS
5027 }
5028 /* we're done, clean up the background iteration context info and
5029 schedule route annoucement
5030 */
5031 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5032 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5033 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5034 }
5035
5036 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5037}
5038
5039
5040/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5041 * and peer.
5042 * - bgp cannot be NULL
5043 * - if table and peer are NULL, cancel all threads within the bgp instance
5044 * - if table is NULL and peer is not,
5045 * remove peer in all threads within the bgp instance
5046 * - if peer is NULL, cancel all threads matching table within the bgp instance
5047 */
5048void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5049 const struct bgp_table *table,
5050 const struct peer *peer)
5051{
5052 struct peer *npeer;
5053 struct listnode *node, *nnode;
5054 int afi, safi;
5055 struct bgp_table *ntable;
5056
5057 if (!bgp)
5058 return;
5059
5060 FOREACH_AFI_SAFI (afi, safi) {
5061 ntable = bgp->rib[afi][safi];
5062 if (!ntable)
5063 continue;
5064 if (table && table != ntable)
5065 continue;
5066
5067 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5068 npeer)) {
5069 if (peer && peer != npeer)
5070 continue;
5071 listnode_delete(ntable->soft_reconfig_peers, npeer);
5072 }
5073
5074 if (!ntable->soft_reconfig_peers
5075 || !list_isempty(ntable->soft_reconfig_peers))
5076 continue;
5077
5078 list_delete(&ntable->soft_reconfig_peers);
5079 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5080 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5081 }
5082}
5083
d62a17ae 5084void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5085{
9bcb3eef 5086 struct bgp_dest *dest;
d62a17ae 5087 struct bgp_table *table;
46aeabed
LS
5088 struct listnode *node, *nnode;
5089 struct peer *npeer;
5090 struct peer_af *paf;
718e3744 5091
feb17238 5092 if (!peer_established(peer))
d62a17ae 5093 return;
718e3744 5094
d62a17ae 5095 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5096 && (safi != SAFI_EVPN)) {
5097 table = peer->bgp->rib[afi][safi];
5098 if (!table)
5099 return;
5100
5101 table->soft_reconfig_init = true;
5102
5103 if (!table->soft_reconfig_peers)
5104 table->soft_reconfig_peers = list_new();
5105 npeer = NULL;
5106 /* add peer to the table soft_reconfig_peers if not already
5107 * there
5108 */
5109 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5110 npeer)) {
5111 if (peer == npeer)
5112 break;
5113 }
5114 if (peer != npeer)
5115 listnode_add(table->soft_reconfig_peers, peer);
5116
5117 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5118 * on table would start back at the beginning.
5119 */
5120 bgp_soft_reconfig_table_flag(table, true);
5121
5122 if (!table->soft_reconfig_thread)
5123 thread_add_event(bm->master,
5124 bgp_soft_reconfig_table_task, table, 0,
5125 &table->soft_reconfig_thread);
5126 /* Cancel bgp_announce_route_timer_expired threads.
5127 * bgp_announce_route_timer_expired threads have been scheduled
5128 * to announce routes as soon as the soft_reconfigure process
5129 * finishes.
5130 * In this case, soft_reconfigure is also scheduled by using
5131 * a thread but is planned after the
5132 * bgp_announce_route_timer_expired threads. It means that,
5133 * without cancelling the threads, the route announcement task
5134 * would run before the soft reconfiguration one. That would
5135 * useless and would block vtysh during several seconds. Route
5136 * announcements are rescheduled as soon as the soft_reconfigure
5137 * process finishes.
5138 */
5139 paf = peer_af_find(peer, afi, safi);
5140 if (paf)
5141 bgp_stop_announce_route_timer(paf);
5142 } else
9bcb3eef
DS
5143 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5144 dest = bgp_route_next(dest)) {
5145 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5146
b54892e0
DS
5147 if (table == NULL)
5148 continue;
8692c506 5149
9bcb3eef 5150 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5151 struct prefix_rd prd;
5152
5153 prd.family = AF_UNSPEC;
5154 prd.prefixlen = 64;
5155 memcpy(&prd.val, p->u.val, 8);
5156
5157 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5158 }
718e3744 5159}
6b0655a2 5160
228da428 5161
d62a17ae 5162struct bgp_clear_node_queue {
9bcb3eef 5163 struct bgp_dest *dest;
228da428
CC
5164};
5165
d62a17ae 5166static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5167{
d62a17ae 5168 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5169 struct bgp_dest *dest = cnq->dest;
d62a17ae 5170 struct peer *peer = wq->spec.data;
40381db7 5171 struct bgp_path_info *pi;
3103e8d2 5172 struct bgp *bgp;
9bcb3eef
DS
5173 afi_t afi = bgp_dest_table(dest)->afi;
5174 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5175
9bcb3eef 5176 assert(dest && peer);
3103e8d2 5177 bgp = peer->bgp;
d62a17ae 5178
5179 /* It is possible that we have multiple paths for a prefix from a peer
5180 * if that peer is using AddPath.
5181 */
9bcb3eef 5182 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5183 if (pi->peer != peer)
ea47320b
DL
5184 continue;
5185
5186 /* graceful restart STALE flag set. */
9af52ccf
DA
5187 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5188 && peer->nsf[afi][safi])
5189 || CHECK_FLAG(peer->af_sflags[afi][safi],
5190 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5191 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5192 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5193 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5194 else {
5195 /* If this is an EVPN route, process for
5196 * un-import. */
5197 if (safi == SAFI_EVPN)
9bcb3eef
DS
5198 bgp_evpn_unimport_route(
5199 bgp, afi, safi,
5200 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5201 /* Handle withdraw for VRF route-leaking and L3VPN */
5202 if (SAFI_UNICAST == safi
5203 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5204 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5205 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5206 bgp, pi);
960035b2 5207 }
3103e8d2 5208 if (SAFI_MPLS_VPN == safi &&
960035b2 5209 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5210 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5211 }
3103e8d2 5212
9bcb3eef 5213 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5214 }
ea47320b 5215 }
d62a17ae 5216 return WQ_SUCCESS;
200df115 5217}
5218
d62a17ae 5219static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5220{
d62a17ae 5221 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5222 struct bgp_dest *dest = cnq->dest;
5223 struct bgp_table *table = bgp_dest_table(dest);
228da428 5224
9bcb3eef 5225 bgp_dest_unlock_node(dest);
d62a17ae 5226 bgp_table_unlock(table);
5227 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5228}
5229
d62a17ae 5230static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5231{
d62a17ae 5232 struct peer *peer = wq->spec.data;
64e580a7 5233
d62a17ae 5234 /* Tickle FSM to start moving again */
5235 BGP_EVENT_ADD(peer, Clearing_Completed);
5236
5237 peer_unlock(peer); /* bgp_clear_route */
200df115 5238}
718e3744 5239
d62a17ae 5240static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5241{
d62a17ae 5242 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5243
5244 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5245#undef CLEAR_QUEUE_NAME_LEN
5246
0ce1ca80 5247 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5248 peer->clear_node_queue->spec.hold = 10;
5249 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5250 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5251 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5252 peer->clear_node_queue->spec.max_retries = 0;
5253
5254 /* we only 'lock' this peer reference when the queue is actually active
5255 */
5256 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5257}
5258
d62a17ae 5259static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5260 struct bgp_table *table)
65ca75e0 5261{
9bcb3eef 5262 struct bgp_dest *dest;
b6c386bb 5263 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5264
d62a17ae 5265 if (!table)
5266 table = peer->bgp->rib[afi][safi];
dc83d712 5267
d62a17ae 5268 /* If still no table => afi/safi isn't configured at all or smth. */
5269 if (!table)
5270 return;
dc83d712 5271
9bcb3eef 5272 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5273 struct bgp_path_info *pi, *next;
d62a17ae 5274 struct bgp_adj_in *ain;
5275 struct bgp_adj_in *ain_next;
5276
5277 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5278 * queued for every clearing peer, regardless of whether it is
5279 * relevant to the peer at hand.
5280 *
5281 * Overview: There are 3 different indices which need to be
5282 * scrubbed, potentially, when a peer is removed:
5283 *
5284 * 1 peer's routes visible via the RIB (ie accepted routes)
5285 * 2 peer's routes visible by the (optional) peer's adj-in index
5286 * 3 other routes visible by the peer's adj-out index
5287 *
5288 * 3 there is no hurry in scrubbing, once the struct peer is
5289 * removed from bgp->peer, we could just GC such deleted peer's
5290 * adj-outs at our leisure.
5291 *
5292 * 1 and 2 must be 'scrubbed' in some way, at least made
5293 * invisible via RIB index before peer session is allowed to be
5294 * brought back up. So one needs to know when such a 'search' is
5295 * complete.
5296 *
5297 * Ideally:
5298 *
5299 * - there'd be a single global queue or a single RIB walker
5300 * - rather than tracking which route_nodes still need to be
5301 * examined on a peer basis, we'd track which peers still
5302 * aren't cleared
5303 *
5304 * Given that our per-peer prefix-counts now should be reliable,
5305 * this may actually be achievable. It doesn't seem to be a huge
5306 * problem at this time,
5307 *
5308 * It is possible that we have multiple paths for a prefix from
5309 * a peer
5310 * if that peer is using AddPath.
5311 */
9bcb3eef 5312 ain = dest->adj_in;
d62a17ae 5313 while (ain) {
5314 ain_next = ain->next;
5315
6a840fd9 5316 if (ain->peer == peer)
9bcb3eef 5317 bgp_adj_in_remove(dest, ain);
d62a17ae 5318
5319 ain = ain_next;
5320 }
5321
9bcb3eef 5322 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5323 next = pi->next;
5324 if (pi->peer != peer)
d62a17ae 5325 continue;
5326
5327 if (force)
9bcb3eef 5328 bgp_path_info_reap(dest, pi);
d62a17ae 5329 else {
5330 struct bgp_clear_node_queue *cnq;
5331
5332 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5333 bgp_table_lock(bgp_dest_table(dest));
5334 bgp_dest_lock_node(dest);
d62a17ae 5335 cnq = XCALLOC(
5336 MTYPE_BGP_CLEAR_NODE_QUEUE,
5337 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5338 cnq->dest = dest;
d62a17ae 5339 work_queue_add(peer->clear_node_queue, cnq);
5340 break;
5341 }
5342 }
5343 }
5344 return;
5345}
5346
5347void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5348{
9bcb3eef 5349 struct bgp_dest *dest;
d62a17ae 5350 struct bgp_table *table;
5351
5352 if (peer->clear_node_queue == NULL)
5353 bgp_clear_node_queue_init(peer);
5354
5355 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5356 * Idle until it receives a Clearing_Completed event. This protects
5357 * against peers which flap faster than we can we clear, which could
5358 * lead to:
5359 *
5360 * a) race with routes from the new session being installed before
5361 * clear_route_node visits the node (to delete the route of that
5362 * peer)
5363 * b) resource exhaustion, clear_route_node likely leads to an entry
5364 * on the process_main queue. Fast-flapping could cause that queue
5365 * to grow and grow.
5366 */
5367
5368 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5369 * the unlock will happen upon work-queue completion; other wise, the
5370 * unlock happens at the end of this function.
5371 */
5372 if (!peer->clear_node_queue->thread)
5373 peer_lock(peer);
5374
5375 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5376 bgp_clear_route_table(peer, afi, safi, NULL);
5377 else
9bcb3eef
DS
5378 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5379 dest = bgp_route_next(dest)) {
5380 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5381 if (!table)
5382 continue;
5383
5384 bgp_clear_route_table(peer, afi, safi, table);
5385 }
d62a17ae 5386
5387 /* unlock if no nodes got added to the clear-node-queue. */
5388 if (!peer->clear_node_queue->thread)
5389 peer_unlock(peer);
718e3744 5390}
d62a17ae 5391
5392void bgp_clear_route_all(struct peer *peer)
718e3744 5393{
d62a17ae 5394 afi_t afi;
5395 safi_t safi;
718e3744 5396
05c7a1cc
QY
5397 FOREACH_AFI_SAFI (afi, safi)
5398 bgp_clear_route(peer, afi, safi);
65efcfce 5399
49e5a4a0 5400#ifdef ENABLE_BGP_VNC
d62a17ae 5401 rfapiProcessPeerDown(peer);
65efcfce 5402#endif
718e3744 5403}
5404
d62a17ae 5405void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5406{
d62a17ae 5407 struct bgp_table *table;
9bcb3eef 5408 struct bgp_dest *dest;
d62a17ae 5409 struct bgp_adj_in *ain;
5410 struct bgp_adj_in *ain_next;
718e3744 5411
d62a17ae 5412 table = peer->bgp->rib[afi][safi];
718e3744 5413
d62a17ae 5414 /* It is possible that we have multiple paths for a prefix from a peer
5415 * if that peer is using AddPath.
5416 */
9bcb3eef
DS
5417 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5418 ain = dest->adj_in;
43143c8f 5419
d62a17ae 5420 while (ain) {
5421 ain_next = ain->next;
43143c8f 5422
6a840fd9 5423 if (ain->peer == peer)
9bcb3eef 5424 bgp_adj_in_remove(dest, ain);
43143c8f 5425
d62a17ae 5426 ain = ain_next;
5427 }
5428 }
718e3744 5429}
93406d87 5430
1479ed2f
DA
5431/* If any of the routes from the peer have been marked with the NO_LLGR
5432 * community, either as sent by the peer, or as the result of a configured
5433 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5434 * operation of [RFC4271].
5435 */
d62a17ae 5436void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5437{
9bcb3eef 5438 struct bgp_dest *dest;
40381db7 5439 struct bgp_path_info *pi;
d62a17ae 5440 struct bgp_table *table;
5441
9af52ccf 5442 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5443 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5444 dest = bgp_route_next(dest)) {
5445 struct bgp_dest *rm;
d62a17ae 5446
5447 /* look for neighbor in tables */
9bcb3eef 5448 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5449 if (!table)
ea47320b
DL
5450 continue;
5451
5452 for (rm = bgp_table_top(table); rm;
5453 rm = bgp_route_next(rm))
9bcb3eef 5454 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5455 pi = pi->next) {
40381db7 5456 if (pi->peer != peer)
ea47320b 5457 continue;
1479ed2f
DA
5458 if (CHECK_FLAG(
5459 peer->af_sflags[afi][safi],
5460 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5461 bgp_attr_get_community(pi->attr) &&
1479ed2f 5462 !community_include(
9a706b42
DA
5463 bgp_attr_get_community(
5464 pi->attr),
1479ed2f 5465 COMMUNITY_NO_LLGR))
e3015d91 5466 continue;
40381db7 5467 if (!CHECK_FLAG(pi->flags,
1defdda8 5468 BGP_PATH_STALE))
e3015d91 5469 continue;
ea47320b 5470
641065d4
KM
5471 /*
5472 * If this is VRF leaked route
5473 * process for withdraw.
5474 */
5475 if (pi->sub_type ==
5476 BGP_ROUTE_IMPORTED &&
5477 peer->bgp->inst_type ==
5478 BGP_INSTANCE_TYPE_DEFAULT)
5479 vpn_leak_to_vrf_withdraw(
5480 peer->bgp, pi);
5481
40381db7 5482 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5483 break;
5484 }
d62a17ae 5485 }
5486 } else {
9bcb3eef
DS
5487 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5488 dest = bgp_route_next(dest))
5489 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5490 pi = pi->next) {
40381db7 5491 if (pi->peer != peer)
ea47320b 5492 continue;
1479ed2f
DA
5493 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5494 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5495 bgp_attr_get_community(pi->attr) &&
5496 !community_include(
5497 bgp_attr_get_community(pi->attr),
5498 COMMUNITY_NO_LLGR))
e3015d91 5499 continue;
40381db7 5500 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5501 continue;
641065d4
KM
5502 if (safi == SAFI_UNICAST &&
5503 (peer->bgp->inst_type ==
5504 BGP_INSTANCE_TYPE_VRF ||
5505 peer->bgp->inst_type ==
5506 BGP_INSTANCE_TYPE_DEFAULT))
5507 vpn_leak_from_vrf_withdraw(
5508 bgp_get_default(), peer->bgp,
5509 pi);
5510
9bcb3eef 5511 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5512 break;
5513 }
d62a17ae 5514 }
93406d87 5515}
6b0655a2 5516
9af52ccf
DA
5517void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5518{
5519 struct bgp_dest *dest, *ndest;
5520 struct bgp_path_info *pi;
5521 struct bgp_table *table;
5522
5523 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5524 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5525 dest = bgp_route_next(dest)) {
5526 table = bgp_dest_get_bgp_table_info(dest);
5527 if (!table)
5528 continue;
5529
5530 for (ndest = bgp_table_top(table); ndest;
5531 ndest = bgp_route_next(ndest)) {
5532 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5533 pi = pi->next) {
5534 if (pi->peer != peer)
5535 continue;
5536
5537 if ((CHECK_FLAG(
5538 peer->af_sflags[afi][safi],
5539 PEER_STATUS_ENHANCED_REFRESH))
5540 && !CHECK_FLAG(pi->flags,
5541 BGP_PATH_STALE)
5542 && !CHECK_FLAG(
5543 pi->flags,
5544 BGP_PATH_UNUSEABLE)) {
5545 if (bgp_debug_neighbor_events(
5546 peer))
5547 zlog_debug(
5548 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5549 peer->host,
5550 afi2str(afi),
5551 safi2str(safi),
5552 bgp_dest_get_prefix(
5553 ndest));
5554
5555 bgp_path_info_set_flag(
5556 ndest, pi,
5557 BGP_PATH_STALE);
5558 }
5559 }
5560 }
5561 }
5562 } else {
5563 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5564 dest = bgp_route_next(dest)) {
5565 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5566 pi = pi->next) {
5567 if (pi->peer != peer)
5568 continue;
5569
5570 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5571 PEER_STATUS_ENHANCED_REFRESH))
5572 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5573 && !CHECK_FLAG(pi->flags,
5574 BGP_PATH_UNUSEABLE)) {
5575 if (bgp_debug_neighbor_events(peer))
5576 zlog_debug(
5577 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5578 peer->host,
5579 afi2str(afi),
5580 safi2str(safi),
5581 bgp_dest_get_prefix(
5582 dest));
5583
5584 bgp_path_info_set_flag(dest, pi,
5585 BGP_PATH_STALE);
5586 }
5587 }
5588 }
5589 }
5590}
5591
3dc339cd 5592bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5593{
e0df4c04 5594 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5595 return true;
e0df4c04 5596
9dac9fc8
DA
5597 if (peer->sort == BGP_PEER_EBGP
5598 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5599 || FILTER_LIST_OUT_NAME(filter)
5600 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5601 return true;
5602 return false;
9dac9fc8
DA
5603}
5604
3dc339cd 5605bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5606{
e0df4c04 5607 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5608 return true;
e0df4c04 5609
9dac9fc8
DA
5610 if (peer->sort == BGP_PEER_EBGP
5611 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5612 || FILTER_LIST_IN_NAME(filter)
5613 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5614 return true;
5615 return false;
9dac9fc8
DA
5616}
5617
568e10ca 5618static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5619 safi_t safi)
bb86c601 5620{
9bcb3eef 5621 struct bgp_dest *dest;
40381db7 5622 struct bgp_path_info *pi;
4b7e6066 5623 struct bgp_path_info *next;
bb86c601 5624
9bcb3eef
DS
5625 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5626 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5627 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5628
40381db7 5629 next = pi->next;
1b7bb747
CS
5630
5631 /* Unimport EVPN routes from VRFs */
5632 if (safi == SAFI_EVPN)
5633 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5634 SAFI_EVPN, p, pi);
1b7bb747 5635
40381db7
DS
5636 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5637 && pi->type == ZEBRA_ROUTE_BGP
5638 && (pi->sub_type == BGP_ROUTE_NORMAL
5639 || pi->sub_type == BGP_ROUTE_AGGREGATE
5640 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5641
d62a17ae 5642 if (bgp_fibupd_safi(safi))
b54892e0 5643 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5644 }
9514b37d 5645
9bcb3eef 5646 bgp_path_info_reap(dest, pi);
d62a17ae 5647 }
bb86c601
LB
5648}
5649
718e3744 5650/* Delete all kernel routes. */
d62a17ae 5651void bgp_cleanup_routes(struct bgp *bgp)
5652{
5653 afi_t afi;
9bcb3eef 5654 struct bgp_dest *dest;
67009e22 5655 struct bgp_table *table;
d62a17ae 5656
5657 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5658 if (afi == AFI_L2VPN)
5659 continue;
568e10ca 5660 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5661 SAFI_UNICAST);
d62a17ae 5662 /*
5663 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5664 */
5665 if (afi != AFI_L2VPN) {
5666 safi_t safi;
5667 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5668 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5669 dest = bgp_route_next(dest)) {
5670 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5671 if (table != NULL) {
5672 bgp_cleanup_table(bgp, table, safi);
5673 bgp_table_finish(&table);
9bcb3eef
DS
5674 bgp_dest_set_bgp_table_info(dest, NULL);
5675 bgp_dest_unlock_node(dest);
d62a17ae 5676 }
5677 }
5678 safi = SAFI_ENCAP;
9bcb3eef
DS
5679 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5680 dest = bgp_route_next(dest)) {
5681 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5682 if (table != NULL) {
5683 bgp_cleanup_table(bgp, table, safi);
5684 bgp_table_finish(&table);
9bcb3eef
DS
5685 bgp_dest_set_bgp_table_info(dest, NULL);
5686 bgp_dest_unlock_node(dest);
d62a17ae 5687 }
5688 }
5689 }
5690 }
9bcb3eef
DS
5691 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5692 dest = bgp_route_next(dest)) {
5693 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5694 if (table != NULL) {
5695 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5696 bgp_table_finish(&table);
9bcb3eef
DS
5697 bgp_dest_set_bgp_table_info(dest, NULL);
5698 bgp_dest_unlock_node(dest);
d62a17ae 5699 }
bb86c601 5700 }
718e3744 5701}
5702
d62a17ae 5703void bgp_reset(void)
718e3744 5704{
d62a17ae 5705 vty_reset();
5706 bgp_zclient_reset();
5707 access_list_reset();
5708 prefix_list_reset();
718e3744 5709}
6b0655a2 5710
be92fc9f 5711bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5712{
d62a17ae 5713 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5714 && CHECK_FLAG(peer->af_cap[afi][safi],
5715 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5716}
5717
718e3744 5718/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5719 value. */
d62a17ae 5720int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5721 struct bgp_nlri *packet)
5722{
d7c0a89a
QY
5723 uint8_t *pnt;
5724 uint8_t *lim;
d62a17ae 5725 struct prefix p;
5726 int psize;
5727 int ret;
5728 afi_t afi;
5729 safi_t safi;
be92fc9f 5730 bool addpath_capable;
d7c0a89a 5731 uint32_t addpath_id;
d62a17ae 5732
d62a17ae 5733 pnt = packet->nlri;
5734 lim = pnt + packet->length;
5735 afi = packet->afi;
5736 safi = packet->safi;
5737 addpath_id = 0;
be92fc9f 5738 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5739
5740 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5741 syntactic validity. If the field is syntactically incorrect,
5742 then the Error Subcode is set to Invalid Network Field. */
5743 for (; pnt < lim; pnt += psize) {
5744 /* Clear prefix structure. */
6006b807 5745 memset(&p, 0, sizeof(p));
d62a17ae 5746
be92fc9f 5747 if (addpath_capable) {
d62a17ae 5748
5749 /* When packet overflow occurs return immediately. */
761ed665 5750 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5751 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5752
a3a850a1 5753 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5754 addpath_id = ntohl(addpath_id);
d62a17ae 5755 pnt += BGP_ADDPATH_ID_LEN;
5756 }
718e3744 5757
d62a17ae 5758 /* Fetch prefix length. */
5759 p.prefixlen = *pnt++;
5760 /* afi/safi validity already verified by caller,
5761 * bgp_update_receive */
5762 p.family = afi2family(afi);
5763
5764 /* Prefix length check. */
5765 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5766 flog_err(
e50f7cfd 5767 EC_BGP_UPDATE_RCV,
14454c9f 5768 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5769 peer->host, p.prefixlen, packet->afi);
513386b5 5770 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5771 }
6b0655a2 5772
d62a17ae 5773 /* Packet size overflow check. */
5774 psize = PSIZE(p.prefixlen);
5775
5776 /* When packet overflow occur return immediately. */
5777 if (pnt + psize > lim) {
af4c2728 5778 flog_err(
e50f7cfd 5779 EC_BGP_UPDATE_RCV,
d62a17ae 5780 "%s [Error] Update packet error (prefix length %d overflows packet)",
5781 peer->host, p.prefixlen);
513386b5 5782 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5783 }
5784
5785 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5786 * prefix for the v4 and v6 afi's and unicast/multicast */
5787 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5788 flog_err(
e50f7cfd 5789 EC_BGP_UPDATE_RCV,
d62a17ae 5790 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5791 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5792 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5793 }
5794
5795 /* Fetch prefix from NLRI packet. */
a85297a7 5796 memcpy(p.u.val, pnt, psize);
d62a17ae 5797
5798 /* Check address. */
5799 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5800 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5801 /* From RFC4271 Section 6.3:
5802 *
5803 * If a prefix in the NLRI field is semantically
5804 * incorrect
5805 * (e.g., an unexpected multicast IP address),
5806 * an error SHOULD
5807 * be logged locally, and the prefix SHOULD be
5808 * ignored.
a4d82a8a 5809 */
af4c2728 5810 flog_err(
e50f7cfd 5811 EC_BGP_UPDATE_RCV,
23d0a753
DA
5812 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5813 peer->host, &p.u.prefix4);
d62a17ae 5814 continue;
5815 }
5816 }
5817
5818 /* Check address. */
5819 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5820 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5821 flog_err(
e50f7cfd 5822 EC_BGP_UPDATE_RCV,
c0d72166
DS
5823 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5824 peer->host, &p.u.prefix6);
d62a17ae 5825
5826 continue;
5827 }
5828 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5829 flog_err(
e50f7cfd 5830 EC_BGP_UPDATE_RCV,
c0d72166
DS
5831 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5832 peer->host, &p.u.prefix6);
d62a17ae 5833
5834 continue;
5835 }
5836 }
5837
5838 /* Normal process. */
5839 if (attr)
5840 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5841 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5842 NULL, NULL, 0, 0, NULL);
d62a17ae 5843 else
5844 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5845 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5846 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5847 NULL);
d62a17ae 5848
513386b5
DA
5849 /* Do not send BGP notification twice when maximum-prefix count
5850 * overflow. */
5851 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5852 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5853
5854 /* Address family configuration mismatch. */
d62a17ae 5855 if (ret < 0)
513386b5 5856 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5857 }
5858
5859 /* Packet length consistency check. */
5860 if (pnt != lim) {
af4c2728 5861 flog_err(
e50f7cfd 5862 EC_BGP_UPDATE_RCV,
d62a17ae 5863 "%s [Error] Update packet error (prefix length mismatch with total length)",
5864 peer->host);
513386b5 5865 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5866 }
6b0655a2 5867
513386b5 5868 return BGP_NLRI_PARSE_OK;
718e3744 5869}
5870
d62a17ae 5871static struct bgp_static *bgp_static_new(void)
718e3744 5872{
d62a17ae 5873 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5874}
5875
d62a17ae 5876static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5877{
0a22ddfb 5878 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5879 route_map_counter_decrement(bgp_static->rmap.map);
5880
0a22ddfb 5881 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5882 XFREE(MTYPE_BGP_STATIC, bgp_static);
5883}
5884
5f040085 5885void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5886 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5887{
9bcb3eef 5888 struct bgp_dest *dest;
40381db7 5889 struct bgp_path_info *pi;
4b7e6066 5890 struct bgp_path_info *new;
40381db7 5891 struct bgp_path_info rmap_path;
d62a17ae 5892 struct attr attr;
5893 struct attr *attr_new;
b68885f9 5894 route_map_result_t ret;
49e5a4a0 5895#ifdef ENABLE_BGP_VNC
d62a17ae 5896 int vnc_implicit_withdraw = 0;
65efcfce 5897#endif
fee0f4c6 5898
d62a17ae 5899 assert(bgp_static);
dd8103a9 5900
9bcb3eef 5901 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5902
0f05ea43 5903 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5904
d62a17ae 5905 attr.nexthop = bgp_static->igpnexthop;
5906 attr.med = bgp_static->igpmetric;
5907 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5908
7226bc40
TA
5909 if (afi == AFI_IP)
5910 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5911
d62a17ae 5912 if (bgp_static->atomic)
5913 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5914
d62a17ae 5915 /* Store label index, if required. */
5916 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5917 attr.label_index = bgp_static->label_index;
5918 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5919 }
718e3744 5920
d62a17ae 5921 /* Apply route-map. */
5922 if (bgp_static->rmap.name) {
5923 struct attr attr_tmp = attr;
80ced710 5924
6006b807 5925 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5926 rmap_path.peer = bgp->peer_self;
5927 rmap_path.attr = &attr_tmp;
fee0f4c6 5928
d62a17ae 5929 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5930
1782514f 5931 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5932
d62a17ae 5933 bgp->peer_self->rmap_type = 0;
718e3744 5934
d62a17ae 5935 if (ret == RMAP_DENYMATCH) {
5936 /* Free uninterned attribute. */
5937 bgp_attr_flush(&attr_tmp);
718e3744 5938
d62a17ae 5939 /* Unintern original. */
5940 aspath_unintern(&attr.aspath);
5941 bgp_static_withdraw(bgp, p, afi, safi);
5942 return;
5943 }
7f323236 5944
637e5ba4 5945 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5946 bgp_attr_add_gshut_community(&attr_tmp);
5947
d62a17ae 5948 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5949 } else {
5950
637e5ba4 5951 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5952 bgp_attr_add_gshut_community(&attr);
5953
d62a17ae 5954 attr_new = bgp_attr_intern(&attr);
7f323236 5955 }
718e3744 5956
9bcb3eef 5957 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5958 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5959 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5960 break;
5961
40381db7
DS
5962 if (pi) {
5963 if (attrhash_cmp(pi->attr, attr_new)
5964 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5965 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5966 bgp_dest_unlock_node(dest);
d62a17ae 5967 bgp_attr_unintern(&attr_new);
5968 aspath_unintern(&attr.aspath);
5969 return;
5970 } else {
5971 /* The attribute is changed. */
9bcb3eef 5972 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5973
5974 /* Rewrite BGP route information. */
40381db7 5975 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5976 bgp_path_info_restore(dest, pi);
d62a17ae 5977 else
40381db7 5978 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5979#ifdef ENABLE_BGP_VNC
d62a17ae 5980 if ((afi == AFI_IP || afi == AFI_IP6)
5981 && (safi == SAFI_UNICAST)) {
40381db7 5982 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5983 /*
5984 * Implicit withdraw case.
40381db7 5985 * We have to do this before pi is
d62a17ae 5986 * changed
5987 */
5988 ++vnc_implicit_withdraw;
40381db7 5989 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5990 vnc_import_bgp_exterior_del_route(
40381db7 5991 bgp, p, pi);
d62a17ae 5992 }
5993 }
65efcfce 5994#endif
40381db7
DS
5995 bgp_attr_unintern(&pi->attr);
5996 pi->attr = attr_new;
5997 pi->uptime = bgp_clock();
49e5a4a0 5998#ifdef ENABLE_BGP_VNC
d62a17ae 5999 if ((afi == AFI_IP || afi == AFI_IP6)
6000 && (safi == SAFI_UNICAST)) {
6001 if (vnc_implicit_withdraw) {
40381db7 6002 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6003 vnc_import_bgp_exterior_add_route(
40381db7 6004 bgp, p, pi);
d62a17ae 6005 }
6006 }
65efcfce 6007#endif
718e3744 6008
d62a17ae 6009 /* Nexthop reachability check. */
892fedb6 6010 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6011 && (safi == SAFI_UNICAST
6012 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6013
6014 struct bgp *bgp_nexthop = bgp;
6015
40381db7
DS
6016 if (pi->extra && pi->extra->bgp_orig)
6017 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6018
6019 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6020 afi, safi, pi, NULL,
654a5978 6021 0, p))
9bcb3eef 6022 bgp_path_info_set_flag(dest, pi,
18ee8310 6023 BGP_PATH_VALID);
d62a17ae 6024 else {
6025 if (BGP_DEBUG(nht, NHT)) {
6026 char buf1[INET6_ADDRSTRLEN];
6027 inet_ntop(p->family,
6028 &p->u.prefix, buf1,
6029 INET6_ADDRSTRLEN);
6030 zlog_debug(
6031 "%s(%s): Route not in table, not advertising",
15569c58 6032 __func__, buf1);
d62a17ae 6033 }
18ee8310 6034 bgp_path_info_unset_flag(
9bcb3eef 6035 dest, pi, BGP_PATH_VALID);
d62a17ae 6036 }
6037 } else {
6038 /* Delete the NHT structure if any, if we're
6039 * toggling between
6040 * enabling/disabling import check. We
6041 * deregister the route
6042 * from NHT to avoid overloading NHT and the
6043 * process interaction
6044 */
40381db7 6045 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6046 bgp_path_info_set_flag(dest, pi,
6047 BGP_PATH_VALID);
d62a17ae 6048 }
6049 /* Process change. */
40381db7 6050 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6051 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6052
6053 if (SAFI_UNICAST == safi
6054 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6055 || bgp->inst_type
6056 == BGP_INSTANCE_TYPE_DEFAULT)) {
6057 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6058 pi);
ddb5b488
PZ
6059 }
6060
9bcb3eef 6061 bgp_dest_unlock_node(dest);
d62a17ae 6062 aspath_unintern(&attr.aspath);
6063 return;
6064 }
718e3744 6065 }
718e3744 6066
d62a17ae 6067 /* Make new BGP info. */
6068 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6069 attr_new, dest);
d62a17ae 6070 /* Nexthop reachability check. */
892fedb6 6071 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6072 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6073 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6074 p))
9bcb3eef 6075 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6076 else {
6077 if (BGP_DEBUG(nht, NHT)) {
6078 char buf1[INET6_ADDRSTRLEN];
6079 inet_ntop(p->family, &p->u.prefix, buf1,
6080 INET6_ADDRSTRLEN);
6081 zlog_debug(
6082 "%s(%s): Route not in table, not advertising",
15569c58 6083 __func__, buf1);
d62a17ae 6084 }
9bcb3eef 6085 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6086 }
6087 } else {
6088 /* Delete the NHT structure if any, if we're toggling between
6089 * enabling/disabling import check. We deregister the route
6090 * from NHT to avoid overloading NHT and the process interaction
6091 */
6092 bgp_unlink_nexthop(new);
6093
9bcb3eef 6094 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6095 }
078430f6 6096
d62a17ae 6097 /* Aggregate address increment. */
6098 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6099
d62a17ae 6100 /* Register new BGP information. */
9bcb3eef 6101 bgp_path_info_add(dest, new);
718e3744 6102
d62a17ae 6103 /* route_node_get lock */
9bcb3eef 6104 bgp_dest_unlock_node(dest);
d62a17ae 6105
6106 /* Process change. */
9bcb3eef 6107 bgp_process(bgp, dest, afi, safi);
d62a17ae 6108
ddb5b488
PZ
6109 if (SAFI_UNICAST == safi
6110 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6111 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6112 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6113 }
6114
d62a17ae 6115 /* Unintern original. */
6116 aspath_unintern(&attr.aspath);
718e3744 6117}
6118
5f040085 6119void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6120 safi_t safi)
718e3744 6121{
9bcb3eef 6122 struct bgp_dest *dest;
40381db7 6123 struct bgp_path_info *pi;
718e3744 6124
9bcb3eef 6125 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6126
d62a17ae 6127 /* Check selected route and self inserted route. */
9bcb3eef 6128 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6129 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6130 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6131 break;
6132
6133 /* Withdraw static BGP route from routing table. */
40381db7 6134 if (pi) {
ddb5b488
PZ
6135 if (SAFI_UNICAST == safi
6136 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6137 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6138 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6139 }
40381db7
DS
6140 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6141 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6142 bgp_path_info_delete(dest, pi);
6143 bgp_process(bgp, dest, afi, safi);
d62a17ae 6144 }
718e3744 6145
d62a17ae 6146 /* Unlock bgp_node_lookup. */
9bcb3eef 6147 bgp_dest_unlock_node(dest);
718e3744 6148}
6149
137446f9
LB
6150/*
6151 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6152 */
5f040085 6153static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6154 afi_t afi, safi_t safi,
6155 struct prefix_rd *prd)
718e3744 6156{
9bcb3eef 6157 struct bgp_dest *dest;
40381db7 6158 struct bgp_path_info *pi;
718e3744 6159
9bcb3eef 6160 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6161
d62a17ae 6162 /* Check selected route and self inserted route. */
9bcb3eef 6163 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6164 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6165 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6166 break;
718e3744 6167
d62a17ae 6168 /* Withdraw static BGP route from routing table. */
40381db7 6169 if (pi) {
49e5a4a0 6170#ifdef ENABLE_BGP_VNC
d62a17ae 6171 rfapiProcessWithdraw(
40381db7 6172 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6173 1); /* Kill, since it is an administrative change */
65efcfce 6174#endif
ddb5b488
PZ
6175 if (SAFI_MPLS_VPN == safi
6176 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6177 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6178 }
40381db7 6179 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6180 bgp_path_info_delete(dest, pi);
6181 bgp_process(bgp, dest, afi, safi);
d62a17ae 6182 }
718e3744 6183
d62a17ae 6184 /* Unlock bgp_node_lookup. */
9bcb3eef 6185 bgp_dest_unlock_node(dest);
718e3744 6186}
6187
5f040085 6188static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6189 struct bgp_static *bgp_static, afi_t afi,
6190 safi_t safi)
137446f9 6191{
9bcb3eef 6192 struct bgp_dest *dest;
4b7e6066 6193 struct bgp_path_info *new;
d62a17ae 6194 struct attr *attr_new;
6195 struct attr attr = {0};
40381db7 6196 struct bgp_path_info *pi;
49e5a4a0 6197#ifdef ENABLE_BGP_VNC
d62a17ae 6198 mpls_label_t label = 0;
65efcfce 6199#endif
d7c0a89a 6200 uint32_t num_labels = 0;
137446f9 6201
d62a17ae 6202 assert(bgp_static);
137446f9 6203
b57ba6d2
MK
6204 if (bgp_static->label != MPLS_INVALID_LABEL)
6205 num_labels = 1;
9bcb3eef
DS
6206 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6207 &bgp_static->prd);
137446f9 6208
0f05ea43 6209 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6210
d62a17ae 6211 attr.nexthop = bgp_static->igpnexthop;
6212 attr.med = bgp_static->igpmetric;
6213 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6214
d62a17ae 6215 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6216 || (safi == SAFI_ENCAP)) {
6217 if (afi == AFI_IP) {
6218 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6219 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6220 }
6221 }
6222 if (afi == AFI_L2VPN) {
b04c1e99
IR
6223 if (bgp_static->gatewayIp.family == AF_INET) {
6224 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6225 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6226 &bgp_static->gatewayIp.u.prefix4,
6227 IPV4_MAX_BYTELEN);
b04c1e99
IR
6228 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6229 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6230 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6231 &bgp_static->gatewayIp.u.prefix6,
6232 IPV6_MAX_BYTELEN);
b04c1e99 6233 }
0a50c248 6234 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6235 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6236 struct bgp_encap_type_vxlan bet;
6006b807 6237 memset(&bet, 0, sizeof(bet));
3714a385 6238 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6239 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6240 }
6241 if (bgp_static->router_mac) {
6242 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6243 }
6244 }
6245 /* Apply route-map. */
6246 if (bgp_static->rmap.name) {
6247 struct attr attr_tmp = attr;
40381db7 6248 struct bgp_path_info rmap_path;
b68885f9 6249 route_map_result_t ret;
137446f9 6250
40381db7
DS
6251 rmap_path.peer = bgp->peer_self;
6252 rmap_path.attr = &attr_tmp;
137446f9 6253
d62a17ae 6254 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6255
1782514f 6256 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6257
d62a17ae 6258 bgp->peer_self->rmap_type = 0;
137446f9 6259
d62a17ae 6260 if (ret == RMAP_DENYMATCH) {
6261 /* Free uninterned attribute. */
6262 bgp_attr_flush(&attr_tmp);
137446f9 6263
d62a17ae 6264 /* Unintern original. */
6265 aspath_unintern(&attr.aspath);
6266 bgp_static_withdraw_safi(bgp, p, afi, safi,
6267 &bgp_static->prd);
6268 return;
6269 }
137446f9 6270
d62a17ae 6271 attr_new = bgp_attr_intern(&attr_tmp);
6272 } else {
6273 attr_new = bgp_attr_intern(&attr);
6274 }
137446f9 6275
9bcb3eef 6276 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6277 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6278 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6279 break;
6280
40381db7 6281 if (pi) {
40381db7 6282 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6283 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6284 bgp_dest_unlock_node(dest);
d62a17ae 6285 bgp_attr_unintern(&attr_new);
6286 aspath_unintern(&attr.aspath);
6287 return;
6288 } else {
6289 /* The attribute is changed. */
9bcb3eef 6290 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6291
6292 /* Rewrite BGP route information. */
40381db7 6293 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6294 bgp_path_info_restore(dest, pi);
d62a17ae 6295 else
40381db7
DS
6296 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6297 bgp_attr_unintern(&pi->attr);
6298 pi->attr = attr_new;
6299 pi->uptime = bgp_clock();
49e5a4a0 6300#ifdef ENABLE_BGP_VNC
40381db7
DS
6301 if (pi->extra)
6302 label = decode_label(&pi->extra->label[0]);
65efcfce 6303#endif
137446f9 6304
d62a17ae 6305 /* Process change. */
40381db7 6306 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6307 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6308
6309 if (SAFI_MPLS_VPN == safi
6310 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6311 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6312 }
49e5a4a0 6313#ifdef ENABLE_BGP_VNC
40381db7
DS
6314 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6315 pi->attr, afi, safi, pi->type,
6316 pi->sub_type, &label);
65efcfce 6317#endif
9bcb3eef 6318 bgp_dest_unlock_node(dest);
d62a17ae 6319 aspath_unintern(&attr.aspath);
6320 return;
6321 }
6322 }
137446f9
LB
6323
6324
d62a17ae 6325 /* Make new BGP info. */
6326 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6327 attr_new, dest);
1defdda8 6328 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6329 bgp_path_info_extra_get(new);
b57ba6d2
MK
6330 if (num_labels) {
6331 new->extra->label[0] = bgp_static->label;
6332 new->extra->num_labels = num_labels;
6333 }
49e5a4a0 6334#ifdef ENABLE_BGP_VNC
d62a17ae 6335 label = decode_label(&bgp_static->label);
65efcfce 6336#endif
137446f9 6337
d62a17ae 6338 /* Aggregate address increment. */
6339 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6340
d62a17ae 6341 /* Register new BGP information. */
9bcb3eef 6342 bgp_path_info_add(dest, new);
d62a17ae 6343 /* route_node_get lock */
9bcb3eef 6344 bgp_dest_unlock_node(dest);
137446f9 6345
d62a17ae 6346 /* Process change. */
9bcb3eef 6347 bgp_process(bgp, dest, afi, safi);
137446f9 6348
ddb5b488
PZ
6349 if (SAFI_MPLS_VPN == safi
6350 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6351 vpn_leak_to_vrf_update(bgp, new);
6352 }
49e5a4a0 6353#ifdef ENABLE_BGP_VNC
d62a17ae 6354 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6355 safi, new->type, new->sub_type, &label);
65efcfce
LB
6356#endif
6357
d62a17ae 6358 /* Unintern original. */
6359 aspath_unintern(&attr.aspath);
137446f9
LB
6360}
6361
718e3744 6362/* Configure static BGP network. When user don't run zebra, static
6363 route should be installed as valid. */
585f1adc
IR
6364static int bgp_static_set(struct vty *vty, const char *negate,
6365 const char *ip_str, afi_t afi, safi_t safi,
6366 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6367{
585f1adc
IR
6368 VTY_DECLVAR_CONTEXT(bgp, bgp);
6369 int ret;
d62a17ae 6370 struct prefix p;
6371 struct bgp_static *bgp_static;
9bcb3eef 6372 struct bgp_dest *dest;
d7c0a89a 6373 uint8_t need_update = 0;
d62a17ae 6374
585f1adc
IR
6375 /* Convert IP prefix string to struct prefix. */
6376 ret = str2prefix(ip_str, &p);
6377 if (!ret) {
6378 vty_out(vty, "%% Malformed prefix\n");
6379 return CMD_WARNING_CONFIG_FAILED;
6380 }
6381 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6382 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6383 return CMD_WARNING_CONFIG_FAILED;
6384 }
6385
d62a17ae 6386 apply_mask(&p);
718e3744 6387
e2a86ad9 6388 if (negate) {
718e3744 6389
e2a86ad9 6390 /* Set BGP static route configuration. */
9bcb3eef 6391 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6392
9bcb3eef 6393 if (!dest) {
585f1adc
IR
6394 vty_out(vty, "%% Can't find static route specified\n");
6395 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6396 }
6397
9bcb3eef 6398 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6399
e2a86ad9
DS
6400 if ((label_index != BGP_INVALID_LABEL_INDEX)
6401 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6402 vty_out(vty,
6403 "%% label-index doesn't match static route\n");
70d9b134 6404 bgp_dest_unlock_node(dest);
585f1adc 6405 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6406 }
d62a17ae 6407
e2a86ad9
DS
6408 if ((rmap && bgp_static->rmap.name)
6409 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6410 vty_out(vty,
6411 "%% route-map name doesn't match static route\n");
70d9b134 6412 bgp_dest_unlock_node(dest);
585f1adc 6413 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6414 }
718e3744 6415
e2a86ad9
DS
6416 /* Update BGP RIB. */
6417 if (!bgp_static->backdoor)
6418 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6419
e2a86ad9
DS
6420 /* Clear configuration. */
6421 bgp_static_free(bgp_static);
9bcb3eef
DS
6422 bgp_dest_set_bgp_static_info(dest, NULL);
6423 bgp_dest_unlock_node(dest);
6424 bgp_dest_unlock_node(dest);
e2a86ad9 6425 } else {
718e3744 6426
e2a86ad9 6427 /* Set BGP static route configuration. */
9bcb3eef
DS
6428 dest = bgp_node_get(bgp->route[afi][safi], &p);
6429 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6430 if (bgp_static) {
e2a86ad9 6431 /* Configuration change. */
e2a86ad9
DS
6432 /* Label index cannot be changed. */
6433 if (bgp_static->label_index != label_index) {
585f1adc
IR
6434 vty_out(vty, "%% cannot change label-index\n");
6435 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6436 }
d62a17ae 6437
e2a86ad9 6438 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6439 if (bgp_static->valid
6440 && bgp_static->backdoor != backdoor)
e2a86ad9 6441 need_update = 1;
718e3744 6442
e2a86ad9 6443 bgp_static->backdoor = backdoor;
718e3744 6444
e2a86ad9 6445 if (rmap) {
0a22ddfb
QY
6446 XFREE(MTYPE_ROUTE_MAP_NAME,
6447 bgp_static->rmap.name);
b4897fa5 6448 route_map_counter_decrement(
6449 bgp_static->rmap.map);
e2a86ad9
DS
6450 bgp_static->rmap.name =
6451 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6452 bgp_static->rmap.map =
6453 route_map_lookup_by_name(rmap);
b4897fa5 6454 route_map_counter_increment(
6455 bgp_static->rmap.map);
e2a86ad9 6456 } else {
0a22ddfb
QY
6457 XFREE(MTYPE_ROUTE_MAP_NAME,
6458 bgp_static->rmap.name);
b4897fa5 6459 route_map_counter_decrement(
6460 bgp_static->rmap.map);
e2a86ad9
DS
6461 bgp_static->rmap.map = NULL;
6462 bgp_static->valid = 0;
6463 }
9bcb3eef 6464 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6465 } else {
6466 /* New configuration. */
6467 bgp_static = bgp_static_new();
6468 bgp_static->backdoor = backdoor;
6469 bgp_static->valid = 0;
6470 bgp_static->igpmetric = 0;
975a328e 6471 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6472 bgp_static->label_index = label_index;
718e3744 6473
e2a86ad9 6474 if (rmap) {
0a22ddfb
QY
6475 XFREE(MTYPE_ROUTE_MAP_NAME,
6476 bgp_static->rmap.name);
b4897fa5 6477 route_map_counter_decrement(
6478 bgp_static->rmap.map);
e2a86ad9
DS
6479 bgp_static->rmap.name =
6480 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6481 bgp_static->rmap.map =
6482 route_map_lookup_by_name(rmap);
b4897fa5 6483 route_map_counter_increment(
6484 bgp_static->rmap.map);
e2a86ad9 6485 }
9bcb3eef 6486 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6487 }
d62a17ae 6488
e2a86ad9
DS
6489 bgp_static->valid = 1;
6490 if (need_update)
6491 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6492
e2a86ad9
DS
6493 if (!bgp_static->backdoor)
6494 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6495 }
d62a17ae 6496
585f1adc 6497 return CMD_SUCCESS;
d62a17ae 6498}
6499
6500void bgp_static_add(struct bgp *bgp)
6501{
6502 afi_t afi;
6503 safi_t safi;
9bcb3eef
DS
6504 struct bgp_dest *dest;
6505 struct bgp_dest *rm;
d62a17ae 6506 struct bgp_table *table;
6507 struct bgp_static *bgp_static;
6508
47fc6261 6509 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6510 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6511 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6512 dest = bgp_route_next(dest)) {
6513 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6514 continue;
ea47320b 6515
05c7a1cc
QY
6516 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6517 || (safi == SAFI_EVPN)) {
9bcb3eef 6518 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6519
6520 for (rm = bgp_table_top(table); rm;
6521 rm = bgp_route_next(rm)) {
a78beeb5 6522 bgp_static =
9bcb3eef 6523 bgp_dest_get_bgp_static_info(
5a8ba9fc 6524 rm);
9bcb3eef
DS
6525 bgp_static_update_safi(
6526 bgp, bgp_dest_get_prefix(rm),
6527 bgp_static, afi, safi);
d62a17ae 6528 }
05c7a1cc 6529 } else {
5a8ba9fc 6530 bgp_static_update(
9bcb3eef
DS
6531 bgp, bgp_dest_get_prefix(dest),
6532 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6533 safi);
ea47320b 6534 }
05c7a1cc 6535 }
47fc6261 6536 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6537}
6538
718e3744 6539/* Called from bgp_delete(). Delete all static routes from the BGP
6540 instance. */
d62a17ae 6541void bgp_static_delete(struct bgp *bgp)
6542{
6543 afi_t afi;
6544 safi_t safi;
9bcb3eef
DS
6545 struct bgp_dest *dest;
6546 struct bgp_dest *rm;
d62a17ae 6547 struct bgp_table *table;
6548 struct bgp_static *bgp_static;
6549
05c7a1cc 6550 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6551 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6552 dest = bgp_route_next(dest)) {
6553 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6554 continue;
ea47320b 6555
05c7a1cc
QY
6556 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6557 || (safi == SAFI_EVPN)) {
9bcb3eef 6558 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6559
6560 for (rm = bgp_table_top(table); rm;
6561 rm = bgp_route_next(rm)) {
a78beeb5 6562 bgp_static =
9bcb3eef 6563 bgp_dest_get_bgp_static_info(
5a8ba9fc 6564 rm);
c7d14ba6
PG
6565 if (!bgp_static)
6566 continue;
6567
05c7a1cc 6568 bgp_static_withdraw_safi(
9bcb3eef 6569 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6570 AFI_IP, safi,
6571 (struct prefix_rd *)
9bcb3eef
DS
6572 bgp_dest_get_prefix(
6573 dest));
ea47320b 6574 bgp_static_free(bgp_static);
811c6797 6575 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6576 NULL);
811c6797 6577 bgp_dest_unlock_node(rm);
d62a17ae 6578 }
05c7a1cc 6579 } else {
9bcb3eef 6580 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6581 bgp_static_withdraw(bgp,
9bcb3eef 6582 bgp_dest_get_prefix(dest),
b54892e0 6583 afi, safi);
05c7a1cc 6584 bgp_static_free(bgp_static);
9bcb3eef
DS
6585 bgp_dest_set_bgp_static_info(dest, NULL);
6586 bgp_dest_unlock_node(dest);
ea47320b 6587 }
05c7a1cc 6588 }
d62a17ae 6589}
6590
6591void bgp_static_redo_import_check(struct bgp *bgp)
6592{
6593 afi_t afi;
6594 safi_t safi;
9bcb3eef
DS
6595 struct bgp_dest *dest;
6596 struct bgp_dest *rm;
d62a17ae 6597 struct bgp_table *table;
6598 struct bgp_static *bgp_static;
6599
6600 /* Use this flag to force reprocessing of the route */
892fedb6 6601 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6602 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6603 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6604 dest = bgp_route_next(dest)) {
6605 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6606 continue;
ea47320b 6607
05c7a1cc
QY
6608 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6609 || (safi == SAFI_EVPN)) {
9bcb3eef 6610 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6611
6612 for (rm = bgp_table_top(table); rm;
6613 rm = bgp_route_next(rm)) {
a78beeb5 6614 bgp_static =
9bcb3eef 6615 bgp_dest_get_bgp_static_info(
5a8ba9fc 6616 rm);
9bcb3eef
DS
6617 bgp_static_update_safi(
6618 bgp, bgp_dest_get_prefix(rm),
6619 bgp_static, afi, safi);
d62a17ae 6620 }
05c7a1cc 6621 } else {
9bcb3eef
DS
6622 bgp_static = bgp_dest_get_bgp_static_info(dest);
6623 bgp_static_update(bgp,
6624 bgp_dest_get_prefix(dest),
6625 bgp_static, afi, safi);
ea47320b 6626 }
05c7a1cc
QY
6627 }
6628 }
892fedb6 6629 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6630}
6631
6632static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6633 safi_t safi)
6634{
6635 struct bgp_table *table;
9bcb3eef 6636 struct bgp_dest *dest;
40381db7 6637 struct bgp_path_info *pi;
d62a17ae 6638
dfb6fd1d
NT
6639 /* Do not install the aggregate route if BGP is in the
6640 * process of termination.
6641 */
892fedb6
DA
6642 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6643 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6644 return;
6645
d62a17ae 6646 table = bgp->rib[afi][safi];
9bcb3eef
DS
6647 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6648 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6649 if (pi->peer == bgp->peer_self
6650 && ((pi->type == ZEBRA_ROUTE_BGP
6651 && pi->sub_type == BGP_ROUTE_STATIC)
6652 || (pi->type != ZEBRA_ROUTE_BGP
6653 && pi->sub_type
d62a17ae 6654 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6655 bgp_aggregate_decrement(
6656 bgp, bgp_dest_get_prefix(dest), pi, afi,
6657 safi);
40381db7 6658 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6659 bgp_path_info_delete(dest, pi);
6660 bgp_process(bgp, dest, afi, safi);
d62a17ae 6661 }
6662 }
6663 }
ad4cbda1 6664}
6665
6666/*
6667 * Purge all networks and redistributed routes from routing table.
6668 * Invoked upon the instance going down.
6669 */
d62a17ae 6670void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6671{
d62a17ae 6672 afi_t afi;
6673 safi_t safi;
ad4cbda1 6674
05c7a1cc
QY
6675 FOREACH_AFI_SAFI (afi, safi)
6676 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6677}
6678
137446f9
LB
6679/*
6680 * gpz 110624
6681 * Currently this is used to set static routes for VPN and ENCAP.
6682 * I think it can probably be factored with bgp_static_set.
6683 */
d62a17ae 6684int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6685 const char *ip_str, const char *rd_str,
6686 const char *label_str, const char *rmap_str,
6687 int evpn_type, const char *esi, const char *gwip,
6688 const char *ethtag, const char *routermac)
6689{
6690 VTY_DECLVAR_CONTEXT(bgp, bgp);
6691 int ret;
6692 struct prefix p;
6693 struct prefix_rd prd;
9bcb3eef
DS
6694 struct bgp_dest *pdest;
6695 struct bgp_dest *dest;
d62a17ae 6696 struct bgp_table *table;
6697 struct bgp_static *bgp_static;
6698 mpls_label_t label = MPLS_INVALID_LABEL;
6699 struct prefix gw_ip;
6700
6701 /* validate ip prefix */
6702 ret = str2prefix(ip_str, &p);
6703 if (!ret) {
6704 vty_out(vty, "%% Malformed prefix\n");
6705 return CMD_WARNING_CONFIG_FAILED;
6706 }
6707 apply_mask(&p);
6708 if ((afi == AFI_L2VPN)
6709 && (bgp_build_evpn_prefix(evpn_type,
6710 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6711 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6712 return CMD_WARNING_CONFIG_FAILED;
6713 }
718e3744 6714
d62a17ae 6715 ret = str2prefix_rd(rd_str, &prd);
6716 if (!ret) {
6717 vty_out(vty, "%% Malformed rd\n");
6718 return CMD_WARNING_CONFIG_FAILED;
6719 }
718e3744 6720
d62a17ae 6721 if (label_str) {
6722 unsigned long label_val;
6723 label_val = strtoul(label_str, NULL, 10);
6724 encode_label(label_val, &label);
6725 }
9bedbb1e 6726
d62a17ae 6727 if (safi == SAFI_EVPN) {
6728 if (esi && str2esi(esi, NULL) == 0) {
6729 vty_out(vty, "%% Malformed ESI\n");
6730 return CMD_WARNING_CONFIG_FAILED;
6731 }
6732 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6733 vty_out(vty, "%% Malformed Router MAC\n");
6734 return CMD_WARNING_CONFIG_FAILED;
6735 }
6736 if (gwip) {
6006b807 6737 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6738 ret = str2prefix(gwip, &gw_ip);
6739 if (!ret) {
6740 vty_out(vty, "%% Malformed GatewayIp\n");
6741 return CMD_WARNING_CONFIG_FAILED;
6742 }
6743 if ((gw_ip.family == AF_INET
3714a385 6744 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6745 (struct prefix_evpn *)&p))
6746 || (gw_ip.family == AF_INET6
3714a385 6747 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6748 (struct prefix_evpn *)&p))) {
6749 vty_out(vty,
6750 "%% GatewayIp family differs with IP prefix\n");
6751 return CMD_WARNING_CONFIG_FAILED;
6752 }
6753 }
6754 }
9bcb3eef
DS
6755 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6756 if (!bgp_dest_has_bgp_path_info_data(pdest))
6757 bgp_dest_set_bgp_table_info(pdest,
67009e22 6758 bgp_table_init(bgp, afi, safi));
9bcb3eef 6759 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6760
9bcb3eef 6761 dest = bgp_node_get(table, &p);
d62a17ae 6762
9bcb3eef 6763 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6764 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6765 bgp_dest_unlock_node(dest);
d62a17ae 6766 } else {
6767 /* New configuration. */
6768 bgp_static = bgp_static_new();
6769 bgp_static->backdoor = 0;
6770 bgp_static->valid = 0;
6771 bgp_static->igpmetric = 0;
975a328e 6772 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6773 bgp_static->label = label;
6774 bgp_static->prd = prd;
6775
6776 if (rmap_str) {
0a22ddfb 6777 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6778 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6779 bgp_static->rmap.name =
6780 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6781 bgp_static->rmap.map =
6782 route_map_lookup_by_name(rmap_str);
b4897fa5 6783 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6784 }
718e3744 6785
d62a17ae 6786 if (safi == SAFI_EVPN) {
6787 if (esi) {
6788 bgp_static->eth_s_id =
6789 XCALLOC(MTYPE_ATTR,
0a50c248 6790 sizeof(esi_t));
d62a17ae 6791 str2esi(esi, bgp_static->eth_s_id);
6792 }
6793 if (routermac) {
6794 bgp_static->router_mac =
28328ea9 6795 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6796 (void)prefix_str2mac(routermac,
6797 bgp_static->router_mac);
d62a17ae 6798 }
6799 if (gwip)
6800 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6801 }
9bcb3eef 6802 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6803
d62a17ae 6804 bgp_static->valid = 1;
6805 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6806 }
718e3744 6807
d62a17ae 6808 return CMD_SUCCESS;
718e3744 6809}
6810
6811/* Configure static BGP network. */
d62a17ae 6812int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6813 const char *ip_str, const char *rd_str,
6814 const char *label_str, int evpn_type, const char *esi,
6815 const char *gwip, const char *ethtag)
6816{
6817 VTY_DECLVAR_CONTEXT(bgp, bgp);
6818 int ret;
6819 struct prefix p;
6820 struct prefix_rd prd;
9bcb3eef
DS
6821 struct bgp_dest *pdest;
6822 struct bgp_dest *dest;
d62a17ae 6823 struct bgp_table *table;
6824 struct bgp_static *bgp_static;
6825 mpls_label_t label = MPLS_INVALID_LABEL;
6826
6827 /* Convert IP prefix string to struct prefix. */
6828 ret = str2prefix(ip_str, &p);
6829 if (!ret) {
6830 vty_out(vty, "%% Malformed prefix\n");
6831 return CMD_WARNING_CONFIG_FAILED;
6832 }
6833 apply_mask(&p);
6834 if ((afi == AFI_L2VPN)
6835 && (bgp_build_evpn_prefix(evpn_type,
6836 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6837 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6838 return CMD_WARNING_CONFIG_FAILED;
6839 }
6840 ret = str2prefix_rd(rd_str, &prd);
6841 if (!ret) {
6842 vty_out(vty, "%% Malformed rd\n");
6843 return CMD_WARNING_CONFIG_FAILED;
6844 }
718e3744 6845
d62a17ae 6846 if (label_str) {
6847 unsigned long label_val;
6848 label_val = strtoul(label_str, NULL, 10);
6849 encode_label(label_val, &label);
6850 }
718e3744 6851
9bcb3eef
DS
6852 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6853 if (!bgp_dest_has_bgp_path_info_data(pdest))
6854 bgp_dest_set_bgp_table_info(pdest,
67009e22 6855 bgp_table_init(bgp, afi, safi));
d62a17ae 6856 else
9bcb3eef
DS
6857 bgp_dest_unlock_node(pdest);
6858 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6859
9bcb3eef 6860 dest = bgp_node_lookup(table, &p);
6b0655a2 6861
9bcb3eef 6862 if (dest) {
d62a17ae 6863 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6864
9bcb3eef 6865 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6866 bgp_static_free(bgp_static);
9bcb3eef
DS
6867 bgp_dest_set_bgp_static_info(dest, NULL);
6868 bgp_dest_unlock_node(dest);
6869 bgp_dest_unlock_node(dest);
d62a17ae 6870 } else
6871 vty_out(vty, "%% Can't find the route\n");
6872
6873 return CMD_SUCCESS;
6874}
6875
6876static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6877 const char *rmap_name)
6878{
6879 VTY_DECLVAR_CONTEXT(bgp, bgp);
6880 struct bgp_rmap *rmap;
6881
6882 rmap = &bgp->table_map[afi][safi];
6883 if (rmap_name) {
0a22ddfb 6884 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6885 route_map_counter_decrement(rmap->map);
d62a17ae 6886 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6887 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6888 route_map_counter_increment(rmap->map);
d62a17ae 6889 } else {
0a22ddfb 6890 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6891 route_map_counter_decrement(rmap->map);
d62a17ae 6892 rmap->map = NULL;
6893 }
73ac8160 6894
d62a17ae 6895 if (bgp_fibupd_safi(safi))
6896 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6897
d62a17ae 6898 return CMD_SUCCESS;
73ac8160
DS
6899}
6900
d62a17ae 6901static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6902 const char *rmap_name)
73ac8160 6903{
d62a17ae 6904 VTY_DECLVAR_CONTEXT(bgp, bgp);
6905 struct bgp_rmap *rmap;
73ac8160 6906
d62a17ae 6907 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6908 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6909 route_map_counter_decrement(rmap->map);
d62a17ae 6910 rmap->map = NULL;
73ac8160 6911
d62a17ae 6912 if (bgp_fibupd_safi(safi))
6913 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6914
d62a17ae 6915 return CMD_SUCCESS;
73ac8160
DS
6916}
6917
2b791107 6918void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6919 safi_t safi)
73ac8160 6920{
d62a17ae 6921 if (bgp->table_map[afi][safi].name) {
d62a17ae 6922 vty_out(vty, " table-map %s\n",
6923 bgp->table_map[afi][safi].name);
6924 }
73ac8160
DS
6925}
6926
73ac8160
DS
6927DEFUN (bgp_table_map,
6928 bgp_table_map_cmd,
6929 "table-map WORD",
6930 "BGP table to RIB route download filter\n"
6931 "Name of the route map\n")
6932{
d62a17ae 6933 int idx_word = 1;
6934 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6935 argv[idx_word]->arg);
73ac8160
DS
6936}
6937DEFUN (no_bgp_table_map,
6938 no_bgp_table_map_cmd,
6939 "no table-map WORD",
3a2d747c 6940 NO_STR
73ac8160
DS
6941 "BGP table to RIB route download filter\n"
6942 "Name of the route map\n")
6943{
d62a17ae 6944 int idx_word = 2;
6945 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6946 argv[idx_word]->arg);
73ac8160
DS
6947}
6948
585f1adc
IR
6949DEFPY(bgp_network,
6950 bgp_network_cmd,
6951 "[no] network \
6952 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 6953 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
6954 backdoor$backdoor}]",
6955 NO_STR
6956 "Specify a network to announce via BGP\n"
6957 "IPv4 prefix\n"
6958 "Network number\n"
6959 "Network mask\n"
6960 "Network mask\n"
6961 "Route-map to modify the attributes\n"
6962 "Name of the route map\n"
6963 "Label index to associate with the prefix\n"
6964 "Label index value\n"
6965 "Specify a BGP backdoor route\n")
6966{
6967 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6968
6969 if (address_str) {
6970 int ret;
718e3744 6971
e2a86ad9 6972 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6973 addr_prefix_str,
6974 sizeof(addr_prefix_str));
e2a86ad9
DS
6975 if (!ret) {
6976 vty_out(vty, "%% Inconsistent address and mask\n");
6977 return CMD_WARNING_CONFIG_FAILED;
6978 }
d62a17ae 6979 }
718e3744 6980
585f1adc
IR
6981 return bgp_static_set(
6982 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6983 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6984 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6985}
6986
585f1adc
IR
6987DEFPY(ipv6_bgp_network,
6988 ipv6_bgp_network_cmd,
6989 "[no] network X:X::X:X/M$prefix \
70dd370f 6990 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
6991 NO_STR
6992 "Specify a network to announce via BGP\n"
6993 "IPv6 prefix\n"
6994 "Route-map to modify the attributes\n"
6995 "Name of the route map\n"
6996 "Label index to associate with the prefix\n"
6997 "Label index value\n")
37a87b8f 6998{
585f1adc
IR
6999 return bgp_static_set(
7000 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7001 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7002}
7003
d62a17ae 7004static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7005{
d62a17ae 7006 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7007}
7008
d62a17ae 7009static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7010{
365ab2e7
RZ
7011 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7012 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7013 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7014 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7015 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7016}
718e3744 7017
365ab2e7
RZ
7018/**
7019 * Helper function to avoid repeated code: prepare variables for a
7020 * `route_map_apply` call.
7021 *
7022 * \returns `true` on route map match, otherwise `false`.
7023 */
7024static bool aggr_suppress_map_test(struct bgp *bgp,
7025 struct bgp_aggregate *aggregate,
7026 struct bgp_path_info *pi)
7027{
7028 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7029 route_map_result_t rmr = RMAP_DENYMATCH;
7030 struct bgp_path_info rmap_path = {};
7031 struct attr attr = {};
7032
7033 /* No route map entries created, just don't match. */
7034 if (aggregate->suppress_map == NULL)
7035 return false;
7036
7037 /* Call route map matching and return result. */
7038 attr.aspath = aspath_empty();
7039 rmap_path.peer = bgp->peer_self;
7040 rmap_path.attr = &attr;
7041
7042 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7043 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7044 bgp->peer_self->rmap_type = 0;
7045
7046 bgp_attr_flush(&attr);
afb254d7 7047 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7048
7049 return rmr == RMAP_PERMITMATCH;
7050}
7051
4056a5f6
RZ
7052/** Test whether the aggregation has suppressed this path or not. */
7053static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7054 struct bgp_path_info *pi)
7055{
7056 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7057 return false;
7058
7059 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7060}
7061
7062/**
7063 * Suppress this path and keep the reference.
7064 *
7065 * \returns `true` if needs processing otherwise `false`.
7066 */
7067static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7068 struct bgp_path_info *pi)
7069{
7070 struct bgp_path_info_extra *pie;
7071
7072 /* Path is already suppressed by this aggregation. */
7073 if (aggr_suppress_exists(aggregate, pi))
7074 return false;
7075
7076 pie = bgp_path_info_extra_get(pi);
7077
7078 /* This is the first suppression, allocate memory and list it. */
7079 if (pie->aggr_suppressors == NULL)
7080 pie->aggr_suppressors = list_new();
7081
7082 listnode_add(pie->aggr_suppressors, aggregate);
7083
7084 /* Only mark for processing if suppressed. */
7085 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7086 if (BGP_DEBUG(update, UPDATE_OUT))
7087 zlog_debug("aggregate-address suppressing: %pFX",
7088 bgp_dest_get_prefix(pi->net));
7089
4056a5f6
RZ
7090 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7091 return true;
7092 }
7093
7094 return false;
7095}
7096
7097/**
7098 * Unsuppress this path and remove the reference.
7099 *
7100 * \returns `true` if needs processing otherwise `false`.
7101 */
7102static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7103 struct bgp_path_info *pi)
7104{
7105 /* Path wasn't suppressed. */
7106 if (!aggr_suppress_exists(aggregate, pi))
7107 return false;
7108
7109 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7110
7111 /* Unsuppress and free extra memory if last item. */
7112 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7113 if (BGP_DEBUG(update, UPDATE_OUT))
7114 zlog_debug("aggregate-address unsuppressing: %pFX",
7115 bgp_dest_get_prefix(pi->net));
7116
4056a5f6
RZ
7117 list_delete(&pi->extra->aggr_suppressors);
7118 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7119 return true;
7120 }
7121
7122 return false;
7123}
7124
3dc339cd
DA
7125static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7126 struct aspath *aspath,
7127 struct community *comm,
7128 struct ecommunity *ecomm,
7129 struct lcommunity *lcomm)
eaaf8adb
DS
7130{
7131 static struct aspath *ae = NULL;
7132
7133 if (!ae)
7134 ae = aspath_empty();
7135
40381db7 7136 if (!pi)
3dc339cd 7137 return false;
eaaf8adb 7138
40381db7 7139 if (origin != pi->attr->origin)
3dc339cd 7140 return false;
eaaf8adb 7141
40381db7 7142 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7143 return false;
29f7d023 7144
9a706b42 7145 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7146 return false;
eaaf8adb 7147
b53e67a3 7148 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7149 return false;
eaaf8adb 7150
1bcf3a96 7151 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7152 return false;
dd18c5a9 7153
40381db7 7154 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7155 return false;
7ce8a8e0 7156
3dc339cd 7157 return true;
eaaf8adb
DS
7158}
7159
5f040085
DS
7160static void bgp_aggregate_install(
7161 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7162 uint8_t origin, struct aspath *aspath, struct community *community,
7163 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7164 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7165{
9bcb3eef 7166 struct bgp_dest *dest;
c701010e 7167 struct bgp_table *table;
6f94b685 7168 struct bgp_path_info *pi, *orig, *new;
20894f50 7169 struct attr *attr;
c701010e
DS
7170
7171 table = bgp->rib[afi][safi];
7172
9bcb3eef 7173 dest = bgp_node_get(table, p);
eaaf8adb 7174
9bcb3eef 7175 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7176 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7177 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7178 break;
7179
6aabb15d
RZ
7180 /*
7181 * If we have paths with different MEDs, then don't install
7182 * (or uninstall) the aggregate route.
7183 */
7184 if (aggregate->match_med && aggregate->med_mismatched)
7185 goto uninstall_aggregate_route;
7186
c701010e 7187 if (aggregate->count > 0) {
eaaf8adb
DS
7188 /*
7189 * If the aggregate information has not changed
7190 * no need to re-install it again.
7191 */
6f94b685 7192 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7193 ecommunity, lcommunity)) {
9bcb3eef 7194 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7195
7196 if (aspath)
7197 aspath_free(aspath);
7198 if (community)
3c1f53de 7199 community_free(&community);
3da2cc32
DS
7200 if (ecommunity)
7201 ecommunity_free(&ecommunity);
dd18c5a9
DS
7202 if (lcommunity)
7203 lcommunity_free(&lcommunity);
eaaf8adb
DS
7204
7205 return;
7206 }
7207
7208 /*
7209 * Mark the old as unusable
7210 */
40381db7 7211 if (pi)
9bcb3eef 7212 bgp_path_info_delete(dest, pi);
eaaf8adb 7213
20894f50
DA
7214 attr = bgp_attr_aggregate_intern(
7215 bgp, origin, aspath, community, ecommunity, lcommunity,
7216 aggregate, atomic_aggregate, p);
7217
7218 if (!attr) {
7219 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7220 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7221 zlog_debug("%s: %pFX null attribute", __func__,
7222 p);
20894f50
DA
7223 return;
7224 }
7225
3da2cc32 7226 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7227 bgp->peer_self, attr, dest);
20894f50 7228
1defdda8 7229 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7230
9bcb3eef
DS
7231 bgp_path_info_add(dest, new);
7232 bgp_process(bgp, dest, afi, safi);
c701010e 7233 } else {
6aabb15d 7234 uninstall_aggregate_route:
6f94b685 7235 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7236 if (pi->peer == bgp->peer_self
7237 && pi->type == ZEBRA_ROUTE_BGP
7238 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7239 break;
7240
7241 /* Withdraw static BGP route from routing table. */
40381db7 7242 if (pi) {
9bcb3eef
DS
7243 bgp_path_info_delete(dest, pi);
7244 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7245 }
7246 }
7247
9bcb3eef 7248 bgp_dest_unlock_node(dest);
c701010e
DS
7249}
7250
6aabb15d
RZ
7251/**
7252 * Check if the current path has different MED than other known paths.
7253 *
7254 * \returns `true` if the MED matched the others else `false`.
7255 */
7256static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7257 struct bgp *bgp, struct bgp_path_info *pi)
7258{
7259 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7260
7261 /* This is the first route being analyzed. */
7262 if (!aggregate->med_initialized) {
7263 aggregate->med_initialized = true;
7264 aggregate->med_mismatched = false;
7265 aggregate->med_matched_value = cur_med;
7266 } else {
7267 /* Check if routes with different MED showed up. */
7268 if (cur_med != aggregate->med_matched_value)
7269 aggregate->med_mismatched = true;
7270 }
7271
7272 return !aggregate->med_mismatched;
7273}
7274
7275/**
7276 * Initializes and tests all routes in the aggregate address path for MED
7277 * values.
7278 *
7279 * \returns `true` if all MEDs are the same otherwise `false`.
7280 */
7281static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7282 struct bgp *bgp, const struct prefix *p,
7283 afi_t afi, safi_t safi)
7284{
7285 struct bgp_table *table = bgp->rib[afi][safi];
7286 const struct prefix *dest_p;
7287 struct bgp_dest *dest, *top;
7288 struct bgp_path_info *pi;
7289 bool med_matched = true;
7290
7291 aggregate->med_initialized = false;
7292
7293 top = bgp_node_get(table, p);
7294 for (dest = bgp_node_get(table, p); dest;
7295 dest = bgp_route_next_until(dest, top)) {
7296 dest_p = bgp_dest_get_prefix(dest);
7297 if (dest_p->prefixlen <= p->prefixlen)
7298 continue;
7299
7300 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7301 if (BGP_PATH_HOLDDOWN(pi))
7302 continue;
7303 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7304 continue;
7305 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7306 med_matched = false;
7307 break;
7308 }
7309 }
7310 if (!med_matched)
7311 break;
7312 }
7313 bgp_dest_unlock_node(top);
7314
7315 return med_matched;
7316}
7317
7318/**
7319 * Toggles the route suppression status for this aggregate address
7320 * configuration.
7321 */
4056a5f6
RZ
7322void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7323 struct bgp *bgp, const struct prefix *p,
7324 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7325{
7326 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7327 const struct prefix *dest_p;
7328 struct bgp_dest *dest, *top;
7329 struct bgp_path_info *pi;
7330 bool toggle_suppression;
7331
7332 /* We've found a different MED we must revert any suppressed routes. */
7333 top = bgp_node_get(table, p);
7334 for (dest = bgp_node_get(table, p); dest;
7335 dest = bgp_route_next_until(dest, top)) {
7336 dest_p = bgp_dest_get_prefix(dest);
7337 if (dest_p->prefixlen <= p->prefixlen)
7338 continue;
7339
7340 toggle_suppression = false;
7341 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7342 if (BGP_PATH_HOLDDOWN(pi))
7343 continue;
7344 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7345 continue;
7346
6aabb15d
RZ
7347 /* We are toggling suppression back. */
7348 if (suppress) {
6aabb15d 7349 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7350 if (aggr_suppress_path(aggregate, pi))
7351 toggle_suppression = true;
6aabb15d
RZ
7352 continue;
7353 }
7354
6aabb15d 7355 /* Install route if there is no more suppression. */
4056a5f6 7356 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7357 toggle_suppression = true;
6aabb15d
RZ
7358 }
7359
7360 if (toggle_suppression)
7361 bgp_process(bgp, dest, afi, safi);
7362 }
7363 bgp_dest_unlock_node(top);
7364}
7365
7366/**
7367 * Aggregate address MED matching incremental test: this function is called
7368 * when the initial aggregation occurred and we are only testing a single
7369 * new path.
7370 *
7371 * In addition to testing and setting the MED validity it also installs back
7372 * suppressed routes (if summary is configured).
7373 *
7374 * Must not be called in `bgp_aggregate_route`.
7375 */
7376static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7377 struct bgp *bgp, const struct prefix *p,
7378 afi_t afi, safi_t safi,
7379 struct bgp_path_info *pi, bool is_adding)
7380{
7381 /* MED matching disabled. */
7382 if (!aggregate->match_med)
7383 return;
7384
7385 /* Aggregation with different MED, nothing to do. */
7386 if (aggregate->med_mismatched)
7387 return;
7388
7389 /*
7390 * Test the current entry:
7391 *
7392 * is_adding == true: if the new entry doesn't match then we must
7393 * install all suppressed routes.
7394 *
7395 * is_adding == false: if the entry being removed was the last
7396 * unmatching entry then we can suppress all routes.
7397 */
7398 if (!is_adding) {
7399 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7400 && aggregate->summary_only)
7401 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7402 safi, true);
7403 } else
7404 bgp_aggregate_med_match(aggregate, bgp, pi);
7405
7406 /* No mismatches, just quit. */
7407 if (!aggregate->med_mismatched)
7408 return;
7409
7410 /* Route summarization is disabled. */
7411 if (!aggregate->summary_only)
7412 return;
7413
7414 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7415}
7416
b5d58c32 7417/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7418void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7419 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7420{
7421 struct bgp_table *table;
9bcb3eef
DS
7422 struct bgp_dest *top;
7423 struct bgp_dest *dest;
d7c0a89a 7424 uint8_t origin;
d62a17ae 7425 struct aspath *aspath = NULL;
d62a17ae 7426 struct community *community = NULL;
3da2cc32 7427 struct ecommunity *ecommunity = NULL;
dd18c5a9 7428 struct lcommunity *lcommunity = NULL;
40381db7 7429 struct bgp_path_info *pi;
d62a17ae 7430 unsigned long match = 0;
d7c0a89a 7431 uint8_t atomic_aggregate = 0;
d62a17ae 7432
9f822fa2
S
7433 /* If the bgp instance is being deleted or self peer is deleted
7434 * then do not create aggregate route
7435 */
892fedb6
DA
7436 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7437 || (bgp->peer_self == NULL))
9f822fa2
S
7438 return;
7439
6aabb15d
RZ
7440 /* Initialize and test routes for MED difference. */
7441 if (aggregate->match_med)
7442 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7443
4056a5f6
RZ
7444 /*
7445 * Reset aggregate count: we might've been called from route map
7446 * update so in that case we must retest all more specific routes.
7447 *
7448 * \see `bgp_route_map_process_update`.
7449 */
7450 aggregate->count = 0;
7451 aggregate->incomplete_origin_count = 0;
7452 aggregate->incomplete_origin_count = 0;
7453 aggregate->egp_origin_count = 0;
7454
d62a17ae 7455 /* ORIGIN attribute: If at least one route among routes that are
7456 aggregated has ORIGIN with the value INCOMPLETE, then the
7457 aggregated route must have the ORIGIN attribute with the value
7458 INCOMPLETE. Otherwise, if at least one route among routes that
7459 are aggregated has ORIGIN with the value EGP, then the aggregated
7460 route must have the origin attribute with the value EGP. In all
7461 other case the value of the ORIGIN attribute of the aggregated
7462 route is INTERNAL. */
7463 origin = BGP_ORIGIN_IGP;
718e3744 7464
d62a17ae 7465 table = bgp->rib[afi][safi];
718e3744 7466
d62a17ae 7467 top = bgp_node_get(table, p);
9bcb3eef
DS
7468 for (dest = bgp_node_get(table, p); dest;
7469 dest = bgp_route_next_until(dest, top)) {
7470 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7471
9bcb3eef 7472 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7473 continue;
d62a17ae 7474
a77e2f4b
S
7475 /* If suppress fib is enabled and route not installed
7476 * in FIB, skip the route
7477 */
7478 if (!bgp_check_advertise(bgp, dest))
7479 continue;
7480
c2ff8b3e 7481 match = 0;
d62a17ae 7482
9bcb3eef 7483 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7484 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7485 continue;
718e3744 7486
40381db7 7487 if (pi->attr->flag
c2ff8b3e
DS
7488 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7489 atomic_aggregate = 1;
d62a17ae 7490
40381db7 7491 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7492 continue;
d62a17ae 7493
f273fef1
DS
7494 /*
7495 * summary-only aggregate route suppress
7496 * aggregated route announcements.
6aabb15d
RZ
7497 *
7498 * MED matching:
7499 * Don't create summaries if MED didn't match
7500 * otherwise neither the specific routes and the
7501 * aggregation will be announced.
f273fef1 7502 */
6aabb15d
RZ
7503 if (aggregate->summary_only
7504 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7505 if (aggr_suppress_path(aggregate, pi))
7506 match++;
d62a17ae 7507 }
c2ff8b3e 7508
365ab2e7
RZ
7509 /*
7510 * Suppress more specific routes that match the route
7511 * map results.
7512 *
7513 * MED matching:
7514 * Don't suppress routes if MED matching is enabled and
7515 * it mismatched otherwise we might end up with no
7516 * routes for this path.
7517 */
7518 if (aggregate->suppress_map_name
7519 && AGGREGATE_MED_VALID(aggregate)
7520 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7521 if (aggr_suppress_path(aggregate, pi))
7522 match++;
d62a17ae 7523 }
c2ff8b3e
DS
7524
7525 aggregate->count++;
7526
f273fef1
DS
7527 /*
7528 * If at least one route among routes that are
7529 * aggregated has ORIGIN with the value INCOMPLETE,
7530 * then the aggregated route MUST have the ORIGIN
7531 * attribute with the value INCOMPLETE. Otherwise, if
7532 * at least one route among routes that are aggregated
7533 * has ORIGIN with the value EGP, then the aggregated
7534 * route MUST have the ORIGIN attribute with the value
7535 * EGP.
7536 */
fc968841
NT
7537 switch (pi->attr->origin) {
7538 case BGP_ORIGIN_INCOMPLETE:
7539 aggregate->incomplete_origin_count++;
7540 break;
7541 case BGP_ORIGIN_EGP:
7542 aggregate->egp_origin_count++;
7543 break;
7544 default:
7545 /*Do nothing.
7546 */
7547 break;
7548 }
c2ff8b3e
DS
7549
7550 if (!aggregate->as_set)
7551 continue;
7552
f273fef1
DS
7553 /*
7554 * as-set aggregate route generate origin, as path,
7555 * and community aggregation.
7556 */
fc968841
NT
7557 /* Compute aggregate route's as-path.
7558 */
ef51a7d8 7559 bgp_compute_aggregate_aspath_hash(aggregate,
7560 pi->attr->aspath);
c2ff8b3e 7561
fc968841
NT
7562 /* Compute aggregate route's community.
7563 */
9a706b42 7564 if (bgp_attr_get_community(pi->attr))
21fec674 7565 bgp_compute_aggregate_community_hash(
9a706b42
DA
7566 aggregate,
7567 bgp_attr_get_community(pi->attr));
dd18c5a9 7568
fc968841
NT
7569 /* Compute aggregate route's extended community.
7570 */
b53e67a3 7571 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7572 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7573 aggregate,
7574 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7575
7576 /* Compute aggregate route's large community.
7577 */
1bcf3a96 7578 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7579 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7580 aggregate,
7581 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7582 }
c2ff8b3e 7583 if (match)
9bcb3eef 7584 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7585 }
21fec674 7586 if (aggregate->as_set) {
ef51a7d8 7587 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7588 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7589 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7590 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7591 }
7592
f1eb1f05 7593
9bcb3eef 7594 bgp_dest_unlock_node(top);
718e3744 7595
718e3744 7596
fc968841
NT
7597 if (aggregate->incomplete_origin_count > 0)
7598 origin = BGP_ORIGIN_INCOMPLETE;
7599 else if (aggregate->egp_origin_count > 0)
7600 origin = BGP_ORIGIN_EGP;
d62a17ae 7601
229757f1
DA
7602 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7603 origin = aggregate->origin;
7604
fc968841
NT
7605 if (aggregate->as_set) {
7606 if (aggregate->aspath)
7607 /* Retrieve aggregate route's as-path.
7608 */
7609 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7610
fc968841
NT
7611 if (aggregate->community)
7612 /* Retrieve aggregate route's community.
7613 */
7614 community = community_dup(aggregate->community);
3da2cc32 7615
fc968841
NT
7616 if (aggregate->ecommunity)
7617 /* Retrieve aggregate route's ecommunity.
7618 */
7619 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7620
fc968841
NT
7621 if (aggregate->lcommunity)
7622 /* Retrieve aggregate route's lcommunity.
7623 */
7624 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7625 }
718e3744 7626
c701010e 7627 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7628 ecommunity, lcommunity, atomic_aggregate,
7629 aggregate);
718e3744 7630}
7631
5f040085
DS
7632void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7633 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7634{
7635 struct bgp_table *table;
9bcb3eef
DS
7636 struct bgp_dest *top;
7637 struct bgp_dest *dest;
40381db7 7638 struct bgp_path_info *pi;
3b7db173
DS
7639 unsigned long match;
7640
7641 table = bgp->rib[afi][safi];
7642
7643 /* If routes exists below this node, generate aggregate routes. */
7644 top = bgp_node_get(table, p);
9bcb3eef
DS
7645 for (dest = bgp_node_get(table, p); dest;
7646 dest = bgp_route_next_until(dest, top)) {
7647 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7648
9bcb3eef 7649 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7650 continue;
7651 match = 0;
7652
9bcb3eef 7653 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7654 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7655 continue;
7656
40381db7 7657 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7658 continue;
7659
92b175bd
RZ
7660 /*
7661 * This route is suppressed: attempt to unsuppress it.
7662 *
7663 * `aggr_unsuppress_path` will fail if this particular
7664 * aggregate route was not the suppressor.
7665 */
7666 if (pi->extra && pi->extra->aggr_suppressors &&
7667 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7668 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7669 match++;
3b7db173 7670 }
365ab2e7 7671
3b7db173 7672 aggregate->count--;
fc968841
NT
7673
7674 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7675 aggregate->incomplete_origin_count--;
7676 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7677 aggregate->egp_origin_count--;
7678
7679 if (aggregate->as_set) {
7680 /* Remove as-path from aggregate.
7681 */
ef51a7d8 7682 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7683 aggregate,
7684 pi->attr->aspath);
7685
9a706b42 7686 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7687 /* Remove community from aggregate.
7688 */
21fec674 7689 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7690 aggregate,
7691 bgp_attr_get_community(
7692 pi->attr));
fc968841 7693
b53e67a3 7694 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7695 /* Remove ecommunity from aggregate.
7696 */
4edd83f9 7697 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7698 aggregate,
7699 bgp_attr_get_ecommunity(
7700 pi->attr));
fc968841 7701
1bcf3a96 7702 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7703 /* Remove lcommunity from aggregate.
7704 */
f1eb1f05 7705 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7706 aggregate,
7707 bgp_attr_get_lcommunity(
7708 pi->attr));
fc968841 7709 }
3b7db173
DS
7710 }
7711
7712 /* If this node was suppressed, process the change. */
7713 if (match)
9bcb3eef 7714 bgp_process(bgp, dest, afi, safi);
3b7db173 7715 }
f1eb1f05 7716 if (aggregate->as_set) {
ef51a7d8 7717 aspath_free(aggregate->aspath);
7718 aggregate->aspath = NULL;
21fec674 7719 if (aggregate->community)
7720 community_free(&aggregate->community);
4edd83f9 7721 if (aggregate->ecommunity)
7722 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7723 if (aggregate->lcommunity)
7724 lcommunity_free(&aggregate->lcommunity);
7725 }
7726
9bcb3eef 7727 bgp_dest_unlock_node(top);
3b7db173 7728}
718e3744 7729
5f040085
DS
7730static void bgp_add_route_to_aggregate(struct bgp *bgp,
7731 const struct prefix *aggr_p,
fc968841
NT
7732 struct bgp_path_info *pinew, afi_t afi,
7733 safi_t safi,
7734 struct bgp_aggregate *aggregate)
7735{
7736 uint8_t origin;
7737 struct aspath *aspath = NULL;
7738 uint8_t atomic_aggregate = 0;
7739 struct community *community = NULL;
7740 struct ecommunity *ecommunity = NULL;
7741 struct lcommunity *lcommunity = NULL;
7742
a4559740 7743 /* If the bgp instance is being deleted or self peer is deleted
7744 * then do not create aggregate route
7745 */
7746 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7747 || (bgp->peer_self == NULL))
7748 return;
7749
fc968841
NT
7750 /* ORIGIN attribute: If at least one route among routes that are
7751 * aggregated has ORIGIN with the value INCOMPLETE, then the
7752 * aggregated route must have the ORIGIN attribute with the value
7753 * INCOMPLETE. Otherwise, if at least one route among routes that
7754 * are aggregated has ORIGIN with the value EGP, then the aggregated
7755 * route must have the origin attribute with the value EGP. In all
7756 * other case the value of the ORIGIN attribute of the aggregated
7757 * route is INTERNAL.
7758 */
7759 origin = BGP_ORIGIN_IGP;
7760
7761 aggregate->count++;
7762
6aabb15d
RZ
7763 /*
7764 * This must be called before `summary` check to avoid
7765 * "suppressing" twice.
7766 */
7767 if (aggregate->match_med)
7768 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7769 pinew, true);
7770
7771 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7772 aggr_suppress_path(aggregate, pinew);
fc968841 7773
365ab2e7
RZ
7774 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7775 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7776 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7777
7778 switch (pinew->attr->origin) {
7779 case BGP_ORIGIN_INCOMPLETE:
7780 aggregate->incomplete_origin_count++;
7781 break;
7782 case BGP_ORIGIN_EGP:
7783 aggregate->egp_origin_count++;
7784 break;
7785 default:
7786 /* Do nothing.
7787 */
7788 break;
7789 }
7790
7791 if (aggregate->incomplete_origin_count > 0)
7792 origin = BGP_ORIGIN_INCOMPLETE;
7793 else if (aggregate->egp_origin_count > 0)
7794 origin = BGP_ORIGIN_EGP;
7795
229757f1
DA
7796 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7797 origin = aggregate->origin;
7798
fc968841
NT
7799 if (aggregate->as_set) {
7800 /* Compute aggregate route's as-path.
7801 */
7802 bgp_compute_aggregate_aspath(aggregate,
7803 pinew->attr->aspath);
7804
7805 /* Compute aggregate route's community.
7806 */
9a706b42 7807 if (bgp_attr_get_community(pinew->attr))
fc968841 7808 bgp_compute_aggregate_community(
9a706b42 7809 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7810
7811 /* Compute aggregate route's extended community.
7812 */
b53e67a3 7813 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7814 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7815 aggregate,
7816 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7817
7818 /* Compute aggregate route's large community.
7819 */
1bcf3a96 7820 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7821 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7822 aggregate,
7823 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7824
7825 /* Retrieve aggregate route's as-path.
7826 */
7827 if (aggregate->aspath)
7828 aspath = aspath_dup(aggregate->aspath);
7829
7830 /* Retrieve aggregate route's community.
7831 */
7832 if (aggregate->community)
7833 community = community_dup(aggregate->community);
7834
7835 /* Retrieve aggregate route's ecommunity.
7836 */
7837 if (aggregate->ecommunity)
7838 ecommunity = ecommunity_dup(aggregate->ecommunity);
7839
7840 /* Retrieve aggregate route's lcommunity.
7841 */
7842 if (aggregate->lcommunity)
7843 lcommunity = lcommunity_dup(aggregate->lcommunity);
7844 }
7845
7846 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7847 aspath, community, ecommunity,
7848 lcommunity, atomic_aggregate, aggregate);
7849}
7850
7851static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7852 safi_t safi,
7853 struct bgp_path_info *pi,
7854 struct bgp_aggregate *aggregate,
5f040085 7855 const struct prefix *aggr_p)
fc968841
NT
7856{
7857 uint8_t origin;
7858 struct aspath *aspath = NULL;
7859 uint8_t atomic_aggregate = 0;
7860 struct community *community = NULL;
7861 struct ecommunity *ecommunity = NULL;
7862 struct lcommunity *lcommunity = NULL;
7863 unsigned long match = 0;
7864
a4559740 7865 /* If the bgp instance is being deleted or self peer is deleted
7866 * then do not create aggregate route
7867 */
7868 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7869 || (bgp->peer_self == NULL))
7870 return;
7871
fc968841
NT
7872 if (BGP_PATH_HOLDDOWN(pi))
7873 return;
7874
7875 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7876 return;
7877
4056a5f6
RZ
7878 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7879 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7880 match++;
fc968841 7881
365ab2e7 7882 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7883 && aggr_suppress_map_test(bgp, aggregate, pi))
7884 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7885 match++;
fc968841 7886
6aabb15d 7887 /*
365ab2e7 7888 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7889 * "unsuppressing" twice.
7890 */
7891 if (aggregate->match_med)
7892 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7893 true);
7894
fc968841
NT
7895 if (aggregate->count > 0)
7896 aggregate->count--;
7897
7898 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7899 aggregate->incomplete_origin_count--;
7900 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7901 aggregate->egp_origin_count--;
7902
7903 if (aggregate->as_set) {
7904 /* Remove as-path from aggregate.
7905 */
7906 bgp_remove_aspath_from_aggregate(aggregate,
7907 pi->attr->aspath);
7908
9a706b42 7909 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7910 /* Remove community from aggregate.
7911 */
7912 bgp_remove_community_from_aggregate(
9a706b42 7913 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7914
b53e67a3 7915 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7916 /* Remove ecommunity from aggregate.
7917 */
7918 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7919 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7920
1bcf3a96 7921 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7922 /* Remove lcommunity from aggregate.
7923 */
7924 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7925 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7926 }
7927
7928 /* If this node was suppressed, process the change. */
7929 if (match)
7930 bgp_process(bgp, pi->net, afi, safi);
7931
7932 origin = BGP_ORIGIN_IGP;
7933 if (aggregate->incomplete_origin_count > 0)
7934 origin = BGP_ORIGIN_INCOMPLETE;
7935 else if (aggregate->egp_origin_count > 0)
7936 origin = BGP_ORIGIN_EGP;
7937
229757f1
DA
7938 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7939 origin = aggregate->origin;
7940
fc968841
NT
7941 if (aggregate->as_set) {
7942 /* Retrieve aggregate route's as-path.
7943 */
7944 if (aggregate->aspath)
7945 aspath = aspath_dup(aggregate->aspath);
7946
7947 /* Retrieve aggregate route's community.
7948 */
7949 if (aggregate->community)
7950 community = community_dup(aggregate->community);
7951
7952 /* Retrieve aggregate route's ecommunity.
7953 */
7954 if (aggregate->ecommunity)
7955 ecommunity = ecommunity_dup(aggregate->ecommunity);
7956
7957 /* Retrieve aggregate route's lcommunity.
7958 */
7959 if (aggregate->lcommunity)
7960 lcommunity = lcommunity_dup(aggregate->lcommunity);
7961 }
7962
7963 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7964 aspath, community, ecommunity,
7965 lcommunity, atomic_aggregate, aggregate);
7966}
7967
5a1ae2c2 7968void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7969 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7970{
9bcb3eef
DS
7971 struct bgp_dest *child;
7972 struct bgp_dest *dest;
d62a17ae 7973 struct bgp_aggregate *aggregate;
7974 struct bgp_table *table;
718e3744 7975
d62a17ae 7976 table = bgp->aggregate[afi][safi];
f018db83 7977
d62a17ae 7978 /* No aggregates configured. */
7979 if (bgp_table_top_nolock(table) == NULL)
7980 return;
f018db83 7981
d62a17ae 7982 if (p->prefixlen == 0)
7983 return;
718e3744 7984
40381db7 7985 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7986 return;
718e3744 7987
a77e2f4b
S
7988 /* If suppress fib is enabled and route not installed
7989 * in FIB, do not update the aggregate route
7990 */
7991 if (!bgp_check_advertise(bgp, pi->net))
7992 return;
7993
d62a17ae 7994 child = bgp_node_get(table, p);
718e3744 7995
d62a17ae 7996 /* Aggregate address configuration check. */
9bcb3eef
DS
7997 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7998 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7999
9bcb3eef
DS
8000 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8001 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8002 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8003 aggregate);
d62a17ae 8004 }
b1e62edd 8005 }
9bcb3eef 8006 bgp_dest_unlock_node(child);
718e3744 8007}
8008
5a1ae2c2 8009void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8010 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8011{
9bcb3eef
DS
8012 struct bgp_dest *child;
8013 struct bgp_dest *dest;
d62a17ae 8014 struct bgp_aggregate *aggregate;
8015 struct bgp_table *table;
718e3744 8016
d62a17ae 8017 table = bgp->aggregate[afi][safi];
718e3744 8018
d62a17ae 8019 /* No aggregates configured. */
8020 if (bgp_table_top_nolock(table) == NULL)
8021 return;
718e3744 8022
d62a17ae 8023 if (p->prefixlen == 0)
8024 return;
718e3744 8025
d62a17ae 8026 child = bgp_node_get(table, p);
718e3744 8027
d62a17ae 8028 /* Aggregate address configuration check. */
9bcb3eef
DS
8029 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8030 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8031
9bcb3eef
DS
8032 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8033 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8034 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8035 aggregate, dest_p);
d62a17ae 8036 }
b1e62edd 8037 }
9bcb3eef 8038 bgp_dest_unlock_node(child);
d62a17ae 8039}
718e3744 8040
718e3744 8041/* Aggregate route attribute. */
8042#define AGGREGATE_SUMMARY_ONLY 1
8043#define AGGREGATE_AS_SET 1
fb29348a 8044#define AGGREGATE_AS_UNSET 0
718e3744 8045
229757f1
DA
8046static const char *bgp_origin2str(uint8_t origin)
8047{
8048 switch (origin) {
8049 case BGP_ORIGIN_IGP:
8050 return "igp";
8051 case BGP_ORIGIN_EGP:
8052 return "egp";
8053 case BGP_ORIGIN_INCOMPLETE:
8054 return "incomplete";
8055 }
8056 return "n/a";
8057}
8058
fdeb5a81 8059static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8060{
8061 switch (v_state) {
fdeb5a81
DS
8062 case RPKI_NOT_BEING_USED:
8063 return "not used";
8064 case RPKI_VALID:
b5b99af8 8065 return "valid";
fdeb5a81 8066 case RPKI_NOTFOUND:
b5b99af8 8067 return "not found";
fdeb5a81 8068 case RPKI_INVALID:
b5b99af8 8069 return "invalid";
b5b99af8 8070 }
fdeb5a81
DS
8071
8072 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8073 return "ERROR";
8074}
8075
585f1adc
IR
8076static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8077 afi_t afi, safi_t safi)
718e3744 8078{
585f1adc
IR
8079 VTY_DECLVAR_CONTEXT(bgp, bgp);
8080 int ret;
8081 struct prefix p;
9bcb3eef 8082 struct bgp_dest *dest;
d62a17ae 8083 struct bgp_aggregate *aggregate;
718e3744 8084
585f1adc
IR
8085 /* Convert string to prefix structure. */
8086 ret = str2prefix(prefix_str, &p);
8087 if (!ret) {
8088 vty_out(vty, "Malformed prefix\n");
8089 return CMD_WARNING_CONFIG_FAILED;
8090 }
8091 apply_mask(&p);
a4559740 8092
d62a17ae 8093 /* Old configuration check. */
585f1adc 8094 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8095 if (!dest) {
585f1adc
IR
8096 vty_out(vty,
8097 "%% There is no aggregate-address configuration.\n");
8098 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8099 }
f6269b4f 8100
9bcb3eef 8101 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8102 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8103 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8104 NULL, NULL, 0, aggregate);
d62a17ae 8105
8106 /* Unlock aggregate address configuration. */
9bcb3eef 8107 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8108
8109 if (aggregate->community)
8110 community_free(&aggregate->community);
8111
8112 if (aggregate->community_hash) {
8113 /* Delete all communities in the hash.
8114 */
8115 hash_clean(aggregate->community_hash,
8116 bgp_aggr_community_remove);
8117 /* Free up the community_hash.
8118 */
8119 hash_free(aggregate->community_hash);
8120 }
8121
8122 if (aggregate->ecommunity)
8123 ecommunity_free(&aggregate->ecommunity);
8124
8125 if (aggregate->ecommunity_hash) {
8126 /* Delete all ecommunities in the hash.
8127 */
8128 hash_clean(aggregate->ecommunity_hash,
8129 bgp_aggr_ecommunity_remove);
8130 /* Free up the ecommunity_hash.
8131 */
8132 hash_free(aggregate->ecommunity_hash);
8133 }
8134
8135 if (aggregate->lcommunity)
8136 lcommunity_free(&aggregate->lcommunity);
8137
8138 if (aggregate->lcommunity_hash) {
8139 /* Delete all lcommunities in the hash.
8140 */
8141 hash_clean(aggregate->lcommunity_hash,
8142 bgp_aggr_lcommunity_remove);
8143 /* Free up the lcommunity_hash.
8144 */
8145 hash_free(aggregate->lcommunity_hash);
8146 }
8147
8148 if (aggregate->aspath)
8149 aspath_free(aggregate->aspath);
8150
8151 if (aggregate->aspath_hash) {
8152 /* Delete all as-paths in the hash.
8153 */
8154 hash_clean(aggregate->aspath_hash,
8155 bgp_aggr_aspath_remove);
8156 /* Free up the aspath_hash.
8157 */
8158 hash_free(aggregate->aspath_hash);
8159 }
8160
d62a17ae 8161 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8162 bgp_dest_unlock_node(dest);
8163 bgp_dest_unlock_node(dest);
d62a17ae 8164
585f1adc 8165 return CMD_SUCCESS;
d62a17ae 8166}
8167
585f1adc
IR
8168static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8169 safi_t safi, const char *rmap,
8170 uint8_t summary_only, uint8_t as_set,
8171 uint8_t origin, bool match_med,
8172 const char *suppress_map)
d62a17ae 8173{
585f1adc 8174 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8175 int ret;
585f1adc 8176 struct prefix p;
9bcb3eef 8177 struct bgp_dest *dest;
d62a17ae 8178 struct bgp_aggregate *aggregate;
fb29348a 8179 uint8_t as_set_new = as_set;
d62a17ae 8180
365ab2e7 8181 if (suppress_map && summary_only) {
585f1adc 8182 vty_out(vty,
365ab2e7 8183 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8184 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8185 }
8186
585f1adc
IR
8187 /* Convert string to prefix structure. */
8188 ret = str2prefix(prefix_str, &p);
8189 if (!ret) {
8190 vty_out(vty, "Malformed prefix\n");
8191 return CMD_WARNING_CONFIG_FAILED;
8192 }
8193 apply_mask(&p);
d62a17ae 8194
585f1adc
IR
8195 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8196 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8197 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8198 prefix_str);
8199 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8200 }
8201
d62a17ae 8202 /* Old configuration check. */
585f1adc 8203 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8204 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8205
20894f50 8206 if (aggregate) {
585f1adc 8207 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8208 /* try to remove the old entry */
585f1adc 8209 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8210 if (ret) {
585f1adc 8211 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8212 bgp_dest_unlock_node(dest);
585f1adc 8213 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8214 }
8215 }
718e3744 8216
d62a17ae 8217 /* Make aggregate address structure. */
8218 aggregate = bgp_aggregate_new();
8219 aggregate->summary_only = summary_only;
6aabb15d 8220 aggregate->match_med = match_med;
fb29348a
DA
8221
8222 /* Network operators MUST NOT locally generate any new
8223 * announcements containing AS_SET or AS_CONFED_SET. If they have
8224 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8225 * SHOULD withdraw those routes and re-announce routes for the
8226 * aggregate or component prefixes (i.e., the more-specific routes
8227 * subsumed by the previously aggregated route) without AS_SET
8228 * or AS_CONFED_SET in the updates.
8229 */
7f972cd8 8230 if (bgp->reject_as_sets) {
fb29348a
DA
8231 if (as_set == AGGREGATE_AS_SET) {
8232 as_set_new = AGGREGATE_AS_UNSET;
8233 zlog_warn(
63efca0e 8234 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8235 __func__);
585f1adc 8236 vty_out(vty,
fb29348a
DA
8237 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8238 }
8239 }
8240
8241 aggregate->as_set = as_set_new;
d62a17ae 8242 aggregate->safi = safi;
229757f1
DA
8243 /* Override ORIGIN attribute if defined.
8244 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8245 * to IGP which is not what rfc4271 says.
8246 * This enables the same behavior, optionally.
8247 */
8248 aggregate->origin = origin;
20894f50
DA
8249
8250 if (rmap) {
8251 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8252 route_map_counter_decrement(aggregate->rmap.map);
8253 aggregate->rmap.name =
8254 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8255 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8256 route_map_counter_increment(aggregate->rmap.map);
8257 }
365ab2e7
RZ
8258
8259 if (suppress_map) {
8260 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8261 route_map_counter_decrement(aggregate->suppress_map);
8262
8263 aggregate->suppress_map_name =
8264 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8265 aggregate->suppress_map =
8266 route_map_lookup_by_name(aggregate->suppress_map_name);
8267 route_map_counter_increment(aggregate->suppress_map);
8268 }
8269
9bcb3eef 8270 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8271
d62a17ae 8272 /* Aggregate address insert into BGP routing table. */
585f1adc 8273 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8274
585f1adc 8275 return CMD_SUCCESS;
718e3744 8276}
8277
585f1adc
IR
8278DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8279 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8280 "as-set$as_set_s"
8281 "|summary-only$summary_only"
cacba915 8282 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8283 "|origin <egp|igp|incomplete>$origin_s"
8284 "|matching-MED-only$match_med"
cacba915 8285 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8286 "}]",
8287 NO_STR
8288 "Configure BGP aggregate entries\n"
764402fe
DA
8289 "Aggregate prefix\n"
8290 "Aggregate address\n"
8291 "Aggregate mask\n"
585f1adc
IR
8292 "Generate AS set path information\n"
8293 "Filter more specific routes from updates\n"
8294 "Apply route map to aggregate network\n"
8295 "Route map name\n"
8296 "BGP origin code\n"
8297 "Remote EGP\n"
8298 "Local IGP\n"
8299 "Unknown heritage\n"
8300 "Only aggregate routes with matching MED\n"
8301 "Suppress the selected more specific routes\n"
8302 "Route map with the route selectors\n")
8303{
8304 const char *prefix_s = NULL;
554b3b10 8305 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8306 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8307 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8308 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8309
554b3b10 8310 if (addr_str) {
7533cad7
QY
8311 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8312 sizeof(prefix_buf))
554b3b10
RZ
8313 == 0) {
8314 vty_out(vty, "%% Inconsistent address and mask\n");
8315 return CMD_WARNING_CONFIG_FAILED;
8316 }
585f1adc
IR
8317 prefix_s = prefix_buf;
8318 } else
8319 prefix_s = prefix_str;
37a87b8f 8320
585f1adc
IR
8321 if (origin_s) {
8322 if (strcmp(origin_s, "egp") == 0)
8323 origin = BGP_ORIGIN_EGP;
8324 else if (strcmp(origin_s, "igp") == 0)
8325 origin = BGP_ORIGIN_IGP;
8326 else if (strcmp(origin_s, "incomplete") == 0)
8327 origin = BGP_ORIGIN_INCOMPLETE;
8328 }
90e21f35 8329
585f1adc
IR
8330 if (as_set_s)
8331 as_set = AGGREGATE_AS_SET;
554b3b10 8332
585f1adc 8333 /* Handle configuration removal, otherwise installation. */
554b3b10 8334 if (no)
585f1adc
IR
8335 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8336
8337 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8338 summary_only != NULL, as_set, origin,
8339 match_med != NULL, suppress_map);
8340}
8341
8342DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8343 "[no] aggregate-address X:X::X:X/M$prefix [{"
8344 "as-set$as_set_s"
8345 "|summary-only$summary_only"
cacba915 8346 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8347 "|origin <egp|igp|incomplete>$origin_s"
8348 "|matching-MED-only$match_med"
cacba915 8349 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8350 "}]",
8351 NO_STR
8352 "Configure BGP aggregate entries\n"
8353 "Aggregate prefix\n"
8354 "Generate AS set path information\n"
8355 "Filter more specific routes from updates\n"
8356 "Apply route map to aggregate network\n"
8357 "Route map name\n"
8358 "BGP origin code\n"
8359 "Remote EGP\n"
8360 "Local IGP\n"
8361 "Unknown heritage\n"
8362 "Only aggregate routes with matching MED\n"
8363 "Suppress the selected more specific routes\n"
8364 "Route map with the route selectors\n")
8365{
8366 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8367 int as_set = AGGREGATE_AS_UNSET;
8368
8369 if (origin_s) {
8370 if (strcmp(origin_s, "egp") == 0)
8371 origin = BGP_ORIGIN_EGP;
8372 else if (strcmp(origin_s, "igp") == 0)
8373 origin = BGP_ORIGIN_IGP;
8374 else if (strcmp(origin_s, "incomplete") == 0)
8375 origin = BGP_ORIGIN_INCOMPLETE;
8376 }
8377
8378 if (as_set_s)
8379 as_set = AGGREGATE_AS_SET;
8380
8381 /* Handle configuration removal, otherwise installation. */
554b3b10 8382 if (no)
585f1adc
IR
8383 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8384 SAFI_UNICAST);
554b3b10 8385
585f1adc
IR
8386 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8387 rmap_name, summary_only != NULL, as_set,
8388 origin, match_med != NULL, suppress_map);
718e3744 8389}
8390
718e3744 8391/* Redistribute route treatment. */
d62a17ae 8392void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8393 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8394 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8395 enum blackhole_type bhtype, uint32_t metric,
8396 uint8_t type, unsigned short instance,
8397 route_tag_t tag)
d62a17ae 8398{
4b7e6066 8399 struct bgp_path_info *new;
40381db7
DS
8400 struct bgp_path_info *bpi;
8401 struct bgp_path_info rmap_path;
9bcb3eef 8402 struct bgp_dest *bn;
d62a17ae 8403 struct attr attr;
8404 struct attr *new_attr;
8405 afi_t afi;
b68885f9 8406 route_map_result_t ret;
d62a17ae 8407 struct bgp_redist *red;
8408
8409 /* Make default attribute. */
0f05ea43 8410 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8411 /*
8412 * This must not be NULL to satisfy Coverity SA
8413 */
8414 assert(attr.aspath);
9de1f7ff 8415
a4d82a8a 8416 switch (nhtype) {
9de1f7ff
DS
8417 case NEXTHOP_TYPE_IFINDEX:
8418 break;
8419 case NEXTHOP_TYPE_IPV4:
8420 case NEXTHOP_TYPE_IPV4_IFINDEX:
8421 attr.nexthop = nexthop->ipv4;
7226bc40 8422 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8423 break;
8424 case NEXTHOP_TYPE_IPV6:
8425 case NEXTHOP_TYPE_IPV6_IFINDEX:
8426 attr.mp_nexthop_global = nexthop->ipv6;
8427 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8428 break;
8429 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8430 switch (p->family) {
8431 case AF_INET:
9de1f7ff 8432 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8433 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8434 break;
8435 case AF_INET6:
9de1f7ff
DS
8436 memset(&attr.mp_nexthop_global, 0,
8437 sizeof(attr.mp_nexthop_global));
74489921 8438 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8439 break;
74489921 8440 }
0789eb69 8441 attr.bh_type = bhtype;
9de1f7ff 8442 break;
d62a17ae 8443 }
0789eb69 8444 attr.nh_type = nhtype;
74489921 8445 attr.nh_ifindex = ifindex;
f04a80a5 8446
d62a17ae 8447 attr.med = metric;
957f74c3 8448 attr.distance = distance;
d62a17ae 8449 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8450 attr.tag = tag;
718e3744 8451
d62a17ae 8452 afi = family2afi(p->family);
6aeb9e78 8453
d62a17ae 8454 red = bgp_redist_lookup(bgp, afi, type, instance);
8455 if (red) {
8456 struct attr attr_new;
718e3744 8457
d62a17ae 8458 /* Copy attribute for modification. */
6f4f49b2 8459 attr_new = attr;
718e3744 8460
d62a17ae 8461 if (red->redist_metric_flag)
8462 attr_new.med = red->redist_metric;
718e3744 8463
d62a17ae 8464 /* Apply route-map. */
8465 if (red->rmap.name) {
6006b807 8466 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8467 rmap_path.peer = bgp->peer_self;
8468 rmap_path.attr = &attr_new;
718e3744 8469
d62a17ae 8470 SET_FLAG(bgp->peer_self->rmap_type,
8471 PEER_RMAP_TYPE_REDISTRIBUTE);
8472
1782514f 8473 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8474
8475 bgp->peer_self->rmap_type = 0;
8476
8477 if (ret == RMAP_DENYMATCH) {
8478 /* Free uninterned attribute. */
8479 bgp_attr_flush(&attr_new);
8480
8481 /* Unintern original. */
8482 aspath_unintern(&attr.aspath);
8483 bgp_redistribute_delete(bgp, p, type, instance);
8484 return;
8485 }
8486 }
8487
637e5ba4 8488 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8489 bgp_attr_add_gshut_community(&attr_new);
8490
d62a17ae 8491 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8492 SAFI_UNICAST, p, NULL);
8493
8494 new_attr = bgp_attr_intern(&attr_new);
8495
9bcb3eef 8496 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8497 if (bpi->peer == bgp->peer_self
8498 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8499 break;
8500
40381db7 8501 if (bpi) {
d62a17ae 8502 /* Ensure the (source route) type is updated. */
40381db7
DS
8503 bpi->type = type;
8504 if (attrhash_cmp(bpi->attr, new_attr)
8505 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8506 bgp_attr_unintern(&new_attr);
8507 aspath_unintern(&attr.aspath);
9bcb3eef 8508 bgp_dest_unlock_node(bn);
d62a17ae 8509 return;
8510 } else {
8511 /* The attribute is changed. */
40381db7 8512 bgp_path_info_set_flag(bn, bpi,
18ee8310 8513 BGP_PATH_ATTR_CHANGED);
d62a17ae 8514
8515 /* Rewrite BGP route information. */
40381db7
DS
8516 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8517 bgp_path_info_restore(bn, bpi);
d62a17ae 8518 else
40381db7
DS
8519 bgp_aggregate_decrement(
8520 bgp, p, bpi, afi, SAFI_UNICAST);
8521 bgp_attr_unintern(&bpi->attr);
8522 bpi->attr = new_attr;
8523 bpi->uptime = bgp_clock();
d62a17ae 8524
8525 /* Process change. */
40381db7 8526 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8527 SAFI_UNICAST);
8528 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8529 bgp_dest_unlock_node(bn);
d62a17ae 8530 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8531
8532 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8533 || (bgp->inst_type
8534 == BGP_INSTANCE_TYPE_DEFAULT)) {
8535
8536 vpn_leak_from_vrf_update(
40381db7 8537 bgp_get_default(), bgp, bpi);
ddb5b488 8538 }
d62a17ae 8539 return;
8540 }
8541 }
8542
8543 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8544 bgp->peer_self, new_attr, bn);
1defdda8 8545 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8546
8547 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8548 bgp_path_info_add(bn, new);
9bcb3eef 8549 bgp_dest_unlock_node(bn);
be785e35 8550 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8551 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8552
8553 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8554 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8555
8556 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8557 }
d62a17ae 8558 }
8559
8560 /* Unintern original. */
8561 aspath_unintern(&attr.aspath);
718e3744 8562}
8563
d7c0a89a
QY
8564void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8565 unsigned short instance)
718e3744 8566{
d62a17ae 8567 afi_t afi;
9bcb3eef 8568 struct bgp_dest *dest;
40381db7 8569 struct bgp_path_info *pi;
d62a17ae 8570 struct bgp_redist *red;
718e3744 8571
d62a17ae 8572 afi = family2afi(p->family);
718e3744 8573
d62a17ae 8574 red = bgp_redist_lookup(bgp, afi, type, instance);
8575 if (red) {
9bcb3eef
DS
8576 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8577 SAFI_UNICAST, p, NULL);
d62a17ae 8578
9bcb3eef 8579 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8580 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8581 break;
8582
40381db7 8583 if (pi) {
ddb5b488
PZ
8584 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8585 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8586
8587 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8588 bgp, pi);
ddb5b488 8589 }
40381db7 8590 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8591 bgp_path_info_delete(dest, pi);
8592 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8593 }
9bcb3eef 8594 bgp_dest_unlock_node(dest);
d62a17ae 8595 }
8596}
8597
8598/* Withdraw specified route type's route. */
8599void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8600 unsigned short instance)
d62a17ae 8601{
9bcb3eef 8602 struct bgp_dest *dest;
40381db7 8603 struct bgp_path_info *pi;
d62a17ae 8604 struct bgp_table *table;
8605
8606 table = bgp->rib[afi][SAFI_UNICAST];
8607
9bcb3eef
DS
8608 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8609 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8610 if (pi->peer == bgp->peer_self && pi->type == type
8611 && pi->instance == instance)
d62a17ae 8612 break;
8613
40381db7 8614 if (pi) {
ddb5b488
PZ
8615 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8616 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8617
8618 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8619 bgp, pi);
ddb5b488 8620 }
9bcb3eef 8621 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8622 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8623 bgp_path_info_delete(dest, pi);
8624 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8625 }
718e3744 8626 }
718e3744 8627}
6b0655a2 8628
718e3744 8629/* Static function to display route. */
7d3cae70
DA
8630static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8631 struct vty *vty, json_object *json, bool wide)
718e3744 8632{
be054588 8633 int len = 0;
d62a17ae 8634 char buf[BUFSIZ];
718e3744 8635
d62a17ae 8636 if (p->family == AF_INET) {
c6462ff4 8637 if (!json) {
8228a9a7 8638 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8639 } else {
8640 json_object_string_add(json, "prefix",
8641 inet_ntop(p->family,
8642 &p->u.prefix, buf,
8643 BUFSIZ));
8644 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8645 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8646 json_object_int_add(json, "version", dest->version);
c6462ff4 8647 }
d62a17ae 8648 } else if (p->family == AF_ETHERNET) {
8228a9a7 8649 len = vty_out(vty, "%pFX", p);
b03b8898 8650 } else if (p->family == AF_EVPN) {
57f7feb6 8651 if (!json)
2dbe669b 8652 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8653 else
60466a63 8654 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8655 } else if (p->family == AF_FLOWSPEC) {
8656 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8657 json ?
8658 NLRI_STRING_FORMAT_JSON_SIMPLE :
8659 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8660 } else {
c6462ff4 8661 if (!json)
8228a9a7 8662 len = vty_out(vty, "%pFX", p);
50e05855
AD
8663 else {
8664 json_object_string_add(json, "prefix",
8665 inet_ntop(p->family,
8666 &p->u.prefix, buf,
8667 BUFSIZ));
8668 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8669 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8670 json_object_int_add(json, "version", dest->version);
37d4e0df 8671 }
9c92b5f7 8672 }
d62a17ae 8673
9c92b5f7 8674 if (!json) {
ae248832 8675 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8676 if (len < 1)
8677 vty_out(vty, "\n%*s", 20, " ");
8678 else
8679 vty_out(vty, "%*s", len, " ");
8680 }
718e3744 8681}
8682
d62a17ae 8683enum bgp_display_type {
8684 normal_list,
718e3744 8685};
8686
1d7260a1 8687const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8688{
8689 switch (reason) {
8690 case bgp_path_selection_none:
8691 return "Nothing to Select";
8692 case bgp_path_selection_first:
8693 return "First path received";
8694 case bgp_path_selection_evpn_sticky_mac:
8695 return "EVPN Sticky Mac";
8696 case bgp_path_selection_evpn_seq:
8697 return "EVPN sequence number";
8698 case bgp_path_selection_evpn_lower_ip:
8699 return "EVPN lower IP";
8700 case bgp_path_selection_evpn_local_path:
8701 return "EVPN local ES path";
8702 case bgp_path_selection_evpn_non_proxy:
8703 return "EVPN non proxy";
8704 case bgp_path_selection_weight:
8705 return "Weight";
8706 case bgp_path_selection_local_pref:
8707 return "Local Pref";
8708 case bgp_path_selection_local_route:
8709 return "Local Route";
8710 case bgp_path_selection_confed_as_path:
8711 return "Confederation based AS Path";
8712 case bgp_path_selection_as_path:
8713 return "AS Path";
8714 case bgp_path_selection_origin:
8715 return "Origin";
8716 case bgp_path_selection_med:
8717 return "MED";
8718 case bgp_path_selection_peer:
8719 return "Peer Type";
8720 case bgp_path_selection_confed:
8721 return "Confed Peer Type";
8722 case bgp_path_selection_igp_metric:
8723 return "IGP Metric";
8724 case bgp_path_selection_older:
8725 return "Older Path";
8726 case bgp_path_selection_router_id:
8727 return "Router ID";
8728 case bgp_path_selection_cluster_length:
bcab253c 8729 return "Cluster length";
bbb46eb5
DA
8730 case bgp_path_selection_stale:
8731 return "Path Staleness";
8732 case bgp_path_selection_local_configured:
8733 return "Locally configured route";
8734 case bgp_path_selection_neighbor_ip:
8735 return "Neighbor IP";
8736 case bgp_path_selection_default:
8737 return "Nothing left to compare";
8738 }
8739 return "Invalid (internal error)";
8740}
8741
18ee8310 8742/* Print the short form route status for a bgp_path_info */
4b7e6066 8743static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8744 struct bgp_path_info *path,
82c298be 8745 const struct prefix *p,
d62a17ae 8746 json_object *json_path)
718e3744 8747{
82c298be
DA
8748 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8749
d62a17ae 8750 if (json_path) {
b05a1c8b 8751
d62a17ae 8752 /* Route status display. */
9b6d8fcf 8753 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8754 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8755
9b6d8fcf 8756 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8757 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8758
4056a5f6 8759 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8760 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8761
9b6d8fcf
DS
8762 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8763 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8764 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8765
d62a17ae 8766 /* Selected */
9b6d8fcf 8767 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8768 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8769
9b6d8fcf 8770 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8771 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8772
bbb46eb5 8773 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8774 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8775 json_object_string_add(json_path, "selectionReason",
8776 bgp_path_selection_reason2str(
8777 path->net->reason));
8778 }
b05a1c8b 8779
9b6d8fcf 8780 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8781 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8782
d62a17ae 8783 /* Internal route. */
9b6d8fcf
DS
8784 if ((path->peer->as)
8785 && (path->peer->as == path->peer->local_as))
d62a17ae 8786 json_object_string_add(json_path, "pathFrom",
8787 "internal");
8788 else
8789 json_object_string_add(json_path, "pathFrom",
8790 "external");
b05a1c8b 8791
d62a17ae 8792 return;
8793 }
b05a1c8b 8794
82c298be
DA
8795 /* RPKI validation state */
8796 rpki_state =
8797 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8798
8799 if (rpki_state == RPKI_VALID)
8800 vty_out(vty, "V");
8801 else if (rpki_state == RPKI_INVALID)
8802 vty_out(vty, "I");
8803 else if (rpki_state == RPKI_NOTFOUND)
8804 vty_out(vty, "N");
8805
d62a17ae 8806 /* Route status display. */
9b6d8fcf 8807 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8808 vty_out(vty, "R");
9b6d8fcf 8809 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8810 vty_out(vty, "S");
4056a5f6 8811 else if (bgp_path_suppressed(path))
d62a17ae 8812 vty_out(vty, "s");
9b6d8fcf
DS
8813 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8814 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8815 vty_out(vty, "*");
8816 else
8817 vty_out(vty, " ");
8818
8819 /* Selected */
9b6d8fcf 8820 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8821 vty_out(vty, "h");
9b6d8fcf 8822 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8823 vty_out(vty, "d");
9b6d8fcf 8824 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8825 vty_out(vty, ">");
9b6d8fcf 8826 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8827 vty_out(vty, "=");
8828 else
8829 vty_out(vty, " ");
718e3744 8830
d62a17ae 8831 /* Internal route. */
9b6d8fcf
DS
8832 if (path->peer && (path->peer->as)
8833 && (path->peer->as == path->peer->local_as))
d62a17ae 8834 vty_out(vty, "i");
8835 else
8836 vty_out(vty, " ");
b40d939b 8837}
8838
2ba93fd6
DA
8839static char *bgp_nexthop_hostname(struct peer *peer,
8840 struct bgp_nexthop_cache *bnc)
25b5da8d 8841{
892fedb6 8842 if (peer->hostname
aef999a2 8843 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8844 return peer->hostname;
8845 return NULL;
8846}
8847
b40d939b 8848/* called from terminal list command */
bd494ec5 8849void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8850 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8851 json_object *json_paths, bool wide)
d62a17ae 8852{
aef999a2 8853 int len;
515c2602 8854 struct attr *attr = path->attr;
d62a17ae 8855 json_object *json_path = NULL;
8856 json_object *json_nexthops = NULL;
8857 json_object *json_nexthop_global = NULL;
8858 json_object *json_nexthop_ll = NULL;
6f214dd3 8859 json_object *json_ext_community = NULL;
9df8b37c 8860 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8861 bool nexthop_self =
9b6d8fcf 8862 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8863 bool nexthop_othervrf = false;
43089216 8864 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8865 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8866 char *nexthop_hostname =
8867 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8868 char esi_buf[ESI_STR_LEN];
d62a17ae 8869
8870 if (json_paths)
8871 json_path = json_object_new_object();
8872
8873 /* short status lead text */
82c298be 8874 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8875
8876 if (!json_paths) {
8877 /* print prefix and mask */
8878 if (!display)
7d3cae70 8879 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8880 else
ae248832 8881 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8882 } else {
7d3cae70 8883 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8884 }
47fc97cc 8885
9df8b37c
PZ
8886 /*
8887 * If vrf id of nexthop is different from that of prefix,
8888 * set up printable string to append
8889 */
9b6d8fcf 8890 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8891 const char *self = "";
8892
8893 if (nexthop_self)
8894 self = "<";
8895
8896 nexthop_othervrf = true;
9b6d8fcf 8897 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8898
9b6d8fcf 8899 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8900 snprintf(vrf_id_str, sizeof(vrf_id_str),
8901 "@%s%s", VRFID_NONE_STR, self);
8902 else
8903 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8904 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8905
9b6d8fcf
DS
8906 if (path->extra->bgp_orig->inst_type
8907 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8908
9b6d8fcf 8909 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8910 } else {
8911 const char *self = "";
8912
8913 if (nexthop_self)
8914 self = "<";
8915
8916 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8917 }
8918
445c2480
DS
8919 /*
8920 * For ENCAP and EVPN routes, nexthop address family is not
8921 * neccessarily the same as the prefix address family.
8922 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8923 * EVPN routes are also exchanged with a MP nexthop. Currently,
8924 * this
8925 * is only IPv4, the value will be present in either
8926 * attr->nexthop or
8927 * attr->mp_nexthop_global_in
8928 */
8929 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8930 char buf[BUFSIZ];
8931 char nexthop[128];
8932 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8933
8934 switch (af) {
8935 case AF_INET:
772270f3
QY
8936 snprintf(nexthop, sizeof(nexthop), "%s",
8937 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8938 BUFSIZ));
445c2480
DS
8939 break;
8940 case AF_INET6:
772270f3
QY
8941 snprintf(nexthop, sizeof(nexthop), "%s",
8942 inet_ntop(af, &attr->mp_nexthop_global, buf,
8943 BUFSIZ));
445c2480
DS
8944 break;
8945 default:
772270f3 8946 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8947 break;
d62a17ae 8948 }
d62a17ae 8949
445c2480
DS
8950 if (json_paths) {
8951 json_nexthop_global = json_object_new_object();
8952
515c2602
DA
8953 json_object_string_add(json_nexthop_global, "ip",
8954 nexthop);
8955
939a97f4 8956 if (path->peer->hostname)
515c2602
DA
8957 json_object_string_add(json_nexthop_global,
8958 "hostname",
939a97f4 8959 path->peer->hostname);
515c2602
DA
8960
8961 json_object_string_add(json_nexthop_global, "afi",
8962 (af == AF_INET) ? "ipv4"
8963 : "ipv6");
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, "%s(%s)%s", nexthop,
8969 nexthop_hostname, vrf_id_str);
8970 else
8971 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8972
ae248832 8973 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8974 if (len < 1)
8975 vty_out(vty, "\n%*s", 36, " ");
8976 else
8977 vty_out(vty, "%*s", len, " ");
8978 }
445c2480
DS
8979 } else if (safi == SAFI_EVPN) {
8980 if (json_paths) {
8981 json_nexthop_global = json_object_new_object();
8982
c949c771 8983 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
8984 "%pI4",
8985 &attr->mp_nexthop_global_in);
515c2602 8986
939a97f4 8987 if (path->peer->hostname)
515c2602
DA
8988 json_object_string_add(json_nexthop_global,
8989 "hostname",
939a97f4 8990 path->peer->hostname);
515c2602 8991
a4d82a8a
PZ
8992 json_object_string_add(json_nexthop_global, "afi",
8993 "ipv4");
445c2480
DS
8994 json_object_boolean_true_add(json_nexthop_global,
8995 "used");
aef999a2
DA
8996 } else {
8997 if (nexthop_hostname)
7226bc40
TA
8998 len = vty_out(vty, "%pI4(%s)%s",
8999 &attr->mp_nexthop_global_in,
aef999a2
DA
9000 nexthop_hostname, vrf_id_str);
9001 else
7226bc40
TA
9002 len = vty_out(vty, "%pI4%s",
9003 &attr->mp_nexthop_global_in,
aef999a2
DA
9004 vrf_id_str);
9005
ae248832 9006 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9007 if (len < 1)
9008 vty_out(vty, "\n%*s", 36, " ");
9009 else
9010 vty_out(vty, "%*s", len, " ");
9011 }
d33fc23b 9012 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9013 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9014 if (json_paths) {
9015 json_nexthop_global = json_object_new_object();
515c2602 9016
026b914a
PG
9017 json_object_string_add(json_nexthop_global,
9018 "afi", "ipv4");
c949c771
DA
9019 json_object_string_addf(json_nexthop_global,
9020 "ip", "%pI4",
9021 &attr->nexthop);
515c2602 9022
939a97f4 9023 if (path->peer->hostname)
515c2602
DA
9024 json_object_string_add(
9025 json_nexthop_global, "hostname",
939a97f4 9026 path->peer->hostname);
515c2602 9027
50e05855
AD
9028 json_object_boolean_true_add(
9029 json_nexthop_global,
026b914a
PG
9030 "used");
9031 } else {
aef999a2
DA
9032 if (nexthop_hostname)
9033 len = vty_out(vty, "%pI4(%s)%s",
9034 &attr->nexthop,
9035 nexthop_hostname,
9036 vrf_id_str);
9037 else
9038 len = vty_out(vty, "%pI4%s",
9039 &attr->nexthop,
9040 vrf_id_str);
9041
ae248832 9042 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9043 if (len < 1)
9044 vty_out(vty, "\n%*s", 36, " ");
9045 else
9046 vty_out(vty, "%*s", len, " ");
026b914a
PG
9047 }
9048 }
7226bc40 9049 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9050 if (json_paths) {
9051 json_nexthop_global = json_object_new_object();
d62a17ae 9052
c949c771
DA
9053 json_object_string_addf(json_nexthop_global, "ip",
9054 "%pI4", &attr->nexthop);
515c2602 9055
939a97f4 9056 if (path->peer->hostname)
515c2602
DA
9057 json_object_string_add(json_nexthop_global,
9058 "hostname",
939a97f4 9059 path->peer->hostname);
445c2480 9060
a4d82a8a
PZ
9061 json_object_string_add(json_nexthop_global, "afi",
9062 "ipv4");
445c2480
DS
9063 json_object_boolean_true_add(json_nexthop_global,
9064 "used");
9065 } else {
aef999a2
DA
9066 if (nexthop_hostname)
9067 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9068 nexthop_hostname, vrf_id_str);
9069 else
9070 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9071 vrf_id_str);
9df8b37c 9072
ae248832 9073 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9074 if (len < 1)
9075 vty_out(vty, "\n%*s", 36, " ");
9076 else
9077 vty_out(vty, "%*s", len, " ");
d62a17ae 9078 }
445c2480 9079 }
b05a1c8b 9080
445c2480 9081 /* IPv6 Next Hop */
7226bc40 9082 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9083 if (json_paths) {
9084 json_nexthop_global = json_object_new_object();
c949c771
DA
9085 json_object_string_addf(json_nexthop_global, "ip",
9086 "%pI6",
9087 &attr->mp_nexthop_global);
515c2602 9088
939a97f4 9089 if (path->peer->hostname)
515c2602
DA
9090 json_object_string_add(json_nexthop_global,
9091 "hostname",
939a97f4 9092 path->peer->hostname);
515c2602 9093
a4d82a8a
PZ
9094 json_object_string_add(json_nexthop_global, "afi",
9095 "ipv6");
9096 json_object_string_add(json_nexthop_global, "scope",
9097 "global");
445c2480
DS
9098
9099 /* We display both LL & GL if both have been
9100 * received */
0606039c
DA
9101 if ((attr->mp_nexthop_len
9102 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9103 || (path->peer->conf_if)) {
a4d82a8a 9104 json_nexthop_ll = json_object_new_object();
c949c771
DA
9105 json_object_string_addf(
9106 json_nexthop_ll, "ip", "%pI6",
9107 &attr->mp_nexthop_local);
515c2602 9108
939a97f4 9109 if (path->peer->hostname)
515c2602
DA
9110 json_object_string_add(
9111 json_nexthop_ll, "hostname",
939a97f4 9112 path->peer->hostname);
515c2602 9113
a4d82a8a
PZ
9114 json_object_string_add(json_nexthop_ll, "afi",
9115 "ipv6");
9116 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9117 "link-local");
d62a17ae 9118
a4d82a8a
PZ
9119 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9120 &attr->mp_nexthop_local)
445c2480
DS
9121 != 0)
9122 && !attr->mp_nexthop_prefer_global)
d62a17ae 9123 json_object_boolean_true_add(
a4d82a8a 9124 json_nexthop_ll, "used");
445c2480
DS
9125 else
9126 json_object_boolean_true_add(
a4d82a8a 9127 json_nexthop_global, "used");
445c2480
DS
9128 } else
9129 json_object_boolean_true_add(
9130 json_nexthop_global, "used");
9131 } else {
9132 /* Display LL if LL/Global both in table unless
9133 * prefer-global is set */
0606039c
DA
9134 if (((attr->mp_nexthop_len
9135 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9136 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9137 || (path->peer->conf_if)) {
9138 if (path->peer->conf_if) {
a4d82a8a 9139 len = vty_out(vty, "%s",
9b6d8fcf 9140 path->peer->conf_if);
ae248832
MK
9141 /* len of IPv6 addr + max len of def
9142 * ifname */
9143 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9144
9145 if (len < 1)
a4d82a8a 9146 vty_out(vty, "\n%*s", 36, " ");
445c2480 9147 else
a4d82a8a 9148 vty_out(vty, "%*s", len, " ");
d62a17ae 9149 } else {
aef999a2
DA
9150 if (nexthop_hostname)
9151 len = vty_out(
9152 vty, "%pI6(%s)%s",
9153 &attr->mp_nexthop_local,
9154 nexthop_hostname,
9155 vrf_id_str);
9156 else
9157 len = vty_out(
9158 vty, "%pI6%s",
9159 &attr->mp_nexthop_local,
9160 vrf_id_str);
9161
ae248832 9162 len = wide ? (41 - len) : (16 - len);
d62a17ae 9163
9164 if (len < 1)
a4d82a8a 9165 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9166 else
a4d82a8a 9167 vty_out(vty, "%*s", len, " ");
d62a17ae 9168 }
445c2480 9169 } else {
aef999a2
DA
9170 if (nexthop_hostname)
9171 len = vty_out(vty, "%pI6(%s)%s",
9172 &attr->mp_nexthop_global,
9173 nexthop_hostname,
9174 vrf_id_str);
9175 else
9176 len = vty_out(vty, "%pI6%s",
9177 &attr->mp_nexthop_global,
9178 vrf_id_str);
9179
ae248832 9180 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9181
9182 if (len < 1)
9183 vty_out(vty, "\n%*s", 36, " ");
9184 else
9185 vty_out(vty, "%*s", len, " ");
d62a17ae 9186 }
9187 }
445c2480 9188 }
718e3744 9189
445c2480
DS
9190 /* MED/Metric */
9191 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9192 if (json_paths)
50e05855 9193 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9194 else if (wide)
9195 vty_out(vty, "%7u", attr->med);
0fbac0b4 9196 else
445c2480 9197 vty_out(vty, "%10u", attr->med);
ae248832
MK
9198 else if (!json_paths) {
9199 if (wide)
9200 vty_out(vty, "%*s", 7, " ");
9201 else
9202 vty_out(vty, "%*s", 10, " ");
9203 }
d62a17ae 9204
445c2480
DS
9205 /* Local Pref */
9206 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9207 if (json_paths)
50e05855 9208 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9209 attr->local_pref);
9210 else
445c2480
DS
9211 vty_out(vty, "%7u", attr->local_pref);
9212 else if (!json_paths)
9213 vty_out(vty, " ");
d62a17ae 9214
445c2480
DS
9215 if (json_paths)
9216 json_object_int_add(json_path, "weight", attr->weight);
9217 else
9218 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9219
47e12884
DA
9220 if (json_paths)
9221 json_object_string_addf(json_path, "peerId", "%pSU",
9222 &path->peer->su);
b05a1c8b 9223
445c2480
DS
9224 /* Print aspath */
9225 if (attr->aspath) {
0fbac0b4 9226 if (json_paths)
50e05855 9227 json_object_string_add(json_path, "path",
0fbac0b4
DA
9228 attr->aspath->str);
9229 else
445c2480 9230 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9231 }
f1aa5d8a 9232
445c2480
DS
9233 /* Print origin */
9234 if (json_paths)
a4d82a8a
PZ
9235 json_object_string_add(json_path, "origin",
9236 bgp_origin_long_str[attr->origin]);
445c2480
DS
9237 else
9238 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9239
9df8b37c 9240 if (json_paths) {
d071f237 9241 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9242 json_object_string_add(json_path, "esi",
9243 esi_to_str(&attr->esi,
9244 esi_buf, sizeof(esi_buf)));
9245 }
6f214dd3
CS
9246 if (safi == SAFI_EVPN &&
9247 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9248 json_ext_community = json_object_new_object();
b53e67a3
DA
9249 json_object_string_add(
9250 json_ext_community, "string",
9251 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9252 json_object_object_add(json_path,
9253 "extendedCommunity",
9254 json_ext_community);
9255 }
9256
9df8b37c
PZ
9257 if (nexthop_self)
9258 json_object_boolean_true_add(json_path,
9259 "announceNexthopSelf");
9260 if (nexthop_othervrf) {
9261 json_object_string_add(json_path, "nhVrfName",
9262 nexthop_vrfname);
9263
9264 json_object_int_add(json_path, "nhVrfId",
9265 ((nexthop_vrfid == VRF_UNKNOWN)
9266 ? -1
9267 : (int)nexthop_vrfid));
9268 }
9269 }
9270
d62a17ae 9271 if (json_paths) {
9272 if (json_nexthop_global || json_nexthop_ll) {
9273 json_nexthops = json_object_new_array();
f1aa5d8a 9274
d62a17ae 9275 if (json_nexthop_global)
9276 json_object_array_add(json_nexthops,
9277 json_nexthop_global);
f1aa5d8a 9278
d62a17ae 9279 if (json_nexthop_ll)
9280 json_object_array_add(json_nexthops,
9281 json_nexthop_ll);
f1aa5d8a 9282
d62a17ae 9283 json_object_object_add(json_path, "nexthops",
9284 json_nexthops);
9285 }
9286
9287 json_object_array_add(json_paths, json_path);
9288 } else {
9289 vty_out(vty, "\n");
6f214dd3 9290
b5e140c8 9291 if (safi == SAFI_EVPN) {
d071f237 9292 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9293 /* XXX - add these params to the json out */
b5e140c8 9294 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9295 vty_out(vty, "ESI:%s",
9296 esi_to_str(&attr->esi, esi_buf,
9297 sizeof(esi_buf)));
60605cbc 9298
229587fb 9299 vty_out(vty, "\n");
b5e140c8
AK
9300 }
9301 if (attr->flag &
9302 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9303 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9304 vty_out(vty, "%s\n",
9305 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9306 }
6f214dd3
CS
9307 }
9308
49e5a4a0 9309#ifdef ENABLE_BGP_VNC
d62a17ae 9310 /* prints an additional line, indented, with VNC info, if
9311 * present */
9312 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9313 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9314#endif
d62a17ae 9315 }
9316}
718e3744 9317
9318/* called from terminal list command */
7d3cae70
DA
9319void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9320 const struct prefix *p, struct attr *attr, safi_t safi,
9321 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9322{
9323 json_object *json_status = NULL;
9324 json_object *json_net = NULL;
aef999a2 9325 int len;
d62a17ae 9326 char buff[BUFSIZ];
dc387b0f 9327
d62a17ae 9328 /* Route status display. */
9329 if (use_json) {
9330 json_status = json_object_new_object();
9331 json_net = json_object_new_object();
9332 } else {
9333 vty_out(vty, "*");
9334 vty_out(vty, ">");
9335 vty_out(vty, " ");
9336 }
718e3744 9337
d62a17ae 9338 /* print prefix and mask */
50e05855 9339 if (use_json) {
dc387b0f
LK
9340 if (safi == SAFI_EVPN)
9341 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9342 else if (p->family == AF_INET || p->family == AF_INET6) {
9343 json_object_string_add(
9344 json_net, "addrPrefix",
9345 inet_ntop(p->family, &p->u.prefix, buff,
9346 BUFSIZ));
9347 json_object_int_add(json_net, "prefixLen",
9348 p->prefixlen);
67d7e256 9349 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9350 }
50e05855 9351 } else
7d3cae70 9352 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9353
9354 /* Print attribute */
9355 if (attr) {
9356 if (use_json) {
7226bc40
TA
9357 if (p->family == AF_INET &&
9358 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9359 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9360 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9361 json_object_string_addf(
9362 json_net, "nextHop", "%pI4",
9363 &attr->mp_nexthop_global_in);
d62a17ae 9364 else
c949c771
DA
9365 json_object_string_addf(
9366 json_net, "nextHop", "%pI4",
9367 &attr->nexthop);
7226bc40
TA
9368 } else if (p->family == AF_INET6 ||
9369 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9370 json_object_string_addf(
9371 json_net, "nextHopGlobal", "%pI6",
9372 &attr->mp_nexthop_global);
7226bc40
TA
9373 } else if (p->family == AF_EVPN &&
9374 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9375 json_object_string_addf(
9376 json_net, "nextHop", "%pI4",
9377 &attr->mp_nexthop_global_in);
23d0a753 9378 }
d62a17ae 9379
9380 if (attr->flag
9381 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9382 json_object_int_add(json_net, "metric",
9383 attr->med);
9384
0fbac0b4 9385 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9386 json_object_int_add(json_net, "locPrf",
0fbac0b4 9387 attr->local_pref);
d62a17ae 9388
9389 json_object_int_add(json_net, "weight", attr->weight);
9390
9391 /* Print aspath */
0fbac0b4 9392 if (attr->aspath)
50e05855 9393 json_object_string_add(json_net, "path",
0fbac0b4 9394 attr->aspath->str);
d62a17ae 9395
9396 /* Print origin */
9397 json_object_string_add(json_net, "bgpOriginCode",
9398 bgp_origin_str[attr->origin]);
9399 } else {
7226bc40
TA
9400 if (p->family == AF_INET &&
9401 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9402 safi == SAFI_EVPN ||
9403 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9404 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9405 || safi == SAFI_EVPN)
23d0a753
DA
9406 vty_out(vty, "%-16pI4",
9407 &attr->mp_nexthop_global_in);
ae248832 9408 else if (wide)
23d0a753 9409 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9410 else
23d0a753 9411 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9412 } else if (p->family == AF_INET6 ||
9413 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9414 char buf[BUFSIZ];
9415
9416 len = vty_out(
9417 vty, "%s",
9418 inet_ntop(AF_INET6,
9419 &attr->mp_nexthop_global, buf,
9420 BUFSIZ));
ae248832 9421 len = wide ? (41 - len) : (16 - len);
d62a17ae 9422 if (len < 1)
9423 vty_out(vty, "\n%*s", 36, " ");
9424 else
9425 vty_out(vty, "%*s", len, " ");
9426 }
9427 if (attr->flag
9428 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9429 if (wide)
9430 vty_out(vty, "%7u", attr->med);
9431 else
9432 vty_out(vty, "%10u", attr->med);
9433 else if (wide)
9434 vty_out(vty, " ");
d62a17ae 9435 else
9436 vty_out(vty, " ");
718e3744 9437
d62a17ae 9438 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9439 vty_out(vty, "%7u", attr->local_pref);
9440 else
9441 vty_out(vty, " ");
9442
9443 vty_out(vty, "%7u ", attr->weight);
9444
9445 /* Print aspath */
9446 if (attr->aspath)
9447 aspath_print_vty(vty, "%s", attr->aspath, " ");
9448
9449 /* Print origin */
9450 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9451 }
9452 }
9453 if (use_json) {
9454 json_object_boolean_true_add(json_status, "*");
9455 json_object_boolean_true_add(json_status, ">");
9456 json_object_object_add(json_net, "appliedStatusSymbols",
9457 json_status);
1608ff77 9458
dc387b0f
LK
9459 prefix2str(p, buff, PREFIX_STRLEN);
9460 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9461 } else
9462 vty_out(vty, "\n");
9463}
9464
bd494ec5 9465void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9466 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9467 json_object *json)
9468{
9469 json_object *json_out = NULL;
9470 struct attr *attr;
9471 mpls_label_t label = MPLS_INVALID_LABEL;
9472
9b6d8fcf 9473 if (!path->extra)
d62a17ae 9474 return;
9475
9476 if (json)
9477 json_out = json_object_new_object();
9478
9479 /* short status lead text */
82c298be 9480 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9481
9482 /* print prefix and mask */
9483 if (json == NULL) {
9484 if (!display)
7d3cae70 9485 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9486 else
9487 vty_out(vty, "%*s", 17, " ");
9488 }
9489
9490 /* Print attribute */
9b6d8fcf 9491 attr = path->attr;
7226bc40
TA
9492 if (((p->family == AF_INET) &&
9493 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9494 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9495 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9496 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9497 || safi == SAFI_EVPN) {
9498 if (json)
c949c771
DA
9499 json_object_string_addf(
9500 json_out, "mpNexthopGlobalIn", "%pI4",
9501 &attr->mp_nexthop_global_in);
05864da7 9502 else
23d0a753
DA
9503 vty_out(vty, "%-16pI4",
9504 &attr->mp_nexthop_global_in);
05864da7
DS
9505 } else {
9506 if (json)
c949c771
DA
9507 json_object_string_addf(json_out, "nexthop",
9508 "%pI4", &attr->nexthop);
05864da7 9509 else
23d0a753 9510 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9511 }
7226bc40
TA
9512 } else if (((p->family == AF_INET6) &&
9513 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9514 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9515 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9516 char buf_a[512];
9517
9518 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9519 if (json)
c949c771
DA
9520 json_object_string_addf(
9521 json_out, "mpNexthopGlobalIn", "%pI6",
9522 &attr->mp_nexthop_global);
05864da7
DS
9523 else
9524 vty_out(vty, "%s",
9525 inet_ntop(AF_INET6,
9526 &attr->mp_nexthop_global,
9527 buf_a, sizeof(buf_a)));
9528 } else if (attr->mp_nexthop_len
9529 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9530 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9531 &attr->mp_nexthop_global,
9532 &attr->mp_nexthop_local);
9533 if (json)
9534 json_object_string_add(json_out,
9535 "mpNexthopGlobalLocal",
9536 buf_a);
9537 else
9538 vty_out(vty, "%s", buf_a);
d62a17ae 9539 }
9540 }
9541
9b6d8fcf 9542 label = decode_label(&path->extra->label[0]);
d62a17ae 9543
9544 if (bgp_is_valid_label(&label)) {
9545 if (json) {
9546 json_object_int_add(json_out, "notag", label);
9547 json_object_array_add(json, json_out);
9548 } else {
9549 vty_out(vty, "notag/%d", label);
9550 vty_out(vty, "\n");
9551 }
700ddfed
PG
9552 } else if (!json)
9553 vty_out(vty, "\n");
d62a17ae 9554}
718e3744 9555
bd494ec5 9556void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9557 struct bgp_path_info *path, int display,
d62a17ae 9558 json_object *json_paths)
718e3744 9559{
d62a17ae 9560 struct attr *attr;
d62a17ae 9561 json_object *json_path = NULL;
14f51eba
LK
9562 json_object *json_nexthop = NULL;
9563 json_object *json_overlay = NULL;
856ca177 9564
9b6d8fcf 9565 if (!path->extra)
d62a17ae 9566 return;
718e3744 9567
14f51eba
LK
9568 if (json_paths) {
9569 json_path = json_object_new_object();
9570 json_overlay = json_object_new_object();
9571 json_nexthop = json_object_new_object();
9572 }
9573
d62a17ae 9574 /* short status lead text */
82c298be 9575 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9576
d62a17ae 9577 /* print prefix and mask */
9578 if (!display)
7d3cae70 9579 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9580 else
9581 vty_out(vty, "%*s", 17, " ");
9582
9583 /* Print attribute */
9b6d8fcf 9584 attr = path->attr;
05864da7 9585 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9586
05864da7
DS
9587 switch (af) {
9588 case AF_INET:
05864da7 9589 if (!json_path) {
db66cf7c 9590 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9591 } else {
db66cf7c
DA
9592 json_object_string_addf(json_nexthop, "ip", "%pI4",
9593 &attr->mp_nexthop_global_in);
14f51eba 9594
05864da7 9595 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9596
05864da7
DS
9597 json_object_object_add(json_path, "nexthop",
9598 json_nexthop);
9599 }
9600 break;
9601 case AF_INET6:
05864da7 9602 if (!json_path) {
db66cf7c
DA
9603 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9604 &attr->mp_nexthop_local);
05864da7 9605 } else {
db66cf7c
DA
9606 json_object_string_addf(json_nexthop, "ipv6Global",
9607 "%pI6",
9608 &attr->mp_nexthop_global);
14f51eba 9609
db66cf7c
DA
9610 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9611 "%pI6",
9612 &attr->mp_nexthop_local);
14f51eba 9613
05864da7 9614 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9615
05864da7
DS
9616 json_object_object_add(json_path, "nexthop",
9617 json_nexthop);
9618 }
9619 break;
9620 default:
9621 if (!json_path) {
9622 vty_out(vty, "?");
9623 } else {
9624 json_object_string_add(json_nexthop, "Error",
9625 "Unsupported address-family");
77a2f8e5
DA
9626 json_object_string_add(json_nexthop, "error",
9627 "Unsupported address-family");
d62a17ae 9628 }
05864da7 9629 }
988258b4 9630
6c924775
DS
9631 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9632
05864da7 9633 if (!json_path)
db66cf7c 9634 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9635 else
db66cf7c 9636 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9637
b53e67a3 9638 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9639 char *mac = NULL;
9640 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9641 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9642 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9643
9644 if (routermac)
9645 mac = ecom_mac2str((char *)routermac->val);
9646 if (mac) {
9647 if (!json_path) {
c4efd0f4 9648 vty_out(vty, "/%s", mac);
05864da7
DS
9649 } else {
9650 json_object_string_add(json_overlay, "rmac",
9651 mac);
988258b4 9652 }
05864da7 9653 XFREE(MTYPE_TMP, mac);
988258b4 9654 }
05864da7 9655 }
718e3744 9656
05864da7
DS
9657 if (!json_path) {
9658 vty_out(vty, "\n");
9659 } else {
9660 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9661
05864da7 9662 json_object_array_add(json_paths, json_path);
14f51eba 9663 }
d62a17ae 9664}
718e3744 9665
d62a17ae 9666/* dampening route */
5f040085
DS
9667static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9668 struct bgp_path_info *path, int display,
9669 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9670 json_object *json_paths)
d62a17ae 9671{
e5be8c1d 9672 struct attr *attr = path->attr;
d62a17ae 9673 int len;
9674 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9675 json_object *json_path = NULL;
9676
9677 if (use_json)
9678 json_path = json_object_new_object();
d62a17ae 9679
9680 /* short status lead text */
e5be8c1d 9681 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9682
9683 /* print prefix and mask */
9684 if (!use_json) {
9685 if (!display)
7d3cae70 9686 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9687 else
9688 vty_out(vty, "%*s", 17, " ");
d62a17ae 9689
e5be8c1d
DA
9690 len = vty_out(vty, "%s", path->peer->host);
9691 len = 17 - len;
9692
9693 if (len < 1)
d62a17ae 9694 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9695 else
9696 vty_out(vty, "%*s", len, " ");
d62a17ae 9697
9b6d8fcf
DS
9698 vty_out(vty, "%s ",
9699 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9700 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9701 use_json, NULL));
d62a17ae 9702
e5be8c1d 9703 if (attr->aspath)
05864da7 9704 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9705
05864da7
DS
9706 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9707
d62a17ae 9708 vty_out(vty, "\n");
e5be8c1d
DA
9709 } else {
9710 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9711 safi, use_json, json_path);
9712
9713 if (attr->aspath)
9714 json_object_string_add(json_path, "asPath",
9715 attr->aspath->str);
9716
9717 json_object_string_add(json_path, "origin",
9718 bgp_origin_str[attr->origin]);
9719 json_object_string_add(json_path, "peerHost", path->peer->host);
9720
9721 json_object_array_add(json_paths, json_path);
9722 }
d62a17ae 9723}
718e3744 9724
d62a17ae 9725/* flap route */
5f040085
DS
9726static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9727 struct bgp_path_info *path, int display,
9728 afi_t afi, safi_t safi, bool use_json,
31258046 9729 json_object *json_paths)
784d3a42 9730{
31258046 9731 struct attr *attr = path->attr;
d62a17ae 9732 struct bgp_damp_info *bdi;
9733 char timebuf[BGP_UPTIME_LEN];
9734 int len;
31258046 9735 json_object *json_path = NULL;
784d3a42 9736
9b6d8fcf 9737 if (!path->extra)
d62a17ae 9738 return;
784d3a42 9739
31258046
DA
9740 if (use_json)
9741 json_path = json_object_new_object();
9742
9b6d8fcf 9743 bdi = path->extra->damp_info;
784d3a42 9744
d62a17ae 9745 /* short status lead text */
31258046 9746 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9747
d62a17ae 9748 if (!use_json) {
9749 if (!display)
7d3cae70 9750 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9751 else
9752 vty_out(vty, "%*s", 17, " ");
784d3a42 9753
31258046
DA
9754 len = vty_out(vty, "%s", path->peer->host);
9755 len = 16 - len;
9756 if (len < 1)
d62a17ae 9757 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9758 else
9759 vty_out(vty, "%*s", len, " ");
784d3a42 9760
31258046
DA
9761 len = vty_out(vty, "%d", bdi->flap);
9762 len = 5 - len;
9763 if (len < 1)
d62a17ae 9764 vty_out(vty, " ");
d62a17ae 9765 else
9766 vty_out(vty, "%*s", len, " ");
d62a17ae 9767
996c9314
LB
9768 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9769 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9770
31258046
DA
9771 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9772 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9773 vty_out(vty, "%s ",
9b6d8fcf 9774 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9775 BGP_UPTIME_LEN, afi,
31258046
DA
9776 safi, use_json, NULL));
9777 else
d62a17ae 9778 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9779
31258046 9780 if (attr->aspath)
05864da7 9781 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9782
05864da7
DS
9783 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9784
d62a17ae 9785 vty_out(vty, "\n");
31258046
DA
9786 } else {
9787 json_object_string_add(json_path, "peerHost", path->peer->host);
9788 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9789
9790 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9791 json_path);
9792
9793 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9794 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9795 bgp_damp_reuse_time_vty(vty, path, timebuf,
9796 BGP_UPTIME_LEN, afi, safi,
9797 use_json, json_path);
9798
9799 if (attr->aspath)
9800 json_object_string_add(json_path, "asPath",
9801 attr->aspath->str);
9802
9803 json_object_string_add(json_path, "origin",
9804 bgp_origin_str[attr->origin]);
9805
9806 json_object_array_add(json_paths, json_path);
9807 }
d62a17ae 9808}
9809
9810static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9811 int *first, const char *header,
9812 json_object *json_adv_to)
9813{
d62a17ae 9814 json_object *json_peer = NULL;
9815
9816 if (json_adv_to) {
9817 /* 'advertised-to' is a dictionary of peers we have advertised
9818 * this
9819 * prefix too. The key is the peer's IP or swpX, the value is
9820 * the
9821 * hostname if we know it and "" if not.
9822 */
9823 json_peer = json_object_new_object();
9824
9825 if (peer->hostname)
9826 json_object_string_add(json_peer, "hostname",
9827 peer->hostname);
9828
9829 if (peer->conf_if)
9830 json_object_object_add(json_adv_to, peer->conf_if,
9831 json_peer);
9832 else
47e12884
DA
9833 json_object_object_addf(json_adv_to, json_peer, "%pSU",
9834 &peer->su);
d62a17ae 9835 } else {
9836 if (*first) {
9837 vty_out(vty, "%s", header);
9838 *first = 0;
9839 }
9840
9841 if (peer->hostname
892fedb6 9842 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9843 if (peer->conf_if)
9844 vty_out(vty, " %s(%s)", peer->hostname,
9845 peer->conf_if);
9846 else
47e12884
DA
9847 vty_out(vty, " %s(%pSU)", peer->hostname,
9848 &peer->su);
d62a17ae 9849 } else {
9850 if (peer->conf_if)
9851 vty_out(vty, " %s", peer->conf_if);
9852 else
47e12884 9853 vty_out(vty, " %pSU", &peer->su);
d62a17ae 9854 }
9855 }
784d3a42
PG
9856}
9857
dcc68b5e
MS
9858static void route_vty_out_tx_ids(struct vty *vty,
9859 struct bgp_addpath_info_data *d)
9860{
9861 int i;
9862
9863 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9864 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9865 d->addpath_tx_id[i],
9866 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9867 }
9868}
9869
5e4d4c8a 9870static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9871 struct bgp_path_info *pi,
9872 struct attr *attr,
9873 json_object *json_path)
5e4d4c8a
AK
9874{
9875 char esi_buf[ESI_STR_LEN];
9876 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9877 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9878 ATTR_ES_PEER_ROUTER);
9879 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9880 ATTR_ES_PEER_ACTIVE);
9881 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9882 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9883 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9884 if (json_path) {
9885 json_object *json_es_info = NULL;
9886
9887 json_object_string_add(
9888 json_path, "esi",
9889 esi_buf);
9890 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9891 json_es_info = json_object_new_object();
9892 if (es_local)
9893 json_object_boolean_true_add(
9894 json_es_info, "localEs");
9895 if (peer_active)
9896 json_object_boolean_true_add(
9897 json_es_info, "peerActive");
9898 if (peer_proxy)
9899 json_object_boolean_true_add(
9900 json_es_info, "peerProxy");
9901 if (peer_router)
9902 json_object_boolean_true_add(
9903 json_es_info, "peerRouter");
9904 if (attr->mm_sync_seqnum)
9905 json_object_int_add(
9906 json_es_info, "peerSeq",
9907 attr->mm_sync_seqnum);
9908 json_object_object_add(
9909 json_path, "es_info",
9910 json_es_info);
9911 }
9912 } else {
9913 if (bgp_evpn_attr_is_sync(attr))
9914 vty_out(vty,
9915 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9916 esi_buf,
9917 es_local ? "local-es":"",
9918 peer_proxy ? "proxy " : "",
9919 peer_active ? "active ":"",
9920 peer_router ? "router ":"",
9921 attr->mm_sync_seqnum);
9922 else
9923 vty_out(vty, " ESI %s %s\n",
9924 esi_buf,
9925 es_local ? "local-es":"");
9926 }
9927}
9928
4933eaaf
DS
9929void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9930 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9931 enum rpki_states rpki_curr_state,
9932 json_object *json_paths)
d62a17ae 9933{
9934 char buf[INET6_ADDRSTRLEN];
9935 char buf1[BUFSIZ];
515c2602 9936 struct attr *attr = path->attr;
d62a17ae 9937 time_t tbuf;
9938 json_object *json_bestpath = NULL;
9939 json_object *json_cluster_list = NULL;
9940 json_object *json_cluster_list_list = NULL;
9941 json_object *json_ext_community = NULL;
9942 json_object *json_last_update = NULL;
7fd077aa 9943 json_object *json_pmsi = NULL;
d62a17ae 9944 json_object *json_nexthop_global = NULL;
9945 json_object *json_nexthop_ll = NULL;
9946 json_object *json_nexthops = NULL;
9947 json_object *json_path = NULL;
9948 json_object *json_peer = NULL;
9949 json_object *json_string = NULL;
9950 json_object *json_adv_to = NULL;
9951 int first = 0;
9952 struct listnode *node, *nnode;
9953 struct peer *peer;
be92fc9f 9954 bool addpath_capable;
d62a17ae 9955 int has_adj;
9956 unsigned int first_as;
1defdda8 9957 bool nexthop_self =
9b6d8fcf 9958 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9959 int i;
2ba93fd6
DA
9960 char *nexthop_hostname =
9961 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
9962 uint32_t ttl = 0;
9963 uint32_t bos = 0;
9964 uint32_t exp = 0;
9965 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 9966
9967 if (json_paths) {
9968 json_path = json_object_new_object();
9969 json_peer = json_object_new_object();
9970 json_nexthop_global = json_object_new_object();
9971 }
9972
8304dabf
AD
9973 if (safi == SAFI_EVPN) {
9974 if (!json_paths)
9975 vty_out(vty, " Route %pRN", bn);
9976 }
9977
44c69747 9978 if (path->extra) {
b57ba6d2 9979 char tag_buf[30];
d62a17ae 9980
d62a17ae 9981 tag_buf[0] = '\0';
9b6d8fcf
DS
9982 if (path->extra && path->extra->num_labels) {
9983 bgp_evpn_label2str(path->extra->label,
9984 path->extra->num_labels, tag_buf,
a4d82a8a 9985 sizeof(tag_buf));
d62a17ae 9986 }
d7325ee7 9987 if (safi == SAFI_EVPN) {
44c69747 9988 if (!json_paths) {
44c69747
LK
9989 if (tag_buf[0] != '\0')
9990 vty_out(vty, " VNI %s", tag_buf);
44c69747 9991 } else {
77a2f8e5 9992 if (tag_buf[0]) {
44c69747
LK
9993 json_object_string_add(json_path, "VNI",
9994 tag_buf);
77a2f8e5
DA
9995 json_object_string_add(json_path, "vni",
9996 tag_buf);
9997 }
44c69747 9998 }
d7325ee7
DD
9999 }
10000
44c69747 10001 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 10002 struct bgp_path_info *parent_ri;
9bcb3eef 10003 struct bgp_dest *dest, *pdest;
d62a17ae 10004
9b6d8fcf 10005 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
10006 dest = parent_ri->net;
10007 if (dest && dest->pdest) {
10008 pdest = dest->pdest;
10009 prefix_rd2str(
10010 (struct prefix_rd *)bgp_dest_get_prefix(
10011 pdest),
10012 buf1, sizeof(buf1));
d7325ee7 10013 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 10014 vty_out(vty,
58bff4d1 10015 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
10016 buf1,
10017 (struct prefix_evpn *)
10018 bgp_dest_get_prefix(
10019 dest),
10020 tag_buf);
58bff4d1
AK
10021 if (attr->es_flags & ATTR_ES_L3_NHG)
10022 vty_out(vty, ", L3NHG %s",
10023 (attr->es_flags
10024 & ATTR_ES_L3_NHG_ACTIVE)
10025 ? "active"
10026 : "inactive");
10027 vty_out(vty, "\n");
10028
d7325ee7 10029 } else
2dbe669b
DA
10030 vty_out(vty,
10031 " Imported from %s:%pFX\n",
10032 buf1,
10033 (struct prefix_evpn *)
10034 bgp_dest_get_prefix(
10035 dest));
d62a17ae 10036 }
10037 }
10038 }
d62a17ae 10039
8304dabf
AD
10040 if (safi == SAFI_EVPN
10041 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10042 char gwip_buf[INET6_ADDRSTRLEN];
10043
860e740b
IR
10044 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10045 sizeof(gwip_buf));
8304dabf
AD
10046
10047 if (json_paths)
10048 json_object_string_add(json_path, "gatewayIP",
10049 gwip_buf);
10050 else
10051 vty_out(vty, " Gateway IP %s", gwip_buf);
10052 }
10053
10054 if (safi == SAFI_EVPN)
10055 vty_out(vty, "\n");
10056
05864da7
DS
10057 /* Line1 display AS-path, Aggregator */
10058 if (attr->aspath) {
10059 if (json_paths) {
10060 if (!attr->aspath->json)
10061 aspath_str_update(attr->aspath, true);
10062 json_object_lock(attr->aspath->json);
10063 json_object_object_add(json_path, "aspath",
10064 attr->aspath->json);
10065 } else {
10066 if (attr->aspath->segments)
10067 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10068 else
05864da7 10069 vty_out(vty, " Local");
d62a17ae 10070 }
05864da7 10071 }
d62a17ae 10072
05864da7
DS
10073 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10074 if (json_paths)
10075 json_object_boolean_true_add(json_path, "removed");
10076 else
10077 vty_out(vty, ", (removed)");
10078 }
d62a17ae 10079
05864da7
DS
10080 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10081 if (json_paths)
10082 json_object_boolean_true_add(json_path, "stale");
10083 else
10084 vty_out(vty, ", (stale)");
10085 }
d62a17ae 10086
05864da7
DS
10087 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10088 if (json_paths) {
10089 json_object_int_add(json_path, "aggregatorAs",
10090 attr->aggregator_as);
c949c771
DA
10091 json_object_string_addf(json_path, "aggregatorId",
10092 "%pI4", &attr->aggregator_addr);
05864da7 10093 } else {
88d495a9
DA
10094 vty_out(vty, ", (aggregated by %u %pI4)",
10095 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10096 }
05864da7 10097 }
d62a17ae 10098
05864da7
DS
10099 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10100 PEER_FLAG_REFLECTOR_CLIENT)) {
10101 if (json_paths)
10102 json_object_boolean_true_add(json_path,
10103 "rxedFromRrClient");
10104 else
10105 vty_out(vty, ", (Received from a RR-client)");
10106 }
d62a17ae 10107
05864da7
DS
10108 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10109 PEER_FLAG_RSERVER_CLIENT)) {
10110 if (json_paths)
10111 json_object_boolean_true_add(json_path,
10112 "rxedFromRsClient");
10113 else
10114 vty_out(vty, ", (Received from a RS-client)");
10115 }
d62a17ae 10116
05864da7
DS
10117 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10118 if (json_paths)
10119 json_object_boolean_true_add(json_path,
10120 "dampeningHistoryEntry");
10121 else
10122 vty_out(vty, ", (history entry)");
10123 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10124 if (json_paths)
10125 json_object_boolean_true_add(json_path,
10126 "dampeningSuppressed");
10127 else
10128 vty_out(vty, ", (suppressed due to dampening)");
10129 }
d62a17ae 10130
05864da7
DS
10131 if (!json_paths)
10132 vty_out(vty, "\n");
d62a17ae 10133
05864da7
DS
10134 /* Line2 display Next-hop, Neighbor, Router-id */
10135 /* Display the nexthop */
9bcb3eef 10136 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0 10137
7226bc40
TA
10138 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
10139 bn_p->family == AF_EVPN) &&
10140 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10141 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10142 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10143 || safi == SAFI_EVPN) {
515c2602 10144 if (json_paths) {
c949c771
DA
10145 json_object_string_addf(
10146 json_nexthop_global, "ip", "%pI4",
10147 &attr->mp_nexthop_global_in);
515c2602 10148
939a97f4 10149 if (path->peer->hostname)
515c2602
DA
10150 json_object_string_add(
10151 json_nexthop_global, "hostname",
939a97f4 10152 path->peer->hostname);
aef999a2
DA
10153 } else {
10154 if (nexthop_hostname)
10155 vty_out(vty, " %pI4(%s)",
10156 &attr->mp_nexthop_global_in,
10157 nexthop_hostname);
10158 else
10159 vty_out(vty, " %pI4",
10160 &attr->mp_nexthop_global_in);
10161 }
d62a17ae 10162 } else {
515c2602 10163 if (json_paths) {
c949c771
DA
10164 json_object_string_addf(json_nexthop_global,
10165 "ip", "%pI4",
10166 &attr->nexthop);
515c2602 10167
939a97f4 10168 if (path->peer->hostname)
515c2602
DA
10169 json_object_string_add(
10170 json_nexthop_global, "hostname",
939a97f4 10171 path->peer->hostname);
aef999a2
DA
10172 } else {
10173 if (nexthop_hostname)
10174 vty_out(vty, " %pI4(%s)",
10175 &attr->nexthop,
10176 nexthop_hostname);
10177 else
10178 vty_out(vty, " %pI4",
10179 &attr->nexthop);
10180 }
d62a17ae 10181 }
10182
05864da7
DS
10183 if (json_paths)
10184 json_object_string_add(json_nexthop_global, "afi",
10185 "ipv4");
10186 } else {
10187 if (json_paths) {
c949c771
DA
10188 json_object_string_addf(json_nexthop_global, "ip",
10189 "%pI6",
10190 &attr->mp_nexthop_global);
515c2602 10191
939a97f4 10192 if (path->peer->hostname)
515c2602
DA
10193 json_object_string_add(json_nexthop_global,
10194 "hostname",
939a97f4 10195 path->peer->hostname);
515c2602 10196
05864da7
DS
10197 json_object_string_add(json_nexthop_global, "afi",
10198 "ipv6");
10199 json_object_string_add(json_nexthop_global, "scope",
10200 "global");
10201 } else {
aef999a2
DA
10202 if (nexthop_hostname)
10203 vty_out(vty, " %pI6(%s)",
10204 &attr->mp_nexthop_global,
10205 nexthop_hostname);
10206 else
10207 vty_out(vty, " %pI6",
10208 &attr->mp_nexthop_global);
d62a17ae 10209 }
05864da7 10210 }
d62a17ae 10211
05864da7
DS
10212 /* Display the IGP cost or 'inaccessible' */
10213 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10214 if (json_paths)
10215 json_object_boolean_false_add(json_nexthop_global,
10216 "accessible");
10217 else
10218 vty_out(vty, " (inaccessible)");
10219 } else {
10220 if (path->extra && path->extra->igpmetric) {
d62a17ae 10221 if (json_paths)
05864da7
DS
10222 json_object_int_add(json_nexthop_global,
10223 "metric",
10224 path->extra->igpmetric);
d62a17ae 10225 else
05864da7
DS
10226 vty_out(vty, " (metric %u)",
10227 path->extra->igpmetric);
d62a17ae 10228 }
10229
05864da7 10230 /* IGP cost is 0, display this only for json */
d62a17ae 10231 else {
d62a17ae 10232 if (json_paths)
05864da7
DS
10233 json_object_int_add(json_nexthop_global,
10234 "metric", 0);
d62a17ae 10235 }
d62a17ae 10236
05864da7
DS
10237 if (json_paths)
10238 json_object_boolean_true_add(json_nexthop_global,
10239 "accessible");
10240 }
d62a17ae 10241
05864da7
DS
10242 /* Display peer "from" output */
10243 /* This path was originated locally */
10244 if (path->peer == bgp->peer_self) {
d62a17ae 10245
7226bc40
TA
10246 if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
10247 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10248 if (json_paths)
05864da7
DS
10249 json_object_string_add(json_peer, "peerId",
10250 "0.0.0.0");
d62a17ae 10251 else
05864da7
DS
10252 vty_out(vty, " from 0.0.0.0 ");
10253 } else {
d62a17ae 10254 if (json_paths)
05864da7
DS
10255 json_object_string_add(json_peer, "peerId",
10256 "::");
d62a17ae 10257 else
05864da7 10258 vty_out(vty, " from :: ");
d62a17ae 10259 }
d62a17ae 10260
4e9a9863 10261 if (json_paths)
c949c771
DA
10262 json_object_string_addf(json_peer, "routerId", "%pI4",
10263 &bgp->router_id);
4e9a9863 10264 else
23d0a753 10265 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10266 }
d62a17ae 10267
05864da7
DS
10268 /* We RXed this path from one of our peers */
10269 else {
10270
10271 if (json_paths) {
47e12884
DA
10272 json_object_string_addf(json_peer, "peerId", "%pSU",
10273 &path->peer->su);
c949c771
DA
10274 json_object_string_addf(json_peer, "routerId", "%pI4",
10275 &path->peer->remote_id);
05864da7
DS
10276
10277 if (path->peer->hostname)
10278 json_object_string_add(json_peer, "hostname",
10279 path->peer->hostname);
10280
10281 if (path->peer->domainname)
10282 json_object_string_add(json_peer, "domainname",
10283 path->peer->domainname);
10284
10285 if (path->peer->conf_if)
10286 json_object_string_add(json_peer, "interface",
10287 path->peer->conf_if);
10288 } else {
10289 if (path->peer->conf_if) {
10290 if (path->peer->hostname
892fedb6
DA
10291 && CHECK_FLAG(path->peer->bgp->flags,
10292 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10293 vty_out(vty, " from %s(%s)",
10294 path->peer->hostname,
10295 path->peer->conf_if);
d62a17ae 10296 else
05864da7 10297 vty_out(vty, " from %s",
9b6d8fcf 10298 path->peer->conf_if);
d62a17ae 10299 } else {
05864da7 10300 if (path->peer->hostname
892fedb6
DA
10301 && CHECK_FLAG(path->peer->bgp->flags,
10302 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10303 vty_out(vty, " from %s(%s)",
10304 path->peer->hostname,
10305 path->peer->host);
d62a17ae 10306 else
47e12884
DA
10307 vty_out(vty, " from %pSU",
10308 &path->peer->su);
d62a17ae 10309 }
d62a17ae 10310
05864da7 10311 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10312 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10313 else
10314 vty_out(vty, " (%s)",
10315 inet_ntop(AF_INET,
10316 &path->peer->remote_id, buf1,
10317 sizeof(buf1)));
d62a17ae 10318 }
05864da7 10319 }
9df8b37c 10320
05864da7
DS
10321 /*
10322 * Note when vrfid of nexthop is different from that of prefix
10323 */
10324 if (path->extra && path->extra->bgp_orig) {
10325 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10326
05864da7
DS
10327 if (json_paths) {
10328 const char *vn;
9df8b37c 10329
05864da7
DS
10330 if (path->extra->bgp_orig->inst_type
10331 == BGP_INSTANCE_TYPE_DEFAULT)
10332 vn = VRF_DEFAULT_NAME;
10333 else
10334 vn = path->extra->bgp_orig->name;
9df8b37c 10335
05864da7 10336 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10337
05864da7
DS
10338 if (nexthop_vrfid == VRF_UNKNOWN) {
10339 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10340 } else {
05864da7
DS
10341 json_object_int_add(json_path, "nhVrfId",
10342 (int)nexthop_vrfid);
9df8b37c 10343 }
05864da7
DS
10344 } else {
10345 if (nexthop_vrfid == VRF_UNKNOWN)
10346 vty_out(vty, " vrf ?");
137147c6
DS
10347 else {
10348 struct vrf *vrf;
10349
10350 vrf = vrf_lookup_by_id(nexthop_vrfid);
10351 vty_out(vty, " vrf %s(%u)",
10352 VRF_LOGNAME(vrf), nexthop_vrfid);
10353 }
9df8b37c 10354 }
05864da7 10355 }
9df8b37c 10356
05864da7
DS
10357 if (nexthop_self) {
10358 if (json_paths) {
10359 json_object_boolean_true_add(json_path,
10360 "announceNexthopSelf");
10361 } else {
10362 vty_out(vty, " announce-nh-self");
9df8b37c 10363 }
05864da7 10364 }
9df8b37c 10365
05864da7
DS
10366 if (!json_paths)
10367 vty_out(vty, "\n");
d62a17ae 10368
05864da7
DS
10369 /* display the link-local nexthop */
10370 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10371 if (json_paths) {
10372 json_nexthop_ll = json_object_new_object();
c949c771
DA
10373 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10374 &attr->mp_nexthop_local);
515c2602 10375
939a97f4 10376 if (path->peer->hostname)
515c2602
DA
10377 json_object_string_add(json_nexthop_ll,
10378 "hostname",
939a97f4 10379 path->peer->hostname);
515c2602 10380
05864da7
DS
10381 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10382 json_object_string_add(json_nexthop_ll, "scope",
10383 "link-local");
d62a17ae 10384
05864da7
DS
10385 json_object_boolean_true_add(json_nexthop_ll,
10386 "accessible");
d62a17ae 10387
05864da7 10388 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10389 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10390 "used");
10391 else
10392 json_object_boolean_true_add(
10393 json_nexthop_global, "used");
10394 } else {
10395 vty_out(vty, " (%s) %s\n",
10396 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10397 buf, INET6_ADDRSTRLEN),
10398 attr->mp_nexthop_prefer_global
10399 ? "(prefer-global)"
10400 : "(used)");
d62a17ae 10401 }
05864da7
DS
10402 }
10403 /* If we do not have a link-local nexthop then we must flag the
10404 global as "used" */
10405 else {
10406 if (json_paths)
10407 json_object_boolean_true_add(json_nexthop_global,
10408 "used");
10409 }
d62a17ae 10410
b5e140c8 10411 if (safi == SAFI_EVPN &&
5e4d4c8a 10412 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10413 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10414 }
10415
05864da7
DS
10416 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10417 * Int/Ext/Local, Atomic, best */
10418 if (json_paths)
10419 json_object_string_add(json_path, "origin",
10420 bgp_origin_long_str[attr->origin]);
10421 else
10422 vty_out(vty, " Origin %s",
10423 bgp_origin_long_str[attr->origin]);
9df8b37c 10424
05864da7 10425 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10426 if (json_paths)
05864da7 10427 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10428 else
05864da7
DS
10429 vty_out(vty, ", metric %u", attr->med);
10430 }
9df8b37c 10431
05864da7
DS
10432 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10433 if (json_paths)
0fbac0b4 10434 json_object_int_add(json_path, "locPrf",
05864da7
DS
10435 attr->local_pref);
10436 else
10437 vty_out(vty, ", localpref %u", attr->local_pref);
10438 }
9df8b37c 10439
05864da7
DS
10440 if (attr->weight != 0) {
10441 if (json_paths)
10442 json_object_int_add(json_path, "weight", attr->weight);
10443 else
10444 vty_out(vty, ", weight %u", attr->weight);
10445 }
9df8b37c 10446
05864da7
DS
10447 if (attr->tag != 0) {
10448 if (json_paths)
10449 json_object_int_add(json_path, "tag", attr->tag);
10450 else
10451 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10452 }
9df8b37c 10453
05864da7
DS
10454 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10455 if (json_paths)
10456 json_object_boolean_false_add(json_path, "valid");
10457 else
10458 vty_out(vty, ", invalid");
10459 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10460 if (json_paths)
10461 json_object_boolean_true_add(json_path, "valid");
10462 else
10463 vty_out(vty, ", valid");
10464 }
9df8b37c 10465
7d3cae70
DA
10466 if (json_paths)
10467 json_object_int_add(json_path, "version", bn->version);
10468
05864da7
DS
10469 if (path->peer != bgp->peer_self) {
10470 if (path->peer->as == path->peer->local_as) {
10471 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10472 if (json_paths)
10473 json_object_string_add(
10474 json_peer, "type",
10475 "confed-internal");
d62a17ae 10476 else
05864da7 10477 vty_out(vty, ", confed-internal");
d62a17ae 10478 } else {
05864da7
DS
10479 if (json_paths)
10480 json_object_string_add(
10481 json_peer, "type", "internal");
10482 else
10483 vty_out(vty, ", internal");
9df8b37c 10484 }
05864da7
DS
10485 } else {
10486 if (bgp_confederation_peers_check(bgp,
10487 path->peer->as)) {
10488 if (json_paths)
10489 json_object_string_add(
10490 json_peer, "type",
10491 "confed-external");
d62a17ae 10492 else
05864da7 10493 vty_out(vty, ", confed-external");
d62a17ae 10494 } else {
05864da7
DS
10495 if (json_paths)
10496 json_object_string_add(
10497 json_peer, "type", "external");
10498 else
10499 vty_out(vty, ", external");
d62a17ae 10500 }
10501 }
05864da7
DS
10502 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10503 if (json_paths) {
10504 json_object_boolean_true_add(json_path, "aggregated");
10505 json_object_boolean_true_add(json_path, "local");
10506 } else {
10507 vty_out(vty, ", aggregated, local");
10508 }
10509 } else if (path->type != ZEBRA_ROUTE_BGP) {
10510 if (json_paths)
10511 json_object_boolean_true_add(json_path, "sourced");
10512 else
10513 vty_out(vty, ", sourced");
10514 } else {
10515 if (json_paths) {
10516 json_object_boolean_true_add(json_path, "sourced");
10517 json_object_boolean_true_add(json_path, "local");
10518 } else {
10519 vty_out(vty, ", sourced, local");
d62a17ae 10520 }
05864da7 10521 }
718e3744 10522
05864da7 10523 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10524 if (json_paths)
05864da7
DS
10525 json_object_boolean_true_add(json_path,
10526 "atomicAggregate");
d62a17ae 10527 else
05864da7
DS
10528 vty_out(vty, ", atomic-aggregate");
10529 }
d62a17ae 10530
d864dd9e
EB
10531 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10532 if (json_paths)
10533 json_object_int_add(json_path, "otc", attr->otc);
10534 else
10535 vty_out(vty, ", otc %u", attr->otc);
10536 }
10537
05864da7
DS
10538 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10539 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10540 && bgp_path_info_mpath_count(path))) {
10541 if (json_paths)
10542 json_object_boolean_true_add(json_path, "multipath");
10543 else
10544 vty_out(vty, ", multipath");
10545 }
50e05855 10546
05864da7
DS
10547 // Mark the bestpath(s)
10548 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10549 first_as = aspath_get_first_as(attr->aspath);
718e3744 10550
05864da7
DS
10551 if (json_paths) {
10552 if (!json_bestpath)
10553 json_bestpath = json_object_new_object();
10554 json_object_int_add(json_bestpath, "bestpathFromAs",
10555 first_as);
10556 } else {
10557 if (first_as)
10558 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10559 else
05864da7 10560 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10561 }
05864da7 10562 }
718e3744 10563
05864da7
DS
10564 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10565 if (json_paths) {
10566 if (!json_bestpath)
10567 json_bestpath = json_object_new_object();
10568 json_object_boolean_true_add(json_bestpath, "overall");
10569 json_object_string_add(
10570 json_bestpath, "selectionReason",
10571 bgp_path_selection_reason2str(bn->reason));
10572 } else {
10573 vty_out(vty, ", best");
10574 vty_out(vty, " (%s)",
10575 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10576 }
05864da7 10577 }
718e3744 10578
4027d19b 10579 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10580 if (json_paths)
10581 json_object_string_add(
10582 json_path, "rpkiValidationState",
4027d19b 10583 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10584 else
1d327209 10585 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10586 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10587 }
10588
05864da7
DS
10589 if (json_bestpath)
10590 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10591
05864da7
DS
10592 if (!json_paths)
10593 vty_out(vty, "\n");
10594
10595 /* Line 4 display Community */
29e72930 10596 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10597 if (json_paths) {
9a706b42
DA
10598 if (!bgp_attr_get_community(attr)->json)
10599 community_str(bgp_attr_get_community(attr),
c0945b78 10600 true, true);
9a706b42
DA
10601 json_object_lock(bgp_attr_get_community(attr)->json);
10602 json_object_object_add(
10603 json_path, "community",
10604 bgp_attr_get_community(attr)->json);
05864da7
DS
10605 } else {
10606 vty_out(vty, " Community: %s\n",
9a706b42 10607 bgp_attr_get_community(attr)->str);
d62a17ae 10608 }
05864da7 10609 }
718e3744 10610
05864da7
DS
10611 /* Line 5 display Extended-community */
10612 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10613 if (json_paths) {
10614 json_ext_community = json_object_new_object();
b53e67a3
DA
10615 json_object_string_add(
10616 json_ext_community, "string",
10617 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10618 json_object_object_add(json_path, "extendedCommunity",
10619 json_ext_community);
d62a17ae 10620 } else {
05864da7 10621 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10622 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10623 }
05864da7 10624 }
718e3744 10625
05864da7
DS
10626 /* Line 6 display Large community */
10627 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10628 if (json_paths) {
1bcf3a96
DA
10629 if (!bgp_attr_get_lcommunity(attr)->json)
10630 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10631 true, true);
1bcf3a96
DA
10632 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10633 json_object_object_add(
10634 json_path, "largeCommunity",
10635 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10636 } else {
10637 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10638 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10639 }
05864da7 10640 }
718e3744 10641
05864da7
DS
10642 /* Line 7 display Originator, Cluster-id */
10643 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10644 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10645 char buf[BUFSIZ] = {0};
10646
05864da7 10647 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10648 if (json_paths)
c949c771
DA
10649 json_object_string_addf(json_path,
10650 "originatorId", "%pI4",
10651 &attr->originator_id);
d62a17ae 10652 else
23d0a753
DA
10653 vty_out(vty, " Originator: %pI4",
10654 &attr->originator_id);
d62a17ae 10655 }
856ca177 10656
05864da7 10657 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10658 struct cluster_list *cluster =
10659 bgp_attr_get_cluster(attr);
05864da7 10660 int i;
d62a17ae 10661
10662 if (json_paths) {
05864da7
DS
10663 json_cluster_list = json_object_new_object();
10664 json_cluster_list_list =
10665 json_object_new_array();
10666
779fee93 10667 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10668 json_string = json_object_new_string(
779fee93
DS
10669 inet_ntop(AF_INET,
10670 &cluster->list[i],
10671 buf, sizeof(buf)));
05864da7
DS
10672 json_object_array_add(
10673 json_cluster_list_list,
10674 json_string);
10675 }
718e3744 10676
05864da7
DS
10677 /*
10678 * struct cluster_list does not have
10679 * "str" variable like aspath and community
10680 * do. Add this someday if someone asks
10681 * for it.
10682 * json_object_string_add(json_cluster_list,
779fee93 10683 * "string", cluster->str);
05864da7
DS
10684 */
10685 json_object_object_add(json_cluster_list,
10686 "list",
10687 json_cluster_list_list);
10688 json_object_object_add(json_path, "clusterList",
10689 json_cluster_list);
0dc8ee70 10690 } else {
05864da7
DS
10691 vty_out(vty, ", Cluster list: ");
10692
779fee93 10693 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10694 vty_out(vty, "%pI4 ",
779fee93 10695 &cluster->list[i]);
05864da7 10696 }
0dc8ee70 10697 }
d62a17ae 10698 }
718e3744 10699
d62a17ae 10700 if (!json_paths)
10701 vty_out(vty, "\n");
05864da7 10702 }
d62a17ae 10703
05864da7 10704 if (path->extra && path->extra->damp_info)
b4f7f45b 10705 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10706
05864da7
DS
10707 /* Remote Label */
10708 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10709 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10710 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10711 &bos);
d62a17ae 10712
05864da7
DS
10713 if (json_paths)
10714 json_object_int_add(json_path, "remoteLabel", label);
10715 else
10716 vty_out(vty, " Remote label: %d\n", label);
10717 }
d62a17ae 10718
e496b420
HS
10719 /* Remote SID */
10720 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10721 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10722 if (json_paths)
10723 json_object_string_add(json_path, "remoteSid", buf);
10724 else
10725 vty_out(vty, " Remote SID: %s\n", buf);
10726 }
10727
05864da7
DS
10728 /* Label Index */
10729 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10730 if (json_paths)
10731 json_object_int_add(json_path, "labelIndex",
10732 attr->label_index);
10733 else
10734 vty_out(vty, " Label Index: %d\n",
10735 attr->label_index);
10736 }
d62a17ae 10737
05864da7
DS
10738 /* Line 8 display Addpath IDs */
10739 if (path->addpath_rx_id
10740 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10741 if (json_paths) {
10742 json_object_int_add(json_path, "addpathRxId",
10743 path->addpath_rx_id);
d62a17ae 10744
05864da7
DS
10745 /* Keep backwards compatibility with the old API
10746 * by putting TX All's ID in the old field
10747 */
10748 json_object_int_add(
10749 json_path, "addpathTxId",
10750 path->tx_addpath
10751 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10752
05864da7
DS
10753 /* ... but create a specific field for each
10754 * strategy
10755 */
10756 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10757 json_object_int_add(
10758 json_path,
10759 bgp_addpath_names(i)->id_json_name,
10760 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10761 }
05864da7
DS
10762 } else {
10763 vty_out(vty, " AddPath ID: RX %u, ",
10764 path->addpath_rx_id);
d62a17ae 10765
05864da7 10766 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10767 }
05864da7 10768 }
520d5d76 10769
05864da7
DS
10770 /* If we used addpath to TX a non-bestpath we need to display
10771 * "Advertised to" on a path-by-path basis
10772 */
10773 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10774 first = 1;
dcc68b5e 10775
05864da7
DS
10776 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10777 addpath_capable =
10778 bgp_addpath_encode_tx(peer, afi, safi);
10779 has_adj = bgp_adj_out_lookup(
10780 peer, path->net,
10781 bgp_addpath_id_for_peer(peer, afi, safi,
10782 &path->tx_addpath));
10783
10784 if ((addpath_capable && has_adj)
10785 || (!addpath_capable && has_adj
10786 && CHECK_FLAG(path->flags,
10787 BGP_PATH_SELECTED))) {
10788 if (json_path && !json_adv_to)
10789 json_adv_to = json_object_new_object();
dcc68b5e 10790
05864da7
DS
10791 route_vty_out_advertised_to(
10792 vty, peer, &first,
10793 " Advertised to:", json_adv_to);
d62a17ae 10794 }
10795 }
718e3744 10796
05864da7
DS
10797 if (json_path) {
10798 if (json_adv_to) {
10799 json_object_object_add(
10800 json_path, "advertisedTo", json_adv_to);
d62a17ae 10801 }
05864da7
DS
10802 } else {
10803 if (!first) {
10804 vty_out(vty, "\n");
d62a17ae 10805 }
10806 }
05864da7 10807 }
b05a1c8b 10808
05864da7
DS
10809 /* Line 9 display Uptime */
10810 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10811 if (json_paths) {
10812 json_last_update = json_object_new_object();
10813 json_object_int_add(json_last_update, "epoch", tbuf);
10814 json_object_string_add(json_last_update, "string",
10815 ctime(&tbuf));
10816 json_object_object_add(json_path, "lastUpdate",
10817 json_last_update);
10818 } else
10819 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10820
05864da7
DS
10821 /* Line 10 display PMSI tunnel attribute, if present */
10822 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10823 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10824 bgp_attr_get_pmsi_tnl_type(attr),
10825 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10826
05864da7
DS
10827 if (json_paths) {
10828 json_pmsi = json_object_new_object();
10829 json_object_string_add(json_pmsi, "tunnelType", str);
10830 json_object_int_add(json_pmsi, "label",
10831 label2vni(&attr->label));
10832 json_object_object_add(json_path, "pmsi", json_pmsi);
10833 } else
10834 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10835 str, label2vni(&attr->label));
d62a17ae 10836 }
f1aa5d8a 10837
848e8cf6
DA
10838 if (path->peer->t_gr_restart &&
10839 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10840 unsigned long gr_remaining =
10841 thread_timer_remain_second(path->peer->t_gr_restart);
10842
10843 if (json_paths) {
10844 json_object_int_add(json_path,
10845 "gracefulRestartSecondsRemaining",
10846 gr_remaining);
10847 } else
10848 vty_out(vty,
10849 " Time until Graceful Restart stale route deleted: %lu\n",
10850 gr_remaining);
10851 }
10852
9a706b42
DA
10853 if (path->peer->t_llgr_stale[afi][safi] &&
10854 bgp_attr_get_community(attr) &&
10855 community_include(bgp_attr_get_community(attr),
10856 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10857 unsigned long llgr_remaining = thread_timer_remain_second(
10858 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10859
48ebba04
DA
10860 if (json_paths) {
10861 json_object_int_add(json_path, "llgrSecondsRemaining",
10862 llgr_remaining);
10863 } else
10864 vty_out(vty,
10865 " Time until Long-lived stale route deleted: %lu\n",
10866 llgr_remaining);
10867 }
10868
92269aa2
DS
10869 /* Output some debug about internal state of the dest flags */
10870 if (json_paths) {
10871 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10872 json_object_boolean_true_add(json_path, "processScheduled");
10873 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10874 json_object_boolean_true_add(json_path, "userCleared");
10875 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10876 json_object_boolean_true_add(json_path, "labelChanged");
10877 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10878 json_object_boolean_true_add(json_path, "registeredForLabel");
10879 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10880 json_object_boolean_true_add(json_path, "selectDefered");
10881 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10882 json_object_boolean_true_add(json_path, "fibInstalled");
10883 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10884 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10885
d62a17ae 10886 if (json_nexthop_global || json_nexthop_ll) {
10887 json_nexthops = json_object_new_array();
f1aa5d8a 10888
d62a17ae 10889 if (json_nexthop_global)
10890 json_object_array_add(json_nexthops,
10891 json_nexthop_global);
f1aa5d8a 10892
d62a17ae 10893 if (json_nexthop_ll)
10894 json_object_array_add(json_nexthops,
10895 json_nexthop_ll);
f1aa5d8a 10896
d62a17ae 10897 json_object_object_add(json_path, "nexthops",
10898 json_nexthops);
10899 }
10900
10901 json_object_object_add(json_path, "peer", json_peer);
10902 json_object_array_add(json_paths, json_path);
05864da7 10903 }
b366b518
BB
10904}
10905
96ade3ed 10906#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10907#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10908#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10909
a4d82a8a 10910static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10911 afi_t afi, safi_t safi, enum bgp_show_type type,
10912 bool use_json);
7f323236
DW
10913static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10914 const char *comstr, int exact, afi_t afi,
96c81f66 10915 safi_t safi, uint16_t show_flags);
d62a17ae 10916
1ae44dfc 10917static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10918 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10919 void *output_arg, const char *rd, int is_last,
96f3485c 10920 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10921 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10922 enum rpki_states rpki_target_state)
d62a17ae 10923{
40381db7 10924 struct bgp_path_info *pi;
9bcb3eef 10925 struct bgp_dest *dest;
2aad8c42
MS
10926 bool header = true;
10927 bool json_detail_header = false;
d62a17ae 10928 int display;
1ae44dfc
LB
10929 unsigned long output_count = 0;
10930 unsigned long total_count = 0;
d62a17ae 10931 struct prefix *p;
d62a17ae 10932 json_object *json_paths = NULL;
10933 int first = 1;
96f3485c
MK
10934 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10935 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10936 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10937
1ae44dfc 10938 if (output_cum && *output_cum != 0)
2aad8c42 10939 header = false;
1ae44dfc 10940
9386b588 10941 if (use_json && !*json_header_depth) {
96f3485c
MK
10942 if (all)
10943 *json_header_depth = 1;
10944 else {
10945 vty_out(vty, "{\n");
10946 *json_header_depth = 2;
10947 }
10948
d62a17ae 10949 vty_out(vty,
23d0a753
DA
10950 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10951 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10952 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10953 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10954 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10955 ? VRF_DEFAULT_NAME
10956 : bgp->name,
10957 table->version, &bgp->router_id,
01eced22 10958 bgp->default_local_pref, bgp->as);
9386b588 10959 if (rd) {
445c2480 10960 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10961 ++*json_header_depth;
10962 }
d62a17ae 10963 }
718e3744 10964
445c2480
DS
10965 if (use_json && rd) {
10966 vty_out(vty, " \"%s\" : { ", rd);
10967 }
10968
2aad8c42
MS
10969 /* Check for 'json detail', where we need header output once per dest */
10970 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10971 type != bgp_show_type_dampend_paths &&
10972 type != bgp_show_type_damp_neighbor &&
10973 type != bgp_show_type_flap_statistics &&
10974 type != bgp_show_type_flap_neighbor)
10975 json_detail_header = true;
10976
d62a17ae 10977 /* Start processing of routes. */
9bcb3eef
DS
10978 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10979 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10980 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10981 bool json_detail = json_detail_header;
b54892e0 10982
9bcb3eef 10983 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10984 if (pi == NULL)
98ce9a06 10985 continue;
d62a17ae 10986
98ce9a06 10987 display = 0;
98ce9a06
DS
10988 if (use_json)
10989 json_paths = json_object_new_array();
10990 else
10991 json_paths = NULL;
d62a17ae 10992
6f94b685 10993 for (; pi; pi = pi->next) {
9a706b42
DA
10994 struct community *picomm = NULL;
10995
10996 picomm = bgp_attr_get_community(pi->attr);
10997
98ce9a06 10998 total_count++;
1e2ce4f1 10999
7d3cae70
DA
11000 if (type == bgp_show_type_prefix_version) {
11001 uint32_t version =
11002 strtoul(output_arg, NULL, 10);
11003 if (dest->version < version)
11004 continue;
11005 }
11006
a70a28a5
DA
11007 if (type == bgp_show_type_community_alias) {
11008 char *alias = output_arg;
11009 char **communities;
11010 int num;
11011 bool found = false;
11012
9a706b42
DA
11013 if (picomm) {
11014 frrstr_split(picomm->str, " ",
11015 &communities, &num);
a70a28a5
DA
11016 for (int i = 0; i < num; i++) {
11017 const char *com2alias =
11018 bgp_community2alias(
11019 communities[i]);
cd9cc0e6
IR
11020 if (!found
11021 && strcmp(alias, com2alias)
11022 == 0)
a70a28a5 11023 found = true;
cd9cc0e6
IR
11024 XFREE(MTYPE_TMP,
11025 communities[i]);
a70a28a5 11026 }
cd9cc0e6 11027 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11028 }
11029
1bcf3a96
DA
11030 if (!found &&
11031 bgp_attr_get_lcommunity(pi->attr)) {
11032 frrstr_split(bgp_attr_get_lcommunity(
11033 pi->attr)
11034 ->str,
a70a28a5
DA
11035 " ", &communities, &num);
11036 for (int i = 0; i < num; i++) {
11037 const char *com2alias =
11038 bgp_community2alias(
11039 communities[i]);
cd9cc0e6
IR
11040 if (!found
11041 && strcmp(alias, com2alias)
11042 == 0)
a70a28a5 11043 found = true;
cd9cc0e6
IR
11044 XFREE(MTYPE_TMP,
11045 communities[i]);
a70a28a5 11046 }
cd9cc0e6 11047 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11048 }
11049
11050 if (!found)
11051 continue;
11052 }
11053
1e2ce4f1
DS
11054 if (type == bgp_show_type_rpki) {
11055 if (dest_p->family == AF_INET
11056 || dest_p->family == AF_INET6)
4027d19b 11057 rpki_curr_state = hook_call(
1e2ce4f1
DS
11058 bgp_rpki_prefix_status,
11059 pi->peer, pi->attr, dest_p);
4027d19b
DS
11060 if (rpki_target_state != RPKI_NOT_BEING_USED
11061 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11062 continue;
11063 }
11064
98ce9a06
DS
11065 if (type == bgp_show_type_flap_statistics
11066 || type == bgp_show_type_flap_neighbor
11067 || type == bgp_show_type_dampend_paths
11068 || type == bgp_show_type_damp_neighbor) {
40381db7 11069 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11070 continue;
11071 }
11072 if (type == bgp_show_type_regexp) {
11073 regex_t *regex = output_arg;
d62a17ae 11074
40381db7 11075 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11076 == REG_NOMATCH)
11077 continue;
11078 }
11079 if (type == bgp_show_type_prefix_list) {
11080 struct prefix_list *plist = output_arg;
d62a17ae 11081
9bcb3eef 11082 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11083 != PREFIX_PERMIT)
11084 continue;
11085 }
ed126382
DA
11086 if (type == bgp_show_type_access_list) {
11087 struct access_list *alist = output_arg;
11088
11089 if (access_list_apply(alist, dest_p) !=
11090 FILTER_PERMIT)
11091 continue;
11092 }
98ce9a06
DS
11093 if (type == bgp_show_type_filter_list) {
11094 struct as_list *as_list = output_arg;
d62a17ae 11095
40381db7 11096 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11097 != AS_FILTER_PERMIT)
11098 continue;
11099 }
11100 if (type == bgp_show_type_route_map) {
11101 struct route_map *rmap = output_arg;
9b6d8fcf 11102 struct bgp_path_info path;
98ce9a06 11103 struct attr dummy_attr;
b68885f9 11104 route_map_result_t ret;
d62a17ae 11105
6f4f49b2 11106 dummy_attr = *pi->attr;
d62a17ae 11107
40381db7 11108 path.peer = pi->peer;
9b6d8fcf 11109 path.attr = &dummy_attr;
d62a17ae 11110
1782514f 11111 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11112 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11113 if (ret == RMAP_DENYMATCH)
11114 continue;
11115 }
11116 if (type == bgp_show_type_neighbor
11117 || type == bgp_show_type_flap_neighbor
11118 || type == bgp_show_type_damp_neighbor) {
11119 union sockunion *su = output_arg;
11120
40381db7
DS
11121 if (pi->peer == NULL
11122 || pi->peer->su_remote == NULL
11123 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11124 continue;
11125 }
11126 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11127 uint32_t destination;
d62a17ae 11128
9bcb3eef 11129 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11130 if (IN_CLASSC(destination)
9bcb3eef 11131 && dest_p->prefixlen == 24)
98ce9a06
DS
11132 continue;
11133 if (IN_CLASSB(destination)
9bcb3eef 11134 && dest_p->prefixlen == 16)
98ce9a06
DS
11135 continue;
11136 if (IN_CLASSA(destination)
9bcb3eef 11137 && dest_p->prefixlen == 8)
98ce9a06
DS
11138 continue;
11139 }
11140 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11141 p = output_arg;
9bcb3eef 11142 if (!prefix_match(p, dest_p))
98ce9a06
DS
11143 continue;
11144 }
11145 if (type == bgp_show_type_community_all) {
9a706b42 11146 if (!picomm)
98ce9a06
DS
11147 continue;
11148 }
11149 if (type == bgp_show_type_community) {
11150 struct community *com = output_arg;
d62a17ae 11151
9a706b42 11152 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11153 continue;
11154 }
11155 if (type == bgp_show_type_community_exact) {
11156 struct community *com = output_arg;
d62a17ae 11157
9a706b42 11158 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11159 continue;
11160 }
11161 if (type == bgp_show_type_community_list) {
11162 struct community_list *list = output_arg;
d62a17ae 11163
9a706b42 11164 if (!community_list_match(picomm, list))
98ce9a06
DS
11165 continue;
11166 }
a4d82a8a 11167 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11168 struct community_list *list = output_arg;
d62a17ae 11169
9a706b42 11170 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11171 continue;
11172 }
11173 if (type == bgp_show_type_lcommunity) {
11174 struct lcommunity *lcom = output_arg;
d62a17ae 11175
1bcf3a96
DA
11176 if (!bgp_attr_get_lcommunity(pi->attr) ||
11177 !lcommunity_match(
11178 bgp_attr_get_lcommunity(pi->attr),
11179 lcom))
98ce9a06
DS
11180 continue;
11181 }
36a206db 11182
11183 if (type == bgp_show_type_lcommunity_exact) {
11184 struct lcommunity *lcom = output_arg;
11185
1bcf3a96
DA
11186 if (!bgp_attr_get_lcommunity(pi->attr) ||
11187 !lcommunity_cmp(
11188 bgp_attr_get_lcommunity(pi->attr),
11189 lcom))
36a206db 11190 continue;
11191 }
98ce9a06
DS
11192 if (type == bgp_show_type_lcommunity_list) {
11193 struct community_list *list = output_arg;
d62a17ae 11194
1bcf3a96
DA
11195 if (!lcommunity_list_match(
11196 bgp_attr_get_lcommunity(pi->attr),
11197 list))
98ce9a06
DS
11198 continue;
11199 }
36a206db 11200 if (type
11201 == bgp_show_type_lcommunity_list_exact) {
11202 struct community_list *list = output_arg;
11203
11204 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11205 bgp_attr_get_lcommunity(pi->attr),
11206 list))
36a206db 11207 continue;
11208 }
98ce9a06 11209 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11210 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11211 continue;
11212 }
11213 if (type == bgp_show_type_dampend_paths
11214 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11215 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11216 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11217 continue;
11218 }
11219
11220 if (!use_json && header) {
23d0a753
DA
11221 vty_out(vty,
11222 "BGP table version is %" PRIu64
11223 ", local router ID is %pI4, vrf id ",
11224 table->version, &bgp->router_id);
9df8b37c
PZ
11225 if (bgp->vrf_id == VRF_UNKNOWN)
11226 vty_out(vty, "%s", VRFID_NONE_STR);
11227 else
11228 vty_out(vty, "%u", bgp->vrf_id);
11229 vty_out(vty, "\n");
01eced22
AD
11230 vty_out(vty, "Default local pref %u, ",
11231 bgp->default_local_pref);
11232 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11233 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11234 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11235 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11236 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11237 if (type == bgp_show_type_dampend_paths
11238 || type == bgp_show_type_damp_neighbor)
98ce9a06 11239 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11240 else if (type == bgp_show_type_flap_statistics
11241 || type == bgp_show_type_flap_neighbor)
98ce9a06 11242 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11243 else
ae248832
MK
11244 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11245 : BGP_SHOW_HEADER));
2aad8c42
MS
11246 header = false;
11247
11248 } else if (json_detail && json_paths != NULL) {
11249 const struct prefix_rd *prd;
11250 json_object *jtemp;
11251
11252 /* Use common detail header, for most types;
11253 * need a json 'object'.
11254 */
11255
11256 jtemp = json_object_new_object();
11257 prd = bgp_rd_from_dest(dest, safi);
11258
11259 route_vty_out_detail_header(
11260 vty, bgp, dest, prd, table->afi,
11261 safi, jtemp);
11262
11263 json_object_array_add(json_paths, jtemp);
11264
11265 json_detail = false;
d62a17ae 11266 }
2aad8c42 11267
98ce9a06
DS
11268 if (rd != NULL && !display && !output_count) {
11269 if (!use_json)
11270 vty_out(vty,
11271 "Route Distinguisher: %s\n",
11272 rd);
d62a17ae 11273 }
98ce9a06
DS
11274 if (type == bgp_show_type_dampend_paths
11275 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11276 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11277 AFI_IP, safi, use_json,
11278 json_paths);
98ce9a06
DS
11279 else if (type == bgp_show_type_flap_statistics
11280 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11281 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11282 AFI_IP, safi, use_json,
11283 json_paths);
f280c93b
DA
11284 else {
11285 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11286 route_vty_out_detail(
11287 vty, bgp, dest, pi,
11288 family2afi(dest_p->family),
11289 safi, RPKI_NOT_BEING_USED,
11290 json_paths);
11291 else
11292 route_vty_out(vty, dest_p, pi, display,
11293 safi, json_paths, wide);
11294 }
98ce9a06 11295 display++;
d62a17ae 11296 }
11297
98ce9a06
DS
11298 if (display) {
11299 output_count++;
11300 if (!use_json)
11301 continue;
11302
625d2931 11303 /* encode prefix */
9bcb3eef 11304 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11305 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11306
1840384b 11307
b54892e0
DS
11308 bgp_fs_nlri_get_string(
11309 (unsigned char *)
9bcb3eef
DS
11310 dest_p->u.prefix_flowspec.ptr,
11311 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11312 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11313 family2afi(dest_p->u
11314 .prefix_flowspec.family));
625d2931 11315 if (first)
b54892e0 11316 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11317 dest_p->u.prefix_flowspec
b54892e0 11318 .prefixlen);
625d2931 11319 else
b54892e0 11320 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11321 dest_p->u.prefix_flowspec
b54892e0 11322 .prefixlen);
625d2931 11323 } else {
625d2931 11324 if (first)
1b78780b 11325 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11326 else
1b78780b 11327 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11328 }
3757f964 11329 vty_json(vty, json_paths);
449feb8e 11330 json_paths = NULL;
98ce9a06 11331 first = 0;
1f83ed02
DS
11332 } else
11333 json_object_free(json_paths);
98ce9a06
DS
11334 }
11335
1ae44dfc
LB
11336 if (output_cum) {
11337 output_count += *output_cum;
11338 *output_cum = output_count;
11339 }
11340 if (total_cum) {
11341 total_count += *total_cum;
11342 *total_cum = total_count;
11343 }
d62a17ae 11344 if (use_json) {
9386b588 11345 if (rd) {
a4d82a8a 11346 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11347 }
11348 if (is_last) {
a4d82a8a
PZ
11349 unsigned long i;
11350 for (i = 0; i < *json_header_depth; ++i)
11351 vty_out(vty, " } ");
96f3485c
MK
11352 if (!all)
11353 vty_out(vty, "\n");
9386b588 11354 }
d62a17ae 11355 } else {
1ae44dfc
LB
11356 if (is_last) {
11357 /* No route is displayed */
11358 if (output_count == 0) {
11359 if (type == bgp_show_type_normal)
11360 vty_out(vty,
11361 "No BGP prefixes displayed, %ld exist\n",
11362 total_count);
11363 } else
d62a17ae 11364 vty_out(vty,
1ae44dfc
LB
11365 "\nDisplayed %ld routes and %ld total paths\n",
11366 output_count, total_count);
11367 }
d62a17ae 11368 }
718e3744 11369
d62a17ae 11370 return CMD_SUCCESS;
718e3744 11371}
11372
1ae44dfc
LB
11373int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11374 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11375 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11376{
9bcb3eef 11377 struct bgp_dest *dest, *next;
1ae44dfc
LB
11378 unsigned long output_cum = 0;
11379 unsigned long total_cum = 0;
9386b588 11380 unsigned long json_header_depth = 0;
67009e22 11381 struct bgp_table *itable;
0136788c 11382 bool show_msg;
96c81f66 11383 uint16_t show_flags = 0;
0136788c
LB
11384
11385 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11386
96f3485c
MK
11387 if (use_json)
11388 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11389
9bcb3eef
DS
11390 for (dest = bgp_table_top(table); dest; dest = next) {
11391 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11392
9bcb3eef
DS
11393 next = bgp_route_next(dest);
11394 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11395 continue;
67009e22 11396
9bcb3eef 11397 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11398 if (itable != NULL) {
1ae44dfc 11399 struct prefix_rd prd;
06b9f471 11400 char rd[RD_ADDRSTRLEN];
1ae44dfc 11401
9bcb3eef 11402 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11403 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11404 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11405 rd, next == NULL, &output_cum,
11406 &total_cum, &json_header_depth,
1e2ce4f1 11407 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11408 if (next == NULL)
11409 show_msg = false;
1ae44dfc
LB
11410 }
11411 }
0136788c
LB
11412 if (show_msg) {
11413 if (output_cum == 0)
11414 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11415 total_cum);
11416 else
11417 vty_out(vty,
11418 "\nDisplayed %ld routes and %ld total paths\n",
11419 output_cum, total_cum);
11420 }
1ae44dfc
LB
11421 return CMD_SUCCESS;
11422}
2aad8c42 11423
d62a17ae 11424static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11425 enum bgp_show_type type, void *output_arg,
96c81f66 11426 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11427{
d62a17ae 11428 struct bgp_table *table;
9386b588 11429 unsigned long json_header_depth = 0;
96f3485c 11430 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11431
d62a17ae 11432 if (bgp == NULL) {
11433 bgp = bgp_get_default();
11434 }
fee0f4c6 11435
d62a17ae 11436 if (bgp == NULL) {
11437 if (!use_json)
11438 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11439 else
11440 vty_out(vty, "{}\n");
d62a17ae 11441 return CMD_WARNING;
11442 }
4dd6177e 11443
cd8c2a27
MS
11444 /* Labeled-unicast routes live in the unicast table. */
11445 if (safi == SAFI_LABELED_UNICAST)
11446 safi = SAFI_UNICAST;
11447
1ae44dfc 11448 table = bgp->rib[afi][safi];
d62a17ae 11449 /* use MPLS and ENCAP specific shows until they are merged */
11450 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11451 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11452 output_arg, use_json);
d62a17ae 11453 }
dba3c1d3
PG
11454
11455 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11456 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11457 output_arg, use_json,
11458 1, NULL, NULL);
11459 }
fee0f4c6 11460
96f3485c 11461 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11462 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11463 rpki_target_state);
fee0f4c6 11464}
11465
d62a17ae 11466static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11467 safi_t safi, uint16_t show_flags)
f186de26 11468{
d62a17ae 11469 struct listnode *node, *nnode;
11470 struct bgp *bgp;
11471 int is_first = 1;
9f049418 11472 bool route_output = false;
96f3485c 11473 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11474
d62a17ae 11475 if (use_json)
11476 vty_out(vty, "{\n");
9f689658 11477
d62a17ae 11478 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11479 route_output = true;
d62a17ae 11480 if (use_json) {
11481 if (!is_first)
11482 vty_out(vty, ",\n");
11483 else
11484 is_first = 0;
11485
11486 vty_out(vty, "\"%s\":",
11487 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11488 ? VRF_DEFAULT_NAME
d62a17ae 11489 : bgp->name);
11490 } else {
11491 vty_out(vty, "\nInstance %s:\n",
11492 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11493 ? VRF_DEFAULT_NAME
d62a17ae 11494 : bgp->name);
11495 }
11496 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11497 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11498 }
9f689658 11499
d62a17ae 11500 if (use_json)
11501 vty_out(vty, "}\n");
9f049418
DS
11502 else if (!route_output)
11503 vty_out(vty, "%% BGP instance not found\n");
f186de26 11504}
11505
718e3744 11506/* Header of detailed BGP route information */
d62a17ae 11507void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11508 struct bgp_dest *dest,
11509 const struct prefix_rd *prd,
d62a17ae 11510 afi_t afi, safi_t safi, json_object *json)
11511{
40381db7 11512 struct bgp_path_info *pi;
b54892e0 11513 const struct prefix *p;
d62a17ae 11514 struct peer *peer;
11515 struct listnode *node, *nnode;
06b9f471 11516 char buf1[RD_ADDRSTRLEN];
d62a17ae 11517 int count = 0;
11518 int best = 0;
11519 int suppress = 0;
c5f1e1b2
C
11520 int accept_own = 0;
11521 int route_filter_translated_v4 = 0;
11522 int route_filter_v4 = 0;
11523 int route_filter_translated_v6 = 0;
11524 int route_filter_v6 = 0;
11525 int llgr_stale = 0;
11526 int no_llgr = 0;
11527 int accept_own_nexthop = 0;
11528 int blackhole = 0;
d62a17ae 11529 int no_export = 0;
11530 int no_advertise = 0;
11531 int local_as = 0;
c5f1e1b2 11532 int no_peer = 0;
d62a17ae 11533 int first = 1;
11534 int has_valid_label = 0;
11535 mpls_label_t label = 0;
11536 json_object *json_adv_to = NULL;
67f67ba4
DA
11537 uint32_t ttl = 0;
11538 uint32_t bos = 0;
11539 uint32_t exp = 0;
9bedbb1e 11540
67f67ba4 11541 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11542
67f67ba4
DA
11543 p = bgp_dest_get_prefix(dest);
11544 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11545
44c69747 11546 if (safi == SAFI_EVPN) {
d62a17ae 11547
44c69747 11548 if (!json) {
2dbe669b 11549 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11550 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11551 : "",
2dbe669b 11552 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11553 } else {
11554 json_object_string_add(json, "rd",
11555 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11556 "");
11557 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11558 }
11559 } else {
11560 if (!json) {
9119ef3a
DA
11561 vty_out(vty,
11562 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11563 "\n",
d62a17ae 11564 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11565 ? prefix_rd2str(prd, buf1,
11566 sizeof(buf1))
11567 : ""),
9119ef3a
DA
11568 safi == SAFI_MPLS_VPN ? ":" : "", p,
11569 dest->version);
cd1964ff 11570
9119ef3a 11571 } else {
67d7e256 11572 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11573 json_object_int_add(json, "version", dest->version);
11574
11575 }
44c69747
LK
11576 }
11577
11578 if (has_valid_label) {
11579 if (json)
11580 json_object_int_add(json, "localLabel", label);
11581 else
d62a17ae 11582 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11583 }
11584
11585 if (!json)
d62a17ae 11586 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11587 vty_out(vty, "not allocated\n");
718e3744 11588
9bcb3eef 11589 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11590 struct community *picomm = NULL;
11591
11592 picomm = bgp_attr_get_community(pi->attr);
11593
d62a17ae 11594 count++;
40381db7 11595 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11596 best = count;
4056a5f6 11597 if (bgp_path_suppressed(pi))
d62a17ae 11598 suppress = 1;
cee9c031 11599
9a706b42 11600 if (!picomm)
cee9c031
QY
11601 continue;
11602
11603 no_advertise += community_include(
9a706b42
DA
11604 picomm, COMMUNITY_NO_ADVERTISE);
11605 no_export +=
11606 community_include(picomm, COMMUNITY_NO_EXPORT);
11607 local_as +=
11608 community_include(picomm, COMMUNITY_LOCAL_AS);
11609 accept_own +=
11610 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11611 route_filter_translated_v4 += community_include(
9a706b42 11612 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11613 route_filter_translated_v6 += community_include(
9a706b42 11614 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11615 route_filter_v4 += community_include(
9a706b42 11616 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11617 route_filter_v6 += community_include(
9a706b42
DA
11618 picomm, COMMUNITY_ROUTE_FILTER_v6);
11619 llgr_stale +=
11620 community_include(picomm, COMMUNITY_LLGR_STALE);
11621 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11622 accept_own_nexthop += community_include(
11623 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11624 blackhole +=
11625 community_include(picomm, COMMUNITY_BLACKHOLE);
11626 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11627 }
718e3744 11628 }
718e3744 11629
d62a17ae 11630 if (!json) {
11631 vty_out(vty, "Paths: (%d available", count);
11632 if (best) {
11633 vty_out(vty, ", best #%d", best);
b84060bb
PG
11634 if (safi == SAFI_UNICAST) {
11635 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11636 vty_out(vty, ", table %s",
11637 VRF_DEFAULT_NAME);
11638 else
11639 vty_out(vty, ", vrf %s",
11640 bgp->name);
11641 }
d62a17ae 11642 } else
11643 vty_out(vty, ", no best path");
11644
c5f1e1b2
C
11645 if (accept_own)
11646 vty_out(vty,
11647 ", accept own local route exported and imported in different VRF");
11648 else if (route_filter_translated_v4)
11649 vty_out(vty,
11650 ", mark translated RTs for VPNv4 route filtering");
11651 else if (route_filter_v4)
11652 vty_out(vty,
11653 ", attach RT as-is for VPNv4 route filtering");
11654 else if (route_filter_translated_v6)
11655 vty_out(vty,
11656 ", mark translated RTs for VPNv6 route filtering");
11657 else if (route_filter_v6)
11658 vty_out(vty,
11659 ", attach RT as-is for VPNv6 route filtering");
11660 else if (llgr_stale)
11661 vty_out(vty,
1479ed2f 11662 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11663 else if (no_llgr)
11664 vty_out(vty,
11665 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11666 else if (accept_own_nexthop)
11667 vty_out(vty,
11668 ", accept local nexthop");
11669 else if (blackhole)
11670 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11671 else if (no_export)
11672 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11673 else if (no_advertise)
11674 vty_out(vty, ", not advertised to any peer");
d62a17ae 11675 else if (local_as)
11676 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11677 else if (no_peer)
11678 vty_out(vty,
11679 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11680
11681 if (suppress)
11682 vty_out(vty,
11683 ", Advertisements suppressed by an aggregate.");
11684 vty_out(vty, ")\n");
11685 }
718e3744 11686
d62a17ae 11687 /* If we are not using addpath then we can display Advertised to and
11688 * that will
11689 * show what peers we advertised the bestpath to. If we are using
11690 * addpath
11691 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11692 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11693 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11694 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11695 if (json && !json_adv_to)
11696 json_adv_to = json_object_new_object();
11697
11698 route_vty_out_advertised_to(
11699 vty, peer, &first,
11700 " Advertised to non peer-group peers:\n ",
11701 json_adv_to);
11702 }
11703 }
11704
11705 if (json) {
11706 if (json_adv_to) {
11707 json_object_object_add(json, "advertisedTo",
11708 json_adv_to);
11709 }
11710 } else {
11711 if (first)
11712 vty_out(vty, " Not advertised to any peer");
11713 vty_out(vty, "\n");
11714 }
11715 }
718e3744 11716}
11717
edfee30d 11718static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11719 struct bgp_dest *bgp_node, struct vty *vty,
11720 struct bgp *bgp, afi_t afi, safi_t safi,
11721 json_object *json, enum bgp_path_type pathtype,
4027d19b 11722 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11723{
11724 struct bgp_path_info *pi;
11725 int header = 1;
11726 char rdbuf[RD_ADDRSTRLEN];
11727 json_object *json_header = NULL;
11728 json_object *json_paths = NULL;
4933eaaf 11729 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11730
9bcb3eef 11731 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11732 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11733
11734 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11735 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11736 pi->peer, pi->attr, p);
4933eaaf 11737
4027d19b
DS
11738 if (rpki_target_state != RPKI_NOT_BEING_USED
11739 && rpki_curr_state != rpki_target_state)
4933eaaf 11740 continue;
44c69747
LK
11741
11742 if (json && !json_paths) {
11743 /* Instantiate json_paths only if path is valid */
11744 json_paths = json_object_new_array();
11745 if (pfx_rd) {
11746 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11747 json_header = json_object_new_object();
11748 } else
11749 json_header = json;
11750 }
11751
11752 if (header) {
11753 route_vty_out_detail_header(
11754 vty, bgp, bgp_node, pfx_rd,
11755 AFI_IP, safi, json_header);
11756 header = 0;
11757 }
11758 (*display)++;
11759
11760 if (pathtype == BGP_PATH_SHOW_ALL
11761 || (pathtype == BGP_PATH_SHOW_BESTPATH
11762 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11763 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11764 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11765 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11766 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11767 safi, rpki_curr_state, json_paths);
44c69747
LK
11768 }
11769
11770 if (json && json_paths) {
11771 json_object_object_add(json_header, "paths", json_paths);
11772
11773 if (pfx_rd)
11774 json_object_object_add(json, rdbuf, json_header);
11775 }
11776}
11777
2aad8c42
MS
11778/*
11779 * Return rd based on safi
11780 */
11781static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11782 safi_t safi)
11783{
11784 switch (safi) {
11785 case SAFI_MPLS_VPN:
11786 case SAFI_ENCAP:
11787 case SAFI_EVPN:
11788 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11789 default:
11790 return NULL;
11791
11792 }
11793}
11794
718e3744 11795/* Display specified route of BGP table. */
d62a17ae 11796static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11797 struct bgp_table *rib, const char *ip_str,
11798 afi_t afi, safi_t safi,
4027d19b 11799 enum rpki_states rpki_target_state,
d62a17ae 11800 struct prefix_rd *prd, int prefix_check,
9f049418 11801 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11802{
11803 int ret;
d62a17ae 11804 int display = 0;
11805 struct prefix match;
9bcb3eef
DS
11806 struct bgp_dest *dest;
11807 struct bgp_dest *rm;
d62a17ae 11808 struct bgp_table *table;
11809 json_object *json = NULL;
11810 json_object *json_paths = NULL;
11811
11812 /* Check IP address argument. */
11813 ret = str2prefix(ip_str, &match);
11814 if (!ret) {
11815 vty_out(vty, "address is malformed\n");
11816 return CMD_WARNING;
11817 }
718e3744 11818
d62a17ae 11819 match.family = afi2family(afi);
b05a1c8b 11820
44c69747 11821 if (use_json)
d62a17ae 11822 json = json_object_new_object();
718e3744 11823
44c69747 11824 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11825 for (dest = bgp_table_top(rib); dest;
11826 dest = bgp_route_next(dest)) {
11827 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11828
9bcb3eef 11829 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11830 continue;
9bcb3eef 11831 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11832 if (!table)
ea47320b 11833 continue;
d62a17ae 11834
4953391b
DA
11835 rm = bgp_node_match(table, &match);
11836 if (rm == NULL)
ea47320b 11837 continue;
d62a17ae 11838
9bcb3eef 11839 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11840 if (prefix_check
b54892e0 11841 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11842 bgp_dest_unlock_node(rm);
ea47320b
DL
11843 continue;
11844 }
d62a17ae 11845
9bcb3eef 11846 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11847 bgp, afi, safi, json, pathtype,
4027d19b 11848 &display, rpki_target_state);
44c69747 11849
9bcb3eef 11850 bgp_dest_unlock_node(rm);
44c69747
LK
11851 }
11852 } else if (safi == SAFI_EVPN) {
9bcb3eef 11853 struct bgp_dest *longest_pfx;
cded3b72 11854 bool is_exact_pfxlen_match = false;
44c69747 11855
9bcb3eef
DS
11856 for (dest = bgp_table_top(rib); dest;
11857 dest = bgp_route_next(dest)) {
11858 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11859
9bcb3eef 11860 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11861 continue;
9bcb3eef 11862 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11863 if (!table)
11864 continue;
11865
11866 longest_pfx = NULL;
cded3b72 11867 is_exact_pfxlen_match = false;
44c69747
LK
11868 /*
11869 * Search through all the prefixes for a match. The
11870 * pfx's are enumerated in ascending order of pfxlens.
11871 * So, the last pfx match is the longest match. Set
11872 * is_exact_pfxlen_match when we get exact pfxlen match
11873 */
11874 for (rm = bgp_table_top(table); rm;
11875 rm = bgp_route_next(rm)) {
b54892e0 11876 const struct prefix *rm_p =
9bcb3eef 11877 bgp_dest_get_prefix(rm);
44c69747
LK
11878 /*
11879 * Get prefixlen of the ip-prefix within type5
11880 * evpn route
11881 */
b54892e0
DS
11882 if (evpn_type5_prefix_match(rm_p, &match)
11883 && rm->info) {
44c69747
LK
11884 longest_pfx = rm;
11885 int type5_pfxlen =
b54892e0
DS
11886 bgp_evpn_get_type5_prefixlen(
11887 rm_p);
44c69747 11888 if (type5_pfxlen == match.prefixlen) {
cded3b72 11889 is_exact_pfxlen_match = true;
9bcb3eef 11890 bgp_dest_unlock_node(rm);
44c69747
LK
11891 break;
11892 }
d62a17ae 11893 }
11894 }
ea47320b 11895
44c69747
LK
11896 if (!longest_pfx)
11897 continue;
11898
11899 if (prefix_check && !is_exact_pfxlen_match)
11900 continue;
11901
11902 rm = longest_pfx;
9bcb3eef 11903 bgp_dest_lock_node(rm);
44c69747 11904
9bcb3eef 11905 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11906 bgp, afi, safi, json, pathtype,
4027d19b 11907 &display, rpki_target_state);
44c69747 11908
9bcb3eef 11909 bgp_dest_unlock_node(rm);
d62a17ae 11910 }
98a9dbc7 11911 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11912 if (use_json)
11913 json_paths = json_object_new_array();
11914
63a0b7a9
PG
11915 display = bgp_flowspec_display_match_per_ip(afi, rib,
11916 &match, prefix_check,
11917 vty,
11918 use_json,
11919 json_paths);
d5f20468
SP
11920 if (use_json) {
11921 if (display)
11922 json_object_object_add(json, "paths",
11923 json_paths);
11924 else
11925 json_object_free(json_paths);
11926 }
d62a17ae 11927 } else {
4953391b
DA
11928 dest = bgp_node_match(rib, &match);
11929 if (dest != NULL) {
9bcb3eef 11930 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11931 if (!prefix_check
9bcb3eef
DS
11932 || dest_p->prefixlen == match.prefixlen) {
11933 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11934 safi, json, pathtype,
4027d19b 11935 &display, rpki_target_state);
d62a17ae 11936 }
11937
9bcb3eef 11938 bgp_dest_unlock_node(dest);
d62a17ae 11939 }
11940 }
e5eee9af 11941
d62a17ae 11942 if (use_json) {
75eeda93 11943 vty_json(vty, json);
d62a17ae 11944 } else {
11945 if (!display) {
11946 vty_out(vty, "%% Network not in table\n");
11947 return CMD_WARNING;
11948 }
11949 }
b05a1c8b 11950
d62a17ae 11951 return CMD_SUCCESS;
718e3744 11952}
11953
fee0f4c6 11954/* Display specified route of Main RIB */
d62a17ae 11955static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11956 afi_t afi, safi_t safi, struct prefix_rd *prd,
11957 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11958 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11959{
9b86009a 11960 if (!bgp) {
d62a17ae 11961 bgp = bgp_get_default();
9b86009a
RW
11962 if (!bgp) {
11963 if (!use_json)
11964 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11965 else
11966 vty_out(vty, "{}\n");
9b86009a
RW
11967 return CMD_WARNING;
11968 }
11969 }
d62a17ae 11970
11971 /* labeled-unicast routes live in the unicast table */
11972 if (safi == SAFI_LABELED_UNICAST)
11973 safi = SAFI_UNICAST;
11974
11975 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11976 afi, safi, rpki_target_state, prd,
8aa22bbb 11977 prefix_check, pathtype, use_json);
d62a17ae 11978}
11979
11980static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11981 struct cmd_token **argv, bool exact, afi_t afi,
11982 safi_t safi, bool uj)
d62a17ae 11983{
11984 struct lcommunity *lcom;
11985 struct buffer *b;
11986 int i;
11987 char *str;
11988 int first = 0;
96c81f66 11989 uint16_t show_flags = 0;
4f28b2b5 11990 int ret;
96f3485c
MK
11991
11992 if (uj)
11993 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11994
11995 b = buffer_new(1024);
11996 for (i = 0; i < argc; i++) {
11997 if (first)
11998 buffer_putc(b, ' ');
11999 else {
12000 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12001 first = 1;
12002 buffer_putstr(b, argv[i]->arg);
12003 }
12004 }
12005 }
12006 buffer_putc(b, '\0');
57d187bc 12007
d62a17ae 12008 str = buffer_getstr(b);
12009 buffer_free(b);
57d187bc 12010
d62a17ae 12011 lcom = lcommunity_str2com(str);
12012 XFREE(MTYPE_TMP, str);
12013 if (!lcom) {
12014 vty_out(vty, "%% Large-community malformed\n");
12015 return CMD_WARNING;
12016 }
57d187bc 12017
4f28b2b5 12018 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12019 (exact ? bgp_show_type_lcommunity_exact
12020 : bgp_show_type_lcommunity),
12021 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12022
12023 lcommunity_free(&lcom);
12024 return ret;
57d187bc
JS
12025}
12026
d62a17ae 12027static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12028 const char *lcom, bool exact, afi_t afi,
12029 safi_t safi, bool uj)
57d187bc 12030{
d62a17ae 12031 struct community_list *list;
96c81f66 12032 uint16_t show_flags = 0;
96f3485c
MK
12033
12034 if (uj)
12035 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12036
57d187bc 12037
e237b0d2 12038 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12039 LARGE_COMMUNITY_LIST_MASTER);
12040 if (list == NULL) {
12041 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12042 lcom);
12043 return CMD_WARNING;
12044 }
57d187bc 12045
36a206db 12046 return bgp_show(vty, bgp, afi, safi,
12047 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12048 : bgp_show_type_lcommunity_list),
1e2ce4f1 12049 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12050}
12051
52951b63
DS
12052DEFUN (show_ip_bgp_large_community_list,
12053 show_ip_bgp_large_community_list_cmd,
77a3a95e 12054 "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
12055 SHOW_STR
12056 IP_STR
12057 BGP_STR
12058 BGP_INSTANCE_HELP_STR
9bedbb1e 12059 BGP_AFI_HELP_STR
4dd6177e 12060 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12061 "Display routes matching the large-community-list\n"
12062 "large-community-list number\n"
12063 "large-community-list name\n"
36a206db 12064 "Exact match of the large-communities\n"
52951b63
DS
12065 JSON_STR)
12066{
d62a17ae 12067 afi_t afi = AFI_IP6;
12068 safi_t safi = SAFI_UNICAST;
12069 int idx = 0;
36a206db 12070 bool exact_match = 0;
4d678463 12071 struct bgp *bgp = NULL;
9f049418 12072 bool uj = use_json(argc, argv);
d62a17ae 12073
ef3364f0
DA
12074 if (uj)
12075 argc--;
4d678463 12076
ef3364f0
DA
12077 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12078 &bgp, uj);
12079 if (!idx)
12080 return CMD_WARNING;
d62a17ae 12081
12082 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12083
12084 const char *clist_number_or_name = argv[++idx]->arg;
12085
12086 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12087 exact_match = 1;
12088
12089 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12090 exact_match, afi, safi, uj);
52951b63
DS
12091}
12092DEFUN (show_ip_bgp_large_community,
12093 show_ip_bgp_large_community_cmd,
36a206db 12094 "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
12095 SHOW_STR
12096 IP_STR
12097 BGP_STR
12098 BGP_INSTANCE_HELP_STR
9bedbb1e 12099 BGP_AFI_HELP_STR
4dd6177e 12100 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12101 "Display routes matching the large-communities\n"
12102 "List of large-community numbers\n"
36a206db 12103 "Exact match of the large-communities\n"
52951b63
DS
12104 JSON_STR)
12105{
d62a17ae 12106 afi_t afi = AFI_IP6;
12107 safi_t safi = SAFI_UNICAST;
12108 int idx = 0;
36a206db 12109 bool exact_match = 0;
4d678463 12110 struct bgp *bgp = NULL;
9f049418 12111 bool uj = use_json(argc, argv);
96c81f66 12112 uint16_t show_flags = 0;
d62a17ae 12113
96f3485c
MK
12114 if (uj) {
12115 argc--;
12116 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12117 }
4d678463 12118
96f3485c
MK
12119 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12120 &bgp, uj);
12121 if (!idx)
12122 return CMD_WARNING;
d62a17ae 12123
36a206db 12124 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12125 if (argv_find(argv, argc, "exact-match", &idx))
12126 exact_match = 1;
12127 return bgp_show_lcommunity(vty, bgp, argc, argv,
12128 exact_match, afi, safi, uj);
12129 } else
d62a17ae 12130 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12131 bgp_show_type_lcommunity_all, NULL, show_flags,
12132 RPKI_NOT_BEING_USED);
52951b63
DS
12133}
12134
71f1613a
DA
12135static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12136 safi_t safi, struct json_object *json_array);
d62a17ae 12137static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12138 safi_t safi, struct json_object *json);
e01ca200 12139
7b2ff250 12140
9ab0cf58
PG
12141DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12142 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12143 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12144 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12145{
12146 bool uj = use_json(argc, argv);
12147 struct bgp *bgp = NULL;
ec76a1d1
DA
12148 safi_t safi = SAFI_UNICAST;
12149 afi_t afi = AFI_IP6;
4265b261 12150 int idx = 0;
6c9d22e2
PG
12151 struct json_object *json_all = NULL;
12152 struct json_object *json_afi_safi = NULL;
4265b261
PG
12153
12154 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12155 &bgp, false);
71f1613a 12156 if (!idx)
4265b261 12157 return CMD_WARNING;
6c9d22e2 12158
4265b261 12159 if (uj)
6c9d22e2 12160 json_all = json_object_new_object();
4265b261 12161
9ab0cf58
PG
12162 FOREACH_AFI_SAFI (afi, safi) {
12163 /*
12164 * So limit output to those afi/safi pairs that
12165 * actually have something interesting in them
12166 */
12167 if (strmatch(get_afi_safi_str(afi, safi, true),
12168 "Unknown")) {
12169 continue;
12170 }
12171 if (uj) {
12172 json_afi_safi = json_object_new_array();
12173 json_object_object_add(
12174 json_all,
12175 get_afi_safi_str(afi, safi, true),
12176 json_afi_safi);
12177 } else {
12178 json_afi_safi = NULL;
6c9d22e2 12179 }
9ab0cf58
PG
12180
12181 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12182 }
6c9d22e2 12183
3757f964
DA
12184 if (uj)
12185 vty_json(vty, json_all);
6c9d22e2 12186
4265b261
PG
12187 return CMD_SUCCESS;
12188}
12189
7b2ff250 12190/* BGP route print out function without JSON */
14718643
PG
12191DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12192 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12193 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12194 SHOW_STR
12195 IP_STR
12196 BGP_STR
12197 BGP_INSTANCE_HELP_STR
12198 L2VPN_HELP_STR
12199 EVPN_HELP_STR
12200 "BGP RIB advertisement statistics\n"
12201 JSON_STR)
12202{
ec76a1d1
DA
12203 afi_t afi = AFI_IP6;
12204 safi_t safi = SAFI_UNICAST;
14718643
PG
12205 struct bgp *bgp = NULL;
12206 int idx = 0, ret;
12207 bool uj = use_json(argc, argv);
12208 struct json_object *json_afi_safi = NULL, *json = NULL;
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;
12214
12215 if (uj)
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);
14718643
PG
12227 }
12228 return ret;
12229}
12230
893cccd0 12231/* BGP route print out function without JSON */
9ab0cf58
PG
12232DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12233 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12234 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12235 "]]\
893cccd0 12236 statistics [json]",
9ab0cf58
PG
12237 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12238 BGP_SAFI_WITH_LABEL_HELP_STR
12239 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12240{
ec76a1d1
DA
12241 afi_t afi = AFI_IP6;
12242 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12243 struct bgp *bgp = NULL;
12244 int idx = 0, ret;
12245 bool uj = use_json(argc, argv);
6c9d22e2 12246 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12247
12248 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12249 &bgp, false);
12250 if (!idx)
12251 return CMD_WARNING;
6c9d22e2 12252
893cccd0 12253 if (uj)
6c9d22e2
PG
12254 json_afi_safi = json_object_new_array();
12255 else
12256 json_afi_safi = NULL;
12257
12258 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12259
12260 if (uj) {
12261 json = json_object_new_object();
12262 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12263 json_afi_safi);
3757f964 12264 vty_json(vty, json);
893cccd0
PG
12265 }
12266 return ret;
893cccd0 12267}
7b2ff250 12268
fe0f234d 12269DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12270 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12271 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12272 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12273 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12274 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12275 "Display the entries for all address families\n"
9ab0cf58
PG
12276 "Display detailed information about dampening\n"
12277 "Display detail of configured dampening parameters\n"
fe0f234d 12278 JSON_STR)
718e3744 12279{
d62a17ae 12280 afi_t afi = AFI_IP6;
12281 safi_t safi = SAFI_UNICAST;
d62a17ae 12282 struct bgp *bgp = NULL;
12283 int idx = 0;
96c81f66 12284 uint16_t show_flags = 0;
fe0f234d
RW
12285 bool uj = use_json(argc, argv);
12286
12287 if (uj) {
12288 argc--;
12289 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12290 }
96f3485c
MK
12291
12292 /* [<ipv4|ipv6> [all]] */
12293 if (all) {
12294 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12295 if (argv_find(argv, argc, "ipv4", &idx))
12296 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12297
12298 if (argv_find(argv, argc, "ipv6", &idx))
12299 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12300 }
d62a17ae 12301
12302 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12303 &bgp, false);
d62a17ae 12304 if (!idx)
12305 return CMD_WARNING;
12306
fe0f234d 12307 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12308}
12309
fe0f234d
RW
12310/* BGP route print out function */
12311DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12312 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12313 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12314 "]]\
96f3485c 12315 [all$all]\
cf4898bc
QY
12316 [cidr-only\
12317 |dampening <flap-statistics|dampened-paths>\
12318 |community [AA:NN|local-AS|no-advertise|no-export\
12319 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12320 |accept-own|accept-own-nexthop|route-filter-v6\
12321 |route-filter-v4|route-filter-translated-v6\
12322 |route-filter-translated-v4] [exact-match]\
70799983 12323 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12324 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12325 |prefix-list WORD\
ed126382 12326 |access-list ACCESSLIST_NAME\
70dd370f 12327 |route-map RMAP_NAME\
1e2ce4f1 12328 |rpki <invalid|valid|notfound>\
7d3cae70 12329 |version (1-4294967295)\
b4ad2fae 12330 |alias ALIAS_NAME\
39c3c736
RW
12331 |A.B.C.D/M longer-prefixes\
12332 |X:X::X:X/M longer-prefixes\
f280c93b 12333 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12334 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12335 BGP_SAFI_WITH_LABEL_HELP_STR
12336 "Display the entries for all address families\n"
12337 "Display only routes with non-natural netmasks\n"
12338 "Display detailed information about dampening\n"
12339 "Display flap statistics of routes\n"
12340 "Display paths suppressed due to dampening\n"
12341 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12342 "Do not send outside local AS (well-known community)\n"
12343 "Do not advertise to any peer (well-known community)\n"
12344 "Do not export to next AS (well-known community)\n"
12345 "Graceful shutdown (well-known community)\n"
12346 "Do not export to any peer (well-known community)\n"
12347 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12348 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12349 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12350 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12351 "Should accept VPN route with local nexthop (well-known community)\n"
12352 "RT VPNv6 route filtering (well-known community)\n"
12353 "RT VPNv4 route filtering (well-known community)\n"
12354 "RT translated VPNv6 route filtering (well-known community)\n"
12355 "RT translated VPNv4 route filtering (well-known community)\n"
12356 "Exact match of the communities\n"
70799983
RW
12357 "Community-list number\n"
12358 "Community-list name\n"
12359 "Display routes matching the community-list\n"
12360 "Exact match of the communities\n"
a7129347
RW
12361 "Display routes conforming to the filter-list\n"
12362 "Regular expression access list name\n"
6deaf579
RW
12363 "Display routes conforming to the prefix-list\n"
12364 "Prefix-list name\n"
ed126382
DA
12365 "Display routes conforming to the access-list\n"
12366 "Access-list name\n"
bf1a944a
RW
12367 "Display routes matching the route-map\n"
12368 "A route-map to match on\n"
a70a28a5
DA
12369 "RPKI route types\n"
12370 "A valid path as determined by rpki\n"
12371 "A invalid path as determined by rpki\n"
12372 "A path that has no rpki data\n"
12373 "Display prefixes with matching version numbers\n"
12374 "Version number and above\n"
12375 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12376 "BGP community alias\n"
12377 "IPv4 prefix\n"
12378 "Display route and more specific routes\n"
12379 "IPv6 prefix\n"
12380 "Display route and more specific routes\n"
12381 JSON_STR
a70a28a5
DA
12382 "Display detailed version of JSON output\n"
12383 "Increase table width for longer prefixes\n")
7b2ff250
DW
12384{
12385 afi_t afi = AFI_IP6;
12386 safi_t safi = SAFI_UNICAST;
12387 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12388 void *output_arg = NULL;
7b2ff250
DW
12389 struct bgp *bgp = NULL;
12390 int idx = 0;
d0086e8e 12391 int exact_match = 0;
96f3485c
MK
12392 char *community = NULL;
12393 bool first = true;
96c81f66 12394 uint16_t show_flags = 0;
4027d19b 12395 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12396 struct prefix p;
96f3485c
MK
12397
12398 if (uj) {
9f049418 12399 argc--;
96f3485c
MK
12400 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12401 }
12402
f280c93b
DA
12403 if (detail)
12404 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12405
96f3485c
MK
12406 /* [<ipv4|ipv6> [all]] */
12407 if (all) {
12408 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12409
12410 if (argv_find(argv, argc, "ipv4", &idx))
12411 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12412
12413 if (argv_find(argv, argc, "ipv6", &idx))
12414 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12415 }
12416
12417 if (wide)
12418 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12419
12420 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12421 &bgp, uj);
7b2ff250
DW
12422 if (!idx)
12423 return CMD_WARNING;
12424
7b2ff250 12425 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12426 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12427
12428 if (argv_find(argv, argc, "dampening", &idx)) {
12429 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12430 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12431 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12432 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12433 }
12434
12435 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12436 char *maybecomm = NULL;
d0086e8e 12437
79bc257a
RW
12438 if (idx + 1 < argc) {
12439 if (argv[idx + 1]->type == VARIABLE_TKN)
12440 maybecomm = argv[idx + 1]->arg;
12441 else
12442 maybecomm = argv[idx + 1]->text;
12443 }
12444
cf4898bc
QY
12445 if (maybecomm && !strmatch(maybecomm, "json")
12446 && !strmatch(maybecomm, "exact-match"))
12447 community = maybecomm;
d0086e8e 12448
cf4898bc
QY
12449 if (argv_find(argv, argc, "exact-match", &idx))
12450 exact_match = 1;
d0086e8e 12451
96f3485c
MK
12452 if (!community)
12453 sh_type = bgp_show_type_community_all;
12454 }
12455
70799983
RW
12456 if (argv_find(argv, argc, "community-list", &idx)) {
12457 const char *clist_number_or_name = argv[++idx]->arg;
12458 struct community_list *list;
12459
12460 if (argv_find(argv, argc, "exact-match", &idx))
12461 exact_match = 1;
12462
12463 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12464 COMMUNITY_LIST_MASTER);
12465 if (list == NULL) {
606d49a4 12466 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12467 clist_number_or_name);
12468 return CMD_WARNING;
12469 }
12470
12471 if (exact_match)
12472 sh_type = bgp_show_type_community_list_exact;
12473 else
12474 sh_type = bgp_show_type_community_list;
12475 output_arg = list;
12476 }
12477
a7129347
RW
12478 if (argv_find(argv, argc, "filter-list", &idx)) {
12479 const char *filter = argv[++idx]->arg;
12480 struct as_list *as_list;
12481
12482 as_list = as_list_lookup(filter);
12483 if (as_list == NULL) {
606d49a4 12484 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12485 filter);
12486 return CMD_WARNING;
12487 }
12488
12489 sh_type = bgp_show_type_filter_list;
12490 output_arg = as_list;
12491 }
12492
6deaf579
RW
12493 if (argv_find(argv, argc, "prefix-list", &idx)) {
12494 const char *prefix_list_str = argv[++idx]->arg;
12495 struct prefix_list *plist;
12496
12497 plist = prefix_list_lookup(afi, prefix_list_str);
12498 if (plist == NULL) {
606d49a4 12499 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12500 prefix_list_str);
12501 return CMD_WARNING;
12502 }
12503
12504 sh_type = bgp_show_type_prefix_list;
12505 output_arg = plist;
12506 }
12507
ed126382
DA
12508 if (argv_find(argv, argc, "access-list", &idx)) {
12509 const char *access_list_str = argv[++idx]->arg;
12510 struct access_list *alist;
12511
12512 alist = access_list_lookup(afi, access_list_str);
12513 if (!alist) {
606d49a4 12514 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12515 access_list_str);
12516 return CMD_WARNING;
12517 }
12518
12519 sh_type = bgp_show_type_access_list;
12520 output_arg = alist;
12521 }
12522
bf1a944a
RW
12523 if (argv_find(argv, argc, "route-map", &idx)) {
12524 const char *rmap_str = argv[++idx]->arg;
12525 struct route_map *rmap;
12526
12527 rmap = route_map_lookup_by_name(rmap_str);
12528 if (!rmap) {
606d49a4 12529 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12530 return CMD_WARNING;
12531 }
12532
12533 sh_type = bgp_show_type_route_map;
12534 output_arg = rmap;
12535 }
12536
1e2ce4f1
DS
12537 if (argv_find(argv, argc, "rpki", &idx)) {
12538 sh_type = bgp_show_type_rpki;
12539 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12540 rpki_target_state = RPKI_VALID;
1e2ce4f1 12541 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12542 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12543 }
12544
7d3cae70
DA
12545 /* Display prefixes with matching version numbers */
12546 if (argv_find(argv, argc, "version", &idx)) {
12547 sh_type = bgp_show_type_prefix_version;
2391833e 12548 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12549 }
12550
a70a28a5
DA
12551 /* Display prefixes with matching BGP community alias */
12552 if (argv_find(argv, argc, "alias", &idx)) {
12553 sh_type = bgp_show_type_community_alias;
2391833e 12554 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12555 }
12556
39c3c736
RW
12557 /* prefix-longer */
12558 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12559 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12560 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12561
12562 if (!str2prefix(prefix_str, &p)) {
12563 vty_out(vty, "%% Malformed Prefix\n");
12564 return CMD_WARNING;
12565 }
12566
12567 sh_type = bgp_show_type_prefix_longer;
12568 output_arg = &p;
a70a28a5
DA
12569 }
12570
96f3485c
MK
12571 if (!all) {
12572 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12573 if (community)
12574 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12575 exact_match, afi, safi,
12576 show_flags);
2391833e 12577 else
a70a28a5 12578 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12579 output_arg, show_flags,
a70a28a5 12580 rpki_target_state);
96f3485c 12581 } else {
fa5ac378
DA
12582 struct listnode *node;
12583 struct bgp *abgp;
96f3485c
MK
12584 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12585 * AFI_IP6 */
12586
12587 if (uj)
12588 vty_out(vty, "{\n");
12589
12590 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12591 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12592 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12593 ? AFI_IP
12594 : AFI_IP6;
fa5ac378
DA
12595 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12596 FOREACH_SAFI (safi) {
12597 if (!bgp_afi_safi_peer_exists(abgp, afi,
12598 safi))
12599 continue;
96f3485c 12600
fa5ac378
DA
12601 if (uj) {
12602 if (first)
12603 first = false;
12604 else
12605 vty_out(vty, ",\n");
12606 vty_out(vty, "\"%s\":{\n",
12607 get_afi_safi_str(afi,
12608 safi,
12609 true));
12610 } else
12611 vty_out(vty,
12612 "\nFor address family: %s\n",
12613 get_afi_safi_str(
12614 afi, safi,
12615 false));
12616
12617 if (community)
12618 bgp_show_community(
12619 vty, abgp, community,
12620 exact_match, afi, safi,
12621 show_flags);
96f3485c 12622 else
fa5ac378
DA
12623 bgp_show(vty, abgp, afi, safi,
12624 sh_type, output_arg,
12625 show_flags,
12626 rpki_target_state);
12627 if (uj)
12628 vty_out(vty, "}\n");
12629 }
96f3485c
MK
12630 }
12631 } else {
12632 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12633 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12634 FOREACH_AFI_SAFI (afi, safi) {
12635 if (!bgp_afi_safi_peer_exists(abgp, afi,
12636 safi))
12637 continue;
96f3485c 12638
fa5ac378
DA
12639 if (uj) {
12640 if (first)
12641 first = false;
12642 else
12643 vty_out(vty, ",\n");
12644
12645 vty_out(vty, "\"%s\":{\n",
12646 get_afi_safi_str(afi,
12647 safi,
12648 true));
12649 } else
12650 vty_out(vty,
12651 "\nFor address family: %s\n",
12652 get_afi_safi_str(
12653 afi, safi,
12654 false));
12655
12656 if (community)
12657 bgp_show_community(
12658 vty, abgp, community,
12659 exact_match, afi, safi,
12660 show_flags);
96f3485c 12661 else
fa5ac378
DA
12662 bgp_show(vty, abgp, afi, safi,
12663 sh_type, output_arg,
12664 show_flags,
12665 rpki_target_state);
12666 if (uj)
12667 vty_out(vty, "}\n");
12668 }
96f3485c
MK
12669 }
12670 }
12671 if (uj)
12672 vty_out(vty, "}\n");
12673 }
12674 return CMD_SUCCESS;
a636c635 12675}
47fc97cc 12676
718e3744 12677DEFUN (show_ip_bgp_route,
12678 show_ip_bgp_route_cmd,
8aa22bbb 12679 "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 12680 SHOW_STR
12681 IP_STR
12682 BGP_STR
a636c635 12683 BGP_INSTANCE_HELP_STR
4f280b15 12684 BGP_AFI_HELP_STR
4dd6177e 12685 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12686 "Network in the BGP routing table to display\n"
0c7b1b01 12687 "IPv4 prefix\n"
8c3deaae 12688 "Network in the BGP routing table to display\n"
0c7b1b01 12689 "IPv6 prefix\n"
4092b06c 12690 "Display only the bestpath\n"
b05a1c8b 12691 "Display only multipaths\n"
8aa22bbb
DS
12692 "Display only paths that match the specified rpki state\n"
12693 "A valid path as determined by rpki\n"
12694 "A invalid path as determined by rpki\n"
12695 "A path that has no rpki data\n"
9973d184 12696 JSON_STR)
4092b06c 12697{
d62a17ae 12698 int prefix_check = 0;
ae19d7dd 12699
d62a17ae 12700 afi_t afi = AFI_IP6;
12701 safi_t safi = SAFI_UNICAST;
12702 char *prefix = NULL;
12703 struct bgp *bgp = NULL;
12704 enum bgp_path_type path_type;
9f049418 12705 bool uj = use_json(argc, argv);
b05a1c8b 12706
d62a17ae 12707 int idx = 0;
ae19d7dd 12708
d62a17ae 12709 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12710 &bgp, uj);
d62a17ae 12711 if (!idx)
12712 return CMD_WARNING;
c41247f5 12713
d62a17ae 12714 if (!bgp) {
12715 vty_out(vty,
12716 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12717 return CMD_WARNING;
12718 }
a636c635 12719
d62a17ae 12720 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12721 if (argv_find(argv, argc, "A.B.C.D", &idx)
12722 || argv_find(argv, argc, "X:X::X:X", &idx))
12723 prefix_check = 0;
12724 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12725 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12726 prefix_check = 1;
12727
12728 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12729 && afi != AFI_IP6) {
12730 vty_out(vty,
12731 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12732 return CMD_WARNING;
12733 }
12734 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12735 && afi != AFI_IP) {
12736 vty_out(vty,
12737 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12738 return CMD_WARNING;
12739 }
12740
12741 prefix = argv[idx]->arg;
12742
12743 /* [<bestpath|multipath>] */
12744 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12745 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12746 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12747 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12748 else
360660c6 12749 path_type = BGP_PATH_SHOW_ALL;
a636c635 12750
d62a17ae 12751 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12752 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12753}
12754
8c3deaae
QY
12755DEFUN (show_ip_bgp_regexp,
12756 show_ip_bgp_regexp_cmd,
3e5b31b3 12757 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12758 SHOW_STR
12759 IP_STR
12760 BGP_STR
b00b230a 12761 BGP_INSTANCE_HELP_STR
4f280b15 12762 BGP_AFI_HELP_STR
4dd6177e 12763 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12764 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12765 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12766 JSON_STR)
8c3deaae 12767{
d62a17ae 12768 afi_t afi = AFI_IP6;
12769 safi_t safi = SAFI_UNICAST;
12770 struct bgp *bgp = NULL;
3e5b31b3
DA
12771 bool uj = use_json(argc, argv);
12772 char *regstr = NULL;
8c3deaae 12773
d62a17ae 12774 int idx = 0;
12775 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12776 &bgp, false);
d62a17ae 12777 if (!idx)
12778 return CMD_WARNING;
8c3deaae 12779
d62a17ae 12780 // get index of regex
3e5b31b3
DA
12781 if (argv_find(argv, argc, "REGEX", &idx))
12782 regstr = argv[idx]->arg;
8c3deaae 12783
5f71d11c 12784 assert(regstr);
3e5b31b3
DA
12785 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12786 bgp_show_type_regexp, uj);
8c3deaae
QY
12787}
12788
ae248832 12789DEFPY (show_ip_bgp_instance_all,
a636c635 12790 show_ip_bgp_instance_all_cmd,
ae248832 12791 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12792 SHOW_STR
a636c635 12793 IP_STR
4092b06c 12794 BGP_STR
a636c635 12795 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12796 BGP_AFI_HELP_STR
4dd6177e 12797 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12798 JSON_STR
12799 "Increase table width for longer prefixes\n")
4092b06c 12800{
54d05dea 12801 afi_t afi = AFI_IP6;
d62a17ae 12802 safi_t safi = SAFI_UNICAST;
12803 struct bgp *bgp = NULL;
d62a17ae 12804 int idx = 0;
96c81f66 12805 uint16_t show_flags = 0;
ae19d7dd 12806
96f3485c 12807 if (uj) {
d62a17ae 12808 argc--;
96f3485c
MK
12809 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12810 }
12811
12812 if (wide)
12813 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12814
9f049418
DS
12815 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12816 &bgp, uj);
12817 if (!idx)
12818 return CMD_WARNING;
12819
96f3485c 12820 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12821 return CMD_SUCCESS;
e3e29b32
LB
12822}
12823
a4d82a8a 12824static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12825 afi_t afi, safi_t safi, enum bgp_show_type type,
12826 bool use_json)
718e3744 12827{
d62a17ae 12828 regex_t *regex;
12829 int rc;
96c81f66 12830 uint16_t show_flags = 0;
96f3485c
MK
12831
12832 if (use_json)
12833 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12834
c3900853 12835 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12836 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12837 regstr);
12838 return CMD_WARNING_CONFIG_FAILED;
12839 }
12840
d62a17ae 12841 regex = bgp_regcomp(regstr);
12842 if (!regex) {
12843 vty_out(vty, "Can't compile regexp %s\n", regstr);
12844 return CMD_WARNING;
12845 }
a636c635 12846
1e2ce4f1
DS
12847 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12848 RPKI_NOT_BEING_USED);
d62a17ae 12849 bgp_regex_free(regex);
12850 return rc;
e3e29b32
LB
12851}
12852
7f323236
DW
12853static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12854 const char *comstr, int exact, afi_t afi,
96c81f66 12855 safi_t safi, uint16_t show_flags)
d62a17ae 12856{
12857 struct community *com;
d62a17ae 12858 int ret = 0;
12859
7f323236 12860 com = community_str2com(comstr);
d62a17ae 12861 if (!com) {
7f323236 12862 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12863 return CMD_WARNING;
12864 }
12865
12866 ret = bgp_show(vty, bgp, afi, safi,
12867 (exact ? bgp_show_type_community_exact
12868 : bgp_show_type_community),
1e2ce4f1 12869 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12870 community_free(&com);
46c3ce83 12871
d62a17ae 12872 return ret;
718e3744 12873}
12874
d62a17ae 12875enum bgp_stats {
12876 BGP_STATS_MAXBITLEN = 0,
12877 BGP_STATS_RIB,
12878 BGP_STATS_PREFIXES,
12879 BGP_STATS_TOTPLEN,
12880 BGP_STATS_UNAGGREGATEABLE,
12881 BGP_STATS_MAX_AGGREGATEABLE,
12882 BGP_STATS_AGGREGATES,
12883 BGP_STATS_SPACE,
12884 BGP_STATS_ASPATH_COUNT,
12885 BGP_STATS_ASPATH_MAXHOPS,
12886 BGP_STATS_ASPATH_TOTHOPS,
12887 BGP_STATS_ASPATH_MAXSIZE,
12888 BGP_STATS_ASPATH_TOTSIZE,
12889 BGP_STATS_ASN_HIGHEST,
12890 BGP_STATS_MAX,
a636c635 12891};
2815e61f 12892
9ab0cf58 12893#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12894#define TABLE_STATS_IDX_JSON 1
12895
12896static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12897 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12898 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12899 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12900 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12901 "unaggregateablePrefixes"},
12902 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12903 "maximumAggregateablePrefixes"},
12904 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12905 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12906 [BGP_STATS_SPACE] = {"Address space advertised",
12907 "addressSpaceAdvertised"},
9ab0cf58
PG
12908 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12909 "advertisementsWithPaths"},
12910 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12911 "longestAsPath"},
12912 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12913 "largestAsPath"},
12914 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12915 "averageAsPathLengthHops"},
12916 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12917 "averageAsPathSizeBytes"},
12918 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12919 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12920};
2815e61f 12921
d62a17ae 12922struct bgp_table_stats {
12923 struct bgp_table *table;
12924 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
12925
12926 unsigned long long
12927 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
12928 1];
12929
8d0ab76d 12930 double total_space;
ff7924f6
PJ
12931};
12932
9bcb3eef 12933static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12934 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12935{
9bcb3eef 12936 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12937 struct bgp_path_info *pi;
b54892e0 12938 const struct prefix *rn_p;
d62a17ae 12939
9bcb3eef 12940 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12941 return;
d62a17ae 12942
9bcb3eef 12943 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12944 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12945 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12946
0747643e 12947 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 12948 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12949 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12950 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12951
9bcb3eef 12952 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12953 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12954 /* announced address space */
12955 if (space)
b54892e0 12956 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12957 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12958 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12959
9c14ec72 12960
9bcb3eef 12961 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12962 ts->counts[BGP_STATS_RIB]++;
12963
05864da7
DS
12964 if (CHECK_FLAG(pi->attr->flag,
12965 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12966 ts->counts[BGP_STATS_AGGREGATES]++;
12967
12968 /* as-path stats */
05864da7 12969 if (pi->attr->aspath) {
9c14ec72
RW
12970 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12971 unsigned int size = aspath_size(pi->attr->aspath);
12972 as_t highest = aspath_highest(pi->attr->aspath);
12973
12974 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12975
12976 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12977 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12978
12979 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12980 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12981
12982 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12983 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12984 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12985 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12986 }
12987 }
12988}
12989
cc9f21da 12990static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12991{
9bcb3eef
DS
12992 struct bgp_dest *dest, *ndest;
12993 struct bgp_dest *top;
9c14ec72
RW
12994 struct bgp_table_stats *ts = THREAD_ARG(t);
12995 unsigned int space = 0;
12996
12997 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12998 return;
9c14ec72
RW
12999
13000 switch (ts->table->afi) {
13001 case AFI_IP:
13002 space = IPV4_MAX_BITLEN;
13003 break;
13004 case AFI_IP6:
13005 space = IPV6_MAX_BITLEN;
13006 break;
3ba7b4af
TA
13007 case AFI_L2VPN:
13008 space = EVPN_ROUTE_PREFIXLEN;
13009 break;
9c14ec72 13010 default:
cc9f21da 13011 return;
9c14ec72
RW
13012 }
13013
13014 ts->counts[BGP_STATS_MAXBITLEN] = space;
13015
9bcb3eef 13016 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13017 if (ts->table->safi == SAFI_MPLS_VPN
13018 || ts->table->safi == SAFI_ENCAP
13019 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13020 struct bgp_table *table;
13021
9bcb3eef 13022 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13023 if (!table)
13024 continue;
13025
13026 top = bgp_table_top(table);
9bcb3eef
DS
13027 for (ndest = bgp_table_top(table); ndest;
13028 ndest = bgp_route_next(ndest))
13029 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13030 } else {
9bcb3eef 13031 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13032 }
13033 }
2815e61f 13034}
ff7924f6 13035
71f1613a
DA
13036static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13037 struct json_object *json_array)
13038{
13039 struct listnode *node, *nnode;
13040 struct bgp *bgp;
13041
13042 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13043 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13044}
13045
13046static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13047 safi_t safi, struct json_object *json_array)
2815e61f 13048{
d62a17ae 13049 struct bgp_table_stats ts;
13050 unsigned int i;
893cccd0
PG
13051 int ret = CMD_SUCCESS;
13052 char temp_buf[20];
6c9d22e2 13053 struct json_object *json = NULL;
0747643e
AQ
13054 uint32_t bitlen = 0;
13055 struct json_object *json_bitlen;
6c9d22e2
PG
13056
13057 if (json_array)
13058 json = json_object_new_object();
019386c2 13059
d62a17ae 13060 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13061 char warning_msg[50];
13062
13063 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13064 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13065 safi);
6c9d22e2
PG
13066
13067 if (!json)
893cccd0
PG
13068 vty_out(vty, "%s\n", warning_msg);
13069 else
9ab0cf58 13070 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13071
893cccd0
PG
13072 ret = CMD_WARNING;
13073 goto end_table_stats;
d62a17ae 13074 }
019386c2 13075
893cccd0 13076 if (!json)
5290ceab
DA
13077 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13078 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13079 else
13080 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13081
d62a17ae 13082 /* labeled-unicast routes live in the unicast table */
13083 if (safi == SAFI_LABELED_UNICAST)
13084 safi = SAFI_UNICAST;
019386c2 13085
d62a17ae 13086 memset(&ts, 0, sizeof(ts));
13087 ts.table = bgp->rib[afi][safi];
13088 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13089
d62a17ae 13090 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13091 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13092 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13093 continue;
13094
13095 switch (i) {
d62a17ae 13096 case BGP_STATS_ASPATH_TOTHOPS:
13097 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13098 if (!json) {
9ab0cf58
PG
13099 snprintf(
13100 temp_buf, sizeof(temp_buf), "%12.2f",
13101 ts.counts[i]
13102 ? (float)ts.counts[i]
13103 / (float)ts.counts
13104 [BGP_STATS_ASPATH_COUNT]
13105 : 0);
893cccd0 13106 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13107 table_stats_strs[i]
13108 [TABLE_STATS_IDX_VTY],
893cccd0 13109 temp_buf);
9ab0cf58
PG
13110 } else {
13111 json_object_double_add(
13112 json,
13113 table_stats_strs[i]
13114 [TABLE_STATS_IDX_JSON],
13115 ts.counts[i]
13116 ? (double)ts.counts[i]
13117 / (double)ts.counts
d62a17ae 13118 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13119 : 0);
13120 }
d62a17ae 13121 break;
13122 case BGP_STATS_TOTPLEN:
6c9d22e2 13123 if (!json) {
9ab0cf58
PG
13124 snprintf(
13125 temp_buf, sizeof(temp_buf), "%12.2f",
13126 ts.counts[i]
13127 ? (float)ts.counts[i]
13128 / (float)ts.counts
13129 [BGP_STATS_PREFIXES]
13130 : 0);
893cccd0 13131 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13132 table_stats_strs[i]
13133 [TABLE_STATS_IDX_VTY],
893cccd0 13134 temp_buf);
9ab0cf58
PG
13135 } else {
13136 json_object_double_add(
13137 json,
13138 table_stats_strs[i]
13139 [TABLE_STATS_IDX_JSON],
13140 ts.counts[i]
13141 ? (double)ts.counts[i]
13142 / (double)ts.counts
d62a17ae 13143 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13144 : 0);
13145 }
d62a17ae 13146 break;
13147 case BGP_STATS_SPACE:
6c9d22e2
PG
13148 if (!json) {
13149 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13150 ts.total_space);
893cccd0 13151 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13152 table_stats_strs[i]
13153 [TABLE_STATS_IDX_VTY],
893cccd0 13154 temp_buf);
9ab0cf58
PG
13155 } else {
13156 json_object_double_add(
13157 json,
13158 table_stats_strs[i]
13159 [TABLE_STATS_IDX_JSON],
13160 (double)ts.total_space);
13161 }
8d0ab76d 13162 if (afi == AFI_IP6) {
6c9d22e2
PG
13163 if (!json) {
13164 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13165 "%12g",
13166 ts.total_space
13167 * pow(2.0, -128 + 32));
6c9d22e2
PG
13168 vty_out(vty, "%30s: %s\n",
13169 "/32 equivalent %s\n",
13170 temp_buf);
9ab0cf58
PG
13171 } else {
13172 json_object_double_add(
13173 json, "/32equivalent",
13174 (double)(ts.total_space
13175 * pow(2.0,
13176 -128 + 32)));
13177 }
6c9d22e2
PG
13178 if (!json) {
13179 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13180 "%12g",
13181 ts.total_space
13182 * pow(2.0, -128 + 48));
6c9d22e2
PG
13183 vty_out(vty, "%30s: %s\n",
13184 "/48 equivalent %s\n",
13185 temp_buf);
9ab0cf58
PG
13186 } else {
13187 json_object_double_add(
13188 json, "/48equivalent",
13189 (double)(ts.total_space
13190 * pow(2.0,
13191 -128 + 48)));
13192 }
8d0ab76d 13193 } else {
6c9d22e2
PG
13194 if (!json) {
13195 snprintf(temp_buf, sizeof(temp_buf),
13196 "%12.2f",
9ab0cf58
PG
13197 ts.total_space * 100.
13198 * pow(2.0, -32));
6c9d22e2 13199 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13200 "% announced ", temp_buf);
13201 } else {
13202 json_object_double_add(
13203 json, "%announced",
13204 (double)(ts.total_space * 100.
13205 * pow(2.0, -32)));
13206 }
6c9d22e2
PG
13207 if (!json) {
13208 snprintf(temp_buf, sizeof(temp_buf),
13209 "%12.2f",
9ab0cf58
PG
13210 ts.total_space
13211 * pow(2.0, -32 + 8));
6c9d22e2
PG
13212 vty_out(vty, "%30s: %s\n",
13213 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13214 } else {
13215 json_object_double_add(
13216 json, "/8equivalent",
13217 (double)(ts.total_space
13218 * pow(2.0, -32 + 8)));
13219 }
6c9d22e2
PG
13220 if (!json) {
13221 snprintf(temp_buf, sizeof(temp_buf),
13222 "%12.2f",
9ab0cf58
PG
13223 ts.total_space
13224 * pow(2.0, -32 + 24));
6c9d22e2 13225 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13226 "/24 equivalent ", temp_buf);
13227 } else {
13228 json_object_double_add(
13229 json, "/24equivalent",
13230 (double)(ts.total_space
13231 * pow(2.0, -32 + 24)));
13232 }
8d0ab76d 13233 }
d62a17ae 13234 break;
13235 default:
6c9d22e2
PG
13236 if (!json) {
13237 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13238 ts.counts[i]);
893cccd0 13239 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13240 table_stats_strs[i]
13241 [TABLE_STATS_IDX_VTY],
13242 temp_buf);
13243 } else {
13244 json_object_int_add(
13245 json,
13246 table_stats_strs[i]
13247 [TABLE_STATS_IDX_JSON],
13248 ts.counts[i]);
13249 }
d62a17ae 13250 }
893cccd0
PG
13251 if (!json)
13252 vty_out(vty, "\n");
d62a17ae 13253 }
0747643e
AQ
13254
13255 switch (afi) {
13256 case AFI_IP:
13257 bitlen = IPV4_MAX_BITLEN;
13258 break;
13259 case AFI_IP6:
13260 bitlen = IPV6_MAX_BITLEN;
13261 break;
13262 case AFI_L2VPN:
13263 bitlen = EVPN_ROUTE_PREFIXLEN;
13264 break;
13265 default:
13266 break;
13267 }
13268
13269 if (json) {
13270 json_bitlen = json_object_new_array();
13271
13272 for (i = 0; i <= bitlen; i++) {
13273 struct json_object *ind_bit = json_object_new_object();
13274
13275 if (!ts.prefix_len_count[i])
13276 continue;
13277
13278 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13279 json_object_int_add(ind_bit, temp_buf,
13280 ts.prefix_len_count[i]);
13281 json_object_array_add(json_bitlen, ind_bit);
13282 }
13283 json_object_object_add(json, "prefixLength", json_bitlen);
13284 }
13285
9ab0cf58 13286end_table_stats:
6c9d22e2
PG
13287 if (json)
13288 json_object_array_add(json_array, json);
893cccd0 13289 return ret;
d62a17ae 13290}
13291
71f1613a
DA
13292static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13293 safi_t safi, struct json_object *json_array)
13294{
13295 if (!bgp) {
13296 bgp_table_stats_all(vty, afi, safi, json_array);
13297 return CMD_SUCCESS;
13298 }
13299
13300 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13301}
13302
d62a17ae 13303enum bgp_pcounts {
13304 PCOUNT_ADJ_IN = 0,
13305 PCOUNT_DAMPED,
13306 PCOUNT_REMOVED,
13307 PCOUNT_HISTORY,
13308 PCOUNT_STALE,
13309 PCOUNT_VALID,
13310 PCOUNT_ALL,
13311 PCOUNT_COUNTED,
7e3d9632 13312 PCOUNT_BPATH_SELECTED,
d62a17ae 13313 PCOUNT_PFCNT, /* the figure we display to users */
13314 PCOUNT_MAX,
a636c635 13315};
718e3744 13316
2b64873d 13317static const char *const pcount_strs[] = {
9d303b37
DL
13318 [PCOUNT_ADJ_IN] = "Adj-in",
13319 [PCOUNT_DAMPED] = "Damped",
13320 [PCOUNT_REMOVED] = "Removed",
13321 [PCOUNT_HISTORY] = "History",
13322 [PCOUNT_STALE] = "Stale",
13323 [PCOUNT_VALID] = "Valid",
13324 [PCOUNT_ALL] = "All RIB",
13325 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13326 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13327 [PCOUNT_PFCNT] = "Useable",
13328 [PCOUNT_MAX] = NULL,
a636c635 13329};
718e3744 13330
d62a17ae 13331struct peer_pcounts {
13332 unsigned int count[PCOUNT_MAX];
13333 const struct peer *peer;
13334 const struct bgp_table *table;
54317cba 13335 safi_t safi;
a636c635 13336};
47fc97cc 13337
9bcb3eef 13338static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13339{
54317cba
JW
13340 const struct bgp_adj_in *ain;
13341 const struct bgp_path_info *pi;
d62a17ae 13342 const struct peer *peer = pc->peer;
13343
54317cba
JW
13344 for (ain = rn->adj_in; ain; ain = ain->next)
13345 if (ain->peer == peer)
13346 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13347
9bcb3eef 13348 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13349
54317cba
JW
13350 if (pi->peer != peer)
13351 continue;
d62a17ae 13352
54317cba 13353 pc->count[PCOUNT_ALL]++;
d62a17ae 13354
54317cba
JW
13355 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13356 pc->count[PCOUNT_DAMPED]++;
13357 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13358 pc->count[PCOUNT_HISTORY]++;
13359 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13360 pc->count[PCOUNT_REMOVED]++;
13361 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13362 pc->count[PCOUNT_STALE]++;
13363 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13364 pc->count[PCOUNT_VALID]++;
13365 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13366 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13367 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13368 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13369
13370 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13371 pc->count[PCOUNT_COUNTED]++;
13372 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13373 flog_err(
13374 EC_LIB_DEVELOPMENT,
13375 "Attempting to count but flags say it is unusable");
13376 } else {
40381db7 13377 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13378 flog_err(
13379 EC_LIB_DEVELOPMENT,
13380 "Not counted but flags say we should");
d62a17ae 13381 }
13382 }
54317cba
JW
13383}
13384
cc9f21da 13385static void bgp_peer_count_walker(struct thread *t)
54317cba 13386{
9bcb3eef 13387 struct bgp_dest *rn, *rm;
54317cba
JW
13388 const struct bgp_table *table;
13389 struct peer_pcounts *pc = THREAD_ARG(t);
13390
13391 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13392 || pc->safi == SAFI_EVPN) {
13393 /* Special handling for 2-level routing tables. */
13394 for (rn = bgp_table_top(pc->table); rn;
13395 rn = bgp_route_next(rn)) {
9bcb3eef 13396 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13397 if (table != NULL)
13398 for (rm = bgp_table_top(table); rm;
13399 rm = bgp_route_next(rm))
13400 bgp_peer_count_proc(rm, pc);
13401 }
13402 } else
13403 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13404 bgp_peer_count_proc(rn, pc);
718e3744 13405}
13406
d62a17ae 13407static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13408 safi_t safi, bool use_json)
856ca177 13409{
d62a17ae 13410 struct peer_pcounts pcounts = {.peer = peer};
13411 unsigned int i;
13412 json_object *json = NULL;
13413 json_object *json_loop = NULL;
856ca177 13414
d62a17ae 13415 if (use_json) {
13416 json = json_object_new_object();
13417 json_loop = json_object_new_object();
13418 }
718e3744 13419
d62a17ae 13420 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13421 || !peer->bgp->rib[afi][safi]) {
13422 if (use_json) {
13423 json_object_string_add(
13424 json, "warning",
13425 "No such neighbor or address family");
13426 vty_out(vty, "%s\n", json_object_to_json_string(json));
13427 json_object_free(json);
d5f20468 13428 json_object_free(json_loop);
d62a17ae 13429 } else
13430 vty_out(vty, "%% No such neighbor or address family\n");
13431
13432 return CMD_WARNING;
13433 }
2a71e9ce 13434
d62a17ae 13435 memset(&pcounts, 0, sizeof(pcounts));
13436 pcounts.peer = peer;
13437 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13438 pcounts.safi = safi;
d62a17ae 13439
13440 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13441 * stats for the thread-walk (i.e. ensure this can't be blamed on
13442 * on just vty_read()).
13443 */
d62a17ae 13444 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13445
13446 if (use_json) {
13447 json_object_string_add(json, "prefixCountsFor", peer->host);
13448 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13449 get_afi_safi_str(afi, safi, true));
d62a17ae 13450 json_object_int_add(json, "pfxCounter",
13451 peer->pcount[afi][safi]);
13452
13453 for (i = 0; i < PCOUNT_MAX; i++)
13454 json_object_int_add(json_loop, pcount_strs[i],
13455 pcounts.count[i]);
13456
13457 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13458
13459 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13460 json_object_string_add(json, "pfxctDriftFor",
13461 peer->host);
13462 json_object_string_add(
13463 json, "recommended",
13464 "Please report this bug, with the above command output");
13465 }
75eeda93 13466 vty_json(vty, json);
d62a17ae 13467 } else {
13468
13469 if (peer->hostname
892fedb6 13470 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13471 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13472 peer->hostname, peer->host,
5cb5f4d0 13473 get_afi_safi_str(afi, safi, false));
d62a17ae 13474 } else {
13475 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13476 get_afi_safi_str(afi, safi, false));
d62a17ae 13477 }
13478
6cde4b45 13479 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13480 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13481
13482 for (i = 0; i < PCOUNT_MAX; i++)
13483 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13484 pcounts.count[i]);
13485
13486 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13487 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13488 vty_out(vty,
13489 "Please report this bug, with the above command output\n");
13490 }
13491 }
13492
13493 return CMD_SUCCESS;
718e3744 13494}
13495
a636c635
DW
13496DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13497 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13498 "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 13499 SHOW_STR
13500 IP_STR
13501 BGP_STR
8386ac43 13502 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13503 BGP_AFI_HELP_STR
13504 BGP_SAFI_HELP_STR
0b16f239
DS
13505 "Detailed information on TCP and BGP neighbor connections\n"
13506 "Neighbor to display information about\n"
13507 "Neighbor to display information about\n"
91d37724 13508 "Neighbor on BGP configured interface\n"
a636c635 13509 "Display detailed prefix count information\n"
9973d184 13510 JSON_STR)
0b16f239 13511{
d62a17ae 13512 afi_t afi = AFI_IP6;
13513 safi_t safi = SAFI_UNICAST;
13514 struct peer *peer;
13515 int idx = 0;
13516 struct bgp *bgp = NULL;
9f049418
DS
13517 bool uj = use_json(argc, argv);
13518
13519 if (uj)
13520 argc--;
856ca177 13521
d62a17ae 13522 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13523 &bgp, uj);
d62a17ae 13524 if (!idx)
13525 return CMD_WARNING;
0b16f239 13526
d62a17ae 13527 argv_find(argv, argc, "neighbors", &idx);
13528 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13529 if (!peer)
13530 return CMD_WARNING;
bb46e94f 13531
29c8d9da 13532 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13533}
0b16f239 13534
d6902373
PG
13535#ifdef KEEP_OLD_VPN_COMMANDS
13536DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13537 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13538 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13539 SHOW_STR
13540 IP_STR
13541 BGP_STR
d6902373 13542 BGP_VPNVX_HELP_STR
91d37724 13543 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13544 "Detailed information on TCP and BGP neighbor connections\n"
13545 "Neighbor to display information about\n"
13546 "Neighbor to display information about\n"
91d37724 13547 "Neighbor on BGP configured interface\n"
a636c635 13548 "Display detailed prefix count information\n"
9973d184 13549 JSON_STR)
a636c635 13550{
d62a17ae 13551 int idx_peer = 6;
13552 struct peer *peer;
9f049418 13553 bool uj = use_json(argc, argv);
a636c635 13554
d62a17ae 13555 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13556 if (!peer)
13557 return CMD_WARNING;
13558
13559 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13560}
13561
d6902373
PG
13562DEFUN (show_ip_bgp_vpn_all_route_prefix,
13563 show_ip_bgp_vpn_all_route_prefix_cmd,
13564 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13565 SHOW_STR
13566 IP_STR
13567 BGP_STR
d6902373 13568 BGP_VPNVX_HELP_STR
91d37724
QY
13569 "Display information about all VPNv4 NLRIs\n"
13570 "Network in the BGP routing table to display\n"
3a2d747c 13571 "Network in the BGP routing table to display\n"
9973d184 13572 JSON_STR)
91d37724 13573{
d62a17ae 13574 int idx = 0;
13575 char *network = NULL;
13576 struct bgp *bgp = bgp_get_default();
13577 if (!bgp) {
13578 vty_out(vty, "Can't find default instance\n");
13579 return CMD_WARNING;
13580 }
87e34b58 13581
d62a17ae 13582 if (argv_find(argv, argc, "A.B.C.D", &idx))
13583 network = argv[idx]->arg;
13584 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13585 network = argv[idx]->arg;
13586 else {
13587 vty_out(vty, "Unable to figure out Network\n");
13588 return CMD_WARNING;
13589 }
87e34b58 13590
d62a17ae 13591 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13592 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13593 use_json(argc, argv));
91d37724 13594}
d6902373 13595#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13596
44c69747
LK
13597DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13598 show_bgp_l2vpn_evpn_route_prefix_cmd,
13599 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13600 SHOW_STR
4c63a661
PG
13601 BGP_STR
13602 L2VPN_HELP_STR
13603 EVPN_HELP_STR
44c69747
LK
13604 "Network in the BGP routing table to display\n"
13605 "Network in the BGP routing table to display\n"
4c63a661
PG
13606 "Network in the BGP routing table to display\n"
13607 "Network in the BGP routing table to display\n"
13608 JSON_STR)
13609{
d62a17ae 13610 int idx = 0;
13611 char *network = NULL;
44c69747 13612 int prefix_check = 0;
a636c635 13613
44c69747
LK
13614 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13615 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13616 network = argv[idx]->arg;
44c69747 13617 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13618 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13619 network = argv[idx]->arg;
44c69747
LK
13620 prefix_check = 1;
13621 } else {
d62a17ae 13622 vty_out(vty, "Unable to figure out Network\n");
13623 return CMD_WARNING;
13624 }
44c69747
LK
13625 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13626 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13627 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13628}
13629
114fc229 13630static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13631 struct bgp_table *table, int *header1,
13632 int *header2, json_object *json,
13633 json_object *json_scode,
13634 json_object *json_ocode, bool wide)
13635{
13636 uint64_t version = table ? table->version : 0;
13637
13638 if (*header1) {
13639 if (json) {
13640 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13641 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13642 "%pI4", &peer->bgp->router_id);
2f9bc755 13643 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13644 peer->bgp->default_local_pref);
13645 json_object_int_add(json, "localAS",
13646 peer->change_local_as
13647 ? peer->change_local_as
13648 : peer->local_as);
2f9bc755
DS
13649 json_object_object_add(json, "bgpStatusCodes",
13650 json_scode);
13651 json_object_object_add(json, "bgpOriginCodes",
13652 json_ocode);
13653 } else {
13654 vty_out(vty,
23d0a753
DA
13655 "BGP table version is %" PRIu64
13656 ", local router ID is %pI4, vrf id ",
114fc229
DA
13657 version, &peer->bgp->router_id);
13658 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13659 vty_out(vty, "%s", VRFID_NONE_STR);
13660 else
114fc229 13661 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13662 vty_out(vty, "\n");
13663 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13664 peer->bgp->default_local_pref);
13665 vty_out(vty, "local AS %u\n",
13666 peer->change_local_as ? peer->change_local_as
13667 : peer->local_as);
2f9bc755
DS
13668 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13669 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13670 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13671 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13672 }
13673 *header1 = 0;
13674 }
13675 if (*header2) {
13676 if (!json)
13677 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13678 : BGP_SHOW_HEADER));
13679 *header2 = 0;
13680 }
13681}
13682
d9478df0
TA
13683static void
13684show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13685 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13686 const char *rmap_name, json_object *json, json_object *json_ar,
13687 json_object *json_scode, json_object *json_ocode,
96c81f66 13688 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13689 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13690{
d62a17ae 13691 struct bgp_adj_in *ain;
13692 struct bgp_adj_out *adj;
9bcb3eef 13693 struct bgp_dest *dest;
d62a17ae 13694 struct bgp *bgp;
d62a17ae 13695 struct attr attr;
13696 int ret;
13697 struct update_subgroup *subgrp;
d62a17ae 13698 struct peer_af *paf;
f99def61 13699 bool route_filtered;
96f3485c
MK
13700 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13701 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13702 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13703 || (safi == SAFI_EVPN))
13704 ? true
13705 : false;
a636c635 13706
d62a17ae 13707 bgp = peer->bgp;
a636c635 13708
d62a17ae 13709 subgrp = peer_subgroup(peer, afi, safi);
13710
6392aaa6 13711 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13712 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13713 if (use_json) {
13714 json_object_int_add(json, "bgpTableVersion",
13715 table->version);
c949c771
DA
13716 json_object_string_addf(json, "bgpLocalRouterId",
13717 "%pI4", &bgp->router_id);
01eced22
AD
13718 json_object_int_add(json, "defaultLocPrf",
13719 bgp->default_local_pref);
114fc229
DA
13720 json_object_int_add(json, "localAS",
13721 peer->change_local_as
13722 ? peer->change_local_as
13723 : peer->local_as);
d62a17ae 13724 json_object_object_add(json, "bgpStatusCodes",
13725 json_scode);
13726 json_object_object_add(json, "bgpOriginCodes",
13727 json_ocode);
07d0c4ed
DA
13728 json_object_string_add(
13729 json, "bgpOriginatingDefaultNetwork",
13730 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13731 } else {
23d0a753
DA
13732 vty_out(vty,
13733 "BGP table version is %" PRIu64
13734 ", local router ID is %pI4, vrf id ",
13735 table->version, &bgp->router_id);
9df8b37c
PZ
13736 if (bgp->vrf_id == VRF_UNKNOWN)
13737 vty_out(vty, "%s", VRFID_NONE_STR);
13738 else
13739 vty_out(vty, "%u", bgp->vrf_id);
13740 vty_out(vty, "\n");
01eced22
AD
13741 vty_out(vty, "Default local pref %u, ",
13742 bgp->default_local_pref);
114fc229
DA
13743 vty_out(vty, "local AS %u\n",
13744 peer->change_local_as ? peer->change_local_as
13745 : peer->local_as);
d62a17ae 13746 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13747 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13748 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13749 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13750
07d0c4ed
DA
13751 vty_out(vty, "Originating default network %s\n\n",
13752 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13753 }
d9478df0 13754 *header1 = 0;
d62a17ae 13755 }
a636c635 13756
9bcb3eef 13757 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13758 if (type == bgp_show_adj_route_received
13759 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13760 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13761 if (ain->peer != peer)
ea47320b 13762 continue;
6392aaa6 13763
114fc229 13764 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13765 header2, json, json_scode,
13766 json_ocode, wide);
13767
13768 if ((safi == SAFI_MPLS_VPN)
13769 || (safi == SAFI_ENCAP)
13770 || (safi == SAFI_EVPN)) {
13771 if (use_json)
13772 json_object_string_add(
13773 json_ar, "rd", rd_str);
13774 else if (show_rd && rd_str) {
13775 vty_out(vty,
13776 "Route Distinguisher: %s\n",
13777 rd_str);
13778 show_rd = false;
13779 }
13780 }
6392aaa6 13781
6f4f49b2 13782 attr = *ain->attr;
f99def61
AD
13783 route_filtered = false;
13784
13785 /* Filter prefix using distribute list,
13786 * filter list or prefix list
13787 */
b54892e0 13788 const struct prefix *rn_p =
9bcb3eef 13789 bgp_dest_get_prefix(dest);
b54892e0
DS
13790 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13791 safi))
13792 == FILTER_DENY)
f99def61
AD
13793 route_filtered = true;
13794
13795 /* Filter prefix using route-map */
b54892e0
DS
13796 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13797 safi, rmap_name, NULL,
13798 0, NULL);
6392aaa6 13799
13c8e163
AD
13800 if (type == bgp_show_adj_route_filtered &&
13801 !route_filtered && ret != RMAP_DENY) {
d498917e 13802 bgp_attr_flush(&attr);
6392aaa6 13803 continue;
d62a17ae 13804 }
6392aaa6 13805
d9478df0
TA
13806 if (type == bgp_show_adj_route_received
13807 && (route_filtered || ret == RMAP_DENY))
13808 (*filtered_count)++;
6392aaa6 13809
7d3cae70 13810 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13811 use_json, json_ar, wide);
d498917e 13812 bgp_attr_flush(&attr);
d9478df0 13813 (*output_count)++;
d62a17ae 13814 }
6392aaa6 13815 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13816 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13817 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13818 if (paf->peer != peer || !adj->attr)
924c3f6a 13819 continue;
d62a17ae 13820
114fc229 13821 show_adj_route_header(vty, peer, table,
d9478df0
TA
13822 header1, header2,
13823 json, json_scode,
13824 json_ocode, wide);
d62a17ae 13825
b54892e0 13826 const struct prefix *rn_p =
9bcb3eef 13827 bgp_dest_get_prefix(dest);
b54892e0 13828
6f4f49b2 13829 attr = *adj->attr;
b755861b 13830 ret = bgp_output_modifier(
b54892e0 13831 peer, rn_p, &attr, afi, safi,
b755861b 13832 rmap_name);
f46d8e1e 13833
b755861b 13834 if (ret != RMAP_DENY) {
d9478df0
TA
13835 if ((safi == SAFI_MPLS_VPN)
13836 || (safi == SAFI_ENCAP)
13837 || (safi == SAFI_EVPN)) {
13838 if (use_json)
13839 json_object_string_add(
13840 json_ar,
13841 "rd",
13842 rd_str);
13843 else if (show_rd
13844 && rd_str) {
13845 vty_out(vty,
13846 "Route Distinguisher: %s\n",
13847 rd_str);
13848 show_rd = false;
13849 }
13850 }
b54892e0 13851 route_vty_out_tmp(
7d3cae70
DA
13852 vty, dest, rn_p, &attr,
13853 safi, use_json, json_ar,
ae248832 13854 wide);
d9478df0 13855 (*output_count)++;
b755861b 13856 } else {
d9478df0 13857 (*filtered_count)++;
a2addae8 13858 }
b755861b 13859
d498917e 13860 bgp_attr_flush(&attr);
924c3f6a 13861 }
f20ce998
DS
13862 } else if (type == bgp_show_adj_route_bestpath) {
13863 struct bgp_path_info *pi;
13864
114fc229
DA
13865 show_adj_route_header(vty, peer, table, header1,
13866 header2, json, json_scode,
13867 json_ocode, wide);
f20ce998
DS
13868
13869 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13870 pi = pi->next) {
13871 if (pi->peer != peer)
13872 continue;
13873
13874 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13875 continue;
13876
7d3cae70 13877 route_vty_out_tmp(vty, dest,
f20ce998
DS
13878 bgp_dest_get_prefix(dest),
13879 pi->attr, safi, use_json,
13880 json_ar, wide);
d9478df0 13881 (*output_count)++;
f20ce998 13882 }
d62a17ae 13883 }
13884 }
a636c635 13885}
2a71e9ce 13886
d62a17ae 13887static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13888 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13889 const char *rmap_name, uint16_t show_flags)
0b16f239 13890{
d9478df0
TA
13891 struct bgp *bgp;
13892 struct bgp_table *table;
d62a17ae 13893 json_object *json = NULL;
d9478df0
TA
13894 json_object *json_scode = NULL;
13895 json_object *json_ocode = NULL;
13896 json_object *json_ar = NULL;
96f3485c 13897 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13898
d9478df0
TA
13899 /* Init BGP headers here so they're only displayed once
13900 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13901 */
13902 int header1 = 1;
13903 int header2 = 1;
13904
13905 /*
13906 * Initialize variables for each RD
13907 * All prefixes under an RD is aggregated within "json_routes"
13908 */
13909 char rd_str[BUFSIZ] = {0};
13910 json_object *json_routes = NULL;
13911
13912
13913 /* For 2-tier tables, prefix counts need to be
13914 * maintained across multiple runs of show_adj_route()
13915 */
13916 unsigned long output_count_per_rd;
13917 unsigned long filtered_count_per_rd;
13918 unsigned long output_count = 0;
13919 unsigned long filtered_count = 0;
13920
13921 if (use_json) {
d62a17ae 13922 json = json_object_new_object();
d9478df0
TA
13923 json_ar = json_object_new_object();
13924 json_scode = json_object_new_object();
13925 json_ocode = json_object_new_object();
13926
13927 json_object_string_add(json_scode, "suppressed", "s");
13928 json_object_string_add(json_scode, "damped", "d");
13929 json_object_string_add(json_scode, "history", "h");
13930 json_object_string_add(json_scode, "valid", "*");
13931 json_object_string_add(json_scode, "best", ">");
13932 json_object_string_add(json_scode, "multipath", "=");
13933 json_object_string_add(json_scode, "internal", "i");
13934 json_object_string_add(json_scode, "ribFailure", "r");
13935 json_object_string_add(json_scode, "stale", "S");
13936 json_object_string_add(json_scode, "removed", "R");
13937
13938 json_object_string_add(json_ocode, "igp", "i");
13939 json_object_string_add(json_ocode, "egp", "e");
13940 json_object_string_add(json_ocode, "incomplete", "?");
13941 }
0b16f239 13942
d62a17ae 13943 if (!peer || !peer->afc[afi][safi]) {
13944 if (use_json) {
13945 json_object_string_add(
13946 json, "warning",
13947 "No such neighbor or address family");
13948 vty_out(vty, "%s\n", json_object_to_json_string(json));
13949 json_object_free(json);
690c3134
MW
13950 json_object_free(json_ar);
13951 json_object_free(json_scode);
13952 json_object_free(json_ocode);
d62a17ae 13953 } else
13954 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13955
d62a17ae 13956 return CMD_WARNING;
13957 }
13958
6392aaa6
PM
13959 if ((type == bgp_show_adj_route_received
13960 || type == bgp_show_adj_route_filtered)
d62a17ae 13961 && !CHECK_FLAG(peer->af_flags[afi][safi],
13962 PEER_FLAG_SOFT_RECONFIG)) {
13963 if (use_json) {
13964 json_object_string_add(
13965 json, "warning",
13966 "Inbound soft reconfiguration not enabled");
13967 vty_out(vty, "%s\n", json_object_to_json_string(json));
13968 json_object_free(json);
690c3134
MW
13969 json_object_free(json_ar);
13970 json_object_free(json_scode);
13971 json_object_free(json_ocode);
d62a17ae 13972 } else
13973 vty_out(vty,
13974 "%% Inbound soft reconfiguration not enabled\n");
13975
13976 return CMD_WARNING;
13977 }
0b16f239 13978
d9478df0
TA
13979 bgp = peer->bgp;
13980
13981 /* labeled-unicast routes live in the unicast table */
13982 if (safi == SAFI_LABELED_UNICAST)
13983 table = bgp->rib[afi][SAFI_UNICAST];
13984 else
13985 table = bgp->rib[afi][safi];
13986
13987 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13988 || (safi == SAFI_EVPN)) {
13989
13990 struct bgp_dest *dest;
13991
13992 for (dest = bgp_table_top(table); dest;
13993 dest = bgp_route_next(dest)) {
13994 table = bgp_dest_get_bgp_table_info(dest);
13995 if (!table)
13996 continue;
13997
13998 output_count_per_rd = 0;
13999 filtered_count_per_rd = 0;
14000
14001 if (use_json)
14002 json_routes = json_object_new_object();
14003
14004 const struct prefix_rd *prd;
14005 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14006 dest);
14007
14008 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14009
14010 show_adj_route(vty, peer, table, afi, safi, type,
14011 rmap_name, json, json_routes, json_scode,
14012 json_ocode, show_flags, &header1,
14013 &header2, rd_str, &output_count_per_rd,
14014 &filtered_count_per_rd);
14015
14016 /* Don't include an empty RD in the output! */
14017 if (json_routes && (output_count_per_rd > 0))
14018 json_object_object_add(json_ar, rd_str,
14019 json_routes);
14020
14021 output_count += output_count_per_rd;
14022 filtered_count += filtered_count_per_rd;
14023 }
14024 } else
14025 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14026 json, json_ar, json_scode, json_ocode,
14027 show_flags, &header1, &header2, rd_str,
14028 &output_count, &filtered_count);
14029
14030 if (use_json) {
c1984955
TA
14031 if (type == bgp_show_adj_route_advertised)
14032 json_object_object_add(json, "advertisedRoutes",
14033 json_ar);
14034 else
14035 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14036 json_object_int_add(json, "totalPrefixCounter", output_count);
14037 json_object_int_add(json, "filteredPrefixCounter",
14038 filtered_count);
14039
690c3134
MW
14040 /*
14041 * These fields only give up ownership to `json` when `header1`
14042 * is used (set to zero). See code in `show_adj_route` and
14043 * `show_adj_route_header`.
14044 */
14045 if (header1 == 1) {
d9478df0
TA
14046 json_object_free(json_scode);
14047 json_object_free(json_ocode);
14048 }
14049
75eeda93 14050 vty_json(vty, json);
d9478df0
TA
14051 } else if (output_count > 0) {
14052 if (filtered_count > 0)
14053 vty_out(vty,
14054 "\nTotal number of prefixes %ld (%ld filtered)\n",
14055 output_count, filtered_count);
14056 else
14057 vty_out(vty, "\nTotal number of prefixes %ld\n",
14058 output_count);
14059 }
0b16f239 14060
d62a17ae 14061 return CMD_SUCCESS;
a636c635 14062}
50ef26d4 14063
f20ce998
DS
14064DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14065 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14066 "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]",
14067 SHOW_STR
14068 IP_STR
14069 BGP_STR
14070 BGP_INSTANCE_HELP_STR
14071 BGP_AFI_HELP_STR
14072 BGP_SAFI_WITH_LABEL_HELP_STR
14073 "Detailed information on TCP and BGP neighbor connections\n"
14074 "Neighbor to display information about\n"
14075 "Neighbor to display information about\n"
14076 "Neighbor on BGP configured interface\n"
14077 "Display the routes selected by best path\n"
14078 JSON_STR
14079 "Increase table width for longer prefixes\n")
14080{
14081 afi_t afi = AFI_IP6;
14082 safi_t safi = SAFI_UNICAST;
14083 char *rmap_name = NULL;
14084 char *peerstr = NULL;
14085 struct bgp *bgp = NULL;
14086 struct peer *peer;
14087 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14088 int idx = 0;
96c81f66 14089 uint16_t show_flags = 0;
96f3485c
MK
14090
14091 if (uj)
14092 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14093
14094 if (wide)
14095 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14096
14097 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14098 &bgp, uj);
14099
14100 if (!idx)
14101 return CMD_WARNING;
14102
14103 argv_find(argv, argc, "neighbors", &idx);
14104 peerstr = argv[++idx]->arg;
14105
14106 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14107 if (!peer)
14108 return CMD_WARNING;
14109
96f3485c
MK
14110 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14111 show_flags);
f20ce998
DS
14112}
14113
ae248832 14114DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14115 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14116 "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 14117 SHOW_STR
14118 IP_STR
14119 BGP_STR
a636c635 14120 BGP_INSTANCE_HELP_STR
7395a2c9 14121 BGP_AFI_HELP_STR
4dd6177e 14122 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14123 "Display the entries for all address families\n"
718e3744 14124 "Detailed information on TCP and BGP neighbor connections\n"
14125 "Neighbor to display information about\n"
14126 "Neighbor to display information about\n"
91d37724 14127 "Neighbor on BGP configured interface\n"
a636c635 14128 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14129 "Display the received routes from neighbor\n"
14130 "Display the filtered routes received from neighbor\n"
a636c635
DW
14131 "Route-map to modify the attributes\n"
14132 "Name of the route map\n"
ae248832
MK
14133 JSON_STR
14134 "Increase table width for longer prefixes\n")
718e3744 14135{
d62a17ae 14136 afi_t afi = AFI_IP6;
14137 safi_t safi = SAFI_UNICAST;
d62a17ae 14138 char *peerstr = NULL;
d62a17ae 14139 struct bgp *bgp = NULL;
14140 struct peer *peer;
6392aaa6 14141 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14142 int idx = 0;
96f3485c 14143 bool first = true;
96c81f66 14144 uint16_t show_flags = 0;
75ce3b14
DA
14145 struct listnode *node;
14146 struct bgp *abgp;
6392aaa6 14147
96f3485c 14148 if (uj) {
d62a17ae 14149 argc--;
96f3485c
MK
14150 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14151 }
14152
14153 if (all) {
14154 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14155 if (argv_find(argv, argc, "ipv4", &idx))
14156 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14157
14158 if (argv_find(argv, argc, "ipv6", &idx))
14159 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14160 }
14161
14162 if (wide)
14163 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14164
9f049418
DS
14165 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14166 &bgp, uj);
14167 if (!idx)
14168 return CMD_WARNING;
14169
d62a17ae 14170 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14171 argv_find(argv, argc, "neighbors", &idx);
14172 peerstr = argv[++idx]->arg;
8c3deaae 14173
d62a17ae 14174 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14175 if (!peer)
14176 return CMD_WARNING;
856ca177 14177
d62a17ae 14178 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14179 type = bgp_show_adj_route_advertised;
14180 else if (argv_find(argv, argc, "received-routes", &idx))
14181 type = bgp_show_adj_route_received;
14182 else if (argv_find(argv, argc, "filtered-routes", &idx))
14183 type = bgp_show_adj_route_filtered;
14184
96f3485c 14185 if (!all)
70dd370f 14186 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14187 show_flags);
14188 if (uj)
14189 vty_out(vty, "{\n");
14190
14191 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14192 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14193 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14194 : AFI_IP6;
75ce3b14
DA
14195 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14196 FOREACH_SAFI (safi) {
14197 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14198 continue;
96f3485c 14199
75ce3b14
DA
14200 if (uj) {
14201 if (first)
14202 first = false;
14203 else
14204 vty_out(vty, ",\n");
14205 vty_out(vty, "\"%s\":",
14206 get_afi_safi_str(afi, safi,
14207 true));
14208 } else
14209 vty_out(vty,
14210 "\nFor address family: %s\n",
14211 get_afi_safi_str(afi, safi,
14212 false));
96f3485c 14213
75ce3b14 14214 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14215 route_map, show_flags);
75ce3b14 14216 }
96f3485c
MK
14217 }
14218 } else {
75ce3b14
DA
14219 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14220 FOREACH_AFI_SAFI (afi, safi) {
14221 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14222 continue;
96f3485c 14223
75ce3b14
DA
14224 if (uj) {
14225 if (first)
14226 first = false;
14227 else
14228 vty_out(vty, ",\n");
14229 vty_out(vty, "\"%s\":",
14230 get_afi_safi_str(afi, safi,
14231 true));
14232 } else
14233 vty_out(vty,
14234 "\nFor address family: %s\n",
14235 get_afi_safi_str(afi, safi,
14236 false));
96f3485c 14237
75ce3b14 14238 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14239 route_map, show_flags);
75ce3b14 14240 }
96f3485c
MK
14241 }
14242 }
14243 if (uj)
14244 vty_out(vty, "}\n");
14245
14246 return CMD_SUCCESS;
95cbbd2a
ML
14247}
14248
718e3744 14249DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14250 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14251 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14252 SHOW_STR
14253 IP_STR
14254 BGP_STR
d3120452 14255 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14256 BGP_AF_STR
14257 BGP_AF_STR
14258 BGP_AF_MODIFIER_STR
718e3744 14259 "Detailed information on TCP and BGP neighbor connections\n"
14260 "Neighbor to display information about\n"
14261 "Neighbor to display information about\n"
91d37724 14262 "Neighbor on BGP configured interface\n"
718e3744 14263 "Display information received from a BGP neighbor\n"
856ca177 14264 "Display the prefixlist filter\n"
9973d184 14265 JSON_STR)
718e3744 14266{
d62a17ae 14267 afi_t afi = AFI_IP6;
14268 safi_t safi = SAFI_UNICAST;
14269 char *peerstr = NULL;
d62a17ae 14270 char name[BUFSIZ];
d62a17ae 14271 struct peer *peer;
d3120452 14272 int count;
d62a17ae 14273 int idx = 0;
d3120452
IR
14274 struct bgp *bgp = NULL;
14275 bool uj = use_json(argc, argv);
14276
14277 if (uj)
14278 argc--;
14279
14280 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14281 &bgp, uj);
14282 if (!idx)
14283 return CMD_WARNING;
d62a17ae 14284
d62a17ae 14285 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14286 argv_find(argv, argc, "neighbors", &idx);
14287 peerstr = argv[++idx]->arg;
14288
d3120452
IR
14289 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14290 if (!peer)
14291 return CMD_WARNING;
718e3744 14292
4ced1a2c 14293 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14294 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14295 if (count) {
14296 if (!uj)
14297 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14298 get_afi_safi_str(afi, safi, false));
d62a17ae 14299 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14300 } else {
14301 if (uj)
14302 vty_out(vty, "{}\n");
14303 else
14304 vty_out(vty, "No functional output\n");
14305 }
718e3744 14306
d62a17ae 14307 return CMD_SUCCESS;
14308}
14309
14310static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14311 afi_t afi, safi_t safi,
9f049418 14312 enum bgp_show_type type, bool use_json)
d62a17ae 14313{
96c81f66 14314 uint16_t show_flags = 0;
96f3485c
MK
14315
14316 if (use_json)
14317 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14318
d62a17ae 14319 if (!peer || !peer->afc[afi][safi]) {
14320 if (use_json) {
14321 json_object *json_no = NULL;
14322 json_no = json_object_new_object();
14323 json_object_string_add(
14324 json_no, "warning",
14325 "No such neighbor or address family");
14326 vty_out(vty, "%s\n",
14327 json_object_to_json_string(json_no));
14328 json_object_free(json_no);
14329 } else
14330 vty_out(vty, "%% No such neighbor or address family\n");
14331 return CMD_WARNING;
14332 }
47fc97cc 14333
7daf25a3
TA
14334 /* labeled-unicast routes live in the unicast table */
14335 if (safi == SAFI_LABELED_UNICAST)
14336 safi = SAFI_UNICAST;
14337
1e2ce4f1
DS
14338 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14339 RPKI_NOT_BEING_USED);
718e3744 14340}
14341
dba3c1d3
PG
14342DEFUN (show_ip_bgp_flowspec_routes_detailed,
14343 show_ip_bgp_flowspec_routes_detailed_cmd,
14344 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14345 SHOW_STR
14346 IP_STR
14347 BGP_STR
14348 BGP_INSTANCE_HELP_STR
14349 BGP_AFI_HELP_STR
14350 "SAFI Flowspec\n"
14351 "Detailed information on flowspec entries\n"
14352 JSON_STR)
14353{
458c1475 14354 afi_t afi = AFI_IP6;
dba3c1d3
PG
14355 safi_t safi = SAFI_UNICAST;
14356 struct bgp *bgp = NULL;
14357 int idx = 0;
9f049418 14358 bool uj = use_json(argc, argv);
5be6fa9b 14359 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14360
96f3485c 14361 if (uj) {
9f049418 14362 argc--;
96f3485c
MK
14363 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14364 }
dba3c1d3
PG
14365
14366 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14367 &bgp, uj);
dba3c1d3
PG
14368 if (!idx)
14369 return CMD_WARNING;
14370
96f3485c 14371 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14372 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14373}
14374
718e3744 14375DEFUN (show_ip_bgp_neighbor_routes,
14376 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14377 "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 14378 SHOW_STR
14379 IP_STR
14380 BGP_STR
8386ac43 14381 BGP_INSTANCE_HELP_STR
4f280b15 14382 BGP_AFI_HELP_STR
4dd6177e 14383 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14384 "Detailed information on TCP and BGP neighbor connections\n"
14385 "Neighbor to display information about\n"
14386 "Neighbor to display information about\n"
91d37724 14387 "Neighbor on BGP configured interface\n"
2525cf39 14388 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14389 "Display the dampened routes received from neighbor\n"
14390 "Display routes learned from neighbor\n"
9973d184 14391 JSON_STR)
718e3744 14392{
d62a17ae 14393 char *peerstr = NULL;
14394 struct bgp *bgp = NULL;
14395 afi_t afi = AFI_IP6;
14396 safi_t safi = SAFI_UNICAST;
14397 struct peer *peer;
14398 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14399 int idx = 0;
9f049418
DS
14400 bool uj = use_json(argc, argv);
14401
14402 if (uj)
14403 argc--;
bb46e94f 14404
d62a17ae 14405 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14406 &bgp, uj);
d62a17ae 14407 if (!idx)
14408 return CMD_WARNING;
c493f2d8 14409
d62a17ae 14410 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14411 argv_find(argv, argc, "neighbors", &idx);
14412 peerstr = argv[++idx]->arg;
8c3deaae 14413
d62a17ae 14414 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14415 if (!peer)
d62a17ae 14416 return CMD_WARNING;
bb46e94f 14417
d62a17ae 14418 if (argv_find(argv, argc, "flap-statistics", &idx))
14419 sh_type = bgp_show_type_flap_neighbor;
14420 else if (argv_find(argv, argc, "dampened-routes", &idx))
14421 sh_type = bgp_show_type_damp_neighbor;
14422 else if (argv_find(argv, argc, "routes", &idx))
14423 sh_type = bgp_show_type_neighbor;
2525cf39 14424
d62a17ae 14425 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14426}
6b0655a2 14427
734b349e 14428struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14429
d62a17ae 14430struct bgp_distance {
14431 /* Distance value for the IP source prefix. */
d7c0a89a 14432 uint8_t distance;
718e3744 14433
d62a17ae 14434 /* Name of the access-list to be matched. */
14435 char *access_list;
718e3744 14436};
14437
4f280b15
LB
14438DEFUN (show_bgp_afi_vpn_rd_route,
14439 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14440 "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
14441 SHOW_STR
14442 BGP_STR
14443 BGP_AFI_HELP_STR
00e6edb9 14444 BGP_AF_MODIFIER_STR
4f280b15
LB
14445 "Display information for a route distinguisher\n"
14446 "Route Distinguisher\n"
a111dd97 14447 "All Route Distinguishers\n"
7395a2c9
DS
14448 "Network in the BGP routing table to display\n"
14449 "Network in the BGP routing table to display\n"
14450 JSON_STR)
4f280b15 14451{
d62a17ae 14452 int ret;
14453 struct prefix_rd prd;
14454 afi_t afi = AFI_MAX;
14455 int idx = 0;
4f280b15 14456
ff6566f3
DS
14457 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14458 vty_out(vty, "%% Malformed Address Family\n");
14459 return CMD_WARNING;
14460 }
14461
a111dd97
TA
14462 if (!strcmp(argv[5]->arg, "all"))
14463 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14464 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14465 RPKI_NOT_BEING_USED,
14466 use_json(argc, argv));
14467
d62a17ae 14468 ret = str2prefix_rd(argv[5]->arg, &prd);
14469 if (!ret) {
14470 vty_out(vty, "%% Malformed Route Distinguisher\n");
14471 return CMD_WARNING;
14472 }
ff6566f3 14473
d62a17ae 14474 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14475 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14476 use_json(argc, argv));
4f280b15
LB
14477}
14478
d62a17ae 14479static struct bgp_distance *bgp_distance_new(void)
718e3744 14480{
d62a17ae 14481 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14482}
14483
d62a17ae 14484static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14485{
d62a17ae 14486 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14487}
14488
585f1adc
IR
14489static int bgp_distance_set(struct vty *vty, const char *distance_str,
14490 const char *ip_str, const char *access_list_str)
718e3744 14491{
d62a17ae 14492 int ret;
585f1adc
IR
14493 afi_t afi;
14494 safi_t safi;
d62a17ae 14495 struct prefix p;
585f1adc 14496 uint8_t distance;
9bcb3eef 14497 struct bgp_dest *dest;
d62a17ae 14498 struct bgp_distance *bdistance;
718e3744 14499
585f1adc
IR
14500 afi = bgp_node_afi(vty);
14501 safi = bgp_node_safi(vty);
14502
d62a17ae 14503 ret = str2prefix(ip_str, &p);
14504 if (ret == 0) {
585f1adc 14505 vty_out(vty, "Malformed prefix\n");
d62a17ae 14506 return CMD_WARNING_CONFIG_FAILED;
14507 }
718e3744 14508
585f1adc
IR
14509 distance = atoi(distance_str);
14510
d62a17ae 14511 /* Get BGP distance node. */
9bcb3eef
DS
14512 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14513 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14514 if (bdistance)
9bcb3eef 14515 bgp_dest_unlock_node(dest);
ca2e160d 14516 else {
d62a17ae 14517 bdistance = bgp_distance_new();
9bcb3eef 14518 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14519 }
718e3744 14520
d62a17ae 14521 /* Set distance value. */
14522 bdistance->distance = distance;
718e3744 14523
d62a17ae 14524 /* Reset access-list configuration. */
e1b36e13 14525 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14526 if (access_list_str)
14527 bdistance->access_list =
14528 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14529
d62a17ae 14530 return CMD_SUCCESS;
718e3744 14531}
14532
585f1adc
IR
14533static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14534 const char *ip_str, const char *access_list_str)
718e3744 14535{
d62a17ae 14536 int ret;
585f1adc
IR
14537 afi_t afi;
14538 safi_t safi;
d62a17ae 14539 struct prefix p;
585f1adc 14540 int distance;
9bcb3eef 14541 struct bgp_dest *dest;
d62a17ae 14542 struct bgp_distance *bdistance;
718e3744 14543
585f1adc
IR
14544 afi = bgp_node_afi(vty);
14545 safi = bgp_node_safi(vty);
14546
d62a17ae 14547 ret = str2prefix(ip_str, &p);
14548 if (ret == 0) {
585f1adc 14549 vty_out(vty, "Malformed prefix\n");
d62a17ae 14550 return CMD_WARNING_CONFIG_FAILED;
14551 }
718e3744 14552
9bcb3eef
DS
14553 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14554 if (!dest) {
585f1adc 14555 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14556 return CMD_WARNING_CONFIG_FAILED;
14557 }
718e3744 14558
9bcb3eef 14559 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14560 distance = atoi(distance_str);
1f9a9fff 14561
d62a17ae 14562 if (bdistance->distance != distance) {
585f1adc 14563 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14564 bgp_dest_unlock_node(dest);
d62a17ae 14565 return CMD_WARNING_CONFIG_FAILED;
14566 }
718e3744 14567
0a22ddfb 14568 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14569 bgp_distance_free(bdistance);
718e3744 14570
9bcb3eef
DS
14571 bgp_dest_set_bgp_path_info(dest, NULL);
14572 bgp_dest_unlock_node(dest);
14573 bgp_dest_unlock_node(dest);
718e3744 14574
d62a17ae 14575 return CMD_SUCCESS;
718e3744 14576}
14577
718e3744 14578/* Apply BGP information to distance method. */
b8685f9b 14579uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14580 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14581{
9bcb3eef 14582 struct bgp_dest *dest;
801bb996 14583 struct prefix q = {0};
d62a17ae 14584 struct peer *peer;
14585 struct bgp_distance *bdistance;
14586 struct access_list *alist;
14587 struct bgp_static *bgp_static;
14588
14589 if (!bgp)
14590 return 0;
14591
40381db7 14592 peer = pinfo->peer;
d62a17ae 14593
7b7d48e5
DS
14594 if (pinfo->attr->distance)
14595 return pinfo->attr->distance;
14596
801bb996
CS
14597 /* Check source address.
14598 * Note: for aggregate route, peer can have unspec af type.
14599 */
14600 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14601 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14602 return 0;
14603
9bcb3eef
DS
14604 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14605 if (dest) {
14606 bdistance = bgp_dest_get_bgp_distance_info(dest);
14607 bgp_dest_unlock_node(dest);
d62a17ae 14608
14609 if (bdistance->access_list) {
14610 alist = access_list_lookup(afi, bdistance->access_list);
14611 if (alist
14612 && access_list_apply(alist, p) == FILTER_PERMIT)
14613 return bdistance->distance;
14614 } else
14615 return bdistance->distance;
718e3744 14616 }
718e3744 14617
d62a17ae 14618 /* Backdoor check. */
9bcb3eef
DS
14619 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14620 if (dest) {
14621 bgp_static = bgp_dest_get_bgp_static_info(dest);
14622 bgp_dest_unlock_node(dest);
718e3744 14623
d62a17ae 14624 if (bgp_static->backdoor) {
14625 if (bgp->distance_local[afi][safi])
14626 return bgp->distance_local[afi][safi];
14627 else
14628 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14629 }
718e3744 14630 }
718e3744 14631
d62a17ae 14632 if (peer->sort == BGP_PEER_EBGP) {
14633 if (bgp->distance_ebgp[afi][safi])
14634 return bgp->distance_ebgp[afi][safi];
14635 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14636 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14637 if (bgp->distance_ibgp[afi][safi])
14638 return bgp->distance_ibgp[afi][safi];
14639 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14640 } else {
14641 if (bgp->distance_local[afi][safi])
14642 return bgp->distance_local[afi][safi];
14643 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14644 }
718e3744 14645}
14646
a612fb77
DA
14647/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14648 * we should tell ZEBRA update the routes for a specific
14649 * AFI/SAFI to reflect changes in RIB.
14650 */
585f1adc
IR
14651static void bgp_announce_routes_distance_update(struct bgp *bgp,
14652 afi_t update_afi,
14653 safi_t update_safi)
a612fb77
DA
14654{
14655 afi_t afi;
14656 safi_t safi;
14657
14658 FOREACH_AFI_SAFI (afi, safi) {
14659 if (!bgp_fibupd_safi(safi))
14660 continue;
14661
8b54bc30
DA
14662 if (afi != update_afi && safi != update_safi)
14663 continue;
14664
14665 if (BGP_DEBUG(zebra, ZEBRA))
14666 zlog_debug(
14667 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14668 __func__, afi, safi);
14669 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14670 }
14671}
14672
585f1adc
IR
14673DEFUN (bgp_distance,
14674 bgp_distance_cmd,
14675 "distance bgp (1-255) (1-255) (1-255)",
14676 "Define an administrative distance\n"
14677 "BGP distance\n"
14678 "Distance for routes external to the AS\n"
14679 "Distance for routes internal to the AS\n"
14680 "Distance for local routes\n")
718e3744 14681{
585f1adc 14682 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14683 int idx_number = 2;
14684 int idx_number_2 = 3;
14685 int idx_number_3 = 4;
585f1adc
IR
14686 int distance_ebgp = atoi(argv[idx_number]->arg);
14687 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14688 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14689 afi_t afi;
14690 safi_t safi;
718e3744 14691
d62a17ae 14692 afi = bgp_node_afi(vty);
14693 safi = bgp_node_safi(vty);
718e3744 14694
585f1adc
IR
14695 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14696 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14697 || bgp->distance_local[afi][safi] != distance_local) {
14698 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14699 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14700 bgp->distance_local[afi][safi] = distance_local;
14701 bgp_announce_routes_distance_update(bgp, afi, safi);
14702 }
14703 return CMD_SUCCESS;
14704}
37a87b8f 14705
585f1adc
IR
14706DEFUN (no_bgp_distance,
14707 no_bgp_distance_cmd,
14708 "no distance bgp [(1-255) (1-255) (1-255)]",
14709 NO_STR
14710 "Define an administrative distance\n"
14711 "BGP distance\n"
14712 "Distance for routes external to the AS\n"
14713 "Distance for routes internal to the AS\n"
14714 "Distance for local routes\n")
718e3744 14715{
585f1adc 14716 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14717 afi_t afi;
14718 safi_t safi;
37a87b8f
CS
14719
14720 afi = bgp_node_afi(vty);
14721 safi = bgp_node_safi(vty);
14722
585f1adc
IR
14723 if (bgp->distance_ebgp[afi][safi] != 0
14724 || bgp->distance_ibgp[afi][safi] != 0
14725 || bgp->distance_local[afi][safi] != 0) {
14726 bgp->distance_ebgp[afi][safi] = 0;
14727 bgp->distance_ibgp[afi][safi] = 0;
14728 bgp->distance_local[afi][safi] = 0;
14729 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14730 }
585f1adc
IR
14731 return CMD_SUCCESS;
14732}
37a87b8f 14733
37a87b8f 14734
585f1adc
IR
14735DEFUN (bgp_distance_source,
14736 bgp_distance_source_cmd,
14737 "distance (1-255) A.B.C.D/M",
14738 "Define an administrative distance\n"
14739 "Administrative distance\n"
14740 "IP source prefix\n")
14741{
14742 int idx_number = 1;
14743 int idx_ipv4_prefixlen = 2;
14744 bgp_distance_set(vty, argv[idx_number]->arg,
14745 argv[idx_ipv4_prefixlen]->arg, NULL);
14746 return CMD_SUCCESS;
734b349e
MZ
14747}
14748
585f1adc
IR
14749DEFUN (no_bgp_distance_source,
14750 no_bgp_distance_source_cmd,
14751 "no distance (1-255) A.B.C.D/M",
14752 NO_STR
14753 "Define an administrative distance\n"
14754 "Administrative distance\n"
14755 "IP source prefix\n")
37a87b8f 14756{
585f1adc
IR
14757 int idx_number = 2;
14758 int idx_ipv4_prefixlen = 3;
14759 bgp_distance_unset(vty, argv[idx_number]->arg,
14760 argv[idx_ipv4_prefixlen]->arg, NULL);
14761 return CMD_SUCCESS;
37a87b8f
CS
14762}
14763
585f1adc
IR
14764DEFUN (bgp_distance_source_access_list,
14765 bgp_distance_source_access_list_cmd,
14766 "distance (1-255) A.B.C.D/M WORD",
14767 "Define an administrative distance\n"
14768 "Administrative distance\n"
14769 "IP source prefix\n"
14770 "Access list name\n")
37a87b8f 14771{
585f1adc
IR
14772 int idx_number = 1;
14773 int idx_ipv4_prefixlen = 2;
14774 int idx_word = 3;
14775 bgp_distance_set(vty, argv[idx_number]->arg,
14776 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14777 return CMD_SUCCESS;
14778}
718e3744 14779
585f1adc
IR
14780DEFUN (no_bgp_distance_source_access_list,
14781 no_bgp_distance_source_access_list_cmd,
14782 "no distance (1-255) A.B.C.D/M WORD",
14783 NO_STR
14784 "Define an administrative distance\n"
14785 "Administrative distance\n"
14786 "IP source prefix\n"
14787 "Access list name\n")
14788{
14789 int idx_number = 2;
14790 int idx_ipv4_prefixlen = 3;
14791 int idx_word = 4;
14792 bgp_distance_unset(vty, argv[idx_number]->arg,
14793 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14794 return CMD_SUCCESS;
14795}
37a87b8f 14796
585f1adc
IR
14797DEFUN (ipv6_bgp_distance_source,
14798 ipv6_bgp_distance_source_cmd,
14799 "distance (1-255) X:X::X:X/M",
14800 "Define an administrative distance\n"
14801 "Administrative distance\n"
14802 "IP source prefix\n")
14803{
14804 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14805 return CMD_SUCCESS;
14806}
7ebe9748 14807
585f1adc
IR
14808DEFUN (no_ipv6_bgp_distance_source,
14809 no_ipv6_bgp_distance_source_cmd,
14810 "no distance (1-255) X:X::X:X/M",
14811 NO_STR
14812 "Define an administrative distance\n"
14813 "Administrative distance\n"
14814 "IP source prefix\n")
14815{
14816 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14817 return CMD_SUCCESS;
14818}
37a87b8f 14819
585f1adc
IR
14820DEFUN (ipv6_bgp_distance_source_access_list,
14821 ipv6_bgp_distance_source_access_list_cmd,
14822 "distance (1-255) X:X::X:X/M WORD",
14823 "Define an administrative distance\n"
14824 "Administrative distance\n"
14825 "IP source prefix\n"
14826 "Access list name\n")
14827{
14828 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14829 return CMD_SUCCESS;
718e3744 14830}
14831
585f1adc
IR
14832DEFUN (no_ipv6_bgp_distance_source_access_list,
14833 no_ipv6_bgp_distance_source_access_list_cmd,
14834 "no distance (1-255) X:X::X:X/M WORD",
14835 NO_STR
14836 "Define an administrative distance\n"
14837 "Administrative distance\n"
14838 "IP source prefix\n"
14839 "Access list name\n")
718e3744 14840{
585f1adc
IR
14841 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14842 return CMD_SUCCESS;
14843}
37a87b8f 14844
585f1adc
IR
14845DEFUN (bgp_damp_set,
14846 bgp_damp_set_cmd,
a30fec23 14847 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14848 "BGP Specific commands\n"
14849 "Enable route-flap dampening\n"
14850 "Half-life time for the penalty\n"
14851 "Value to start reusing a route\n"
14852 "Value to start suppressing a route\n"
14853 "Maximum duration to suppress a stable route\n")
14854{
14855 VTY_DECLVAR_CONTEXT(bgp, bgp);
14856 int idx_half_life = 2;
14857 int idx_reuse = 3;
14858 int idx_suppress = 4;
14859 int idx_max_suppress = 5;
37a87b8f
CS
14860 int half = DEFAULT_HALF_LIFE * 60;
14861 int reuse = DEFAULT_REUSE;
14862 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14863 int max = 4 * half;
14864
14865 if (argc == 6) {
14866 half = atoi(argv[idx_half_life]->arg) * 60;
14867 reuse = atoi(argv[idx_reuse]->arg);
14868 suppress = atoi(argv[idx_suppress]->arg);
14869 max = atoi(argv[idx_max_suppress]->arg) * 60;
14870 } else if (argc == 3) {
14871 half = atoi(argv[idx_half_life]->arg) * 60;
14872 max = 4 * half;
14873 }
14874
14875 /*
14876 * These can't be 0 but our SA doesn't understand the
14877 * way our cli is constructed
14878 */
14879 assert(reuse);
14880 assert(half);
14881 if (suppress < reuse) {
14882 vty_out(vty,
14883 "Suppress value cannot be less than reuse value \n");
14884 return 0;
14885 }
14886
14887 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14888 reuse, suppress, max);
14889}
14890
14891DEFUN (bgp_damp_unset,
14892 bgp_damp_unset_cmd,
a30fec23 14893 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14894 NO_STR
14895 "BGP Specific commands\n"
14896 "Enable route-flap dampening\n"
14897 "Half-life time for the penalty\n"
14898 "Value to start reusing a route\n"
14899 "Value to start suppressing a route\n"
14900 "Maximum duration to suppress a stable route\n")
14901{
14902 VTY_DECLVAR_CONTEXT(bgp, bgp);
14903 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14904}
14905
718e3744 14906/* Display specified route of BGP table. */
d62a17ae 14907static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14908 const char *ip_str, afi_t afi, safi_t safi,
14909 struct prefix_rd *prd, int prefix_check)
14910{
14911 int ret;
14912 struct prefix match;
9bcb3eef
DS
14913 struct bgp_dest *dest;
14914 struct bgp_dest *rm;
40381db7
DS
14915 struct bgp_path_info *pi;
14916 struct bgp_path_info *pi_temp;
d62a17ae 14917 struct bgp *bgp;
14918 struct bgp_table *table;
14919
14920 /* BGP structure lookup. */
14921 if (view_name) {
14922 bgp = bgp_lookup_by_name(view_name);
14923 if (bgp == NULL) {
14924 vty_out(vty, "%% Can't find BGP instance %s\n",
14925 view_name);
14926 return CMD_WARNING;
14927 }
14928 } else {
14929 bgp = bgp_get_default();
14930 if (bgp == NULL) {
14931 vty_out(vty, "%% No BGP process is configured\n");
14932 return CMD_WARNING;
14933 }
718e3744 14934 }
718e3744 14935
d62a17ae 14936 /* Check IP address argument. */
14937 ret = str2prefix(ip_str, &match);
14938 if (!ret) {
14939 vty_out(vty, "%% address is malformed\n");
14940 return CMD_WARNING;
14941 }
718e3744 14942
d62a17ae 14943 match.family = afi2family(afi);
14944
14945 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14946 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14947 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14948 dest = bgp_route_next(dest)) {
14949 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14950
9bcb3eef 14951 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14952 continue;
9bcb3eef 14953 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14954 if (!table)
ea47320b 14955 continue;
4953391b
DA
14956 rm = bgp_node_match(table, &match);
14957 if (rm == NULL)
ea47320b 14958 continue;
d62a17ae 14959
9bcb3eef 14960 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14961
ea47320b 14962 if (!prefix_check
b54892e0 14963 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14964 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14965 while (pi) {
14966 if (pi->extra && pi->extra->damp_info) {
14967 pi_temp = pi->next;
ea47320b 14968 bgp_damp_info_free(
19971c9a 14969 pi->extra->damp_info,
5c8846f6 14970 1, afi, safi);
40381db7 14971 pi = pi_temp;
ea47320b 14972 } else
40381db7 14973 pi = pi->next;
d62a17ae 14974 }
ea47320b
DL
14975 }
14976
9bcb3eef 14977 bgp_dest_unlock_node(rm);
d62a17ae 14978 }
14979 } else {
4953391b
DA
14980 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14981 if (dest != NULL) {
9bcb3eef 14982 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14983
d62a17ae 14984 if (!prefix_check
9bcb3eef
DS
14985 || dest_p->prefixlen == match.prefixlen) {
14986 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14987 while (pi) {
14988 if (pi->extra && pi->extra->damp_info) {
14989 pi_temp = pi->next;
d62a17ae 14990 bgp_damp_info_free(
19971c9a 14991 pi->extra->damp_info,
5c8846f6 14992 1, afi, safi);
40381db7 14993 pi = pi_temp;
d62a17ae 14994 } else
40381db7 14995 pi = pi->next;
d62a17ae 14996 }
14997 }
14998
9bcb3eef 14999 bgp_dest_unlock_node(dest);
d62a17ae 15000 }
15001 }
718e3744 15002
d62a17ae 15003 return CMD_SUCCESS;
718e3744 15004}
15005
15006DEFUN (clear_ip_bgp_dampening,
15007 clear_ip_bgp_dampening_cmd,
15008 "clear ip bgp dampening",
15009 CLEAR_STR
15010 IP_STR
15011 BGP_STR
15012 "Clear route flap dampening information\n")
15013{
b4f7f45b 15014 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15015 return CMD_SUCCESS;
718e3744 15016}
15017
15018DEFUN (clear_ip_bgp_dampening_prefix,
15019 clear_ip_bgp_dampening_prefix_cmd,
15020 "clear ip bgp dampening A.B.C.D/M",
15021 CLEAR_STR
15022 IP_STR
15023 BGP_STR
15024 "Clear route flap dampening information\n"
0c7b1b01 15025 "IPv4 prefix\n")
718e3744 15026{
d62a17ae 15027 int idx_ipv4_prefixlen = 4;
15028 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15029 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15030}
15031
15032DEFUN (clear_ip_bgp_dampening_address,
15033 clear_ip_bgp_dampening_address_cmd,
15034 "clear ip bgp dampening A.B.C.D",
15035 CLEAR_STR
15036 IP_STR
15037 BGP_STR
15038 "Clear route flap dampening information\n"
15039 "Network to clear damping information\n")
15040{
d62a17ae 15041 int idx_ipv4 = 4;
15042 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15043 SAFI_UNICAST, NULL, 0);
718e3744 15044}
15045
15046DEFUN (clear_ip_bgp_dampening_address_mask,
15047 clear_ip_bgp_dampening_address_mask_cmd,
15048 "clear ip bgp dampening A.B.C.D A.B.C.D",
15049 CLEAR_STR
15050 IP_STR
15051 BGP_STR
15052 "Clear route flap dampening information\n"
15053 "Network to clear damping information\n"
15054 "Network mask\n")
15055{
d62a17ae 15056 int idx_ipv4 = 4;
15057 int idx_ipv4_2 = 5;
15058 int ret;
15059 char prefix_str[BUFSIZ];
718e3744 15060
d62a17ae 15061 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15062 prefix_str, sizeof(prefix_str));
d62a17ae 15063 if (!ret) {
15064 vty_out(vty, "%% Inconsistent address and mask\n");
15065 return CMD_WARNING;
15066 }
718e3744 15067
d62a17ae 15068 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15069 NULL, 0);
718e3744 15070}
6b0655a2 15071
e3b78da8 15072static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15073{
15074 struct vty *vty = arg;
e3b78da8 15075 struct peer *peer = bucket->data;
825d9834 15076
47e12884 15077 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15078}
15079
2a0e69ae
DS
15080DEFUN (show_bgp_listeners,
15081 show_bgp_listeners_cmd,
15082 "show bgp listeners",
15083 SHOW_STR
15084 BGP_STR
15085 "Display Listen Sockets and who created them\n")
15086{
15087 bgp_dump_listener_info(vty);
15088
15089 return CMD_SUCCESS;
15090}
15091
825d9834
DS
15092DEFUN (show_bgp_peerhash,
15093 show_bgp_peerhash_cmd,
15094 "show bgp peerhash",
15095 SHOW_STR
15096 BGP_STR
15097 "Display information about the BGP peerhash\n")
15098{
15099 struct list *instances = bm->bgp;
15100 struct listnode *node;
15101 struct bgp *bgp;
15102
15103 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15104 vty_out(vty, "BGP: %s\n", bgp->name);
15105 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15106 vty);
15107 }
15108
15109 return CMD_SUCCESS;
15110}
15111
587ff0fd 15112/* also used for encap safi */
2b791107
DL
15113static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15114 afi_t afi, safi_t safi)
d62a17ae 15115{
9bcb3eef
DS
15116 struct bgp_dest *pdest;
15117 struct bgp_dest *dest;
d62a17ae 15118 struct bgp_table *table;
b54892e0
DS
15119 const struct prefix *p;
15120 const struct prefix_rd *prd;
d62a17ae 15121 struct bgp_static *bgp_static;
15122 mpls_label_t label;
d62a17ae 15123 char rdbuf[RD_ADDRSTRLEN];
15124
15125 /* Network configuration. */
9bcb3eef
DS
15126 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15127 pdest = bgp_route_next(pdest)) {
15128 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15129 if (!table)
ea47320b 15130 continue;
d62a17ae 15131
9bcb3eef
DS
15132 for (dest = bgp_table_top(table); dest;
15133 dest = bgp_route_next(dest)) {
15134 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15135 if (bgp_static == NULL)
ea47320b 15136 continue;
d62a17ae 15137
9bcb3eef
DS
15138 p = bgp_dest_get_prefix(dest);
15139 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15140 pdest);
d62a17ae 15141
ea47320b 15142 /* "network" configuration display. */
06b9f471 15143 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
15144 label = decode_label(&bgp_static->label);
15145
8228a9a7 15146 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
15147 if (safi == SAFI_MPLS_VPN)
15148 vty_out(vty, " label %u", label);
15149
15150 if (bgp_static->rmap.name)
15151 vty_out(vty, " route-map %s",
15152 bgp_static->rmap.name);
e2a86ad9
DS
15153
15154 if (bgp_static->backdoor)
15155 vty_out(vty, " backdoor");
15156
ea47320b
DL
15157 vty_out(vty, "\n");
15158 }
15159 }
d62a17ae 15160}
15161
2b791107
DL
15162static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15163 afi_t afi, safi_t safi)
d62a17ae 15164{
9bcb3eef
DS
15165 struct bgp_dest *pdest;
15166 struct bgp_dest *dest;
d62a17ae 15167 struct bgp_table *table;
b54892e0
DS
15168 const struct prefix *p;
15169 const struct prefix_rd *prd;
d62a17ae 15170 struct bgp_static *bgp_static;
ff44f570 15171 char buf[PREFIX_STRLEN * 2];
d62a17ae 15172 char buf2[SU_ADDRSTRLEN];
15173 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15174 char esi_buf[ESI_STR_LEN];
d62a17ae 15175
15176 /* Network configuration. */
9bcb3eef
DS
15177 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15178 pdest = bgp_route_next(pdest)) {
15179 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15180 if (!table)
ea47320b 15181 continue;
d62a17ae 15182
9bcb3eef
DS
15183 for (dest = bgp_table_top(table); dest;
15184 dest = bgp_route_next(dest)) {
15185 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15186 if (bgp_static == NULL)
ea47320b 15187 continue;
d62a17ae 15188
ea47320b 15189 char *macrouter = NULL;
d62a17ae 15190
ea47320b
DL
15191 if (bgp_static->router_mac)
15192 macrouter = prefix_mac2str(
15193 bgp_static->router_mac, NULL, 0);
15194 if (bgp_static->eth_s_id)
0a50c248
AK
15195 esi_to_str(bgp_static->eth_s_id,
15196 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15197 p = bgp_dest_get_prefix(dest);
15198 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15199
ea47320b 15200 /* "network" configuration display. */
06b9f471 15201 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15202 if (p->u.prefix_evpn.route_type == 5) {
15203 char local_buf[PREFIX_STRLEN];
3714a385 15204 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15205 struct prefix_evpn *)p)
15206 ? AF_INET
15207 : AF_INET6;
3714a385 15208 inet_ntop(family,
15209 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15210 local_buf, PREFIX_STRLEN);
772270f3
QY
15211 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15212 p->u.prefix_evpn.prefix_addr
15213 .ip_prefix_length);
197cb530
PG
15214 } else {
15215 prefix2str(p, buf, sizeof(buf));
15216 }
ea47320b 15217
a4d82a8a
PZ
15218 if (bgp_static->gatewayIp.family == AF_INET
15219 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15220 inet_ntop(bgp_static->gatewayIp.family,
15221 &bgp_static->gatewayIp.u.prefix, buf2,
15222 sizeof(buf2));
ea47320b 15223 vty_out(vty,
7bcc8dac 15224 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15225 buf, rdbuf,
15226 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15227 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15228 macrouter);
15229
0a22ddfb 15230 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15231 }
15232 }
3da6fcd5
PG
15233}
15234
718e3744 15235/* Configuration of static route announcement and aggregate
15236 information. */
2b791107
DL
15237void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15238 safi_t safi)
d62a17ae 15239{
9bcb3eef 15240 struct bgp_dest *dest;
b54892e0 15241 const struct prefix *p;
d62a17ae 15242 struct bgp_static *bgp_static;
15243 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15244
2b791107
DL
15245 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15246 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15247 return;
15248 }
d62a17ae 15249
2b791107
DL
15250 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15251 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15252 return;
15253 }
d62a17ae 15254
15255 /* Network configuration. */
9bcb3eef
DS
15256 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15257 dest = bgp_route_next(dest)) {
15258 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15259 if (bgp_static == NULL)
ea47320b 15260 continue;
d62a17ae 15261
9bcb3eef 15262 p = bgp_dest_get_prefix(dest);
d62a17ae 15263
8228a9a7 15264 vty_out(vty, " network %pFX", p);
d62a17ae 15265
ea47320b
DL
15266 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15267 vty_out(vty, " label-index %u",
15268 bgp_static->label_index);
d62a17ae 15269
ea47320b
DL
15270 if (bgp_static->rmap.name)
15271 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15272
15273 if (bgp_static->backdoor)
15274 vty_out(vty, " backdoor");
718e3744 15275
ea47320b
DL
15276 vty_out(vty, "\n");
15277 }
15278
d62a17ae 15279 /* Aggregate-address configuration. */
9bcb3eef
DS
15280 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15281 dest = bgp_route_next(dest)) {
15282 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15283 if (bgp_aggregate == NULL)
ea47320b 15284 continue;
d62a17ae 15285
9bcb3eef 15286 p = bgp_dest_get_prefix(dest);
d62a17ae 15287
8228a9a7 15288 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15289
ea47320b
DL
15290 if (bgp_aggregate->as_set)
15291 vty_out(vty, " as-set");
d62a17ae 15292
ea47320b
DL
15293 if (bgp_aggregate->summary_only)
15294 vty_out(vty, " summary-only");
718e3744 15295
20894f50
DA
15296 if (bgp_aggregate->rmap.name)
15297 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15298
229757f1
DA
15299 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15300 vty_out(vty, " origin %s",
15301 bgp_origin2str(bgp_aggregate->origin));
15302
6aabb15d
RZ
15303 if (bgp_aggregate->match_med)
15304 vty_out(vty, " matching-MED-only");
15305
365ab2e7
RZ
15306 if (bgp_aggregate->suppress_map_name)
15307 vty_out(vty, " suppress-map %s",
15308 bgp_aggregate->suppress_map_name);
15309
ea47320b
DL
15310 vty_out(vty, "\n");
15311 }
d62a17ae 15312}
734b349e 15313
2b791107 15314void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15315 safi_t safi)
d62a17ae 15316{
9bcb3eef 15317 struct bgp_dest *dest;
d62a17ae 15318 struct bgp_distance *bdistance;
15319
15320 /* Distance configuration. */
15321 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15322 && bgp->distance_local[afi][safi]
15323 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15324 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15325 || bgp->distance_local[afi][safi]
15326 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15327 vty_out(vty, " distance bgp %d %d %d\n",
15328 bgp->distance_ebgp[afi][safi],
15329 bgp->distance_ibgp[afi][safi],
15330 bgp->distance_local[afi][safi]);
15331 }
734b349e 15332
9bcb3eef
DS
15333 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15334 dest = bgp_route_next(dest)) {
15335 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15336 if (bdistance != NULL)
56ca3b5b 15337 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15338 bdistance->distance, dest,
d62a17ae 15339 bdistance->access_list ? bdistance->access_list
15340 : "");
ca2e160d 15341 }
718e3744 15342}
15343
15344/* Allocate routing table structure and install commands. */
d62a17ae 15345void bgp_route_init(void)
15346{
15347 afi_t afi;
15348 safi_t safi;
15349
15350 /* Init BGP distance table. */
05c7a1cc 15351 FOREACH_AFI_SAFI (afi, safi)
960035b2 15352 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15353
15354 /* IPv4 BGP commands. */
15355 install_element(BGP_NODE, &bgp_table_map_cmd);
15356 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15357 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15358
554b3b10 15359 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15360
15361 /* IPv4 unicast configuration. */
15362 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15363 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15364 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15365
554b3b10 15366 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15367
15368 /* IPv4 multicast configuration. */
15369 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15370 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15371 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15372 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15373
15374 /* IPv4 labeled-unicast configuration. */
fb985e0c 15375 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15376 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15377
d62a17ae 15378 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15379 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15380 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15381 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15382 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15383 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15384 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15385 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15386
15387 install_element(VIEW_NODE,
15388 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15389 install_element(VIEW_NODE,
15390 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15391 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15392 install_element(VIEW_NODE,
15393 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15394#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15395 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15396#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15397 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15398 install_element(VIEW_NODE,
44c69747 15399 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15400
d62a17ae 15401 /* BGP dampening clear commands */
15402 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15403 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15404
d62a17ae 15405 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15406 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15407
15408 /* prefix count */
15409 install_element(ENABLE_NODE,
15410 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15411#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15412 install_element(ENABLE_NODE,
15413 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15414#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15415
d62a17ae 15416 /* New config IPv6 BGP commands. */
15417 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15418 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15419 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15420
554b3b10 15421 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15422
15423 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15424
fb985e0c
DA
15425 /* IPv6 labeled unicast address family. */
15426 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15427 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15428
d62a17ae 15429 install_element(BGP_NODE, &bgp_distance_cmd);
15430 install_element(BGP_NODE, &no_bgp_distance_cmd);
15431 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15432 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15433 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15434 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15435 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15436 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15437 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15438 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15439 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15440 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15441 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15442 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15443 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15444 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15445 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15446 install_element(BGP_IPV4M_NODE,
15447 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15448 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15449 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15450 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15451 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15452 install_element(BGP_IPV6_NODE,
15453 &ipv6_bgp_distance_source_access_list_cmd);
15454 install_element(BGP_IPV6_NODE,
15455 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15456 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15457 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15458 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15459 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15460 install_element(BGP_IPV6M_NODE,
15461 &ipv6_bgp_distance_source_access_list_cmd);
15462 install_element(BGP_IPV6M_NODE,
15463 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15464
ef5f4b23 15465 /* BGP dampening */
585f1adc
IR
15466 install_element(BGP_NODE, &bgp_damp_set_cmd);
15467 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15468 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15469 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15470 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15471 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15472 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15473 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15474 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15475 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15476 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15477 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15478 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15479 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15480
15481 /* Large Communities */
15482 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15483 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15484
15485 /* show bgp ipv4 flowspec detailed */
15486 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15487
2a0e69ae 15488 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15489 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15490}
15491
15492void bgp_route_finish(void)
15493{
15494 afi_t afi;
15495 safi_t safi;
15496
05c7a1cc
QY
15497 FOREACH_AFI_SAFI (afi, safi) {
15498 bgp_table_unlock(bgp_distance_table[afi][safi]);
15499 bgp_distance_table[afi][safi] = NULL;
15500 }
228da428 15501}