]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #11848 from rgirada/ospf_gr_nbr
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
2aad8c42
MS
105/* Render dest to prefix_rd based on safi */
106static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
107 safi_t safi);
108
718e3744 109/* Extern from bgp_dump.c */
dde72586
SH
110extern const char *bgp_origin_str[];
111extern const char *bgp_origin_long_str[];
3742de8d 112
b7d08f5a 113/* PMSI strings. */
114#define PMSI_TNLTYPE_STR_NO_INFO "No info"
115#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116static const struct message bgp_pmsi_tnltype_str[] = {
117 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 125 {0}
126};
b7d08f5a 127
9df8b37c 128#define VRFID_NONE_STR "-"
46aeabed 129#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 130
4a11bf2c 131DEFINE_HOOK(bgp_process,
9bcb3eef
DS
132 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
133 struct peer *peer, bool withdraw),
8451921b 134 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 135
4056a5f6
RZ
136/** Test if path is suppressed. */
137static bool bgp_path_suppressed(struct bgp_path_info *pi)
138{
139 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
140 return false;
141
142 return listcount(pi->extra->aggr_suppressors) > 0;
143}
4a11bf2c 144
9bcb3eef 145struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 146 safi_t safi, const struct prefix *p,
d62a17ae 147 struct prefix_rd *prd)
148{
9bcb3eef
DS
149 struct bgp_dest *dest;
150 struct bgp_dest *pdest = NULL;
d62a17ae 151
152 assert(table);
d62a17ae 153
154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN)) {
9bcb3eef 156 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 157
9bcb3eef
DS
158 if (!bgp_dest_has_bgp_path_info_data(pdest))
159 bgp_dest_set_bgp_table_info(
160 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 161 else
9bcb3eef
DS
162 bgp_dest_unlock_node(pdest);
163 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 164 }
718e3744 165
9bcb3eef 166 dest = bgp_node_get(table, p);
718e3744 167
d62a17ae 168 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
169 || (safi == SAFI_EVPN))
9bcb3eef 170 dest->pdest = pdest;
718e3744 171
9bcb3eef 172 return dest;
718e3744 173}
6b0655a2 174
9bcb3eef 175struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 176 safi_t safi, const struct prefix *p,
d62a17ae 177 struct prefix_rd *prd)
128ea8ab 178{
9bcb3eef
DS
179 struct bgp_dest *dest;
180 struct bgp_dest *pdest = NULL;
128ea8ab 181
d62a17ae 182 if (!table)
183 return NULL;
128ea8ab 184
d62a17ae 185 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
186 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
187 pdest = bgp_node_lookup(table, (struct prefix *)prd);
188 if (!pdest)
d62a17ae 189 return NULL;
128ea8ab 190
9bcb3eef
DS
191 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
192 bgp_dest_unlock_node(pdest);
d62a17ae 193 return NULL;
194 }
128ea8ab 195
9bcb3eef 196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 197 }
128ea8ab 198
9bcb3eef 199 dest = bgp_node_lookup(table, p);
128ea8ab 200
9bcb3eef 201 return dest;
128ea8ab 202}
203
18ee8310
DS
204/* Allocate bgp_path_info_extra */
205static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 206{
4b7e6066
DS
207 struct bgp_path_info_extra *new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
209 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
210 new->label[0] = MPLS_INVALID_LABEL;
211 new->num_labels = 0;
3e3708cb
PG
212 new->bgp_fs_pbr = NULL;
213 new->bgp_fs_iprule = NULL;
d62a17ae 214 return new;
fb982c25
PJ
215}
216
a2e219fe 217void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 218{
4b7e6066 219 struct bgp_path_info_extra *e;
d62a17ae 220
c93a3b77
DS
221 if (!extra || !*extra)
222 return;
d62a17ae 223
c93a3b77 224 e = *extra;
4538f895 225 if (e->damp_info)
b4f7f45b
IR
226 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
227 e->damp_info->safi);
4538f895 228
c93a3b77
DS
229 e->damp_info = NULL;
230 if (e->parent) {
40381db7 231 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 232
40381db7 233 if (bpi->net) {
0e70e6c8
DL
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
237 *
40381db7
DS
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
0e70e6c8
DL
241 */
242 unsigned refcount;
243
40381db7 244 bpi = bgp_path_info_lock(bpi);
c10e14e9 245 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 246 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 247 if (!refcount)
40381db7
DS
248 bpi->net = NULL;
249 bgp_path_info_unlock(bpi);
0e70e6c8 250 }
18ee8310 251 bgp_path_info_unlock(e->parent);
c93a3b77 252 e->parent = NULL;
d62a17ae 253 }
c93a3b77
DS
254
255 if (e->bgp_orig)
256 bgp_unlock(e->bgp_orig);
c26edcda 257
ff3bf9a4
DS
258 if (e->aggr_suppressors)
259 list_delete(&e->aggr_suppressors);
260
60605cbc
AK
261 if (e->mh_info)
262 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 263
ce3c0614
PG
264 if ((*extra)->bgp_fs_iprule)
265 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 266 if ((*extra)->bgp_fs_pbr)
6a154c88 267 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 268 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
269}
270
18ee8310
DS
271/* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
fb982c25 273 */
40381db7 274struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 275{
40381db7
DS
276 if (!pi->extra)
277 pi->extra = bgp_path_info_extra_new();
278 return pi->extra;
fb982c25
PJ
279}
280
718e3744 281/* Free bgp route information. */
9b6d8fcf 282static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 283{
05864da7 284 bgp_attr_unintern(&path->attr);
fb018d25 285
9b6d8fcf
DS
286 bgp_unlink_nexthop(path);
287 bgp_path_info_extra_free(&path->extra);
288 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
289 if (path->net)
290 bgp_addpath_free_info_data(&path->tx_addpath,
291 &path->net->tx_addpath);
718e3744 292
9b6d8fcf 293 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 294
9b6d8fcf 295 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 296}
297
9b6d8fcf 298struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 299{
9b6d8fcf
DS
300 path->lock++;
301 return path;
200df115 302}
303
9b6d8fcf 304struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 305{
9b6d8fcf
DS
306 assert(path && path->lock > 0);
307 path->lock--;
d62a17ae 308
9b6d8fcf 309 if (path->lock == 0) {
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
9b6d8fcf 314 return path;
200df115 315}
316
f009ff26 317/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 318static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 319{
320 struct peer *peer;
321 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 322 bool set_flag = false;
f009ff26 323 struct bgp *bgp = NULL;
324 struct bgp_table *table = NULL;
325 afi_t afi = 0;
326 safi_t safi = 0;
f009ff26 327
328 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
329 * then the route selection is deferred
330 */
9bcb3eef 331 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 332 return 0;
333
9bcb3eef 334 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 335 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 336 zlog_debug(
56ca3b5b
DL
337 "Route %pBD is in workqueue and being processed, not deferred.",
338 dest);
b54892e0 339
5f9c1aa2 340 return 0;
341 }
342
9bcb3eef 343 table = bgp_dest_table(dest);
f009ff26 344 if (table) {
345 bgp = table->bgp;
346 afi = table->afi;
347 safi = table->safi;
348 }
349
9bcb3eef 350 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 351 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
352 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
353 continue;
354
355 /* Route selection is deferred if there is a stale path which
356 * which indicates peer is in restart mode
357 */
36235319
QY
358 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
359 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 360 set_flag = true;
f009ff26 361 } else {
362 /* If the peer is graceful restart capable and peer is
363 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
364 */
365 peer = old_pi->peer;
36235319
QY
366 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
367 && BGP_PEER_RESTARTING_MODE(peer)
368 && (old_pi
369 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 370 set_flag = true;
f009ff26 371 }
372 }
373 if (set_flag)
374 break;
375 }
376
377 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
378 * is active
379 */
2ba1fe69 380 if (set_flag && table) {
f009ff26 381 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
382 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
383 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 384 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 385 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
386 zlog_debug("DEFER route %pBD, dest %p", dest,
387 dest);
f009ff26 388 return 0;
389 }
390 }
391 return -1;
392}
393
9bcb3eef 394void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 395{
4b7e6066 396 struct bgp_path_info *top;
718e3744 397
9bcb3eef 398 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 399
6f94b685 400 pi->next = top;
40381db7 401 pi->prev = NULL;
d62a17ae 402 if (top)
40381db7 403 top->prev = pi;
9bcb3eef 404 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 405
40381db7 406 bgp_path_info_lock(pi);
9bcb3eef 407 bgp_dest_lock_node(dest);
40381db7 408 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 409 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 410 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 411}
412
d62a17ae 413/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 414 completion callback *only* */
9bcb3eef 415void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 416{
40381db7
DS
417 if (pi->next)
418 pi->next->prev = pi->prev;
419 if (pi->prev)
420 pi->prev->next = pi->next;
d62a17ae 421 else
9bcb3eef 422 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 423
40381db7
DS
424 bgp_path_info_mpath_dequeue(pi);
425 bgp_path_info_unlock(pi);
7fd28dd2 426 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 427 bgp_dest_unlock_node(dest);
718e3744 428}
429
9bcb3eef 430void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 431{
9bcb3eef 432 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 433 /* set of previous already took care of pcount */
40381db7 434 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 435}
436
18ee8310 437/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
438 called when a route is deleted and then quickly re-added before the
439 deletion has been processed */
9bcb3eef 440void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 441{
9bcb3eef 442 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 443 /* unset of previous already took care of pcount */
40381db7 444 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
445}
446
d62a17ae 447/* Adjust pcount as required */
9bcb3eef 448static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 449{
d62a17ae 450 struct bgp_table *table;
67174041 451
9bcb3eef 452 assert(dest && bgp_dest_table(dest));
40381db7 453 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 454
9bcb3eef 455 table = bgp_dest_table(dest);
67174041 456
40381db7 457 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 458 return;
459
40381db7
DS
460 if (!BGP_PATH_COUNTABLE(pi)
461 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 462
40381db7 463 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 464
465 /* slight hack, but more robust against errors. */
40381db7
DS
466 if (pi->peer->pcount[table->afi][table->safi])
467 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 468 else
450971aa 469 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 470 "Asked to decrement 0 prefix count for peer");
40381db7
DS
471 } else if (BGP_PATH_COUNTABLE(pi)
472 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
473 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
474 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 475 }
1a392d46
PJ
476}
477
40381db7
DS
478static int bgp_label_index_differs(struct bgp_path_info *pi1,
479 struct bgp_path_info *pi2)
28d58fd7 480{
40381db7 481 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 482}
1a392d46 483
18ee8310 484/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
485 * This is here primarily to keep prefix-count in check.
486 */
9bcb3eef 487void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 488 uint32_t flag)
1a392d46 489{
40381db7 490 SET_FLAG(pi->flags, flag);
d62a17ae 491
492 /* early bath if we know it's not a flag that changes countability state
493 */
494 if (!CHECK_FLAG(flag,
1defdda8 495 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 496 return;
497
9bcb3eef 498 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
499}
500
9bcb3eef 501void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 502 uint32_t flag)
1a392d46 503{
40381db7 504 UNSET_FLAG(pi->flags, flag);
d62a17ae 505
506 /* early bath if we know it's not a flag that changes countability state
507 */
508 if (!CHECK_FLAG(flag,
1defdda8 509 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 510 return;
511
9bcb3eef 512 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
513}
514
718e3744 515/* Get MED value. If MED value is missing and "bgp bestpath
516 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 517static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 518{
519 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
520 return attr->med;
521 else {
892fedb6 522 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 523 return BGP_MED_MAX;
524 else
525 return 0;
526 }
718e3744 527}
528
7533cad7
QY
529void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
530 size_t buf_len)
2ec1e66f 531{
40381db7 532 if (pi->addpath_rx_id)
7533cad7
QY
533 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
534 pi->peer->host, pi->addpath_rx_id);
d62a17ae 535 else
7533cad7 536 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 537}
9fbdd100 538
da0c0ef7
KM
539
540/*
541 * Get the ultimate path info.
542 */
543struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
544{
545 struct bgp_path_info *bpi_ultimate;
546
547 if (info->sub_type != BGP_ROUTE_IMPORTED)
548 return info;
549
550 for (bpi_ultimate = info;
551 bpi_ultimate->extra && bpi_ultimate->extra->parent;
552 bpi_ultimate = bpi_ultimate->extra->parent)
553 ;
554
555 return bpi_ultimate;
556}
557
d62a17ae 558/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
559 */
18ee8310
DS
560static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
561 struct bgp_path_info *exist, int *paths_eq,
562 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
563 char *pfx_buf, afi_t afi, safi_t safi,
564 enum bgp_path_selection_reason *reason)
d62a17ae 565{
5df26422 566 const struct prefix *new_p;
d62a17ae 567 struct attr *newattr, *existattr;
3061acc2
DA
568 enum bgp_peer_sort new_sort;
569 enum bgp_peer_sort exist_sort;
d7c0a89a
QY
570 uint32_t new_pref;
571 uint32_t exist_pref;
572 uint32_t new_med;
573 uint32_t exist_med;
574 uint32_t new_weight;
575 uint32_t exist_weight;
d62a17ae 576 uint32_t newm, existm;
577 struct in_addr new_id;
578 struct in_addr exist_id;
579 int new_cluster;
580 int exist_cluster;
581 int internal_as_route;
582 int confed_as_route;
04d14c8b 583 int ret = 0;
ee88563a
JM
584 int igp_metric_ret = 0;
585 int peer_sort_ret = -1;
d62a17ae 586 char new_buf[PATH_ADDPATH_STR_BUFFER];
587 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
588 uint32_t new_mm_seq;
589 uint32_t exist_mm_seq;
6d8c603a 590 int nh_cmp;
d071f237
AK
591 esi_t *exist_esi;
592 esi_t *new_esi;
593 bool same_esi;
594 bool old_proxy;
595 bool new_proxy;
33c6e933 596 bool new_origin, exist_origin;
da0c0ef7 597 struct bgp_path_info *bpi_ultimate;
d62a17ae 598
599 *paths_eq = 0;
600
601 /* 0. Null check. */
602 if (new == NULL) {
fdf81fa0 603 *reason = bgp_path_selection_none;
d62a17ae 604 if (debug)
605 zlog_debug("%s: new is NULL", pfx_buf);
606 return 0;
607 }
2ec1e66f 608
da0c0ef7
KM
609 if (debug) {
610 bpi_ultimate = bgp_get_imported_bpi_ultimate(new);
611 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, new_buf,
7533cad7 612 sizeof(new_buf));
da0c0ef7 613 }
718e3744 614
d62a17ae 615 if (exist == NULL) {
fdf81fa0 616 *reason = bgp_path_selection_first;
d62a17ae 617 if (debug)
4378495a
DS
618 zlog_debug("%s(%s): %s is the initial bestpath",
619 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 620 return 1;
621 }
2ec1e66f 622
d62a17ae 623 if (debug) {
da0c0ef7
KM
624 bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
625 bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
7533cad7 626 sizeof(exist_buf));
4378495a
DS
627 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
628 pfx_buf, bgp->name_pretty, new_buf, new->flags,
629 exist_buf, exist->flags);
d62a17ae 630 }
8ff56318 631
d62a17ae 632 newattr = new->attr;
633 existattr = exist->attr;
634
1479ed2f
DA
635 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
636 * Capability" to a neighbor MUST perform the following upon receiving
637 * a route from that neighbor with the "LLGR_STALE" community, or upon
638 * attaching the "LLGR_STALE" community itself per Section 4.2:
639 *
640 * Treat the route as the least-preferred in route selection (see
641 * below). See the Risks of Depreferencing Routes section (Section 5.2)
642 * for a discussion of potential risks inherent in doing this.
643 */
9a706b42
DA
644 if (bgp_attr_get_community(newattr) &&
645 community_include(bgp_attr_get_community(newattr),
646 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
647 if (debug)
648 zlog_debug(
649 "%s: %s wins over %s due to LLGR_STALE community",
650 pfx_buf, new_buf, exist_buf);
651 return 0;
652 }
653
9a706b42
DA
654 if (bgp_attr_get_community(existattr) &&
655 community_include(bgp_attr_get_community(existattr),
656 COMMUNITY_LLGR_STALE)) {
1479ed2f
DA
657 if (debug)
658 zlog_debug(
659 "%s: %s loses to %s due to LLGR_STALE community",
660 pfx_buf, new_buf, exist_buf);
661 return 1;
662 }
663
5df26422
NS
664 new_p = bgp_dest_get_prefix(new->net);
665
d62a17ae 666 /* For EVPN routes, we cannot just go by local vs remote, we have to
667 * look at the MAC mobility sequence number, if present.
668 */
5df26422
NS
669 if ((safi == SAFI_EVPN)
670 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 671 /* This is an error condition described in RFC 7432 Section
672 * 15.2. The RFC
673 * states that in this scenario "the PE MUST alert the operator"
674 * but it
675 * does not state what other action to take. In order to provide
676 * some
677 * consistency in this scenario we are going to prefer the path
678 * with the
679 * sticky flag.
680 */
681 if (newattr->sticky != existattr->sticky) {
682 if (!debug) {
5df26422
NS
683 prefix2str(new_p, pfx_buf,
684 sizeof(*pfx_buf)
685 * PREFIX2STR_BUFFER);
18ee8310 686 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
687 new, new_buf, sizeof(new_buf));
688 bgp_path_info_path_with_addpath_rx_str(
689 exist, exist_buf, sizeof(exist_buf));
d62a17ae 690 }
691
692 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 693 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
694 if (debug)
695 zlog_debug(
696 "%s: %s wins over %s due to sticky MAC flag",
697 pfx_buf, new_buf, exist_buf);
d62a17ae 698 return 1;
699 }
700
701 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
703 if (debug)
704 zlog_debug(
705 "%s: %s loses to %s due to sticky MAC flag",
706 pfx_buf, new_buf, exist_buf);
d62a17ae 707 return 0;
708 }
709 }
128ea8ab 710
d071f237
AK
711 new_esi = bgp_evpn_attr_get_esi(newattr);
712 exist_esi = bgp_evpn_attr_get_esi(existattr);
713 if (bgp_evpn_is_esi_valid(new_esi) &&
714 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
715 same_esi = true;
716 } else {
717 same_esi = false;
718 }
719
720 /* If both paths have the same non-zero ES and
721 * one path is local it wins.
722 * PS: Note the local path wins even if the remote
723 * has the higher MM seq. The local path's
724 * MM seq will be fixed up to match the highest
725 * rem seq, subsequently.
726 */
727 if (same_esi) {
728 char esi_buf[ESI_STR_LEN];
729
730 if (bgp_evpn_is_path_local(bgp, new)) {
731 *reason = bgp_path_selection_evpn_local_path;
732 if (debug)
733 zlog_debug(
734 "%s: %s wins over %s as ES %s is same and local",
735 pfx_buf, new_buf, exist_buf,
736 esi_to_str(new_esi, esi_buf,
737 sizeof(esi_buf)));
738 return 1;
739 }
740 if (bgp_evpn_is_path_local(bgp, exist)) {
741 *reason = bgp_path_selection_evpn_local_path;
742 if (debug)
743 zlog_debug(
744 "%s: %s loses to %s as ES %s is same and local",
745 pfx_buf, new_buf, exist_buf,
746 esi_to_str(new_esi, esi_buf,
747 sizeof(esi_buf)));
748 return 0;
749 }
750 }
751
d62a17ae 752 new_mm_seq = mac_mobility_seqnum(newattr);
753 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 754
d62a17ae 755 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 756 *reason = bgp_path_selection_evpn_seq;
d62a17ae 757 if (debug)
758 zlog_debug(
759 "%s: %s wins over %s due to MM seq %u > %u",
760 pfx_buf, new_buf, exist_buf, new_mm_seq,
761 exist_mm_seq);
762 return 1;
763 }
8ff56318 764
d62a17ae 765 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 766 *reason = bgp_path_selection_evpn_seq;
d62a17ae 767 if (debug)
768 zlog_debug(
769 "%s: %s loses to %s due to MM seq %u < %u",
770 pfx_buf, new_buf, exist_buf, new_mm_seq,
771 exist_mm_seq);
772 return 0;
773 }
6d8c603a 774
d071f237
AK
775 /* if the sequence numbers and ESI are the same and one path
776 * is non-proxy it wins (over proxy)
777 */
778 new_proxy = bgp_evpn_attr_is_proxy(newattr);
779 old_proxy = bgp_evpn_attr_is_proxy(existattr);
780 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
781 old_proxy != new_proxy) {
782 if (!new_proxy) {
783 *reason = bgp_path_selection_evpn_non_proxy;
784 if (debug)
785 zlog_debug(
786 "%s: %s wins over %s, same seq/es and non-proxy",
787 pfx_buf, new_buf, exist_buf);
788 return 1;
789 }
790
791 *reason = bgp_path_selection_evpn_non_proxy;
792 if (debug)
793 zlog_debug(
794 "%s: %s loses to %s, same seq/es and non-proxy",
795 pfx_buf, new_buf, exist_buf);
796 return 0;
797 }
798
6d8c603a
AK
799 /*
800 * if sequence numbers are the same path with the lowest IP
801 * wins
802 */
803 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
804 if (nh_cmp < 0) {
fdf81fa0 805 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
806 if (debug)
807 zlog_debug(
23d0a753 808 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 809 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 810 &new->attr->nexthop);
6d8c603a
AK
811 return 1;
812 }
813 if (nh_cmp > 0) {
fdf81fa0 814 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
815 if (debug)
816 zlog_debug(
23d0a753 817 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 818 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 819 &new->attr->nexthop);
6d8c603a
AK
820 return 0;
821 }
d62a17ae 822 }
9fbdd100 823
d62a17ae 824 /* 1. Weight check. */
d62a17ae 825 new_weight = newattr->weight;
826 exist_weight = existattr->weight;
8ff56318 827
d62a17ae 828 if (new_weight > exist_weight) {
fdf81fa0 829 *reason = bgp_path_selection_weight;
d62a17ae 830 if (debug)
831 zlog_debug("%s: %s wins over %s due to weight %d > %d",
832 pfx_buf, new_buf, exist_buf, new_weight,
833 exist_weight);
834 return 1;
835 }
718e3744 836
d62a17ae 837 if (new_weight < exist_weight) {
fdf81fa0 838 *reason = bgp_path_selection_weight;
d62a17ae 839 if (debug)
840 zlog_debug("%s: %s loses to %s due to weight %d < %d",
841 pfx_buf, new_buf, exist_buf, new_weight,
842 exist_weight);
843 return 0;
844 }
9fbdd100 845
d62a17ae 846 /* 2. Local preference check. */
847 new_pref = exist_pref = bgp->default_local_pref;
848
849 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 new_pref = newattr->local_pref;
851 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
852 exist_pref = existattr->local_pref;
853
854 if (new_pref > exist_pref) {
fdf81fa0 855 *reason = bgp_path_selection_local_pref;
d62a17ae 856 if (debug)
857 zlog_debug(
858 "%s: %s wins over %s due to localpref %d > %d",
859 pfx_buf, new_buf, exist_buf, new_pref,
860 exist_pref);
861 return 1;
862 }
718e3744 863
d62a17ae 864 if (new_pref < exist_pref) {
fdf81fa0 865 *reason = bgp_path_selection_local_pref;
d62a17ae 866 if (debug)
867 zlog_debug(
868 "%s: %s loses to %s due to localpref %d < %d",
869 pfx_buf, new_buf, exist_buf, new_pref,
870 exist_pref);
871 return 0;
872 }
9fbdd100 873
d62a17ae 874 /* 3. Local route check. We prefer:
875 * - BGP_ROUTE_STATIC
876 * - BGP_ROUTE_AGGREGATE
877 * - BGP_ROUTE_REDISTRIBUTE
878 */
33c6e933
DS
879 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
880 new->sub_type == BGP_ROUTE_IMPORTED);
881 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
882 exist->sub_type == BGP_ROUTE_IMPORTED);
883
884 if (new_origin && !exist_origin) {
fdf81fa0 885 *reason = bgp_path_selection_local_route;
d62a17ae 886 if (debug)
887 zlog_debug(
888 "%s: %s wins over %s due to preferred BGP_ROUTE type",
889 pfx_buf, new_buf, exist_buf);
890 return 1;
891 }
718e3744 892
33c6e933 893 if (!new_origin && exist_origin) {
fdf81fa0 894 *reason = bgp_path_selection_local_route;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s loses to %s due to preferred BGP_ROUTE type",
898 pfx_buf, new_buf, exist_buf);
899 return 0;
6811845b 900 }
718e3744 901
da0c0ef7
KM
902 /* Here if these are imported routes then get ultimate pi for
903 * path compare.
904 */
905 new = bgp_get_imported_bpi_ultimate(new);
906 exist = bgp_get_imported_bpi_ultimate(exist);
907 newattr = new->attr;
908 existattr = exist->attr;
909
d62a17ae 910 /* 4. AS path length check. */
892fedb6 911 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 912 int exist_hops = aspath_count_hops(existattr->aspath);
913 int exist_confeds = aspath_count_confeds(existattr->aspath);
914
892fedb6 915 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 916 int aspath_hops;
917
918 aspath_hops = aspath_count_hops(newattr->aspath);
919 aspath_hops += aspath_count_confeds(newattr->aspath);
920
921 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 922 *reason = bgp_path_selection_confed_as_path;
d62a17ae 923 if (debug)
924 zlog_debug(
925 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
926 pfx_buf, new_buf, exist_buf,
927 aspath_hops,
928 (exist_hops + exist_confeds));
929 return 1;
930 }
931
932 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 933 *reason = bgp_path_selection_confed_as_path;
d62a17ae 934 if (debug)
935 zlog_debug(
936 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
937 pfx_buf, new_buf, exist_buf,
938 aspath_hops,
939 (exist_hops + exist_confeds));
940 return 0;
941 }
942 } else {
943 int newhops = aspath_count_hops(newattr->aspath);
944
945 if (newhops < exist_hops) {
fdf81fa0 946 *reason = bgp_path_selection_as_path;
d62a17ae 947 if (debug)
948 zlog_debug(
949 "%s: %s wins over %s due to aspath hopcount %d < %d",
950 pfx_buf, new_buf, exist_buf,
951 newhops, exist_hops);
952 return 1;
953 }
954
955 if (newhops > exist_hops) {
fdf81fa0 956 *reason = bgp_path_selection_as_path;
d62a17ae 957 if (debug)
958 zlog_debug(
959 "%s: %s loses to %s due to aspath hopcount %d > %d",
960 pfx_buf, new_buf, exist_buf,
961 newhops, exist_hops);
962 return 0;
963 }
964 }
965 }
9fbdd100 966
d62a17ae 967 /* 5. Origin check. */
968 if (newattr->origin < existattr->origin) {
fdf81fa0 969 *reason = bgp_path_selection_origin;
d62a17ae 970 if (debug)
971 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
972 pfx_buf, new_buf, exist_buf,
973 bgp_origin_long_str[newattr->origin],
974 bgp_origin_long_str[existattr->origin]);
975 return 1;
976 }
718e3744 977
d62a17ae 978 if (newattr->origin > existattr->origin) {
fdf81fa0 979 *reason = bgp_path_selection_origin;
d62a17ae 980 if (debug)
981 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
982 pfx_buf, new_buf, exist_buf,
983 bgp_origin_long_str[newattr->origin],
984 bgp_origin_long_str[existattr->origin]);
985 return 0;
986 }
718e3744 987
d62a17ae 988 /* 6. MED check. */
989 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
990 && aspath_count_hops(existattr->aspath) == 0);
991 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
992 && aspath_count_confeds(existattr->aspath) > 0
993 && aspath_count_hops(newattr->aspath) == 0
994 && aspath_count_hops(existattr->aspath) == 0);
995
892fedb6
DA
996 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
997 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 998 || aspath_cmp_left(newattr->aspath, existattr->aspath)
999 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
1000 || internal_as_route) {
1001 new_med = bgp_med_value(new->attr, bgp);
1002 exist_med = bgp_med_value(exist->attr, bgp);
1003
1004 if (new_med < exist_med) {
fdf81fa0 1005 *reason = bgp_path_selection_med;
d62a17ae 1006 if (debug)
1007 zlog_debug(
1008 "%s: %s wins over %s due to MED %d < %d",
1009 pfx_buf, new_buf, exist_buf, new_med,
1010 exist_med);
1011 return 1;
1012 }
8ff56318 1013
d62a17ae 1014 if (new_med > exist_med) {
fdf81fa0 1015 *reason = bgp_path_selection_med;
d62a17ae 1016 if (debug)
1017 zlog_debug(
1018 "%s: %s loses to %s due to MED %d > %d",
1019 pfx_buf, new_buf, exist_buf, new_med,
1020 exist_med);
1021 return 0;
1022 }
1023 }
9fbdd100 1024
d62a17ae 1025 /* 7. Peer type check. */
1026 new_sort = new->peer->sort;
1027 exist_sort = exist->peer->sort;
1028
1029 if (new_sort == BGP_PEER_EBGP
1030 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1031 *reason = bgp_path_selection_peer;
d62a17ae 1032 if (debug)
1033 zlog_debug(
1034 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1035 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1036 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1037 return 1;
1038 peer_sort_ret = 1;
d62a17ae 1039 }
718e3744 1040
d62a17ae 1041 if (exist_sort == BGP_PEER_EBGP
1042 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1043 *reason = bgp_path_selection_peer;
d62a17ae 1044 if (debug)
1045 zlog_debug(
1046 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1047 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1048 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1049 return 0;
1050 peer_sort_ret = 0;
d62a17ae 1051 }
8ff56318 1052
d62a17ae 1053 /* 8. IGP metric check. */
1054 newm = existm = 0;
8ff56318 1055
d62a17ae 1056 if (new->extra)
1057 newm = new->extra->igpmetric;
1058 if (exist->extra)
1059 existm = exist->extra->igpmetric;
9fbdd100 1060
d62a17ae 1061 if (newm < existm) {
ee88563a 1062 if (debug && peer_sort_ret < 0)
d62a17ae 1063 zlog_debug(
d588b995 1064 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1065 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1066 igp_metric_ret = 1;
d62a17ae 1067 }
718e3744 1068
d62a17ae 1069 if (newm > existm) {
ee88563a 1070 if (debug && peer_sort_ret < 0)
d62a17ae 1071 zlog_debug(
d588b995 1072 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1073 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1074 igp_metric_ret = 0;
5e242b0d 1075 }
5e242b0d 1076
d62a17ae 1077 /* 9. Same IGP metric. Compare the cluster list length as
1078 representative of IGP hops metric. Rewrite the metric value
1079 pair (newm, existm) with the cluster list length. Prefer the
1080 path with smaller cluster list length. */
1081 if (newm == existm) {
aa53c036
DS
1082 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP &&
1083 peer_sort_lookup(exist->peer) == BGP_PEER_IBGP &&
1084 (mpath_cfg == NULL || mpath_cfg->same_clusterlen)) {
d62a17ae 1085 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1086 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1087
1088 if (newm < existm) {
ee88563a 1089 if (debug && peer_sort_ret < 0)
d62a17ae 1090 zlog_debug(
d588b995 1091 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1092 pfx_buf, new_buf, exist_buf,
1093 newm, existm);
ee88563a 1094 igp_metric_ret = 1;
d62a17ae 1095 }
1096
1097 if (newm > existm) {
ee88563a 1098 if (debug && peer_sort_ret < 0)
d62a17ae 1099 zlog_debug(
d588b995 1100 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1101 pfx_buf, new_buf, exist_buf,
1102 newm, existm);
ee88563a 1103 igp_metric_ret = 0;
d62a17ae 1104 }
1105 }
1106 }
31a4638f 1107
d62a17ae 1108 /* 10. confed-external vs. confed-internal */
1109 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1110 if (new_sort == BGP_PEER_CONFED
1111 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1112 *reason = bgp_path_selection_confed;
d62a17ae 1113 if (debug)
1114 zlog_debug(
1115 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1116 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1117 if (!CHECK_FLAG(bgp->flags,
1118 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1119 return 1;
1120 peer_sort_ret = 1;
d62a17ae 1121 }
718e3744 1122
d62a17ae 1123 if (exist_sort == BGP_PEER_CONFED
1124 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1125 *reason = bgp_path_selection_confed;
d62a17ae 1126 if (debug)
1127 zlog_debug(
1128 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1129 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1130 if (!CHECK_FLAG(bgp->flags,
1131 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1132 return 0;
1133 peer_sort_ret = 0;
d62a17ae 1134 }
1135 }
718e3744 1136
d62a17ae 1137 /* 11. Maximum path check. */
1138 if (newm == existm) {
1139 /* If one path has a label but the other does not, do not treat
1140 * them as equals for multipath
1141 */
a4d82a8a 1142 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1143 != (exist->extra
b57ba6d2 1144 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1145 if (debug)
1146 zlog_debug(
1147 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1148 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1149 } else if (CHECK_FLAG(bgp->flags,
1150 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1151
1152 /*
1153 * For the two paths, all comparison steps till IGP
1154 * metric
1155 * have succeeded - including AS_PATH hop count. Since
1156 * 'bgp
1157 * bestpath as-path multipath-relax' knob is on, we
1158 * don't need
1159 * an exact match of AS_PATH. Thus, mark the paths are
1160 * equal.
1161 * That will trigger both these paths to get into the
1162 * multipath
1163 * array.
1164 */
1165 *paths_eq = 1;
1166
1167 if (debug)
1168 zlog_debug(
1169 "%s: %s and %s are equal via multipath-relax",
1170 pfx_buf, new_buf, exist_buf);
1171 } else if (new->peer->sort == BGP_PEER_IBGP) {
1172 if (aspath_cmp(new->attr->aspath,
1173 exist->attr->aspath)) {
1174 *paths_eq = 1;
1175
1176 if (debug)
1177 zlog_debug(
1178 "%s: %s and %s are equal via matching aspaths",
1179 pfx_buf, new_buf, exist_buf);
1180 }
1181 } else if (new->peer->as == exist->peer->as) {
1182 *paths_eq = 1;
1183
1184 if (debug)
1185 zlog_debug(
1186 "%s: %s and %s are equal via same remote-as",
1187 pfx_buf, new_buf, exist_buf);
1188 }
1189 } else {
1190 /*
1191 * TODO: If unequal cost ibgp multipath is enabled we can
1192 * mark the paths as equal here instead of returning
1193 */
ee88563a
JM
1194
1195 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1196 * if either step 7 or 10 (peer type checks) yielded a winner,
1197 * that result was returned immediately. Returning from step 10
1198 * ignored the return value computed in steps 8 and 9 (IGP
1199 * metric checks). In order to preserve that behavior, if
1200 * peer_sort_ret is set, return that rather than igp_metric_ret.
1201 */
1202 ret = peer_sort_ret;
1203 if (peer_sort_ret < 0) {
1204 ret = igp_metric_ret;
1205 if (debug) {
1206 if (ret == 1)
1207 zlog_debug(
1208 "%s: %s wins over %s after IGP metric comparison",
1209 pfx_buf, new_buf, exist_buf);
1210 else
1211 zlog_debug(
1212 "%s: %s loses to %s after IGP metric comparison",
1213 pfx_buf, new_buf, exist_buf);
1214 }
1215 *reason = bgp_path_selection_igp_metric;
d62a17ae 1216 }
1217 return ret;
1218 }
718e3744 1219
ee88563a
JM
1220 /*
1221 * At this point, the decision whether to set *paths_eq = 1 has been
1222 * completed. If we deferred returning because of bestpath peer-type
1223 * relax configuration, return now.
1224 */
1225 if (peer_sort_ret >= 0)
1226 return peer_sort_ret;
1227
d62a17ae 1228 /* 12. If both paths are external, prefer the path that was received
1229 first (the oldest one). This step minimizes route-flap, since a
1230 newer path won't displace an older one, even if it was the
1231 preferred route based on the additional decision criteria below. */
892fedb6 1232 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1233 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1234 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1235 *reason = bgp_path_selection_older;
d62a17ae 1236 if (debug)
1237 zlog_debug(
1238 "%s: %s wins over %s due to oldest external",
1239 pfx_buf, new_buf, exist_buf);
1240 return 1;
1241 }
9fbdd100 1242
1defdda8 1243 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1244 *reason = bgp_path_selection_older;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s loses to %s due to oldest external",
1248 pfx_buf, new_buf, exist_buf);
1249 return 0;
1250 }
1251 }
718e3744 1252
ce5002c6 1253 /* 13. Router-ID comparison. */
d62a17ae 1254 /* If one of the paths is "stale", the corresponding peer router-id will
1255 * be 0 and would always win over the other path. If originator id is
ce5002c6 1256 * used for the comparison, it will decide which path is better.
d62a17ae 1257 */
1258 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1259 new_id.s_addr = newattr->originator_id.s_addr;
1260 else
1261 new_id.s_addr = new->peer->remote_id.s_addr;
1262 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1263 exist_id.s_addr = existattr->originator_id.s_addr;
1264 else
1265 exist_id.s_addr = exist->peer->remote_id.s_addr;
1266
1267 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1268 *reason = bgp_path_selection_router_id;
d62a17ae 1269 if (debug)
1270 zlog_debug(
1271 "%s: %s wins over %s due to Router-ID comparison",
1272 pfx_buf, new_buf, exist_buf);
1273 return 1;
1274 }
718e3744 1275
d62a17ae 1276 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1277 *reason = bgp_path_selection_router_id;
d62a17ae 1278 if (debug)
1279 zlog_debug(
1280 "%s: %s loses to %s due to Router-ID comparison",
1281 pfx_buf, new_buf, exist_buf);
1282 return 0;
1283 }
9fbdd100 1284
ce5002c6 1285 /* 14. Cluster length comparison. */
d62a17ae 1286 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1287 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1288
1289 if (new_cluster < exist_cluster) {
fdf81fa0 1290 *reason = bgp_path_selection_cluster_length;
d62a17ae 1291 if (debug)
1292 zlog_debug(
1293 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1294 pfx_buf, new_buf, exist_buf, new_cluster,
1295 exist_cluster);
1296 return 1;
1297 }
718e3744 1298
d62a17ae 1299 if (new_cluster > exist_cluster) {
fdf81fa0 1300 *reason = bgp_path_selection_cluster_length;
d62a17ae 1301 if (debug)
1302 zlog_debug(
1303 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1304 pfx_buf, new_buf, exist_buf, new_cluster,
1305 exist_cluster);
1306 return 0;
1307 }
9fbdd100 1308
ce5002c6 1309 /* 15. Neighbor address comparison. */
d62a17ae 1310 /* Do this only if neither path is "stale" as stale paths do not have
1311 * valid peer information (as the connection may or may not be up).
1312 */
1defdda8 1313 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1314 *reason = bgp_path_selection_stale;
d62a17ae 1315 if (debug)
1316 zlog_debug(
1317 "%s: %s wins over %s due to latter path being STALE",
1318 pfx_buf, new_buf, exist_buf);
1319 return 1;
1320 }
0de5153c 1321
1defdda8 1322 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1323 *reason = bgp_path_selection_stale;
d62a17ae 1324 if (debug)
1325 zlog_debug(
1326 "%s: %s loses to %s due to former path being STALE",
1327 pfx_buf, new_buf, exist_buf);
1328 return 0;
1329 }
718e3744 1330
d62a17ae 1331 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1332 if (new->peer->su_remote == NULL) {
1333 *reason = bgp_path_selection_local_configured;
d62a17ae 1334 return 0;
fdf81fa0
DS
1335 }
1336 if (exist->peer->su_remote == NULL) {
1337 *reason = bgp_path_selection_local_configured;
d62a17ae 1338 return 1;
fdf81fa0 1339 }
9fbdd100 1340
d62a17ae 1341 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1342
1343 if (ret == 1) {
fdf81fa0 1344 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1345 if (debug)
1346 zlog_debug(
1347 "%s: %s loses to %s due to Neighor IP comparison",
1348 pfx_buf, new_buf, exist_buf);
1349 return 0;
1350 }
1351
1352 if (ret == -1) {
fdf81fa0 1353 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1354 if (debug)
1355 zlog_debug(
1356 "%s: %s wins over %s due to Neighor IP comparison",
1357 pfx_buf, new_buf, exist_buf);
1358 return 1;
1359 }
9fbdd100 1360
fdf81fa0 1361 *reason = bgp_path_selection_default;
d62a17ae 1362 if (debug)
1363 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1364 pfx_buf, new_buf, exist_buf);
718e3744 1365
d62a17ae 1366 return 1;
718e3744 1367}
1368
d071f237
AK
1369
1370int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1371 struct bgp_path_info *exist, int *paths_eq)
1372{
1373 enum bgp_path_selection_reason reason;
1374 char pfx_buf[PREFIX2STR_BUFFER];
1375
1376 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1377 AFI_L2VPN, SAFI_EVPN, &reason);
1378}
1379
65efcfce
LB
1380/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1381 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1382 * multipath is enabled
65efcfce 1383 * This version is compatible with */
18ee8310
DS
1384int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1385 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1386 afi_t afi, safi_t safi,
1387 enum bgp_path_selection_reason *reason)
d62a17ae 1388{
1389 int paths_eq;
1390 int ret;
18ee8310 1391 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1392 afi, safi, reason);
d62a17ae 1393
1394 if (paths_eq)
1395 ret = 0;
1396 else {
1397 if (ret == 1)
1398 ret = -1;
1399 else
1400 ret = 1;
1401 }
1402 return ret;
65efcfce
LB
1403}
1404
5a1ae2c2
DS
1405static enum filter_type bgp_input_filter(struct peer *peer,
1406 const struct prefix *p,
d62a17ae 1407 struct attr *attr, afi_t afi,
1408 safi_t safi)
718e3744 1409{
d62a17ae 1410 struct bgp_filter *filter;
6401252f 1411 enum filter_type ret = FILTER_PERMIT;
718e3744 1412
d62a17ae 1413 filter = &peer->filter[afi][safi];
718e3744 1414
d62a17ae 1415#define FILTER_EXIST_WARN(F, f, filter) \
1416 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1417 zlog_debug("%s: Could not find configured input %s-list %s!", \
1418 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1419
1420 if (DISTRIBUTE_IN_NAME(filter)) {
1421 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1422
6401252f
QY
1423 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1424 == FILTER_DENY) {
1425 ret = FILTER_DENY;
1426 goto done;
1427 }
d62a17ae 1428 }
1429
1430 if (PREFIX_LIST_IN_NAME(filter)) {
1431 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1432
6401252f
QY
1433 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1434 == PREFIX_DENY) {
1435 ret = FILTER_DENY;
1436 goto done;
1437 }
d62a17ae 1438 }
1439
1440 if (FILTER_LIST_IN_NAME(filter)) {
1441 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1442
1443 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1444 == AS_FILTER_DENY) {
1445 ret = FILTER_DENY;
1446 goto done;
1447 }
d62a17ae 1448 }
1449
6401252f 1450done:
c7bb4f00 1451 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1452 char pfxprint[PREFIX2STR_BUFFER];
1453
1454 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1455 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1456 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1457 }
1458
1459 return ret;
650f76c2 1460#undef FILTER_EXIST_WARN
718e3744 1461}
1462
b8685f9b
DS
1463static enum filter_type bgp_output_filter(struct peer *peer,
1464 const struct prefix *p,
d62a17ae 1465 struct attr *attr, afi_t afi,
1466 safi_t safi)
718e3744 1467{
d62a17ae 1468 struct bgp_filter *filter;
6401252f 1469 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1470
1471 filter = &peer->filter[afi][safi];
1472
1473#define FILTER_EXIST_WARN(F, f, filter) \
1474 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1475 zlog_debug("%s: Could not find configured output %s-list %s!", \
1476 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1477
d62a17ae 1478 if (DISTRIBUTE_OUT_NAME(filter)) {
1479 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1480
6401252f
QY
1481 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1482 == FILTER_DENY) {
1483 ret = FILTER_DENY;
1484 goto done;
1485 }
d62a17ae 1486 }
1487
1488 if (PREFIX_LIST_OUT_NAME(filter)) {
1489 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1490
d62a17ae 1491 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1492 == PREFIX_DENY) {
1493 ret = FILTER_DENY;
1494 goto done;
1495 }
d62a17ae 1496 }
718e3744 1497
d62a17ae 1498 if (FILTER_LIST_OUT_NAME(filter)) {
1499 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1500
d62a17ae 1501 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1502 == AS_FILTER_DENY) {
1503 ret = FILTER_DENY;
1504 goto done;
1505 }
1506 }
1507
c7bb4f00 1508 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1509 char pfxprint[PREFIX2STR_BUFFER];
1510
1511 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1512 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1513 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1514 }
718e3744 1515
6401252f
QY
1516done:
1517 return ret;
650f76c2 1518#undef FILTER_EXIST_WARN
718e3744 1519}
1520
1521/* If community attribute includes no_export then return 1. */
3dc339cd 1522static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1523{
9a706b42 1524 if (bgp_attr_get_community(attr)) {
d62a17ae 1525 /* NO_ADVERTISE check. */
9a706b42
DA
1526 if (community_include(bgp_attr_get_community(attr),
1527 COMMUNITY_NO_ADVERTISE))
3dc339cd 1528 return true;
d62a17ae 1529
1530 /* NO_EXPORT check. */
9a706b42
DA
1531 if (peer->sort == BGP_PEER_EBGP &&
1532 community_include(bgp_attr_get_community(attr),
1533 COMMUNITY_NO_EXPORT))
3dc339cd 1534 return true;
d62a17ae 1535
1536 /* NO_EXPORT_SUBCONFED check. */
1537 if (peer->sort == BGP_PEER_EBGP
1538 || peer->sort == BGP_PEER_CONFED)
9a706b42 1539 if (community_include(bgp_attr_get_community(attr),
d62a17ae 1540 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1541 return true;
d62a17ae 1542 }
3dc339cd 1543 return false;
718e3744 1544}
1545
1546/* Route reflection loop check. */
3dc339cd 1547static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1548{
d62a17ae 1549 struct in_addr cluster_id;
779fee93 1550 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1551
779fee93 1552 if (cluster) {
d62a17ae 1553 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1554 cluster_id = peer->bgp->cluster_id;
1555 else
1556 cluster_id = peer->bgp->router_id;
1557
779fee93 1558 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1559 return true;
d62a17ae 1560 }
3dc339cd 1561 return false;
718e3744 1562}
6b0655a2 1563
d864dd9e
EB
1564static bool bgp_otc_filter(struct peer *peer, struct attr *attr)
1565{
1566 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1567 if (peer->local_role == ROLE_PROVIDER ||
1568 peer->local_role == ROLE_RS_SERVER)
1569 return true;
1570 if (peer->local_role == ROLE_PEER && attr->otc != peer->as)
1571 return true;
1572 return false;
1573 }
1574 if (peer->local_role == ROLE_CUSTOMER ||
1575 peer->local_role == ROLE_PEER ||
1576 peer->local_role == ROLE_RS_CLIENT) {
1577 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1578 attr->otc = peer->as;
1579 }
1580 return false;
1581}
1582
1583static bool bgp_otc_egress(struct peer *peer, struct attr *attr)
1584{
1585 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
1586 if (peer->local_role == ROLE_CUSTOMER ||
1587 peer->local_role == ROLE_RS_CLIENT ||
1588 peer->local_role == ROLE_PEER)
1589 return true;
1590 return false;
1591 }
1592 if (peer->local_role == ROLE_PROVIDER ||
1593 peer->local_role == ROLE_PEER ||
1594 peer->local_role == ROLE_RS_SERVER) {
1595 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
1596 attr->otc = peer->bgp->as;
1597 }
1598 return false;
1599}
1600
5a78f2bc
EB
1601static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
1602{
1603 return ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST);
1604}
1605
5a1ae2c2 1606static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1607 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1608 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1609 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1610{
d62a17ae 1611 struct bgp_filter *filter;
82b692c0
LK
1612 struct bgp_path_info rmap_path = { 0 };
1613 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1614 route_map_result_t ret;
1615 struct route_map *rmap = NULL;
718e3744 1616
d62a17ae 1617 filter = &peer->filter[afi][safi];
718e3744 1618
d62a17ae 1619 /* Apply default weight value. */
1620 if (peer->weight[afi][safi])
1621 attr->weight = peer->weight[afi][safi];
718e3744 1622
d62a17ae 1623 if (rmap_name) {
1624 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1625
d62a17ae 1626 if (rmap == NULL)
1627 return RMAP_DENY;
1628 } else {
1629 if (ROUTE_MAP_IN_NAME(filter)) {
1630 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1631
d62a17ae 1632 if (rmap == NULL)
1633 return RMAP_DENY;
1634 }
1635 }
0b16f239 1636
d62a17ae 1637 /* Route map apply. */
1638 if (rmap) {
6006b807 1639 memset(&rmap_path, 0, sizeof(rmap_path));
544be979 1640 /* Duplicate current value to new structure for modification. */
40381db7
DS
1641 rmap_path.peer = peer;
1642 rmap_path.attr = attr;
82b692c0 1643 rmap_path.extra = &extra;
9bcb3eef 1644 rmap_path.net = dest;
196c6b09 1645
82b692c0
LK
1646 extra.num_labels = num_labels;
1647 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1648 memcpy(extra.label, label,
1649 num_labels * sizeof(mpls_label_t));
718e3744 1650
d62a17ae 1651 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1652
d62a17ae 1653 /* Apply BGP route map to the attribute. */
1782514f 1654 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1655
d62a17ae 1656 peer->rmap_type = 0;
0b16f239 1657
1f2263be 1658 if (ret == RMAP_DENYMATCH)
d62a17ae 1659 return RMAP_DENY;
0b16f239 1660 }
d62a17ae 1661 return RMAP_PERMIT;
0b16f239
DS
1662}
1663
5f040085 1664static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1665 struct attr *attr, afi_t afi, safi_t safi,
1666 const char *rmap_name)
0b16f239 1667{
40381db7 1668 struct bgp_path_info rmap_path;
d62a17ae 1669 route_map_result_t ret;
1670 struct route_map *rmap = NULL;
d7c0a89a 1671 uint8_t rmap_type;
0b16f239 1672
b787157a
DS
1673 /*
1674 * So if we get to this point and have no rmap_name
1675 * we want to just show the output as it currently
1676 * exists.
1677 */
1678 if (!rmap_name)
1679 return RMAP_PERMIT;
0b16f239 1680
d62a17ae 1681 /* Apply default weight value. */
1682 if (peer->weight[afi][safi])
1683 attr->weight = peer->weight[afi][safi];
0b16f239 1684
b787157a 1685 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1686
b787157a
DS
1687 /*
1688 * If we have a route map name and we do not find
1689 * the routemap that means we have an implicit
1690 * deny.
1691 */
1692 if (rmap == NULL)
1693 return RMAP_DENY;
0b16f239 1694
6006b807 1695 memset(&rmap_path, 0, sizeof(rmap_path));
d62a17ae 1696 /* Route map apply. */
544be979 1697 /* Duplicate current value to new structure for modification. */
40381db7
DS
1698 rmap_path.peer = peer;
1699 rmap_path.attr = attr;
0b16f239 1700
0f672529 1701 rmap_type = peer->rmap_type;
b787157a 1702 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1703
b787157a 1704 /* Apply BGP route map to the attribute. */
1782514f 1705 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1706
0f672529 1707 peer->rmap_type = rmap_type;
b787157a
DS
1708
1709 if (ret == RMAP_DENYMATCH)
1710 /*
1711 * caller has multiple error paths with bgp_attr_flush()
1712 */
1713 return RMAP_DENY;
ac41b2a2 1714
d62a17ae 1715 return RMAP_PERMIT;
718e3744 1716}
6b0655a2 1717
5000f21c 1718/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1719static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1720 struct peer *peer, struct attr *attr)
1721{
1722 if (peer->sort == BGP_PEER_EBGP
1723 && (peer_af_flag_check(peer, afi, safi,
1724 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1725 || peer_af_flag_check(peer, afi, safi,
1726 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1727 || peer_af_flag_check(peer, afi, safi,
1728 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1729 || peer_af_flag_check(peer, afi, safi,
1730 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1731 // Take action on the entire aspath
1732 if (peer_af_flag_check(peer, afi, safi,
1733 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1734 || peer_af_flag_check(peer, afi, safi,
1735 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1736 if (peer_af_flag_check(
1737 peer, afi, safi,
1738 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1739 attr->aspath = aspath_replace_private_asns(
bf26b80e 1740 attr->aspath, bgp->as, peer->as);
d62a17ae 1741
179d5a0e
TA
1742 /*
1743 * Even if the aspath consists of just private ASNs we
1744 * need to walk the AS-Path to maintain all instances
1745 * of the peer's ASN to break possible loops.
1746 */
d62a17ae 1747 else
1748 attr->aspath = aspath_remove_private_asns(
bf26b80e 1749 attr->aspath, peer->as);
d62a17ae 1750 }
1751
1752 // 'all' was not specified so the entire aspath must be private
1753 // ASNs
1754 // for us to do anything
1755 else if (aspath_private_as_check(attr->aspath)) {
1756 if (peer_af_flag_check(
1757 peer, afi, safi,
1758 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1759 attr->aspath = aspath_replace_private_asns(
bf26b80e 1760 attr->aspath, bgp->as, peer->as);
d62a17ae 1761 else
179d5a0e
TA
1762 /*
1763 * Walk the aspath to retain any instances of
1764 * the peer_asn
1765 */
1766 attr->aspath = aspath_remove_private_asns(
1767 attr->aspath, peer->as);
d62a17ae 1768 }
1769 }
5000f21c
DS
1770}
1771
c7122e14 1772/* If this is an EBGP peer with as-override */
d62a17ae 1773static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1774 struct peer *peer, struct attr *attr)
1775{
9bbdb457
DA
1776 if (peer->sort == BGP_PEER_EBGP &&
1777 peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
1778 attr->aspath = aspath_replace_specific_asn(attr->aspath,
1779 peer->as, bgp->as);
d62a17ae 1780}
1781
1479ed2f
DA
1782void bgp_attr_add_llgr_community(struct attr *attr)
1783{
1784 struct community *old;
1785 struct community *new;
1786 struct community *merge;
1787 struct community *llgr;
1788
9a706b42 1789 old = bgp_attr_get_community(attr);
1479ed2f
DA
1790 llgr = community_str2com("llgr-stale");
1791
1792 assert(llgr);
1793
1794 if (old) {
1795 merge = community_merge(community_dup(old), llgr);
1796
1797 if (old->refcnt == 0)
1798 community_free(&old);
1799
1800 new = community_uniq_sort(merge);
1801 community_free(&merge);
1802 } else {
1803 new = community_dup(llgr);
1804 }
1805
1806 community_free(&llgr);
1807
9a706b42 1808 bgp_attr_set_community(attr, new);
1479ed2f
DA
1809}
1810
7f323236
DW
1811void bgp_attr_add_gshut_community(struct attr *attr)
1812{
1813 struct community *old;
1814 struct community *new;
1815 struct community *merge;
1816 struct community *gshut;
1817
9a706b42 1818 old = bgp_attr_get_community(attr);
7f323236
DW
1819 gshut = community_str2com("graceful-shutdown");
1820
990f4f91 1821 assert(gshut);
1822
7f323236
DW
1823 if (old) {
1824 merge = community_merge(community_dup(old), gshut);
1825
a4d82a8a 1826 if (old->refcnt == 0)
3c1f53de 1827 community_free(&old);
7f323236
DW
1828
1829 new = community_uniq_sort(merge);
3c1f53de 1830 community_free(&merge);
7f323236
DW
1831 } else {
1832 new = community_dup(gshut);
1833 }
1834
3c1f53de 1835 community_free(&gshut);
9a706b42 1836 bgp_attr_set_community(attr, new);
7f323236
DW
1837
1838 /* When we add the graceful-shutdown community we must also
1839 * lower the local-preference */
1840 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1841 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1842}
1843
1844
e73c112e
MK
1845/* Notify BGP Conditional advertisement scanner process. */
1846void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1847{
e73c112e 1848 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1849 afi_t afi = SUBGRP_AFI(subgrp);
1850 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1851 struct bgp_filter *filter = &peer->filter[afi][safi];
1852
1853 if (!ADVERTISE_MAP_NAME(filter))
1854 return;
1855
52979c3b
DS
1856 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1857 return;
e73c112e 1858
52979c3b 1859 peer->advmap_table_change = true;
e73c112e
MK
1860}
1861
1862
f2ee6d5c 1863void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1864{
960035b2 1865 if (family == AF_INET) {
975a328e
DA
1866 attr->nexthop.s_addr = INADDR_ANY;
1867 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1868 }
d62a17ae 1869 if (family == AF_INET6)
1870 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1871 if (family == AF_EVPN)
1872 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1873}
1874
9bcb3eef 1875bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1876 struct update_subgroup *subgrp,
7f7940e6 1877 const struct prefix *p, struct attr *attr,
51c3a7de 1878 struct attr *post_attr)
d62a17ae 1879{
1880 struct bgp_filter *filter;
1881 struct peer *from;
1882 struct peer *peer;
1883 struct peer *onlypeer;
1884 struct bgp *bgp;
40381db7 1885 struct attr *piattr;
b68885f9 1886 route_map_result_t ret;
d62a17ae 1887 int transparent;
1888 int reflect;
1889 afi_t afi;
1890 safi_t safi;
1891 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1892 bool nh_reset = false;
1893 uint64_t cum_bw;
d62a17ae 1894
1895 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1896 return false;
d62a17ae 1897
1898 afi = SUBGRP_AFI(subgrp);
1899 safi = SUBGRP_SAFI(subgrp);
1900 peer = SUBGRP_PEER(subgrp);
1901 onlypeer = NULL;
1902 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1903 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1904
40381db7 1905 from = pi->peer;
d62a17ae 1906 filter = &peer->filter[afi][safi];
1907 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1908 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1909 : pi->attr;
3f9c7369 1910
d0bf49ec
LS
1911 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1912 peer->pmax_out[afi][safi] != 0 &&
1913 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1914 if (BGP_DEBUG(update, UPDATE_OUT) ||
1915 BGP_DEBUG(update, UPDATE_PREFIX)) {
1916 zlog_debug("%s reached maximum prefix to be send (%u)",
1917 peer->host, peer->pmax_out[afi][safi]);
1918 }
1919 return false;
1920 }
1921
49e5a4a0 1922#ifdef ENABLE_BGP_VNC
d62a17ae 1923 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1924 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1925 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1926
1927 /*
1928 * direct and direct_ext type routes originate internally even
1929 * though they can have peer pointers that reference other
1930 * systems
1931 */
8228a9a7
DS
1932 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1933 __func__, p);
d62a17ae 1934 samepeer_safe = 1;
1935 }
65efcfce
LB
1936#endif
1937
ddb5b488
PZ
1938 if (((afi == AFI_IP) || (afi == AFI_IP6))
1939 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1940 && (pi->type == ZEBRA_ROUTE_BGP)
1941 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1942
1943 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1944
1945 samepeer_safe = 1;
1946 }
1947
d62a17ae 1948 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1949 * pi is valid */
1950 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1951 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1952 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1953 return false;
d62a17ae 1954 }
adbac85e 1955
d62a17ae 1956 /* If this is not the bestpath then check to see if there is an enabled
1957 * addpath
1958 * feature that requires us to advertise it */
40381db7 1959 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1960 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1961 return false;
d62a17ae 1962 }
1963 }
06370dac 1964
d62a17ae 1965 /* Aggregate-address suppress check. */
4056a5f6
RZ
1966 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1967 return false;
3f9c7369 1968
13b7e7f0
DS
1969 /*
1970 * If we are doing VRF 2 VRF leaking via the import
1971 * statement, we want to prevent the route going
1972 * off box as that the RT and RD created are localy
1973 * significant and globaly useless.
1974 */
40381db7
DS
1975 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1976 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1977 return false;
13b7e7f0 1978
d62a17ae 1979 /* If it's labeled safi, make sure the route has a valid label. */
1980 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1981 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1982 if (!bgp_is_valid_label(&label)) {
1983 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1984 zlog_debug("u%" PRIu64 ":s%" PRIu64
1985 " %pFX is filtered - no label (%p)",
d62a17ae 1986 subgrp->update_group->id, subgrp->id,
8228a9a7 1987 p, &label);
3dc339cd 1988 return false;
d62a17ae 1989 }
1990 }
cd1964ff 1991
d62a17ae 1992 /* Do not send back route to sender. */
1993 if (onlypeer && from == onlypeer) {
3dc339cd 1994 return false;
d62a17ae 1995 }
3f9c7369 1996
d62a17ae 1997 /* Do not send the default route in the BGP table if the neighbor is
1998 * configured for default-originate */
1999 if (CHECK_FLAG(peer->af_flags[afi][safi],
2000 PEER_FLAG_DEFAULT_ORIGINATE)) {
2001 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 2002 return false;
d62a17ae 2003 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 2004 return false;
d62a17ae 2005 }
4125bb67 2006
d62a17ae 2007 /* Transparency check. */
2008 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
2009 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
2010 transparent = 1;
2011 else
2012 transparent = 0;
2013
2014 /* If community is not disabled check the no-export and local. */
40381db7 2015 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 2016 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
2017 zlog_debug("%s: community filter check fail for %pFX",
2018 __func__, p);
3dc339cd 2019 return false;
d62a17ae 2020 }
3f9c7369 2021
d62a17ae 2022 /* If the attribute has originator-id and it is same as remote
2023 peer's id. */
40381db7
DS
2024 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
2025 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 2026 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2027 zlog_debug(
8228a9a7
DS
2028 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
2029 onlypeer->host, p);
3dc339cd 2030 return false;
d62a17ae 2031 }
3f9c7369 2032
d62a17ae 2033 /* ORF prefix-list filter check */
2034 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
2035 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
2036 || CHECK_FLAG(peer->af_cap[afi][safi],
2037 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
2038 if (peer->orf_plist[afi][safi]) {
2039 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2040 == PREFIX_DENY) {
2041 if (bgp_debug_update(NULL, p,
2042 subgrp->update_group, 0))
2043 zlog_debug(
8228a9a7
DS
2044 "%s [Update:SEND] %pFX is filtered via ORF",
2045 peer->host, p);
3dc339cd 2046 return false;
d62a17ae 2047 }
2048 }
2049
2050 /* Output filter check. */
40381db7 2051 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2052 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2053 zlog_debug("%s [Update:SEND] %pFX is filtered",
2054 peer->host, p);
3dc339cd 2055 return false;
d62a17ae 2056 }
3f9c7369 2057
d62a17ae 2058 /* AS path loop check. */
2b31007c
RZ
2059 if (onlypeer && onlypeer->as_path_loop_detection
2060 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2061 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2062 zlog_debug(
3efd0893 2063 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2064 onlypeer->host, onlypeer->as);
3dc339cd 2065 return false;
d62a17ae 2066 }
3f9c7369 2067
d62a17ae 2068 /* If we're a CONFED we need to loop check the CONFED ID too */
2069 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2070 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2071 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2072 zlog_debug(
3efd0893 2073 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2074 peer->host, bgp->confed_id);
3dc339cd 2075 return false;
d62a17ae 2076 }
3f9c7369 2077 }
3f9c7369 2078
d62a17ae 2079 /* Route-Reflect check. */
2080 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2081 reflect = 1;
2082 else
2083 reflect = 0;
2084
2085 /* IBGP reflection check. */
2086 if (reflect && !samepeer_safe) {
2087 /* A route from a Client peer. */
2088 if (CHECK_FLAG(from->af_flags[afi][safi],
2089 PEER_FLAG_REFLECTOR_CLIENT)) {
2090 /* Reflect to all the Non-Client peers and also to the
2091 Client peers other than the originator. Originator
2092 check
2093 is already done. So there is noting to do. */
2094 /* no bgp client-to-client reflection check. */
892fedb6
DA
2095 if (CHECK_FLAG(bgp->flags,
2096 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2097 if (CHECK_FLAG(peer->af_flags[afi][safi],
2098 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2099 return false;
d62a17ae 2100 } else {
2101 /* A route from a Non-client peer. Reflect to all other
2102 clients. */
2103 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2104 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2105 return false;
d62a17ae 2106 }
2107 }
3f9c7369 2108
51c3a7de
DA
2109 /* For modify attribute, copy it to temporary structure.
2110 * post_attr comes from BGP conditional advertisements, where
2111 * attributes are already processed by advertise-map route-map,
2112 * and this needs to be saved instead of overwriting from the
2113 * path attributes.
2114 */
2115 if (post_attr)
2116 *attr = *post_attr;
2117 else
2118 *attr = *piattr;
d62a17ae 2119
2120 /* If local-preference is not set. */
2121 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2122 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2123 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2124 attr->local_pref = bgp->default_local_pref;
3f9c7369 2125 }
3f9c7369 2126
d62a17ae 2127 /* If originator-id is not set and the route is to be reflected,
2128 set the originator id */
2129 if (reflect
2130 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2131 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2132 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2133 }
3f9c7369 2134
d62a17ae 2135 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2136 */
2137 if (peer->sort == BGP_PEER_EBGP
2138 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2139 if (from != bgp->peer_self && !transparent
2140 && !CHECK_FLAG(peer->af_flags[afi][safi],
2141 PEER_FLAG_MED_UNCHANGED))
2142 attr->flag &=
2143 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2144 }
3f9c7369 2145
d62a17ae 2146 /* Since the nexthop attribute can vary per peer, it is not explicitly
2147 * set
2148 * in announce check, only certain flags and length (or number of
2149 * nexthops
2150 * -- for IPv6/MP_REACH) are set here in order to guide the update
2151 * formation
2152 * code in setting the nexthop(s) on a per peer basis in
2153 * reformat_peer().
2154 * Typically, the source nexthop in the attribute is preserved but in
2155 * the
2156 * scenarios where we know it will always be overwritten, we reset the
2157 * nexthop to "0" in an attempt to achieve better Update packing. An
2158 * example of this is when a prefix from each of 2 IBGP peers needs to
2159 * be
2160 * announced to an EBGP peer (and they have the same attributes barring
2161 * their nexthop).
2162 */
2163 if (reflect)
2164 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2165
2166#define NEXTHOP_IS_V6 \
2167 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2168 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2169 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2170 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2171
2172 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2173 * if
2174 * the peer (group) is configured to receive link-local nexthop
2175 * unchanged
c728d027
DA
2176 * and it is available in the prefix OR we're not reflecting the route,
2177 * link-local nexthop address is valid and
d62a17ae 2178 * the peer (group) to whom we're going to announce is on a shared
2179 * network
2180 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2181 * By checking if nexthop LL address is valid we are sure that
2182 * we do not announce LL address as `::`.
d62a17ae 2183 */
2184 if (NEXTHOP_IS_V6) {
2185 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2186 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2187 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2188 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2189 || (!reflect && !transparent
c728d027
DA
2190 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2191 && peer->shared_network
d62a17ae 2192 && (from == bgp->peer_self
2193 || peer->sort == BGP_PEER_EBGP))) {
2194 attr->mp_nexthop_len =
2195 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2196 }
3f9c7369 2197
d62a17ae 2198 /* Clear off link-local nexthop in source, whenever it is not
2199 * needed to
2200 * ensure more prefixes share the same attribute for
2201 * announcement.
2202 */
2203 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2204 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2205 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2206 }
3f9c7369 2207
5a78f2bc
EB
2208 if (bgp_check_role_applicability(afi, safi) &&
2209 bgp_otc_egress(peer, attr))
d864dd9e
EB
2210 return false;
2211
d62a17ae 2212 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2213 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2214
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(
02494580
DA
2281 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2282 peer->host, p,
2283 ROUTE_MAP_OUT_NAME(filter));
a49e87d2 2284 bgp_attr_flush(rmap_path.attr);
3dc339cd 2285 return false;
d62a17ae 2286 }
3f9c7369 2287 }
3f9c7369 2288
9dac9fc8
DA
2289 /* RFC 8212 to prevent route leaks.
2290 * This specification intends to improve this situation by requiring the
2291 * explicit configuration of both BGP Import and Export Policies for any
2292 * External BGP (EBGP) session such as customers, peers, or
2293 * confederation boundaries for all enabled address families. Through
2294 * codification of the aforementioned requirement, operators will
2295 * benefit from consistent behavior across different BGP
2296 * implementations.
2297 */
1d3fdccf 2298 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2299 if (!bgp_outbound_policy_exists(peer, filter)) {
2300 if (monotime_since(&bgp->ebgprequirespolicywarning,
2301 NULL) > FIFTEENMINUTE2USEC ||
2302 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2303 zlog_warn(
2304 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2305 monotime(&bgp->ebgprequirespolicywarning);
2306 }
3dc339cd 2307 return false;
b17826b7 2308 }
9dac9fc8 2309
fb29348a
DA
2310 /* draft-ietf-idr-deprecate-as-set-confed-set
2311 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2312 * Eventually, This document (if approved) updates RFC 4271
2313 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2314 * and obsoletes RFC 6472.
2315 */
7f972cd8 2316 if (peer->bgp->reject_as_sets)
fb29348a 2317 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2318 return false;
fb29348a 2319
33d022bc
DA
2320 /* Codification of AS 0 Processing */
2321 if (aspath_check_as_zero(attr->aspath))
e2369003 2322 return false;
33d022bc 2323
637e5ba4 2324 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2325 if (peer->sort == BGP_PEER_IBGP
2326 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2327 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2328 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2329 } else {
2330 bgp_attr_add_gshut_community(attr);
2331 }
2332 }
2333
1479ed2f
DA
2334 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2335 * Capability" to a neighbor MUST perform the following upon receiving
2336 * a route from that neighbor with the "LLGR_STALE" community, or upon
2337 * attaching the "LLGR_STALE" community itself per Section 4.2:
2338 *
2339 * The route SHOULD NOT be advertised to any neighbor from which the
2340 * Long-lived Graceful Restart Capability has not been received.
2341 */
9a706b42
DA
2342 if (bgp_attr_get_community(attr) &&
2343 community_include(bgp_attr_get_community(attr),
2344 COMMUNITY_LLGR_STALE) &&
1479ed2f
DA
2345 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2346 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2347 return false;
2348
d62a17ae 2349 /* After route-map has been applied, we check to see if the nexthop to
2350 * be carried in the attribute (that is used for the announcement) can
2351 * be cleared off or not. We do this in all cases where we would be
2352 * setting the nexthop to "ourselves". For IPv6, we only need to
2353 * consider
2354 * the global nexthop here; the link-local nexthop would have been
2355 * cleared
2356 * already, and if not, it is required by the update formation code.
2357 * Also see earlier comments in this function.
2358 */
2359 /*
2360 * If route-map has performed some operation on the nexthop or the peer
2361 * configuration says to pass it unchanged, we cannot reset the nexthop
2362 * here, so only attempt to do it if these aren't true. Note that the
2363 * route-map handler itself might have cleared the nexthop, if for
2364 * example,
2365 * it is configured as 'peer-address'.
2366 */
2367 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2368 piattr->rmap_change_flags)
d62a17ae 2369 && !transparent
2370 && !CHECK_FLAG(peer->af_flags[afi][safi],
2371 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2372 /* We can reset the nexthop, if setting (or forcing) it to
2373 * 'self' */
2374 if (CHECK_FLAG(peer->af_flags[afi][safi],
2375 PEER_FLAG_NEXTHOP_SELF)
2376 || CHECK_FLAG(peer->af_flags[afi][safi],
2377 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2378 if (!reflect
2379 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2380 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2381 subgroup_announce_reset_nhop(
2382 (peer_cap_enhe(peer, afi, safi)
2383 ? AF_INET6
2384 : p->family),
2385 attr);
7b651a32 2386 nh_reset = true;
2387 }
d62a17ae 2388 } else if (peer->sort == BGP_PEER_EBGP) {
2389 /* Can also reset the nexthop if announcing to EBGP, but
2390 * only if
2391 * no peer in the subgroup is on a shared subnet.
2392 * Note: 3rd party nexthop currently implemented for
2393 * IPv4 only.
2394 */
737af885
BS
2395 if ((p->family == AF_INET) &&
2396 (!bgp_subgrp_multiaccess_check_v4(
2397 piattr->nexthop,
7b651a32 2398 subgrp, from))) {
d62a17ae 2399 subgroup_announce_reset_nhop(
2400 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2401 ? AF_INET6
2402 : p->family),
737af885 2403 attr);
7b651a32 2404 nh_reset = true;
2405 }
737af885
BS
2406
2407 if ((p->family == AF_INET6) &&
2408 (!bgp_subgrp_multiaccess_check_v6(
2409 piattr->mp_nexthop_global,
7b651a32 2410 subgrp, from))) {
737af885
BS
2411 subgroup_announce_reset_nhop(
2412 (peer_cap_enhe(peer, afi, safi)
2413 ? AF_INET6
2414 : p->family),
2415 attr);
7b651a32 2416 nh_reset = true;
2417 }
737af885
BS
2418
2419
2420
40381db7 2421 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2422 /*
2423 * This flag is used for leaked vpn-vrf routes
2424 */
2425 int family = p->family;
2426
2427 if (peer_cap_enhe(peer, afi, safi))
2428 family = AF_INET6;
2429
2430 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2431 zlog_debug(
1defdda8 2432 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2433 __func__, family2str(family));
2434 subgroup_announce_reset_nhop(family, attr);
7b651a32 2435 nh_reset = true;
d62a17ae 2436 }
63696f1d 2437 }
960035b2 2438
63696f1d 2439 /* If IPv6/MP and nexthop does not have any override and happens
2440 * to
2441 * be a link-local address, reset it so that we don't pass along
2442 * the
2443 * source's link-local IPv6 address to recipients who may not be
2444 * on
2445 * the same interface.
2446 */
2447 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2448 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2449 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2450 nh_reset = true;
2451 }
d62a17ae 2452 }
3f9c7369 2453
7b651a32 2454 /*
2455 * When the next hop is set to ourselves, if all multipaths have
2456 * link-bandwidth announce the cumulative bandwidth as that makes
2457 * the most sense. However, don't modify if the link-bandwidth has
2458 * been explicitly set by user policy.
2459 */
2460 if (nh_reset &&
f7e1c681 2461 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2462 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2463 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2464 bgp_attr_set_ecommunity(
2465 attr,
2466 ecommunity_replace_linkbw(
2467 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2468 CHECK_FLAG(
2469 peer->flags,
2470 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2471
3dc339cd 2472 return true;
3f9c7369
DS
2473}
2474
cc9f21da 2475static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2476{
2477 struct afi_safi_info *info;
2478 afi_t afi;
2479 safi_t safi;
2480 struct bgp *bgp;
2481
2482 info = THREAD_ARG(thread);
2483 afi = info->afi;
2484 safi = info->safi;
2485 bgp = info->bgp;
2486
2487 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2488 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2489 safi);
f009ff26 2490
2491 bgp->gr_info[afi][safi].t_route_select = NULL;
2492
2493 XFREE(MTYPE_TMP, info);
2494
2495 /* Best path selection */
cc9f21da 2496 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2497}
2498
9bcb3eef 2499void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2500 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2501 struct bgp_path_info_pair *result, afi_t afi,
2502 safi_t safi)
2503{
2504 struct bgp_path_info *new_select;
2505 struct bgp_path_info *old_select;
40381db7
DS
2506 struct bgp_path_info *pi;
2507 struct bgp_path_info *pi1;
2508 struct bgp_path_info *pi2;
2509 struct bgp_path_info *nextpi = NULL;
d62a17ae 2510 int paths_eq, do_mpath, debug;
2511 struct list mp_list;
2512 char pfx_buf[PREFIX2STR_BUFFER];
2513 char path_buf[PATH_ADDPATH_STR_BUFFER];
2514
2515 bgp_mp_list_init(&mp_list);
2516 do_mpath =
2517 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2518
9bcb3eef 2519 debug = bgp_debug_bestpath(dest);
d62a17ae 2520
2521 if (debug)
9bcb3eef 2522 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2523
9bcb3eef 2524 dest->reason = bgp_path_selection_none;
d62a17ae 2525 /* bgp deterministic-med */
2526 new_select = NULL;
892fedb6 2527 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2528
1defdda8 2529 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2530 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2531 pi1 = pi1->next)
9bcb3eef 2532 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2533 BGP_PATH_DMED_SELECTED);
d62a17ae 2534
9bcb3eef 2535 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2536 pi1 = pi1->next) {
40381db7 2537 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2538 continue;
40381db7 2539 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2540 continue;
ea8b2282 2541 if (pi1->peer != bgp->peer_self)
feb17238 2542 if (!peer_established(pi1->peer))
d62a17ae 2543 continue;
2544
40381db7
DS
2545 new_select = pi1;
2546 if (pi1->next) {
2547 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2548 if (CHECK_FLAG(pi2->flags,
1defdda8 2549 BGP_PATH_DMED_CHECK))
d62a17ae 2550 continue;
40381db7 2551 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2552 continue;
ea8b2282 2553 if (pi2->peer != bgp->peer_self
d62a17ae 2554 && !CHECK_FLAG(
ea8b2282
DS
2555 pi2->peer->sflags,
2556 PEER_STATUS_NSF_WAIT))
40381db7 2557 if (pi2->peer->status
d62a17ae 2558 != Established)
2559 continue;
2560
121e245d
DS
2561 if (!aspath_cmp_left(pi1->attr->aspath,
2562 pi2->attr->aspath)
2563 && !aspath_cmp_left_confed(
40381db7 2564 pi1->attr->aspath,
121e245d
DS
2565 pi2->attr->aspath))
2566 continue;
d62a17ae 2567
121e245d
DS
2568 if (bgp_path_info_cmp(
2569 bgp, pi2, new_select,
2570 &paths_eq, mpath_cfg, debug,
fdf81fa0 2571 pfx_buf, afi, safi,
9bcb3eef 2572 &dest->reason)) {
121e245d 2573 bgp_path_info_unset_flag(
9bcb3eef 2574 dest, new_select,
121e245d
DS
2575 BGP_PATH_DMED_SELECTED);
2576 new_select = pi2;
d62a17ae 2577 }
121e245d
DS
2578
2579 bgp_path_info_set_flag(
9bcb3eef 2580 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2581 }
2582 }
9bcb3eef 2583 bgp_path_info_set_flag(dest, new_select,
18ee8310 2584 BGP_PATH_DMED_CHECK);
9bcb3eef 2585 bgp_path_info_set_flag(dest, new_select,
18ee8310 2586 BGP_PATH_DMED_SELECTED);
d62a17ae 2587
2588 if (debug) {
18ee8310 2589 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2590 new_select, path_buf, sizeof(path_buf));
8228a9a7 2591 zlog_debug(
4378495a
DS
2592 "%pBD(%s): %s is the bestpath from AS %u",
2593 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2594 aspath_get_first_as(
2595 new_select->attr->aspath));
d62a17ae 2596 }
2597 }
2598 }
96450faf 2599
d62a17ae 2600 /* Check old selected route and new selected route. */
2601 old_select = NULL;
2602 new_select = NULL;
9bcb3eef 2603 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2604 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2605 enum bgp_path_selection_reason reason;
2606
40381db7
DS
2607 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2608 old_select = pi;
d62a17ae 2609
40381db7 2610 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2611 /* reap REMOVED routes, if needs be
2612 * selected route must stay for a while longer though
2613 */
40381db7
DS
2614 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2615 && (pi != old_select))
9bcb3eef 2616 bgp_path_info_reap(dest, pi);
d62a17ae 2617
ddb5b488 2618 if (debug)
40381db7
DS
2619 zlog_debug("%s: pi %p in holddown", __func__,
2620 pi);
ddb5b488 2621
d62a17ae 2622 continue;
2623 }
96450faf 2624
40381db7
DS
2625 if (pi->peer && pi->peer != bgp->peer_self
2626 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2627 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2628
2629 if (debug)
2630 zlog_debug(
40381db7
DS
2631 "%s: pi %p non self peer %s not estab state",
2632 __func__, pi, pi->peer->host);
ddb5b488 2633
d62a17ae 2634 continue;
ddb5b488 2635 }
9fbdd100 2636
892fedb6 2637 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2638 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2639 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2640 if (debug)
40381db7 2641 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2642 continue;
2643 }
9fbdd100 2644
9bcb3eef 2645 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2646
9bcb3eef 2647 reason = dest->reason;
40381db7 2648 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2649 debug, pfx_buf, afi, safi,
2650 &dest->reason)) {
19ea4cec
DS
2651 if (new_select == NULL &&
2652 reason != bgp_path_selection_none)
9bcb3eef 2653 dest->reason = reason;
40381db7 2654 new_select = pi;
d62a17ae 2655 }
2656 }
718e3744 2657
d62a17ae 2658 /* Now that we know which path is the bestpath see if any of the other
2659 * paths
2660 * qualify as multipaths
2661 */
2662 if (debug) {
2663 if (new_select)
7533cad7
QY
2664 bgp_path_info_path_with_addpath_rx_str(
2665 new_select, path_buf, sizeof(path_buf));
d62a17ae 2666 else
772270f3 2667 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2668 zlog_debug(
4378495a
DS
2669 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2670 dest, bgp->name_pretty, path_buf,
d62a17ae 2671 old_select ? old_select->peer->host : "NONE");
96450faf 2672 }
9fbdd100 2673
d62a17ae 2674 if (do_mpath && new_select) {
9bcb3eef 2675 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2676 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2677
2678 if (debug)
18ee8310 2679 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2680 pi, path_buf, sizeof(path_buf));
d62a17ae 2681
40381db7 2682 if (pi == new_select) {
d62a17ae 2683 if (debug)
2684 zlog_debug(
4378495a
DS
2685 "%pBD(%s): %s is the bestpath, add to the multipath list",
2686 dest, bgp->name_pretty,
2687 path_buf);
40381db7 2688 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2689 continue;
2690 }
2691
40381db7 2692 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2693 continue;
2694
40381db7
DS
2695 if (pi->peer && pi->peer != bgp->peer_self
2696 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2697 PEER_STATUS_NSF_WAIT))
feb17238 2698 if (!peer_established(pi->peer))
d62a17ae 2699 continue;
2700
40381db7 2701 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2702 if (debug)
2703 zlog_debug(
8228a9a7
DS
2704 "%pBD: %s has the same nexthop as the bestpath, skip it",
2705 dest, path_buf);
d62a17ae 2706 continue;
2707 }
2708
40381db7 2709 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2710 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2711 &dest->reason);
d62a17ae 2712
2713 if (paths_eq) {
2714 if (debug)
2715 zlog_debug(
8228a9a7
DS
2716 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2717 dest, path_buf);
40381db7 2718 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2719 }
2720 }
2721 }
fee0f4c6 2722
4378495a 2723 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2724 mpath_cfg);
2725 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2726 bgp_mp_list_clear(&mp_list);
96450faf 2727
9bcb3eef 2728 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2729
d62a17ae 2730 result->old = old_select;
2731 result->new = new_select;
96450faf 2732
d62a17ae 2733 return;
fee0f4c6 2734}
2735
3f9c7369
DS
2736/*
2737 * A new route/change in bestpath of an existing route. Evaluate the path
2738 * for advertisement to the subgroup.
2739 */
3dc339cd
DA
2740void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2741 struct bgp_path_info *selected,
9bcb3eef 2742 struct bgp_dest *dest,
3dc339cd 2743 uint32_t addpath_tx_id)
d62a17ae 2744{
b54892e0 2745 const struct prefix *p;
d62a17ae 2746 struct peer *onlypeer;
2747 struct attr attr;
2748 afi_t afi;
2749 safi_t safi;
a77e2f4b
S
2750 struct bgp *bgp;
2751 bool advertise;
adbac85e 2752
9bcb3eef 2753 p = bgp_dest_get_prefix(dest);
d62a17ae 2754 afi = SUBGRP_AFI(subgrp);
2755 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2756 bgp = SUBGRP_INST(subgrp);
d62a17ae 2757 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2758 : NULL);
2759
2dbe669b
DA
2760 if (BGP_DEBUG(update, UPDATE_OUT))
2761 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2762
d62a17ae 2763 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2764 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2765 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2766 return;
d62a17ae 2767
6006b807 2768 memset(&attr, 0, sizeof(attr));
d62a17ae 2769 /* It's initialized in bgp_announce_check() */
2770
a77e2f4b
S
2771 /* Announcement to the subgroup. If the route is filtered withdraw it.
2772 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2773 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2774 * route
d62a17ae 2775 */
a77e2f4b
S
2776 advertise = bgp_check_advertise(bgp, dest);
2777
d62a17ae 2778 if (selected) {
7f7940e6 2779 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2780 NULL)) {
a77e2f4b
S
2781 /* Route is selected, if the route is already installed
2782 * in FIB, then it is advertised
2783 */
be785e35
DS
2784 if (advertise) {
2785 if (!bgp_check_withdrawal(bgp, dest))
2786 bgp_adj_out_set_subgroup(
2787 dest, subgrp, &attr, selected);
2788 else
2789 bgp_adj_out_unset_subgroup(
2790 dest, subgrp, 1, addpath_tx_id);
2791 }
a77e2f4b 2792 } else
9bcb3eef 2793 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2794 addpath_tx_id);
d62a17ae 2795 }
2796
2797 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2798 else {
9bcb3eef 2799 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2800 }
200df115 2801}
fee0f4c6 2802
3064bf43 2803/*
e1072051 2804 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2805 * This is called at the end of route processing.
3064bf43 2806 */
9bcb3eef 2807void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2808{
40381db7 2809 struct bgp_path_info *pi;
3064bf43 2810
9bcb3eef 2811 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2812 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2813 continue;
40381db7
DS
2814 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2815 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2816 }
3064bf43 2817}
2818
2819/*
2820 * Has the route changed from the RIB's perspective? This is invoked only
2821 * if the route selection returns the same best route as earlier - to
2822 * determine if we need to update zebra or not.
2823 */
9bcb3eef 2824bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2825{
4b7e6066 2826 struct bgp_path_info *mpinfo;
d62a17ae 2827
2bb9eff4
DS
2828 /* If this is multipath, check all selected paths for any nexthop
2829 * change or attribute change. Some attribute changes (e.g., community)
2830 * aren't of relevance to the RIB, but we'll update zebra to ensure
2831 * we handle the case of BGP nexthop change. This is the behavior
2832 * when the best path has an attribute change anyway.
d62a17ae 2833 */
1defdda8 2834 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2835 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2836 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2837 return true;
d62a17ae 2838
2bb9eff4
DS
2839 /*
2840 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2841 */
18ee8310
DS
2842 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2843 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2844 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2845 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2846 return true;
d62a17ae 2847 }
3064bf43 2848
d62a17ae 2849 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2850 return false;
3064bf43 2851}
2852
d62a17ae 2853struct bgp_process_queue {
2854 struct bgp *bgp;
9bcb3eef 2855 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2856#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2857 unsigned int flags;
2858 unsigned int queued;
200df115 2859};
2860
3b0c17e1 2861static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2862 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2863 struct bgp_path_info *new_select,
2864 struct bgp_path_info *old_select)
2865{
9bcb3eef 2866 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2867
2868 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2869 return;
2870
2871 if (advertise_type5_routes(bgp, afi) && new_select
2872 && is_route_injectable_into_evpn(new_select)) {
2873
2874 /* apply the route-map */
2875 if (bgp->adv_cmd_rmap[afi][safi].map) {
2876 route_map_result_t ret;
2877 struct bgp_path_info rmap_path;
2878 struct bgp_path_info_extra rmap_path_extra;
2879 struct attr dummy_attr;
2880
2881 dummy_attr = *new_select->attr;
2882
2883 /* Fill temp path_info */
9bcb3eef 2884 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2885 new_select, new_select->peer,
2886 &dummy_attr);
2887
2888 RESET_FLAG(dummy_attr.rmap_change_flags);
2889
2890 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2891 p, &rmap_path);
3b0c17e1 2892
2893 if (ret == RMAP_DENYMATCH) {
2894 bgp_attr_flush(&dummy_attr);
2895 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2896 safi);
2897 } else
2898 bgp_evpn_advertise_type5_route(
2899 bgp, p, &dummy_attr, afi, safi);
2900 } else {
2901 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2902 afi, safi);
2903 }
2904 } else if (advertise_type5_routes(bgp, afi) && old_select
2905 && is_route_injectable_into_evpn(old_select))
2906 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2907}
2908
bb2ca692
MS
2909/*
2910 * Utility to determine whether a particular path_info should use
2911 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2912 * in a path where we basically _know_ this is a BGP-LU route.
2913 */
2914static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2915{
2916 /* Certain types get imp null; so do paths where the nexthop is
2917 * not labeled.
2918 */
2919 if (new_select->sub_type == BGP_ROUTE_STATIC
2920 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2921 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2922 return true;
2923 else if (new_select->extra == NULL ||
2924 !bgp_is_valid_label(&new_select->extra->label[0]))
2925 /* TODO -- should be configurable? */
2926 return true;
2927 else
2928 return false;
2929}
2930
3103e8d2
DS
2931/*
2932 * old_select = The old best path
2933 * new_select = the new best path
2934 *
2935 * if (!old_select && new_select)
2936 * We are sending new information on.
2937 *
2938 * if (old_select && new_select) {
2939 * if (new_select != old_select)
2940 * We have a new best path send a change
2941 * else
2942 * We've received a update with new attributes that needs
2943 * to be passed on.
2944 * }
2945 *
2946 * if (old_select && !new_select)
2947 * We have no eligible route that we can announce or the rn
2948 * is being removed.
2949 */
9bcb3eef 2950static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2951 afi_t afi, safi_t safi)
d62a17ae 2952{
4b7e6066
DS
2953 struct bgp_path_info *new_select;
2954 struct bgp_path_info *old_select;
2955 struct bgp_path_info_pair old_and_new;
ddb5b488 2956 int debug = 0;
d62a17ae 2957
892fedb6 2958 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2959 if (dest)
2960 debug = bgp_debug_bestpath(dest);
b54892e0 2961 if (debug)
f4c713ae 2962 zlog_debug(
56ca3b5b 2963 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2964 __func__, dest);
f4c713ae
LB
2965 return;
2966 }
d62a17ae 2967 /* Is it end of initial update? (after startup) */
9bcb3eef 2968 if (!dest) {
e36f61b5
DS
2969 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2970 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2971
2972 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2973 FOREACH_AFI_SAFI (afi, safi) {
2974 if (bgp_fibupd_safi(safi))
2975 bgp_zebra_announce_table(bgp, afi, safi);
2976 }
d62a17ae 2977 bgp->main_peers_update_hold = 0;
2978
2979 bgp_start_routeadv(bgp);
aac24838 2980 return;
d62a17ae 2981 }
cb1faec9 2982
9bcb3eef 2983 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2984
9bcb3eef 2985 debug = bgp_debug_bestpath(dest);
b54892e0 2986 if (debug)
4378495a
DS
2987 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2988 dest, bgp->name_pretty, afi2str(afi),
2989 safi2str(safi));
ddb5b488 2990
f009ff26 2991 /* The best path calculation for the route is deferred if
2992 * BGP_NODE_SELECT_DEFER is set
2993 */
9bcb3eef 2994 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2995 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2996 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2997 return;
2998 }
2999
d62a17ae 3000 /* Best path selection. */
9bcb3eef 3001 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 3002 afi, safi);
3003 old_select = old_and_new.old;
3004 new_select = old_and_new.new;
3005
3006 /* Do we need to allocate or free labels?
3007 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
3008 * necessary to do this upon changes to best path. Exceptions:
3009 * - label index has changed -> recalculate resulting label
3010 * - path_info sub_type changed -> switch to/from implicit-null
3011 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 3012 */
318cac96 3013 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 3014 if (new_select) {
3015 if (!old_select
3016 || bgp_label_index_differs(new_select, old_select)
57592a53 3017 || new_select->sub_type != old_select->sub_type
9bcb3eef 3018 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
3019 /* Enforced penultimate hop popping:
3020 * implicit-null for local routes, aggregate
3021 * and redistributed routes
3022 */
bb2ca692 3023 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 3024 if (CHECK_FLAG(
9bcb3eef 3025 dest->flags,
992dd67e
PR
3026 BGP_NODE_REGISTERED_FOR_LABEL)
3027 || CHECK_FLAG(
3028 dest->flags,
3029 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 3030 bgp_unregister_for_label(dest);
67f67ba4
DA
3031 dest->local_label = mpls_lse_encode(
3032 MPLS_LABEL_IMPLICIT_NULL, 0, 0,
3033 1);
9bcb3eef 3034 bgp_set_valid_label(&dest->local_label);
d62a17ae 3035 } else
9bcb3eef
DS
3036 bgp_register_for_label(dest,
3037 new_select);
d62a17ae 3038 }
9bcb3eef 3039 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
3040 BGP_NODE_REGISTERED_FOR_LABEL)
3041 || CHECK_FLAG(dest->flags,
3042 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3043 bgp_unregister_for_label(dest);
318cac96 3044 }
992dd67e
PR
3045 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
3046 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 3047 bgp_unregister_for_label(dest);
d62a17ae 3048 }
cd1964ff 3049
b54892e0 3050 if (debug)
ddb5b488 3051 zlog_debug(
4378495a
DS
3052 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
3053 __func__, dest, bgp->name_pretty, afi2str(afi),
3054 safi2str(safi), old_select, new_select);
ddb5b488 3055
d62a17ae 3056 /* If best route remains the same and this is not due to user-initiated
3057 * clear, see exactly what needs to be done.
3058 */
d62a17ae 3059 if (old_select && old_select == new_select
9bcb3eef 3060 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 3061 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 3062 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 3063 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 3064#ifdef ENABLE_BGP_VNC
d62a17ae 3065 vnc_import_bgp_add_route(bgp, p, old_select);
3066 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 3067#endif
bb744275 3068 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
3069 && !bgp_option_check(BGP_OPT_NO_FIB)) {
3070
be785e35
DS
3071 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3072 && new_select->sub_type == BGP_ROUTE_NORMAL)
3073 SET_FLAG(dest->flags,
3074 BGP_NODE_FIB_INSTALL_PENDING);
3075
ddb5b488
PZ
3076 if (new_select->type == ZEBRA_ROUTE_BGP
3077 && (new_select->sub_type == BGP_ROUTE_NORMAL
3078 || new_select->sub_type
3079 == BGP_ROUTE_IMPORTED))
3080
9bcb3eef 3081 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3082 bgp, afi, safi);
3083 }
d62a17ae 3084 }
d62a17ae 3085
3086 /* If there is a change of interest to peers, reannounce the
3087 * route. */
1defdda8 3088 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3089 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3090 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3091 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3092
3093 /* unicast routes must also be annouced to
3094 * labeled-unicast update-groups */
3095 if (safi == SAFI_UNICAST)
3096 group_announce_route(bgp, afi,
9bcb3eef 3097 SAFI_LABELED_UNICAST, dest,
d62a17ae 3098 new_select);
3099
1defdda8 3100 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3101 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3102 }
fee0f4c6 3103
3b0c17e1 3104 /* advertise/withdraw type-5 routes */
3105 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3106 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3107 bgp_process_evpn_route_injection(
9bcb3eef 3108 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3109
b1875e65 3110 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3111 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3112 bgp_zebra_clear_route_change_flags(dest);
3113 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3114 return;
d62a17ae 3115 }
8ad7271d 3116
d62a17ae 3117 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3118 */
9bcb3eef 3119 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3120
3121 /* bestpath has changed; bump version */
3122 if (old_select || new_select) {
9bcb3eef 3123 bgp_bump_version(dest);
d62a17ae 3124
3125 if (!bgp->t_rmap_def_originate_eval) {
3126 bgp_lock(bgp);
3127 thread_add_timer(
3128 bm->master,
3129 update_group_refresh_default_originate_route_map,
3130 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3131 &bgp->t_rmap_def_originate_eval);
3132 }
3133 }
3f9c7369 3134
d62a17ae 3135 if (old_select)
9bcb3eef 3136 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3137 if (new_select) {
ddb5b488
PZ
3138 if (debug)
3139 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3140 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3141 bgp_path_info_unset_flag(dest, new_select,
3142 BGP_PATH_ATTR_CHANGED);
1defdda8 3143 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3144 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3145 }
338b3424 3146
49e5a4a0 3147#ifdef ENABLE_BGP_VNC
d62a17ae 3148 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3149 if (old_select != new_select) {
3150 if (old_select) {
3151 vnc_import_bgp_exterior_del_route(bgp, p,
3152 old_select);
3153 vnc_import_bgp_del_route(bgp, p, old_select);
3154 }
3155 if (new_select) {
3156 vnc_import_bgp_exterior_add_route(bgp, p,
3157 new_select);
3158 vnc_import_bgp_add_route(bgp, p, new_select);
3159 }
3160 }
3161 }
65efcfce
LB
3162#endif
3163
9bcb3eef 3164 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3165
3166 /* unicast routes must also be annouced to labeled-unicast update-groups
3167 */
3168 if (safi == SAFI_UNICAST)
9bcb3eef 3169 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3170 new_select);
3171
3172 /* FIB update. */
3173 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3174 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3175
d62a17ae 3176 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3177 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3178 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3179 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3180
be785e35
DS
3181 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3182 SET_FLAG(dest->flags,
3183 BGP_NODE_FIB_INSTALL_PENDING);
3184
2b659f33
MK
3185 /* if this is an evpn imported type-5 prefix,
3186 * we need to withdraw the route first to clear
3187 * the nh neigh and the RMAC entry.
3188 */
3189 if (old_select &&
3190 is_route_parent_evpn(old_select))
3191 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3192
9bcb3eef 3193 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3194 } else {
d62a17ae 3195 /* Withdraw the route from the kernel. */
3196 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3197 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3198 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3199 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3200
568e10ca 3201 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3202 }
718e3744 3203 }
3064bf43 3204
9bcb3eef 3205 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3206 old_select);
5424b7ba 3207
d62a17ae 3208 /* Clear any route change flags. */
9bcb3eef 3209 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3210
18ee8310 3211 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3212 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3213 bgp_path_info_reap(dest, old_select);
d62a17ae 3214
9bcb3eef 3215 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3216 return;
718e3744 3217}
3218
f009ff26 3219/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
42c93837 3220void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
f009ff26 3221{
9bcb3eef 3222 struct bgp_dest *dest;
f009ff26 3223 int cnt = 0;
3224 struct afi_safi_info *thread_info;
f009ff26 3225
56c226e7
DS
3226 if (bgp->gr_info[afi][safi].t_route_select) {
3227 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3228
3229 thread_info = THREAD_ARG(t);
3230 XFREE(MTYPE_TMP, thread_info);
fa5806c3 3231 THREAD_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3232 }
f009ff26 3233
3234 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3235 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3236 get_afi_safi_str(afi, safi, false),
26742171 3237 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3238 }
3239
3240 /* Process the route list */
6338d242 3241 for (dest = bgp_table_top(bgp->rib[afi][safi]);
067ea165
CB
3242 dest && bgp->gr_info[afi][safi].gr_deferred != 0 &&
3243 cnt < BGP_MAX_BEST_ROUTE_SELECT;
26742171
DS
3244 dest = bgp_route_next(dest)) {
3245 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3246 continue;
3247
3248 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3249 bgp->gr_info[afi][safi].gr_deferred--;
3250 bgp_process_main_one(bgp, dest, afi, safi);
3251 cnt++;
067ea165
CB
3252 }
3253 /* If iteration stopped before the entire table was traversed then the
3254 * node needs to be unlocked.
3255 */
3256 if (dest) {
3257 bgp_dest_unlock_node(dest);
3258 dest = NULL;
f009ff26 3259 }
3260
9e3b51a7 3261 /* Send EOR message when all routes are processed */
6338d242 3262 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3263 bgp_send_delayed_eor(bgp);
8c48b3b6 3264 /* Send route processing complete message to RIB */
3265 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3266 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
42c93837 3267 return;
9e3b51a7 3268 }
f009ff26 3269
3270 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3271
3272 thread_info->afi = afi;
3273 thread_info->safi = safi;
3274 thread_info->bgp = bgp;
3275
3276 /* If there are more routes to be processed, start the
3277 * selection timer
3278 */
3279 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3280 BGP_ROUTE_SELECT_DELAY,
3281 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3282}
3283
aac24838 3284static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3285{
aac24838
JB
3286 struct bgp_process_queue *pqnode = data;
3287 struct bgp *bgp = pqnode->bgp;
d62a17ae 3288 struct bgp_table *table;
9bcb3eef 3289 struct bgp_dest *dest;
aac24838
JB
3290
3291 /* eoiu marker */
3292 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3293 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3294 /* should always have dedicated wq call */
3295 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3296 return WQ_SUCCESS;
3297 }
3298
ac021f40 3299 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3300 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3301 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3302 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3303 table = bgp_dest_table(dest);
3304 /* note, new DESTs may be added as part of processing */
3305 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3306
9bcb3eef 3307 bgp_dest_unlock_node(dest);
d62a17ae 3308 bgp_table_unlock(table);
3309 }
aac24838
JB
3310
3311 return WQ_SUCCESS;
3312}
3313
3314static void bgp_processq_del(struct work_queue *wq, void *data)
3315{
3316 struct bgp_process_queue *pqnode = data;
3317
3318 bgp_unlock(pqnode->bgp);
3319
3320 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3321}
3322
b6c386bb 3323void bgp_process_queue_init(struct bgp *bgp)
200df115 3324{
b6c386bb
DS
3325 if (!bgp->process_queue) {
3326 char name[BUFSIZ];
3327
3328 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3329 bgp->process_queue = work_queue_new(bm->master, name);
3330 }
3331
3332 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3333 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3334 bgp->process_queue->spec.max_retries = 0;
3335 bgp->process_queue->spec.hold = 50;
d62a17ae 3336 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3337 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3338}
3339
cfe8d15a 3340static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3341{
3342 struct bgp_process_queue *pqnode;
3343
a4d82a8a
PZ
3344 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3345 sizeof(struct bgp_process_queue));
aac24838
JB
3346
3347 /* unlocked in bgp_processq_del */
3348 pqnode->bgp = bgp_lock(bgp);
3349 STAILQ_INIT(&pqnode->pqueue);
3350
aac24838
JB
3351 return pqnode;
3352}
3353
9bcb3eef 3354void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3355{
aac24838 3356#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3357 struct work_queue *wq = bgp->process_queue;
d62a17ae 3358 struct bgp_process_queue *pqnode;
cfe8d15a 3359 int pqnode_reuse = 0;
495f0b13 3360
d62a17ae 3361 /* already scheduled for processing? */
9bcb3eef 3362 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3363 return;
2e02b9b2 3364
f009ff26 3365 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3366 * the workqueue
3367 */
9bcb3eef 3368 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3369 if (BGP_DEBUG(update, UPDATE_OUT))
3370 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3371 dest);
f009ff26 3372 return;
3373 }
3374
46aeabed
LS
3375 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3376 if (BGP_DEBUG(update, UPDATE_OUT))
3377 zlog_debug(
3378 "Soft reconfigure table in progress for route %p",
3379 dest);
3380 return;
3381 }
3382
aac24838 3383 if (wq == NULL)
d62a17ae 3384 return;
3385
aac24838 3386 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3387 limit only if is from the same BGP view and it's not an EOIU marker
3388 */
aac24838
JB
3389 if (work_queue_item_count(wq)) {
3390 struct work_queue_item *item = work_queue_last_item(wq);
3391 pqnode = item->data;
228da428 3392
a4d82a8a
PZ
3393 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3394 || pqnode->bgp != bgp
3395 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3396 pqnode = bgp_processq_alloc(bgp);
3397 else
3398 pqnode_reuse = 1;
aac24838 3399 } else
cfe8d15a 3400 pqnode = bgp_processq_alloc(bgp);
aac24838 3401 /* all unlocked in bgp_process_wq */
9bcb3eef 3402 bgp_table_lock(bgp_dest_table(dest));
aac24838 3403
9bcb3eef
DS
3404 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3405 bgp_dest_lock_node(dest);
aac24838 3406
60466a63 3407 /* can't be enqueued twice */
9bcb3eef
DS
3408 assert(STAILQ_NEXT(dest, pq) == NULL);
3409 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3410 pqnode->queued++;
3411
cfe8d15a
LB
3412 if (!pqnode_reuse)
3413 work_queue_add(wq, pqnode);
3414
d62a17ae 3415 return;
fee0f4c6 3416}
0a486e5f 3417
d62a17ae 3418void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3419{
d62a17ae 3420 struct bgp_process_queue *pqnode;
cb1faec9 3421
b6c386bb 3422 if (bgp->process_queue == NULL)
d62a17ae 3423 return;
2e02b9b2 3424
cfe8d15a 3425 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3426
aac24838 3427 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3428 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3429}
3430
cc9f21da 3431static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3432{
d62a17ae 3433 struct peer *peer;
0a486e5f 3434
d62a17ae 3435 peer = THREAD_ARG(thread);
3436 peer->t_pmax_restart = NULL;
0a486e5f 3437
d62a17ae 3438 if (bgp_debug_neighbor_events(peer))
3439 zlog_debug(
3440 "%s Maximum-prefix restart timer expired, restore peering",
3441 peer->host);
0a486e5f 3442
a9bafa95 3443 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3444 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3445}
3446
9cbd06e0
DA
3447static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3448 safi_t safi)
3449{
3450 uint32_t count = 0;
f41b0459 3451 bool filtered = false;
9cbd06e0
DA
3452 struct bgp_dest *dest;
3453 struct bgp_adj_in *ain;
40bb2ccf 3454 struct attr attr = {};
9cbd06e0
DA
3455 struct bgp_table *table = peer->bgp->rib[afi][safi];
3456
3457 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3458 for (ain = dest->adj_in; ain; ain = ain->next) {
3459 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3460
3461 attr = *ain->attr;
9cbd06e0
DA
3462
3463 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3464 == FILTER_DENY)
f41b0459
DA
3465 filtered = true;
3466
3467 if (bgp_input_modifier(
3468 peer, rn_p, &attr, afi, safi,
3469 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3470 NULL, 0, NULL)
3471 == RMAP_DENY)
3472 filtered = true;
3473
3474 if (filtered)
9cbd06e0 3475 count++;
f41b0459 3476
d498917e 3477 bgp_attr_flush(&attr);
9cbd06e0
DA
3478 }
3479 }
3480
3481 return count;
3482}
3483
3dc339cd
DA
3484bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3485 int always)
718e3744 3486{
d62a17ae 3487 iana_afi_t pkt_afi;
5c525538 3488 iana_safi_t pkt_safi;
9cbd06e0
DA
3489 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3490 PEER_FLAG_MAX_PREFIX_FORCE))
3491 ? bgp_filtered_routes_count(peer, afi, safi)
3492 + peer->pcount[afi][safi]
3493 : peer->pcount[afi][safi];
9cabb64b 3494
d62a17ae 3495 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3496 return false;
e0701b79 3497
9cbd06e0 3498 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3499 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3500 PEER_STATUS_PREFIX_LIMIT)
3501 && !always)
3dc339cd 3502 return false;
e0701b79 3503
d62a17ae 3504 zlog_info(
f70c91dc
DA
3505 "%%MAXPFXEXCEED: No. of %s prefix received from %pBP %u exceed, limit %u",
3506 get_afi_safi_str(afi, safi, false), peer, pcount,
3507 peer->pmax[afi][safi]);
d62a17ae 3508 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3509
3510 if (CHECK_FLAG(peer->af_flags[afi][safi],
3511 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3512 return false;
d62a17ae 3513
3514 /* Convert AFI, SAFI to values for packet. */
3515 pkt_afi = afi_int2iana(afi);
3516 pkt_safi = safi_int2iana(safi);
3517 {
d7c0a89a 3518 uint8_t ndata[7];
d62a17ae 3519
3520 ndata[0] = (pkt_afi >> 8);
3521 ndata[1] = pkt_afi;
3522 ndata[2] = pkt_safi;
3523 ndata[3] = (peer->pmax[afi][safi] >> 24);
3524 ndata[4] = (peer->pmax[afi][safi] >> 16);
3525 ndata[5] = (peer->pmax[afi][safi] >> 8);
3526 ndata[6] = (peer->pmax[afi][safi]);
3527
3528 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3529 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3530 BGP_NOTIFY_CEASE_MAX_PREFIX,
3531 ndata, 7);
3532 }
3533
3534 /* Dynamic peers will just close their connection. */
3535 if (peer_dynamic_neighbor(peer))
3dc339cd 3536 return true;
d62a17ae 3537
3538 /* restart timer start */
3539 if (peer->pmax_restart[afi][safi]) {
3540 peer->v_pmax_restart =
3541 peer->pmax_restart[afi][safi] * 60;
3542
3543 if (bgp_debug_neighbor_events(peer))
3544 zlog_debug(
f70c91dc
DA
3545 "%pBP Maximum-prefix restart timer started for %d secs",
3546 peer, peer->v_pmax_restart);
d62a17ae 3547
3548 BGP_TIMER_ON(peer->t_pmax_restart,
3549 bgp_maximum_prefix_restart_timer,
3550 peer->v_pmax_restart);
3551 }
3552
3dc339cd 3553 return true;
d62a17ae 3554 } else
3555 UNSET_FLAG(peer->af_sflags[afi][safi],
3556 PEER_STATUS_PREFIX_LIMIT);
3557
b1823b69
DS
3558 if (pcount
3559 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3560 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3561 PEER_STATUS_PREFIX_THRESHOLD)
3562 && !always)
3dc339cd 3563 return false;
d62a17ae 3564
3565 zlog_info(
f70c91dc
DA
3566 "%%MAXPFX: No. of %s prefix received from %pBP reaches %u, max %u",
3567 get_afi_safi_str(afi, safi, false), peer, pcount,
9cbd06e0 3568 peer->pmax[afi][safi]);
d62a17ae 3569 SET_FLAG(peer->af_sflags[afi][safi],
3570 PEER_STATUS_PREFIX_THRESHOLD);
3571 } else
3572 UNSET_FLAG(peer->af_sflags[afi][safi],
3573 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3574 return false;
718e3744 3575}
3576
b40d939b 3577/* Unconditionally remove the route from the RIB, without taking
3578 * damping into consideration (eg, because the session went down)
3579 */
9bcb3eef 3580void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3581 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3582{
f009ff26 3583
3584 struct bgp *bgp = NULL;
3585 bool delete_route = false;
3586
9bcb3eef
DS
3587 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3588 safi);
d62a17ae 3589
f009ff26 3590 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3591 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3592
f009ff26 3593 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3594 * flag
3595 */
3596 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3597 delete_route = true;
9bcb3eef 3598 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3599 delete_route = true;
f009ff26 3600 if (delete_route) {
9bcb3eef
DS
3601 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3602 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3603 bgp = pi->peer->bgp;
26742171 3604 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3605 }
3606 }
3607 }
4a11bf2c 3608
9bcb3eef
DS
3609 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3610 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3611}
3612
9bcb3eef 3613static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3614 struct peer *peer, afi_t afi, safi_t safi,
3615 struct prefix_rd *prd)
3616{
9bcb3eef 3617 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3618
d62a17ae 3619 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3620 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3621 */
b4f7f45b
IR
3622 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3623 && peer->sort == BGP_PEER_EBGP)
3624 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3625 == BGP_DAMP_SUPPRESSED) {
3626 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3627 safi);
3628 return;
d62a17ae 3629 }
3630
49e5a4a0 3631#ifdef ENABLE_BGP_VNC
d62a17ae 3632 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3633 struct bgp_dest *pdest = NULL;
d62a17ae 3634 struct bgp_table *table = NULL;
3635
9bcb3eef
DS
3636 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3637 (struct prefix *)prd);
3638 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3639 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3640
3641 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3642 peer->bgp, prd, table, p, pi);
d62a17ae 3643 }
9bcb3eef 3644 bgp_dest_unlock_node(pdest);
d62a17ae 3645 }
3646 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3647 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3648
b54892e0
DS
3649 vnc_import_bgp_del_route(peer->bgp, p, pi);
3650 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3651 }
65efcfce 3652 }
d62a17ae 3653#endif
128ea8ab 3654
d62a17ae 3655 /* If this is an EVPN route, process for un-import. */
3656 if (safi == SAFI_EVPN)
b54892e0 3657 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3658
9bcb3eef 3659 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3660}
3661
4b7e6066
DS
3662struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3663 struct peer *peer, struct attr *attr,
9bcb3eef 3664 struct bgp_dest *dest)
fb018d25 3665{
4b7e6066 3666 struct bgp_path_info *new;
fb018d25 3667
d62a17ae 3668 /* Make new BGP info. */
4b7e6066 3669 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3670 new->type = type;
3671 new->instance = instance;
3672 new->sub_type = sub_type;
3673 new->peer = peer;
3674 new->attr = attr;
3675 new->uptime = bgp_clock();
9bcb3eef 3676 new->net = dest;
d62a17ae 3677 return new;
fb018d25
DS
3678}
3679
c265ee22 3680/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3681bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3682 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3683 struct bgp_dest *dest)
d62a17ae 3684{
2dbe3fa9 3685 bool ret = false;
b099a5c8
DA
3686 bool is_bgp_static_route =
3687 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3688 : false;
d62a17ae 3689
e8442016
DS
3690 /*
3691 * Only validated for unicast and multicast currently.
3692 * Also valid for EVPN where the nexthop is an IP address.
3693 * If we are a bgp static route being checked then there is
3694 * no need to check to see if the nexthop is martian as
3695 * that it should be ok.
3696 */
3697 if (is_bgp_static_route ||
3698 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3699 return false;
d62a17ae 3700
3701 /* If NEXT_HOP is present, validate it. */
3702 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e24a6977
DA
3703 if (attr->nexthop.s_addr == INADDR_ANY ||
3704 !ipv4_unicast_valid(&attr->nexthop) ||
3705 bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3706 return true;
d62a17ae 3707 }
c265ee22 3708
d62a17ae 3709 /* If MP_NEXTHOP is present, validate it. */
3710 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3711 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3712 * it is not an IPv6 link-local address.
0355b41d
DA
3713 *
3714 * If we receive an UPDATE with nexthop length set to 32 bytes
3715 * we shouldn't discard an UPDATE if it's set to (::).
3716 * The link-local (2st) is validated along the code path later.
d62a17ae 3717 */
3718 if (attr->mp_nexthop_len) {
3719 switch (attr->mp_nexthop_len) {
3720 case BGP_ATTR_NHLEN_IPV4:
3721 case BGP_ATTR_NHLEN_VPNV4:
e24a6977
DA
3722 ret = (attr->mp_nexthop_global_in.s_addr ==
3723 INADDR_ANY ||
3724 !ipv4_unicast_valid(
3725 &attr->mp_nexthop_global_in) ||
3726 bgp_nexthop_self(bgp, afi, type, stype, attr,
3727 dest));
d62a17ae 3728 break;
3729
3730 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3731 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3732 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3733 &attr->mp_nexthop_global)
d62a17ae 3734 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3735 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3736 &attr->mp_nexthop_global)
3737 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3738 dest));
d62a17ae 3739 break;
0355b41d
DA
3740 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3741 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3742 || IN6_IS_ADDR_MULTICAST(
3743 &attr->mp_nexthop_global)
3744 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3745 dest));
0355b41d 3746 break;
d62a17ae 3747
3748 default:
3dc339cd 3749 ret = true;
d62a17ae 3750 break;
3751 }
3752 }
c265ee22 3753
d62a17ae 3754 return ret;
3755}
3756
aade37d7 3757static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3758{
3759 struct community *old;
3760 struct community *new;
3761 struct community *merge;
aade37d7 3762 struct community *no_export;
2721dd61 3763
9a706b42 3764 old = bgp_attr_get_community(attr);
aade37d7 3765 no_export = community_str2com("no-export");
2721dd61 3766
b4efa101
DA
3767 assert(no_export);
3768
2721dd61 3769 if (old) {
aade37d7 3770 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3771
3772 if (!old->refcnt)
3773 community_free(&old);
3774
3775 new = community_uniq_sort(merge);
3776 community_free(&merge);
3777 } else {
aade37d7 3778 new = community_dup(no_export);
2721dd61
DA
3779 }
3780
aade37d7 3781 community_free(&no_export);
2721dd61 3782
9a706b42 3783 bgp_attr_set_community(attr, new);
2721dd61
DA
3784}
3785
5a1ae2c2 3786int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3787 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3788 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3789 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3790 struct bgp_route_evpn *evpn)
d62a17ae 3791{
3792 int ret;
3793 int aspath_loop_count = 0;
9bcb3eef 3794 struct bgp_dest *dest;
d62a17ae 3795 struct bgp *bgp;
3796 struct attr new_attr;
3797 struct attr *attr_new;
40381db7 3798 struct bgp_path_info *pi;
4b7e6066
DS
3799 struct bgp_path_info *new;
3800 struct bgp_path_info_extra *extra;
d62a17ae 3801 const char *reason;
3802 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3803 int connected = 0;
3804 int do_loop_check = 1;
3805 int has_valid_label = 0;
7c312383 3806 afi_t nh_afi;
949b0f24 3807 uint8_t pi_type = 0;
3808 uint8_t pi_sub_type = 0;
9146341f 3809 bool force_evpn_import = false;
907707db 3810 safi_t orig_safi = safi;
a486300b 3811 bool leak_success = true;
949b0f24 3812
c7bb4f00 3813 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3814 char pfxprint[PREFIX2STR_BUFFER];
3815
3816 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3817 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3818 afi, safi, attr);
6401252f
QY
3819 }
3820
49e5a4a0 3821#ifdef ENABLE_BGP_VNC
d62a17ae 3822 int vnc_implicit_withdraw = 0;
65efcfce 3823#endif
d62a17ae 3824 int same_attr = 0;
718e3744 3825
907707db
MS
3826 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3827 if (orig_safi == SAFI_LABELED_UNICAST)
3828 safi = SAFI_UNICAST;
3829
6006b807 3830 memset(&new_attr, 0, sizeof(new_attr));
d62a17ae 3831 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3832 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3833
d62a17ae 3834 bgp = peer->bgp;
9bcb3eef 3835 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3836 /* TODO: Check to see if we can get rid of "is_valid_label" */
3837 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3838 has_valid_label = (num_labels > 0) ? 1 : 0;
3839 else
3840 has_valid_label = bgp_is_valid_label(label);
718e3744 3841
28f66de2
MS
3842 if (has_valid_label)
3843 assert(label != NULL);
3844
66ff6089
AD
3845 /* Update overlay index of the attribute */
3846 if (afi == AFI_L2VPN && evpn)
3847 memcpy(&attr->evpn_overlay, evpn,
3848 sizeof(struct bgp_route_evpn));
3849
d62a17ae 3850 /* When peer's soft reconfiguration enabled. Record input packet in
3851 Adj-RIBs-In. */
3852 if (!soft_reconfig
3853 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3854 && peer != bgp->peer_self)
9bcb3eef 3855 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3856
3857 /* Check previously received route. */
9bcb3eef 3858 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3859 if (pi->peer == peer && pi->type == type
3860 && pi->sub_type == sub_type
3861 && pi->addpath_rx_id == addpath_id)
d62a17ae 3862 break;
3863
3864 /* AS path local-as loop check. */
3865 if (peer->change_local_as) {
c4368918
DW
3866 if (peer->allowas_in[afi][safi])
3867 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3868 else if (!CHECK_FLAG(peer->flags,
3869 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3870 aspath_loop_count = 1;
3871
3872 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3873 > aspath_loop_count) {
b4d46cc9 3874 peer->stat_pfx_aspath_loop++;
692174a1 3875 reason = "as-path contains our own AS;";
d62a17ae 3876 goto filtered;
3877 }
718e3744 3878 }
718e3744 3879
d62a17ae 3880 /* If the peer is configured for "allowas-in origin" and the last ASN in
3881 * the
3882 * as-path is our ASN then we do not need to call aspath_loop_check
3883 */
3884 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3885 if (aspath_get_last_as(attr->aspath) == bgp->as)
3886 do_loop_check = 0;
3887
3888 /* AS path loop check. */
3889 if (do_loop_check) {
3890 if (aspath_loop_check(attr->aspath, bgp->as)
3891 > peer->allowas_in[afi][safi]
3892 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3893 && aspath_loop_check(attr->aspath, bgp->confed_id)
3894 > peer->allowas_in[afi][safi])) {
b4d46cc9 3895 peer->stat_pfx_aspath_loop++;
d62a17ae 3896 reason = "as-path contains our own AS;";
3897 goto filtered;
3898 }
3899 }
aac9ef6c 3900
d62a17ae 3901 /* Route reflector originator ID check. */
3902 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3903 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3904 peer->stat_pfx_originator_loop++;
d62a17ae 3905 reason = "originator is us;";
3906 goto filtered;
3907 }
718e3744 3908
d62a17ae 3909 /* Route reflector cluster ID check. */
3910 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3911 peer->stat_pfx_cluster_loop++;
d62a17ae 3912 reason = "reflected from the same cluster;";
3913 goto filtered;
3914 }
718e3744 3915
d62a17ae 3916 /* Apply incoming filter. */
907707db 3917 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3918 peer->stat_pfx_filter++;
d62a17ae 3919 reason = "filter;";
3920 goto filtered;
3921 }
718e3744 3922
a8b72dc6
DA
3923 /* RFC 8212 to prevent route leaks.
3924 * This specification intends to improve this situation by requiring the
3925 * explicit configuration of both BGP Import and Export Policies for any
3926 * External BGP (EBGP) session such as customers, peers, or
3927 * confederation boundaries for all enabled address families. Through
3928 * codification of the aforementioned requirement, operators will
3929 * benefit from consistent behavior across different BGP
3930 * implementations.
3931 */
1d3fdccf 3932 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3933 if (!bgp_inbound_policy_exists(peer,
3934 &peer->filter[afi][safi])) {
3935 reason = "inbound policy missing";
b17826b7
DS
3936 if (monotime_since(&bgp->ebgprequirespolicywarning,
3937 NULL) > FIFTEENMINUTE2USEC ||
3938 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3939 zlog_warn(
3940 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3941 monotime(&bgp->ebgprequirespolicywarning);
3942 }
a8b72dc6
DA
3943 goto filtered;
3944 }
3945
fb29348a
DA
3946 /* draft-ietf-idr-deprecate-as-set-confed-set
3947 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3948 * Eventually, This document (if approved) updates RFC 4271
3949 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3950 * and obsoletes RFC 6472.
3951 */
7f972cd8 3952 if (peer->bgp->reject_as_sets)
fb29348a
DA
3953 if (aspath_check_as_sets(attr->aspath)) {
3954 reason =
3955 "as-path contains AS_SET or AS_CONFED_SET type;";
3956 goto filtered;
3957 }
3958
6f4f49b2 3959 new_attr = *attr;
d62a17ae 3960
3961 /* Apply incoming route-map.
3962 * NB: new_attr may now contain newly allocated values from route-map
3963 * "set"
3964 * commands, so we need bgp_attr_flush in the error paths, until we
3965 * intern
3966 * the attr (which takes over the memory references) */
907707db 3967 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3968 num_labels, dest)
3969 == RMAP_DENY) {
b4d46cc9 3970 peer->stat_pfx_filter++;
d62a17ae 3971 reason = "route-map;";
3972 bgp_attr_flush(&new_attr);
3973 goto filtered;
3974 }
718e3744 3975
05864da7 3976 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3977 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3978 /* remove from RIB previous entry */
3979 bgp_zebra_withdraw(p, pi, bgp, safi);
3980 }
3981
7f323236
DW
3982 if (peer->sort == BGP_PEER_EBGP) {
3983
2721dd61
DA
3984 /* rfc7999:
3985 * A BGP speaker receiving an announcement tagged with the
3986 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3987 * NO_EXPORT community as defined in RFC1997, or a
3988 * similar community, to prevent propagation of the
3989 * prefix outside the local AS. The community to prevent
3990 * propagation SHOULD be chosen according to the operator's
3991 * routing policy.
3992 */
9a706b42
DA
3993 if (bgp_attr_get_community(&new_attr) &&
3994 community_include(bgp_attr_get_community(&new_attr),
3995 COMMUNITY_BLACKHOLE))
aade37d7 3996 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3997
a4d82a8a
PZ
3998 /* If we receive the graceful-shutdown community from an eBGP
3999 * peer we must lower local-preference */
9a706b42
DA
4000 if (bgp_attr_get_community(&new_attr) &&
4001 community_include(bgp_attr_get_community(&new_attr),
4002 COMMUNITY_GSHUT)) {
7f323236
DW
4003 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
4004 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
4005
a4d82a8a
PZ
4006 /* If graceful-shutdown is configured then add the GSHUT
4007 * community to all paths received from eBGP peers */
637e5ba4 4008 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 4009 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
4010 }
4011
949b0f24 4012 if (pi) {
4013 pi_type = pi->type;
4014 pi_sub_type = pi->sub_type;
4015 }
4016
d62a17ae 4017 /* next hop check. */
a4d82a8a 4018 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
4019 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
4020 &new_attr, dest)) {
b4d46cc9 4021 peer->stat_pfx_nh_invalid++;
d62a17ae 4022 reason = "martian or self next-hop;";
4023 bgp_attr_flush(&new_attr);
4024 goto filtered;
4025 }
718e3744 4026
5c14a191 4027 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 4028 peer->stat_pfx_nh_invalid++;
4e802e66 4029 reason = "self mac;";
4dbf2038 4030 bgp_attr_flush(&new_attr);
4e802e66
DS
4031 goto filtered;
4032 }
4033
5a78f2bc
EB
4034 if (bgp_check_role_applicability(afi, safi) &&
4035 bgp_otc_filter(peer, &new_attr)) {
d864dd9e
EB
4036 reason = "failing otc validation";
4037 bgp_attr_flush(&new_attr);
4038 goto filtered;
4039 }
a1b773e2
DS
4040 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
4041 * condition :
4042 * Suppress fib is enabled
4043 * BGP_OPT_NO_FIB is not enabled
4044 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
4045 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
4046 */
4047 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
4048 && (sub_type == BGP_ROUTE_NORMAL)
4049 && (!bgp_option_check(BGP_OPT_NO_FIB))
4050 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
4051 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
4052
9cbd06e0
DA
4053 /* If maximum prefix count is configured and current prefix
4054 * count exeed it.
4055 */
4dbf2038
IR
4056 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
4057 bgp_attr_flush(&new_attr);
9cbd06e0 4058 return -1;
4dbf2038
IR
4059 }
4060
4061 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 4062
d62a17ae 4063 /* If the update is implicit withdraw. */
40381db7
DS
4064 if (pi) {
4065 pi->uptime = bgp_clock();
4066 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 4067
9bcb3eef 4068 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4069
d62a17ae 4070 /* Same attribute comes in. */
40381db7 4071 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 4072 && same_attr
d62a17ae 4073 && (!has_valid_label
40381db7 4074 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 4075 num_labels * sizeof(mpls_label_t))
66ff6089 4076 == 0)) {
b4f7f45b
IR
4077 if (CHECK_FLAG(bgp->af_flags[afi][safi],
4078 BGP_CONFIG_DAMPENING)
d62a17ae 4079 && peer->sort == BGP_PEER_EBGP
40381db7 4080 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 4081 if (bgp_debug_update(peer, p, NULL, 1)) {
4082 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4083 afi, safi, prd, p, label,
4084 num_labels, addpath_id ? 1 : 0,
66ff6089 4085 addpath_id, evpn, pfx_buf,
a4d82a8a 4086 sizeof(pfx_buf));
f70c91dc 4087 zlog_debug("%pBP rcvd %s", peer,
d62a17ae 4088 pfx_buf);
4089 }
4090
9bcb3eef 4091 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4092 != BGP_DAMP_SUPPRESSED) {
40381db7 4093 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4094 safi);
9bcb3eef 4095 bgp_process(bgp, dest, afi, safi);
d62a17ae 4096 }
4097 } else /* Duplicate - odd */
4098 {
4099 if (bgp_debug_update(peer, p, NULL, 1)) {
4100 if (!peer->rcvd_attr_printed) {
4101 zlog_debug(
f70c91dc
DA
4102 "%pBP rcvd UPDATE w/ attr: %s",
4103 peer,
d62a17ae 4104 peer->rcvd_attr_str);
4105 peer->rcvd_attr_printed = 1;
4106 }
4107
4108 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4109 afi, safi, prd, p, label,
4110 num_labels, addpath_id ? 1 : 0,
66ff6089 4111 addpath_id, evpn, pfx_buf,
a4d82a8a 4112 sizeof(pfx_buf));
d62a17ae 4113 zlog_debug(
f70c91dc
DA
4114 "%pBP rcvd %s...duplicate ignored",
4115 peer, pfx_buf);
d62a17ae 4116 }
4117
4118 /* graceful restart STALE flag unset. */
40381db7 4119 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4120 bgp_path_info_unset_flag(
9bcb3eef
DS
4121 dest, pi, BGP_PATH_STALE);
4122 bgp_dest_set_defer_flag(dest, false);
4123 bgp_process(bgp, dest, afi, safi);
d62a17ae 4124 }
4125 }
4126
9bcb3eef 4127 bgp_dest_unlock_node(dest);
d62a17ae 4128 bgp_attr_unintern(&attr_new);
4129
4130 return 0;
4131 }
718e3744 4132
d62a17ae 4133 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4134 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4135 if (bgp_debug_update(peer, p, NULL, 1)) {
4136 bgp_debug_rdpfxpath2str(
a4d82a8a 4137 afi, safi, prd, p, label, num_labels,
66ff6089 4138 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4139 pfx_buf, sizeof(pfx_buf));
d62a17ae 4140 zlog_debug(
f70c91dc
DA
4141 "%pBP rcvd %s, flapped quicker than processing",
4142 peer, pfx_buf);
d62a17ae 4143 }
4144
9bcb3eef 4145 bgp_path_info_restore(dest, pi);
9146341f 4146
4147 /*
4148 * If the BGP_PATH_REMOVED flag is set, then EVPN
4149 * routes would have been unimported already when a
4150 * prior BGP withdraw processing happened. Such routes
4151 * need to be imported again, so flag accordingly.
4152 */
4153 force_evpn_import = true;
d62a17ae 4154 }
718e3744 4155
d62a17ae 4156 /* Received Logging. */
4157 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4158 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4159 num_labels, addpath_id ? 1 : 0,
66ff6089 4160 addpath_id, evpn, pfx_buf,
a4d82a8a 4161 sizeof(pfx_buf));
f70c91dc 4162 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4163 }
718e3744 4164
d62a17ae 4165 /* graceful restart STALE flag unset. */
f009ff26 4166 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4167 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4168 bgp_dest_set_defer_flag(dest, false);
f009ff26 4169 }
d62a17ae 4170
4171 /* The attribute is changed. */
9bcb3eef 4172 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4173
4174 /* implicit withdraw, decrement aggregate and pcount here.
4175 * only if update is accepted, they'll increment below.
4176 */
40381db7 4177 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4178
4179 /* Update bgp route dampening information. */
b4f7f45b 4180 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4181 && peer->sort == BGP_PEER_EBGP) {
4182 /* This is implicit withdraw so we should update
b4f7f45b
IR
4183 dampening
4184 information. */
40381db7 4185 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4186 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4187 }
49e5a4a0 4188#ifdef ENABLE_BGP_VNC
d62a17ae 4189 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4190 struct bgp_dest *pdest = NULL;
d62a17ae 4191 struct bgp_table *table = NULL;
4192
9bcb3eef
DS
4193 pdest = bgp_node_get(bgp->rib[afi][safi],
4194 (struct prefix *)prd);
4195 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4197
4198 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4199 bgp, prd, table, p, pi);
d62a17ae 4200 }
9bcb3eef 4201 bgp_dest_unlock_node(pdest);
d62a17ae 4202 }
4203 if ((afi == AFI_IP || afi == AFI_IP6)
4204 && (safi == SAFI_UNICAST)) {
40381db7 4205 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4206 /*
4207 * Implicit withdraw case.
4208 */
4209 ++vnc_implicit_withdraw;
40381db7
DS
4210 vnc_import_bgp_del_route(bgp, p, pi);
4211 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4212 }
4213 }
65efcfce 4214#endif
128ea8ab 4215
d62a17ae 4216 /* Special handling for EVPN update of an existing route. If the
4217 * extended community attribute has changed, we need to
4218 * un-import
4219 * the route using its existing extended community. It will be
4220 * subsequently processed for import with the new extended
4221 * community.
4222 */
6f8c9c11
PR
4223 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4224 && !same_attr) {
40381db7 4225 if ((pi->attr->flag
d62a17ae 4226 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4227 && (attr_new->flag
4228 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4229 int cmp;
4230
b53e67a3
DA
4231 cmp = ecommunity_cmp(
4232 bgp_attr_get_ecommunity(pi->attr),
4233 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4234 if (!cmp) {
4235 if (bgp_debug_update(peer, p, NULL, 1))
4236 zlog_debug(
4237 "Change in EXT-COMM, existing %s new %s",
4238 ecommunity_str(
b53e67a3
DA
4239 bgp_attr_get_ecommunity(
4240 pi->attr)),
d62a17ae 4241 ecommunity_str(
b53e67a3
DA
4242 bgp_attr_get_ecommunity(
4243 attr_new)));
6f8c9c11
PR
4244 if (safi == SAFI_EVPN)
4245 bgp_evpn_unimport_route(
4246 bgp, afi, safi, p, pi);
4247 else /* SAFI_MPLS_VPN */
4248 vpn_leak_to_vrf_withdraw(bgp,
4249 pi);
d62a17ae 4250 }
4251 }
4252 }
718e3744 4253
d62a17ae 4254 /* Update to new attribute. */
40381db7
DS
4255 bgp_attr_unintern(&pi->attr);
4256 pi->attr = attr_new;
d62a17ae 4257
4258 /* Update MPLS label */
4259 if (has_valid_label) {
40381db7 4260 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4261 if (extra->label != label) {
4262 memcpy(&extra->label, label,
dbd587da 4263 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4264 extra->num_labels = num_labels;
4265 }
b57ba6d2
MK
4266 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4267 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4268 }
718e3744 4269
e496b420
HS
4270 /* Update SRv6 SID */
4271 if (attr->srv6_l3vpn) {
4272 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4273 if (sid_diff(&extra->sid[0].sid,
4274 &attr->srv6_l3vpn->sid)) {
4275 sid_copy(&extra->sid[0].sid,
e496b420
HS
4276 &attr->srv6_l3vpn->sid);
4277 extra->num_sids = 1;
cc8f05df 4278
16f3db2d
RS
4279 extra->sid[0].loc_block_len = 0;
4280 extra->sid[0].loc_node_len = 0;
4281 extra->sid[0].func_len = 0;
4282 extra->sid[0].arg_len = 0;
ea7cd161
RS
4283 extra->sid[0].transposition_len = 0;
4284 extra->sid[0].transposition_offset = 0;
16f3db2d
RS
4285
4286 if (attr->srv6_l3vpn->loc_block_len != 0) {
4287 extra->sid[0].loc_block_len =
4288 attr->srv6_l3vpn->loc_block_len;
4289 extra->sid[0].loc_node_len =
4290 attr->srv6_l3vpn->loc_node_len;
4291 extra->sid[0].func_len =
4292 attr->srv6_l3vpn->func_len;
4293 extra->sid[0].arg_len =
4294 attr->srv6_l3vpn->arg_len;
ea7cd161 4295 extra->sid[0].transposition_len =
cc8f05df 4296 attr->srv6_l3vpn
ea7cd161
RS
4297 ->transposition_len;
4298 extra->sid[0].transposition_offset =
cc8f05df 4299 attr->srv6_l3vpn
ea7cd161
RS
4300 ->transposition_offset;
4301 }
e496b420
HS
4302 }
4303 } else if (attr->srv6_vpn) {
4304 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4305 if (sid_diff(&extra->sid[0].sid,
4306 &attr->srv6_vpn->sid)) {
4307 sid_copy(&extra->sid[0].sid,
4308 &attr->srv6_vpn->sid);
e496b420
HS
4309 extra->num_sids = 1;
4310 }
4311 }
4312
49e5a4a0 4313#ifdef ENABLE_BGP_VNC
d62a17ae 4314 if ((afi == AFI_IP || afi == AFI_IP6)
4315 && (safi == SAFI_UNICAST)) {
4316 if (vnc_implicit_withdraw) {
4317 /*
4318 * Add back the route with its new attributes
4319 * (e.g., nexthop).
4320 * The route is still selected, until the route
4321 * selection
4322 * queued by bgp_process actually runs. We have
4323 * to make this
4324 * update to the VNC side immediately to avoid
4325 * racing against
4326 * configuration changes (e.g., route-map
4327 * changes) which
4328 * trigger re-importation of the entire RIB.
4329 */
40381db7
DS
4330 vnc_import_bgp_add_route(bgp, p, pi);
4331 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4332 }
4333 }
65efcfce
LB
4334#endif
4335
d62a17ae 4336 /* Update bgp route dampening information. */
b4f7f45b 4337 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4338 && peer->sort == BGP_PEER_EBGP) {
4339 /* Now we do normal update dampening. */
9bcb3eef 4340 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4341 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4342 bgp_dest_unlock_node(dest);
d62a17ae 4343 return 0;
4344 }
4345 }
128ea8ab 4346
d62a17ae 4347 /* Nexthop reachability check - for unicast and
4348 * labeled-unicast.. */
7c312383
AD
4349 if (((afi == AFI_IP || afi == AFI_IP6)
4350 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4351 || (safi == SAFI_EVPN &&
4352 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4353 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4354 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4355 && !CHECK_FLAG(peer->flags,
4356 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4357 && !CHECK_FLAG(bgp->flags,
4358 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4359 connected = 1;
4360 else
4361 connected = 0;
4362
960035b2
PZ
4363 struct bgp *bgp_nexthop = bgp;
4364
40381db7
DS
4365 if (pi->extra && pi->extra->bgp_orig)
4366 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4367
7c312383
AD
4368 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4369
4370 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4371 safi, pi, NULL, connected,
4372 p)
a4d82a8a 4373 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4374 bgp_path_info_set_flag(dest, pi,
4375 BGP_PATH_VALID);
d62a17ae 4376 else {
4377 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4378 zlog_debug("%s(%pI4): NH unresolved",
4379 __func__,
4380 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4381 }
9bcb3eef 4382 bgp_path_info_unset_flag(dest, pi,
18ee8310 4383 BGP_PATH_VALID);
d62a17ae 4384 }
4385 } else
9bcb3eef 4386 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4387
49e5a4a0 4388#ifdef ENABLE_BGP_VNC
d62a17ae 4389 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4390 struct bgp_dest *pdest = NULL;
d62a17ae 4391 struct bgp_table *table = NULL;
4392
9bcb3eef
DS
4393 pdest = bgp_node_get(bgp->rib[afi][safi],
4394 (struct prefix *)prd);
4395 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4396 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4397
4398 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4399 bgp, prd, table, p, pi);
d62a17ae 4400 }
9bcb3eef 4401 bgp_dest_unlock_node(pdest);
d62a17ae 4402 }
4403#endif
718e3744 4404
d62a17ae 4405 /* If this is an EVPN route and some attribute has changed,
9146341f 4406 * or we are explicitly told to perform a route import, process
d62a17ae 4407 * route for import. If the extended community has changed, we
4408 * would
4409 * have done the un-import earlier and the import would result
4410 * in the
4411 * route getting injected into appropriate L2 VNIs. If it is
4412 * just
4413 * some other attribute change, the import will result in
4414 * updating
4415 * the attributes for the route in the VNI(s).
4416 */
9146341f 4417 if (safi == SAFI_EVPN &&
4418 (!same_attr || force_evpn_import) &&
7c312383 4419 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4420 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4421
4422 /* Process change. */
40381db7 4423 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4424
9bcb3eef
DS
4425 bgp_process(bgp, dest, afi, safi);
4426 bgp_dest_unlock_node(dest);
558d1fec 4427
ddb5b488
PZ
4428 if (SAFI_UNICAST == safi
4429 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4430 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4431
40381db7 4432 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4433 }
4434 if ((SAFI_MPLS_VPN == safi)
4435 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4436
a486300b 4437 leak_success = vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4438 }
4439
49e5a4a0 4440#ifdef ENABLE_BGP_VNC
d62a17ae 4441 if (SAFI_MPLS_VPN == safi) {
4442 mpls_label_t label_decoded = decode_label(label);
28070ee3 4443
d62a17ae 4444 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4445 type, sub_type, &label_decoded);
4446 }
4447 if (SAFI_ENCAP == safi) {
4448 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4449 type, sub_type, NULL);
4450 }
28070ee3 4451#endif
a486300b
PG
4452 if ((safi == SAFI_MPLS_VPN) &&
4453 !CHECK_FLAG(bgp->af_flags[afi][safi],
4454 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4455 !leak_success) {
4456 bgp_unlink_nexthop(pi);
4457 bgp_path_info_delete(dest, pi);
4458 }
d62a17ae 4459 return 0;
4460 } // End of implicit withdraw
718e3744 4461
d62a17ae 4462 /* Received Logging. */
4463 if (bgp_debug_update(peer, p, NULL, 1)) {
4464 if (!peer->rcvd_attr_printed) {
f70c91dc 4465 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4466 peer->rcvd_attr_str);
4467 peer->rcvd_attr_printed = 1;
4468 }
718e3744 4469
a4d82a8a 4470 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4471 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4472 pfx_buf, sizeof(pfx_buf));
f70c91dc 4473 zlog_debug("%pBP rcvd %s", peer, pfx_buf);
d62a17ae 4474 }
718e3744 4475
d62a17ae 4476 /* Make new BGP info. */
9bcb3eef 4477 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4478
d62a17ae 4479 /* Update MPLS label */
4480 if (has_valid_label) {
18ee8310 4481 extra = bgp_path_info_extra_get(new);
8ba71050 4482 if (extra->label != label) {
dbd587da
QY
4483 memcpy(&extra->label, label,
4484 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4485 extra->num_labels = num_labels;
4486 }
b57ba6d2
MK
4487 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4488 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4489 }
718e3744 4490
e496b420
HS
4491 /* Update SRv6 SID */
4492 if (safi == SAFI_MPLS_VPN) {
4493 extra = bgp_path_info_extra_get(new);
4494 if (attr->srv6_l3vpn) {
16f3db2d 4495 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4496 extra->num_sids = 1;
cc8f05df 4497
16f3db2d
RS
4498 extra->sid[0].loc_block_len =
4499 attr->srv6_l3vpn->loc_block_len;
4500 extra->sid[0].loc_node_len =
4501 attr->srv6_l3vpn->loc_node_len;
4502 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4503 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
ea7cd161
RS
4504 extra->sid[0].transposition_len =
4505 attr->srv6_l3vpn->transposition_len;
4506 extra->sid[0].transposition_offset =
4507 attr->srv6_l3vpn->transposition_offset;
e496b420 4508 } else if (attr->srv6_vpn) {
16f3db2d 4509 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4510 extra->num_sids = 1;
4511 }
4512 }
4513
d62a17ae 4514 /* Nexthop reachability check. */
7c312383
AD
4515 if (((afi == AFI_IP || afi == AFI_IP6)
4516 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4517 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4518 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4519 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4520 && !CHECK_FLAG(peer->flags,
4521 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4522 && !CHECK_FLAG(bgp->flags,
4523 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4524 connected = 1;
4525 else
4526 connected = 0;
4527
7c312383
AD
4528 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4529
4053e952 4530 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4531 connected, p)
a4d82a8a 4532 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4533 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4534 else {
4535 if (BGP_DEBUG(nht, NHT)) {
4536 char buf1[INET6_ADDRSTRLEN];
4537 inet_ntop(AF_INET,
4538 (const void *)&attr_new->nexthop,
4539 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4540 zlog_debug("%s(%s): NH unresolved", __func__,
4541 buf1);
d62a17ae 4542 }
9bcb3eef 4543 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4544 }
4545 } else
9bcb3eef 4546 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4547
d62a17ae 4548 /* Addpath ID */
4549 new->addpath_rx_id = addpath_id;
4550
4551 /* Increment prefix */
4552 bgp_aggregate_increment(bgp, p, new, afi, safi);
4553
4554 /* Register new BGP information. */
9bcb3eef 4555 bgp_path_info_add(dest, new);
d62a17ae 4556
4557 /* route_node_get lock */
9bcb3eef 4558 bgp_dest_unlock_node(dest);
558d1fec 4559
49e5a4a0 4560#ifdef ENABLE_BGP_VNC
d62a17ae 4561 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4562 struct bgp_dest *pdest = NULL;
d62a17ae 4563 struct bgp_table *table = NULL;
4564
9bcb3eef
DS
4565 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4566 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4567 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4568
4569 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4570 bgp, prd, table, p, new);
4571 }
9bcb3eef 4572 bgp_dest_unlock_node(pdest);
d62a17ae 4573 }
65efcfce
LB
4574#endif
4575
d62a17ae 4576 /* If this is an EVPN route, process for import. */
7c312383 4577 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4578 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4579
9bcb3eef 4580 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4581
d62a17ae 4582 /* Process change. */
9bcb3eef 4583 bgp_process(bgp, dest, afi, safi);
718e3744 4584
ddb5b488
PZ
4585 if (SAFI_UNICAST == safi
4586 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4587 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4588 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4589 }
4590 if ((SAFI_MPLS_VPN == safi)
4591 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
a486300b 4592 leak_success = vpn_leak_to_vrf_update(bgp, new);
ddb5b488 4593 }
49e5a4a0 4594#ifdef ENABLE_BGP_VNC
d62a17ae 4595 if (SAFI_MPLS_VPN == safi) {
4596 mpls_label_t label_decoded = decode_label(label);
28070ee3 4597
d62a17ae 4598 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4599 sub_type, &label_decoded);
4600 }
4601 if (SAFI_ENCAP == safi) {
4602 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4603 sub_type, NULL);
4604 }
28070ee3 4605#endif
a486300b
PG
4606 if ((safi == SAFI_MPLS_VPN) &&
4607 !CHECK_FLAG(bgp->af_flags[afi][safi],
4608 BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL) &&
4609 !leak_success) {
4610 bgp_unlink_nexthop(new);
4611 bgp_path_info_delete(dest, new);
4612 }
28070ee3 4613
d62a17ae 4614 return 0;
718e3744 4615
d62a17ae 4616/* This BGP update is filtered. Log the reason then update BGP
4617 entry. */
4618filtered:
9bcb3eef 4619 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4620
d62a17ae 4621 if (bgp_debug_update(peer, p, NULL, 1)) {
4622 if (!peer->rcvd_attr_printed) {
f70c91dc 4623 zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer,
d62a17ae 4624 peer->rcvd_attr_str);
4625 peer->rcvd_attr_printed = 1;
4626 }
718e3744 4627
a4d82a8a 4628 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4629 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4630 pfx_buf, sizeof(pfx_buf));
f70c91dc
DA
4631 zlog_debug("%pBP rcvd UPDATE about %s -- DENIED due to: %s",
4632 peer, pfx_buf, reason);
d62a17ae 4633 }
128ea8ab 4634
40381db7 4635 if (pi) {
d62a17ae 4636 /* If this is an EVPN route, un-import it as it is now filtered.
4637 */
4638 if (safi == SAFI_EVPN)
40381db7 4639 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4640
ddb5b488
PZ
4641 if (SAFI_UNICAST == safi
4642 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4643 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4644
40381db7 4645 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4646 }
4647 if ((SAFI_MPLS_VPN == safi)
4648 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4649
40381db7 4650 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4651 }
4652
9bcb3eef 4653 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4654 }
4655
9bcb3eef 4656 bgp_dest_unlock_node(dest);
558d1fec 4657
49e5a4a0 4658#ifdef ENABLE_BGP_VNC
d62a17ae 4659 /*
4660 * Filtered update is treated as an implicit withdrawal (see
4661 * bgp_rib_remove()
4662 * a few lines above)
4663 */
4664 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4665 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4666 0);
4667 }
97736e32
PZ
4668#endif
4669
d62a17ae 4670 return 0;
718e3744 4671}
4672
26a3ffd6 4673int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4674 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4675 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4676 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4677{
d62a17ae 4678 struct bgp *bgp;
4679 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4680 struct bgp_dest *dest;
40381db7 4681 struct bgp_path_info *pi;
718e3744 4682
49e5a4a0 4683#ifdef ENABLE_BGP_VNC
d62a17ae 4684 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4685 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4686 0);
4687 }
28070ee3
PZ
4688#endif
4689
d62a17ae 4690 bgp = peer->bgp;
4691
4692 /* Lookup node. */
9bcb3eef 4693 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4694
4695 /* If peer is soft reconfiguration enabled. Record input packet for
4696 * further calculation.
4697 *
4698 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4699 * routes that are filtered. This tanks out Quagga RS pretty badly due
4700 * to
4701 * the iteration over all RS clients.
4702 * Since we need to remove the entry from adj_in anyway, do that first
4703 * and
4704 * if there was no entry, we don't need to do anything more.
4705 */
4706 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4707 && peer != bgp->peer_self)
9bcb3eef 4708 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4709 peer->stat_pfx_dup_withdraw++;
4710
d62a17ae 4711 if (bgp_debug_update(peer, p, NULL, 1)) {
4712 bgp_debug_rdpfxpath2str(
a4d82a8a 4713 afi, safi, prd, p, label, num_labels,
6c995628
AD
4714 addpath_id ? 1 : 0, addpath_id, NULL,
4715 pfx_buf, sizeof(pfx_buf));
d62a17ae 4716 zlog_debug(
4717 "%s withdrawing route %s not in adj-in",
4718 peer->host, pfx_buf);
4719 }
9bcb3eef 4720 bgp_dest_unlock_node(dest);
d62a17ae 4721 return 0;
4722 }
cd808e74 4723
d62a17ae 4724 /* Lookup withdrawn route. */
9bcb3eef 4725 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4726 if (pi->peer == peer && pi->type == type
4727 && pi->sub_type == sub_type
4728 && pi->addpath_rx_id == addpath_id)
d62a17ae 4729 break;
4730
4731 /* Logging. */
4732 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4733 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4734 addpath_id ? 1 : 0, addpath_id, NULL,
4735 pfx_buf, sizeof(pfx_buf));
f70c91dc 4736 zlog_debug("%pBP rcvd UPDATE about %s -- withdrawn", peer,
d62a17ae 4737 pfx_buf);
4738 }
718e3744 4739
d62a17ae 4740 /* Withdraw specified route from routing table. */
40381db7 4741 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4742 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4743 if (SAFI_UNICAST == safi
4744 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4745 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4746 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4747 }
4748 if ((SAFI_MPLS_VPN == safi)
4749 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4750
40381db7 4751 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4752 }
4753 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4754 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4755 addpath_id ? 1 : 0, addpath_id, NULL,
4756 pfx_buf, sizeof(pfx_buf));
d62a17ae 4757 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4758 }
718e3744 4759
d62a17ae 4760 /* Unlock bgp_node_get() lock. */
9bcb3eef 4761 bgp_dest_unlock_node(dest);
d62a17ae 4762
4763 return 0;
718e3744 4764}
6b0655a2 4765
d62a17ae 4766void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4767 int withdraw)
718e3744 4768{
d62a17ae 4769 struct update_subgroup *subgrp;
4770 subgrp = peer_subgroup(peer, afi, safi);
4771 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4772}
6182d65b 4773
718e3744 4774
3f9c7369
DS
4775/*
4776 * bgp_stop_announce_route_timer
4777 */
d62a17ae 4778void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4779{
d62a17ae 4780 if (!paf->t_announce_route)
4781 return;
4782
c3aaa89a 4783 THREAD_OFF(paf->t_announce_route);
718e3744 4784}
6b0655a2 4785
3f9c7369
DS
4786/*
4787 * bgp_announce_route_timer_expired
4788 *
4789 * Callback that is invoked when the route announcement timer for a
4790 * peer_af expires.
4791 */
cc9f21da 4792static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4793{
d62a17ae 4794 struct peer_af *paf;
4795 struct peer *peer;
558d1fec 4796
d62a17ae 4797 paf = THREAD_ARG(t);
4798 peer = paf->peer;
718e3744 4799
feb17238 4800 if (!peer_established(peer))
cc9f21da 4801 return;
3f9c7369 4802
d62a17ae 4803 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4804 return;
3f9c7369 4805
d62a17ae 4806 peer_af_announce_route(paf, 1);
c5aec50b
MK
4807
4808 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4809 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4810}
4811
3f9c7369
DS
4812/*
4813 * bgp_announce_route
4814 *
4815 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4816 *
4817 * if force is true we will force an update even if the update
4818 * limiting code is attempted to kick in.
3f9c7369 4819 */
e1a32ec1 4820void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4821{
4822 struct peer_af *paf;
4823 struct update_subgroup *subgrp;
4824
4825 paf = peer_af_find(peer, afi, safi);
4826 if (!paf)
4827 return;
4828 subgrp = PAF_SUBGRP(paf);
4829
4830 /*
4831 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4832 * or a refresh has already been triggered.
4833 */
4834 if (!subgrp || paf->t_announce_route)
4835 return;
4836
e1a32ec1
DS
4837 if (force)
4838 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4839
d62a17ae 4840 /*
4841 * Start a timer to stagger/delay the announce. This serves
4842 * two purposes - announcement can potentially be combined for
4843 * multiple peers and the announcement doesn't happen in the
4844 * vty context.
4845 */
4846 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4847 (subgrp->peer_count == 1)
4848 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4849 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4850 &paf->t_announce_route);
3f9c7369
DS
4851}
4852
4853/*
4854 * Announce routes from all AF tables to a peer.
4855 *
4856 * This should ONLY be called when there is a need to refresh the
4857 * routes to the peer based on a policy change for this peer alone
4858 * or a route refresh request received from the peer.
4859 * The operation will result in splitting the peer from its existing
4860 * subgroups and putting it in new subgroups.
4861 */
d62a17ae 4862void bgp_announce_route_all(struct peer *peer)
718e3744 4863{
d62a17ae 4864 afi_t afi;
4865 safi_t safi;
4866
05c7a1cc 4867 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4868 bgp_announce_route(peer, afi, safi, false);
718e3744 4869}
6b0655a2 4870
46aeabed
LS
4871/* Flag or unflag bgp_dest to determine whether it should be treated by
4872 * bgp_soft_reconfig_table_task.
4873 * Flag if flag is true. Unflag if flag is false.
4874 */
4875static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4876{
4877 struct bgp_dest *dest;
4878 struct bgp_adj_in *ain;
4879
4880 if (!table)
4881 return;
4882
4883 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4884 for (ain = dest->adj_in; ain; ain = ain->next) {
4885 if (ain->peer != NULL)
4886 break;
4887 }
4888 if (flag && ain != NULL && ain->peer != NULL)
4889 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4890 else
4891 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4892 }
4893}
4894
4895static int bgp_soft_reconfig_table_update(struct peer *peer,
4896 struct bgp_dest *dest,
4897 struct bgp_adj_in *ain, afi_t afi,
4898 safi_t safi, struct prefix_rd *prd)
4899{
4900 struct bgp_path_info *pi;
4901 uint32_t num_labels = 0;
4902 mpls_label_t *label_pnt = NULL;
4903 struct bgp_route_evpn evpn;
4904
4905 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4906 if (pi->peer == peer)
4907 break;
4908
4909 if (pi && pi->extra)
4910 num_labels = pi->extra->num_labels;
4911 if (num_labels)
4912 label_pnt = &pi->extra->label[0];
4913 if (pi)
4914 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4915 sizeof(evpn));
4916 else
4917 memset(&evpn, 0, sizeof(evpn));
4918
4919 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4920 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4921 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4922 &evpn);
4923}
4924
d62a17ae 4925static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4926 struct bgp_table *table,
4927 struct prefix_rd *prd)
718e3744 4928{
d62a17ae 4929 int ret;
9bcb3eef 4930 struct bgp_dest *dest;
d62a17ae 4931 struct bgp_adj_in *ain;
718e3744 4932
d62a17ae 4933 if (!table)
4934 table = peer->bgp->rib[afi][safi];
718e3744 4935
9bcb3eef
DS
4936 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4937 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4938 if (ain->peer != peer)
4939 continue;
8692c506 4940
46aeabed
LS
4941 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4942 afi, safi, prd);
ea47320b
DL
4943
4944 if (ret < 0) {
9bcb3eef 4945 bgp_dest_unlock_node(dest);
ea47320b 4946 return;
d62a17ae 4947 }
4948 }
718e3744 4949}
4950
46aeabed
LS
4951/* Do soft reconfig table per bgp table.
4952 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4953 * when BGP_NODE_SOFT_RECONFIG is set,
4954 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4955 * Schedule a new thread to continue the job.
4956 * Without splitting the full job into several part,
4957 * vtysh waits for the job to finish before responding to a BGP command
4958 */
cc9f21da 4959static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4960{
4961 uint32_t iter, max_iter;
4962 int ret;
4963 struct bgp_dest *dest;
4964 struct bgp_adj_in *ain;
4965 struct peer *peer;
4966 struct bgp_table *table;
4967 struct prefix_rd *prd;
4968 struct listnode *node, *nnode;
4969
4970 table = THREAD_ARG(thread);
4971 prd = NULL;
4972
4973 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4974 if (table->soft_reconfig_init) {
4975 /* first call of the function with a new srta structure.
4976 * Don't do any treatment this time on nodes
4977 * in order vtysh to respond quickly
4978 */
4979 max_iter = 0;
4980 }
4981
4982 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4983 dest = bgp_route_next(dest)) {
4984 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4985 continue;
4986
4987 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4988
4989 for (ain = dest->adj_in; ain; ain = ain->next) {
4990 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4991 nnode, peer)) {
4992 if (ain->peer != peer)
4993 continue;
4994
4995 ret = bgp_soft_reconfig_table_update(
4996 peer, dest, ain, table->afi,
4997 table->safi, prd);
4998 iter++;
4999
5000 if (ret < 0) {
5001 bgp_dest_unlock_node(dest);
5002 listnode_delete(
5003 table->soft_reconfig_peers,
5004 peer);
5005 bgp_announce_route(peer, table->afi,
e1a32ec1 5006 table->safi, false);
46aeabed
LS
5007 if (list_isempty(
5008 table->soft_reconfig_peers)) {
5009 list_delete(
5010 &table->soft_reconfig_peers);
5011 bgp_soft_reconfig_table_flag(
5012 table, false);
cc9f21da 5013 return;
46aeabed
LS
5014 }
5015 }
5016 }
5017 }
5018 }
5019
5020 /* we're either starting the initial iteration,
5021 * or we're going to continue an ongoing iteration
5022 */
5023 if (dest || table->soft_reconfig_init) {
5024 table->soft_reconfig_init = false;
5025 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
5026 table, 0, &table->soft_reconfig_thread);
cc9f21da 5027 return;
46aeabed
LS
5028 }
5029 /* we're done, clean up the background iteration context info and
5030 schedule route annoucement
5031 */
5032 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
5033 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 5034 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
5035 }
5036
5037 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
5038}
5039
5040
5041/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
5042 * and peer.
5043 * - bgp cannot be NULL
5044 * - if table and peer are NULL, cancel all threads within the bgp instance
5045 * - if table is NULL and peer is not,
5046 * remove peer in all threads within the bgp instance
5047 * - if peer is NULL, cancel all threads matching table within the bgp instance
5048 */
5049void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
5050 const struct bgp_table *table,
5051 const struct peer *peer)
5052{
5053 struct peer *npeer;
5054 struct listnode *node, *nnode;
5055 int afi, safi;
5056 struct bgp_table *ntable;
5057
5058 if (!bgp)
5059 return;
5060
5061 FOREACH_AFI_SAFI (afi, safi) {
5062 ntable = bgp->rib[afi][safi];
5063 if (!ntable)
5064 continue;
5065 if (table && table != ntable)
5066 continue;
5067
5068 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
5069 npeer)) {
5070 if (peer && peer != npeer)
5071 continue;
5072 listnode_delete(ntable->soft_reconfig_peers, npeer);
5073 }
5074
5075 if (!ntable->soft_reconfig_peers
5076 || !list_isempty(ntable->soft_reconfig_peers))
5077 continue;
5078
5079 list_delete(&ntable->soft_reconfig_peers);
5080 bgp_soft_reconfig_table_flag(ntable, false);
fa5806c3 5081 THREAD_OFF(ntable->soft_reconfig_thread);
46aeabed
LS
5082 }
5083}
5084
d62a17ae 5085void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5086{
9bcb3eef 5087 struct bgp_dest *dest;
d62a17ae 5088 struct bgp_table *table;
46aeabed
LS
5089 struct listnode *node, *nnode;
5090 struct peer *npeer;
5091 struct peer_af *paf;
718e3744 5092
feb17238 5093 if (!peer_established(peer))
d62a17ae 5094 return;
718e3744 5095
d62a17ae 5096 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5097 && (safi != SAFI_EVPN)) {
5098 table = peer->bgp->rib[afi][safi];
5099 if (!table)
5100 return;
5101
5102 table->soft_reconfig_init = true;
5103
5104 if (!table->soft_reconfig_peers)
5105 table->soft_reconfig_peers = list_new();
5106 npeer = NULL;
5107 /* add peer to the table soft_reconfig_peers if not already
5108 * there
5109 */
5110 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5111 npeer)) {
5112 if (peer == npeer)
5113 break;
5114 }
5115 if (peer != npeer)
5116 listnode_add(table->soft_reconfig_peers, peer);
5117
5118 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5119 * on table would start back at the beginning.
5120 */
5121 bgp_soft_reconfig_table_flag(table, true);
5122
5123 if (!table->soft_reconfig_thread)
5124 thread_add_event(bm->master,
5125 bgp_soft_reconfig_table_task, table, 0,
5126 &table->soft_reconfig_thread);
5127 /* Cancel bgp_announce_route_timer_expired threads.
5128 * bgp_announce_route_timer_expired threads have been scheduled
5129 * to announce routes as soon as the soft_reconfigure process
5130 * finishes.
5131 * In this case, soft_reconfigure is also scheduled by using
5132 * a thread but is planned after the
5133 * bgp_announce_route_timer_expired threads. It means that,
5134 * without cancelling the threads, the route announcement task
5135 * would run before the soft reconfiguration one. That would
5136 * useless and would block vtysh during several seconds. Route
5137 * announcements are rescheduled as soon as the soft_reconfigure
5138 * process finishes.
5139 */
5140 paf = peer_af_find(peer, afi, safi);
5141 if (paf)
5142 bgp_stop_announce_route_timer(paf);
5143 } else
9bcb3eef
DS
5144 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5145 dest = bgp_route_next(dest)) {
5146 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5147
b54892e0
DS
5148 if (table == NULL)
5149 continue;
8692c506 5150
9bcb3eef 5151 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5152 struct prefix_rd prd;
5153
5154 prd.family = AF_UNSPEC;
5155 prd.prefixlen = 64;
5156 memcpy(&prd.val, p->u.val, 8);
5157
5158 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5159 }
718e3744 5160}
6b0655a2 5161
228da428 5162
d62a17ae 5163struct bgp_clear_node_queue {
9bcb3eef 5164 struct bgp_dest *dest;
228da428
CC
5165};
5166
d62a17ae 5167static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5168{
d62a17ae 5169 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5170 struct bgp_dest *dest = cnq->dest;
d62a17ae 5171 struct peer *peer = wq->spec.data;
40381db7 5172 struct bgp_path_info *pi;
3103e8d2 5173 struct bgp *bgp;
9bcb3eef
DS
5174 afi_t afi = bgp_dest_table(dest)->afi;
5175 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5176
9bcb3eef 5177 assert(dest && peer);
3103e8d2 5178 bgp = peer->bgp;
d62a17ae 5179
5180 /* It is possible that we have multiple paths for a prefix from a peer
5181 * if that peer is using AddPath.
5182 */
9bcb3eef 5183 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5184 if (pi->peer != peer)
ea47320b
DL
5185 continue;
5186
5187 /* graceful restart STALE flag set. */
9af52ccf
DA
5188 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5189 && peer->nsf[afi][safi])
5190 || CHECK_FLAG(peer->af_sflags[afi][safi],
5191 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5192 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5193 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5194 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5195 else {
5196 /* If this is an EVPN route, process for
5197 * un-import. */
5198 if (safi == SAFI_EVPN)
9bcb3eef
DS
5199 bgp_evpn_unimport_route(
5200 bgp, afi, safi,
5201 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5202 /* Handle withdraw for VRF route-leaking and L3VPN */
5203 if (SAFI_UNICAST == safi
5204 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5205 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5206 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5207 bgp, pi);
960035b2 5208 }
3103e8d2 5209 if (SAFI_MPLS_VPN == safi &&
960035b2 5210 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5211 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5212 }
3103e8d2 5213
9bcb3eef 5214 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5215 }
ea47320b 5216 }
d62a17ae 5217 return WQ_SUCCESS;
200df115 5218}
5219
d62a17ae 5220static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5221{
d62a17ae 5222 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5223 struct bgp_dest *dest = cnq->dest;
5224 struct bgp_table *table = bgp_dest_table(dest);
228da428 5225
9bcb3eef 5226 bgp_dest_unlock_node(dest);
d62a17ae 5227 bgp_table_unlock(table);
5228 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5229}
5230
d62a17ae 5231static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5232{
d62a17ae 5233 struct peer *peer = wq->spec.data;
64e580a7 5234
d62a17ae 5235 /* Tickle FSM to start moving again */
5236 BGP_EVENT_ADD(peer, Clearing_Completed);
5237
5238 peer_unlock(peer); /* bgp_clear_route */
200df115 5239}
718e3744 5240
d62a17ae 5241static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5242{
d62a17ae 5243 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5244
5245 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5246#undef CLEAR_QUEUE_NAME_LEN
5247
0ce1ca80 5248 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5249 peer->clear_node_queue->spec.hold = 10;
5250 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5251 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5252 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5253 peer->clear_node_queue->spec.max_retries = 0;
5254
5255 /* we only 'lock' this peer reference when the queue is actually active
5256 */
5257 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5258}
5259
d62a17ae 5260static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5261 struct bgp_table *table)
65ca75e0 5262{
9bcb3eef 5263 struct bgp_dest *dest;
b6c386bb 5264 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5265
d62a17ae 5266 if (!table)
5267 table = peer->bgp->rib[afi][safi];
dc83d712 5268
d62a17ae 5269 /* If still no table => afi/safi isn't configured at all or smth. */
5270 if (!table)
5271 return;
dc83d712 5272
9bcb3eef 5273 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5274 struct bgp_path_info *pi, *next;
d62a17ae 5275 struct bgp_adj_in *ain;
5276 struct bgp_adj_in *ain_next;
5277
5278 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5279 * queued for every clearing peer, regardless of whether it is
5280 * relevant to the peer at hand.
5281 *
5282 * Overview: There are 3 different indices which need to be
5283 * scrubbed, potentially, when a peer is removed:
5284 *
5285 * 1 peer's routes visible via the RIB (ie accepted routes)
5286 * 2 peer's routes visible by the (optional) peer's adj-in index
5287 * 3 other routes visible by the peer's adj-out index
5288 *
5289 * 3 there is no hurry in scrubbing, once the struct peer is
5290 * removed from bgp->peer, we could just GC such deleted peer's
5291 * adj-outs at our leisure.
5292 *
5293 * 1 and 2 must be 'scrubbed' in some way, at least made
5294 * invisible via RIB index before peer session is allowed to be
5295 * brought back up. So one needs to know when such a 'search' is
5296 * complete.
5297 *
5298 * Ideally:
5299 *
5300 * - there'd be a single global queue or a single RIB walker
5301 * - rather than tracking which route_nodes still need to be
5302 * examined on a peer basis, we'd track which peers still
5303 * aren't cleared
5304 *
5305 * Given that our per-peer prefix-counts now should be reliable,
5306 * this may actually be achievable. It doesn't seem to be a huge
5307 * problem at this time,
5308 *
5309 * It is possible that we have multiple paths for a prefix from
5310 * a peer
5311 * if that peer is using AddPath.
5312 */
9bcb3eef 5313 ain = dest->adj_in;
d62a17ae 5314 while (ain) {
5315 ain_next = ain->next;
5316
6a840fd9 5317 if (ain->peer == peer)
9bcb3eef 5318 bgp_adj_in_remove(dest, ain);
d62a17ae 5319
5320 ain = ain_next;
5321 }
5322
9bcb3eef 5323 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5324 next = pi->next;
5325 if (pi->peer != peer)
d62a17ae 5326 continue;
5327
5328 if (force)
9bcb3eef 5329 bgp_path_info_reap(dest, pi);
d62a17ae 5330 else {
5331 struct bgp_clear_node_queue *cnq;
5332
5333 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5334 bgp_table_lock(bgp_dest_table(dest));
5335 bgp_dest_lock_node(dest);
d62a17ae 5336 cnq = XCALLOC(
5337 MTYPE_BGP_CLEAR_NODE_QUEUE,
5338 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5339 cnq->dest = dest;
d62a17ae 5340 work_queue_add(peer->clear_node_queue, cnq);
5341 break;
5342 }
5343 }
5344 }
5345 return;
5346}
5347
5348void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5349{
9bcb3eef 5350 struct bgp_dest *dest;
d62a17ae 5351 struct bgp_table *table;
5352
5353 if (peer->clear_node_queue == NULL)
5354 bgp_clear_node_queue_init(peer);
5355
5356 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5357 * Idle until it receives a Clearing_Completed event. This protects
5358 * against peers which flap faster than we can we clear, which could
5359 * lead to:
5360 *
5361 * a) race with routes from the new session being installed before
5362 * clear_route_node visits the node (to delete the route of that
5363 * peer)
5364 * b) resource exhaustion, clear_route_node likely leads to an entry
5365 * on the process_main queue. Fast-flapping could cause that queue
5366 * to grow and grow.
5367 */
5368
5369 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5370 * the unlock will happen upon work-queue completion; other wise, the
5371 * unlock happens at the end of this function.
5372 */
5373 if (!peer->clear_node_queue->thread)
5374 peer_lock(peer);
5375
5376 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5377 bgp_clear_route_table(peer, afi, safi, NULL);
5378 else
9bcb3eef
DS
5379 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5380 dest = bgp_route_next(dest)) {
5381 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5382 if (!table)
5383 continue;
5384
5385 bgp_clear_route_table(peer, afi, safi, table);
5386 }
d62a17ae 5387
5388 /* unlock if no nodes got added to the clear-node-queue. */
5389 if (!peer->clear_node_queue->thread)
5390 peer_unlock(peer);
718e3744 5391}
d62a17ae 5392
5393void bgp_clear_route_all(struct peer *peer)
718e3744 5394{
d62a17ae 5395 afi_t afi;
5396 safi_t safi;
718e3744 5397
05c7a1cc
QY
5398 FOREACH_AFI_SAFI (afi, safi)
5399 bgp_clear_route(peer, afi, safi);
65efcfce 5400
49e5a4a0 5401#ifdef ENABLE_BGP_VNC
d62a17ae 5402 rfapiProcessPeerDown(peer);
65efcfce 5403#endif
718e3744 5404}
5405
d62a17ae 5406void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5407{
d62a17ae 5408 struct bgp_table *table;
9bcb3eef 5409 struct bgp_dest *dest;
d62a17ae 5410 struct bgp_adj_in *ain;
5411 struct bgp_adj_in *ain_next;
718e3744 5412
d62a17ae 5413 table = peer->bgp->rib[afi][safi];
718e3744 5414
d62a17ae 5415 /* It is possible that we have multiple paths for a prefix from a peer
5416 * if that peer is using AddPath.
5417 */
9bcb3eef
DS
5418 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5419 ain = dest->adj_in;
43143c8f 5420
d62a17ae 5421 while (ain) {
5422 ain_next = ain->next;
43143c8f 5423
6a840fd9 5424 if (ain->peer == peer)
9bcb3eef 5425 bgp_adj_in_remove(dest, ain);
43143c8f 5426
d62a17ae 5427 ain = ain_next;
5428 }
5429 }
718e3744 5430}
93406d87 5431
1479ed2f
DA
5432/* If any of the routes from the peer have been marked with the NO_LLGR
5433 * community, either as sent by the peer, or as the result of a configured
5434 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5435 * operation of [RFC4271].
5436 */
d62a17ae 5437void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5438{
9bcb3eef 5439 struct bgp_dest *dest;
40381db7 5440 struct bgp_path_info *pi;
d62a17ae 5441 struct bgp_table *table;
5442
9af52ccf 5443 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5444 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5445 dest = bgp_route_next(dest)) {
5446 struct bgp_dest *rm;
d62a17ae 5447
5448 /* look for neighbor in tables */
9bcb3eef 5449 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5450 if (!table)
ea47320b
DL
5451 continue;
5452
5453 for (rm = bgp_table_top(table); rm;
5454 rm = bgp_route_next(rm))
9bcb3eef 5455 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5456 pi = pi->next) {
40381db7 5457 if (pi->peer != peer)
ea47320b 5458 continue;
1479ed2f
DA
5459 if (CHECK_FLAG(
5460 peer->af_sflags[afi][safi],
5461 PEER_STATUS_LLGR_WAIT) &&
9a706b42 5462 bgp_attr_get_community(pi->attr) &&
1479ed2f 5463 !community_include(
9a706b42
DA
5464 bgp_attr_get_community(
5465 pi->attr),
1479ed2f 5466 COMMUNITY_NO_LLGR))
e3015d91 5467 continue;
40381db7 5468 if (!CHECK_FLAG(pi->flags,
1defdda8 5469 BGP_PATH_STALE))
e3015d91 5470 continue;
ea47320b 5471
641065d4
KM
5472 /*
5473 * If this is VRF leaked route
5474 * process for withdraw.
5475 */
5476 if (pi->sub_type ==
5477 BGP_ROUTE_IMPORTED &&
5478 peer->bgp->inst_type ==
5479 BGP_INSTANCE_TYPE_DEFAULT)
5480 vpn_leak_to_vrf_withdraw(
5481 peer->bgp, pi);
5482
40381db7 5483 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5484 break;
5485 }
d62a17ae 5486 }
5487 } else {
9bcb3eef
DS
5488 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5489 dest = bgp_route_next(dest))
5490 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5491 pi = pi->next) {
40381db7 5492 if (pi->peer != peer)
ea47320b 5493 continue;
1479ed2f
DA
5494 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5495 PEER_STATUS_LLGR_WAIT) &&
9a706b42
DA
5496 bgp_attr_get_community(pi->attr) &&
5497 !community_include(
5498 bgp_attr_get_community(pi->attr),
5499 COMMUNITY_NO_LLGR))
e3015d91 5500 continue;
40381db7 5501 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
e3015d91 5502 continue;
641065d4
KM
5503 if (safi == SAFI_UNICAST &&
5504 (peer->bgp->inst_type ==
5505 BGP_INSTANCE_TYPE_VRF ||
5506 peer->bgp->inst_type ==
5507 BGP_INSTANCE_TYPE_DEFAULT))
5508 vpn_leak_from_vrf_withdraw(
5509 bgp_get_default(), peer->bgp,
5510 pi);
5511
9bcb3eef 5512 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5513 break;
5514 }
d62a17ae 5515 }
93406d87 5516}
6b0655a2 5517
9af52ccf
DA
5518void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5519{
5520 struct bgp_dest *dest, *ndest;
5521 struct bgp_path_info *pi;
5522 struct bgp_table *table;
5523
5524 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5525 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5526 dest = bgp_route_next(dest)) {
5527 table = bgp_dest_get_bgp_table_info(dest);
5528 if (!table)
5529 continue;
5530
5531 for (ndest = bgp_table_top(table); ndest;
5532 ndest = bgp_route_next(ndest)) {
5533 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5534 pi = pi->next) {
5535 if (pi->peer != peer)
5536 continue;
5537
5538 if ((CHECK_FLAG(
5539 peer->af_sflags[afi][safi],
5540 PEER_STATUS_ENHANCED_REFRESH))
5541 && !CHECK_FLAG(pi->flags,
5542 BGP_PATH_STALE)
5543 && !CHECK_FLAG(
5544 pi->flags,
5545 BGP_PATH_UNUSEABLE)) {
5546 if (bgp_debug_neighbor_events(
5547 peer))
5548 zlog_debug(
5549 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5550 peer->host,
5551 afi2str(afi),
5552 safi2str(safi),
5553 bgp_dest_get_prefix(
5554 ndest));
5555
5556 bgp_path_info_set_flag(
5557 ndest, pi,
5558 BGP_PATH_STALE);
5559 }
5560 }
5561 }
5562 }
5563 } else {
5564 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5565 dest = bgp_route_next(dest)) {
5566 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5567 pi = pi->next) {
5568 if (pi->peer != peer)
5569 continue;
5570
5571 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5572 PEER_STATUS_ENHANCED_REFRESH))
5573 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5574 && !CHECK_FLAG(pi->flags,
5575 BGP_PATH_UNUSEABLE)) {
5576 if (bgp_debug_neighbor_events(peer))
5577 zlog_debug(
5578 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5579 peer->host,
5580 afi2str(afi),
5581 safi2str(safi),
5582 bgp_dest_get_prefix(
5583 dest));
5584
5585 bgp_path_info_set_flag(dest, pi,
5586 BGP_PATH_STALE);
5587 }
5588 }
5589 }
5590 }
5591}
5592
3dc339cd 5593bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5594{
e0df4c04 5595 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5596 return true;
e0df4c04 5597
9dac9fc8
DA
5598 if (peer->sort == BGP_PEER_EBGP
5599 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5600 || FILTER_LIST_OUT_NAME(filter)
5601 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5602 return true;
5603 return false;
9dac9fc8
DA
5604}
5605
3dc339cd 5606bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5607{
e0df4c04 5608 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5609 return true;
e0df4c04 5610
9dac9fc8
DA
5611 if (peer->sort == BGP_PEER_EBGP
5612 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5613 || FILTER_LIST_IN_NAME(filter)
5614 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5615 return true;
5616 return false;
9dac9fc8
DA
5617}
5618
568e10ca 5619static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5620 safi_t safi)
bb86c601 5621{
9bcb3eef 5622 struct bgp_dest *dest;
40381db7 5623 struct bgp_path_info *pi;
4b7e6066 5624 struct bgp_path_info *next;
bb86c601 5625
9bcb3eef
DS
5626 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5627 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5628 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5629
40381db7 5630 next = pi->next;
1b7bb747
CS
5631
5632 /* Unimport EVPN routes from VRFs */
5633 if (safi == SAFI_EVPN)
5634 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5635 SAFI_EVPN, p, pi);
1b7bb747 5636
40381db7
DS
5637 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5638 && pi->type == ZEBRA_ROUTE_BGP
5639 && (pi->sub_type == BGP_ROUTE_NORMAL
5640 || pi->sub_type == BGP_ROUTE_AGGREGATE
5641 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5642
d62a17ae 5643 if (bgp_fibupd_safi(safi))
b54892e0 5644 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5645 }
9514b37d 5646
9bcb3eef 5647 bgp_path_info_reap(dest, pi);
d62a17ae 5648 }
bb86c601
LB
5649}
5650
718e3744 5651/* Delete all kernel routes. */
d62a17ae 5652void bgp_cleanup_routes(struct bgp *bgp)
5653{
5654 afi_t afi;
9bcb3eef 5655 struct bgp_dest *dest;
67009e22 5656 struct bgp_table *table;
d62a17ae 5657
5658 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5659 if (afi == AFI_L2VPN)
5660 continue;
568e10ca 5661 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5662 SAFI_UNICAST);
d62a17ae 5663 /*
5664 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5665 */
5666 if (afi != AFI_L2VPN) {
5667 safi_t safi;
5668 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5669 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5670 dest = bgp_route_next(dest)) {
5671 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5672 if (table != NULL) {
5673 bgp_cleanup_table(bgp, table, safi);
5674 bgp_table_finish(&table);
9bcb3eef
DS
5675 bgp_dest_set_bgp_table_info(dest, NULL);
5676 bgp_dest_unlock_node(dest);
d62a17ae 5677 }
5678 }
5679 safi = SAFI_ENCAP;
9bcb3eef
DS
5680 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5681 dest = bgp_route_next(dest)) {
5682 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5683 if (table != NULL) {
5684 bgp_cleanup_table(bgp, table, safi);
5685 bgp_table_finish(&table);
9bcb3eef
DS
5686 bgp_dest_set_bgp_table_info(dest, NULL);
5687 bgp_dest_unlock_node(dest);
d62a17ae 5688 }
5689 }
5690 }
5691 }
9bcb3eef
DS
5692 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5693 dest = bgp_route_next(dest)) {
5694 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5695 if (table != NULL) {
5696 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5697 bgp_table_finish(&table);
9bcb3eef
DS
5698 bgp_dest_set_bgp_table_info(dest, NULL);
5699 bgp_dest_unlock_node(dest);
d62a17ae 5700 }
bb86c601 5701 }
718e3744 5702}
5703
d62a17ae 5704void bgp_reset(void)
718e3744 5705{
d62a17ae 5706 vty_reset();
5707 bgp_zclient_reset();
5708 access_list_reset();
5709 prefix_list_reset();
718e3744 5710}
6b0655a2 5711
be92fc9f 5712bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5713{
d62a17ae 5714 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5715 && CHECK_FLAG(peer->af_cap[afi][safi],
5716 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5717}
5718
718e3744 5719/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5720 value. */
d62a17ae 5721int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5722 struct bgp_nlri *packet)
5723{
d7c0a89a
QY
5724 uint8_t *pnt;
5725 uint8_t *lim;
d62a17ae 5726 struct prefix p;
5727 int psize;
5728 int ret;
5729 afi_t afi;
5730 safi_t safi;
be92fc9f 5731 bool addpath_capable;
d7c0a89a 5732 uint32_t addpath_id;
d62a17ae 5733
d62a17ae 5734 pnt = packet->nlri;
5735 lim = pnt + packet->length;
5736 afi = packet->afi;
5737 safi = packet->safi;
5738 addpath_id = 0;
be92fc9f 5739 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5740
5741 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5742 syntactic validity. If the field is syntactically incorrect,
5743 then the Error Subcode is set to Invalid Network Field. */
5744 for (; pnt < lim; pnt += psize) {
5745 /* Clear prefix structure. */
6006b807 5746 memset(&p, 0, sizeof(p));
d62a17ae 5747
be92fc9f 5748 if (addpath_capable) {
d62a17ae 5749
5750 /* When packet overflow occurs return immediately. */
761ed665 5751 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5752 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5753
a3a850a1 5754 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5755 addpath_id = ntohl(addpath_id);
d62a17ae 5756 pnt += BGP_ADDPATH_ID_LEN;
5757 }
718e3744 5758
d62a17ae 5759 /* Fetch prefix length. */
5760 p.prefixlen = *pnt++;
5761 /* afi/safi validity already verified by caller,
5762 * bgp_update_receive */
5763 p.family = afi2family(afi);
5764
5765 /* Prefix length check. */
5766 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5767 flog_err(
e50f7cfd 5768 EC_BGP_UPDATE_RCV,
14454c9f 5769 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5770 peer->host, p.prefixlen, packet->afi);
513386b5 5771 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5772 }
6b0655a2 5773
d62a17ae 5774 /* Packet size overflow check. */
5775 psize = PSIZE(p.prefixlen);
5776
5777 /* When packet overflow occur return immediately. */
5778 if (pnt + psize > lim) {
af4c2728 5779 flog_err(
e50f7cfd 5780 EC_BGP_UPDATE_RCV,
d62a17ae 5781 "%s [Error] Update packet error (prefix length %d overflows packet)",
5782 peer->host, p.prefixlen);
513386b5 5783 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5784 }
5785
5786 /* Defensive coding, double-check the psize fits in a struct
e5b71bc6
DS
5787 * prefix for the v4 and v6 afi's and unicast/multicast */
5788 if (psize > (ssize_t)sizeof(p.u.val)) {
af4c2728 5789 flog_err(
e50f7cfd 5790 EC_BGP_UPDATE_RCV,
d62a17ae 5791 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
e5b71bc6 5792 peer->host, p.prefixlen, sizeof(p.u.val));
513386b5 5793 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5794 }
5795
5796 /* Fetch prefix from NLRI packet. */
a85297a7 5797 memcpy(p.u.val, pnt, psize);
d62a17ae 5798
5799 /* Check address. */
5800 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5801 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5802 /* From RFC4271 Section 6.3:
5803 *
5804 * If a prefix in the NLRI field is semantically
5805 * incorrect
5806 * (e.g., an unexpected multicast IP address),
5807 * an error SHOULD
5808 * be logged locally, and the prefix SHOULD be
5809 * ignored.
a4d82a8a 5810 */
af4c2728 5811 flog_err(
e50f7cfd 5812 EC_BGP_UPDATE_RCV,
23d0a753
DA
5813 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5814 peer->host, &p.u.prefix4);
d62a17ae 5815 continue;
5816 }
5817 }
5818
5819 /* Check address. */
5820 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5821 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5822 flog_err(
e50f7cfd 5823 EC_BGP_UPDATE_RCV,
c0d72166
DS
5824 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5825 peer->host, &p.u.prefix6);
d62a17ae 5826
5827 continue;
5828 }
5829 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5830 flog_err(
e50f7cfd 5831 EC_BGP_UPDATE_RCV,
c0d72166
DS
5832 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5833 peer->host, &p.u.prefix6);
d62a17ae 5834
5835 continue;
5836 }
5837 }
5838
5839 /* Normal process. */
5840 if (attr)
5841 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5842 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5843 NULL, NULL, 0, 0, NULL);
d62a17ae 5844 else
5845 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5846 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5847 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5848 NULL);
d62a17ae 5849
513386b5
DA
5850 /* Do not send BGP notification twice when maximum-prefix count
5851 * overflow. */
5852 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5853 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5854
5855 /* Address family configuration mismatch. */
d62a17ae 5856 if (ret < 0)
513386b5 5857 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5858 }
5859
5860 /* Packet length consistency check. */
5861 if (pnt != lim) {
af4c2728 5862 flog_err(
e50f7cfd 5863 EC_BGP_UPDATE_RCV,
d62a17ae 5864 "%s [Error] Update packet error (prefix length mismatch with total length)",
5865 peer->host);
513386b5 5866 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5867 }
6b0655a2 5868
513386b5 5869 return BGP_NLRI_PARSE_OK;
718e3744 5870}
5871
d62a17ae 5872static struct bgp_static *bgp_static_new(void)
718e3744 5873{
d62a17ae 5874 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5875}
5876
d62a17ae 5877static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5878{
0a22ddfb 5879 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5880 route_map_counter_decrement(bgp_static->rmap.map);
5881
0a22ddfb 5882 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5883 XFREE(MTYPE_BGP_STATIC, bgp_static);
5884}
5885
5f040085 5886void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5887 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5888{
9bcb3eef 5889 struct bgp_dest *dest;
40381db7 5890 struct bgp_path_info *pi;
4b7e6066 5891 struct bgp_path_info *new;
40381db7 5892 struct bgp_path_info rmap_path;
d62a17ae 5893 struct attr attr;
5894 struct attr *attr_new;
b68885f9 5895 route_map_result_t ret;
49e5a4a0 5896#ifdef ENABLE_BGP_VNC
d62a17ae 5897 int vnc_implicit_withdraw = 0;
65efcfce 5898#endif
fee0f4c6 5899
d62a17ae 5900 assert(bgp_static);
dd8103a9 5901
9bcb3eef 5902 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5903
0f05ea43 5904 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
718e3744 5905
d62a17ae 5906 attr.nexthop = bgp_static->igpnexthop;
5907 attr.med = bgp_static->igpmetric;
5908 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5909
7226bc40
TA
5910 if (afi == AFI_IP)
5911 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
5912
d62a17ae 5913 if (bgp_static->atomic)
5914 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5915
d62a17ae 5916 /* Store label index, if required. */
5917 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5918 attr.label_index = bgp_static->label_index;
5919 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5920 }
718e3744 5921
d62a17ae 5922 /* Apply route-map. */
5923 if (bgp_static->rmap.name) {
5924 struct attr attr_tmp = attr;
80ced710 5925
6006b807 5926 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
5927 rmap_path.peer = bgp->peer_self;
5928 rmap_path.attr = &attr_tmp;
fee0f4c6 5929
d62a17ae 5930 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5931
1782514f 5932 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5933
d62a17ae 5934 bgp->peer_self->rmap_type = 0;
718e3744 5935
d62a17ae 5936 if (ret == RMAP_DENYMATCH) {
5937 /* Free uninterned attribute. */
5938 bgp_attr_flush(&attr_tmp);
718e3744 5939
d62a17ae 5940 /* Unintern original. */
5941 aspath_unintern(&attr.aspath);
5942 bgp_static_withdraw(bgp, p, afi, safi);
5943 return;
5944 }
7f323236 5945
637e5ba4 5946 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5947 bgp_attr_add_gshut_community(&attr_tmp);
5948
d62a17ae 5949 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5950 } else {
5951
637e5ba4 5952 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5953 bgp_attr_add_gshut_community(&attr);
5954
d62a17ae 5955 attr_new = bgp_attr_intern(&attr);
7f323236 5956 }
718e3744 5957
9bcb3eef 5958 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5959 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5960 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5961 break;
5962
40381db7
DS
5963 if (pi) {
5964 if (attrhash_cmp(pi->attr, attr_new)
5965 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5966 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5967 bgp_dest_unlock_node(dest);
d62a17ae 5968 bgp_attr_unintern(&attr_new);
5969 aspath_unintern(&attr.aspath);
5970 return;
5971 } else {
5972 /* The attribute is changed. */
9bcb3eef 5973 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5974
5975 /* Rewrite BGP route information. */
40381db7 5976 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5977 bgp_path_info_restore(dest, pi);
d62a17ae 5978 else
40381db7 5979 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5980#ifdef ENABLE_BGP_VNC
d62a17ae 5981 if ((afi == AFI_IP || afi == AFI_IP6)
5982 && (safi == SAFI_UNICAST)) {
40381db7 5983 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5984 /*
5985 * Implicit withdraw case.
40381db7 5986 * We have to do this before pi is
d62a17ae 5987 * changed
5988 */
5989 ++vnc_implicit_withdraw;
40381db7 5990 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5991 vnc_import_bgp_exterior_del_route(
40381db7 5992 bgp, p, pi);
d62a17ae 5993 }
5994 }
65efcfce 5995#endif
40381db7
DS
5996 bgp_attr_unintern(&pi->attr);
5997 pi->attr = attr_new;
5998 pi->uptime = bgp_clock();
49e5a4a0 5999#ifdef ENABLE_BGP_VNC
d62a17ae 6000 if ((afi == AFI_IP || afi == AFI_IP6)
6001 && (safi == SAFI_UNICAST)) {
6002 if (vnc_implicit_withdraw) {
40381db7 6003 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 6004 vnc_import_bgp_exterior_add_route(
40381db7 6005 bgp, p, pi);
d62a17ae 6006 }
6007 }
65efcfce 6008#endif
718e3744 6009
d62a17ae 6010 /* Nexthop reachability check. */
892fedb6 6011 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6012 && (safi == SAFI_UNICAST
6013 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
6014
6015 struct bgp *bgp_nexthop = bgp;
6016
40381db7
DS
6017 if (pi->extra && pi->extra->bgp_orig)
6018 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
6019
6020 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 6021 afi, safi, pi, NULL,
654a5978 6022 0, p))
9bcb3eef 6023 bgp_path_info_set_flag(dest, pi,
18ee8310 6024 BGP_PATH_VALID);
d62a17ae 6025 else {
6026 if (BGP_DEBUG(nht, NHT)) {
6027 char buf1[INET6_ADDRSTRLEN];
6028 inet_ntop(p->family,
6029 &p->u.prefix, buf1,
6030 INET6_ADDRSTRLEN);
6031 zlog_debug(
6032 "%s(%s): Route not in table, not advertising",
15569c58 6033 __func__, buf1);
d62a17ae 6034 }
18ee8310 6035 bgp_path_info_unset_flag(
9bcb3eef 6036 dest, pi, BGP_PATH_VALID);
d62a17ae 6037 }
6038 } else {
6039 /* Delete the NHT structure if any, if we're
6040 * toggling between
6041 * enabling/disabling import check. We
6042 * deregister the route
6043 * from NHT to avoid overloading NHT and the
6044 * process interaction
6045 */
40381db7 6046 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6047 bgp_path_info_set_flag(dest, pi,
6048 BGP_PATH_VALID);
d62a17ae 6049 }
6050 /* Process change. */
40381db7 6051 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6052 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6053
6054 if (SAFI_UNICAST == safi
6055 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6056 || bgp->inst_type
6057 == BGP_INSTANCE_TYPE_DEFAULT)) {
6058 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 6059 pi);
ddb5b488
PZ
6060 }
6061
9bcb3eef 6062 bgp_dest_unlock_node(dest);
d62a17ae 6063 aspath_unintern(&attr.aspath);
6064 return;
6065 }
718e3744 6066 }
718e3744 6067
d62a17ae 6068 /* Make new BGP info. */
6069 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6070 attr_new, dest);
d62a17ae 6071 /* Nexthop reachability check. */
892fedb6 6072 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 6073 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
6074 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
6075 p))
9bcb3eef 6076 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6077 else {
6078 if (BGP_DEBUG(nht, NHT)) {
6079 char buf1[INET6_ADDRSTRLEN];
6080 inet_ntop(p->family, &p->u.prefix, buf1,
6081 INET6_ADDRSTRLEN);
6082 zlog_debug(
6083 "%s(%s): Route not in table, not advertising",
15569c58 6084 __func__, buf1);
d62a17ae 6085 }
9bcb3eef 6086 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6087 }
6088 } else {
6089 /* Delete the NHT structure if any, if we're toggling between
6090 * enabling/disabling import check. We deregister the route
6091 * from NHT to avoid overloading NHT and the process interaction
6092 */
6093 bgp_unlink_nexthop(new);
6094
9bcb3eef 6095 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6096 }
078430f6 6097
d62a17ae 6098 /* Aggregate address increment. */
6099 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6100
d62a17ae 6101 /* Register new BGP information. */
9bcb3eef 6102 bgp_path_info_add(dest, new);
718e3744 6103
d62a17ae 6104 /* route_node_get lock */
9bcb3eef 6105 bgp_dest_unlock_node(dest);
d62a17ae 6106
6107 /* Process change. */
9bcb3eef 6108 bgp_process(bgp, dest, afi, safi);
d62a17ae 6109
ddb5b488
PZ
6110 if (SAFI_UNICAST == safi
6111 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6112 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6113 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6114 }
6115
d62a17ae 6116 /* Unintern original. */
6117 aspath_unintern(&attr.aspath);
718e3744 6118}
6119
5f040085 6120void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6121 safi_t safi)
718e3744 6122{
9bcb3eef 6123 struct bgp_dest *dest;
40381db7 6124 struct bgp_path_info *pi;
718e3744 6125
9bcb3eef 6126 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6127
d62a17ae 6128 /* Check selected route and self inserted route. */
9bcb3eef 6129 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6130 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6131 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6132 break;
6133
6134 /* Withdraw static BGP route from routing table. */
40381db7 6135 if (pi) {
ddb5b488
PZ
6136 if (SAFI_UNICAST == safi
6137 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6138 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6139 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6140 }
40381db7
DS
6141 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6142 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6143 bgp_path_info_delete(dest, pi);
6144 bgp_process(bgp, dest, afi, safi);
d62a17ae 6145 }
718e3744 6146
d62a17ae 6147 /* Unlock bgp_node_lookup. */
9bcb3eef 6148 bgp_dest_unlock_node(dest);
718e3744 6149}
6150
137446f9
LB
6151/*
6152 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6153 */
5f040085 6154static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6155 afi_t afi, safi_t safi,
6156 struct prefix_rd *prd)
718e3744 6157{
9bcb3eef 6158 struct bgp_dest *dest;
40381db7 6159 struct bgp_path_info *pi;
718e3744 6160
9bcb3eef 6161 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6162
d62a17ae 6163 /* Check selected route and self inserted route. */
9bcb3eef 6164 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6165 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6166 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6167 break;
718e3744 6168
d62a17ae 6169 /* Withdraw static BGP route from routing table. */
40381db7 6170 if (pi) {
49e5a4a0 6171#ifdef ENABLE_BGP_VNC
d62a17ae 6172 rfapiProcessWithdraw(
40381db7 6173 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6174 1); /* Kill, since it is an administrative change */
65efcfce 6175#endif
ddb5b488
PZ
6176 if (SAFI_MPLS_VPN == safi
6177 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6178 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6179 }
40381db7 6180 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6181 bgp_path_info_delete(dest, pi);
6182 bgp_process(bgp, dest, afi, safi);
d62a17ae 6183 }
718e3744 6184
d62a17ae 6185 /* Unlock bgp_node_lookup. */
9bcb3eef 6186 bgp_dest_unlock_node(dest);
718e3744 6187}
6188
5f040085 6189static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6190 struct bgp_static *bgp_static, afi_t afi,
6191 safi_t safi)
137446f9 6192{
9bcb3eef 6193 struct bgp_dest *dest;
4b7e6066 6194 struct bgp_path_info *new;
d62a17ae 6195 struct attr *attr_new;
6196 struct attr attr = {0};
40381db7 6197 struct bgp_path_info *pi;
49e5a4a0 6198#ifdef ENABLE_BGP_VNC
d62a17ae 6199 mpls_label_t label = 0;
65efcfce 6200#endif
d7c0a89a 6201 uint32_t num_labels = 0;
137446f9 6202
d62a17ae 6203 assert(bgp_static);
137446f9 6204
b57ba6d2
MK
6205 if (bgp_static->label != MPLS_INVALID_LABEL)
6206 num_labels = 1;
9bcb3eef
DS
6207 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6208 &bgp_static->prd);
137446f9 6209
0f05ea43 6210 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
137446f9 6211
d62a17ae 6212 attr.nexthop = bgp_static->igpnexthop;
6213 attr.med = bgp_static->igpmetric;
6214 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6215
d62a17ae 6216 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6217 || (safi == SAFI_ENCAP)) {
6218 if (afi == AFI_IP) {
6219 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6220 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6221 }
6222 }
6223 if (afi == AFI_L2VPN) {
b04c1e99
IR
6224 if (bgp_static->gatewayIp.family == AF_INET) {
6225 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6226 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6227 &bgp_static->gatewayIp.u.prefix4,
6228 IPV4_MAX_BYTELEN);
b04c1e99
IR
6229 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6230 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6231 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6232 &bgp_static->gatewayIp.u.prefix6,
6233 IPV6_MAX_BYTELEN);
b04c1e99 6234 }
0a50c248 6235 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6236 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6237 struct bgp_encap_type_vxlan bet;
6006b807 6238 memset(&bet, 0, sizeof(bet));
3714a385 6239 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6240 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6241 }
6242 if (bgp_static->router_mac) {
6243 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6244 }
6245 }
6246 /* Apply route-map. */
6247 if (bgp_static->rmap.name) {
6248 struct attr attr_tmp = attr;
40381db7 6249 struct bgp_path_info rmap_path;
b68885f9 6250 route_map_result_t ret;
137446f9 6251
40381db7
DS
6252 rmap_path.peer = bgp->peer_self;
6253 rmap_path.attr = &attr_tmp;
137446f9 6254
d62a17ae 6255 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6256
1782514f 6257 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6258
d62a17ae 6259 bgp->peer_self->rmap_type = 0;
137446f9 6260
d62a17ae 6261 if (ret == RMAP_DENYMATCH) {
6262 /* Free uninterned attribute. */
6263 bgp_attr_flush(&attr_tmp);
137446f9 6264
d62a17ae 6265 /* Unintern original. */
6266 aspath_unintern(&attr.aspath);
6267 bgp_static_withdraw_safi(bgp, p, afi, safi,
6268 &bgp_static->prd);
6269 return;
6270 }
137446f9 6271
d62a17ae 6272 attr_new = bgp_attr_intern(&attr_tmp);
6273 } else {
6274 attr_new = bgp_attr_intern(&attr);
6275 }
137446f9 6276
9bcb3eef 6277 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6278 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6279 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6280 break;
6281
40381db7 6282 if (pi) {
40381db7 6283 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6284 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6285 bgp_dest_unlock_node(dest);
d62a17ae 6286 bgp_attr_unintern(&attr_new);
6287 aspath_unintern(&attr.aspath);
6288 return;
6289 } else {
6290 /* The attribute is changed. */
9bcb3eef 6291 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6292
6293 /* Rewrite BGP route information. */
40381db7 6294 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6295 bgp_path_info_restore(dest, pi);
d62a17ae 6296 else
40381db7
DS
6297 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6298 bgp_attr_unintern(&pi->attr);
6299 pi->attr = attr_new;
6300 pi->uptime = bgp_clock();
49e5a4a0 6301#ifdef ENABLE_BGP_VNC
40381db7
DS
6302 if (pi->extra)
6303 label = decode_label(&pi->extra->label[0]);
65efcfce 6304#endif
137446f9 6305
d62a17ae 6306 /* Process change. */
40381db7 6307 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6308 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6309
6310 if (SAFI_MPLS_VPN == safi
6311 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6312 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6313 }
49e5a4a0 6314#ifdef ENABLE_BGP_VNC
40381db7
DS
6315 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6316 pi->attr, afi, safi, pi->type,
6317 pi->sub_type, &label);
65efcfce 6318#endif
9bcb3eef 6319 bgp_dest_unlock_node(dest);
d62a17ae 6320 aspath_unintern(&attr.aspath);
6321 return;
6322 }
6323 }
137446f9
LB
6324
6325
d62a17ae 6326 /* Make new BGP info. */
6327 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6328 attr_new, dest);
1defdda8 6329 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6330 bgp_path_info_extra_get(new);
b57ba6d2
MK
6331 if (num_labels) {
6332 new->extra->label[0] = bgp_static->label;
6333 new->extra->num_labels = num_labels;
6334 }
49e5a4a0 6335#ifdef ENABLE_BGP_VNC
d62a17ae 6336 label = decode_label(&bgp_static->label);
65efcfce 6337#endif
137446f9 6338
d62a17ae 6339 /* Aggregate address increment. */
6340 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6341
d62a17ae 6342 /* Register new BGP information. */
9bcb3eef 6343 bgp_path_info_add(dest, new);
d62a17ae 6344 /* route_node_get lock */
9bcb3eef 6345 bgp_dest_unlock_node(dest);
137446f9 6346
d62a17ae 6347 /* Process change. */
9bcb3eef 6348 bgp_process(bgp, dest, afi, safi);
137446f9 6349
ddb5b488
PZ
6350 if (SAFI_MPLS_VPN == safi
6351 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6352 vpn_leak_to_vrf_update(bgp, new);
6353 }
49e5a4a0 6354#ifdef ENABLE_BGP_VNC
d62a17ae 6355 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6356 safi, new->type, new->sub_type, &label);
65efcfce
LB
6357#endif
6358
d62a17ae 6359 /* Unintern original. */
6360 aspath_unintern(&attr.aspath);
137446f9
LB
6361}
6362
718e3744 6363/* Configure static BGP network. When user don't run zebra, static
6364 route should be installed as valid. */
585f1adc
IR
6365static int bgp_static_set(struct vty *vty, const char *negate,
6366 const char *ip_str, afi_t afi, safi_t safi,
6367 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6368{
585f1adc
IR
6369 VTY_DECLVAR_CONTEXT(bgp, bgp);
6370 int ret;
d62a17ae 6371 struct prefix p;
6372 struct bgp_static *bgp_static;
9bcb3eef 6373 struct bgp_dest *dest;
d7c0a89a 6374 uint8_t need_update = 0;
d62a17ae 6375
585f1adc
IR
6376 /* Convert IP prefix string to struct prefix. */
6377 ret = str2prefix(ip_str, &p);
6378 if (!ret) {
6379 vty_out(vty, "%% Malformed prefix\n");
6380 return CMD_WARNING_CONFIG_FAILED;
6381 }
6382 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6383 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6384 return CMD_WARNING_CONFIG_FAILED;
6385 }
6386
d62a17ae 6387 apply_mask(&p);
718e3744 6388
e2a86ad9 6389 if (negate) {
718e3744 6390
e2a86ad9 6391 /* Set BGP static route configuration. */
9bcb3eef 6392 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6393
9bcb3eef 6394 if (!dest) {
585f1adc
IR
6395 vty_out(vty, "%% Can't find static route specified\n");
6396 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6397 }
6398
9bcb3eef 6399 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6400
e2a86ad9
DS
6401 if ((label_index != BGP_INVALID_LABEL_INDEX)
6402 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6403 vty_out(vty,
6404 "%% label-index doesn't match static route\n");
70d9b134 6405 bgp_dest_unlock_node(dest);
585f1adc 6406 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6407 }
d62a17ae 6408
e2a86ad9
DS
6409 if ((rmap && bgp_static->rmap.name)
6410 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6411 vty_out(vty,
6412 "%% route-map name doesn't match static route\n");
70d9b134 6413 bgp_dest_unlock_node(dest);
585f1adc 6414 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6415 }
718e3744 6416
e2a86ad9
DS
6417 /* Update BGP RIB. */
6418 if (!bgp_static->backdoor)
6419 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6420
e2a86ad9
DS
6421 /* Clear configuration. */
6422 bgp_static_free(bgp_static);
9bcb3eef
DS
6423 bgp_dest_set_bgp_static_info(dest, NULL);
6424 bgp_dest_unlock_node(dest);
6425 bgp_dest_unlock_node(dest);
e2a86ad9 6426 } else {
718e3744 6427
e2a86ad9 6428 /* Set BGP static route configuration. */
9bcb3eef
DS
6429 dest = bgp_node_get(bgp->route[afi][safi], &p);
6430 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6431 if (bgp_static) {
e2a86ad9 6432 /* Configuration change. */
e2a86ad9
DS
6433 /* Label index cannot be changed. */
6434 if (bgp_static->label_index != label_index) {
585f1adc
IR
6435 vty_out(vty, "%% cannot change label-index\n");
6436 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6437 }
d62a17ae 6438
e2a86ad9 6439 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6440 if (bgp_static->valid
6441 && bgp_static->backdoor != backdoor)
e2a86ad9 6442 need_update = 1;
718e3744 6443
e2a86ad9 6444 bgp_static->backdoor = backdoor;
718e3744 6445
e2a86ad9 6446 if (rmap) {
0a22ddfb
QY
6447 XFREE(MTYPE_ROUTE_MAP_NAME,
6448 bgp_static->rmap.name);
b4897fa5 6449 route_map_counter_decrement(
6450 bgp_static->rmap.map);
e2a86ad9
DS
6451 bgp_static->rmap.name =
6452 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6453 bgp_static->rmap.map =
6454 route_map_lookup_by_name(rmap);
b4897fa5 6455 route_map_counter_increment(
6456 bgp_static->rmap.map);
e2a86ad9 6457 } else {
0a22ddfb
QY
6458 XFREE(MTYPE_ROUTE_MAP_NAME,
6459 bgp_static->rmap.name);
b4897fa5 6460 route_map_counter_decrement(
6461 bgp_static->rmap.map);
e2a86ad9
DS
6462 bgp_static->rmap.map = NULL;
6463 bgp_static->valid = 0;
6464 }
9bcb3eef 6465 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6466 } else {
6467 /* New configuration. */
6468 bgp_static = bgp_static_new();
6469 bgp_static->backdoor = backdoor;
6470 bgp_static->valid = 0;
6471 bgp_static->igpmetric = 0;
975a328e 6472 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6473 bgp_static->label_index = label_index;
718e3744 6474
e2a86ad9 6475 if (rmap) {
0a22ddfb
QY
6476 XFREE(MTYPE_ROUTE_MAP_NAME,
6477 bgp_static->rmap.name);
b4897fa5 6478 route_map_counter_decrement(
6479 bgp_static->rmap.map);
e2a86ad9
DS
6480 bgp_static->rmap.name =
6481 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6482 bgp_static->rmap.map =
6483 route_map_lookup_by_name(rmap);
b4897fa5 6484 route_map_counter_increment(
6485 bgp_static->rmap.map);
e2a86ad9 6486 }
9bcb3eef 6487 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6488 }
d62a17ae 6489
e2a86ad9
DS
6490 bgp_static->valid = 1;
6491 if (need_update)
6492 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6493
e2a86ad9
DS
6494 if (!bgp_static->backdoor)
6495 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6496 }
d62a17ae 6497
585f1adc 6498 return CMD_SUCCESS;
d62a17ae 6499}
6500
6501void bgp_static_add(struct bgp *bgp)
6502{
6503 afi_t afi;
6504 safi_t safi;
9bcb3eef
DS
6505 struct bgp_dest *dest;
6506 struct bgp_dest *rm;
d62a17ae 6507 struct bgp_table *table;
6508 struct bgp_static *bgp_static;
6509
47fc6261 6510 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6511 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6512 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6513 dest = bgp_route_next(dest)) {
6514 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6515 continue;
ea47320b 6516
05c7a1cc
QY
6517 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6518 || (safi == SAFI_EVPN)) {
9bcb3eef 6519 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6520
6521 for (rm = bgp_table_top(table); rm;
6522 rm = bgp_route_next(rm)) {
a78beeb5 6523 bgp_static =
9bcb3eef 6524 bgp_dest_get_bgp_static_info(
5a8ba9fc 6525 rm);
9bcb3eef
DS
6526 bgp_static_update_safi(
6527 bgp, bgp_dest_get_prefix(rm),
6528 bgp_static, afi, safi);
d62a17ae 6529 }
05c7a1cc 6530 } else {
5a8ba9fc 6531 bgp_static_update(
9bcb3eef
DS
6532 bgp, bgp_dest_get_prefix(dest),
6533 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6534 safi);
ea47320b 6535 }
05c7a1cc 6536 }
47fc6261 6537 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6538}
6539
718e3744 6540/* Called from bgp_delete(). Delete all static routes from the BGP
6541 instance. */
d62a17ae 6542void bgp_static_delete(struct bgp *bgp)
6543{
6544 afi_t afi;
6545 safi_t safi;
9bcb3eef
DS
6546 struct bgp_dest *dest;
6547 struct bgp_dest *rm;
d62a17ae 6548 struct bgp_table *table;
6549 struct bgp_static *bgp_static;
6550
05c7a1cc 6551 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6552 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6553 dest = bgp_route_next(dest)) {
6554 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6555 continue;
ea47320b 6556
05c7a1cc
QY
6557 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6558 || (safi == SAFI_EVPN)) {
9bcb3eef 6559 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6560
6561 for (rm = bgp_table_top(table); rm;
6562 rm = bgp_route_next(rm)) {
a78beeb5 6563 bgp_static =
9bcb3eef 6564 bgp_dest_get_bgp_static_info(
5a8ba9fc 6565 rm);
c7d14ba6
PG
6566 if (!bgp_static)
6567 continue;
6568
05c7a1cc 6569 bgp_static_withdraw_safi(
9bcb3eef 6570 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6571 AFI_IP, safi,
6572 (struct prefix_rd *)
9bcb3eef
DS
6573 bgp_dest_get_prefix(
6574 dest));
ea47320b 6575 bgp_static_free(bgp_static);
811c6797 6576 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6577 NULL);
811c6797 6578 bgp_dest_unlock_node(rm);
d62a17ae 6579 }
05c7a1cc 6580 } else {
9bcb3eef 6581 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6582 bgp_static_withdraw(bgp,
9bcb3eef 6583 bgp_dest_get_prefix(dest),
b54892e0 6584 afi, safi);
05c7a1cc 6585 bgp_static_free(bgp_static);
9bcb3eef
DS
6586 bgp_dest_set_bgp_static_info(dest, NULL);
6587 bgp_dest_unlock_node(dest);
ea47320b 6588 }
05c7a1cc 6589 }
d62a17ae 6590}
6591
6592void bgp_static_redo_import_check(struct bgp *bgp)
6593{
6594 afi_t afi;
6595 safi_t safi;
9bcb3eef
DS
6596 struct bgp_dest *dest;
6597 struct bgp_dest *rm;
d62a17ae 6598 struct bgp_table *table;
6599 struct bgp_static *bgp_static;
6600
6601 /* Use this flag to force reprocessing of the route */
892fedb6 6602 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6603 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6604 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6605 dest = bgp_route_next(dest)) {
6606 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6607 continue;
ea47320b 6608
05c7a1cc
QY
6609 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6610 || (safi == SAFI_EVPN)) {
9bcb3eef 6611 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6612
6613 for (rm = bgp_table_top(table); rm;
6614 rm = bgp_route_next(rm)) {
a78beeb5 6615 bgp_static =
9bcb3eef 6616 bgp_dest_get_bgp_static_info(
5a8ba9fc 6617 rm);
9bcb3eef
DS
6618 bgp_static_update_safi(
6619 bgp, bgp_dest_get_prefix(rm),
6620 bgp_static, afi, safi);
d62a17ae 6621 }
05c7a1cc 6622 } else {
9bcb3eef
DS
6623 bgp_static = bgp_dest_get_bgp_static_info(dest);
6624 bgp_static_update(bgp,
6625 bgp_dest_get_prefix(dest),
6626 bgp_static, afi, safi);
ea47320b 6627 }
05c7a1cc
QY
6628 }
6629 }
892fedb6 6630 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6631}
6632
6633static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6634 safi_t safi)
6635{
6636 struct bgp_table *table;
9bcb3eef 6637 struct bgp_dest *dest;
40381db7 6638 struct bgp_path_info *pi;
d62a17ae 6639
dfb6fd1d
NT
6640 /* Do not install the aggregate route if BGP is in the
6641 * process of termination.
6642 */
892fedb6
DA
6643 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6644 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6645 return;
6646
d62a17ae 6647 table = bgp->rib[afi][safi];
9bcb3eef
DS
6648 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6649 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6650 if (pi->peer == bgp->peer_self
6651 && ((pi->type == ZEBRA_ROUTE_BGP
6652 && pi->sub_type == BGP_ROUTE_STATIC)
6653 || (pi->type != ZEBRA_ROUTE_BGP
6654 && pi->sub_type
d62a17ae 6655 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6656 bgp_aggregate_decrement(
6657 bgp, bgp_dest_get_prefix(dest), pi, afi,
6658 safi);
40381db7 6659 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6660 bgp_path_info_delete(dest, pi);
6661 bgp_process(bgp, dest, afi, safi);
d62a17ae 6662 }
6663 }
6664 }
ad4cbda1 6665}
6666
6667/*
6668 * Purge all networks and redistributed routes from routing table.
6669 * Invoked upon the instance going down.
6670 */
d62a17ae 6671void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6672{
d62a17ae 6673 afi_t afi;
6674 safi_t safi;
ad4cbda1 6675
05c7a1cc
QY
6676 FOREACH_AFI_SAFI (afi, safi)
6677 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6678}
6679
137446f9
LB
6680/*
6681 * gpz 110624
6682 * Currently this is used to set static routes for VPN and ENCAP.
6683 * I think it can probably be factored with bgp_static_set.
6684 */
d62a17ae 6685int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6686 const char *ip_str, const char *rd_str,
6687 const char *label_str, const char *rmap_str,
6688 int evpn_type, const char *esi, const char *gwip,
6689 const char *ethtag, const char *routermac)
6690{
6691 VTY_DECLVAR_CONTEXT(bgp, bgp);
6692 int ret;
6693 struct prefix p;
6694 struct prefix_rd prd;
9bcb3eef
DS
6695 struct bgp_dest *pdest;
6696 struct bgp_dest *dest;
d62a17ae 6697 struct bgp_table *table;
6698 struct bgp_static *bgp_static;
6699 mpls_label_t label = MPLS_INVALID_LABEL;
6700 struct prefix gw_ip;
6701
6702 /* validate ip prefix */
6703 ret = str2prefix(ip_str, &p);
6704 if (!ret) {
6705 vty_out(vty, "%% Malformed prefix\n");
6706 return CMD_WARNING_CONFIG_FAILED;
6707 }
6708 apply_mask(&p);
6709 if ((afi == AFI_L2VPN)
6710 && (bgp_build_evpn_prefix(evpn_type,
6711 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6712 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6713 return CMD_WARNING_CONFIG_FAILED;
6714 }
718e3744 6715
d62a17ae 6716 ret = str2prefix_rd(rd_str, &prd);
6717 if (!ret) {
6718 vty_out(vty, "%% Malformed rd\n");
6719 return CMD_WARNING_CONFIG_FAILED;
6720 }
718e3744 6721
d62a17ae 6722 if (label_str) {
6723 unsigned long label_val;
6724 label_val = strtoul(label_str, NULL, 10);
6725 encode_label(label_val, &label);
6726 }
9bedbb1e 6727
d62a17ae 6728 if (safi == SAFI_EVPN) {
6729 if (esi && str2esi(esi, NULL) == 0) {
6730 vty_out(vty, "%% Malformed ESI\n");
6731 return CMD_WARNING_CONFIG_FAILED;
6732 }
6733 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6734 vty_out(vty, "%% Malformed Router MAC\n");
6735 return CMD_WARNING_CONFIG_FAILED;
6736 }
6737 if (gwip) {
6006b807 6738 memset(&gw_ip, 0, sizeof(gw_ip));
d62a17ae 6739 ret = str2prefix(gwip, &gw_ip);
6740 if (!ret) {
6741 vty_out(vty, "%% Malformed GatewayIp\n");
6742 return CMD_WARNING_CONFIG_FAILED;
6743 }
6744 if ((gw_ip.family == AF_INET
3714a385 6745 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6746 (struct prefix_evpn *)&p))
6747 || (gw_ip.family == AF_INET6
3714a385 6748 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6749 (struct prefix_evpn *)&p))) {
6750 vty_out(vty,
6751 "%% GatewayIp family differs with IP prefix\n");
6752 return CMD_WARNING_CONFIG_FAILED;
6753 }
6754 }
6755 }
9bcb3eef
DS
6756 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6757 if (!bgp_dest_has_bgp_path_info_data(pdest))
6758 bgp_dest_set_bgp_table_info(pdest,
67009e22 6759 bgp_table_init(bgp, afi, safi));
9bcb3eef 6760 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6761
9bcb3eef 6762 dest = bgp_node_get(table, &p);
d62a17ae 6763
9bcb3eef 6764 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6765 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6766 bgp_dest_unlock_node(dest);
d62a17ae 6767 } else {
6768 /* New configuration. */
6769 bgp_static = bgp_static_new();
6770 bgp_static->backdoor = 0;
6771 bgp_static->valid = 0;
6772 bgp_static->igpmetric = 0;
975a328e 6773 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6774 bgp_static->label = label;
6775 bgp_static->prd = prd;
6776
6777 if (rmap_str) {
0a22ddfb 6778 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6779 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6780 bgp_static->rmap.name =
6781 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6782 bgp_static->rmap.map =
6783 route_map_lookup_by_name(rmap_str);
b4897fa5 6784 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6785 }
718e3744 6786
d62a17ae 6787 if (safi == SAFI_EVPN) {
6788 if (esi) {
6789 bgp_static->eth_s_id =
6790 XCALLOC(MTYPE_ATTR,
0a50c248 6791 sizeof(esi_t));
d62a17ae 6792 str2esi(esi, bgp_static->eth_s_id);
6793 }
6794 if (routermac) {
6795 bgp_static->router_mac =
28328ea9 6796 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6797 (void)prefix_str2mac(routermac,
6798 bgp_static->router_mac);
d62a17ae 6799 }
6800 if (gwip)
6801 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6802 }
9bcb3eef 6803 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6804
d62a17ae 6805 bgp_static->valid = 1;
6806 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6807 }
718e3744 6808
d62a17ae 6809 return CMD_SUCCESS;
718e3744 6810}
6811
6812/* Configure static BGP network. */
d62a17ae 6813int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6814 const char *ip_str, const char *rd_str,
6815 const char *label_str, int evpn_type, const char *esi,
6816 const char *gwip, const char *ethtag)
6817{
6818 VTY_DECLVAR_CONTEXT(bgp, bgp);
6819 int ret;
6820 struct prefix p;
6821 struct prefix_rd prd;
9bcb3eef
DS
6822 struct bgp_dest *pdest;
6823 struct bgp_dest *dest;
d62a17ae 6824 struct bgp_table *table;
6825 struct bgp_static *bgp_static;
6826 mpls_label_t label = MPLS_INVALID_LABEL;
6827
6828 /* Convert IP prefix string to struct prefix. */
6829 ret = str2prefix(ip_str, &p);
6830 if (!ret) {
6831 vty_out(vty, "%% Malformed prefix\n");
6832 return CMD_WARNING_CONFIG_FAILED;
6833 }
6834 apply_mask(&p);
6835 if ((afi == AFI_L2VPN)
6836 && (bgp_build_evpn_prefix(evpn_type,
6837 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6838 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6839 return CMD_WARNING_CONFIG_FAILED;
6840 }
6841 ret = str2prefix_rd(rd_str, &prd);
6842 if (!ret) {
6843 vty_out(vty, "%% Malformed rd\n");
6844 return CMD_WARNING_CONFIG_FAILED;
6845 }
718e3744 6846
d62a17ae 6847 if (label_str) {
6848 unsigned long label_val;
6849 label_val = strtoul(label_str, NULL, 10);
6850 encode_label(label_val, &label);
6851 }
718e3744 6852
9bcb3eef
DS
6853 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6854 if (!bgp_dest_has_bgp_path_info_data(pdest))
6855 bgp_dest_set_bgp_table_info(pdest,
67009e22 6856 bgp_table_init(bgp, afi, safi));
d62a17ae 6857 else
9bcb3eef
DS
6858 bgp_dest_unlock_node(pdest);
6859 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6860
9bcb3eef 6861 dest = bgp_node_lookup(table, &p);
6b0655a2 6862
9bcb3eef 6863 if (dest) {
d62a17ae 6864 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6865
9bcb3eef 6866 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6867 bgp_static_free(bgp_static);
9bcb3eef
DS
6868 bgp_dest_set_bgp_static_info(dest, NULL);
6869 bgp_dest_unlock_node(dest);
6870 bgp_dest_unlock_node(dest);
d62a17ae 6871 } else
6872 vty_out(vty, "%% Can't find the route\n");
6873
6874 return CMD_SUCCESS;
6875}
6876
6877static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6878 const char *rmap_name)
6879{
6880 VTY_DECLVAR_CONTEXT(bgp, bgp);
6881 struct bgp_rmap *rmap;
6882
6883 rmap = &bgp->table_map[afi][safi];
6884 if (rmap_name) {
0a22ddfb 6885 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6886 route_map_counter_decrement(rmap->map);
d62a17ae 6887 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6888 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6889 route_map_counter_increment(rmap->map);
d62a17ae 6890 } else {
0a22ddfb 6891 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6892 route_map_counter_decrement(rmap->map);
d62a17ae 6893 rmap->map = NULL;
6894 }
73ac8160 6895
d62a17ae 6896 if (bgp_fibupd_safi(safi))
6897 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6898
d62a17ae 6899 return CMD_SUCCESS;
73ac8160
DS
6900}
6901
d62a17ae 6902static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6903 const char *rmap_name)
73ac8160 6904{
d62a17ae 6905 VTY_DECLVAR_CONTEXT(bgp, bgp);
6906 struct bgp_rmap *rmap;
73ac8160 6907
d62a17ae 6908 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6909 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6910 route_map_counter_decrement(rmap->map);
d62a17ae 6911 rmap->map = NULL;
73ac8160 6912
d62a17ae 6913 if (bgp_fibupd_safi(safi))
6914 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6915
d62a17ae 6916 return CMD_SUCCESS;
73ac8160
DS
6917}
6918
2b791107 6919void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6920 safi_t safi)
73ac8160 6921{
d62a17ae 6922 if (bgp->table_map[afi][safi].name) {
d62a17ae 6923 vty_out(vty, " table-map %s\n",
6924 bgp->table_map[afi][safi].name);
6925 }
73ac8160
DS
6926}
6927
73ac8160
DS
6928DEFUN (bgp_table_map,
6929 bgp_table_map_cmd,
6930 "table-map WORD",
6931 "BGP table to RIB route download filter\n"
6932 "Name of the route map\n")
6933{
d62a17ae 6934 int idx_word = 1;
6935 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6936 argv[idx_word]->arg);
73ac8160
DS
6937}
6938DEFUN (no_bgp_table_map,
6939 no_bgp_table_map_cmd,
6940 "no table-map WORD",
3a2d747c 6941 NO_STR
73ac8160
DS
6942 "BGP table to RIB route download filter\n"
6943 "Name of the route map\n")
6944{
d62a17ae 6945 int idx_word = 2;
6946 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6947 argv[idx_word]->arg);
73ac8160
DS
6948}
6949
585f1adc
IR
6950DEFPY(bgp_network,
6951 bgp_network_cmd,
6952 "[no] network \
6953 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
70dd370f 6954 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index| \
585f1adc
IR
6955 backdoor$backdoor}]",
6956 NO_STR
6957 "Specify a network to announce via BGP\n"
6958 "IPv4 prefix\n"
6959 "Network number\n"
6960 "Network mask\n"
6961 "Network mask\n"
6962 "Route-map to modify the attributes\n"
6963 "Name of the route map\n"
6964 "Label index to associate with the prefix\n"
6965 "Label index value\n"
6966 "Specify a BGP backdoor route\n")
6967{
6968 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6969
6970 if (address_str) {
6971 int ret;
718e3744 6972
e2a86ad9 6973 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6974 addr_prefix_str,
6975 sizeof(addr_prefix_str));
e2a86ad9
DS
6976 if (!ret) {
6977 vty_out(vty, "%% Inconsistent address and mask\n");
6978 return CMD_WARNING_CONFIG_FAILED;
6979 }
d62a17ae 6980 }
718e3744 6981
585f1adc
IR
6982 return bgp_static_set(
6983 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6984 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6985 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6986}
6987
585f1adc
IR
6988DEFPY(ipv6_bgp_network,
6989 ipv6_bgp_network_cmd,
6990 "[no] network X:X::X:X/M$prefix \
70dd370f 6991 [{route-map RMAP_NAME$map_name|label-index (0-1048560)$label_index}]",
585f1adc
IR
6992 NO_STR
6993 "Specify a network to announce via BGP\n"
6994 "IPv6 prefix\n"
6995 "Route-map to modify the attributes\n"
6996 "Name of the route map\n"
6997 "Label index to associate with the prefix\n"
6998 "Label index value\n")
37a87b8f 6999{
585f1adc
IR
7000 return bgp_static_set(
7001 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
7002 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
7003}
7004
d62a17ae 7005static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 7006{
d62a17ae 7007 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 7008}
7009
d62a17ae 7010static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 7011{
365ab2e7
RZ
7012 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7013 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
7014 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7015 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 7016 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
7017}
718e3744 7018
365ab2e7
RZ
7019/**
7020 * Helper function to avoid repeated code: prepare variables for a
7021 * `route_map_apply` call.
7022 *
7023 * \returns `true` on route map match, otherwise `false`.
7024 */
7025static bool aggr_suppress_map_test(struct bgp *bgp,
7026 struct bgp_aggregate *aggregate,
7027 struct bgp_path_info *pi)
7028{
7029 const struct prefix *p = bgp_dest_get_prefix(pi->net);
7030 route_map_result_t rmr = RMAP_DENYMATCH;
7031 struct bgp_path_info rmap_path = {};
7032 struct attr attr = {};
7033
7034 /* No route map entries created, just don't match. */
7035 if (aggregate->suppress_map == NULL)
7036 return false;
7037
7038 /* Call route map matching and return result. */
7039 attr.aspath = aspath_empty();
7040 rmap_path.peer = bgp->peer_self;
7041 rmap_path.attr = &attr;
7042
7043 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 7044 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
7045 bgp->peer_self->rmap_type = 0;
7046
7047 bgp_attr_flush(&attr);
afb254d7 7048 aspath_unintern(&attr.aspath);
365ab2e7
RZ
7049
7050 return rmr == RMAP_PERMITMATCH;
7051}
7052
4056a5f6
RZ
7053/** Test whether the aggregation has suppressed this path or not. */
7054static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
7055 struct bgp_path_info *pi)
7056{
7057 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
7058 return false;
7059
7060 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
7061}
7062
7063/**
7064 * Suppress this path and keep the reference.
7065 *
7066 * \returns `true` if needs processing otherwise `false`.
7067 */
7068static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
7069 struct bgp_path_info *pi)
7070{
7071 struct bgp_path_info_extra *pie;
7072
7073 /* Path is already suppressed by this aggregation. */
7074 if (aggr_suppress_exists(aggregate, pi))
7075 return false;
7076
7077 pie = bgp_path_info_extra_get(pi);
7078
7079 /* This is the first suppression, allocate memory and list it. */
7080 if (pie->aggr_suppressors == NULL)
7081 pie->aggr_suppressors = list_new();
7082
7083 listnode_add(pie->aggr_suppressors, aggregate);
7084
7085 /* Only mark for processing if suppressed. */
7086 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7087 if (BGP_DEBUG(update, UPDATE_OUT))
7088 zlog_debug("aggregate-address suppressing: %pFX",
7089 bgp_dest_get_prefix(pi->net));
7090
4056a5f6
RZ
7091 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7092 return true;
7093 }
7094
7095 return false;
7096}
7097
7098/**
7099 * Unsuppress this path and remove the reference.
7100 *
7101 * \returns `true` if needs processing otherwise `false`.
7102 */
7103static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7104 struct bgp_path_info *pi)
7105{
7106 /* Path wasn't suppressed. */
7107 if (!aggr_suppress_exists(aggregate, pi))
7108 return false;
7109
7110 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7111
7112 /* Unsuppress and free extra memory if last item. */
7113 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7114 if (BGP_DEBUG(update, UPDATE_OUT))
7115 zlog_debug("aggregate-address unsuppressing: %pFX",
7116 bgp_dest_get_prefix(pi->net));
7117
4056a5f6
RZ
7118 list_delete(&pi->extra->aggr_suppressors);
7119 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7120 return true;
7121 }
7122
7123 return false;
7124}
7125
3dc339cd
DA
7126static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7127 struct aspath *aspath,
7128 struct community *comm,
7129 struct ecommunity *ecomm,
7130 struct lcommunity *lcomm)
eaaf8adb
DS
7131{
7132 static struct aspath *ae = NULL;
7133
7134 if (!ae)
7135 ae = aspath_empty();
7136
40381db7 7137 if (!pi)
3dc339cd 7138 return false;
eaaf8adb 7139
40381db7 7140 if (origin != pi->attr->origin)
3dc339cd 7141 return false;
eaaf8adb 7142
40381db7 7143 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7144 return false;
29f7d023 7145
9a706b42 7146 if (!community_cmp(bgp_attr_get_community(pi->attr), comm))
3dc339cd 7147 return false;
eaaf8adb 7148
b53e67a3 7149 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7150 return false;
eaaf8adb 7151
1bcf3a96 7152 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7153 return false;
dd18c5a9 7154
40381db7 7155 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7156 return false;
7ce8a8e0 7157
3dc339cd 7158 return true;
eaaf8adb
DS
7159}
7160
5f040085
DS
7161static void bgp_aggregate_install(
7162 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7163 uint8_t origin, struct aspath *aspath, struct community *community,
7164 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7165 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7166{
9bcb3eef 7167 struct bgp_dest *dest;
c701010e 7168 struct bgp_table *table;
6f94b685 7169 struct bgp_path_info *pi, *orig, *new;
20894f50 7170 struct attr *attr;
c701010e
DS
7171
7172 table = bgp->rib[afi][safi];
7173
9bcb3eef 7174 dest = bgp_node_get(table, p);
eaaf8adb 7175
9bcb3eef 7176 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7177 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7178 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7179 break;
7180
6aabb15d
RZ
7181 /*
7182 * If we have paths with different MEDs, then don't install
7183 * (or uninstall) the aggregate route.
7184 */
7185 if (aggregate->match_med && aggregate->med_mismatched)
7186 goto uninstall_aggregate_route;
7187
c701010e 7188 if (aggregate->count > 0) {
eaaf8adb
DS
7189 /*
7190 * If the aggregate information has not changed
7191 * no need to re-install it again.
7192 */
6f94b685 7193 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7194 ecommunity, lcommunity)) {
9bcb3eef 7195 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7196
7197 if (aspath)
7198 aspath_free(aspath);
7199 if (community)
3c1f53de 7200 community_free(&community);
3da2cc32
DS
7201 if (ecommunity)
7202 ecommunity_free(&ecommunity);
dd18c5a9
DS
7203 if (lcommunity)
7204 lcommunity_free(&lcommunity);
eaaf8adb
DS
7205
7206 return;
7207 }
7208
7209 /*
7210 * Mark the old as unusable
7211 */
40381db7 7212 if (pi)
9bcb3eef 7213 bgp_path_info_delete(dest, pi);
eaaf8adb 7214
20894f50
DA
7215 attr = bgp_attr_aggregate_intern(
7216 bgp, origin, aspath, community, ecommunity, lcommunity,
7217 aggregate, atomic_aggregate, p);
7218
7219 if (!attr) {
7220 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7221 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7222 zlog_debug("%s: %pFX null attribute", __func__,
7223 p);
20894f50
DA
7224 return;
7225 }
7226
3da2cc32 7227 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7228 bgp->peer_self, attr, dest);
20894f50 7229
1defdda8 7230 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7231
9bcb3eef
DS
7232 bgp_path_info_add(dest, new);
7233 bgp_process(bgp, dest, afi, safi);
c701010e 7234 } else {
6aabb15d 7235 uninstall_aggregate_route:
6f94b685 7236 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7237 if (pi->peer == bgp->peer_self
7238 && pi->type == ZEBRA_ROUTE_BGP
7239 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7240 break;
7241
7242 /* Withdraw static BGP route from routing table. */
40381db7 7243 if (pi) {
9bcb3eef
DS
7244 bgp_path_info_delete(dest, pi);
7245 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7246 }
7247 }
7248
9bcb3eef 7249 bgp_dest_unlock_node(dest);
c701010e
DS
7250}
7251
6aabb15d
RZ
7252/**
7253 * Check if the current path has different MED than other known paths.
7254 *
7255 * \returns `true` if the MED matched the others else `false`.
7256 */
7257static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7258 struct bgp *bgp, struct bgp_path_info *pi)
7259{
7260 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7261
7262 /* This is the first route being analyzed. */
7263 if (!aggregate->med_initialized) {
7264 aggregate->med_initialized = true;
7265 aggregate->med_mismatched = false;
7266 aggregate->med_matched_value = cur_med;
7267 } else {
7268 /* Check if routes with different MED showed up. */
7269 if (cur_med != aggregate->med_matched_value)
7270 aggregate->med_mismatched = true;
7271 }
7272
7273 return !aggregate->med_mismatched;
7274}
7275
7276/**
7277 * Initializes and tests all routes in the aggregate address path for MED
7278 * values.
7279 *
7280 * \returns `true` if all MEDs are the same otherwise `false`.
7281 */
7282static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7283 struct bgp *bgp, const struct prefix *p,
7284 afi_t afi, safi_t safi)
7285{
7286 struct bgp_table *table = bgp->rib[afi][safi];
7287 const struct prefix *dest_p;
7288 struct bgp_dest *dest, *top;
7289 struct bgp_path_info *pi;
7290 bool med_matched = true;
7291
7292 aggregate->med_initialized = false;
7293
7294 top = bgp_node_get(table, p);
7295 for (dest = bgp_node_get(table, p); dest;
7296 dest = bgp_route_next_until(dest, top)) {
7297 dest_p = bgp_dest_get_prefix(dest);
7298 if (dest_p->prefixlen <= p->prefixlen)
7299 continue;
7300
7301 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7302 if (BGP_PATH_HOLDDOWN(pi))
7303 continue;
7304 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7305 continue;
7306 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7307 med_matched = false;
7308 break;
7309 }
7310 }
7311 if (!med_matched)
7312 break;
7313 }
7314 bgp_dest_unlock_node(top);
7315
7316 return med_matched;
7317}
7318
7319/**
7320 * Toggles the route suppression status for this aggregate address
7321 * configuration.
7322 */
4056a5f6
RZ
7323void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7324 struct bgp *bgp, const struct prefix *p,
7325 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7326{
7327 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7328 const struct prefix *dest_p;
7329 struct bgp_dest *dest, *top;
7330 struct bgp_path_info *pi;
7331 bool toggle_suppression;
7332
7333 /* We've found a different MED we must revert any suppressed routes. */
7334 top = bgp_node_get(table, p);
7335 for (dest = bgp_node_get(table, p); dest;
7336 dest = bgp_route_next_until(dest, top)) {
7337 dest_p = bgp_dest_get_prefix(dest);
7338 if (dest_p->prefixlen <= p->prefixlen)
7339 continue;
7340
7341 toggle_suppression = false;
7342 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7343 if (BGP_PATH_HOLDDOWN(pi))
7344 continue;
7345 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7346 continue;
7347
6aabb15d
RZ
7348 /* We are toggling suppression back. */
7349 if (suppress) {
6aabb15d 7350 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7351 if (aggr_suppress_path(aggregate, pi))
7352 toggle_suppression = true;
6aabb15d
RZ
7353 continue;
7354 }
7355
6aabb15d 7356 /* Install route if there is no more suppression. */
4056a5f6 7357 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7358 toggle_suppression = true;
6aabb15d
RZ
7359 }
7360
7361 if (toggle_suppression)
7362 bgp_process(bgp, dest, afi, safi);
7363 }
7364 bgp_dest_unlock_node(top);
7365}
7366
7367/**
7368 * Aggregate address MED matching incremental test: this function is called
7369 * when the initial aggregation occurred and we are only testing a single
7370 * new path.
7371 *
7372 * In addition to testing and setting the MED validity it also installs back
7373 * suppressed routes (if summary is configured).
7374 *
7375 * Must not be called in `bgp_aggregate_route`.
7376 */
7377static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7378 struct bgp *bgp, const struct prefix *p,
7379 afi_t afi, safi_t safi,
7380 struct bgp_path_info *pi, bool is_adding)
7381{
7382 /* MED matching disabled. */
7383 if (!aggregate->match_med)
7384 return;
7385
7386 /* Aggregation with different MED, nothing to do. */
7387 if (aggregate->med_mismatched)
7388 return;
7389
7390 /*
7391 * Test the current entry:
7392 *
7393 * is_adding == true: if the new entry doesn't match then we must
7394 * install all suppressed routes.
7395 *
7396 * is_adding == false: if the entry being removed was the last
7397 * unmatching entry then we can suppress all routes.
7398 */
7399 if (!is_adding) {
7400 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7401 && aggregate->summary_only)
7402 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7403 safi, true);
7404 } else
7405 bgp_aggregate_med_match(aggregate, bgp, pi);
7406
7407 /* No mismatches, just quit. */
7408 if (!aggregate->med_mismatched)
7409 return;
7410
7411 /* Route summarization is disabled. */
7412 if (!aggregate->summary_only)
7413 return;
7414
7415 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7416}
7417
b5d58c32 7418/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7419void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7420 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7421{
7422 struct bgp_table *table;
9bcb3eef
DS
7423 struct bgp_dest *top;
7424 struct bgp_dest *dest;
d7c0a89a 7425 uint8_t origin;
d62a17ae 7426 struct aspath *aspath = NULL;
d62a17ae 7427 struct community *community = NULL;
3da2cc32 7428 struct ecommunity *ecommunity = NULL;
dd18c5a9 7429 struct lcommunity *lcommunity = NULL;
40381db7 7430 struct bgp_path_info *pi;
d62a17ae 7431 unsigned long match = 0;
d7c0a89a 7432 uint8_t atomic_aggregate = 0;
d62a17ae 7433
9f822fa2
S
7434 /* If the bgp instance is being deleted or self peer is deleted
7435 * then do not create aggregate route
7436 */
892fedb6
DA
7437 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7438 || (bgp->peer_self == NULL))
9f822fa2
S
7439 return;
7440
6aabb15d
RZ
7441 /* Initialize and test routes for MED difference. */
7442 if (aggregate->match_med)
7443 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7444
4056a5f6
RZ
7445 /*
7446 * Reset aggregate count: we might've been called from route map
7447 * update so in that case we must retest all more specific routes.
7448 *
7449 * \see `bgp_route_map_process_update`.
7450 */
7451 aggregate->count = 0;
7452 aggregate->incomplete_origin_count = 0;
7453 aggregate->incomplete_origin_count = 0;
7454 aggregate->egp_origin_count = 0;
7455
d62a17ae 7456 /* ORIGIN attribute: If at least one route among routes that are
7457 aggregated has ORIGIN with the value INCOMPLETE, then the
7458 aggregated route must have the ORIGIN attribute with the value
7459 INCOMPLETE. Otherwise, if at least one route among routes that
7460 are aggregated has ORIGIN with the value EGP, then the aggregated
7461 route must have the origin attribute with the value EGP. In all
7462 other case the value of the ORIGIN attribute of the aggregated
7463 route is INTERNAL. */
7464 origin = BGP_ORIGIN_IGP;
718e3744 7465
d62a17ae 7466 table = bgp->rib[afi][safi];
718e3744 7467
d62a17ae 7468 top = bgp_node_get(table, p);
9bcb3eef
DS
7469 for (dest = bgp_node_get(table, p); dest;
7470 dest = bgp_route_next_until(dest, top)) {
7471 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7472
9bcb3eef 7473 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7474 continue;
d62a17ae 7475
a77e2f4b
S
7476 /* If suppress fib is enabled and route not installed
7477 * in FIB, skip the route
7478 */
7479 if (!bgp_check_advertise(bgp, dest))
7480 continue;
7481
c2ff8b3e 7482 match = 0;
d62a17ae 7483
9bcb3eef 7484 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7485 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7486 continue;
718e3744 7487
40381db7 7488 if (pi->attr->flag
c2ff8b3e
DS
7489 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7490 atomic_aggregate = 1;
d62a17ae 7491
40381db7 7492 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7493 continue;
d62a17ae 7494
f273fef1
DS
7495 /*
7496 * summary-only aggregate route suppress
7497 * aggregated route announcements.
6aabb15d
RZ
7498 *
7499 * MED matching:
7500 * Don't create summaries if MED didn't match
7501 * otherwise neither the specific routes and the
7502 * aggregation will be announced.
f273fef1 7503 */
6aabb15d
RZ
7504 if (aggregate->summary_only
7505 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7506 if (aggr_suppress_path(aggregate, pi))
7507 match++;
d62a17ae 7508 }
c2ff8b3e 7509
365ab2e7
RZ
7510 /*
7511 * Suppress more specific routes that match the route
7512 * map results.
7513 *
7514 * MED matching:
7515 * Don't suppress routes if MED matching is enabled and
7516 * it mismatched otherwise we might end up with no
7517 * routes for this path.
7518 */
7519 if (aggregate->suppress_map_name
7520 && AGGREGATE_MED_VALID(aggregate)
7521 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7522 if (aggr_suppress_path(aggregate, pi))
7523 match++;
d62a17ae 7524 }
c2ff8b3e
DS
7525
7526 aggregate->count++;
7527
f273fef1
DS
7528 /*
7529 * If at least one route among routes that are
7530 * aggregated has ORIGIN with the value INCOMPLETE,
7531 * then the aggregated route MUST have the ORIGIN
7532 * attribute with the value INCOMPLETE. Otherwise, if
7533 * at least one route among routes that are aggregated
7534 * has ORIGIN with the value EGP, then the aggregated
7535 * route MUST have the ORIGIN attribute with the value
7536 * EGP.
7537 */
fc968841
NT
7538 switch (pi->attr->origin) {
7539 case BGP_ORIGIN_INCOMPLETE:
7540 aggregate->incomplete_origin_count++;
7541 break;
7542 case BGP_ORIGIN_EGP:
7543 aggregate->egp_origin_count++;
7544 break;
7545 default:
7546 /*Do nothing.
7547 */
7548 break;
7549 }
c2ff8b3e
DS
7550
7551 if (!aggregate->as_set)
7552 continue;
7553
f273fef1
DS
7554 /*
7555 * as-set aggregate route generate origin, as path,
7556 * and community aggregation.
7557 */
fc968841
NT
7558 /* Compute aggregate route's as-path.
7559 */
ef51a7d8 7560 bgp_compute_aggregate_aspath_hash(aggregate,
7561 pi->attr->aspath);
c2ff8b3e 7562
fc968841
NT
7563 /* Compute aggregate route's community.
7564 */
9a706b42 7565 if (bgp_attr_get_community(pi->attr))
21fec674 7566 bgp_compute_aggregate_community_hash(
9a706b42
DA
7567 aggregate,
7568 bgp_attr_get_community(pi->attr));
dd18c5a9 7569
fc968841
NT
7570 /* Compute aggregate route's extended community.
7571 */
b53e67a3 7572 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7573 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7574 aggregate,
7575 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7576
7577 /* Compute aggregate route's large community.
7578 */
1bcf3a96 7579 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7580 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7581 aggregate,
7582 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7583 }
c2ff8b3e 7584 if (match)
9bcb3eef 7585 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7586 }
21fec674 7587 if (aggregate->as_set) {
ef51a7d8 7588 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7589 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7590 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7591 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7592 }
7593
f1eb1f05 7594
9bcb3eef 7595 bgp_dest_unlock_node(top);
718e3744 7596
718e3744 7597
fc968841
NT
7598 if (aggregate->incomplete_origin_count > 0)
7599 origin = BGP_ORIGIN_INCOMPLETE;
7600 else if (aggregate->egp_origin_count > 0)
7601 origin = BGP_ORIGIN_EGP;
d62a17ae 7602
229757f1
DA
7603 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7604 origin = aggregate->origin;
7605
fc968841
NT
7606 if (aggregate->as_set) {
7607 if (aggregate->aspath)
7608 /* Retrieve aggregate route's as-path.
7609 */
7610 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7611
fc968841
NT
7612 if (aggregate->community)
7613 /* Retrieve aggregate route's community.
7614 */
7615 community = community_dup(aggregate->community);
3da2cc32 7616
fc968841
NT
7617 if (aggregate->ecommunity)
7618 /* Retrieve aggregate route's ecommunity.
7619 */
7620 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7621
fc968841
NT
7622 if (aggregate->lcommunity)
7623 /* Retrieve aggregate route's lcommunity.
7624 */
7625 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7626 }
718e3744 7627
c701010e 7628 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7629 ecommunity, lcommunity, atomic_aggregate,
7630 aggregate);
718e3744 7631}
7632
5f040085
DS
7633void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7634 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7635{
7636 struct bgp_table *table;
9bcb3eef
DS
7637 struct bgp_dest *top;
7638 struct bgp_dest *dest;
40381db7 7639 struct bgp_path_info *pi;
3b7db173
DS
7640 unsigned long match;
7641
7642 table = bgp->rib[afi][safi];
7643
7644 /* If routes exists below this node, generate aggregate routes. */
7645 top = bgp_node_get(table, p);
9bcb3eef
DS
7646 for (dest = bgp_node_get(table, p); dest;
7647 dest = bgp_route_next_until(dest, top)) {
7648 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7649
9bcb3eef 7650 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7651 continue;
7652 match = 0;
7653
9bcb3eef 7654 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7655 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7656 continue;
7657
40381db7 7658 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7659 continue;
7660
92b175bd
RZ
7661 /*
7662 * This route is suppressed: attempt to unsuppress it.
7663 *
7664 * `aggr_unsuppress_path` will fail if this particular
7665 * aggregate route was not the suppressor.
7666 */
7667 if (pi->extra && pi->extra->aggr_suppressors &&
7668 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7669 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7670 match++;
3b7db173 7671 }
365ab2e7 7672
3b7db173 7673 aggregate->count--;
fc968841
NT
7674
7675 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7676 aggregate->incomplete_origin_count--;
7677 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7678 aggregate->egp_origin_count--;
7679
7680 if (aggregate->as_set) {
7681 /* Remove as-path from aggregate.
7682 */
ef51a7d8 7683 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7684 aggregate,
7685 pi->attr->aspath);
7686
9a706b42 7687 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7688 /* Remove community from aggregate.
7689 */
21fec674 7690 bgp_remove_comm_from_aggregate_hash(
9a706b42
DA
7691 aggregate,
7692 bgp_attr_get_community(
7693 pi->attr));
fc968841 7694
b53e67a3 7695 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7696 /* Remove ecommunity from aggregate.
7697 */
4edd83f9 7698 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7699 aggregate,
7700 bgp_attr_get_ecommunity(
7701 pi->attr));
fc968841 7702
1bcf3a96 7703 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7704 /* Remove lcommunity from aggregate.
7705 */
f1eb1f05 7706 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7707 aggregate,
7708 bgp_attr_get_lcommunity(
7709 pi->attr));
fc968841 7710 }
3b7db173
DS
7711 }
7712
7713 /* If this node was suppressed, process the change. */
7714 if (match)
9bcb3eef 7715 bgp_process(bgp, dest, afi, safi);
3b7db173 7716 }
f1eb1f05 7717 if (aggregate->as_set) {
ef51a7d8 7718 aspath_free(aggregate->aspath);
7719 aggregate->aspath = NULL;
21fec674 7720 if (aggregate->community)
7721 community_free(&aggregate->community);
4edd83f9 7722 if (aggregate->ecommunity)
7723 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7724 if (aggregate->lcommunity)
7725 lcommunity_free(&aggregate->lcommunity);
7726 }
7727
9bcb3eef 7728 bgp_dest_unlock_node(top);
3b7db173 7729}
718e3744 7730
5f040085
DS
7731static void bgp_add_route_to_aggregate(struct bgp *bgp,
7732 const struct prefix *aggr_p,
fc968841
NT
7733 struct bgp_path_info *pinew, afi_t afi,
7734 safi_t safi,
7735 struct bgp_aggregate *aggregate)
7736{
7737 uint8_t origin;
7738 struct aspath *aspath = NULL;
7739 uint8_t atomic_aggregate = 0;
7740 struct community *community = NULL;
7741 struct ecommunity *ecommunity = NULL;
7742 struct lcommunity *lcommunity = NULL;
7743
a4559740 7744 /* If the bgp instance is being deleted or self peer is deleted
7745 * then do not create aggregate route
7746 */
7747 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7748 || (bgp->peer_self == NULL))
7749 return;
7750
fc968841
NT
7751 /* ORIGIN attribute: If at least one route among routes that are
7752 * aggregated has ORIGIN with the value INCOMPLETE, then the
7753 * aggregated route must have the ORIGIN attribute with the value
7754 * INCOMPLETE. Otherwise, if at least one route among routes that
7755 * are aggregated has ORIGIN with the value EGP, then the aggregated
7756 * route must have the origin attribute with the value EGP. In all
7757 * other case the value of the ORIGIN attribute of the aggregated
7758 * route is INTERNAL.
7759 */
7760 origin = BGP_ORIGIN_IGP;
7761
7762 aggregate->count++;
7763
6aabb15d
RZ
7764 /*
7765 * This must be called before `summary` check to avoid
7766 * "suppressing" twice.
7767 */
7768 if (aggregate->match_med)
7769 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7770 pinew, true);
7771
7772 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7773 aggr_suppress_path(aggregate, pinew);
fc968841 7774
365ab2e7
RZ
7775 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7776 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7777 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7778
7779 switch (pinew->attr->origin) {
7780 case BGP_ORIGIN_INCOMPLETE:
7781 aggregate->incomplete_origin_count++;
7782 break;
7783 case BGP_ORIGIN_EGP:
7784 aggregate->egp_origin_count++;
7785 break;
7786 default:
7787 /* Do nothing.
7788 */
7789 break;
7790 }
7791
7792 if (aggregate->incomplete_origin_count > 0)
7793 origin = BGP_ORIGIN_INCOMPLETE;
7794 else if (aggregate->egp_origin_count > 0)
7795 origin = BGP_ORIGIN_EGP;
7796
229757f1
DA
7797 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7798 origin = aggregate->origin;
7799
fc968841
NT
7800 if (aggregate->as_set) {
7801 /* Compute aggregate route's as-path.
7802 */
7803 bgp_compute_aggregate_aspath(aggregate,
7804 pinew->attr->aspath);
7805
7806 /* Compute aggregate route's community.
7807 */
9a706b42 7808 if (bgp_attr_get_community(pinew->attr))
fc968841 7809 bgp_compute_aggregate_community(
9a706b42 7810 aggregate, bgp_attr_get_community(pinew->attr));
fc968841
NT
7811
7812 /* Compute aggregate route's extended community.
7813 */
b53e67a3 7814 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7815 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7816 aggregate,
7817 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7818
7819 /* Compute aggregate route's large community.
7820 */
1bcf3a96 7821 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7822 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7823 aggregate,
7824 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7825
7826 /* Retrieve aggregate route's as-path.
7827 */
7828 if (aggregate->aspath)
7829 aspath = aspath_dup(aggregate->aspath);
7830
7831 /* Retrieve aggregate route's community.
7832 */
7833 if (aggregate->community)
7834 community = community_dup(aggregate->community);
7835
7836 /* Retrieve aggregate route's ecommunity.
7837 */
7838 if (aggregate->ecommunity)
7839 ecommunity = ecommunity_dup(aggregate->ecommunity);
7840
7841 /* Retrieve aggregate route's lcommunity.
7842 */
7843 if (aggregate->lcommunity)
7844 lcommunity = lcommunity_dup(aggregate->lcommunity);
7845 }
7846
7847 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7848 aspath, community, ecommunity,
7849 lcommunity, atomic_aggregate, aggregate);
7850}
7851
7852static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7853 safi_t safi,
7854 struct bgp_path_info *pi,
7855 struct bgp_aggregate *aggregate,
5f040085 7856 const struct prefix *aggr_p)
fc968841
NT
7857{
7858 uint8_t origin;
7859 struct aspath *aspath = NULL;
7860 uint8_t atomic_aggregate = 0;
7861 struct community *community = NULL;
7862 struct ecommunity *ecommunity = NULL;
7863 struct lcommunity *lcommunity = NULL;
7864 unsigned long match = 0;
7865
a4559740 7866 /* If the bgp instance is being deleted or self peer is deleted
7867 * then do not create aggregate route
7868 */
7869 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7870 || (bgp->peer_self == NULL))
7871 return;
7872
fc968841
NT
7873 if (BGP_PATH_HOLDDOWN(pi))
7874 return;
7875
7876 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7877 return;
7878
4056a5f6
RZ
7879 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7880 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7881 match++;
fc968841 7882
365ab2e7 7883 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7884 && aggr_suppress_map_test(bgp, aggregate, pi))
7885 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7886 match++;
fc968841 7887
6aabb15d 7888 /*
365ab2e7 7889 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7890 * "unsuppressing" twice.
7891 */
7892 if (aggregate->match_med)
7893 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7894 true);
7895
fc968841
NT
7896 if (aggregate->count > 0)
7897 aggregate->count--;
7898
7899 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7900 aggregate->incomplete_origin_count--;
7901 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7902 aggregate->egp_origin_count--;
7903
7904 if (aggregate->as_set) {
7905 /* Remove as-path from aggregate.
7906 */
7907 bgp_remove_aspath_from_aggregate(aggregate,
7908 pi->attr->aspath);
7909
9a706b42 7910 if (bgp_attr_get_community(pi->attr))
fc968841
NT
7911 /* Remove community from aggregate.
7912 */
7913 bgp_remove_community_from_aggregate(
9a706b42 7914 aggregate, bgp_attr_get_community(pi->attr));
fc968841 7915
b53e67a3 7916 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7917 /* Remove ecommunity from aggregate.
7918 */
7919 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7920 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7921
1bcf3a96 7922 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7923 /* Remove lcommunity from aggregate.
7924 */
7925 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7926 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7927 }
7928
7929 /* If this node was suppressed, process the change. */
7930 if (match)
7931 bgp_process(bgp, pi->net, afi, safi);
7932
7933 origin = BGP_ORIGIN_IGP;
7934 if (aggregate->incomplete_origin_count > 0)
7935 origin = BGP_ORIGIN_INCOMPLETE;
7936 else if (aggregate->egp_origin_count > 0)
7937 origin = BGP_ORIGIN_EGP;
7938
229757f1
DA
7939 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7940 origin = aggregate->origin;
7941
fc968841
NT
7942 if (aggregate->as_set) {
7943 /* Retrieve aggregate route's as-path.
7944 */
7945 if (aggregate->aspath)
7946 aspath = aspath_dup(aggregate->aspath);
7947
7948 /* Retrieve aggregate route's community.
7949 */
7950 if (aggregate->community)
7951 community = community_dup(aggregate->community);
7952
7953 /* Retrieve aggregate route's ecommunity.
7954 */
7955 if (aggregate->ecommunity)
7956 ecommunity = ecommunity_dup(aggregate->ecommunity);
7957
7958 /* Retrieve aggregate route's lcommunity.
7959 */
7960 if (aggregate->lcommunity)
7961 lcommunity = lcommunity_dup(aggregate->lcommunity);
7962 }
7963
7964 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7965 aspath, community, ecommunity,
7966 lcommunity, atomic_aggregate, aggregate);
7967}
7968
5a1ae2c2 7969void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7970 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7971{
9bcb3eef
DS
7972 struct bgp_dest *child;
7973 struct bgp_dest *dest;
d62a17ae 7974 struct bgp_aggregate *aggregate;
7975 struct bgp_table *table;
718e3744 7976
d62a17ae 7977 table = bgp->aggregate[afi][safi];
f018db83 7978
d62a17ae 7979 /* No aggregates configured. */
7980 if (bgp_table_top_nolock(table) == NULL)
7981 return;
f018db83 7982
d62a17ae 7983 if (p->prefixlen == 0)
7984 return;
718e3744 7985
40381db7 7986 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7987 return;
718e3744 7988
a77e2f4b
S
7989 /* If suppress fib is enabled and route not installed
7990 * in FIB, do not update the aggregate route
7991 */
7992 if (!bgp_check_advertise(bgp, pi->net))
7993 return;
7994
d62a17ae 7995 child = bgp_node_get(table, p);
718e3744 7996
d62a17ae 7997 /* Aggregate address configuration check. */
9bcb3eef
DS
7998 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7999 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8000
9bcb3eef
DS
8001 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8002 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
8003 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 8004 aggregate);
d62a17ae 8005 }
b1e62edd 8006 }
9bcb3eef 8007 bgp_dest_unlock_node(child);
718e3744 8008}
8009
5a1ae2c2 8010void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 8011 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 8012{
9bcb3eef
DS
8013 struct bgp_dest *child;
8014 struct bgp_dest *dest;
d62a17ae 8015 struct bgp_aggregate *aggregate;
8016 struct bgp_table *table;
718e3744 8017
d62a17ae 8018 table = bgp->aggregate[afi][safi];
718e3744 8019
d62a17ae 8020 /* No aggregates configured. */
8021 if (bgp_table_top_nolock(table) == NULL)
8022 return;
718e3744 8023
d62a17ae 8024 if (p->prefixlen == 0)
8025 return;
718e3744 8026
d62a17ae 8027 child = bgp_node_get(table, p);
718e3744 8028
d62a17ae 8029 /* Aggregate address configuration check. */
9bcb3eef
DS
8030 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
8031 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 8032
9bcb3eef
DS
8033 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
8034 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 8035 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 8036 aggregate, dest_p);
d62a17ae 8037 }
b1e62edd 8038 }
9bcb3eef 8039 bgp_dest_unlock_node(child);
d62a17ae 8040}
718e3744 8041
718e3744 8042/* Aggregate route attribute. */
8043#define AGGREGATE_SUMMARY_ONLY 1
8044#define AGGREGATE_AS_SET 1
fb29348a 8045#define AGGREGATE_AS_UNSET 0
718e3744 8046
229757f1
DA
8047static const char *bgp_origin2str(uint8_t origin)
8048{
8049 switch (origin) {
8050 case BGP_ORIGIN_IGP:
8051 return "igp";
8052 case BGP_ORIGIN_EGP:
8053 return "egp";
8054 case BGP_ORIGIN_INCOMPLETE:
8055 return "incomplete";
8056 }
8057 return "n/a";
8058}
8059
fdeb5a81 8060static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
8061{
8062 switch (v_state) {
fdeb5a81
DS
8063 case RPKI_NOT_BEING_USED:
8064 return "not used";
8065 case RPKI_VALID:
b5b99af8 8066 return "valid";
fdeb5a81 8067 case RPKI_NOTFOUND:
b5b99af8 8068 return "not found";
fdeb5a81 8069 case RPKI_INVALID:
b5b99af8 8070 return "invalid";
b5b99af8 8071 }
fdeb5a81
DS
8072
8073 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
8074 return "ERROR";
8075}
8076
585f1adc
IR
8077static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
8078 afi_t afi, safi_t safi)
718e3744 8079{
585f1adc
IR
8080 VTY_DECLVAR_CONTEXT(bgp, bgp);
8081 int ret;
8082 struct prefix p;
9bcb3eef 8083 struct bgp_dest *dest;
d62a17ae 8084 struct bgp_aggregate *aggregate;
718e3744 8085
585f1adc
IR
8086 /* Convert string to prefix structure. */
8087 ret = str2prefix(prefix_str, &p);
8088 if (!ret) {
8089 vty_out(vty, "Malformed prefix\n");
8090 return CMD_WARNING_CONFIG_FAILED;
8091 }
8092 apply_mask(&p);
a4559740 8093
d62a17ae 8094 /* Old configuration check. */
585f1adc 8095 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8096 if (!dest) {
585f1adc
IR
8097 vty_out(vty,
8098 "%% There is no aggregate-address configuration.\n");
8099 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8100 }
f6269b4f 8101
9bcb3eef 8102 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8103 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8104 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8105 NULL, NULL, 0, aggregate);
d62a17ae 8106
8107 /* Unlock aggregate address configuration. */
9bcb3eef 8108 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8109
8110 if (aggregate->community)
8111 community_free(&aggregate->community);
8112
8113 if (aggregate->community_hash) {
8114 /* Delete all communities in the hash.
8115 */
8116 hash_clean(aggregate->community_hash,
8117 bgp_aggr_community_remove);
8118 /* Free up the community_hash.
8119 */
8120 hash_free(aggregate->community_hash);
8121 }
8122
8123 if (aggregate->ecommunity)
8124 ecommunity_free(&aggregate->ecommunity);
8125
8126 if (aggregate->ecommunity_hash) {
8127 /* Delete all ecommunities in the hash.
8128 */
8129 hash_clean(aggregate->ecommunity_hash,
8130 bgp_aggr_ecommunity_remove);
8131 /* Free up the ecommunity_hash.
8132 */
8133 hash_free(aggregate->ecommunity_hash);
8134 }
8135
8136 if (aggregate->lcommunity)
8137 lcommunity_free(&aggregate->lcommunity);
8138
8139 if (aggregate->lcommunity_hash) {
8140 /* Delete all lcommunities in the hash.
8141 */
8142 hash_clean(aggregate->lcommunity_hash,
8143 bgp_aggr_lcommunity_remove);
8144 /* Free up the lcommunity_hash.
8145 */
8146 hash_free(aggregate->lcommunity_hash);
8147 }
8148
8149 if (aggregate->aspath)
8150 aspath_free(aggregate->aspath);
8151
8152 if (aggregate->aspath_hash) {
8153 /* Delete all as-paths in the hash.
8154 */
8155 hash_clean(aggregate->aspath_hash,
8156 bgp_aggr_aspath_remove);
8157 /* Free up the aspath_hash.
8158 */
8159 hash_free(aggregate->aspath_hash);
8160 }
8161
d62a17ae 8162 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8163 bgp_dest_unlock_node(dest);
8164 bgp_dest_unlock_node(dest);
d62a17ae 8165
585f1adc 8166 return CMD_SUCCESS;
d62a17ae 8167}
8168
585f1adc
IR
8169static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8170 safi_t safi, const char *rmap,
8171 uint8_t summary_only, uint8_t as_set,
8172 uint8_t origin, bool match_med,
8173 const char *suppress_map)
d62a17ae 8174{
585f1adc 8175 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8176 int ret;
585f1adc 8177 struct prefix p;
9bcb3eef 8178 struct bgp_dest *dest;
d62a17ae 8179 struct bgp_aggregate *aggregate;
fb29348a 8180 uint8_t as_set_new = as_set;
d62a17ae 8181
365ab2e7 8182 if (suppress_map && summary_only) {
585f1adc 8183 vty_out(vty,
365ab2e7 8184 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8185 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8186 }
8187
585f1adc
IR
8188 /* Convert string to prefix structure. */
8189 ret = str2prefix(prefix_str, &p);
8190 if (!ret) {
8191 vty_out(vty, "Malformed prefix\n");
8192 return CMD_WARNING_CONFIG_FAILED;
8193 }
8194 apply_mask(&p);
d62a17ae 8195
585f1adc
IR
8196 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8197 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8198 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8199 prefix_str);
8200 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8201 }
8202
d62a17ae 8203 /* Old configuration check. */
585f1adc 8204 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8205 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8206
20894f50 8207 if (aggregate) {
585f1adc 8208 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8209 /* try to remove the old entry */
585f1adc 8210 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8211 if (ret) {
585f1adc 8212 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8213 bgp_dest_unlock_node(dest);
585f1adc 8214 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8215 }
8216 }
718e3744 8217
d62a17ae 8218 /* Make aggregate address structure. */
8219 aggregate = bgp_aggregate_new();
8220 aggregate->summary_only = summary_only;
6aabb15d 8221 aggregate->match_med = match_med;
fb29348a
DA
8222
8223 /* Network operators MUST NOT locally generate any new
8224 * announcements containing AS_SET or AS_CONFED_SET. If they have
8225 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8226 * SHOULD withdraw those routes and re-announce routes for the
8227 * aggregate or component prefixes (i.e., the more-specific routes
8228 * subsumed by the previously aggregated route) without AS_SET
8229 * or AS_CONFED_SET in the updates.
8230 */
7f972cd8 8231 if (bgp->reject_as_sets) {
fb29348a
DA
8232 if (as_set == AGGREGATE_AS_SET) {
8233 as_set_new = AGGREGATE_AS_UNSET;
8234 zlog_warn(
63efca0e 8235 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8236 __func__);
585f1adc 8237 vty_out(vty,
fb29348a
DA
8238 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8239 }
8240 }
8241
8242 aggregate->as_set = as_set_new;
d62a17ae 8243 aggregate->safi = safi;
229757f1
DA
8244 /* Override ORIGIN attribute if defined.
8245 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8246 * to IGP which is not what rfc4271 says.
8247 * This enables the same behavior, optionally.
8248 */
8249 aggregate->origin = origin;
20894f50
DA
8250
8251 if (rmap) {
8252 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8253 route_map_counter_decrement(aggregate->rmap.map);
8254 aggregate->rmap.name =
8255 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8256 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8257 route_map_counter_increment(aggregate->rmap.map);
8258 }
365ab2e7
RZ
8259
8260 if (suppress_map) {
8261 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8262 route_map_counter_decrement(aggregate->suppress_map);
8263
8264 aggregate->suppress_map_name =
8265 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8266 aggregate->suppress_map =
8267 route_map_lookup_by_name(aggregate->suppress_map_name);
8268 route_map_counter_increment(aggregate->suppress_map);
8269 }
8270
9bcb3eef 8271 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8272
d62a17ae 8273 /* Aggregate address insert into BGP routing table. */
585f1adc 8274 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8275
585f1adc 8276 return CMD_SUCCESS;
718e3744 8277}
8278
585f1adc
IR
8279DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8280 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8281 "as-set$as_set_s"
8282 "|summary-only$summary_only"
cacba915 8283 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8284 "|origin <egp|igp|incomplete>$origin_s"
8285 "|matching-MED-only$match_med"
cacba915 8286 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8287 "}]",
8288 NO_STR
8289 "Configure BGP aggregate entries\n"
764402fe
DA
8290 "Aggregate prefix\n"
8291 "Aggregate address\n"
8292 "Aggregate mask\n"
585f1adc
IR
8293 "Generate AS set path information\n"
8294 "Filter more specific routes from updates\n"
8295 "Apply route map to aggregate network\n"
8296 "Route map name\n"
8297 "BGP origin code\n"
8298 "Remote EGP\n"
8299 "Local IGP\n"
8300 "Unknown heritage\n"
8301 "Only aggregate routes with matching MED\n"
8302 "Suppress the selected more specific routes\n"
8303 "Route map with the route selectors\n")
8304{
8305 const char *prefix_s = NULL;
554b3b10 8306 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8307 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8308 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8309 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8310
554b3b10 8311 if (addr_str) {
7533cad7
QY
8312 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8313 sizeof(prefix_buf))
554b3b10
RZ
8314 == 0) {
8315 vty_out(vty, "%% Inconsistent address and mask\n");
8316 return CMD_WARNING_CONFIG_FAILED;
8317 }
585f1adc
IR
8318 prefix_s = prefix_buf;
8319 } else
8320 prefix_s = prefix_str;
37a87b8f 8321
585f1adc
IR
8322 if (origin_s) {
8323 if (strcmp(origin_s, "egp") == 0)
8324 origin = BGP_ORIGIN_EGP;
8325 else if (strcmp(origin_s, "igp") == 0)
8326 origin = BGP_ORIGIN_IGP;
8327 else if (strcmp(origin_s, "incomplete") == 0)
8328 origin = BGP_ORIGIN_INCOMPLETE;
8329 }
90e21f35 8330
585f1adc
IR
8331 if (as_set_s)
8332 as_set = AGGREGATE_AS_SET;
554b3b10 8333
585f1adc 8334 /* Handle configuration removal, otherwise installation. */
554b3b10 8335 if (no)
585f1adc
IR
8336 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8337
8338 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8339 summary_only != NULL, as_set, origin,
8340 match_med != NULL, suppress_map);
8341}
8342
8343DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8344 "[no] aggregate-address X:X::X:X/M$prefix [{"
8345 "as-set$as_set_s"
8346 "|summary-only$summary_only"
cacba915 8347 "|route-map RMAP_NAME$rmap_name"
585f1adc
IR
8348 "|origin <egp|igp|incomplete>$origin_s"
8349 "|matching-MED-only$match_med"
cacba915 8350 "|suppress-map RMAP_NAME$suppress_map"
585f1adc
IR
8351 "}]",
8352 NO_STR
8353 "Configure BGP aggregate entries\n"
8354 "Aggregate prefix\n"
8355 "Generate AS set path information\n"
8356 "Filter more specific routes from updates\n"
8357 "Apply route map to aggregate network\n"
8358 "Route map name\n"
8359 "BGP origin code\n"
8360 "Remote EGP\n"
8361 "Local IGP\n"
8362 "Unknown heritage\n"
8363 "Only aggregate routes with matching MED\n"
8364 "Suppress the selected more specific routes\n"
8365 "Route map with the route selectors\n")
8366{
8367 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8368 int as_set = AGGREGATE_AS_UNSET;
8369
8370 if (origin_s) {
8371 if (strcmp(origin_s, "egp") == 0)
8372 origin = BGP_ORIGIN_EGP;
8373 else if (strcmp(origin_s, "igp") == 0)
8374 origin = BGP_ORIGIN_IGP;
8375 else if (strcmp(origin_s, "incomplete") == 0)
8376 origin = BGP_ORIGIN_INCOMPLETE;
8377 }
8378
8379 if (as_set_s)
8380 as_set = AGGREGATE_AS_SET;
8381
8382 /* Handle configuration removal, otherwise installation. */
554b3b10 8383 if (no)
585f1adc
IR
8384 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8385 SAFI_UNICAST);
554b3b10 8386
585f1adc
IR
8387 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8388 rmap_name, summary_only != NULL, as_set,
8389 origin, match_med != NULL, suppress_map);
718e3744 8390}
8391
718e3744 8392/* Redistribute route treatment. */
d62a17ae 8393void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8394 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8395 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8396 enum blackhole_type bhtype, uint32_t metric,
8397 uint8_t type, unsigned short instance,
8398 route_tag_t tag)
d62a17ae 8399{
4b7e6066 8400 struct bgp_path_info *new;
40381db7
DS
8401 struct bgp_path_info *bpi;
8402 struct bgp_path_info rmap_path;
9bcb3eef 8403 struct bgp_dest *bn;
d62a17ae 8404 struct attr attr;
8405 struct attr *new_attr;
8406 afi_t afi;
b68885f9 8407 route_map_result_t ret;
d62a17ae 8408 struct bgp_redist *red;
8409
8410 /* Make default attribute. */
0f05ea43 8411 bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8412 /*
8413 * This must not be NULL to satisfy Coverity SA
8414 */
8415 assert(attr.aspath);
9de1f7ff 8416
a4d82a8a 8417 switch (nhtype) {
9de1f7ff
DS
8418 case NEXTHOP_TYPE_IFINDEX:
8419 break;
8420 case NEXTHOP_TYPE_IPV4:
8421 case NEXTHOP_TYPE_IPV4_IFINDEX:
8422 attr.nexthop = nexthop->ipv4;
7226bc40 8423 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
9de1f7ff
DS
8424 break;
8425 case NEXTHOP_TYPE_IPV6:
8426 case NEXTHOP_TYPE_IPV6_IFINDEX:
8427 attr.mp_nexthop_global = nexthop->ipv6;
8428 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8429 break;
8430 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8431 switch (p->family) {
8432 case AF_INET:
9de1f7ff 8433 attr.nexthop.s_addr = INADDR_ANY;
7226bc40 8434 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
74489921
RW
8435 break;
8436 case AF_INET6:
9de1f7ff
DS
8437 memset(&attr.mp_nexthop_global, 0,
8438 sizeof(attr.mp_nexthop_global));
74489921 8439 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8440 break;
74489921 8441 }
0789eb69 8442 attr.bh_type = bhtype;
9de1f7ff 8443 break;
d62a17ae 8444 }
0789eb69 8445 attr.nh_type = nhtype;
74489921 8446 attr.nh_ifindex = ifindex;
f04a80a5 8447
d62a17ae 8448 attr.med = metric;
957f74c3 8449 attr.distance = distance;
d62a17ae 8450 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8451 attr.tag = tag;
718e3744 8452
d62a17ae 8453 afi = family2afi(p->family);
6aeb9e78 8454
d62a17ae 8455 red = bgp_redist_lookup(bgp, afi, type, instance);
8456 if (red) {
8457 struct attr attr_new;
718e3744 8458
d62a17ae 8459 /* Copy attribute for modification. */
6f4f49b2 8460 attr_new = attr;
718e3744 8461
d62a17ae 8462 if (red->redist_metric_flag)
8463 attr_new.med = red->redist_metric;
718e3744 8464
d62a17ae 8465 /* Apply route-map. */
8466 if (red->rmap.name) {
6006b807 8467 memset(&rmap_path, 0, sizeof(rmap_path));
40381db7
DS
8468 rmap_path.peer = bgp->peer_self;
8469 rmap_path.attr = &attr_new;
718e3744 8470
d62a17ae 8471 SET_FLAG(bgp->peer_self->rmap_type,
8472 PEER_RMAP_TYPE_REDISTRIBUTE);
8473
1782514f 8474 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8475
8476 bgp->peer_self->rmap_type = 0;
8477
8478 if (ret == RMAP_DENYMATCH) {
8479 /* Free uninterned attribute. */
8480 bgp_attr_flush(&attr_new);
8481
8482 /* Unintern original. */
8483 aspath_unintern(&attr.aspath);
8484 bgp_redistribute_delete(bgp, p, type, instance);
8485 return;
8486 }
8487 }
8488
637e5ba4 8489 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8490 bgp_attr_add_gshut_community(&attr_new);
8491
d62a17ae 8492 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8493 SAFI_UNICAST, p, NULL);
8494
8495 new_attr = bgp_attr_intern(&attr_new);
8496
9bcb3eef 8497 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8498 if (bpi->peer == bgp->peer_self
8499 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8500 break;
8501
40381db7 8502 if (bpi) {
d62a17ae 8503 /* Ensure the (source route) type is updated. */
40381db7
DS
8504 bpi->type = type;
8505 if (attrhash_cmp(bpi->attr, new_attr)
8506 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8507 bgp_attr_unintern(&new_attr);
8508 aspath_unintern(&attr.aspath);
9bcb3eef 8509 bgp_dest_unlock_node(bn);
d62a17ae 8510 return;
8511 } else {
8512 /* The attribute is changed. */
40381db7 8513 bgp_path_info_set_flag(bn, bpi,
18ee8310 8514 BGP_PATH_ATTR_CHANGED);
d62a17ae 8515
8516 /* Rewrite BGP route information. */
40381db7
DS
8517 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8518 bgp_path_info_restore(bn, bpi);
d62a17ae 8519 else
40381db7
DS
8520 bgp_aggregate_decrement(
8521 bgp, p, bpi, afi, SAFI_UNICAST);
8522 bgp_attr_unintern(&bpi->attr);
8523 bpi->attr = new_attr;
8524 bpi->uptime = bgp_clock();
d62a17ae 8525
8526 /* Process change. */
40381db7 8527 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8528 SAFI_UNICAST);
8529 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8530 bgp_dest_unlock_node(bn);
d62a17ae 8531 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8532
8533 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8534 || (bgp->inst_type
8535 == BGP_INSTANCE_TYPE_DEFAULT)) {
8536
8537 vpn_leak_from_vrf_update(
40381db7 8538 bgp_get_default(), bgp, bpi);
ddb5b488 8539 }
d62a17ae 8540 return;
8541 }
8542 }
8543
8544 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8545 bgp->peer_self, new_attr, bn);
1defdda8 8546 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8547
8548 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8549 bgp_path_info_add(bn, new);
9bcb3eef 8550 bgp_dest_unlock_node(bn);
be785e35 8551 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8552 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8553
8554 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8555 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8556
8557 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8558 }
d62a17ae 8559 }
8560
8561 /* Unintern original. */
8562 aspath_unintern(&attr.aspath);
718e3744 8563}
8564
d7c0a89a
QY
8565void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8566 unsigned short instance)
718e3744 8567{
d62a17ae 8568 afi_t afi;
9bcb3eef 8569 struct bgp_dest *dest;
40381db7 8570 struct bgp_path_info *pi;
d62a17ae 8571 struct bgp_redist *red;
718e3744 8572
d62a17ae 8573 afi = family2afi(p->family);
718e3744 8574
d62a17ae 8575 red = bgp_redist_lookup(bgp, afi, type, instance);
8576 if (red) {
9bcb3eef
DS
8577 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8578 SAFI_UNICAST, p, NULL);
d62a17ae 8579
9bcb3eef 8580 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8581 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8582 break;
8583
40381db7 8584 if (pi) {
ddb5b488
PZ
8585 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8586 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8587
8588 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8589 bgp, pi);
ddb5b488 8590 }
40381db7 8591 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8592 bgp_path_info_delete(dest, pi);
8593 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8594 }
9bcb3eef 8595 bgp_dest_unlock_node(dest);
d62a17ae 8596 }
8597}
8598
8599/* Withdraw specified route type's route. */
8600void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8601 unsigned short instance)
d62a17ae 8602{
9bcb3eef 8603 struct bgp_dest *dest;
40381db7 8604 struct bgp_path_info *pi;
d62a17ae 8605 struct bgp_table *table;
8606
8607 table = bgp->rib[afi][SAFI_UNICAST];
8608
9bcb3eef
DS
8609 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8610 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8611 if (pi->peer == bgp->peer_self && pi->type == type
8612 && pi->instance == instance)
d62a17ae 8613 break;
8614
40381db7 8615 if (pi) {
ddb5b488
PZ
8616 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8617 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8618
8619 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8620 bgp, pi);
ddb5b488 8621 }
9bcb3eef 8622 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8623 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8624 bgp_path_info_delete(dest, pi);
8625 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8626 }
718e3744 8627 }
718e3744 8628}
6b0655a2 8629
718e3744 8630/* Static function to display route. */
7d3cae70
DA
8631static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8632 struct vty *vty, json_object *json, bool wide)
718e3744 8633{
be054588 8634 int len = 0;
d62a17ae 8635 char buf[BUFSIZ];
718e3744 8636
d62a17ae 8637 if (p->family == AF_INET) {
c6462ff4 8638 if (!json) {
8228a9a7 8639 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8640 } else {
8641 json_object_string_add(json, "prefix",
8642 inet_ntop(p->family,
8643 &p->u.prefix, buf,
8644 BUFSIZ));
8645 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8646 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8647 json_object_int_add(json, "version", dest->version);
c6462ff4 8648 }
d62a17ae 8649 } else if (p->family == AF_ETHERNET) {
8228a9a7 8650 len = vty_out(vty, "%pFX", p);
b03b8898 8651 } else if (p->family == AF_EVPN) {
57f7feb6 8652 if (!json)
2dbe669b 8653 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8654 else
60466a63 8655 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8656 } else if (p->family == AF_FLOWSPEC) {
8657 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8658 json ?
8659 NLRI_STRING_FORMAT_JSON_SIMPLE :
8660 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8661 } else {
c6462ff4 8662 if (!json)
8228a9a7 8663 len = vty_out(vty, "%pFX", p);
50e05855
AD
8664 else {
8665 json_object_string_add(json, "prefix",
8666 inet_ntop(p->family,
8667 &p->u.prefix, buf,
8668 BUFSIZ));
8669 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8670 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8671 json_object_int_add(json, "version", dest->version);
37d4e0df 8672 }
9c92b5f7 8673 }
d62a17ae 8674
9c92b5f7 8675 if (!json) {
ae248832 8676 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8677 if (len < 1)
8678 vty_out(vty, "\n%*s", 20, " ");
8679 else
8680 vty_out(vty, "%*s", len, " ");
8681 }
718e3744 8682}
8683
d62a17ae 8684enum bgp_display_type {
8685 normal_list,
718e3744 8686};
8687
1d7260a1 8688const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8689{
8690 switch (reason) {
8691 case bgp_path_selection_none:
8692 return "Nothing to Select";
8693 case bgp_path_selection_first:
8694 return "First path received";
8695 case bgp_path_selection_evpn_sticky_mac:
8696 return "EVPN Sticky Mac";
8697 case bgp_path_selection_evpn_seq:
8698 return "EVPN sequence number";
8699 case bgp_path_selection_evpn_lower_ip:
8700 return "EVPN lower IP";
8701 case bgp_path_selection_evpn_local_path:
8702 return "EVPN local ES path";
8703 case bgp_path_selection_evpn_non_proxy:
8704 return "EVPN non proxy";
8705 case bgp_path_selection_weight:
8706 return "Weight";
8707 case bgp_path_selection_local_pref:
8708 return "Local Pref";
8709 case bgp_path_selection_local_route:
8710 return "Local Route";
8711 case bgp_path_selection_confed_as_path:
8712 return "Confederation based AS Path";
8713 case bgp_path_selection_as_path:
8714 return "AS Path";
8715 case bgp_path_selection_origin:
8716 return "Origin";
8717 case bgp_path_selection_med:
8718 return "MED";
8719 case bgp_path_selection_peer:
8720 return "Peer Type";
8721 case bgp_path_selection_confed:
8722 return "Confed Peer Type";
8723 case bgp_path_selection_igp_metric:
8724 return "IGP Metric";
8725 case bgp_path_selection_older:
8726 return "Older Path";
8727 case bgp_path_selection_router_id:
8728 return "Router ID";
8729 case bgp_path_selection_cluster_length:
bcab253c 8730 return "Cluster length";
bbb46eb5
DA
8731 case bgp_path_selection_stale:
8732 return "Path Staleness";
8733 case bgp_path_selection_local_configured:
8734 return "Locally configured route";
8735 case bgp_path_selection_neighbor_ip:
8736 return "Neighbor IP";
8737 case bgp_path_selection_default:
8738 return "Nothing left to compare";
8739 }
8740 return "Invalid (internal error)";
8741}
8742
18ee8310 8743/* Print the short form route status for a bgp_path_info */
4b7e6066 8744static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8745 struct bgp_path_info *path,
82c298be 8746 const struct prefix *p,
d62a17ae 8747 json_object *json_path)
718e3744 8748{
82c298be
DA
8749 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8750
d62a17ae 8751 if (json_path) {
b05a1c8b 8752
d62a17ae 8753 /* Route status display. */
9b6d8fcf 8754 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8755 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8756
9b6d8fcf 8757 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8758 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8759
4056a5f6 8760 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8761 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8762
9b6d8fcf
DS
8763 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8764 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8765 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8766
d62a17ae 8767 /* Selected */
9b6d8fcf 8768 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8769 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8770
9b6d8fcf 8771 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8772 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8773
bbb46eb5 8774 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8775 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8776 json_object_string_add(json_path, "selectionReason",
8777 bgp_path_selection_reason2str(
8778 path->net->reason));
8779 }
b05a1c8b 8780
9b6d8fcf 8781 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8782 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8783
d62a17ae 8784 /* Internal route. */
9b6d8fcf
DS
8785 if ((path->peer->as)
8786 && (path->peer->as == path->peer->local_as))
d62a17ae 8787 json_object_string_add(json_path, "pathFrom",
8788 "internal");
8789 else
8790 json_object_string_add(json_path, "pathFrom",
8791 "external");
b05a1c8b 8792
d62a17ae 8793 return;
8794 }
b05a1c8b 8795
82c298be
DA
8796 /* RPKI validation state */
8797 rpki_state =
8798 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8799
8800 if (rpki_state == RPKI_VALID)
8801 vty_out(vty, "V");
8802 else if (rpki_state == RPKI_INVALID)
8803 vty_out(vty, "I");
8804 else if (rpki_state == RPKI_NOTFOUND)
8805 vty_out(vty, "N");
8806
d62a17ae 8807 /* Route status display. */
9b6d8fcf 8808 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8809 vty_out(vty, "R");
9b6d8fcf 8810 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8811 vty_out(vty, "S");
4056a5f6 8812 else if (bgp_path_suppressed(path))
d62a17ae 8813 vty_out(vty, "s");
9b6d8fcf
DS
8814 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8815 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8816 vty_out(vty, "*");
8817 else
8818 vty_out(vty, " ");
8819
8820 /* Selected */
9b6d8fcf 8821 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8822 vty_out(vty, "h");
9b6d8fcf 8823 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8824 vty_out(vty, "d");
9b6d8fcf 8825 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8826 vty_out(vty, ">");
9b6d8fcf 8827 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8828 vty_out(vty, "=");
8829 else
8830 vty_out(vty, " ");
718e3744 8831
d62a17ae 8832 /* Internal route. */
9b6d8fcf
DS
8833 if (path->peer && (path->peer->as)
8834 && (path->peer->as == path->peer->local_as))
d62a17ae 8835 vty_out(vty, "i");
8836 else
8837 vty_out(vty, " ");
b40d939b 8838}
8839
2ba93fd6
DA
8840static char *bgp_nexthop_hostname(struct peer *peer,
8841 struct bgp_nexthop_cache *bnc)
25b5da8d 8842{
892fedb6 8843 if (peer->hostname
aef999a2 8844 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8845 return peer->hostname;
8846 return NULL;
8847}
8848
b40d939b 8849/* called from terminal list command */
bd494ec5 8850void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8851 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8852 json_object *json_paths, bool wide)
d62a17ae 8853{
aef999a2 8854 int len;
515c2602 8855 struct attr *attr = path->attr;
d62a17ae 8856 json_object *json_path = NULL;
8857 json_object *json_nexthops = NULL;
8858 json_object *json_nexthop_global = NULL;
8859 json_object *json_nexthop_ll = NULL;
6f214dd3 8860 json_object *json_ext_community = NULL;
9df8b37c 8861 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8862 bool nexthop_self =
9b6d8fcf 8863 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8864 bool nexthop_othervrf = false;
43089216 8865 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8866 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8867 char *nexthop_hostname =
8868 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8869 char esi_buf[ESI_STR_LEN];
d62a17ae 8870
8871 if (json_paths)
8872 json_path = json_object_new_object();
8873
8874 /* short status lead text */
82c298be 8875 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8876
8877 if (!json_paths) {
8878 /* print prefix and mask */
8879 if (!display)
7d3cae70 8880 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8881 else
ae248832 8882 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8883 } else {
7d3cae70 8884 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8885 }
47fc97cc 8886
9df8b37c
PZ
8887 /*
8888 * If vrf id of nexthop is different from that of prefix,
8889 * set up printable string to append
8890 */
9b6d8fcf 8891 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8892 const char *self = "";
8893
8894 if (nexthop_self)
8895 self = "<";
8896
8897 nexthop_othervrf = true;
9b6d8fcf 8898 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8899
9b6d8fcf 8900 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8901 snprintf(vrf_id_str, sizeof(vrf_id_str),
8902 "@%s%s", VRFID_NONE_STR, self);
8903 else
8904 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8905 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8906
9b6d8fcf
DS
8907 if (path->extra->bgp_orig->inst_type
8908 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8909
9b6d8fcf 8910 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8911 } else {
8912 const char *self = "";
8913
8914 if (nexthop_self)
8915 self = "<";
8916
8917 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8918 }
8919
445c2480
DS
8920 /*
8921 * For ENCAP and EVPN routes, nexthop address family is not
8922 * neccessarily the same as the prefix address family.
8923 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8924 * EVPN routes are also exchanged with a MP nexthop. Currently,
8925 * this
8926 * is only IPv4, the value will be present in either
8927 * attr->nexthop or
8928 * attr->mp_nexthop_global_in
8929 */
8930 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8931 char buf[BUFSIZ];
8932 char nexthop[128];
8933 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8934
8935 switch (af) {
8936 case AF_INET:
772270f3
QY
8937 snprintf(nexthop, sizeof(nexthop), "%s",
8938 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8939 BUFSIZ));
445c2480
DS
8940 break;
8941 case AF_INET6:
772270f3
QY
8942 snprintf(nexthop, sizeof(nexthop), "%s",
8943 inet_ntop(af, &attr->mp_nexthop_global, buf,
8944 BUFSIZ));
445c2480
DS
8945 break;
8946 default:
772270f3 8947 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8948 break;
d62a17ae 8949 }
d62a17ae 8950
445c2480
DS
8951 if (json_paths) {
8952 json_nexthop_global = json_object_new_object();
8953
515c2602
DA
8954 json_object_string_add(json_nexthop_global, "ip",
8955 nexthop);
8956
939a97f4 8957 if (path->peer->hostname)
515c2602
DA
8958 json_object_string_add(json_nexthop_global,
8959 "hostname",
939a97f4 8960 path->peer->hostname);
515c2602
DA
8961
8962 json_object_string_add(json_nexthop_global, "afi",
8963 (af == AF_INET) ? "ipv4"
8964 : "ipv6");
445c2480
DS
8965 json_object_boolean_true_add(json_nexthop_global,
8966 "used");
aef999a2
DA
8967 } else {
8968 if (nexthop_hostname)
8969 len = vty_out(vty, "%s(%s)%s", nexthop,
8970 nexthop_hostname, vrf_id_str);
8971 else
8972 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8973
ae248832 8974 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8975 if (len < 1)
8976 vty_out(vty, "\n%*s", 36, " ");
8977 else
8978 vty_out(vty, "%*s", len, " ");
8979 }
445c2480
DS
8980 } else if (safi == SAFI_EVPN) {
8981 if (json_paths) {
8982 json_nexthop_global = json_object_new_object();
8983
c949c771 8984 json_object_string_addf(json_nexthop_global, "ip",
7226bc40
TA
8985 "%pI4",
8986 &attr->mp_nexthop_global_in);
515c2602 8987
939a97f4 8988 if (path->peer->hostname)
515c2602
DA
8989 json_object_string_add(json_nexthop_global,
8990 "hostname",
939a97f4 8991 path->peer->hostname);
515c2602 8992
a4d82a8a
PZ
8993 json_object_string_add(json_nexthop_global, "afi",
8994 "ipv4");
445c2480
DS
8995 json_object_boolean_true_add(json_nexthop_global,
8996 "used");
aef999a2
DA
8997 } else {
8998 if (nexthop_hostname)
7226bc40
TA
8999 len = vty_out(vty, "%pI4(%s)%s",
9000 &attr->mp_nexthop_global_in,
aef999a2
DA
9001 nexthop_hostname, vrf_id_str);
9002 else
7226bc40
TA
9003 len = vty_out(vty, "%pI4%s",
9004 &attr->mp_nexthop_global_in,
aef999a2
DA
9005 vrf_id_str);
9006
ae248832 9007 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9008 if (len < 1)
9009 vty_out(vty, "\n%*s", 36, " ");
9010 else
9011 vty_out(vty, "%*s", len, " ");
9012 }
d33fc23b 9013 } else if (safi == SAFI_FLOWSPEC) {
975a328e 9014 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
9015 if (json_paths) {
9016 json_nexthop_global = json_object_new_object();
515c2602 9017
026b914a
PG
9018 json_object_string_add(json_nexthop_global,
9019 "afi", "ipv4");
c949c771
DA
9020 json_object_string_addf(json_nexthop_global,
9021 "ip", "%pI4",
9022 &attr->nexthop);
515c2602 9023
939a97f4 9024 if (path->peer->hostname)
515c2602
DA
9025 json_object_string_add(
9026 json_nexthop_global, "hostname",
939a97f4 9027 path->peer->hostname);
515c2602 9028
50e05855
AD
9029 json_object_boolean_true_add(
9030 json_nexthop_global,
026b914a
PG
9031 "used");
9032 } else {
aef999a2
DA
9033 if (nexthop_hostname)
9034 len = vty_out(vty, "%pI4(%s)%s",
9035 &attr->nexthop,
9036 nexthop_hostname,
9037 vrf_id_str);
9038 else
9039 len = vty_out(vty, "%pI4%s",
9040 &attr->nexthop,
9041 vrf_id_str);
9042
ae248832 9043 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9044 if (len < 1)
9045 vty_out(vty, "\n%*s", 36, " ");
9046 else
9047 vty_out(vty, "%*s", len, " ");
026b914a
PG
9048 }
9049 }
7226bc40 9050 } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9051 if (json_paths) {
9052 json_nexthop_global = json_object_new_object();
d62a17ae 9053
c949c771
DA
9054 json_object_string_addf(json_nexthop_global, "ip",
9055 "%pI4", &attr->nexthop);
515c2602 9056
939a97f4 9057 if (path->peer->hostname)
515c2602
DA
9058 json_object_string_add(json_nexthop_global,
9059 "hostname",
939a97f4 9060 path->peer->hostname);
445c2480 9061
a4d82a8a
PZ
9062 json_object_string_add(json_nexthop_global, "afi",
9063 "ipv4");
445c2480
DS
9064 json_object_boolean_true_add(json_nexthop_global,
9065 "used");
9066 } else {
aef999a2
DA
9067 if (nexthop_hostname)
9068 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
9069 nexthop_hostname, vrf_id_str);
9070 else
9071 len = vty_out(vty, "%pI4%s", &attr->nexthop,
9072 vrf_id_str);
9df8b37c 9073
ae248832 9074 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
9075 if (len < 1)
9076 vty_out(vty, "\n%*s", 36, " ");
9077 else
9078 vty_out(vty, "%*s", len, " ");
d62a17ae 9079 }
445c2480 9080 }
b05a1c8b 9081
445c2480 9082 /* IPv6 Next Hop */
7226bc40 9083 else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
445c2480
DS
9084 if (json_paths) {
9085 json_nexthop_global = json_object_new_object();
c949c771
DA
9086 json_object_string_addf(json_nexthop_global, "ip",
9087 "%pI6",
9088 &attr->mp_nexthop_global);
515c2602 9089
939a97f4 9090 if (path->peer->hostname)
515c2602
DA
9091 json_object_string_add(json_nexthop_global,
9092 "hostname",
939a97f4 9093 path->peer->hostname);
515c2602 9094
a4d82a8a
PZ
9095 json_object_string_add(json_nexthop_global, "afi",
9096 "ipv6");
9097 json_object_string_add(json_nexthop_global, "scope",
9098 "global");
445c2480
DS
9099
9100 /* We display both LL & GL if both have been
9101 * received */
0606039c
DA
9102 if ((attr->mp_nexthop_len
9103 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9104 || (path->peer->conf_if)) {
a4d82a8a 9105 json_nexthop_ll = json_object_new_object();
c949c771
DA
9106 json_object_string_addf(
9107 json_nexthop_ll, "ip", "%pI6",
9108 &attr->mp_nexthop_local);
515c2602 9109
939a97f4 9110 if (path->peer->hostname)
515c2602
DA
9111 json_object_string_add(
9112 json_nexthop_ll, "hostname",
939a97f4 9113 path->peer->hostname);
515c2602 9114
a4d82a8a
PZ
9115 json_object_string_add(json_nexthop_ll, "afi",
9116 "ipv6");
9117 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9118 "link-local");
d62a17ae 9119
a4d82a8a
PZ
9120 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9121 &attr->mp_nexthop_local)
445c2480
DS
9122 != 0)
9123 && !attr->mp_nexthop_prefer_global)
d62a17ae 9124 json_object_boolean_true_add(
a4d82a8a 9125 json_nexthop_ll, "used");
445c2480
DS
9126 else
9127 json_object_boolean_true_add(
a4d82a8a 9128 json_nexthop_global, "used");
445c2480
DS
9129 } else
9130 json_object_boolean_true_add(
9131 json_nexthop_global, "used");
9132 } else {
9133 /* Display LL if LL/Global both in table unless
9134 * prefer-global is set */
0606039c
DA
9135 if (((attr->mp_nexthop_len
9136 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9137 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9138 || (path->peer->conf_if)) {
9139 if (path->peer->conf_if) {
a4d82a8a 9140 len = vty_out(vty, "%s",
9b6d8fcf 9141 path->peer->conf_if);
ae248832
MK
9142 /* len of IPv6 addr + max len of def
9143 * ifname */
9144 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9145
9146 if (len < 1)
a4d82a8a 9147 vty_out(vty, "\n%*s", 36, " ");
445c2480 9148 else
a4d82a8a 9149 vty_out(vty, "%*s", len, " ");
d62a17ae 9150 } else {
aef999a2
DA
9151 if (nexthop_hostname)
9152 len = vty_out(
9153 vty, "%pI6(%s)%s",
9154 &attr->mp_nexthop_local,
9155 nexthop_hostname,
9156 vrf_id_str);
9157 else
9158 len = vty_out(
9159 vty, "%pI6%s",
9160 &attr->mp_nexthop_local,
9161 vrf_id_str);
9162
ae248832 9163 len = wide ? (41 - len) : (16 - len);
d62a17ae 9164
9165 if (len < 1)
a4d82a8a 9166 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9167 else
a4d82a8a 9168 vty_out(vty, "%*s", len, " ");
d62a17ae 9169 }
445c2480 9170 } else {
aef999a2
DA
9171 if (nexthop_hostname)
9172 len = vty_out(vty, "%pI6(%s)%s",
9173 &attr->mp_nexthop_global,
9174 nexthop_hostname,
9175 vrf_id_str);
9176 else
9177 len = vty_out(vty, "%pI6%s",
9178 &attr->mp_nexthop_global,
9179 vrf_id_str);
9180
ae248832 9181 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9182
9183 if (len < 1)
9184 vty_out(vty, "\n%*s", 36, " ");
9185 else
9186 vty_out(vty, "%*s", len, " ");
d62a17ae 9187 }
9188 }
445c2480 9189 }
718e3744 9190
445c2480
DS
9191 /* MED/Metric */
9192 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9193 if (json_paths)
50e05855 9194 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9195 else if (wide)
9196 vty_out(vty, "%7u", attr->med);
0fbac0b4 9197 else
445c2480 9198 vty_out(vty, "%10u", attr->med);
ae248832
MK
9199 else if (!json_paths) {
9200 if (wide)
9201 vty_out(vty, "%*s", 7, " ");
9202 else
9203 vty_out(vty, "%*s", 10, " ");
9204 }
d62a17ae 9205
445c2480
DS
9206 /* Local Pref */
9207 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9208 if (json_paths)
50e05855 9209 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9210 attr->local_pref);
9211 else
445c2480
DS
9212 vty_out(vty, "%7u", attr->local_pref);
9213 else if (!json_paths)
9214 vty_out(vty, " ");
d62a17ae 9215
445c2480
DS
9216 if (json_paths)
9217 json_object_int_add(json_path, "weight", attr->weight);
9218 else
9219 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9220
47e12884
DA
9221 if (json_paths)
9222 json_object_string_addf(json_path, "peerId", "%pSU",
9223 &path->peer->su);
b05a1c8b 9224
445c2480
DS
9225 /* Print aspath */
9226 if (attr->aspath) {
0fbac0b4 9227 if (json_paths)
50e05855 9228 json_object_string_add(json_path, "path",
0fbac0b4
DA
9229 attr->aspath->str);
9230 else
445c2480 9231 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9232 }
f1aa5d8a 9233
445c2480
DS
9234 /* Print origin */
9235 if (json_paths)
a4d82a8a
PZ
9236 json_object_string_add(json_path, "origin",
9237 bgp_origin_long_str[attr->origin]);
445c2480
DS
9238 else
9239 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9240
9df8b37c 9241 if (json_paths) {
d071f237 9242 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9243 json_object_string_add(json_path, "esi",
9244 esi_to_str(&attr->esi,
9245 esi_buf, sizeof(esi_buf)));
9246 }
6f214dd3
CS
9247 if (safi == SAFI_EVPN &&
9248 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9249 json_ext_community = json_object_new_object();
b53e67a3
DA
9250 json_object_string_add(
9251 json_ext_community, "string",
9252 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9253 json_object_object_add(json_path,
9254 "extendedCommunity",
9255 json_ext_community);
9256 }
9257
9df8b37c
PZ
9258 if (nexthop_self)
9259 json_object_boolean_true_add(json_path,
9260 "announceNexthopSelf");
9261 if (nexthop_othervrf) {
9262 json_object_string_add(json_path, "nhVrfName",
9263 nexthop_vrfname);
9264
9265 json_object_int_add(json_path, "nhVrfId",
9266 ((nexthop_vrfid == VRF_UNKNOWN)
9267 ? -1
9268 : (int)nexthop_vrfid));
9269 }
9270 }
9271
d62a17ae 9272 if (json_paths) {
9273 if (json_nexthop_global || json_nexthop_ll) {
9274 json_nexthops = json_object_new_array();
f1aa5d8a 9275
d62a17ae 9276 if (json_nexthop_global)
9277 json_object_array_add(json_nexthops,
9278 json_nexthop_global);
f1aa5d8a 9279
d62a17ae 9280 if (json_nexthop_ll)
9281 json_object_array_add(json_nexthops,
9282 json_nexthop_ll);
f1aa5d8a 9283
d62a17ae 9284 json_object_object_add(json_path, "nexthops",
9285 json_nexthops);
9286 }
9287
9288 json_object_array_add(json_paths, json_path);
9289 } else {
9290 vty_out(vty, "\n");
6f214dd3 9291
b5e140c8 9292 if (safi == SAFI_EVPN) {
d071f237 9293 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9294 /* XXX - add these params to the json out */
b5e140c8 9295 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9296 vty_out(vty, "ESI:%s",
9297 esi_to_str(&attr->esi, esi_buf,
9298 sizeof(esi_buf)));
60605cbc 9299
229587fb 9300 vty_out(vty, "\n");
b5e140c8
AK
9301 }
9302 if (attr->flag &
9303 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9304 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9305 vty_out(vty, "%s\n",
9306 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9307 }
6f214dd3
CS
9308 }
9309
49e5a4a0 9310#ifdef ENABLE_BGP_VNC
d62a17ae 9311 /* prints an additional line, indented, with VNC info, if
9312 * present */
9313 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9314 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9315#endif
d62a17ae 9316 }
9317}
718e3744 9318
9319/* called from terminal list command */
7d3cae70
DA
9320void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9321 const struct prefix *p, struct attr *attr, safi_t safi,
9322 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9323{
9324 json_object *json_status = NULL;
9325 json_object *json_net = NULL;
aef999a2 9326 int len;
d62a17ae 9327 char buff[BUFSIZ];
dc387b0f 9328
d62a17ae 9329 /* Route status display. */
9330 if (use_json) {
9331 json_status = json_object_new_object();
9332 json_net = json_object_new_object();
9333 } else {
9334 vty_out(vty, "*");
9335 vty_out(vty, ">");
9336 vty_out(vty, " ");
9337 }
718e3744 9338
d62a17ae 9339 /* print prefix and mask */
50e05855 9340 if (use_json) {
dc387b0f
LK
9341 if (safi == SAFI_EVPN)
9342 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9343 else if (p->family == AF_INET || p->family == AF_INET6) {
9344 json_object_string_add(
9345 json_net, "addrPrefix",
9346 inet_ntop(p->family, &p->u.prefix, buff,
9347 BUFSIZ));
9348 json_object_int_add(json_net, "prefixLen",
9349 p->prefixlen);
67d7e256 9350 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9351 }
50e05855 9352 } else
7d3cae70 9353 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9354
9355 /* Print attribute */
9356 if (attr) {
9357 if (use_json) {
7226bc40
TA
9358 if (p->family == AF_INET &&
9359 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9360 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
dc387b0f 9361 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9362 json_object_string_addf(
9363 json_net, "nextHop", "%pI4",
9364 &attr->mp_nexthop_global_in);
d62a17ae 9365 else
c949c771
DA
9366 json_object_string_addf(
9367 json_net, "nextHop", "%pI4",
9368 &attr->nexthop);
7226bc40
TA
9369 } else if (p->family == AF_INET6 ||
9370 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
c949c771
DA
9371 json_object_string_addf(
9372 json_net, "nextHopGlobal", "%pI6",
9373 &attr->mp_nexthop_global);
7226bc40
TA
9374 } else if (p->family == AF_EVPN &&
9375 !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9376 json_object_string_addf(
9377 json_net, "nextHop", "%pI4",
9378 &attr->mp_nexthop_global_in);
23d0a753 9379 }
d62a17ae 9380
9381 if (attr->flag
9382 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9383 json_object_int_add(json_net, "metric",
9384 attr->med);
9385
0fbac0b4 9386 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9387 json_object_int_add(json_net, "locPrf",
0fbac0b4 9388 attr->local_pref);
d62a17ae 9389
9390 json_object_int_add(json_net, "weight", attr->weight);
9391
9392 /* Print aspath */
0fbac0b4 9393 if (attr->aspath)
50e05855 9394 json_object_string_add(json_net, "path",
0fbac0b4 9395 attr->aspath->str);
d62a17ae 9396
9397 /* Print origin */
9398 json_object_string_add(json_net, "bgpOriginCode",
9399 bgp_origin_str[attr->origin]);
9400 } else {
7226bc40
TA
9401 if (p->family == AF_INET &&
9402 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
9403 safi == SAFI_EVPN ||
9404 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 9405 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9406 || safi == SAFI_EVPN)
23d0a753
DA
9407 vty_out(vty, "%-16pI4",
9408 &attr->mp_nexthop_global_in);
ae248832 9409 else if (wide)
23d0a753 9410 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9411 else
23d0a753 9412 vty_out(vty, "%-16pI4", &attr->nexthop);
7226bc40
TA
9413 } else if (p->family == AF_INET6 ||
9414 BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
d62a17ae 9415 char buf[BUFSIZ];
9416
9417 len = vty_out(
9418 vty, "%s",
9419 inet_ntop(AF_INET6,
9420 &attr->mp_nexthop_global, buf,
9421 BUFSIZ));
ae248832 9422 len = wide ? (41 - len) : (16 - len);
d62a17ae 9423 if (len < 1)
9424 vty_out(vty, "\n%*s", 36, " ");
9425 else
9426 vty_out(vty, "%*s", len, " ");
9427 }
9428 if (attr->flag
9429 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9430 if (wide)
9431 vty_out(vty, "%7u", attr->med);
9432 else
9433 vty_out(vty, "%10u", attr->med);
9434 else if (wide)
9435 vty_out(vty, " ");
d62a17ae 9436 else
9437 vty_out(vty, " ");
718e3744 9438
d62a17ae 9439 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9440 vty_out(vty, "%7u", attr->local_pref);
9441 else
9442 vty_out(vty, " ");
9443
9444 vty_out(vty, "%7u ", attr->weight);
9445
9446 /* Print aspath */
9447 if (attr->aspath)
9448 aspath_print_vty(vty, "%s", attr->aspath, " ");
9449
9450 /* Print origin */
9451 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9452 }
9453 }
9454 if (use_json) {
9455 json_object_boolean_true_add(json_status, "*");
9456 json_object_boolean_true_add(json_status, ">");
9457 json_object_object_add(json_net, "appliedStatusSymbols",
9458 json_status);
1608ff77 9459
dc387b0f
LK
9460 prefix2str(p, buff, PREFIX_STRLEN);
9461 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9462 } else
9463 vty_out(vty, "\n");
9464}
9465
bd494ec5 9466void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9467 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9468 json_object *json)
9469{
9470 json_object *json_out = NULL;
9471 struct attr *attr;
9472 mpls_label_t label = MPLS_INVALID_LABEL;
9473
9b6d8fcf 9474 if (!path->extra)
d62a17ae 9475 return;
9476
9477 if (json)
9478 json_out = json_object_new_object();
9479
9480 /* short status lead text */
82c298be 9481 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9482
9483 /* print prefix and mask */
9484 if (json == NULL) {
9485 if (!display)
7d3cae70 9486 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9487 else
9488 vty_out(vty, "%*s", 17, " ");
9489 }
9490
9491 /* Print attribute */
9b6d8fcf 9492 attr = path->attr;
7226bc40
TA
9493 if (((p->family == AF_INET) &&
9494 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9495 (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
9496 (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9497 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9498 || safi == SAFI_EVPN) {
9499 if (json)
c949c771
DA
9500 json_object_string_addf(
9501 json_out, "mpNexthopGlobalIn", "%pI4",
9502 &attr->mp_nexthop_global_in);
05864da7 9503 else
23d0a753
DA
9504 vty_out(vty, "%-16pI4",
9505 &attr->mp_nexthop_global_in);
05864da7
DS
9506 } else {
9507 if (json)
c949c771
DA
9508 json_object_string_addf(json_out, "nexthop",
9509 "%pI4", &attr->nexthop);
05864da7 9510 else
23d0a753 9511 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7 9512 }
7226bc40
TA
9513 } else if (((p->family == AF_INET6) &&
9514 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
9515 (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
9516 (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
9517 char buf_a[512];
9518
9519 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9520 if (json)
c949c771
DA
9521 json_object_string_addf(
9522 json_out, "mpNexthopGlobalIn", "%pI6",
9523 &attr->mp_nexthop_global);
05864da7
DS
9524 else
9525 vty_out(vty, "%s",
9526 inet_ntop(AF_INET6,
9527 &attr->mp_nexthop_global,
9528 buf_a, sizeof(buf_a)));
9529 } else if (attr->mp_nexthop_len
9530 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9531 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9532 &attr->mp_nexthop_global,
9533 &attr->mp_nexthop_local);
9534 if (json)
9535 json_object_string_add(json_out,
9536 "mpNexthopGlobalLocal",
9537 buf_a);
9538 else
9539 vty_out(vty, "%s", buf_a);
d62a17ae 9540 }
9541 }
9542
9b6d8fcf 9543 label = decode_label(&path->extra->label[0]);
d62a17ae 9544
9545 if (bgp_is_valid_label(&label)) {
9546 if (json) {
9547 json_object_int_add(json_out, "notag", label);
9548 json_object_array_add(json, json_out);
9549 } else {
9550 vty_out(vty, "notag/%d", label);
9551 vty_out(vty, "\n");
9552 }
700ddfed
PG
9553 } else if (!json)
9554 vty_out(vty, "\n");
d62a17ae 9555}
718e3744 9556
bd494ec5 9557void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9558 struct bgp_path_info *path, int display,
d62a17ae 9559 json_object *json_paths)
718e3744 9560{
d62a17ae 9561 struct attr *attr;
d62a17ae 9562 json_object *json_path = NULL;
14f51eba
LK
9563 json_object *json_nexthop = NULL;
9564 json_object *json_overlay = NULL;
856ca177 9565
9b6d8fcf 9566 if (!path->extra)
d62a17ae 9567 return;
718e3744 9568
14f51eba
LK
9569 if (json_paths) {
9570 json_path = json_object_new_object();
9571 json_overlay = json_object_new_object();
9572 json_nexthop = json_object_new_object();
9573 }
9574
d62a17ae 9575 /* short status lead text */
82c298be 9576 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9577
d62a17ae 9578 /* print prefix and mask */
9579 if (!display)
7d3cae70 9580 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9581 else
9582 vty_out(vty, "%*s", 17, " ");
9583
9584 /* Print attribute */
9b6d8fcf 9585 attr = path->attr;
05864da7 9586 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9587
05864da7
DS
9588 switch (af) {
9589 case AF_INET:
05864da7 9590 if (!json_path) {
db66cf7c 9591 vty_out(vty, "%-16pI4", &attr->mp_nexthop_global_in);
05864da7 9592 } else {
db66cf7c
DA
9593 json_object_string_addf(json_nexthop, "ip", "%pI4",
9594 &attr->mp_nexthop_global_in);
14f51eba 9595
05864da7 9596 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9597
05864da7
DS
9598 json_object_object_add(json_path, "nexthop",
9599 json_nexthop);
9600 }
9601 break;
9602 case AF_INET6:
05864da7 9603 if (!json_path) {
db66cf7c
DA
9604 vty_out(vty, "%pI6(%pI6)", &attr->mp_nexthop_global,
9605 &attr->mp_nexthop_local);
05864da7 9606 } else {
db66cf7c
DA
9607 json_object_string_addf(json_nexthop, "ipv6Global",
9608 "%pI6",
9609 &attr->mp_nexthop_global);
14f51eba 9610
db66cf7c
DA
9611 json_object_string_addf(json_nexthop, "ipv6LinkLocal",
9612 "%pI6",
9613 &attr->mp_nexthop_local);
14f51eba 9614
05864da7 9615 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9616
05864da7
DS
9617 json_object_object_add(json_path, "nexthop",
9618 json_nexthop);
9619 }
9620 break;
9621 default:
9622 if (!json_path) {
9623 vty_out(vty, "?");
9624 } else {
9625 json_object_string_add(json_nexthop, "Error",
9626 "Unsupported address-family");
77a2f8e5
DA
9627 json_object_string_add(json_nexthop, "error",
9628 "Unsupported address-family");
d62a17ae 9629 }
05864da7 9630 }
988258b4 9631
6c924775
DS
9632 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9633
05864da7 9634 if (!json_path)
db66cf7c 9635 vty_out(vty, "/%pIA", &eo->gw_ip);
05864da7 9636 else
db66cf7c 9637 json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip);
05864da7 9638
b53e67a3 9639 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9640 char *mac = NULL;
9641 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9642 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9643 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9644
9645 if (routermac)
9646 mac = ecom_mac2str((char *)routermac->val);
9647 if (mac) {
9648 if (!json_path) {
c4efd0f4 9649 vty_out(vty, "/%s", mac);
05864da7
DS
9650 } else {
9651 json_object_string_add(json_overlay, "rmac",
9652 mac);
988258b4 9653 }
05864da7 9654 XFREE(MTYPE_TMP, mac);
988258b4 9655 }
05864da7 9656 }
718e3744 9657
05864da7
DS
9658 if (!json_path) {
9659 vty_out(vty, "\n");
9660 } else {
9661 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9662
05864da7 9663 json_object_array_add(json_paths, json_path);
14f51eba 9664 }
d62a17ae 9665}
718e3744 9666
d62a17ae 9667/* dampening route */
5f040085
DS
9668static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9669 struct bgp_path_info *path, int display,
9670 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9671 json_object *json_paths)
d62a17ae 9672{
e5be8c1d 9673 struct attr *attr = path->attr;
d62a17ae 9674 int len;
9675 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9676 json_object *json_path = NULL;
9677
9678 if (use_json)
9679 json_path = json_object_new_object();
d62a17ae 9680
9681 /* short status lead text */
e5be8c1d 9682 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9683
9684 /* print prefix and mask */
9685 if (!use_json) {
9686 if (!display)
7d3cae70 9687 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9688 else
9689 vty_out(vty, "%*s", 17, " ");
d62a17ae 9690
e5be8c1d
DA
9691 len = vty_out(vty, "%s", path->peer->host);
9692 len = 17 - len;
9693
9694 if (len < 1)
d62a17ae 9695 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9696 else
9697 vty_out(vty, "%*s", len, " ");
d62a17ae 9698
9b6d8fcf
DS
9699 vty_out(vty, "%s ",
9700 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9701 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9702 use_json, NULL));
d62a17ae 9703
e5be8c1d 9704 if (attr->aspath)
05864da7 9705 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9706
05864da7
DS
9707 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9708
d62a17ae 9709 vty_out(vty, "\n");
e5be8c1d
DA
9710 } else {
9711 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9712 safi, use_json, json_path);
9713
9714 if (attr->aspath)
9715 json_object_string_add(json_path, "asPath",
9716 attr->aspath->str);
9717
9718 json_object_string_add(json_path, "origin",
9719 bgp_origin_str[attr->origin]);
9720 json_object_string_add(json_path, "peerHost", path->peer->host);
9721
9722 json_object_array_add(json_paths, json_path);
9723 }
d62a17ae 9724}
718e3744 9725
d62a17ae 9726/* flap route */
5f040085
DS
9727static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9728 struct bgp_path_info *path, int display,
9729 afi_t afi, safi_t safi, bool use_json,
31258046 9730 json_object *json_paths)
784d3a42 9731{
31258046 9732 struct attr *attr = path->attr;
d62a17ae 9733 struct bgp_damp_info *bdi;
9734 char timebuf[BGP_UPTIME_LEN];
9735 int len;
31258046 9736 json_object *json_path = NULL;
784d3a42 9737
9b6d8fcf 9738 if (!path->extra)
d62a17ae 9739 return;
784d3a42 9740
31258046
DA
9741 if (use_json)
9742 json_path = json_object_new_object();
9743
9b6d8fcf 9744 bdi = path->extra->damp_info;
784d3a42 9745
d62a17ae 9746 /* short status lead text */
31258046 9747 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9748
d62a17ae 9749 if (!use_json) {
9750 if (!display)
7d3cae70 9751 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9752 else
9753 vty_out(vty, "%*s", 17, " ");
784d3a42 9754
31258046
DA
9755 len = vty_out(vty, "%s", path->peer->host);
9756 len = 16 - len;
9757 if (len < 1)
d62a17ae 9758 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9759 else
9760 vty_out(vty, "%*s", len, " ");
784d3a42 9761
31258046
DA
9762 len = vty_out(vty, "%d", bdi->flap);
9763 len = 5 - len;
9764 if (len < 1)
d62a17ae 9765 vty_out(vty, " ");
d62a17ae 9766 else
9767 vty_out(vty, "%*s", len, " ");
d62a17ae 9768
996c9314
LB
9769 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9770 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9771
31258046
DA
9772 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9773 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9774 vty_out(vty, "%s ",
9b6d8fcf 9775 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9776 BGP_UPTIME_LEN, afi,
31258046
DA
9777 safi, use_json, NULL));
9778 else
d62a17ae 9779 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9780
31258046 9781 if (attr->aspath)
05864da7 9782 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9783
05864da7
DS
9784 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9785
d62a17ae 9786 vty_out(vty, "\n");
31258046
DA
9787 } else {
9788 json_object_string_add(json_path, "peerHost", path->peer->host);
9789 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9790
9791 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9792 json_path);
9793
9794 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9795 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9796 bgp_damp_reuse_time_vty(vty, path, timebuf,
9797 BGP_UPTIME_LEN, afi, safi,
9798 use_json, json_path);
9799
9800 if (attr->aspath)
9801 json_object_string_add(json_path, "asPath",
9802 attr->aspath->str);
9803
9804 json_object_string_add(json_path, "origin",
9805 bgp_origin_str[attr->origin]);
9806
9807 json_object_array_add(json_paths, json_path);
9808 }
d62a17ae 9809}
9810
9811static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9812 int *first, const char *header,
9813 json_object *json_adv_to)
9814{
d62a17ae 9815 json_object *json_peer = NULL;
9816
9817 if (json_adv_to) {
9818 /* 'advertised-to' is a dictionary of peers we have advertised
9819 * this
9820 * prefix too. The key is the peer's IP or swpX, the value is
9821 * the
9822 * hostname if we know it and "" if not.
9823 */
9824 json_peer = json_object_new_object();
9825
9826 if (peer->hostname)
9827 json_object_string_add(json_peer, "hostname",
9828 peer->hostname);
9829
9830 if (peer->conf_if)
9831 json_object_object_add(json_adv_to, peer->conf_if,
9832 json_peer);
9833 else
47e12884
DA
9834 json_object_object_addf(json_adv_to, json_peer, "%pSU",
9835 &peer->su);
d62a17ae 9836 } else {
9837 if (*first) {
9838 vty_out(vty, "%s", header);
9839 *first = 0;
9840 }
9841
9842 if (peer->hostname
892fedb6 9843 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9844 if (peer->conf_if)
9845 vty_out(vty, " %s(%s)", peer->hostname,
9846 peer->conf_if);
9847 else
47e12884
DA
9848 vty_out(vty, " %s(%pSU)", peer->hostname,
9849 &peer->su);
d62a17ae 9850 } else {
9851 if (peer->conf_if)
9852 vty_out(vty, " %s", peer->conf_if);
9853 else
47e12884 9854 vty_out(vty, " %pSU", &peer->su);
d62a17ae 9855 }
9856 }
784d3a42
PG
9857}
9858
dcc68b5e
MS
9859static void route_vty_out_tx_ids(struct vty *vty,
9860 struct bgp_addpath_info_data *d)
9861{
9862 int i;
9863
9864 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9865 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9866 d->addpath_tx_id[i],
9867 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9868 }
9869}
9870
5e4d4c8a 9871static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9872 struct bgp_path_info *pi,
9873 struct attr *attr,
9874 json_object *json_path)
5e4d4c8a
AK
9875{
9876 char esi_buf[ESI_STR_LEN];
9877 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9878 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9879 ATTR_ES_PEER_ROUTER);
9880 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9881 ATTR_ES_PEER_ACTIVE);
9882 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9883 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9884 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9885 if (json_path) {
9886 json_object *json_es_info = NULL;
9887
9888 json_object_string_add(
9889 json_path, "esi",
9890 esi_buf);
9891 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9892 json_es_info = json_object_new_object();
9893 if (es_local)
9894 json_object_boolean_true_add(
9895 json_es_info, "localEs");
9896 if (peer_active)
9897 json_object_boolean_true_add(
9898 json_es_info, "peerActive");
9899 if (peer_proxy)
9900 json_object_boolean_true_add(
9901 json_es_info, "peerProxy");
9902 if (peer_router)
9903 json_object_boolean_true_add(
9904 json_es_info, "peerRouter");
9905 if (attr->mm_sync_seqnum)
9906 json_object_int_add(
9907 json_es_info, "peerSeq",
9908 attr->mm_sync_seqnum);
9909 json_object_object_add(
9910 json_path, "es_info",
9911 json_es_info);
9912 }
9913 } else {
9914 if (bgp_evpn_attr_is_sync(attr))
9915 vty_out(vty,
9916 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9917 esi_buf,
9918 es_local ? "local-es":"",
9919 peer_proxy ? "proxy " : "",
9920 peer_active ? "active ":"",
9921 peer_router ? "router ":"",
9922 attr->mm_sync_seqnum);
9923 else
9924 vty_out(vty, " ESI %s %s\n",
9925 esi_buf,
9926 es_local ? "local-es":"");
9927 }
9928}
9929
4933eaaf
DS
9930void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9931 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9932 enum rpki_states rpki_curr_state,
9933 json_object *json_paths)
d62a17ae 9934{
9935 char buf[INET6_ADDRSTRLEN];
9936 char buf1[BUFSIZ];
515c2602 9937 struct attr *attr = path->attr;
d62a17ae 9938 time_t tbuf;
9939 json_object *json_bestpath = NULL;
9940 json_object *json_cluster_list = NULL;
9941 json_object *json_cluster_list_list = NULL;
9942 json_object *json_ext_community = NULL;
9943 json_object *json_last_update = NULL;
7fd077aa 9944 json_object *json_pmsi = NULL;
d62a17ae 9945 json_object *json_nexthop_global = NULL;
9946 json_object *json_nexthop_ll = NULL;
9947 json_object *json_nexthops = NULL;
9948 json_object *json_path = NULL;
9949 json_object *json_peer = NULL;
9950 json_object *json_string = NULL;
9951 json_object *json_adv_to = NULL;
9952 int first = 0;
9953 struct listnode *node, *nnode;
9954 struct peer *peer;
be92fc9f 9955 bool addpath_capable;
d62a17ae 9956 int has_adj;
9957 unsigned int first_as;
1defdda8 9958 bool nexthop_self =
9b6d8fcf 9959 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9960 int i;
2ba93fd6
DA
9961 char *nexthop_hostname =
9962 bgp_nexthop_hostname(path->peer, path->nexthop);
67f67ba4
DA
9963 uint32_t ttl = 0;
9964 uint32_t bos = 0;
9965 uint32_t exp = 0;
9966 mpls_label_t label = MPLS_INVALID_LABEL;
d62a17ae 9967
9968 if (json_paths) {
9969 json_path = json_object_new_object();
9970 json_peer = json_object_new_object();
9971 json_nexthop_global = json_object_new_object();
9972 }
9973
8304dabf
AD
9974 if (safi == SAFI_EVPN) {
9975 if (!json_paths)
9976 vty_out(vty, " Route %pRN", bn);
9977 }
9978
44c69747 9979 if (path->extra) {
b57ba6d2 9980 char tag_buf[30];
d62a17ae 9981
d62a17ae 9982 tag_buf[0] = '\0';
9b6d8fcf
DS
9983 if (path->extra && path->extra->num_labels) {
9984 bgp_evpn_label2str(path->extra->label,
9985 path->extra->num_labels, tag_buf,
a4d82a8a 9986 sizeof(tag_buf));
d62a17ae 9987 }
d7325ee7 9988 if (safi == SAFI_EVPN) {
44c69747 9989 if (!json_paths) {
44c69747
LK
9990 if (tag_buf[0] != '\0')
9991 vty_out(vty, " VNI %s", tag_buf);
44c69747 9992 } else {
77a2f8e5 9993 if (tag_buf[0]) {
44c69747
LK
9994 json_object_string_add(json_path, "VNI",
9995 tag_buf);
77a2f8e5
DA
9996 json_object_string_add(json_path, "vni",
9997 tag_buf);
9998 }
44c69747 9999 }
d7325ee7
DD
10000 }
10001
44c69747 10002 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 10003 struct bgp_path_info *parent_ri;
9bcb3eef 10004 struct bgp_dest *dest, *pdest;
d62a17ae 10005
9b6d8fcf 10006 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
10007 dest = parent_ri->net;
10008 if (dest && dest->pdest) {
10009 pdest = dest->pdest;
10010 prefix_rd2str(
10011 (struct prefix_rd *)bgp_dest_get_prefix(
10012 pdest),
10013 buf1, sizeof(buf1));
d7325ee7 10014 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 10015 vty_out(vty,
58bff4d1 10016 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
10017 buf1,
10018 (struct prefix_evpn *)
10019 bgp_dest_get_prefix(
10020 dest),
10021 tag_buf);
58bff4d1
AK
10022 if (attr->es_flags & ATTR_ES_L3_NHG)
10023 vty_out(vty, ", L3NHG %s",
10024 (attr->es_flags
10025 & ATTR_ES_L3_NHG_ACTIVE)
10026 ? "active"
10027 : "inactive");
10028 vty_out(vty, "\n");
10029
d7325ee7 10030 } else
2dbe669b
DA
10031 vty_out(vty,
10032 " Imported from %s:%pFX\n",
10033 buf1,
10034 (struct prefix_evpn *)
10035 bgp_dest_get_prefix(
10036 dest));
d62a17ae 10037 }
10038 }
10039 }
d62a17ae 10040
8304dabf
AD
10041 if (safi == SAFI_EVPN
10042 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
10043 char gwip_buf[INET6_ADDRSTRLEN];
10044
860e740b
IR
10045 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
10046 sizeof(gwip_buf));
8304dabf
AD
10047
10048 if (json_paths)
10049 json_object_string_add(json_path, "gatewayIP",
10050 gwip_buf);
10051 else
10052 vty_out(vty, " Gateway IP %s", gwip_buf);
10053 }
10054
10055 if (safi == SAFI_EVPN)
10056 vty_out(vty, "\n");
10057
05864da7
DS
10058 /* Line1 display AS-path, Aggregator */
10059 if (attr->aspath) {
10060 if (json_paths) {
10061 if (!attr->aspath->json)
10062 aspath_str_update(attr->aspath, true);
10063 json_object_lock(attr->aspath->json);
10064 json_object_object_add(json_path, "aspath",
10065 attr->aspath->json);
10066 } else {
10067 if (attr->aspath->segments)
10068 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 10069 else
05864da7 10070 vty_out(vty, " Local");
d62a17ae 10071 }
05864da7 10072 }
d62a17ae 10073
05864da7
DS
10074 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
10075 if (json_paths)
10076 json_object_boolean_true_add(json_path, "removed");
10077 else
10078 vty_out(vty, ", (removed)");
10079 }
d62a17ae 10080
05864da7
DS
10081 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10082 if (json_paths)
10083 json_object_boolean_true_add(json_path, "stale");
10084 else
10085 vty_out(vty, ", (stale)");
10086 }
d62a17ae 10087
05864da7
DS
10088 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10089 if (json_paths) {
10090 json_object_int_add(json_path, "aggregatorAs",
10091 attr->aggregator_as);
c949c771
DA
10092 json_object_string_addf(json_path, "aggregatorId",
10093 "%pI4", &attr->aggregator_addr);
05864da7 10094 } else {
88d495a9
DA
10095 vty_out(vty, ", (aggregated by %u %pI4)",
10096 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10097 }
05864da7 10098 }
d62a17ae 10099
05864da7
DS
10100 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10101 PEER_FLAG_REFLECTOR_CLIENT)) {
10102 if (json_paths)
10103 json_object_boolean_true_add(json_path,
10104 "rxedFromRrClient");
10105 else
10106 vty_out(vty, ", (Received from a RR-client)");
10107 }
d62a17ae 10108
05864da7
DS
10109 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10110 PEER_FLAG_RSERVER_CLIENT)) {
10111 if (json_paths)
10112 json_object_boolean_true_add(json_path,
10113 "rxedFromRsClient");
10114 else
10115 vty_out(vty, ", (Received from a RS-client)");
10116 }
d62a17ae 10117
05864da7
DS
10118 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10119 if (json_paths)
10120 json_object_boolean_true_add(json_path,
10121 "dampeningHistoryEntry");
10122 else
10123 vty_out(vty, ", (history entry)");
10124 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10125 if (json_paths)
10126 json_object_boolean_true_add(json_path,
10127 "dampeningSuppressed");
10128 else
10129 vty_out(vty, ", (suppressed due to dampening)");
10130 }
d62a17ae 10131
05864da7
DS
10132 if (!json_paths)
10133 vty_out(vty, "\n");
d62a17ae 10134
05864da7
DS
10135 /* Line2 display Next-hop, Neighbor, Router-id */
10136 /* Display the nexthop */
9bcb3eef 10137 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0 10138
7226bc40
TA
10139 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
10140 bn_p->family == AF_EVPN) &&
10141 (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
10142 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
05864da7
DS
10143 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10144 || safi == SAFI_EVPN) {
515c2602 10145 if (json_paths) {
c949c771
DA
10146 json_object_string_addf(
10147 json_nexthop_global, "ip", "%pI4",
10148 &attr->mp_nexthop_global_in);
515c2602 10149
939a97f4 10150 if (path->peer->hostname)
515c2602
DA
10151 json_object_string_add(
10152 json_nexthop_global, "hostname",
939a97f4 10153 path->peer->hostname);
aef999a2
DA
10154 } else {
10155 if (nexthop_hostname)
10156 vty_out(vty, " %pI4(%s)",
10157 &attr->mp_nexthop_global_in,
10158 nexthop_hostname);
10159 else
10160 vty_out(vty, " %pI4",
10161 &attr->mp_nexthop_global_in);
10162 }
d62a17ae 10163 } else {
515c2602 10164 if (json_paths) {
c949c771
DA
10165 json_object_string_addf(json_nexthop_global,
10166 "ip", "%pI4",
10167 &attr->nexthop);
515c2602 10168
939a97f4 10169 if (path->peer->hostname)
515c2602
DA
10170 json_object_string_add(
10171 json_nexthop_global, "hostname",
939a97f4 10172 path->peer->hostname);
aef999a2
DA
10173 } else {
10174 if (nexthop_hostname)
10175 vty_out(vty, " %pI4(%s)",
10176 &attr->nexthop,
10177 nexthop_hostname);
10178 else
10179 vty_out(vty, " %pI4",
10180 &attr->nexthop);
10181 }
d62a17ae 10182 }
10183
05864da7
DS
10184 if (json_paths)
10185 json_object_string_add(json_nexthop_global, "afi",
10186 "ipv4");
10187 } else {
10188 if (json_paths) {
c949c771
DA
10189 json_object_string_addf(json_nexthop_global, "ip",
10190 "%pI6",
10191 &attr->mp_nexthop_global);
515c2602 10192
939a97f4 10193 if (path->peer->hostname)
515c2602
DA
10194 json_object_string_add(json_nexthop_global,
10195 "hostname",
939a97f4 10196 path->peer->hostname);
515c2602 10197
05864da7
DS
10198 json_object_string_add(json_nexthop_global, "afi",
10199 "ipv6");
10200 json_object_string_add(json_nexthop_global, "scope",
10201 "global");
10202 } else {
aef999a2
DA
10203 if (nexthop_hostname)
10204 vty_out(vty, " %pI6(%s)",
10205 &attr->mp_nexthop_global,
10206 nexthop_hostname);
10207 else
10208 vty_out(vty, " %pI6",
10209 &attr->mp_nexthop_global);
d62a17ae 10210 }
05864da7 10211 }
d62a17ae 10212
05864da7
DS
10213 /* Display the IGP cost or 'inaccessible' */
10214 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10215 if (json_paths)
10216 json_object_boolean_false_add(json_nexthop_global,
10217 "accessible");
10218 else
10219 vty_out(vty, " (inaccessible)");
10220 } else {
10221 if (path->extra && path->extra->igpmetric) {
d62a17ae 10222 if (json_paths)
05864da7
DS
10223 json_object_int_add(json_nexthop_global,
10224 "metric",
10225 path->extra->igpmetric);
d62a17ae 10226 else
05864da7
DS
10227 vty_out(vty, " (metric %u)",
10228 path->extra->igpmetric);
d62a17ae 10229 }
10230
05864da7 10231 /* IGP cost is 0, display this only for json */
d62a17ae 10232 else {
d62a17ae 10233 if (json_paths)
05864da7
DS
10234 json_object_int_add(json_nexthop_global,
10235 "metric", 0);
d62a17ae 10236 }
d62a17ae 10237
05864da7
DS
10238 if (json_paths)
10239 json_object_boolean_true_add(json_nexthop_global,
10240 "accessible");
10241 }
d62a17ae 10242
05864da7
DS
10243 /* Display peer "from" output */
10244 /* This path was originated locally */
10245 if (path->peer == bgp->peer_self) {
d62a17ae 10246
7226bc40
TA
10247 if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
10248 !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
d62a17ae 10249 if (json_paths)
05864da7
DS
10250 json_object_string_add(json_peer, "peerId",
10251 "0.0.0.0");
d62a17ae 10252 else
05864da7
DS
10253 vty_out(vty, " from 0.0.0.0 ");
10254 } else {
d62a17ae 10255 if (json_paths)
05864da7
DS
10256 json_object_string_add(json_peer, "peerId",
10257 "::");
d62a17ae 10258 else
05864da7 10259 vty_out(vty, " from :: ");
d62a17ae 10260 }
d62a17ae 10261
4e9a9863 10262 if (json_paths)
c949c771
DA
10263 json_object_string_addf(json_peer, "routerId", "%pI4",
10264 &bgp->router_id);
4e9a9863 10265 else
23d0a753 10266 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10267 }
d62a17ae 10268
05864da7
DS
10269 /* We RXed this path from one of our peers */
10270 else {
10271
10272 if (json_paths) {
47e12884
DA
10273 json_object_string_addf(json_peer, "peerId", "%pSU",
10274 &path->peer->su);
c949c771
DA
10275 json_object_string_addf(json_peer, "routerId", "%pI4",
10276 &path->peer->remote_id);
05864da7
DS
10277
10278 if (path->peer->hostname)
10279 json_object_string_add(json_peer, "hostname",
10280 path->peer->hostname);
10281
10282 if (path->peer->domainname)
10283 json_object_string_add(json_peer, "domainname",
10284 path->peer->domainname);
10285
10286 if (path->peer->conf_if)
10287 json_object_string_add(json_peer, "interface",
10288 path->peer->conf_if);
10289 } else {
10290 if (path->peer->conf_if) {
10291 if (path->peer->hostname
892fedb6
DA
10292 && CHECK_FLAG(path->peer->bgp->flags,
10293 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10294 vty_out(vty, " from %s(%s)",
10295 path->peer->hostname,
10296 path->peer->conf_if);
d62a17ae 10297 else
05864da7 10298 vty_out(vty, " from %s",
9b6d8fcf 10299 path->peer->conf_if);
d62a17ae 10300 } else {
05864da7 10301 if (path->peer->hostname
892fedb6
DA
10302 && CHECK_FLAG(path->peer->bgp->flags,
10303 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10304 vty_out(vty, " from %s(%s)",
10305 path->peer->hostname,
10306 path->peer->host);
d62a17ae 10307 else
47e12884
DA
10308 vty_out(vty, " from %pSU",
10309 &path->peer->su);
d62a17ae 10310 }
d62a17ae 10311
05864da7 10312 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10313 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10314 else
10315 vty_out(vty, " (%s)",
10316 inet_ntop(AF_INET,
10317 &path->peer->remote_id, buf1,
10318 sizeof(buf1)));
d62a17ae 10319 }
05864da7 10320 }
9df8b37c 10321
05864da7
DS
10322 /*
10323 * Note when vrfid of nexthop is different from that of prefix
10324 */
10325 if (path->extra && path->extra->bgp_orig) {
10326 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10327
05864da7
DS
10328 if (json_paths) {
10329 const char *vn;
9df8b37c 10330
05864da7
DS
10331 if (path->extra->bgp_orig->inst_type
10332 == BGP_INSTANCE_TYPE_DEFAULT)
10333 vn = VRF_DEFAULT_NAME;
10334 else
10335 vn = path->extra->bgp_orig->name;
9df8b37c 10336
05864da7 10337 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10338
05864da7
DS
10339 if (nexthop_vrfid == VRF_UNKNOWN) {
10340 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10341 } else {
05864da7
DS
10342 json_object_int_add(json_path, "nhVrfId",
10343 (int)nexthop_vrfid);
9df8b37c 10344 }
05864da7
DS
10345 } else {
10346 if (nexthop_vrfid == VRF_UNKNOWN)
10347 vty_out(vty, " vrf ?");
137147c6
DS
10348 else {
10349 struct vrf *vrf;
10350
10351 vrf = vrf_lookup_by_id(nexthop_vrfid);
10352 vty_out(vty, " vrf %s(%u)",
10353 VRF_LOGNAME(vrf), nexthop_vrfid);
10354 }
9df8b37c 10355 }
05864da7 10356 }
9df8b37c 10357
05864da7
DS
10358 if (nexthop_self) {
10359 if (json_paths) {
10360 json_object_boolean_true_add(json_path,
10361 "announceNexthopSelf");
10362 } else {
10363 vty_out(vty, " announce-nh-self");
9df8b37c 10364 }
05864da7 10365 }
9df8b37c 10366
05864da7
DS
10367 if (!json_paths)
10368 vty_out(vty, "\n");
d62a17ae 10369
05864da7
DS
10370 /* display the link-local nexthop */
10371 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10372 if (json_paths) {
10373 json_nexthop_ll = json_object_new_object();
c949c771
DA
10374 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10375 &attr->mp_nexthop_local);
515c2602 10376
939a97f4 10377 if (path->peer->hostname)
515c2602
DA
10378 json_object_string_add(json_nexthop_ll,
10379 "hostname",
939a97f4 10380 path->peer->hostname);
515c2602 10381
05864da7
DS
10382 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10383 json_object_string_add(json_nexthop_ll, "scope",
10384 "link-local");
d62a17ae 10385
05864da7
DS
10386 json_object_boolean_true_add(json_nexthop_ll,
10387 "accessible");
d62a17ae 10388
05864da7 10389 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10390 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10391 "used");
10392 else
10393 json_object_boolean_true_add(
10394 json_nexthop_global, "used");
10395 } else {
10396 vty_out(vty, " (%s) %s\n",
10397 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10398 buf, INET6_ADDRSTRLEN),
10399 attr->mp_nexthop_prefer_global
10400 ? "(prefer-global)"
10401 : "(used)");
d62a17ae 10402 }
05864da7
DS
10403 }
10404 /* If we do not have a link-local nexthop then we must flag the
10405 global as "used" */
10406 else {
10407 if (json_paths)
10408 json_object_boolean_true_add(json_nexthop_global,
10409 "used");
10410 }
d62a17ae 10411
b5e140c8 10412 if (safi == SAFI_EVPN &&
5e4d4c8a 10413 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10414 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10415 }
10416
05864da7
DS
10417 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10418 * Int/Ext/Local, Atomic, best */
10419 if (json_paths)
10420 json_object_string_add(json_path, "origin",
10421 bgp_origin_long_str[attr->origin]);
10422 else
10423 vty_out(vty, " Origin %s",
10424 bgp_origin_long_str[attr->origin]);
9df8b37c 10425
05864da7 10426 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10427 if (json_paths)
05864da7 10428 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10429 else
05864da7
DS
10430 vty_out(vty, ", metric %u", attr->med);
10431 }
9df8b37c 10432
05864da7
DS
10433 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10434 if (json_paths)
0fbac0b4 10435 json_object_int_add(json_path, "locPrf",
05864da7
DS
10436 attr->local_pref);
10437 else
10438 vty_out(vty, ", localpref %u", attr->local_pref);
10439 }
9df8b37c 10440
05864da7
DS
10441 if (attr->weight != 0) {
10442 if (json_paths)
10443 json_object_int_add(json_path, "weight", attr->weight);
10444 else
10445 vty_out(vty, ", weight %u", attr->weight);
10446 }
9df8b37c 10447
05864da7
DS
10448 if (attr->tag != 0) {
10449 if (json_paths)
10450 json_object_int_add(json_path, "tag", attr->tag);
10451 else
10452 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10453 }
9df8b37c 10454
05864da7
DS
10455 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10456 if (json_paths)
10457 json_object_boolean_false_add(json_path, "valid");
10458 else
10459 vty_out(vty, ", invalid");
10460 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10461 if (json_paths)
10462 json_object_boolean_true_add(json_path, "valid");
10463 else
10464 vty_out(vty, ", valid");
10465 }
9df8b37c 10466
7d3cae70
DA
10467 if (json_paths)
10468 json_object_int_add(json_path, "version", bn->version);
10469
05864da7
DS
10470 if (path->peer != bgp->peer_self) {
10471 if (path->peer->as == path->peer->local_as) {
10472 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10473 if (json_paths)
10474 json_object_string_add(
10475 json_peer, "type",
10476 "confed-internal");
d62a17ae 10477 else
05864da7 10478 vty_out(vty, ", confed-internal");
d62a17ae 10479 } else {
05864da7
DS
10480 if (json_paths)
10481 json_object_string_add(
10482 json_peer, "type", "internal");
10483 else
10484 vty_out(vty, ", internal");
9df8b37c 10485 }
05864da7
DS
10486 } else {
10487 if (bgp_confederation_peers_check(bgp,
10488 path->peer->as)) {
10489 if (json_paths)
10490 json_object_string_add(
10491 json_peer, "type",
10492 "confed-external");
d62a17ae 10493 else
05864da7 10494 vty_out(vty, ", confed-external");
d62a17ae 10495 } else {
05864da7
DS
10496 if (json_paths)
10497 json_object_string_add(
10498 json_peer, "type", "external");
10499 else
10500 vty_out(vty, ", external");
d62a17ae 10501 }
10502 }
05864da7
DS
10503 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10504 if (json_paths) {
10505 json_object_boolean_true_add(json_path, "aggregated");
10506 json_object_boolean_true_add(json_path, "local");
10507 } else {
10508 vty_out(vty, ", aggregated, local");
10509 }
10510 } else if (path->type != ZEBRA_ROUTE_BGP) {
10511 if (json_paths)
10512 json_object_boolean_true_add(json_path, "sourced");
10513 else
10514 vty_out(vty, ", sourced");
10515 } else {
10516 if (json_paths) {
10517 json_object_boolean_true_add(json_path, "sourced");
10518 json_object_boolean_true_add(json_path, "local");
10519 } else {
10520 vty_out(vty, ", sourced, local");
d62a17ae 10521 }
05864da7 10522 }
718e3744 10523
05864da7 10524 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10525 if (json_paths)
05864da7
DS
10526 json_object_boolean_true_add(json_path,
10527 "atomicAggregate");
d62a17ae 10528 else
05864da7
DS
10529 vty_out(vty, ", atomic-aggregate");
10530 }
d62a17ae 10531
d864dd9e
EB
10532 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
10533 if (json_paths)
10534 json_object_int_add(json_path, "otc", attr->otc);
10535 else
10536 vty_out(vty, ", otc %u", attr->otc);
10537 }
10538
05864da7
DS
10539 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10540 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10541 && bgp_path_info_mpath_count(path))) {
10542 if (json_paths)
10543 json_object_boolean_true_add(json_path, "multipath");
10544 else
10545 vty_out(vty, ", multipath");
10546 }
50e05855 10547
05864da7
DS
10548 // Mark the bestpath(s)
10549 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10550 first_as = aspath_get_first_as(attr->aspath);
718e3744 10551
05864da7
DS
10552 if (json_paths) {
10553 if (!json_bestpath)
10554 json_bestpath = json_object_new_object();
10555 json_object_int_add(json_bestpath, "bestpathFromAs",
10556 first_as);
10557 } else {
10558 if (first_as)
10559 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10560 else
05864da7 10561 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10562 }
05864da7 10563 }
718e3744 10564
05864da7
DS
10565 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10566 if (json_paths) {
10567 if (!json_bestpath)
10568 json_bestpath = json_object_new_object();
10569 json_object_boolean_true_add(json_bestpath, "overall");
10570 json_object_string_add(
10571 json_bestpath, "selectionReason",
10572 bgp_path_selection_reason2str(bn->reason));
10573 } else {
10574 vty_out(vty, ", best");
10575 vty_out(vty, " (%s)",
10576 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10577 }
05864da7 10578 }
718e3744 10579
4027d19b 10580 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10581 if (json_paths)
10582 json_object_string_add(
10583 json_path, "rpkiValidationState",
4027d19b 10584 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10585 else
1d327209 10586 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10587 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10588 }
10589
05864da7
DS
10590 if (json_bestpath)
10591 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10592
05864da7
DS
10593 if (!json_paths)
10594 vty_out(vty, "\n");
10595
10596 /* Line 4 display Community */
29e72930 10597 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7 10598 if (json_paths) {
9a706b42
DA
10599 if (!bgp_attr_get_community(attr)->json)
10600 community_str(bgp_attr_get_community(attr),
c0945b78 10601 true, true);
9a706b42
DA
10602 json_object_lock(bgp_attr_get_community(attr)->json);
10603 json_object_object_add(
10604 json_path, "community",
10605 bgp_attr_get_community(attr)->json);
05864da7
DS
10606 } else {
10607 vty_out(vty, " Community: %s\n",
9a706b42 10608 bgp_attr_get_community(attr)->str);
d62a17ae 10609 }
05864da7 10610 }
718e3744 10611
05864da7
DS
10612 /* Line 5 display Extended-community */
10613 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10614 if (json_paths) {
10615 json_ext_community = json_object_new_object();
b53e67a3
DA
10616 json_object_string_add(
10617 json_ext_community, "string",
10618 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10619 json_object_object_add(json_path, "extendedCommunity",
10620 json_ext_community);
d62a17ae 10621 } else {
05864da7 10622 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10623 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10624 }
05864da7 10625 }
718e3744 10626
05864da7
DS
10627 /* Line 6 display Large community */
10628 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10629 if (json_paths) {
1bcf3a96
DA
10630 if (!bgp_attr_get_lcommunity(attr)->json)
10631 lcommunity_str(bgp_attr_get_lcommunity(attr),
c0945b78 10632 true, true);
1bcf3a96
DA
10633 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10634 json_object_object_add(
10635 json_path, "largeCommunity",
10636 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10637 } else {
10638 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10639 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10640 }
05864da7 10641 }
718e3744 10642
05864da7
DS
10643 /* Line 7 display Originator, Cluster-id */
10644 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10645 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10646 char buf[BUFSIZ] = {0};
10647
05864da7 10648 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10649 if (json_paths)
c949c771
DA
10650 json_object_string_addf(json_path,
10651 "originatorId", "%pI4",
10652 &attr->originator_id);
d62a17ae 10653 else
23d0a753
DA
10654 vty_out(vty, " Originator: %pI4",
10655 &attr->originator_id);
d62a17ae 10656 }
856ca177 10657
05864da7 10658 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10659 struct cluster_list *cluster =
10660 bgp_attr_get_cluster(attr);
05864da7 10661 int i;
d62a17ae 10662
10663 if (json_paths) {
05864da7
DS
10664 json_cluster_list = json_object_new_object();
10665 json_cluster_list_list =
10666 json_object_new_array();
10667
779fee93 10668 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10669 json_string = json_object_new_string(
779fee93
DS
10670 inet_ntop(AF_INET,
10671 &cluster->list[i],
10672 buf, sizeof(buf)));
05864da7
DS
10673 json_object_array_add(
10674 json_cluster_list_list,
10675 json_string);
10676 }
718e3744 10677
05864da7
DS
10678 /*
10679 * struct cluster_list does not have
10680 * "str" variable like aspath and community
10681 * do. Add this someday if someone asks
10682 * for it.
10683 * json_object_string_add(json_cluster_list,
779fee93 10684 * "string", cluster->str);
05864da7
DS
10685 */
10686 json_object_object_add(json_cluster_list,
10687 "list",
10688 json_cluster_list_list);
10689 json_object_object_add(json_path, "clusterList",
10690 json_cluster_list);
0dc8ee70 10691 } else {
05864da7
DS
10692 vty_out(vty, ", Cluster list: ");
10693
779fee93 10694 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10695 vty_out(vty, "%pI4 ",
779fee93 10696 &cluster->list[i]);
05864da7 10697 }
0dc8ee70 10698 }
d62a17ae 10699 }
718e3744 10700
d62a17ae 10701 if (!json_paths)
10702 vty_out(vty, "\n");
05864da7 10703 }
d62a17ae 10704
05864da7 10705 if (path->extra && path->extra->damp_info)
b4f7f45b 10706 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10707
05864da7
DS
10708 /* Remote Label */
10709 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10710 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
67f67ba4
DA
10711 mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
10712 &bos);
d62a17ae 10713
05864da7
DS
10714 if (json_paths)
10715 json_object_int_add(json_path, "remoteLabel", label);
10716 else
10717 vty_out(vty, " Remote label: %d\n", label);
10718 }
d62a17ae 10719
e496b420
HS
10720 /* Remote SID */
10721 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10722 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10723 if (json_paths)
10724 json_object_string_add(json_path, "remoteSid", buf);
10725 else
10726 vty_out(vty, " Remote SID: %s\n", buf);
10727 }
10728
05864da7
DS
10729 /* Label Index */
10730 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10731 if (json_paths)
10732 json_object_int_add(json_path, "labelIndex",
10733 attr->label_index);
10734 else
10735 vty_out(vty, " Label Index: %d\n",
10736 attr->label_index);
10737 }
d62a17ae 10738
05864da7
DS
10739 /* Line 8 display Addpath IDs */
10740 if (path->addpath_rx_id
10741 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10742 if (json_paths) {
10743 json_object_int_add(json_path, "addpathRxId",
10744 path->addpath_rx_id);
d62a17ae 10745
05864da7
DS
10746 /* Keep backwards compatibility with the old API
10747 * by putting TX All's ID in the old field
10748 */
10749 json_object_int_add(
10750 json_path, "addpathTxId",
10751 path->tx_addpath
10752 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10753
05864da7
DS
10754 /* ... but create a specific field for each
10755 * strategy
10756 */
10757 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10758 json_object_int_add(
10759 json_path,
10760 bgp_addpath_names(i)->id_json_name,
10761 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10762 }
05864da7
DS
10763 } else {
10764 vty_out(vty, " AddPath ID: RX %u, ",
10765 path->addpath_rx_id);
d62a17ae 10766
05864da7 10767 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10768 }
05864da7 10769 }
520d5d76 10770
05864da7
DS
10771 /* If we used addpath to TX a non-bestpath we need to display
10772 * "Advertised to" on a path-by-path basis
10773 */
10774 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10775 first = 1;
dcc68b5e 10776
05864da7
DS
10777 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10778 addpath_capable =
10779 bgp_addpath_encode_tx(peer, afi, safi);
10780 has_adj = bgp_adj_out_lookup(
10781 peer, path->net,
10782 bgp_addpath_id_for_peer(peer, afi, safi,
10783 &path->tx_addpath));
10784
10785 if ((addpath_capable && has_adj)
10786 || (!addpath_capable && has_adj
10787 && CHECK_FLAG(path->flags,
10788 BGP_PATH_SELECTED))) {
10789 if (json_path && !json_adv_to)
10790 json_adv_to = json_object_new_object();
dcc68b5e 10791
05864da7
DS
10792 route_vty_out_advertised_to(
10793 vty, peer, &first,
10794 " Advertised to:", json_adv_to);
d62a17ae 10795 }
10796 }
718e3744 10797
05864da7
DS
10798 if (json_path) {
10799 if (json_adv_to) {
10800 json_object_object_add(
10801 json_path, "advertisedTo", json_adv_to);
d62a17ae 10802 }
05864da7
DS
10803 } else {
10804 if (!first) {
10805 vty_out(vty, "\n");
d62a17ae 10806 }
10807 }
05864da7 10808 }
b05a1c8b 10809
05864da7
DS
10810 /* Line 9 display Uptime */
10811 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10812 if (json_paths) {
10813 json_last_update = json_object_new_object();
10814 json_object_int_add(json_last_update, "epoch", tbuf);
10815 json_object_string_add(json_last_update, "string",
10816 ctime(&tbuf));
10817 json_object_object_add(json_path, "lastUpdate",
10818 json_last_update);
10819 } else
10820 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10821
05864da7
DS
10822 /* Line 10 display PMSI tunnel attribute, if present */
10823 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10824 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10825 bgp_attr_get_pmsi_tnl_type(attr),
10826 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10827
05864da7
DS
10828 if (json_paths) {
10829 json_pmsi = json_object_new_object();
10830 json_object_string_add(json_pmsi, "tunnelType", str);
10831 json_object_int_add(json_pmsi, "label",
10832 label2vni(&attr->label));
10833 json_object_object_add(json_path, "pmsi", json_pmsi);
10834 } else
10835 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10836 str, label2vni(&attr->label));
d62a17ae 10837 }
f1aa5d8a 10838
848e8cf6
DA
10839 if (path->peer->t_gr_restart &&
10840 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10841 unsigned long gr_remaining =
10842 thread_timer_remain_second(path->peer->t_gr_restart);
10843
10844 if (json_paths) {
10845 json_object_int_add(json_path,
10846 "gracefulRestartSecondsRemaining",
10847 gr_remaining);
10848 } else
10849 vty_out(vty,
10850 " Time until Graceful Restart stale route deleted: %lu\n",
10851 gr_remaining);
10852 }
10853
9a706b42
DA
10854 if (path->peer->t_llgr_stale[afi][safi] &&
10855 bgp_attr_get_community(attr) &&
10856 community_include(bgp_attr_get_community(attr),
10857 COMMUNITY_LLGR_STALE)) {
48ebba04
DA
10858 unsigned long llgr_remaining = thread_timer_remain_second(
10859 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10860
48ebba04
DA
10861 if (json_paths) {
10862 json_object_int_add(json_path, "llgrSecondsRemaining",
10863 llgr_remaining);
10864 } else
10865 vty_out(vty,
10866 " Time until Long-lived stale route deleted: %lu\n",
10867 llgr_remaining);
10868 }
10869
92269aa2
DS
10870 /* Output some debug about internal state of the dest flags */
10871 if (json_paths) {
10872 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10873 json_object_boolean_true_add(json_path, "processScheduled");
10874 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10875 json_object_boolean_true_add(json_path, "userCleared");
10876 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10877 json_object_boolean_true_add(json_path, "labelChanged");
10878 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10879 json_object_boolean_true_add(json_path, "registeredForLabel");
10880 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10881 json_object_boolean_true_add(json_path, "selectDefered");
10882 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10883 json_object_boolean_true_add(json_path, "fibInstalled");
10884 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10885 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10886
d62a17ae 10887 if (json_nexthop_global || json_nexthop_ll) {
10888 json_nexthops = json_object_new_array();
f1aa5d8a 10889
d62a17ae 10890 if (json_nexthop_global)
10891 json_object_array_add(json_nexthops,
10892 json_nexthop_global);
f1aa5d8a 10893
d62a17ae 10894 if (json_nexthop_ll)
10895 json_object_array_add(json_nexthops,
10896 json_nexthop_ll);
f1aa5d8a 10897
d62a17ae 10898 json_object_object_add(json_path, "nexthops",
10899 json_nexthops);
10900 }
10901
10902 json_object_object_add(json_path, "peer", json_peer);
10903 json_object_array_add(json_paths, json_path);
05864da7 10904 }
b366b518
BB
10905}
10906
96ade3ed 10907#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10908#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10909#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10910
a4d82a8a 10911static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10912 afi_t afi, safi_t safi, enum bgp_show_type type,
10913 bool use_json);
7f323236
DW
10914static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10915 const char *comstr, int exact, afi_t afi,
96c81f66 10916 safi_t safi, uint16_t show_flags);
d62a17ae 10917
1ae44dfc 10918static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10919 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10920 void *output_arg, const char *rd, int is_last,
96f3485c 10921 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10922 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10923 enum rpki_states rpki_target_state)
d62a17ae 10924{
40381db7 10925 struct bgp_path_info *pi;
9bcb3eef 10926 struct bgp_dest *dest;
2aad8c42
MS
10927 bool header = true;
10928 bool json_detail_header = false;
d62a17ae 10929 int display;
1ae44dfc
LB
10930 unsigned long output_count = 0;
10931 unsigned long total_count = 0;
d62a17ae 10932 struct prefix *p;
d62a17ae 10933 json_object *json_paths = NULL;
10934 int first = 1;
96f3485c
MK
10935 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10936 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10937 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10938
1ae44dfc 10939 if (output_cum && *output_cum != 0)
2aad8c42 10940 header = false;
1ae44dfc 10941
9386b588 10942 if (use_json && !*json_header_depth) {
96f3485c
MK
10943 if (all)
10944 *json_header_depth = 1;
10945 else {
10946 vty_out(vty, "{\n");
10947 *json_header_depth = 2;
10948 }
10949
d62a17ae 10950 vty_out(vty,
23d0a753
DA
10951 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10952 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10953 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10954 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10955 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10956 ? VRF_DEFAULT_NAME
10957 : bgp->name,
10958 table->version, &bgp->router_id,
01eced22 10959 bgp->default_local_pref, bgp->as);
9386b588 10960 if (rd) {
445c2480 10961 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10962 ++*json_header_depth;
10963 }
d62a17ae 10964 }
718e3744 10965
445c2480
DS
10966 if (use_json && rd) {
10967 vty_out(vty, " \"%s\" : { ", rd);
10968 }
10969
2aad8c42
MS
10970 /* Check for 'json detail', where we need header output once per dest */
10971 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10972 type != bgp_show_type_dampend_paths &&
10973 type != bgp_show_type_damp_neighbor &&
10974 type != bgp_show_type_flap_statistics &&
10975 type != bgp_show_type_flap_neighbor)
10976 json_detail_header = true;
10977
d62a17ae 10978 /* Start processing of routes. */
9bcb3eef
DS
10979 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10980 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10981 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10982 bool json_detail = json_detail_header;
b54892e0 10983
9bcb3eef 10984 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10985 if (pi == NULL)
98ce9a06 10986 continue;
d62a17ae 10987
98ce9a06 10988 display = 0;
98ce9a06
DS
10989 if (use_json)
10990 json_paths = json_object_new_array();
10991 else
10992 json_paths = NULL;
d62a17ae 10993
6f94b685 10994 for (; pi; pi = pi->next) {
9a706b42
DA
10995 struct community *picomm = NULL;
10996
10997 picomm = bgp_attr_get_community(pi->attr);
10998
98ce9a06 10999 total_count++;
1e2ce4f1 11000
7d3cae70
DA
11001 if (type == bgp_show_type_prefix_version) {
11002 uint32_t version =
11003 strtoul(output_arg, NULL, 10);
11004 if (dest->version < version)
11005 continue;
11006 }
11007
a70a28a5
DA
11008 if (type == bgp_show_type_community_alias) {
11009 char *alias = output_arg;
11010 char **communities;
11011 int num;
11012 bool found = false;
11013
9a706b42
DA
11014 if (picomm) {
11015 frrstr_split(picomm->str, " ",
11016 &communities, &num);
a70a28a5
DA
11017 for (int i = 0; i < num; i++) {
11018 const char *com2alias =
11019 bgp_community2alias(
11020 communities[i]);
cd9cc0e6
IR
11021 if (!found
11022 && strcmp(alias, com2alias)
11023 == 0)
a70a28a5 11024 found = true;
cd9cc0e6
IR
11025 XFREE(MTYPE_TMP,
11026 communities[i]);
a70a28a5 11027 }
cd9cc0e6 11028 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11029 }
11030
1bcf3a96
DA
11031 if (!found &&
11032 bgp_attr_get_lcommunity(pi->attr)) {
11033 frrstr_split(bgp_attr_get_lcommunity(
11034 pi->attr)
11035 ->str,
a70a28a5
DA
11036 " ", &communities, &num);
11037 for (int i = 0; i < num; i++) {
11038 const char *com2alias =
11039 bgp_community2alias(
11040 communities[i]);
cd9cc0e6
IR
11041 if (!found
11042 && strcmp(alias, com2alias)
11043 == 0)
a70a28a5 11044 found = true;
cd9cc0e6
IR
11045 XFREE(MTYPE_TMP,
11046 communities[i]);
a70a28a5 11047 }
cd9cc0e6 11048 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
11049 }
11050
11051 if (!found)
11052 continue;
11053 }
11054
1e2ce4f1
DS
11055 if (type == bgp_show_type_rpki) {
11056 if (dest_p->family == AF_INET
11057 || dest_p->family == AF_INET6)
4027d19b 11058 rpki_curr_state = hook_call(
1e2ce4f1
DS
11059 bgp_rpki_prefix_status,
11060 pi->peer, pi->attr, dest_p);
4027d19b
DS
11061 if (rpki_target_state != RPKI_NOT_BEING_USED
11062 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
11063 continue;
11064 }
11065
98ce9a06
DS
11066 if (type == bgp_show_type_flap_statistics
11067 || type == bgp_show_type_flap_neighbor
11068 || type == bgp_show_type_dampend_paths
11069 || type == bgp_show_type_damp_neighbor) {
40381db7 11070 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
11071 continue;
11072 }
11073 if (type == bgp_show_type_regexp) {
11074 regex_t *regex = output_arg;
d62a17ae 11075
40381db7 11076 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
11077 == REG_NOMATCH)
11078 continue;
11079 }
11080 if (type == bgp_show_type_prefix_list) {
11081 struct prefix_list *plist = output_arg;
d62a17ae 11082
9bcb3eef 11083 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
11084 != PREFIX_PERMIT)
11085 continue;
11086 }
ed126382
DA
11087 if (type == bgp_show_type_access_list) {
11088 struct access_list *alist = output_arg;
11089
11090 if (access_list_apply(alist, dest_p) !=
11091 FILTER_PERMIT)
11092 continue;
11093 }
98ce9a06
DS
11094 if (type == bgp_show_type_filter_list) {
11095 struct as_list *as_list = output_arg;
d62a17ae 11096
40381db7 11097 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
11098 != AS_FILTER_PERMIT)
11099 continue;
11100 }
11101 if (type == bgp_show_type_route_map) {
11102 struct route_map *rmap = output_arg;
9b6d8fcf 11103 struct bgp_path_info path;
98ce9a06 11104 struct attr dummy_attr;
b68885f9 11105 route_map_result_t ret;
d62a17ae 11106
6f4f49b2 11107 dummy_attr = *pi->attr;
d62a17ae 11108
40381db7 11109 path.peer = pi->peer;
9b6d8fcf 11110 path.attr = &dummy_attr;
d62a17ae 11111
1782514f 11112 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11113 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11114 if (ret == RMAP_DENYMATCH)
11115 continue;
11116 }
11117 if (type == bgp_show_type_neighbor
11118 || type == bgp_show_type_flap_neighbor
11119 || type == bgp_show_type_damp_neighbor) {
11120 union sockunion *su = output_arg;
11121
40381db7
DS
11122 if (pi->peer == NULL
11123 || pi->peer->su_remote == NULL
11124 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11125 continue;
11126 }
11127 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11128 uint32_t destination;
d62a17ae 11129
9bcb3eef 11130 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11131 if (IN_CLASSC(destination)
9bcb3eef 11132 && dest_p->prefixlen == 24)
98ce9a06
DS
11133 continue;
11134 if (IN_CLASSB(destination)
9bcb3eef 11135 && dest_p->prefixlen == 16)
98ce9a06
DS
11136 continue;
11137 if (IN_CLASSA(destination)
9bcb3eef 11138 && dest_p->prefixlen == 8)
98ce9a06
DS
11139 continue;
11140 }
11141 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11142 p = output_arg;
9bcb3eef 11143 if (!prefix_match(p, dest_p))
98ce9a06
DS
11144 continue;
11145 }
11146 if (type == bgp_show_type_community_all) {
9a706b42 11147 if (!picomm)
98ce9a06
DS
11148 continue;
11149 }
11150 if (type == bgp_show_type_community) {
11151 struct community *com = output_arg;
d62a17ae 11152
9a706b42 11153 if (!picomm || !community_match(picomm, com))
98ce9a06
DS
11154 continue;
11155 }
11156 if (type == bgp_show_type_community_exact) {
11157 struct community *com = output_arg;
d62a17ae 11158
9a706b42 11159 if (!picomm || !community_cmp(picomm, com))
98ce9a06
DS
11160 continue;
11161 }
11162 if (type == bgp_show_type_community_list) {
11163 struct community_list *list = output_arg;
d62a17ae 11164
9a706b42 11165 if (!community_list_match(picomm, list))
98ce9a06
DS
11166 continue;
11167 }
a4d82a8a 11168 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11169 struct community_list *list = output_arg;
d62a17ae 11170
9a706b42 11171 if (!community_list_exact_match(picomm, list))
98ce9a06
DS
11172 continue;
11173 }
11174 if (type == bgp_show_type_lcommunity) {
11175 struct lcommunity *lcom = output_arg;
d62a17ae 11176
1bcf3a96
DA
11177 if (!bgp_attr_get_lcommunity(pi->attr) ||
11178 !lcommunity_match(
11179 bgp_attr_get_lcommunity(pi->attr),
11180 lcom))
98ce9a06
DS
11181 continue;
11182 }
36a206db 11183
11184 if (type == bgp_show_type_lcommunity_exact) {
11185 struct lcommunity *lcom = output_arg;
11186
1bcf3a96
DA
11187 if (!bgp_attr_get_lcommunity(pi->attr) ||
11188 !lcommunity_cmp(
11189 bgp_attr_get_lcommunity(pi->attr),
11190 lcom))
36a206db 11191 continue;
11192 }
98ce9a06
DS
11193 if (type == bgp_show_type_lcommunity_list) {
11194 struct community_list *list = output_arg;
d62a17ae 11195
1bcf3a96
DA
11196 if (!lcommunity_list_match(
11197 bgp_attr_get_lcommunity(pi->attr),
11198 list))
98ce9a06
DS
11199 continue;
11200 }
36a206db 11201 if (type
11202 == bgp_show_type_lcommunity_list_exact) {
11203 struct community_list *list = output_arg;
11204
11205 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11206 bgp_attr_get_lcommunity(pi->attr),
11207 list))
36a206db 11208 continue;
11209 }
98ce9a06 11210 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11211 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11212 continue;
11213 }
11214 if (type == bgp_show_type_dampend_paths
11215 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11216 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11217 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11218 continue;
11219 }
11220
11221 if (!use_json && header) {
23d0a753
DA
11222 vty_out(vty,
11223 "BGP table version is %" PRIu64
11224 ", local router ID is %pI4, vrf id ",
11225 table->version, &bgp->router_id);
9df8b37c
PZ
11226 if (bgp->vrf_id == VRF_UNKNOWN)
11227 vty_out(vty, "%s", VRFID_NONE_STR);
11228 else
11229 vty_out(vty, "%u", bgp->vrf_id);
11230 vty_out(vty, "\n");
01eced22
AD
11231 vty_out(vty, "Default local pref %u, ",
11232 bgp->default_local_pref);
11233 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11234 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11235 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11236 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11237 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11238 if (type == bgp_show_type_dampend_paths
11239 || type == bgp_show_type_damp_neighbor)
98ce9a06 11240 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11241 else if (type == bgp_show_type_flap_statistics
11242 || type == bgp_show_type_flap_neighbor)
98ce9a06 11243 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11244 else
ae248832
MK
11245 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11246 : BGP_SHOW_HEADER));
2aad8c42
MS
11247 header = false;
11248
11249 } else if (json_detail && json_paths != NULL) {
11250 const struct prefix_rd *prd;
11251 json_object *jtemp;
11252
11253 /* Use common detail header, for most types;
11254 * need a json 'object'.
11255 */
11256
11257 jtemp = json_object_new_object();
11258 prd = bgp_rd_from_dest(dest, safi);
11259
11260 route_vty_out_detail_header(
11261 vty, bgp, dest, prd, table->afi,
11262 safi, jtemp);
11263
11264 json_object_array_add(json_paths, jtemp);
11265
11266 json_detail = false;
d62a17ae 11267 }
2aad8c42 11268
98ce9a06
DS
11269 if (rd != NULL && !display && !output_count) {
11270 if (!use_json)
11271 vty_out(vty,
11272 "Route Distinguisher: %s\n",
11273 rd);
d62a17ae 11274 }
98ce9a06
DS
11275 if (type == bgp_show_type_dampend_paths
11276 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11277 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11278 AFI_IP, safi, use_json,
11279 json_paths);
98ce9a06
DS
11280 else if (type == bgp_show_type_flap_statistics
11281 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11282 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11283 AFI_IP, safi, use_json,
11284 json_paths);
f280c93b
DA
11285 else {
11286 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11287 route_vty_out_detail(
11288 vty, bgp, dest, pi,
11289 family2afi(dest_p->family),
11290 safi, RPKI_NOT_BEING_USED,
11291 json_paths);
11292 else
11293 route_vty_out(vty, dest_p, pi, display,
11294 safi, json_paths, wide);
11295 }
98ce9a06 11296 display++;
d62a17ae 11297 }
11298
98ce9a06
DS
11299 if (display) {
11300 output_count++;
11301 if (!use_json)
11302 continue;
11303
625d2931 11304 /* encode prefix */
9bcb3eef 11305 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11306 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11307
1840384b 11308
b54892e0
DS
11309 bgp_fs_nlri_get_string(
11310 (unsigned char *)
9bcb3eef
DS
11311 dest_p->u.prefix_flowspec.ptr,
11312 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11313 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11314 family2afi(dest_p->u
11315 .prefix_flowspec.family));
625d2931 11316 if (first)
b54892e0 11317 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11318 dest_p->u.prefix_flowspec
b54892e0 11319 .prefixlen);
625d2931 11320 else
b54892e0 11321 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11322 dest_p->u.prefix_flowspec
b54892e0 11323 .prefixlen);
625d2931 11324 } else {
625d2931 11325 if (first)
1b78780b 11326 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11327 else
1b78780b 11328 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11329 }
3757f964 11330 vty_json(vty, json_paths);
449feb8e 11331 json_paths = NULL;
98ce9a06 11332 first = 0;
1f83ed02
DS
11333 } else
11334 json_object_free(json_paths);
98ce9a06
DS
11335 }
11336
1ae44dfc
LB
11337 if (output_cum) {
11338 output_count += *output_cum;
11339 *output_cum = output_count;
11340 }
11341 if (total_cum) {
11342 total_count += *total_cum;
11343 *total_cum = total_count;
11344 }
d62a17ae 11345 if (use_json) {
9386b588 11346 if (rd) {
a4d82a8a 11347 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11348 }
11349 if (is_last) {
a4d82a8a
PZ
11350 unsigned long i;
11351 for (i = 0; i < *json_header_depth; ++i)
11352 vty_out(vty, " } ");
96f3485c
MK
11353 if (!all)
11354 vty_out(vty, "\n");
9386b588 11355 }
d62a17ae 11356 } else {
1ae44dfc
LB
11357 if (is_last) {
11358 /* No route is displayed */
11359 if (output_count == 0) {
11360 if (type == bgp_show_type_normal)
11361 vty_out(vty,
11362 "No BGP prefixes displayed, %ld exist\n",
11363 total_count);
11364 } else
d62a17ae 11365 vty_out(vty,
1ae44dfc
LB
11366 "\nDisplayed %ld routes and %ld total paths\n",
11367 output_count, total_count);
11368 }
d62a17ae 11369 }
718e3744 11370
d62a17ae 11371 return CMD_SUCCESS;
718e3744 11372}
11373
1ae44dfc
LB
11374int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11375 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11376 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11377{
9bcb3eef 11378 struct bgp_dest *dest, *next;
1ae44dfc
LB
11379 unsigned long output_cum = 0;
11380 unsigned long total_cum = 0;
9386b588 11381 unsigned long json_header_depth = 0;
67009e22 11382 struct bgp_table *itable;
0136788c 11383 bool show_msg;
96c81f66 11384 uint16_t show_flags = 0;
0136788c
LB
11385
11386 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11387
96f3485c
MK
11388 if (use_json)
11389 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11390
9bcb3eef
DS
11391 for (dest = bgp_table_top(table); dest; dest = next) {
11392 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11393
9bcb3eef
DS
11394 next = bgp_route_next(dest);
11395 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11396 continue;
67009e22 11397
9bcb3eef 11398 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11399 if (itable != NULL) {
1ae44dfc 11400 struct prefix_rd prd;
06b9f471 11401 char rd[RD_ADDRSTRLEN];
1ae44dfc 11402
9bcb3eef 11403 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11404 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11405 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11406 rd, next == NULL, &output_cum,
11407 &total_cum, &json_header_depth,
1e2ce4f1 11408 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11409 if (next == NULL)
11410 show_msg = false;
1ae44dfc
LB
11411 }
11412 }
0136788c
LB
11413 if (show_msg) {
11414 if (output_cum == 0)
11415 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11416 total_cum);
11417 else
11418 vty_out(vty,
11419 "\nDisplayed %ld routes and %ld total paths\n",
11420 output_cum, total_cum);
11421 }
1ae44dfc
LB
11422 return CMD_SUCCESS;
11423}
2aad8c42 11424
d62a17ae 11425static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11426 enum bgp_show_type type, void *output_arg,
96c81f66 11427 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11428{
d62a17ae 11429 struct bgp_table *table;
9386b588 11430 unsigned long json_header_depth = 0;
96f3485c 11431 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11432
d62a17ae 11433 if (bgp == NULL) {
11434 bgp = bgp_get_default();
11435 }
fee0f4c6 11436
d62a17ae 11437 if (bgp == NULL) {
11438 if (!use_json)
11439 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11440 else
11441 vty_out(vty, "{}\n");
d62a17ae 11442 return CMD_WARNING;
11443 }
4dd6177e 11444
cd8c2a27
MS
11445 /* Labeled-unicast routes live in the unicast table. */
11446 if (safi == SAFI_LABELED_UNICAST)
11447 safi = SAFI_UNICAST;
11448
1ae44dfc 11449 table = bgp->rib[afi][safi];
d62a17ae 11450 /* use MPLS and ENCAP specific shows until they are merged */
11451 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11452 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11453 output_arg, use_json);
d62a17ae 11454 }
dba3c1d3
PG
11455
11456 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11457 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11458 output_arg, use_json,
11459 1, NULL, NULL);
11460 }
fee0f4c6 11461
96f3485c 11462 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11463 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11464 rpki_target_state);
fee0f4c6 11465}
11466
d62a17ae 11467static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11468 safi_t safi, uint16_t show_flags)
f186de26 11469{
d62a17ae 11470 struct listnode *node, *nnode;
11471 struct bgp *bgp;
11472 int is_first = 1;
9f049418 11473 bool route_output = false;
96f3485c 11474 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11475
d62a17ae 11476 if (use_json)
11477 vty_out(vty, "{\n");
9f689658 11478
d62a17ae 11479 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11480 route_output = true;
d62a17ae 11481 if (use_json) {
11482 if (!is_first)
11483 vty_out(vty, ",\n");
11484 else
11485 is_first = 0;
11486
11487 vty_out(vty, "\"%s\":",
11488 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11489 ? VRF_DEFAULT_NAME
d62a17ae 11490 : bgp->name);
11491 } else {
11492 vty_out(vty, "\nInstance %s:\n",
11493 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11494 ? VRF_DEFAULT_NAME
d62a17ae 11495 : bgp->name);
11496 }
11497 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11498 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11499 }
9f689658 11500
d62a17ae 11501 if (use_json)
11502 vty_out(vty, "}\n");
9f049418
DS
11503 else if (!route_output)
11504 vty_out(vty, "%% BGP instance not found\n");
f186de26 11505}
11506
718e3744 11507/* Header of detailed BGP route information */
d62a17ae 11508void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11509 struct bgp_dest *dest,
11510 const struct prefix_rd *prd,
d62a17ae 11511 afi_t afi, safi_t safi, json_object *json)
11512{
40381db7 11513 struct bgp_path_info *pi;
b54892e0 11514 const struct prefix *p;
d62a17ae 11515 struct peer *peer;
11516 struct listnode *node, *nnode;
06b9f471 11517 char buf1[RD_ADDRSTRLEN];
d62a17ae 11518 int count = 0;
11519 int best = 0;
11520 int suppress = 0;
c5f1e1b2
C
11521 int accept_own = 0;
11522 int route_filter_translated_v4 = 0;
11523 int route_filter_v4 = 0;
11524 int route_filter_translated_v6 = 0;
11525 int route_filter_v6 = 0;
11526 int llgr_stale = 0;
11527 int no_llgr = 0;
11528 int accept_own_nexthop = 0;
11529 int blackhole = 0;
d62a17ae 11530 int no_export = 0;
11531 int no_advertise = 0;
11532 int local_as = 0;
c5f1e1b2 11533 int no_peer = 0;
d62a17ae 11534 int first = 1;
11535 int has_valid_label = 0;
11536 mpls_label_t label = 0;
11537 json_object *json_adv_to = NULL;
67f67ba4
DA
11538 uint32_t ttl = 0;
11539 uint32_t bos = 0;
11540 uint32_t exp = 0;
9bedbb1e 11541
67f67ba4 11542 mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
d62a17ae 11543
67f67ba4
DA
11544 p = bgp_dest_get_prefix(dest);
11545 has_valid_label = bgp_is_valid_label(&label);
d62a17ae 11546
44c69747 11547 if (safi == SAFI_EVPN) {
d62a17ae 11548
44c69747 11549 if (!json) {
2dbe669b 11550 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11551 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11552 : "",
2dbe669b 11553 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11554 } else {
11555 json_object_string_add(json, "rd",
11556 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11557 "");
11558 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11559 }
11560 } else {
11561 if (!json) {
9119ef3a
DA
11562 vty_out(vty,
11563 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11564 "\n",
d62a17ae 11565 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11566 ? prefix_rd2str(prd, buf1,
11567 sizeof(buf1))
11568 : ""),
9119ef3a
DA
11569 safi == SAFI_MPLS_VPN ? ":" : "", p,
11570 dest->version);
cd1964ff 11571
9119ef3a 11572 } else {
67d7e256 11573 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11574 json_object_int_add(json, "version", dest->version);
11575
11576 }
44c69747
LK
11577 }
11578
11579 if (has_valid_label) {
11580 if (json)
11581 json_object_int_add(json, "localLabel", label);
11582 else
d62a17ae 11583 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11584 }
11585
11586 if (!json)
d62a17ae 11587 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11588 vty_out(vty, "not allocated\n");
718e3744 11589
9bcb3eef 11590 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9a706b42
DA
11591 struct community *picomm = NULL;
11592
11593 picomm = bgp_attr_get_community(pi->attr);
11594
d62a17ae 11595 count++;
40381db7 11596 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11597 best = count;
4056a5f6 11598 if (bgp_path_suppressed(pi))
d62a17ae 11599 suppress = 1;
cee9c031 11600
9a706b42 11601 if (!picomm)
cee9c031
QY
11602 continue;
11603
11604 no_advertise += community_include(
9a706b42
DA
11605 picomm, COMMUNITY_NO_ADVERTISE);
11606 no_export +=
11607 community_include(picomm, COMMUNITY_NO_EXPORT);
11608 local_as +=
11609 community_include(picomm, COMMUNITY_LOCAL_AS);
11610 accept_own +=
11611 community_include(picomm, COMMUNITY_ACCEPT_OWN);
cee9c031 11612 route_filter_translated_v4 += community_include(
9a706b42 11613 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
cee9c031 11614 route_filter_translated_v6 += community_include(
9a706b42 11615 picomm, COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
cee9c031 11616 route_filter_v4 += community_include(
9a706b42 11617 picomm, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11618 route_filter_v6 += community_include(
9a706b42
DA
11619 picomm, COMMUNITY_ROUTE_FILTER_v6);
11620 llgr_stale +=
11621 community_include(picomm, COMMUNITY_LLGR_STALE);
11622 no_llgr += community_include(picomm, COMMUNITY_NO_LLGR);
11623 accept_own_nexthop += community_include(
11624 picomm, COMMUNITY_ACCEPT_OWN_NEXTHOP);
11625 blackhole +=
11626 community_include(picomm, COMMUNITY_BLACKHOLE);
11627 no_peer += community_include(picomm, COMMUNITY_NO_PEER);
d62a17ae 11628 }
718e3744 11629 }
718e3744 11630
d62a17ae 11631 if (!json) {
11632 vty_out(vty, "Paths: (%d available", count);
11633 if (best) {
11634 vty_out(vty, ", best #%d", best);
b84060bb
PG
11635 if (safi == SAFI_UNICAST) {
11636 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11637 vty_out(vty, ", table %s",
11638 VRF_DEFAULT_NAME);
11639 else
11640 vty_out(vty, ", vrf %s",
11641 bgp->name);
11642 }
d62a17ae 11643 } else
11644 vty_out(vty, ", no best path");
11645
c5f1e1b2
C
11646 if (accept_own)
11647 vty_out(vty,
11648 ", accept own local route exported and imported in different VRF");
11649 else if (route_filter_translated_v4)
11650 vty_out(vty,
11651 ", mark translated RTs for VPNv4 route filtering");
11652 else if (route_filter_v4)
11653 vty_out(vty,
11654 ", attach RT as-is for VPNv4 route filtering");
11655 else if (route_filter_translated_v6)
11656 vty_out(vty,
11657 ", mark translated RTs for VPNv6 route filtering");
11658 else if (route_filter_v6)
11659 vty_out(vty,
11660 ", attach RT as-is for VPNv6 route filtering");
11661 else if (llgr_stale)
11662 vty_out(vty,
1479ed2f 11663 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11664 else if (no_llgr)
11665 vty_out(vty,
11666 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11667 else if (accept_own_nexthop)
11668 vty_out(vty,
11669 ", accept local nexthop");
11670 else if (blackhole)
11671 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11672 else if (no_export)
11673 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11674 else if (no_advertise)
11675 vty_out(vty, ", not advertised to any peer");
d62a17ae 11676 else if (local_as)
11677 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11678 else if (no_peer)
11679 vty_out(vty,
11680 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11681
11682 if (suppress)
11683 vty_out(vty,
11684 ", Advertisements suppressed by an aggregate.");
11685 vty_out(vty, ")\n");
11686 }
718e3744 11687
d62a17ae 11688 /* If we are not using addpath then we can display Advertised to and
11689 * that will
11690 * show what peers we advertised the bestpath to. If we are using
11691 * addpath
11692 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11693 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11694 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11695 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11696 if (json && !json_adv_to)
11697 json_adv_to = json_object_new_object();
11698
11699 route_vty_out_advertised_to(
11700 vty, peer, &first,
11701 " Advertised to non peer-group peers:\n ",
11702 json_adv_to);
11703 }
11704 }
11705
11706 if (json) {
11707 if (json_adv_to) {
11708 json_object_object_add(json, "advertisedTo",
11709 json_adv_to);
11710 }
11711 } else {
11712 if (first)
11713 vty_out(vty, " Not advertised to any peer");
11714 vty_out(vty, "\n");
11715 }
11716 }
718e3744 11717}
11718
edfee30d 11719static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11720 struct bgp_dest *bgp_node, struct vty *vty,
11721 struct bgp *bgp, afi_t afi, safi_t safi,
11722 json_object *json, enum bgp_path_type pathtype,
4027d19b 11723 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11724{
11725 struct bgp_path_info *pi;
11726 int header = 1;
11727 char rdbuf[RD_ADDRSTRLEN];
11728 json_object *json_header = NULL;
11729 json_object *json_paths = NULL;
4933eaaf 11730 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11731
9bcb3eef 11732 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11733 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11734
11735 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11736 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11737 pi->peer, pi->attr, p);
4933eaaf 11738
4027d19b
DS
11739 if (rpki_target_state != RPKI_NOT_BEING_USED
11740 && rpki_curr_state != rpki_target_state)
4933eaaf 11741 continue;
44c69747
LK
11742
11743 if (json && !json_paths) {
11744 /* Instantiate json_paths only if path is valid */
11745 json_paths = json_object_new_array();
11746 if (pfx_rd) {
11747 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11748 json_header = json_object_new_object();
11749 } else
11750 json_header = json;
11751 }
11752
11753 if (header) {
11754 route_vty_out_detail_header(
11755 vty, bgp, bgp_node, pfx_rd,
11756 AFI_IP, safi, json_header);
11757 header = 0;
11758 }
11759 (*display)++;
11760
11761 if (pathtype == BGP_PATH_SHOW_ALL
11762 || (pathtype == BGP_PATH_SHOW_BESTPATH
11763 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11764 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11765 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11766 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11767 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11768 safi, rpki_curr_state, json_paths);
44c69747
LK
11769 }
11770
11771 if (json && json_paths) {
11772 json_object_object_add(json_header, "paths", json_paths);
11773
11774 if (pfx_rd)
11775 json_object_object_add(json, rdbuf, json_header);
11776 }
11777}
11778
2aad8c42
MS
11779/*
11780 * Return rd based on safi
11781 */
11782static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11783 safi_t safi)
11784{
11785 switch (safi) {
11786 case SAFI_MPLS_VPN:
11787 case SAFI_ENCAP:
11788 case SAFI_EVPN:
11789 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11790 default:
11791 return NULL;
11792
11793 }
11794}
11795
718e3744 11796/* Display specified route of BGP table. */
d62a17ae 11797static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11798 struct bgp_table *rib, const char *ip_str,
11799 afi_t afi, safi_t safi,
4027d19b 11800 enum rpki_states rpki_target_state,
d62a17ae 11801 struct prefix_rd *prd, int prefix_check,
9f049418 11802 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11803{
11804 int ret;
d62a17ae 11805 int display = 0;
11806 struct prefix match;
9bcb3eef
DS
11807 struct bgp_dest *dest;
11808 struct bgp_dest *rm;
d62a17ae 11809 struct bgp_table *table;
11810 json_object *json = NULL;
11811 json_object *json_paths = NULL;
11812
11813 /* Check IP address argument. */
11814 ret = str2prefix(ip_str, &match);
11815 if (!ret) {
11816 vty_out(vty, "address is malformed\n");
11817 return CMD_WARNING;
11818 }
718e3744 11819
d62a17ae 11820 match.family = afi2family(afi);
b05a1c8b 11821
44c69747 11822 if (use_json)
d62a17ae 11823 json = json_object_new_object();
718e3744 11824
44c69747 11825 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11826 for (dest = bgp_table_top(rib); dest;
11827 dest = bgp_route_next(dest)) {
11828 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11829
9bcb3eef 11830 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11831 continue;
9bcb3eef 11832 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11833 if (!table)
ea47320b 11834 continue;
d62a17ae 11835
4953391b
DA
11836 rm = bgp_node_match(table, &match);
11837 if (rm == NULL)
ea47320b 11838 continue;
d62a17ae 11839
9bcb3eef 11840 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11841 if (prefix_check
b54892e0 11842 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11843 bgp_dest_unlock_node(rm);
ea47320b
DL
11844 continue;
11845 }
d62a17ae 11846
9bcb3eef 11847 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11848 bgp, afi, safi, json, pathtype,
4027d19b 11849 &display, rpki_target_state);
44c69747 11850
9bcb3eef 11851 bgp_dest_unlock_node(rm);
44c69747
LK
11852 }
11853 } else if (safi == SAFI_EVPN) {
9bcb3eef 11854 struct bgp_dest *longest_pfx;
cded3b72 11855 bool is_exact_pfxlen_match = false;
44c69747 11856
9bcb3eef
DS
11857 for (dest = bgp_table_top(rib); dest;
11858 dest = bgp_route_next(dest)) {
11859 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11860
9bcb3eef 11861 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11862 continue;
9bcb3eef 11863 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11864 if (!table)
11865 continue;
11866
11867 longest_pfx = NULL;
cded3b72 11868 is_exact_pfxlen_match = false;
44c69747
LK
11869 /*
11870 * Search through all the prefixes for a match. The
11871 * pfx's are enumerated in ascending order of pfxlens.
11872 * So, the last pfx match is the longest match. Set
11873 * is_exact_pfxlen_match when we get exact pfxlen match
11874 */
11875 for (rm = bgp_table_top(table); rm;
11876 rm = bgp_route_next(rm)) {
b54892e0 11877 const struct prefix *rm_p =
9bcb3eef 11878 bgp_dest_get_prefix(rm);
44c69747
LK
11879 /*
11880 * Get prefixlen of the ip-prefix within type5
11881 * evpn route
11882 */
b54892e0
DS
11883 if (evpn_type5_prefix_match(rm_p, &match)
11884 && rm->info) {
44c69747
LK
11885 longest_pfx = rm;
11886 int type5_pfxlen =
b54892e0
DS
11887 bgp_evpn_get_type5_prefixlen(
11888 rm_p);
44c69747 11889 if (type5_pfxlen == match.prefixlen) {
cded3b72 11890 is_exact_pfxlen_match = true;
9bcb3eef 11891 bgp_dest_unlock_node(rm);
44c69747
LK
11892 break;
11893 }
d62a17ae 11894 }
11895 }
ea47320b 11896
44c69747
LK
11897 if (!longest_pfx)
11898 continue;
11899
11900 if (prefix_check && !is_exact_pfxlen_match)
11901 continue;
11902
11903 rm = longest_pfx;
9bcb3eef 11904 bgp_dest_lock_node(rm);
44c69747 11905
9bcb3eef 11906 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11907 bgp, afi, safi, json, pathtype,
4027d19b 11908 &display, rpki_target_state);
44c69747 11909
9bcb3eef 11910 bgp_dest_unlock_node(rm);
d62a17ae 11911 }
98a9dbc7 11912 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11913 if (use_json)
11914 json_paths = json_object_new_array();
11915
63a0b7a9
PG
11916 display = bgp_flowspec_display_match_per_ip(afi, rib,
11917 &match, prefix_check,
11918 vty,
11919 use_json,
11920 json_paths);
d5f20468
SP
11921 if (use_json) {
11922 if (display)
11923 json_object_object_add(json, "paths",
11924 json_paths);
11925 else
11926 json_object_free(json_paths);
11927 }
d62a17ae 11928 } else {
4953391b
DA
11929 dest = bgp_node_match(rib, &match);
11930 if (dest != NULL) {
9bcb3eef 11931 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11932 if (!prefix_check
9bcb3eef
DS
11933 || dest_p->prefixlen == match.prefixlen) {
11934 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11935 safi, json, pathtype,
4027d19b 11936 &display, rpki_target_state);
d62a17ae 11937 }
11938
9bcb3eef 11939 bgp_dest_unlock_node(dest);
d62a17ae 11940 }
11941 }
e5eee9af 11942
d62a17ae 11943 if (use_json) {
75eeda93 11944 vty_json(vty, json);
d62a17ae 11945 } else {
11946 if (!display) {
11947 vty_out(vty, "%% Network not in table\n");
11948 return CMD_WARNING;
11949 }
11950 }
b05a1c8b 11951
d62a17ae 11952 return CMD_SUCCESS;
718e3744 11953}
11954
fee0f4c6 11955/* Display specified route of Main RIB */
d62a17ae 11956static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11957 afi_t afi, safi_t safi, struct prefix_rd *prd,
11958 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11959 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11960{
9b86009a 11961 if (!bgp) {
d62a17ae 11962 bgp = bgp_get_default();
9b86009a
RW
11963 if (!bgp) {
11964 if (!use_json)
11965 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11966 else
11967 vty_out(vty, "{}\n");
9b86009a
RW
11968 return CMD_WARNING;
11969 }
11970 }
d62a17ae 11971
11972 /* labeled-unicast routes live in the unicast table */
11973 if (safi == SAFI_LABELED_UNICAST)
11974 safi = SAFI_UNICAST;
11975
11976 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11977 afi, safi, rpki_target_state, prd,
8aa22bbb 11978 prefix_check, pathtype, use_json);
d62a17ae 11979}
11980
11981static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11982 struct cmd_token **argv, bool exact, afi_t afi,
11983 safi_t safi, bool uj)
d62a17ae 11984{
11985 struct lcommunity *lcom;
11986 struct buffer *b;
11987 int i;
11988 char *str;
11989 int first = 0;
96c81f66 11990 uint16_t show_flags = 0;
4f28b2b5 11991 int ret;
96f3485c
MK
11992
11993 if (uj)
11994 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11995
11996 b = buffer_new(1024);
11997 for (i = 0; i < argc; i++) {
11998 if (first)
11999 buffer_putc(b, ' ');
12000 else {
12001 if (strmatch(argv[i]->text, "AA:BB:CC")) {
12002 first = 1;
12003 buffer_putstr(b, argv[i]->arg);
12004 }
12005 }
12006 }
12007 buffer_putc(b, '\0');
57d187bc 12008
d62a17ae 12009 str = buffer_getstr(b);
12010 buffer_free(b);
57d187bc 12011
d62a17ae 12012 lcom = lcommunity_str2com(str);
12013 XFREE(MTYPE_TMP, str);
12014 if (!lcom) {
12015 vty_out(vty, "%% Large-community malformed\n");
12016 return CMD_WARNING;
12017 }
57d187bc 12018
4f28b2b5 12019 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12020 (exact ? bgp_show_type_lcommunity_exact
12021 : bgp_show_type_lcommunity),
12022 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
12023
12024 lcommunity_free(&lcom);
12025 return ret;
57d187bc
JS
12026}
12027
d62a17ae 12028static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 12029 const char *lcom, bool exact, afi_t afi,
12030 safi_t safi, bool uj)
57d187bc 12031{
d62a17ae 12032 struct community_list *list;
96c81f66 12033 uint16_t show_flags = 0;
96f3485c
MK
12034
12035 if (uj)
12036 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12037
57d187bc 12038
e237b0d2 12039 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 12040 LARGE_COMMUNITY_LIST_MASTER);
12041 if (list == NULL) {
12042 vty_out(vty, "%% %s is not a valid large-community-list name\n",
12043 lcom);
12044 return CMD_WARNING;
12045 }
57d187bc 12046
36a206db 12047 return bgp_show(vty, bgp, afi, safi,
12048 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 12049 : bgp_show_type_lcommunity_list),
1e2ce4f1 12050 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 12051}
12052
52951b63
DS
12053DEFUN (show_ip_bgp_large_community_list,
12054 show_ip_bgp_large_community_list_cmd,
77a3a95e 12055 "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
12056 SHOW_STR
12057 IP_STR
12058 BGP_STR
12059 BGP_INSTANCE_HELP_STR
9bedbb1e 12060 BGP_AFI_HELP_STR
4dd6177e 12061 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12062 "Display routes matching the large-community-list\n"
12063 "large-community-list number\n"
12064 "large-community-list name\n"
36a206db 12065 "Exact match of the large-communities\n"
52951b63
DS
12066 JSON_STR)
12067{
d62a17ae 12068 afi_t afi = AFI_IP6;
12069 safi_t safi = SAFI_UNICAST;
12070 int idx = 0;
36a206db 12071 bool exact_match = 0;
4d678463 12072 struct bgp *bgp = NULL;
9f049418 12073 bool uj = use_json(argc, argv);
d62a17ae 12074
ef3364f0
DA
12075 if (uj)
12076 argc--;
4d678463 12077
ef3364f0
DA
12078 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12079 &bgp, uj);
12080 if (!idx)
12081 return CMD_WARNING;
d62a17ae 12082
12083 argv_find(argv, argc, "large-community-list", &idx);
36a206db 12084
12085 const char *clist_number_or_name = argv[++idx]->arg;
12086
12087 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12088 exact_match = 1;
12089
12090 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
12091 exact_match, afi, safi, uj);
52951b63
DS
12092}
12093DEFUN (show_ip_bgp_large_community,
12094 show_ip_bgp_large_community_cmd,
36a206db 12095 "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
12096 SHOW_STR
12097 IP_STR
12098 BGP_STR
12099 BGP_INSTANCE_HELP_STR
9bedbb1e 12100 BGP_AFI_HELP_STR
4dd6177e 12101 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
12102 "Display routes matching the large-communities\n"
12103 "List of large-community numbers\n"
36a206db 12104 "Exact match of the large-communities\n"
52951b63
DS
12105 JSON_STR)
12106{
d62a17ae 12107 afi_t afi = AFI_IP6;
12108 safi_t safi = SAFI_UNICAST;
12109 int idx = 0;
36a206db 12110 bool exact_match = 0;
4d678463 12111 struct bgp *bgp = NULL;
9f049418 12112 bool uj = use_json(argc, argv);
96c81f66 12113 uint16_t show_flags = 0;
d62a17ae 12114
96f3485c
MK
12115 if (uj) {
12116 argc--;
12117 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12118 }
4d678463 12119
96f3485c
MK
12120 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12121 &bgp, uj);
12122 if (!idx)
12123 return CMD_WARNING;
d62a17ae 12124
36a206db 12125 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12126 if (argv_find(argv, argc, "exact-match", &idx))
12127 exact_match = 1;
12128 return bgp_show_lcommunity(vty, bgp, argc, argv,
12129 exact_match, afi, safi, uj);
12130 } else
d62a17ae 12131 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12132 bgp_show_type_lcommunity_all, NULL, show_flags,
12133 RPKI_NOT_BEING_USED);
52951b63
DS
12134}
12135
71f1613a
DA
12136static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12137 safi_t safi, struct json_object *json_array);
d62a17ae 12138static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12139 safi_t safi, struct json_object *json);
e01ca200 12140
7b2ff250 12141
9ab0cf58
PG
12142DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12143 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12144 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12145 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12146{
12147 bool uj = use_json(argc, argv);
12148 struct bgp *bgp = NULL;
ec76a1d1
DA
12149 safi_t safi = SAFI_UNICAST;
12150 afi_t afi = AFI_IP6;
4265b261 12151 int idx = 0;
6c9d22e2
PG
12152 struct json_object *json_all = NULL;
12153 struct json_object *json_afi_safi = NULL;
4265b261
PG
12154
12155 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12156 &bgp, false);
71f1613a 12157 if (!idx)
4265b261 12158 return CMD_WARNING;
6c9d22e2 12159
4265b261 12160 if (uj)
6c9d22e2 12161 json_all = json_object_new_object();
4265b261 12162
9ab0cf58
PG
12163 FOREACH_AFI_SAFI (afi, safi) {
12164 /*
12165 * So limit output to those afi/safi pairs that
12166 * actually have something interesting in them
12167 */
12168 if (strmatch(get_afi_safi_str(afi, safi, true),
12169 "Unknown")) {
12170 continue;
12171 }
12172 if (uj) {
12173 json_afi_safi = json_object_new_array();
12174 json_object_object_add(
12175 json_all,
12176 get_afi_safi_str(afi, safi, true),
12177 json_afi_safi);
12178 } else {
12179 json_afi_safi = NULL;
6c9d22e2 12180 }
9ab0cf58
PG
12181
12182 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12183 }
6c9d22e2 12184
3757f964
DA
12185 if (uj)
12186 vty_json(vty, json_all);
6c9d22e2 12187
4265b261
PG
12188 return CMD_SUCCESS;
12189}
12190
7b2ff250 12191/* BGP route print out function without JSON */
14718643
PG
12192DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12193 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12194 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12195 SHOW_STR
12196 IP_STR
12197 BGP_STR
12198 BGP_INSTANCE_HELP_STR
12199 L2VPN_HELP_STR
12200 EVPN_HELP_STR
12201 "BGP RIB advertisement statistics\n"
12202 JSON_STR)
12203{
ec76a1d1
DA
12204 afi_t afi = AFI_IP6;
12205 safi_t safi = SAFI_UNICAST;
14718643
PG
12206 struct bgp *bgp = NULL;
12207 int idx = 0, ret;
12208 bool uj = use_json(argc, argv);
12209 struct json_object *json_afi_safi = NULL, *json = NULL;
12210
12211 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12212 &bgp, false);
12213 if (!idx)
12214 return CMD_WARNING;
12215
12216 if (uj)
12217 json_afi_safi = json_object_new_array();
12218 else
12219 json_afi_safi = NULL;
12220
12221 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12222
12223 if (uj) {
12224 json = json_object_new_object();
12225 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12226 json_afi_safi);
3757f964 12227 vty_json(vty, json);
14718643
PG
12228 }
12229 return ret;
12230}
12231
893cccd0 12232/* BGP route print out function without JSON */
9ab0cf58
PG
12233DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12234 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12235 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12236 "]]\
893cccd0 12237 statistics [json]",
9ab0cf58
PG
12238 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12239 BGP_SAFI_WITH_LABEL_HELP_STR
12240 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12241{
ec76a1d1
DA
12242 afi_t afi = AFI_IP6;
12243 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12244 struct bgp *bgp = NULL;
12245 int idx = 0, ret;
12246 bool uj = use_json(argc, argv);
6c9d22e2 12247 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12248
12249 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12250 &bgp, false);
12251 if (!idx)
12252 return CMD_WARNING;
6c9d22e2 12253
893cccd0 12254 if (uj)
6c9d22e2
PG
12255 json_afi_safi = json_object_new_array();
12256 else
12257 json_afi_safi = NULL;
12258
12259 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12260
12261 if (uj) {
12262 json = json_object_new_object();
12263 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12264 json_afi_safi);
3757f964 12265 vty_json(vty, json);
893cccd0
PG
12266 }
12267 return ret;
893cccd0 12268}
7b2ff250 12269
fe0f234d 12270DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12271 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12272 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12273 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12274 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12275 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12276 "Display the entries for all address families\n"
9ab0cf58
PG
12277 "Display detailed information about dampening\n"
12278 "Display detail of configured dampening parameters\n"
fe0f234d 12279 JSON_STR)
718e3744 12280{
d62a17ae 12281 afi_t afi = AFI_IP6;
12282 safi_t safi = SAFI_UNICAST;
d62a17ae 12283 struct bgp *bgp = NULL;
12284 int idx = 0;
96c81f66 12285 uint16_t show_flags = 0;
fe0f234d
RW
12286 bool uj = use_json(argc, argv);
12287
12288 if (uj) {
12289 argc--;
12290 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12291 }
96f3485c
MK
12292
12293 /* [<ipv4|ipv6> [all]] */
12294 if (all) {
12295 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12296 if (argv_find(argv, argc, "ipv4", &idx))
12297 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12298
12299 if (argv_find(argv, argc, "ipv6", &idx))
12300 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12301 }
d62a17ae 12302
12303 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12304 &bgp, false);
d62a17ae 12305 if (!idx)
12306 return CMD_WARNING;
12307
fe0f234d 12308 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12309}
12310
fe0f234d
RW
12311/* BGP route print out function */
12312DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12313 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12314 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12315 "]]\
96f3485c 12316 [all$all]\
cf4898bc
QY
12317 [cidr-only\
12318 |dampening <flap-statistics|dampened-paths>\
12319 |community [AA:NN|local-AS|no-advertise|no-export\
12320 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12321 |accept-own|accept-own-nexthop|route-filter-v6\
12322 |route-filter-v4|route-filter-translated-v6\
12323 |route-filter-translated-v4] [exact-match]\
70799983 12324 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12325 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12326 |prefix-list WORD\
ed126382 12327 |access-list ACCESSLIST_NAME\
70dd370f 12328 |route-map RMAP_NAME\
1e2ce4f1 12329 |rpki <invalid|valid|notfound>\
7d3cae70 12330 |version (1-4294967295)\
b4ad2fae 12331 |alias ALIAS_NAME\
39c3c736
RW
12332 |A.B.C.D/M longer-prefixes\
12333 |X:X::X:X/M longer-prefixes\
f280c93b 12334 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12335 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12336 BGP_SAFI_WITH_LABEL_HELP_STR
12337 "Display the entries for all address families\n"
12338 "Display only routes with non-natural netmasks\n"
12339 "Display detailed information about dampening\n"
12340 "Display flap statistics of routes\n"
12341 "Display paths suppressed due to dampening\n"
12342 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12343 "Do not send outside local AS (well-known community)\n"
12344 "Do not advertise to any peer (well-known community)\n"
12345 "Do not export to next AS (well-known community)\n"
12346 "Graceful shutdown (well-known community)\n"
12347 "Do not export to any peer (well-known community)\n"
12348 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12349 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12350 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12351 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12352 "Should accept VPN route with local nexthop (well-known community)\n"
12353 "RT VPNv6 route filtering (well-known community)\n"
12354 "RT VPNv4 route filtering (well-known community)\n"
12355 "RT translated VPNv6 route filtering (well-known community)\n"
12356 "RT translated VPNv4 route filtering (well-known community)\n"
12357 "Exact match of the communities\n"
70799983
RW
12358 "Community-list number\n"
12359 "Community-list name\n"
12360 "Display routes matching the community-list\n"
12361 "Exact match of the communities\n"
a7129347
RW
12362 "Display routes conforming to the filter-list\n"
12363 "Regular expression access list name\n"
6deaf579
RW
12364 "Display routes conforming to the prefix-list\n"
12365 "Prefix-list name\n"
ed126382
DA
12366 "Display routes conforming to the access-list\n"
12367 "Access-list name\n"
bf1a944a
RW
12368 "Display routes matching the route-map\n"
12369 "A route-map to match on\n"
a70a28a5
DA
12370 "RPKI route types\n"
12371 "A valid path as determined by rpki\n"
12372 "A invalid path as determined by rpki\n"
12373 "A path that has no rpki data\n"
12374 "Display prefixes with matching version numbers\n"
12375 "Version number and above\n"
12376 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12377 "BGP community alias\n"
12378 "IPv4 prefix\n"
12379 "Display route and more specific routes\n"
12380 "IPv6 prefix\n"
12381 "Display route and more specific routes\n"
12382 JSON_STR
a70a28a5
DA
12383 "Display detailed version of JSON output\n"
12384 "Increase table width for longer prefixes\n")
7b2ff250
DW
12385{
12386 afi_t afi = AFI_IP6;
12387 safi_t safi = SAFI_UNICAST;
12388 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12389 void *output_arg = NULL;
7b2ff250
DW
12390 struct bgp *bgp = NULL;
12391 int idx = 0;
d0086e8e 12392 int exact_match = 0;
96f3485c
MK
12393 char *community = NULL;
12394 bool first = true;
96c81f66 12395 uint16_t show_flags = 0;
4027d19b 12396 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12397 struct prefix p;
96f3485c
MK
12398
12399 if (uj) {
9f049418 12400 argc--;
96f3485c
MK
12401 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12402 }
12403
f280c93b
DA
12404 if (detail)
12405 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12406
96f3485c
MK
12407 /* [<ipv4|ipv6> [all]] */
12408 if (all) {
12409 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12410
12411 if (argv_find(argv, argc, "ipv4", &idx))
12412 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12413
12414 if (argv_find(argv, argc, "ipv6", &idx))
12415 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12416 }
12417
12418 if (wide)
12419 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12420
12421 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12422 &bgp, uj);
7b2ff250
DW
12423 if (!idx)
12424 return CMD_WARNING;
12425
7b2ff250 12426 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12427 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12428
12429 if (argv_find(argv, argc, "dampening", &idx)) {
12430 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12431 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12432 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12433 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12434 }
12435
12436 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12437 char *maybecomm = NULL;
d0086e8e 12438
79bc257a
RW
12439 if (idx + 1 < argc) {
12440 if (argv[idx + 1]->type == VARIABLE_TKN)
12441 maybecomm = argv[idx + 1]->arg;
12442 else
12443 maybecomm = argv[idx + 1]->text;
12444 }
12445
cf4898bc
QY
12446 if (maybecomm && !strmatch(maybecomm, "json")
12447 && !strmatch(maybecomm, "exact-match"))
12448 community = maybecomm;
d0086e8e 12449
cf4898bc
QY
12450 if (argv_find(argv, argc, "exact-match", &idx))
12451 exact_match = 1;
d0086e8e 12452
96f3485c
MK
12453 if (!community)
12454 sh_type = bgp_show_type_community_all;
12455 }
12456
70799983
RW
12457 if (argv_find(argv, argc, "community-list", &idx)) {
12458 const char *clist_number_or_name = argv[++idx]->arg;
12459 struct community_list *list;
12460
12461 if (argv_find(argv, argc, "exact-match", &idx))
12462 exact_match = 1;
12463
12464 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12465 COMMUNITY_LIST_MASTER);
12466 if (list == NULL) {
606d49a4 12467 vty_out(vty, "%% %s community-list not found\n",
70799983
RW
12468 clist_number_or_name);
12469 return CMD_WARNING;
12470 }
12471
12472 if (exact_match)
12473 sh_type = bgp_show_type_community_list_exact;
12474 else
12475 sh_type = bgp_show_type_community_list;
12476 output_arg = list;
12477 }
12478
a7129347
RW
12479 if (argv_find(argv, argc, "filter-list", &idx)) {
12480 const char *filter = argv[++idx]->arg;
12481 struct as_list *as_list;
12482
12483 as_list = as_list_lookup(filter);
12484 if (as_list == NULL) {
606d49a4 12485 vty_out(vty, "%% %s AS-path access-list not found\n",
a7129347
RW
12486 filter);
12487 return CMD_WARNING;
12488 }
12489
12490 sh_type = bgp_show_type_filter_list;
12491 output_arg = as_list;
12492 }
12493
6deaf579
RW
12494 if (argv_find(argv, argc, "prefix-list", &idx)) {
12495 const char *prefix_list_str = argv[++idx]->arg;
12496 struct prefix_list *plist;
12497
12498 plist = prefix_list_lookup(afi, prefix_list_str);
12499 if (plist == NULL) {
606d49a4 12500 vty_out(vty, "%% %s prefix-list not found\n",
6deaf579
RW
12501 prefix_list_str);
12502 return CMD_WARNING;
12503 }
12504
12505 sh_type = bgp_show_type_prefix_list;
12506 output_arg = plist;
12507 }
12508
ed126382
DA
12509 if (argv_find(argv, argc, "access-list", &idx)) {
12510 const char *access_list_str = argv[++idx]->arg;
12511 struct access_list *alist;
12512
12513 alist = access_list_lookup(afi, access_list_str);
12514 if (!alist) {
606d49a4 12515 vty_out(vty, "%% %s access-list not found\n",
ed126382
DA
12516 access_list_str);
12517 return CMD_WARNING;
12518 }
12519
12520 sh_type = bgp_show_type_access_list;
12521 output_arg = alist;
12522 }
12523
bf1a944a
RW
12524 if (argv_find(argv, argc, "route-map", &idx)) {
12525 const char *rmap_str = argv[++idx]->arg;
12526 struct route_map *rmap;
12527
12528 rmap = route_map_lookup_by_name(rmap_str);
12529 if (!rmap) {
606d49a4 12530 vty_out(vty, "%% %s route-map not found\n", rmap_str);
bf1a944a
RW
12531 return CMD_WARNING;
12532 }
12533
12534 sh_type = bgp_show_type_route_map;
12535 output_arg = rmap;
12536 }
12537
1e2ce4f1
DS
12538 if (argv_find(argv, argc, "rpki", &idx)) {
12539 sh_type = bgp_show_type_rpki;
12540 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12541 rpki_target_state = RPKI_VALID;
1e2ce4f1 12542 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12543 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12544 }
12545
7d3cae70
DA
12546 /* Display prefixes with matching version numbers */
12547 if (argv_find(argv, argc, "version", &idx)) {
12548 sh_type = bgp_show_type_prefix_version;
2391833e 12549 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12550 }
12551
a70a28a5
DA
12552 /* Display prefixes with matching BGP community alias */
12553 if (argv_find(argv, argc, "alias", &idx)) {
12554 sh_type = bgp_show_type_community_alias;
2391833e 12555 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12556 }
12557
39c3c736
RW
12558 /* prefix-longer */
12559 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12560 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12561 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12562
12563 if (!str2prefix(prefix_str, &p)) {
12564 vty_out(vty, "%% Malformed Prefix\n");
12565 return CMD_WARNING;
12566 }
12567
12568 sh_type = bgp_show_type_prefix_longer;
12569 output_arg = &p;
a70a28a5
DA
12570 }
12571
96f3485c
MK
12572 if (!all) {
12573 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12574 if (community)
12575 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12576 exact_match, afi, safi,
12577 show_flags);
2391833e 12578 else
a70a28a5 12579 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12580 output_arg, show_flags,
a70a28a5 12581 rpki_target_state);
96f3485c 12582 } else {
fa5ac378
DA
12583 struct listnode *node;
12584 struct bgp *abgp;
96f3485c
MK
12585 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12586 * AFI_IP6 */
12587
12588 if (uj)
12589 vty_out(vty, "{\n");
12590
12591 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12592 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12593 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12594 ? AFI_IP
12595 : AFI_IP6;
fa5ac378
DA
12596 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12597 FOREACH_SAFI (safi) {
12598 if (!bgp_afi_safi_peer_exists(abgp, afi,
12599 safi))
12600 continue;
96f3485c 12601
fa5ac378
DA
12602 if (uj) {
12603 if (first)
12604 first = false;
12605 else
12606 vty_out(vty, ",\n");
12607 vty_out(vty, "\"%s\":{\n",
12608 get_afi_safi_str(afi,
12609 safi,
12610 true));
12611 } else
12612 vty_out(vty,
12613 "\nFor address family: %s\n",
12614 get_afi_safi_str(
12615 afi, safi,
12616 false));
12617
12618 if (community)
12619 bgp_show_community(
12620 vty, abgp, community,
12621 exact_match, afi, safi,
12622 show_flags);
96f3485c 12623 else
fa5ac378
DA
12624 bgp_show(vty, abgp, afi, safi,
12625 sh_type, output_arg,
12626 show_flags,
12627 rpki_target_state);
12628 if (uj)
12629 vty_out(vty, "}\n");
12630 }
96f3485c
MK
12631 }
12632 } else {
12633 /* show <ip> bgp all: for each AFI and SAFI*/
fa5ac378
DA
12634 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
12635 FOREACH_AFI_SAFI (afi, safi) {
12636 if (!bgp_afi_safi_peer_exists(abgp, afi,
12637 safi))
12638 continue;
96f3485c 12639
fa5ac378
DA
12640 if (uj) {
12641 if (first)
12642 first = false;
12643 else
12644 vty_out(vty, ",\n");
12645
12646 vty_out(vty, "\"%s\":{\n",
12647 get_afi_safi_str(afi,
12648 safi,
12649 true));
12650 } else
12651 vty_out(vty,
12652 "\nFor address family: %s\n",
12653 get_afi_safi_str(
12654 afi, safi,
12655 false));
12656
12657 if (community)
12658 bgp_show_community(
12659 vty, abgp, community,
12660 exact_match, afi, safi,
12661 show_flags);
96f3485c 12662 else
fa5ac378
DA
12663 bgp_show(vty, abgp, afi, safi,
12664 sh_type, output_arg,
12665 show_flags,
12666 rpki_target_state);
12667 if (uj)
12668 vty_out(vty, "}\n");
12669 }
96f3485c
MK
12670 }
12671 }
12672 if (uj)
12673 vty_out(vty, "}\n");
12674 }
12675 return CMD_SUCCESS;
a636c635 12676}
47fc97cc 12677
718e3744 12678DEFUN (show_ip_bgp_route,
12679 show_ip_bgp_route_cmd,
8aa22bbb 12680 "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 12681 SHOW_STR
12682 IP_STR
12683 BGP_STR
a636c635 12684 BGP_INSTANCE_HELP_STR
4f280b15 12685 BGP_AFI_HELP_STR
4dd6177e 12686 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12687 "Network in the BGP routing table to display\n"
0c7b1b01 12688 "IPv4 prefix\n"
8c3deaae 12689 "Network in the BGP routing table to display\n"
0c7b1b01 12690 "IPv6 prefix\n"
4092b06c 12691 "Display only the bestpath\n"
b05a1c8b 12692 "Display only multipaths\n"
8aa22bbb
DS
12693 "Display only paths that match the specified rpki state\n"
12694 "A valid path as determined by rpki\n"
12695 "A invalid path as determined by rpki\n"
12696 "A path that has no rpki data\n"
9973d184 12697 JSON_STR)
4092b06c 12698{
d62a17ae 12699 int prefix_check = 0;
ae19d7dd 12700
d62a17ae 12701 afi_t afi = AFI_IP6;
12702 safi_t safi = SAFI_UNICAST;
12703 char *prefix = NULL;
12704 struct bgp *bgp = NULL;
12705 enum bgp_path_type path_type;
9f049418 12706 bool uj = use_json(argc, argv);
b05a1c8b 12707
d62a17ae 12708 int idx = 0;
ae19d7dd 12709
d62a17ae 12710 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12711 &bgp, uj);
d62a17ae 12712 if (!idx)
12713 return CMD_WARNING;
c41247f5 12714
d62a17ae 12715 if (!bgp) {
12716 vty_out(vty,
12717 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12718 return CMD_WARNING;
12719 }
a636c635 12720
d62a17ae 12721 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12722 if (argv_find(argv, argc, "A.B.C.D", &idx)
12723 || argv_find(argv, argc, "X:X::X:X", &idx))
12724 prefix_check = 0;
12725 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12726 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12727 prefix_check = 1;
12728
12729 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12730 && afi != AFI_IP6) {
12731 vty_out(vty,
12732 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12733 return CMD_WARNING;
12734 }
12735 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12736 && afi != AFI_IP) {
12737 vty_out(vty,
12738 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12739 return CMD_WARNING;
12740 }
12741
12742 prefix = argv[idx]->arg;
12743
12744 /* [<bestpath|multipath>] */
12745 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12746 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12747 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12748 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12749 else
360660c6 12750 path_type = BGP_PATH_SHOW_ALL;
a636c635 12751
d62a17ae 12752 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12753 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12754}
12755
8c3deaae
QY
12756DEFUN (show_ip_bgp_regexp,
12757 show_ip_bgp_regexp_cmd,
3e5b31b3 12758 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12759 SHOW_STR
12760 IP_STR
12761 BGP_STR
b00b230a 12762 BGP_INSTANCE_HELP_STR
4f280b15 12763 BGP_AFI_HELP_STR
4dd6177e 12764 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12765 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12766 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12767 JSON_STR)
8c3deaae 12768{
d62a17ae 12769 afi_t afi = AFI_IP6;
12770 safi_t safi = SAFI_UNICAST;
12771 struct bgp *bgp = NULL;
3e5b31b3
DA
12772 bool uj = use_json(argc, argv);
12773 char *regstr = NULL;
8c3deaae 12774
d62a17ae 12775 int idx = 0;
12776 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12777 &bgp, false);
d62a17ae 12778 if (!idx)
12779 return CMD_WARNING;
8c3deaae 12780
d62a17ae 12781 // get index of regex
3e5b31b3
DA
12782 if (argv_find(argv, argc, "REGEX", &idx))
12783 regstr = argv[idx]->arg;
8c3deaae 12784
5f71d11c 12785 assert(regstr);
3e5b31b3
DA
12786 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12787 bgp_show_type_regexp, uj);
8c3deaae
QY
12788}
12789
ae248832 12790DEFPY (show_ip_bgp_instance_all,
a636c635 12791 show_ip_bgp_instance_all_cmd,
ae248832 12792 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12793 SHOW_STR
a636c635 12794 IP_STR
4092b06c 12795 BGP_STR
a636c635 12796 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12797 BGP_AFI_HELP_STR
4dd6177e 12798 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12799 JSON_STR
12800 "Increase table width for longer prefixes\n")
4092b06c 12801{
54d05dea 12802 afi_t afi = AFI_IP6;
d62a17ae 12803 safi_t safi = SAFI_UNICAST;
12804 struct bgp *bgp = NULL;
d62a17ae 12805 int idx = 0;
96c81f66 12806 uint16_t show_flags = 0;
ae19d7dd 12807
96f3485c 12808 if (uj) {
d62a17ae 12809 argc--;
96f3485c
MK
12810 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12811 }
12812
12813 if (wide)
12814 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12815
9f049418
DS
12816 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12817 &bgp, uj);
12818 if (!idx)
12819 return CMD_WARNING;
12820
96f3485c 12821 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12822 return CMD_SUCCESS;
e3e29b32
LB
12823}
12824
a4d82a8a 12825static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12826 afi_t afi, safi_t safi, enum bgp_show_type type,
12827 bool use_json)
718e3744 12828{
d62a17ae 12829 regex_t *regex;
12830 int rc;
96c81f66 12831 uint16_t show_flags = 0;
96f3485c
MK
12832
12833 if (use_json)
12834 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12835
c3900853 12836 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12837 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12838 regstr);
12839 return CMD_WARNING_CONFIG_FAILED;
12840 }
12841
d62a17ae 12842 regex = bgp_regcomp(regstr);
12843 if (!regex) {
12844 vty_out(vty, "Can't compile regexp %s\n", regstr);
12845 return CMD_WARNING;
12846 }
a636c635 12847
1e2ce4f1
DS
12848 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12849 RPKI_NOT_BEING_USED);
d62a17ae 12850 bgp_regex_free(regex);
12851 return rc;
e3e29b32
LB
12852}
12853
7f323236
DW
12854static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12855 const char *comstr, int exact, afi_t afi,
96c81f66 12856 safi_t safi, uint16_t show_flags)
d62a17ae 12857{
12858 struct community *com;
d62a17ae 12859 int ret = 0;
12860
7f323236 12861 com = community_str2com(comstr);
d62a17ae 12862 if (!com) {
7f323236 12863 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12864 return CMD_WARNING;
12865 }
12866
12867 ret = bgp_show(vty, bgp, afi, safi,
12868 (exact ? bgp_show_type_community_exact
12869 : bgp_show_type_community),
1e2ce4f1 12870 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12871 community_free(&com);
46c3ce83 12872
d62a17ae 12873 return ret;
718e3744 12874}
12875
d62a17ae 12876enum bgp_stats {
12877 BGP_STATS_MAXBITLEN = 0,
12878 BGP_STATS_RIB,
12879 BGP_STATS_PREFIXES,
12880 BGP_STATS_TOTPLEN,
12881 BGP_STATS_UNAGGREGATEABLE,
12882 BGP_STATS_MAX_AGGREGATEABLE,
12883 BGP_STATS_AGGREGATES,
12884 BGP_STATS_SPACE,
12885 BGP_STATS_ASPATH_COUNT,
12886 BGP_STATS_ASPATH_MAXHOPS,
12887 BGP_STATS_ASPATH_TOTHOPS,
12888 BGP_STATS_ASPATH_MAXSIZE,
12889 BGP_STATS_ASPATH_TOTSIZE,
12890 BGP_STATS_ASN_HIGHEST,
12891 BGP_STATS_MAX,
a636c635 12892};
2815e61f 12893
9ab0cf58 12894#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12895#define TABLE_STATS_IDX_JSON 1
12896
12897static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12898 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12899 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12900 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12901 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12902 "unaggregateablePrefixes"},
12903 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12904 "maximumAggregateablePrefixes"},
12905 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12906 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12907 [BGP_STATS_SPACE] = {"Address space advertised",
12908 "addressSpaceAdvertised"},
9ab0cf58
PG
12909 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12910 "advertisementsWithPaths"},
12911 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12912 "longestAsPath"},
12913 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12914 "largestAsPath"},
12915 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12916 "averageAsPathLengthHops"},
12917 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12918 "averageAsPathSizeBytes"},
12919 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12920 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12921};
2815e61f 12922
d62a17ae 12923struct bgp_table_stats {
12924 struct bgp_table *table;
12925 unsigned long long counts[BGP_STATS_MAX];
0747643e
AQ
12926
12927 unsigned long long
12928 prefix_len_count[MAX(EVPN_ROUTE_PREFIXLEN, IPV6_MAX_BITLEN) +
12929 1];
12930
8d0ab76d 12931 double total_space;
ff7924f6
PJ
12932};
12933
9bcb3eef 12934static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12935 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12936{
9bcb3eef 12937 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12938 struct bgp_path_info *pi;
b54892e0 12939 const struct prefix *rn_p;
d62a17ae 12940
9bcb3eef 12941 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12942 return;
d62a17ae 12943
9bcb3eef 12944 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12945 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12946 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12947
0747643e 12948 ts->prefix_len_count[rn_p->prefixlen]++;
9c14ec72 12949 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12950 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12951 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12952
9bcb3eef 12953 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12954 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12955 /* announced address space */
12956 if (space)
b54892e0 12957 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12958 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12959 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12960
9c14ec72 12961
9bcb3eef 12962 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12963 ts->counts[BGP_STATS_RIB]++;
12964
05864da7
DS
12965 if (CHECK_FLAG(pi->attr->flag,
12966 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12967 ts->counts[BGP_STATS_AGGREGATES]++;
12968
12969 /* as-path stats */
05864da7 12970 if (pi->attr->aspath) {
9c14ec72
RW
12971 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12972 unsigned int size = aspath_size(pi->attr->aspath);
12973 as_t highest = aspath_highest(pi->attr->aspath);
12974
12975 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12976
12977 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12978 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12979
12980 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12981 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12982
12983 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12984 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12985 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12986 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12987 }
12988 }
12989}
12990
cc9f21da 12991static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12992{
9bcb3eef
DS
12993 struct bgp_dest *dest, *ndest;
12994 struct bgp_dest *top;
9c14ec72
RW
12995 struct bgp_table_stats *ts = THREAD_ARG(t);
12996 unsigned int space = 0;
12997
12998 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12999 return;
9c14ec72
RW
13000
13001 switch (ts->table->afi) {
13002 case AFI_IP:
13003 space = IPV4_MAX_BITLEN;
13004 break;
13005 case AFI_IP6:
13006 space = IPV6_MAX_BITLEN;
13007 break;
3ba7b4af
TA
13008 case AFI_L2VPN:
13009 space = EVPN_ROUTE_PREFIXLEN;
13010 break;
9c14ec72 13011 default:
cc9f21da 13012 return;
9c14ec72
RW
13013 }
13014
13015 ts->counts[BGP_STATS_MAXBITLEN] = space;
13016
9bcb3eef 13017 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
13018 if (ts->table->safi == SAFI_MPLS_VPN
13019 || ts->table->safi == SAFI_ENCAP
13020 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
13021 struct bgp_table *table;
13022
9bcb3eef 13023 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
13024 if (!table)
13025 continue;
13026
13027 top = bgp_table_top(table);
9bcb3eef
DS
13028 for (ndest = bgp_table_top(table); ndest;
13029 ndest = bgp_route_next(ndest))
13030 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 13031 } else {
9bcb3eef 13032 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 13033 }
13034 }
2815e61f 13035}
ff7924f6 13036
71f1613a
DA
13037static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
13038 struct json_object *json_array)
13039{
13040 struct listnode *node, *nnode;
13041 struct bgp *bgp;
13042
13043 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
13044 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13045}
13046
13047static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
13048 safi_t safi, struct json_object *json_array)
2815e61f 13049{
d62a17ae 13050 struct bgp_table_stats ts;
13051 unsigned int i;
893cccd0
PG
13052 int ret = CMD_SUCCESS;
13053 char temp_buf[20];
6c9d22e2 13054 struct json_object *json = NULL;
0747643e
AQ
13055 uint32_t bitlen = 0;
13056 struct json_object *json_bitlen;
6c9d22e2
PG
13057
13058 if (json_array)
13059 json = json_object_new_object();
019386c2 13060
d62a17ae 13061 if (!bgp->rib[afi][safi]) {
893cccd0
PG
13062 char warning_msg[50];
13063
13064 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
13065 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
13066 safi);
6c9d22e2
PG
13067
13068 if (!json)
893cccd0
PG
13069 vty_out(vty, "%s\n", warning_msg);
13070 else
9ab0cf58 13071 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 13072
893cccd0
PG
13073 ret = CMD_WARNING;
13074 goto end_table_stats;
d62a17ae 13075 }
019386c2 13076
893cccd0 13077 if (!json)
5290ceab
DA
13078 vty_out(vty, "BGP %s RIB statistics (%s)\n",
13079 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
13080 else
13081 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 13082
d62a17ae 13083 /* labeled-unicast routes live in the unicast table */
13084 if (safi == SAFI_LABELED_UNICAST)
13085 safi = SAFI_UNICAST;
019386c2 13086
d62a17ae 13087 memset(&ts, 0, sizeof(ts));
13088 ts.table = bgp->rib[afi][safi];
13089 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 13090
d62a17ae 13091 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
13092 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
13093 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 13094 continue;
13095
13096 switch (i) {
d62a17ae 13097 case BGP_STATS_ASPATH_TOTHOPS:
13098 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 13099 if (!json) {
9ab0cf58
PG
13100 snprintf(
13101 temp_buf, sizeof(temp_buf), "%12.2f",
13102 ts.counts[i]
13103 ? (float)ts.counts[i]
13104 / (float)ts.counts
13105 [BGP_STATS_ASPATH_COUNT]
13106 : 0);
893cccd0 13107 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13108 table_stats_strs[i]
13109 [TABLE_STATS_IDX_VTY],
893cccd0 13110 temp_buf);
9ab0cf58
PG
13111 } else {
13112 json_object_double_add(
13113 json,
13114 table_stats_strs[i]
13115 [TABLE_STATS_IDX_JSON],
13116 ts.counts[i]
13117 ? (double)ts.counts[i]
13118 / (double)ts.counts
d62a17ae 13119 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
13120 : 0);
13121 }
d62a17ae 13122 break;
13123 case BGP_STATS_TOTPLEN:
6c9d22e2 13124 if (!json) {
9ab0cf58
PG
13125 snprintf(
13126 temp_buf, sizeof(temp_buf), "%12.2f",
13127 ts.counts[i]
13128 ? (float)ts.counts[i]
13129 / (float)ts.counts
13130 [BGP_STATS_PREFIXES]
13131 : 0);
893cccd0 13132 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13133 table_stats_strs[i]
13134 [TABLE_STATS_IDX_VTY],
893cccd0 13135 temp_buf);
9ab0cf58
PG
13136 } else {
13137 json_object_double_add(
13138 json,
13139 table_stats_strs[i]
13140 [TABLE_STATS_IDX_JSON],
13141 ts.counts[i]
13142 ? (double)ts.counts[i]
13143 / (double)ts.counts
d62a17ae 13144 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13145 : 0);
13146 }
d62a17ae 13147 break;
13148 case BGP_STATS_SPACE:
6c9d22e2
PG
13149 if (!json) {
13150 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13151 ts.total_space);
893cccd0 13152 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13153 table_stats_strs[i]
13154 [TABLE_STATS_IDX_VTY],
893cccd0 13155 temp_buf);
9ab0cf58
PG
13156 } else {
13157 json_object_double_add(
13158 json,
13159 table_stats_strs[i]
13160 [TABLE_STATS_IDX_JSON],
13161 (double)ts.total_space);
13162 }
8d0ab76d 13163 if (afi == AFI_IP6) {
6c9d22e2
PG
13164 if (!json) {
13165 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13166 "%12g",
13167 ts.total_space
13168 * pow(2.0, -128 + 32));
6c9d22e2
PG
13169 vty_out(vty, "%30s: %s\n",
13170 "/32 equivalent %s\n",
13171 temp_buf);
9ab0cf58
PG
13172 } else {
13173 json_object_double_add(
13174 json, "/32equivalent",
13175 (double)(ts.total_space
13176 * pow(2.0,
13177 -128 + 32)));
13178 }
6c9d22e2
PG
13179 if (!json) {
13180 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13181 "%12g",
13182 ts.total_space
13183 * pow(2.0, -128 + 48));
6c9d22e2
PG
13184 vty_out(vty, "%30s: %s\n",
13185 "/48 equivalent %s\n",
13186 temp_buf);
9ab0cf58
PG
13187 } else {
13188 json_object_double_add(
13189 json, "/48equivalent",
13190 (double)(ts.total_space
13191 * pow(2.0,
13192 -128 + 48)));
13193 }
8d0ab76d 13194 } else {
6c9d22e2
PG
13195 if (!json) {
13196 snprintf(temp_buf, sizeof(temp_buf),
13197 "%12.2f",
9ab0cf58
PG
13198 ts.total_space * 100.
13199 * pow(2.0, -32));
6c9d22e2 13200 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13201 "% announced ", temp_buf);
13202 } else {
13203 json_object_double_add(
13204 json, "%announced",
13205 (double)(ts.total_space * 100.
13206 * pow(2.0, -32)));
13207 }
6c9d22e2
PG
13208 if (!json) {
13209 snprintf(temp_buf, sizeof(temp_buf),
13210 "%12.2f",
9ab0cf58
PG
13211 ts.total_space
13212 * pow(2.0, -32 + 8));
6c9d22e2
PG
13213 vty_out(vty, "%30s: %s\n",
13214 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13215 } else {
13216 json_object_double_add(
13217 json, "/8equivalent",
13218 (double)(ts.total_space
13219 * pow(2.0, -32 + 8)));
13220 }
6c9d22e2
PG
13221 if (!json) {
13222 snprintf(temp_buf, sizeof(temp_buf),
13223 "%12.2f",
9ab0cf58
PG
13224 ts.total_space
13225 * pow(2.0, -32 + 24));
6c9d22e2 13226 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13227 "/24 equivalent ", temp_buf);
13228 } else {
13229 json_object_double_add(
13230 json, "/24equivalent",
13231 (double)(ts.total_space
13232 * pow(2.0, -32 + 24)));
13233 }
8d0ab76d 13234 }
d62a17ae 13235 break;
13236 default:
6c9d22e2
PG
13237 if (!json) {
13238 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13239 ts.counts[i]);
893cccd0 13240 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13241 table_stats_strs[i]
13242 [TABLE_STATS_IDX_VTY],
13243 temp_buf);
13244 } else {
13245 json_object_int_add(
13246 json,
13247 table_stats_strs[i]
13248 [TABLE_STATS_IDX_JSON],
13249 ts.counts[i]);
13250 }
d62a17ae 13251 }
893cccd0
PG
13252 if (!json)
13253 vty_out(vty, "\n");
d62a17ae 13254 }
0747643e
AQ
13255
13256 switch (afi) {
13257 case AFI_IP:
13258 bitlen = IPV4_MAX_BITLEN;
13259 break;
13260 case AFI_IP6:
13261 bitlen = IPV6_MAX_BITLEN;
13262 break;
13263 case AFI_L2VPN:
13264 bitlen = EVPN_ROUTE_PREFIXLEN;
13265 break;
13266 default:
13267 break;
13268 }
13269
13270 if (json) {
13271 json_bitlen = json_object_new_array();
13272
13273 for (i = 0; i <= bitlen; i++) {
13274 struct json_object *ind_bit = json_object_new_object();
13275
13276 if (!ts.prefix_len_count[i])
13277 continue;
13278
13279 snprintf(temp_buf, sizeof(temp_buf), "%u", i);
13280 json_object_int_add(ind_bit, temp_buf,
13281 ts.prefix_len_count[i]);
13282 json_object_array_add(json_bitlen, ind_bit);
13283 }
13284 json_object_object_add(json, "prefixLength", json_bitlen);
13285 }
13286
9ab0cf58 13287end_table_stats:
6c9d22e2
PG
13288 if (json)
13289 json_object_array_add(json_array, json);
893cccd0 13290 return ret;
d62a17ae 13291}
13292
71f1613a
DA
13293static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13294 safi_t safi, struct json_object *json_array)
13295{
13296 if (!bgp) {
13297 bgp_table_stats_all(vty, afi, safi, json_array);
13298 return CMD_SUCCESS;
13299 }
13300
13301 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13302}
13303
d62a17ae 13304enum bgp_pcounts {
13305 PCOUNT_ADJ_IN = 0,
13306 PCOUNT_DAMPED,
13307 PCOUNT_REMOVED,
13308 PCOUNT_HISTORY,
13309 PCOUNT_STALE,
13310 PCOUNT_VALID,
13311 PCOUNT_ALL,
13312 PCOUNT_COUNTED,
7e3d9632 13313 PCOUNT_BPATH_SELECTED,
d62a17ae 13314 PCOUNT_PFCNT, /* the figure we display to users */
13315 PCOUNT_MAX,
a636c635 13316};
718e3744 13317
2b64873d 13318static const char *const pcount_strs[] = {
9d303b37
DL
13319 [PCOUNT_ADJ_IN] = "Adj-in",
13320 [PCOUNT_DAMPED] = "Damped",
13321 [PCOUNT_REMOVED] = "Removed",
13322 [PCOUNT_HISTORY] = "History",
13323 [PCOUNT_STALE] = "Stale",
13324 [PCOUNT_VALID] = "Valid",
13325 [PCOUNT_ALL] = "All RIB",
13326 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13327 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13328 [PCOUNT_PFCNT] = "Useable",
13329 [PCOUNT_MAX] = NULL,
a636c635 13330};
718e3744 13331
d62a17ae 13332struct peer_pcounts {
13333 unsigned int count[PCOUNT_MAX];
13334 const struct peer *peer;
13335 const struct bgp_table *table;
54317cba 13336 safi_t safi;
a636c635 13337};
47fc97cc 13338
9bcb3eef 13339static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13340{
54317cba
JW
13341 const struct bgp_adj_in *ain;
13342 const struct bgp_path_info *pi;
d62a17ae 13343 const struct peer *peer = pc->peer;
13344
54317cba
JW
13345 for (ain = rn->adj_in; ain; ain = ain->next)
13346 if (ain->peer == peer)
13347 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13348
9bcb3eef 13349 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13350
54317cba
JW
13351 if (pi->peer != peer)
13352 continue;
d62a17ae 13353
54317cba 13354 pc->count[PCOUNT_ALL]++;
d62a17ae 13355
54317cba
JW
13356 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13357 pc->count[PCOUNT_DAMPED]++;
13358 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13359 pc->count[PCOUNT_HISTORY]++;
13360 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13361 pc->count[PCOUNT_REMOVED]++;
13362 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13363 pc->count[PCOUNT_STALE]++;
13364 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13365 pc->count[PCOUNT_VALID]++;
13366 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13367 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13368 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13369 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13370
13371 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13372 pc->count[PCOUNT_COUNTED]++;
13373 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13374 flog_err(
13375 EC_LIB_DEVELOPMENT,
13376 "Attempting to count but flags say it is unusable");
13377 } else {
40381db7 13378 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13379 flog_err(
13380 EC_LIB_DEVELOPMENT,
13381 "Not counted but flags say we should");
d62a17ae 13382 }
13383 }
54317cba
JW
13384}
13385
cc9f21da 13386static void bgp_peer_count_walker(struct thread *t)
54317cba 13387{
9bcb3eef 13388 struct bgp_dest *rn, *rm;
54317cba
JW
13389 const struct bgp_table *table;
13390 struct peer_pcounts *pc = THREAD_ARG(t);
13391
13392 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13393 || pc->safi == SAFI_EVPN) {
13394 /* Special handling for 2-level routing tables. */
13395 for (rn = bgp_table_top(pc->table); rn;
13396 rn = bgp_route_next(rn)) {
9bcb3eef 13397 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13398 if (table != NULL)
13399 for (rm = bgp_table_top(table); rm;
13400 rm = bgp_route_next(rm))
13401 bgp_peer_count_proc(rm, pc);
13402 }
13403 } else
13404 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13405 bgp_peer_count_proc(rn, pc);
718e3744 13406}
13407
d62a17ae 13408static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13409 safi_t safi, bool use_json)
856ca177 13410{
d62a17ae 13411 struct peer_pcounts pcounts = {.peer = peer};
13412 unsigned int i;
13413 json_object *json = NULL;
13414 json_object *json_loop = NULL;
856ca177 13415
d62a17ae 13416 if (use_json) {
13417 json = json_object_new_object();
13418 json_loop = json_object_new_object();
13419 }
718e3744 13420
d62a17ae 13421 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13422 || !peer->bgp->rib[afi][safi]) {
13423 if (use_json) {
13424 json_object_string_add(
13425 json, "warning",
13426 "No such neighbor or address family");
13427 vty_out(vty, "%s\n", json_object_to_json_string(json));
13428 json_object_free(json);
d5f20468 13429 json_object_free(json_loop);
d62a17ae 13430 } else
13431 vty_out(vty, "%% No such neighbor or address family\n");
13432
13433 return CMD_WARNING;
13434 }
2a71e9ce 13435
d62a17ae 13436 memset(&pcounts, 0, sizeof(pcounts));
13437 pcounts.peer = peer;
13438 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13439 pcounts.safi = safi;
d62a17ae 13440
13441 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13442 * stats for the thread-walk (i.e. ensure this can't be blamed on
13443 * on just vty_read()).
13444 */
d62a17ae 13445 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13446
13447 if (use_json) {
13448 json_object_string_add(json, "prefixCountsFor", peer->host);
13449 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13450 get_afi_safi_str(afi, safi, true));
d62a17ae 13451 json_object_int_add(json, "pfxCounter",
13452 peer->pcount[afi][safi]);
13453
13454 for (i = 0; i < PCOUNT_MAX; i++)
13455 json_object_int_add(json_loop, pcount_strs[i],
13456 pcounts.count[i]);
13457
13458 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13459
13460 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13461 json_object_string_add(json, "pfxctDriftFor",
13462 peer->host);
13463 json_object_string_add(
13464 json, "recommended",
13465 "Please report this bug, with the above command output");
13466 }
75eeda93 13467 vty_json(vty, json);
d62a17ae 13468 } else {
13469
13470 if (peer->hostname
892fedb6 13471 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13472 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13473 peer->hostname, peer->host,
5cb5f4d0 13474 get_afi_safi_str(afi, safi, false));
d62a17ae 13475 } else {
13476 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13477 get_afi_safi_str(afi, safi, false));
d62a17ae 13478 }
13479
6cde4b45 13480 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13481 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13482
13483 for (i = 0; i < PCOUNT_MAX; i++)
13484 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13485 pcounts.count[i]);
13486
13487 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13488 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13489 vty_out(vty,
13490 "Please report this bug, with the above command output\n");
13491 }
13492 }
13493
13494 return CMD_SUCCESS;
718e3744 13495}
13496
a636c635
DW
13497DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13498 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13499 "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 13500 SHOW_STR
13501 IP_STR
13502 BGP_STR
8386ac43 13503 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13504 BGP_AFI_HELP_STR
13505 BGP_SAFI_HELP_STR
0b16f239
DS
13506 "Detailed information on TCP and BGP neighbor connections\n"
13507 "Neighbor to display information about\n"
13508 "Neighbor to display information about\n"
91d37724 13509 "Neighbor on BGP configured interface\n"
a636c635 13510 "Display detailed prefix count information\n"
9973d184 13511 JSON_STR)
0b16f239 13512{
d62a17ae 13513 afi_t afi = AFI_IP6;
13514 safi_t safi = SAFI_UNICAST;
13515 struct peer *peer;
13516 int idx = 0;
13517 struct bgp *bgp = NULL;
9f049418
DS
13518 bool uj = use_json(argc, argv);
13519
13520 if (uj)
13521 argc--;
856ca177 13522
d62a17ae 13523 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13524 &bgp, uj);
d62a17ae 13525 if (!idx)
13526 return CMD_WARNING;
0b16f239 13527
d62a17ae 13528 argv_find(argv, argc, "neighbors", &idx);
13529 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13530 if (!peer)
13531 return CMD_WARNING;
bb46e94f 13532
29c8d9da 13533 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13534}
0b16f239 13535
d6902373
PG
13536#ifdef KEEP_OLD_VPN_COMMANDS
13537DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13538 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13539 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13540 SHOW_STR
13541 IP_STR
13542 BGP_STR
d6902373 13543 BGP_VPNVX_HELP_STR
91d37724 13544 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13545 "Detailed information on TCP and BGP neighbor connections\n"
13546 "Neighbor to display information about\n"
13547 "Neighbor to display information about\n"
91d37724 13548 "Neighbor on BGP configured interface\n"
a636c635 13549 "Display detailed prefix count information\n"
9973d184 13550 JSON_STR)
a636c635 13551{
d62a17ae 13552 int idx_peer = 6;
13553 struct peer *peer;
9f049418 13554 bool uj = use_json(argc, argv);
a636c635 13555
d62a17ae 13556 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13557 if (!peer)
13558 return CMD_WARNING;
13559
13560 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13561}
13562
d6902373
PG
13563DEFUN (show_ip_bgp_vpn_all_route_prefix,
13564 show_ip_bgp_vpn_all_route_prefix_cmd,
13565 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13566 SHOW_STR
13567 IP_STR
13568 BGP_STR
d6902373 13569 BGP_VPNVX_HELP_STR
91d37724
QY
13570 "Display information about all VPNv4 NLRIs\n"
13571 "Network in the BGP routing table to display\n"
3a2d747c 13572 "Network in the BGP routing table to display\n"
9973d184 13573 JSON_STR)
91d37724 13574{
d62a17ae 13575 int idx = 0;
13576 char *network = NULL;
13577 struct bgp *bgp = bgp_get_default();
13578 if (!bgp) {
13579 vty_out(vty, "Can't find default instance\n");
13580 return CMD_WARNING;
13581 }
87e34b58 13582
d62a17ae 13583 if (argv_find(argv, argc, "A.B.C.D", &idx))
13584 network = argv[idx]->arg;
13585 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13586 network = argv[idx]->arg;
13587 else {
13588 vty_out(vty, "Unable to figure out Network\n");
13589 return CMD_WARNING;
13590 }
87e34b58 13591
d62a17ae 13592 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13593 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13594 use_json(argc, argv));
91d37724 13595}
d6902373 13596#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13597
44c69747
LK
13598DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13599 show_bgp_l2vpn_evpn_route_prefix_cmd,
13600 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13601 SHOW_STR
4c63a661
PG
13602 BGP_STR
13603 L2VPN_HELP_STR
13604 EVPN_HELP_STR
44c69747
LK
13605 "Network in the BGP routing table to display\n"
13606 "Network in the BGP routing table to display\n"
4c63a661
PG
13607 "Network in the BGP routing table to display\n"
13608 "Network in the BGP routing table to display\n"
13609 JSON_STR)
13610{
d62a17ae 13611 int idx = 0;
13612 char *network = NULL;
44c69747 13613 int prefix_check = 0;
a636c635 13614
44c69747
LK
13615 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13616 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13617 network = argv[idx]->arg;
44c69747 13618 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13619 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13620 network = argv[idx]->arg;
44c69747
LK
13621 prefix_check = 1;
13622 } else {
d62a17ae 13623 vty_out(vty, "Unable to figure out Network\n");
13624 return CMD_WARNING;
13625 }
44c69747
LK
13626 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13627 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13628 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13629}
13630
114fc229 13631static void show_adj_route_header(struct vty *vty, struct peer *peer,
2f9bc755
DS
13632 struct bgp_table *table, int *header1,
13633 int *header2, json_object *json,
13634 json_object *json_scode,
13635 json_object *json_ocode, bool wide)
13636{
13637 uint64_t version = table ? table->version : 0;
13638
13639 if (*header1) {
13640 if (json) {
13641 json_object_int_add(json, "bgpTableVersion", version);
c949c771 13642 json_object_string_addf(json, "bgpLocalRouterId",
114fc229 13643 "%pI4", &peer->bgp->router_id);
2f9bc755 13644 json_object_int_add(json, "defaultLocPrf",
114fc229
DA
13645 peer->bgp->default_local_pref);
13646 json_object_int_add(json, "localAS",
13647 peer->change_local_as
13648 ? peer->change_local_as
13649 : peer->local_as);
2f9bc755
DS
13650 json_object_object_add(json, "bgpStatusCodes",
13651 json_scode);
13652 json_object_object_add(json, "bgpOriginCodes",
13653 json_ocode);
13654 } else {
13655 vty_out(vty,
23d0a753
DA
13656 "BGP table version is %" PRIu64
13657 ", local router ID is %pI4, vrf id ",
114fc229
DA
13658 version, &peer->bgp->router_id);
13659 if (peer->bgp->vrf_id == VRF_UNKNOWN)
2f9bc755
DS
13660 vty_out(vty, "%s", VRFID_NONE_STR);
13661 else
114fc229 13662 vty_out(vty, "%u", peer->bgp->vrf_id);
2f9bc755
DS
13663 vty_out(vty, "\n");
13664 vty_out(vty, "Default local pref %u, ",
114fc229
DA
13665 peer->bgp->default_local_pref);
13666 vty_out(vty, "local AS %u\n",
13667 peer->change_local_as ? peer->change_local_as
13668 : peer->local_as);
2f9bc755
DS
13669 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13670 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13671 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13672 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13673 }
13674 *header1 = 0;
13675 }
13676 if (*header2) {
13677 if (!json)
13678 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13679 : BGP_SHOW_HEADER));
13680 *header2 = 0;
13681 }
13682}
13683
d9478df0
TA
13684static void
13685show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13686 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13687 const char *rmap_name, json_object *json, json_object *json_ar,
13688 json_object *json_scode, json_object *json_ocode,
96c81f66 13689 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13690 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13691{
d62a17ae 13692 struct bgp_adj_in *ain;
13693 struct bgp_adj_out *adj;
9bcb3eef 13694 struct bgp_dest *dest;
d62a17ae 13695 struct bgp *bgp;
d62a17ae 13696 struct attr attr;
13697 int ret;
13698 struct update_subgroup *subgrp;
d62a17ae 13699 struct peer_af *paf;
f99def61 13700 bool route_filtered;
96f3485c
MK
13701 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13702 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13703 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13704 || (safi == SAFI_EVPN))
13705 ? true
13706 : false;
a636c635 13707
d62a17ae 13708 bgp = peer->bgp;
a636c635 13709
d62a17ae 13710 subgrp = peer_subgroup(peer, afi, safi);
13711
6392aaa6 13712 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13713 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13714 if (use_json) {
13715 json_object_int_add(json, "bgpTableVersion",
13716 table->version);
c949c771
DA
13717 json_object_string_addf(json, "bgpLocalRouterId",
13718 "%pI4", &bgp->router_id);
01eced22
AD
13719 json_object_int_add(json, "defaultLocPrf",
13720 bgp->default_local_pref);
114fc229
DA
13721 json_object_int_add(json, "localAS",
13722 peer->change_local_as
13723 ? peer->change_local_as
13724 : peer->local_as);
d62a17ae 13725 json_object_object_add(json, "bgpStatusCodes",
13726 json_scode);
13727 json_object_object_add(json, "bgpOriginCodes",
13728 json_ocode);
07d0c4ed
DA
13729 json_object_string_add(
13730 json, "bgpOriginatingDefaultNetwork",
13731 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13732 } else {
23d0a753
DA
13733 vty_out(vty,
13734 "BGP table version is %" PRIu64
13735 ", local router ID is %pI4, vrf id ",
13736 table->version, &bgp->router_id);
9df8b37c
PZ
13737 if (bgp->vrf_id == VRF_UNKNOWN)
13738 vty_out(vty, "%s", VRFID_NONE_STR);
13739 else
13740 vty_out(vty, "%u", bgp->vrf_id);
13741 vty_out(vty, "\n");
01eced22
AD
13742 vty_out(vty, "Default local pref %u, ",
13743 bgp->default_local_pref);
114fc229
DA
13744 vty_out(vty, "local AS %u\n",
13745 peer->change_local_as ? peer->change_local_as
13746 : peer->local_as);
d62a17ae 13747 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13748 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13749 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13750 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13751
07d0c4ed
DA
13752 vty_out(vty, "Originating default network %s\n\n",
13753 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13754 }
d9478df0 13755 *header1 = 0;
d62a17ae 13756 }
a636c635 13757
9bcb3eef 13758 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13759 if (type == bgp_show_adj_route_received
13760 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13761 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13762 if (ain->peer != peer)
ea47320b 13763 continue;
6392aaa6 13764
114fc229 13765 show_adj_route_header(vty, peer, table, header1,
d9478df0
TA
13766 header2, json, json_scode,
13767 json_ocode, wide);
13768
13769 if ((safi == SAFI_MPLS_VPN)
13770 || (safi == SAFI_ENCAP)
13771 || (safi == SAFI_EVPN)) {
13772 if (use_json)
13773 json_object_string_add(
13774 json_ar, "rd", rd_str);
13775 else if (show_rd && rd_str) {
13776 vty_out(vty,
13777 "Route Distinguisher: %s\n",
13778 rd_str);
13779 show_rd = false;
13780 }
13781 }
6392aaa6 13782
6f4f49b2 13783 attr = *ain->attr;
f99def61
AD
13784 route_filtered = false;
13785
13786 /* Filter prefix using distribute list,
13787 * filter list or prefix list
13788 */
b54892e0 13789 const struct prefix *rn_p =
9bcb3eef 13790 bgp_dest_get_prefix(dest);
b54892e0
DS
13791 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13792 safi))
13793 == FILTER_DENY)
f99def61
AD
13794 route_filtered = true;
13795
13796 /* Filter prefix using route-map */
b54892e0
DS
13797 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13798 safi, rmap_name, NULL,
13799 0, NULL);
6392aaa6 13800
13c8e163
AD
13801 if (type == bgp_show_adj_route_filtered &&
13802 !route_filtered && ret != RMAP_DENY) {
d498917e 13803 bgp_attr_flush(&attr);
6392aaa6 13804 continue;
d62a17ae 13805 }
6392aaa6 13806
d9478df0
TA
13807 if (type == bgp_show_adj_route_received
13808 && (route_filtered || ret == RMAP_DENY))
13809 (*filtered_count)++;
6392aaa6 13810
7d3cae70 13811 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13812 use_json, json_ar, wide);
d498917e 13813 bgp_attr_flush(&attr);
d9478df0 13814 (*output_count)++;
d62a17ae 13815 }
6392aaa6 13816 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13817 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13818 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13819 if (paf->peer != peer || !adj->attr)
924c3f6a 13820 continue;
d62a17ae 13821
114fc229 13822 show_adj_route_header(vty, peer, table,
d9478df0
TA
13823 header1, header2,
13824 json, json_scode,
13825 json_ocode, wide);
d62a17ae 13826
b54892e0 13827 const struct prefix *rn_p =
9bcb3eef 13828 bgp_dest_get_prefix(dest);
b54892e0 13829
6f4f49b2 13830 attr = *adj->attr;
b755861b 13831 ret = bgp_output_modifier(
b54892e0 13832 peer, rn_p, &attr, afi, safi,
b755861b 13833 rmap_name);
f46d8e1e 13834
b755861b 13835 if (ret != RMAP_DENY) {
d9478df0
TA
13836 if ((safi == SAFI_MPLS_VPN)
13837 || (safi == SAFI_ENCAP)
13838 || (safi == SAFI_EVPN)) {
13839 if (use_json)
13840 json_object_string_add(
13841 json_ar,
13842 "rd",
13843 rd_str);
13844 else if (show_rd
13845 && rd_str) {
13846 vty_out(vty,
13847 "Route Distinguisher: %s\n",
13848 rd_str);
13849 show_rd = false;
13850 }
13851 }
b54892e0 13852 route_vty_out_tmp(
7d3cae70
DA
13853 vty, dest, rn_p, &attr,
13854 safi, use_json, json_ar,
ae248832 13855 wide);
d9478df0 13856 (*output_count)++;
b755861b 13857 } else {
d9478df0 13858 (*filtered_count)++;
a2addae8 13859 }
b755861b 13860
d498917e 13861 bgp_attr_flush(&attr);
924c3f6a 13862 }
f20ce998
DS
13863 } else if (type == bgp_show_adj_route_bestpath) {
13864 struct bgp_path_info *pi;
13865
114fc229
DA
13866 show_adj_route_header(vty, peer, table, header1,
13867 header2, json, json_scode,
13868 json_ocode, wide);
f20ce998
DS
13869
13870 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13871 pi = pi->next) {
13872 if (pi->peer != peer)
13873 continue;
13874
13875 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13876 continue;
13877
7d3cae70 13878 route_vty_out_tmp(vty, dest,
f20ce998
DS
13879 bgp_dest_get_prefix(dest),
13880 pi->attr, safi, use_json,
13881 json_ar, wide);
d9478df0 13882 (*output_count)++;
f20ce998 13883 }
d62a17ae 13884 }
13885 }
a636c635 13886}
2a71e9ce 13887
d62a17ae 13888static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13889 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13890 const char *rmap_name, uint16_t show_flags)
0b16f239 13891{
d9478df0
TA
13892 struct bgp *bgp;
13893 struct bgp_table *table;
d62a17ae 13894 json_object *json = NULL;
d9478df0
TA
13895 json_object *json_scode = NULL;
13896 json_object *json_ocode = NULL;
13897 json_object *json_ar = NULL;
96f3485c 13898 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13899
d9478df0
TA
13900 /* Init BGP headers here so they're only displayed once
13901 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13902 */
13903 int header1 = 1;
13904 int header2 = 1;
13905
13906 /*
13907 * Initialize variables for each RD
13908 * All prefixes under an RD is aggregated within "json_routes"
13909 */
13910 char rd_str[BUFSIZ] = {0};
13911 json_object *json_routes = NULL;
13912
13913
13914 /* For 2-tier tables, prefix counts need to be
13915 * maintained across multiple runs of show_adj_route()
13916 */
13917 unsigned long output_count_per_rd;
13918 unsigned long filtered_count_per_rd;
13919 unsigned long output_count = 0;
13920 unsigned long filtered_count = 0;
13921
13922 if (use_json) {
d62a17ae 13923 json = json_object_new_object();
d9478df0
TA
13924 json_ar = json_object_new_object();
13925 json_scode = json_object_new_object();
13926 json_ocode = json_object_new_object();
13927
13928 json_object_string_add(json_scode, "suppressed", "s");
13929 json_object_string_add(json_scode, "damped", "d");
13930 json_object_string_add(json_scode, "history", "h");
13931 json_object_string_add(json_scode, "valid", "*");
13932 json_object_string_add(json_scode, "best", ">");
13933 json_object_string_add(json_scode, "multipath", "=");
13934 json_object_string_add(json_scode, "internal", "i");
13935 json_object_string_add(json_scode, "ribFailure", "r");
13936 json_object_string_add(json_scode, "stale", "S");
13937 json_object_string_add(json_scode, "removed", "R");
13938
13939 json_object_string_add(json_ocode, "igp", "i");
13940 json_object_string_add(json_ocode, "egp", "e");
13941 json_object_string_add(json_ocode, "incomplete", "?");
13942 }
0b16f239 13943
d62a17ae 13944 if (!peer || !peer->afc[afi][safi]) {
13945 if (use_json) {
13946 json_object_string_add(
13947 json, "warning",
13948 "No such neighbor or address family");
13949 vty_out(vty, "%s\n", json_object_to_json_string(json));
13950 json_object_free(json);
690c3134
MW
13951 json_object_free(json_ar);
13952 json_object_free(json_scode);
13953 json_object_free(json_ocode);
d62a17ae 13954 } else
13955 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13956
d62a17ae 13957 return CMD_WARNING;
13958 }
13959
6392aaa6
PM
13960 if ((type == bgp_show_adj_route_received
13961 || type == bgp_show_adj_route_filtered)
d62a17ae 13962 && !CHECK_FLAG(peer->af_flags[afi][safi],
13963 PEER_FLAG_SOFT_RECONFIG)) {
13964 if (use_json) {
13965 json_object_string_add(
13966 json, "warning",
13967 "Inbound soft reconfiguration not enabled");
13968 vty_out(vty, "%s\n", json_object_to_json_string(json));
13969 json_object_free(json);
690c3134
MW
13970 json_object_free(json_ar);
13971 json_object_free(json_scode);
13972 json_object_free(json_ocode);
d62a17ae 13973 } else
13974 vty_out(vty,
13975 "%% Inbound soft reconfiguration not enabled\n");
13976
13977 return CMD_WARNING;
13978 }
0b16f239 13979
d9478df0
TA
13980 bgp = peer->bgp;
13981
13982 /* labeled-unicast routes live in the unicast table */
13983 if (safi == SAFI_LABELED_UNICAST)
13984 table = bgp->rib[afi][SAFI_UNICAST];
13985 else
13986 table = bgp->rib[afi][safi];
13987
13988 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13989 || (safi == SAFI_EVPN)) {
13990
13991 struct bgp_dest *dest;
13992
13993 for (dest = bgp_table_top(table); dest;
13994 dest = bgp_route_next(dest)) {
13995 table = bgp_dest_get_bgp_table_info(dest);
13996 if (!table)
13997 continue;
13998
13999 output_count_per_rd = 0;
14000 filtered_count_per_rd = 0;
14001
14002 if (use_json)
14003 json_routes = json_object_new_object();
14004
14005 const struct prefix_rd *prd;
14006 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14007 dest);
14008
14009 prefix_rd2str(prd, rd_str, sizeof(rd_str));
14010
14011 show_adj_route(vty, peer, table, afi, safi, type,
14012 rmap_name, json, json_routes, json_scode,
14013 json_ocode, show_flags, &header1,
14014 &header2, rd_str, &output_count_per_rd,
14015 &filtered_count_per_rd);
14016
14017 /* Don't include an empty RD in the output! */
14018 if (json_routes && (output_count_per_rd > 0))
14019 json_object_object_add(json_ar, rd_str,
14020 json_routes);
14021
14022 output_count += output_count_per_rd;
14023 filtered_count += filtered_count_per_rd;
14024 }
14025 } else
14026 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
14027 json, json_ar, json_scode, json_ocode,
14028 show_flags, &header1, &header2, rd_str,
14029 &output_count, &filtered_count);
14030
14031 if (use_json) {
c1984955
TA
14032 if (type == bgp_show_adj_route_advertised)
14033 json_object_object_add(json, "advertisedRoutes",
14034 json_ar);
14035 else
14036 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
14037 json_object_int_add(json, "totalPrefixCounter", output_count);
14038 json_object_int_add(json, "filteredPrefixCounter",
14039 filtered_count);
14040
690c3134
MW
14041 /*
14042 * These fields only give up ownership to `json` when `header1`
14043 * is used (set to zero). See code in `show_adj_route` and
14044 * `show_adj_route_header`.
14045 */
14046 if (header1 == 1) {
d9478df0
TA
14047 json_object_free(json_scode);
14048 json_object_free(json_ocode);
14049 }
14050
75eeda93 14051 vty_json(vty, json);
d9478df0
TA
14052 } else if (output_count > 0) {
14053 if (filtered_count > 0)
14054 vty_out(vty,
14055 "\nTotal number of prefixes %ld (%ld filtered)\n",
14056 output_count, filtered_count);
14057 else
14058 vty_out(vty, "\nTotal number of prefixes %ld\n",
14059 output_count);
14060 }
0b16f239 14061
d62a17ae 14062 return CMD_SUCCESS;
a636c635 14063}
50ef26d4 14064
f20ce998
DS
14065DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
14066 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
14067 "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]",
14068 SHOW_STR
14069 IP_STR
14070 BGP_STR
14071 BGP_INSTANCE_HELP_STR
14072 BGP_AFI_HELP_STR
14073 BGP_SAFI_WITH_LABEL_HELP_STR
14074 "Detailed information on TCP and BGP neighbor connections\n"
14075 "Neighbor to display information about\n"
14076 "Neighbor to display information about\n"
14077 "Neighbor on BGP configured interface\n"
14078 "Display the routes selected by best path\n"
14079 JSON_STR
14080 "Increase table width for longer prefixes\n")
14081{
14082 afi_t afi = AFI_IP6;
14083 safi_t safi = SAFI_UNICAST;
14084 char *rmap_name = NULL;
14085 char *peerstr = NULL;
14086 struct bgp *bgp = NULL;
14087 struct peer *peer;
14088 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
14089 int idx = 0;
96c81f66 14090 uint16_t show_flags = 0;
96f3485c
MK
14091
14092 if (uj)
14093 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14094
14095 if (wide)
14096 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
14097
14098 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14099 &bgp, uj);
14100
14101 if (!idx)
14102 return CMD_WARNING;
14103
14104 argv_find(argv, argc, "neighbors", &idx);
14105 peerstr = argv[++idx]->arg;
14106
14107 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14108 if (!peer)
14109 return CMD_WARNING;
14110
96f3485c
MK
14111 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14112 show_flags);
f20ce998
DS
14113}
14114
ae248832 14115DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 14116 show_ip_bgp_instance_neighbor_advertised_route_cmd,
70dd370f 14117 "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 14118 SHOW_STR
14119 IP_STR
14120 BGP_STR
a636c635 14121 BGP_INSTANCE_HELP_STR
7395a2c9 14122 BGP_AFI_HELP_STR
4dd6177e 14123 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 14124 "Display the entries for all address families\n"
718e3744 14125 "Detailed information on TCP and BGP neighbor connections\n"
14126 "Neighbor to display information about\n"
14127 "Neighbor to display information about\n"
91d37724 14128 "Neighbor on BGP configured interface\n"
a636c635 14129 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
14130 "Display the received routes from neighbor\n"
14131 "Display the filtered routes received from neighbor\n"
a636c635
DW
14132 "Route-map to modify the attributes\n"
14133 "Name of the route map\n"
ae248832
MK
14134 JSON_STR
14135 "Increase table width for longer prefixes\n")
718e3744 14136{
d62a17ae 14137 afi_t afi = AFI_IP6;
14138 safi_t safi = SAFI_UNICAST;
d62a17ae 14139 char *peerstr = NULL;
d62a17ae 14140 struct bgp *bgp = NULL;
14141 struct peer *peer;
6392aaa6 14142 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 14143 int idx = 0;
96f3485c 14144 bool first = true;
96c81f66 14145 uint16_t show_flags = 0;
75ce3b14
DA
14146 struct listnode *node;
14147 struct bgp *abgp;
6392aaa6 14148
96f3485c 14149 if (uj) {
d62a17ae 14150 argc--;
96f3485c
MK
14151 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14152 }
14153
14154 if (all) {
14155 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
14156 if (argv_find(argv, argc, "ipv4", &idx))
14157 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
14158
14159 if (argv_find(argv, argc, "ipv6", &idx))
14160 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
14161 }
14162
14163 if (wide)
14164 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 14165
9f049418
DS
14166 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14167 &bgp, uj);
14168 if (!idx)
14169 return CMD_WARNING;
14170
d62a17ae 14171 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14172 argv_find(argv, argc, "neighbors", &idx);
14173 peerstr = argv[++idx]->arg;
8c3deaae 14174
d62a17ae 14175 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14176 if (!peer)
14177 return CMD_WARNING;
856ca177 14178
d62a17ae 14179 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
14180 type = bgp_show_adj_route_advertised;
14181 else if (argv_find(argv, argc, "received-routes", &idx))
14182 type = bgp_show_adj_route_received;
14183 else if (argv_find(argv, argc, "filtered-routes", &idx))
14184 type = bgp_show_adj_route_filtered;
14185
96f3485c 14186 if (!all)
70dd370f 14187 return peer_adj_routes(vty, peer, afi, safi, type, route_map,
96f3485c
MK
14188 show_flags);
14189 if (uj)
14190 vty_out(vty, "{\n");
14191
14192 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14193 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14194 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14195 : AFI_IP6;
75ce3b14
DA
14196 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14197 FOREACH_SAFI (safi) {
14198 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14199 continue;
96f3485c 14200
75ce3b14
DA
14201 if (uj) {
14202 if (first)
14203 first = false;
14204 else
14205 vty_out(vty, ",\n");
14206 vty_out(vty, "\"%s\":",
14207 get_afi_safi_str(afi, safi,
14208 true));
14209 } else
14210 vty_out(vty,
14211 "\nFor address family: %s\n",
14212 get_afi_safi_str(afi, safi,
14213 false));
96f3485c 14214
75ce3b14 14215 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14216 route_map, show_flags);
75ce3b14 14217 }
96f3485c
MK
14218 }
14219 } else {
75ce3b14
DA
14220 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, abgp)) {
14221 FOREACH_AFI_SAFI (afi, safi) {
14222 if (!bgp_afi_safi_peer_exists(abgp, afi, safi))
14223 continue;
96f3485c 14224
75ce3b14
DA
14225 if (uj) {
14226 if (first)
14227 first = false;
14228 else
14229 vty_out(vty, ",\n");
14230 vty_out(vty, "\"%s\":",
14231 get_afi_safi_str(afi, safi,
14232 true));
14233 } else
14234 vty_out(vty,
14235 "\nFor address family: %s\n",
14236 get_afi_safi_str(afi, safi,
14237 false));
96f3485c 14238
75ce3b14 14239 peer_adj_routes(vty, peer, afi, safi, type,
70dd370f 14240 route_map, show_flags);
75ce3b14 14241 }
96f3485c
MK
14242 }
14243 }
14244 if (uj)
14245 vty_out(vty, "}\n");
14246
14247 return CMD_SUCCESS;
95cbbd2a
ML
14248}
14249
718e3744 14250DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14251 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14252 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14253 SHOW_STR
14254 IP_STR
14255 BGP_STR
d3120452 14256 BGP_INSTANCE_HELP_STR
00e6edb9
DA
14257 BGP_AF_STR
14258 BGP_AF_STR
14259 BGP_AF_MODIFIER_STR
718e3744 14260 "Detailed information on TCP and BGP neighbor connections\n"
14261 "Neighbor to display information about\n"
14262 "Neighbor to display information about\n"
91d37724 14263 "Neighbor on BGP configured interface\n"
718e3744 14264 "Display information received from a BGP neighbor\n"
856ca177 14265 "Display the prefixlist filter\n"
9973d184 14266 JSON_STR)
718e3744 14267{
d62a17ae 14268 afi_t afi = AFI_IP6;
14269 safi_t safi = SAFI_UNICAST;
14270 char *peerstr = NULL;
d62a17ae 14271 char name[BUFSIZ];
d62a17ae 14272 struct peer *peer;
d3120452 14273 int count;
d62a17ae 14274 int idx = 0;
d3120452
IR
14275 struct bgp *bgp = NULL;
14276 bool uj = use_json(argc, argv);
14277
14278 if (uj)
14279 argc--;
14280
14281 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14282 &bgp, uj);
14283 if (!idx)
14284 return CMD_WARNING;
d62a17ae 14285
d62a17ae 14286 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14287 argv_find(argv, argc, "neighbors", &idx);
14288 peerstr = argv[++idx]->arg;
14289
d3120452
IR
14290 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14291 if (!peer)
14292 return CMD_WARNING;
718e3744 14293
4ced1a2c 14294 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14295 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14296 if (count) {
14297 if (!uj)
14298 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14299 get_afi_safi_str(afi, safi, false));
d62a17ae 14300 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14301 } else {
14302 if (uj)
14303 vty_out(vty, "{}\n");
14304 else
14305 vty_out(vty, "No functional output\n");
14306 }
718e3744 14307
d62a17ae 14308 return CMD_SUCCESS;
14309}
14310
14311static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14312 afi_t afi, safi_t safi,
9f049418 14313 enum bgp_show_type type, bool use_json)
d62a17ae 14314{
96c81f66 14315 uint16_t show_flags = 0;
96f3485c
MK
14316
14317 if (use_json)
14318 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14319
d62a17ae 14320 if (!peer || !peer->afc[afi][safi]) {
14321 if (use_json) {
14322 json_object *json_no = NULL;
14323 json_no = json_object_new_object();
14324 json_object_string_add(
14325 json_no, "warning",
14326 "No such neighbor or address family");
14327 vty_out(vty, "%s\n",
14328 json_object_to_json_string(json_no));
14329 json_object_free(json_no);
14330 } else
14331 vty_out(vty, "%% No such neighbor or address family\n");
14332 return CMD_WARNING;
14333 }
47fc97cc 14334
7daf25a3
TA
14335 /* labeled-unicast routes live in the unicast table */
14336 if (safi == SAFI_LABELED_UNICAST)
14337 safi = SAFI_UNICAST;
14338
1e2ce4f1
DS
14339 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14340 RPKI_NOT_BEING_USED);
718e3744 14341}
14342
dba3c1d3
PG
14343DEFUN (show_ip_bgp_flowspec_routes_detailed,
14344 show_ip_bgp_flowspec_routes_detailed_cmd,
14345 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14346 SHOW_STR
14347 IP_STR
14348 BGP_STR
14349 BGP_INSTANCE_HELP_STR
14350 BGP_AFI_HELP_STR
14351 "SAFI Flowspec\n"
14352 "Detailed information on flowspec entries\n"
14353 JSON_STR)
14354{
458c1475 14355 afi_t afi = AFI_IP6;
dba3c1d3
PG
14356 safi_t safi = SAFI_UNICAST;
14357 struct bgp *bgp = NULL;
14358 int idx = 0;
9f049418 14359 bool uj = use_json(argc, argv);
5be6fa9b 14360 uint16_t show_flags = BGP_SHOW_OPT_DETAIL;
9f049418 14361
96f3485c 14362 if (uj) {
9f049418 14363 argc--;
96f3485c
MK
14364 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14365 }
dba3c1d3
PG
14366
14367 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14368 &bgp, uj);
dba3c1d3
PG
14369 if (!idx)
14370 return CMD_WARNING;
14371
96f3485c 14372 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14373 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14374}
14375
718e3744 14376DEFUN (show_ip_bgp_neighbor_routes,
14377 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14378 "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 14379 SHOW_STR
14380 IP_STR
14381 BGP_STR
8386ac43 14382 BGP_INSTANCE_HELP_STR
4f280b15 14383 BGP_AFI_HELP_STR
4dd6177e 14384 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14385 "Detailed information on TCP and BGP neighbor connections\n"
14386 "Neighbor to display information about\n"
14387 "Neighbor to display information about\n"
91d37724 14388 "Neighbor on BGP configured interface\n"
2525cf39 14389 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14390 "Display the dampened routes received from neighbor\n"
14391 "Display routes learned from neighbor\n"
9973d184 14392 JSON_STR)
718e3744 14393{
d62a17ae 14394 char *peerstr = NULL;
14395 struct bgp *bgp = NULL;
14396 afi_t afi = AFI_IP6;
14397 safi_t safi = SAFI_UNICAST;
14398 struct peer *peer;
14399 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14400 int idx = 0;
9f049418
DS
14401 bool uj = use_json(argc, argv);
14402
14403 if (uj)
14404 argc--;
bb46e94f 14405
d62a17ae 14406 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14407 &bgp, uj);
d62a17ae 14408 if (!idx)
14409 return CMD_WARNING;
c493f2d8 14410
d62a17ae 14411 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14412 argv_find(argv, argc, "neighbors", &idx);
14413 peerstr = argv[++idx]->arg;
8c3deaae 14414
d62a17ae 14415 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14416 if (!peer)
d62a17ae 14417 return CMD_WARNING;
bb46e94f 14418
d62a17ae 14419 if (argv_find(argv, argc, "flap-statistics", &idx))
14420 sh_type = bgp_show_type_flap_neighbor;
14421 else if (argv_find(argv, argc, "dampened-routes", &idx))
14422 sh_type = bgp_show_type_damp_neighbor;
14423 else if (argv_find(argv, argc, "routes", &idx))
14424 sh_type = bgp_show_type_neighbor;
2525cf39 14425
d62a17ae 14426 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14427}
6b0655a2 14428
734b349e 14429struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14430
d62a17ae 14431struct bgp_distance {
14432 /* Distance value for the IP source prefix. */
d7c0a89a 14433 uint8_t distance;
718e3744 14434
d62a17ae 14435 /* Name of the access-list to be matched. */
14436 char *access_list;
718e3744 14437};
14438
4f280b15
LB
14439DEFUN (show_bgp_afi_vpn_rd_route,
14440 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14441 "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
14442 SHOW_STR
14443 BGP_STR
14444 BGP_AFI_HELP_STR
00e6edb9 14445 BGP_AF_MODIFIER_STR
4f280b15
LB
14446 "Display information for a route distinguisher\n"
14447 "Route Distinguisher\n"
a111dd97 14448 "All Route Distinguishers\n"
7395a2c9
DS
14449 "Network in the BGP routing table to display\n"
14450 "Network in the BGP routing table to display\n"
14451 JSON_STR)
4f280b15 14452{
d62a17ae 14453 int ret;
14454 struct prefix_rd prd;
14455 afi_t afi = AFI_MAX;
14456 int idx = 0;
4f280b15 14457
ff6566f3
DS
14458 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14459 vty_out(vty, "%% Malformed Address Family\n");
14460 return CMD_WARNING;
14461 }
14462
a111dd97
TA
14463 if (!strcmp(argv[5]->arg, "all"))
14464 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14465 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14466 RPKI_NOT_BEING_USED,
14467 use_json(argc, argv));
14468
d62a17ae 14469 ret = str2prefix_rd(argv[5]->arg, &prd);
14470 if (!ret) {
14471 vty_out(vty, "%% Malformed Route Distinguisher\n");
14472 return CMD_WARNING;
14473 }
ff6566f3 14474
d62a17ae 14475 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14476 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14477 use_json(argc, argv));
4f280b15
LB
14478}
14479
d62a17ae 14480static struct bgp_distance *bgp_distance_new(void)
718e3744 14481{
d62a17ae 14482 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14483}
14484
d62a17ae 14485static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14486{
d62a17ae 14487 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14488}
14489
585f1adc
IR
14490static int bgp_distance_set(struct vty *vty, const char *distance_str,
14491 const char *ip_str, const char *access_list_str)
718e3744 14492{
d62a17ae 14493 int ret;
585f1adc
IR
14494 afi_t afi;
14495 safi_t safi;
d62a17ae 14496 struct prefix p;
585f1adc 14497 uint8_t distance;
9bcb3eef 14498 struct bgp_dest *dest;
d62a17ae 14499 struct bgp_distance *bdistance;
718e3744 14500
585f1adc
IR
14501 afi = bgp_node_afi(vty);
14502 safi = bgp_node_safi(vty);
14503
d62a17ae 14504 ret = str2prefix(ip_str, &p);
14505 if (ret == 0) {
585f1adc 14506 vty_out(vty, "Malformed prefix\n");
d62a17ae 14507 return CMD_WARNING_CONFIG_FAILED;
14508 }
718e3744 14509
585f1adc
IR
14510 distance = atoi(distance_str);
14511
d62a17ae 14512 /* Get BGP distance node. */
9bcb3eef
DS
14513 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14514 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14515 if (bdistance)
9bcb3eef 14516 bgp_dest_unlock_node(dest);
ca2e160d 14517 else {
d62a17ae 14518 bdistance = bgp_distance_new();
9bcb3eef 14519 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14520 }
718e3744 14521
d62a17ae 14522 /* Set distance value. */
14523 bdistance->distance = distance;
718e3744 14524
d62a17ae 14525 /* Reset access-list configuration. */
e1b36e13 14526 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14527 if (access_list_str)
14528 bdistance->access_list =
14529 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14530
d62a17ae 14531 return CMD_SUCCESS;
718e3744 14532}
14533
585f1adc
IR
14534static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14535 const char *ip_str, const char *access_list_str)
718e3744 14536{
d62a17ae 14537 int ret;
585f1adc
IR
14538 afi_t afi;
14539 safi_t safi;
d62a17ae 14540 struct prefix p;
585f1adc 14541 int distance;
9bcb3eef 14542 struct bgp_dest *dest;
d62a17ae 14543 struct bgp_distance *bdistance;
718e3744 14544
585f1adc
IR
14545 afi = bgp_node_afi(vty);
14546 safi = bgp_node_safi(vty);
14547
d62a17ae 14548 ret = str2prefix(ip_str, &p);
14549 if (ret == 0) {
585f1adc 14550 vty_out(vty, "Malformed prefix\n");
d62a17ae 14551 return CMD_WARNING_CONFIG_FAILED;
14552 }
718e3744 14553
9bcb3eef
DS
14554 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14555 if (!dest) {
585f1adc 14556 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14557 return CMD_WARNING_CONFIG_FAILED;
14558 }
718e3744 14559
9bcb3eef 14560 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14561 distance = atoi(distance_str);
1f9a9fff 14562
d62a17ae 14563 if (bdistance->distance != distance) {
585f1adc 14564 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14565 bgp_dest_unlock_node(dest);
d62a17ae 14566 return CMD_WARNING_CONFIG_FAILED;
14567 }
718e3744 14568
0a22ddfb 14569 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14570 bgp_distance_free(bdistance);
718e3744 14571
9bcb3eef
DS
14572 bgp_dest_set_bgp_path_info(dest, NULL);
14573 bgp_dest_unlock_node(dest);
14574 bgp_dest_unlock_node(dest);
718e3744 14575
d62a17ae 14576 return CMD_SUCCESS;
718e3744 14577}
14578
718e3744 14579/* Apply BGP information to distance method. */
b8685f9b 14580uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14581 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14582{
9bcb3eef 14583 struct bgp_dest *dest;
801bb996 14584 struct prefix q = {0};
d62a17ae 14585 struct peer *peer;
14586 struct bgp_distance *bdistance;
14587 struct access_list *alist;
14588 struct bgp_static *bgp_static;
14589
14590 if (!bgp)
14591 return 0;
14592
40381db7 14593 peer = pinfo->peer;
d62a17ae 14594
7b7d48e5
DS
14595 if (pinfo->attr->distance)
14596 return pinfo->attr->distance;
14597
801bb996
CS
14598 /* Check source address.
14599 * Note: for aggregate route, peer can have unspec af type.
14600 */
14601 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14602 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14603 return 0;
14604
9bcb3eef
DS
14605 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14606 if (dest) {
14607 bdistance = bgp_dest_get_bgp_distance_info(dest);
14608 bgp_dest_unlock_node(dest);
d62a17ae 14609
14610 if (bdistance->access_list) {
14611 alist = access_list_lookup(afi, bdistance->access_list);
14612 if (alist
14613 && access_list_apply(alist, p) == FILTER_PERMIT)
14614 return bdistance->distance;
14615 } else
14616 return bdistance->distance;
718e3744 14617 }
718e3744 14618
d62a17ae 14619 /* Backdoor check. */
9bcb3eef
DS
14620 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14621 if (dest) {
14622 bgp_static = bgp_dest_get_bgp_static_info(dest);
14623 bgp_dest_unlock_node(dest);
718e3744 14624
d62a17ae 14625 if (bgp_static->backdoor) {
14626 if (bgp->distance_local[afi][safi])
14627 return bgp->distance_local[afi][safi];
14628 else
14629 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14630 }
718e3744 14631 }
718e3744 14632
d62a17ae 14633 if (peer->sort == BGP_PEER_EBGP) {
14634 if (bgp->distance_ebgp[afi][safi])
14635 return bgp->distance_ebgp[afi][safi];
14636 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14637 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14638 if (bgp->distance_ibgp[afi][safi])
14639 return bgp->distance_ibgp[afi][safi];
14640 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14641 } else {
14642 if (bgp->distance_local[afi][safi])
14643 return bgp->distance_local[afi][safi];
14644 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14645 }
718e3744 14646}
14647
a612fb77
DA
14648/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14649 * we should tell ZEBRA update the routes for a specific
14650 * AFI/SAFI to reflect changes in RIB.
14651 */
585f1adc
IR
14652static void bgp_announce_routes_distance_update(struct bgp *bgp,
14653 afi_t update_afi,
14654 safi_t update_safi)
a612fb77
DA
14655{
14656 afi_t afi;
14657 safi_t safi;
14658
14659 FOREACH_AFI_SAFI (afi, safi) {
14660 if (!bgp_fibupd_safi(safi))
14661 continue;
14662
8b54bc30
DA
14663 if (afi != update_afi && safi != update_safi)
14664 continue;
14665
14666 if (BGP_DEBUG(zebra, ZEBRA))
14667 zlog_debug(
14668 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14669 __func__, afi, safi);
14670 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14671 }
14672}
14673
585f1adc
IR
14674DEFUN (bgp_distance,
14675 bgp_distance_cmd,
14676 "distance bgp (1-255) (1-255) (1-255)",
14677 "Define an administrative distance\n"
14678 "BGP distance\n"
14679 "Distance for routes external to the AS\n"
14680 "Distance for routes internal to the AS\n"
14681 "Distance for local routes\n")
718e3744 14682{
585f1adc 14683 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14684 int idx_number = 2;
14685 int idx_number_2 = 3;
14686 int idx_number_3 = 4;
585f1adc
IR
14687 int distance_ebgp = atoi(argv[idx_number]->arg);
14688 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14689 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14690 afi_t afi;
14691 safi_t safi;
718e3744 14692
d62a17ae 14693 afi = bgp_node_afi(vty);
14694 safi = bgp_node_safi(vty);
718e3744 14695
585f1adc
IR
14696 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14697 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14698 || bgp->distance_local[afi][safi] != distance_local) {
14699 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14700 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14701 bgp->distance_local[afi][safi] = distance_local;
14702 bgp_announce_routes_distance_update(bgp, afi, safi);
14703 }
14704 return CMD_SUCCESS;
14705}
37a87b8f 14706
585f1adc
IR
14707DEFUN (no_bgp_distance,
14708 no_bgp_distance_cmd,
14709 "no distance bgp [(1-255) (1-255) (1-255)]",
14710 NO_STR
14711 "Define an administrative distance\n"
14712 "BGP distance\n"
14713 "Distance for routes external to the AS\n"
14714 "Distance for routes internal to the AS\n"
14715 "Distance for local routes\n")
718e3744 14716{
585f1adc 14717 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14718 afi_t afi;
14719 safi_t safi;
37a87b8f
CS
14720
14721 afi = bgp_node_afi(vty);
14722 safi = bgp_node_safi(vty);
14723
585f1adc
IR
14724 if (bgp->distance_ebgp[afi][safi] != 0
14725 || bgp->distance_ibgp[afi][safi] != 0
14726 || bgp->distance_local[afi][safi] != 0) {
14727 bgp->distance_ebgp[afi][safi] = 0;
14728 bgp->distance_ibgp[afi][safi] = 0;
14729 bgp->distance_local[afi][safi] = 0;
14730 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14731 }
585f1adc
IR
14732 return CMD_SUCCESS;
14733}
37a87b8f 14734
37a87b8f 14735
585f1adc
IR
14736DEFUN (bgp_distance_source,
14737 bgp_distance_source_cmd,
14738 "distance (1-255) A.B.C.D/M",
14739 "Define an administrative distance\n"
14740 "Administrative distance\n"
14741 "IP source prefix\n")
14742{
14743 int idx_number = 1;
14744 int idx_ipv4_prefixlen = 2;
14745 bgp_distance_set(vty, argv[idx_number]->arg,
14746 argv[idx_ipv4_prefixlen]->arg, NULL);
14747 return CMD_SUCCESS;
734b349e
MZ
14748}
14749
585f1adc
IR
14750DEFUN (no_bgp_distance_source,
14751 no_bgp_distance_source_cmd,
14752 "no distance (1-255) A.B.C.D/M",
14753 NO_STR
14754 "Define an administrative distance\n"
14755 "Administrative distance\n"
14756 "IP source prefix\n")
37a87b8f 14757{
585f1adc
IR
14758 int idx_number = 2;
14759 int idx_ipv4_prefixlen = 3;
14760 bgp_distance_unset(vty, argv[idx_number]->arg,
14761 argv[idx_ipv4_prefixlen]->arg, NULL);
14762 return CMD_SUCCESS;
37a87b8f
CS
14763}
14764
585f1adc
IR
14765DEFUN (bgp_distance_source_access_list,
14766 bgp_distance_source_access_list_cmd,
14767 "distance (1-255) A.B.C.D/M WORD",
14768 "Define an administrative distance\n"
14769 "Administrative distance\n"
14770 "IP source prefix\n"
14771 "Access list name\n")
37a87b8f 14772{
585f1adc
IR
14773 int idx_number = 1;
14774 int idx_ipv4_prefixlen = 2;
14775 int idx_word = 3;
14776 bgp_distance_set(vty, argv[idx_number]->arg,
14777 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14778 return CMD_SUCCESS;
14779}
718e3744 14780
585f1adc
IR
14781DEFUN (no_bgp_distance_source_access_list,
14782 no_bgp_distance_source_access_list_cmd,
14783 "no distance (1-255) A.B.C.D/M WORD",
14784 NO_STR
14785 "Define an administrative distance\n"
14786 "Administrative distance\n"
14787 "IP source prefix\n"
14788 "Access list name\n")
14789{
14790 int idx_number = 2;
14791 int idx_ipv4_prefixlen = 3;
14792 int idx_word = 4;
14793 bgp_distance_unset(vty, argv[idx_number]->arg,
14794 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14795 return CMD_SUCCESS;
14796}
37a87b8f 14797
585f1adc
IR
14798DEFUN (ipv6_bgp_distance_source,
14799 ipv6_bgp_distance_source_cmd,
14800 "distance (1-255) X:X::X:X/M",
14801 "Define an administrative distance\n"
14802 "Administrative distance\n"
14803 "IP source prefix\n")
14804{
14805 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14806 return CMD_SUCCESS;
14807}
7ebe9748 14808
585f1adc
IR
14809DEFUN (no_ipv6_bgp_distance_source,
14810 no_ipv6_bgp_distance_source_cmd,
14811 "no distance (1-255) X:X::X:X/M",
14812 NO_STR
14813 "Define an administrative distance\n"
14814 "Administrative distance\n"
14815 "IP source prefix\n")
14816{
14817 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14818 return CMD_SUCCESS;
14819}
37a87b8f 14820
585f1adc
IR
14821DEFUN (ipv6_bgp_distance_source_access_list,
14822 ipv6_bgp_distance_source_access_list_cmd,
14823 "distance (1-255) X:X::X:X/M WORD",
14824 "Define an administrative distance\n"
14825 "Administrative distance\n"
14826 "IP source prefix\n"
14827 "Access list name\n")
14828{
14829 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14830 return CMD_SUCCESS;
718e3744 14831}
14832
585f1adc
IR
14833DEFUN (no_ipv6_bgp_distance_source_access_list,
14834 no_ipv6_bgp_distance_source_access_list_cmd,
14835 "no distance (1-255) X:X::X:X/M WORD",
14836 NO_STR
14837 "Define an administrative distance\n"
14838 "Administrative distance\n"
14839 "IP source prefix\n"
14840 "Access list name\n")
718e3744 14841{
585f1adc
IR
14842 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14843 return CMD_SUCCESS;
14844}
37a87b8f 14845
585f1adc
IR
14846DEFUN (bgp_damp_set,
14847 bgp_damp_set_cmd,
a30fec23 14848 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14849 "BGP Specific commands\n"
14850 "Enable route-flap dampening\n"
14851 "Half-life time for the penalty\n"
14852 "Value to start reusing a route\n"
14853 "Value to start suppressing a route\n"
14854 "Maximum duration to suppress a stable route\n")
14855{
14856 VTY_DECLVAR_CONTEXT(bgp, bgp);
14857 int idx_half_life = 2;
14858 int idx_reuse = 3;
14859 int idx_suppress = 4;
14860 int idx_max_suppress = 5;
37a87b8f
CS
14861 int half = DEFAULT_HALF_LIFE * 60;
14862 int reuse = DEFAULT_REUSE;
14863 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14864 int max = 4 * half;
14865
14866 if (argc == 6) {
14867 half = atoi(argv[idx_half_life]->arg) * 60;
14868 reuse = atoi(argv[idx_reuse]->arg);
14869 suppress = atoi(argv[idx_suppress]->arg);
14870 max = atoi(argv[idx_max_suppress]->arg) * 60;
14871 } else if (argc == 3) {
14872 half = atoi(argv[idx_half_life]->arg) * 60;
14873 max = 4 * half;
14874 }
14875
14876 /*
14877 * These can't be 0 but our SA doesn't understand the
14878 * way our cli is constructed
14879 */
14880 assert(reuse);
14881 assert(half);
14882 if (suppress < reuse) {
14883 vty_out(vty,
14884 "Suppress value cannot be less than reuse value \n");
14885 return 0;
14886 }
14887
14888 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14889 reuse, suppress, max);
14890}
14891
14892DEFUN (bgp_damp_unset,
14893 bgp_damp_unset_cmd,
a30fec23 14894 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14895 NO_STR
14896 "BGP Specific commands\n"
14897 "Enable route-flap dampening\n"
14898 "Half-life time for the penalty\n"
14899 "Value to start reusing a route\n"
14900 "Value to start suppressing a route\n"
14901 "Maximum duration to suppress a stable route\n")
14902{
14903 VTY_DECLVAR_CONTEXT(bgp, bgp);
14904 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14905}
14906
718e3744 14907/* Display specified route of BGP table. */
d62a17ae 14908static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14909 const char *ip_str, afi_t afi, safi_t safi,
14910 struct prefix_rd *prd, int prefix_check)
14911{
14912 int ret;
14913 struct prefix match;
9bcb3eef
DS
14914 struct bgp_dest *dest;
14915 struct bgp_dest *rm;
40381db7
DS
14916 struct bgp_path_info *pi;
14917 struct bgp_path_info *pi_temp;
d62a17ae 14918 struct bgp *bgp;
14919 struct bgp_table *table;
14920
14921 /* BGP structure lookup. */
14922 if (view_name) {
14923 bgp = bgp_lookup_by_name(view_name);
14924 if (bgp == NULL) {
14925 vty_out(vty, "%% Can't find BGP instance %s\n",
14926 view_name);
14927 return CMD_WARNING;
14928 }
14929 } else {
14930 bgp = bgp_get_default();
14931 if (bgp == NULL) {
14932 vty_out(vty, "%% No BGP process is configured\n");
14933 return CMD_WARNING;
14934 }
718e3744 14935 }
718e3744 14936
d62a17ae 14937 /* Check IP address argument. */
14938 ret = str2prefix(ip_str, &match);
14939 if (!ret) {
14940 vty_out(vty, "%% address is malformed\n");
14941 return CMD_WARNING;
14942 }
718e3744 14943
d62a17ae 14944 match.family = afi2family(afi);
14945
14946 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14947 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14948 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14949 dest = bgp_route_next(dest)) {
14950 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14951
9bcb3eef 14952 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14953 continue;
9bcb3eef 14954 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14955 if (!table)
ea47320b 14956 continue;
4953391b
DA
14957 rm = bgp_node_match(table, &match);
14958 if (rm == NULL)
ea47320b 14959 continue;
d62a17ae 14960
9bcb3eef 14961 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14962
ea47320b 14963 if (!prefix_check
b54892e0 14964 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14965 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14966 while (pi) {
14967 if (pi->extra && pi->extra->damp_info) {
14968 pi_temp = pi->next;
ea47320b 14969 bgp_damp_info_free(
19971c9a 14970 pi->extra->damp_info,
5c8846f6 14971 1, afi, safi);
40381db7 14972 pi = pi_temp;
ea47320b 14973 } else
40381db7 14974 pi = pi->next;
d62a17ae 14975 }
ea47320b
DL
14976 }
14977
9bcb3eef 14978 bgp_dest_unlock_node(rm);
d62a17ae 14979 }
14980 } else {
4953391b
DA
14981 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14982 if (dest != NULL) {
9bcb3eef 14983 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14984
d62a17ae 14985 if (!prefix_check
9bcb3eef
DS
14986 || dest_p->prefixlen == match.prefixlen) {
14987 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14988 while (pi) {
14989 if (pi->extra && pi->extra->damp_info) {
14990 pi_temp = pi->next;
d62a17ae 14991 bgp_damp_info_free(
19971c9a 14992 pi->extra->damp_info,
5c8846f6 14993 1, afi, safi);
40381db7 14994 pi = pi_temp;
d62a17ae 14995 } else
40381db7 14996 pi = pi->next;
d62a17ae 14997 }
14998 }
14999
9bcb3eef 15000 bgp_dest_unlock_node(dest);
d62a17ae 15001 }
15002 }
718e3744 15003
d62a17ae 15004 return CMD_SUCCESS;
718e3744 15005}
15006
15007DEFUN (clear_ip_bgp_dampening,
15008 clear_ip_bgp_dampening_cmd,
15009 "clear ip bgp dampening",
15010 CLEAR_STR
15011 IP_STR
15012 BGP_STR
15013 "Clear route flap dampening information\n")
15014{
b4f7f45b 15015 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 15016 return CMD_SUCCESS;
718e3744 15017}
15018
15019DEFUN (clear_ip_bgp_dampening_prefix,
15020 clear_ip_bgp_dampening_prefix_cmd,
15021 "clear ip bgp dampening A.B.C.D/M",
15022 CLEAR_STR
15023 IP_STR
15024 BGP_STR
15025 "Clear route flap dampening information\n"
0c7b1b01 15026 "IPv4 prefix\n")
718e3744 15027{
d62a17ae 15028 int idx_ipv4_prefixlen = 4;
15029 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
15030 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 15031}
15032
15033DEFUN (clear_ip_bgp_dampening_address,
15034 clear_ip_bgp_dampening_address_cmd,
15035 "clear ip bgp dampening A.B.C.D",
15036 CLEAR_STR
15037 IP_STR
15038 BGP_STR
15039 "Clear route flap dampening information\n"
15040 "Network to clear damping information\n")
15041{
d62a17ae 15042 int idx_ipv4 = 4;
15043 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
15044 SAFI_UNICAST, NULL, 0);
718e3744 15045}
15046
15047DEFUN (clear_ip_bgp_dampening_address_mask,
15048 clear_ip_bgp_dampening_address_mask_cmd,
15049 "clear ip bgp dampening A.B.C.D A.B.C.D",
15050 CLEAR_STR
15051 IP_STR
15052 BGP_STR
15053 "Clear route flap dampening information\n"
15054 "Network to clear damping information\n"
15055 "Network mask\n")
15056{
d62a17ae 15057 int idx_ipv4 = 4;
15058 int idx_ipv4_2 = 5;
15059 int ret;
15060 char prefix_str[BUFSIZ];
718e3744 15061
d62a17ae 15062 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 15063 prefix_str, sizeof(prefix_str));
d62a17ae 15064 if (!ret) {
15065 vty_out(vty, "%% Inconsistent address and mask\n");
15066 return CMD_WARNING;
15067 }
718e3744 15068
d62a17ae 15069 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
15070 NULL, 0);
718e3744 15071}
6b0655a2 15072
e3b78da8 15073static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
15074{
15075 struct vty *vty = arg;
e3b78da8 15076 struct peer *peer = bucket->data;
825d9834 15077
47e12884 15078 vty_out(vty, "\tPeer: %s %pSU\n", peer->host, &peer->su);
825d9834
DS
15079}
15080
2a0e69ae
DS
15081DEFUN (show_bgp_listeners,
15082 show_bgp_listeners_cmd,
15083 "show bgp listeners",
15084 SHOW_STR
15085 BGP_STR
15086 "Display Listen Sockets and who created them\n")
15087{
15088 bgp_dump_listener_info(vty);
15089
15090 return CMD_SUCCESS;
15091}
15092
825d9834
DS
15093DEFUN (show_bgp_peerhash,
15094 show_bgp_peerhash_cmd,
15095 "show bgp peerhash",
15096 SHOW_STR
15097 BGP_STR
15098 "Display information about the BGP peerhash\n")
15099{
15100 struct list *instances = bm->bgp;
15101 struct listnode *node;
15102 struct bgp *bgp;
15103
15104 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
15105 vty_out(vty, "BGP: %s\n", bgp->name);
15106 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
15107 vty);
15108 }
15109
15110 return CMD_SUCCESS;
15111}
15112
587ff0fd 15113/* also used for encap safi */
2b791107
DL
15114static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
15115 afi_t afi, safi_t safi)
d62a17ae 15116{
9bcb3eef
DS
15117 struct bgp_dest *pdest;
15118 struct bgp_dest *dest;
d62a17ae 15119 struct bgp_table *table;
b54892e0
DS
15120 const struct prefix *p;
15121 const struct prefix_rd *prd;
d62a17ae 15122 struct bgp_static *bgp_static;
15123 mpls_label_t label;
d62a17ae 15124 char rdbuf[RD_ADDRSTRLEN];
15125
15126 /* Network configuration. */
9bcb3eef
DS
15127 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15128 pdest = bgp_route_next(pdest)) {
15129 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15130 if (!table)
ea47320b 15131 continue;
d62a17ae 15132
9bcb3eef
DS
15133 for (dest = bgp_table_top(table); dest;
15134 dest = bgp_route_next(dest)) {
15135 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15136 if (bgp_static == NULL)
ea47320b 15137 continue;
d62a17ae 15138
9bcb3eef
DS
15139 p = bgp_dest_get_prefix(dest);
15140 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
15141 pdest);
d62a17ae 15142
ea47320b 15143 /* "network" configuration display. */
06b9f471 15144 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
15145 label = decode_label(&bgp_static->label);
15146
8228a9a7 15147 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
15148 if (safi == SAFI_MPLS_VPN)
15149 vty_out(vty, " label %u", label);
15150
15151 if (bgp_static->rmap.name)
15152 vty_out(vty, " route-map %s",
15153 bgp_static->rmap.name);
e2a86ad9
DS
15154
15155 if (bgp_static->backdoor)
15156 vty_out(vty, " backdoor");
15157
ea47320b
DL
15158 vty_out(vty, "\n");
15159 }
15160 }
d62a17ae 15161}
15162
2b791107
DL
15163static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
15164 afi_t afi, safi_t safi)
d62a17ae 15165{
9bcb3eef
DS
15166 struct bgp_dest *pdest;
15167 struct bgp_dest *dest;
d62a17ae 15168 struct bgp_table *table;
b54892e0
DS
15169 const struct prefix *p;
15170 const struct prefix_rd *prd;
d62a17ae 15171 struct bgp_static *bgp_static;
ff44f570 15172 char buf[PREFIX_STRLEN * 2];
d62a17ae 15173 char buf2[SU_ADDRSTRLEN];
15174 char rdbuf[RD_ADDRSTRLEN];
5f933e1e 15175 char esi_buf[ESI_STR_LEN];
d62a17ae 15176
15177 /* Network configuration. */
9bcb3eef
DS
15178 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15179 pdest = bgp_route_next(pdest)) {
15180 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15181 if (!table)
ea47320b 15182 continue;
d62a17ae 15183
9bcb3eef
DS
15184 for (dest = bgp_table_top(table); dest;
15185 dest = bgp_route_next(dest)) {
15186 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15187 if (bgp_static == NULL)
ea47320b 15188 continue;
d62a17ae 15189
ea47320b 15190 char *macrouter = NULL;
d62a17ae 15191
ea47320b
DL
15192 if (bgp_static->router_mac)
15193 macrouter = prefix_mac2str(
15194 bgp_static->router_mac, NULL, 0);
15195 if (bgp_static->eth_s_id)
0a50c248
AK
15196 esi_to_str(bgp_static->eth_s_id,
15197 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15198 p = bgp_dest_get_prefix(dest);
15199 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15200
ea47320b 15201 /* "network" configuration display. */
06b9f471 15202 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15203 if (p->u.prefix_evpn.route_type == 5) {
15204 char local_buf[PREFIX_STRLEN];
3714a385 15205 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15206 struct prefix_evpn *)p)
15207 ? AF_INET
15208 : AF_INET6;
3714a385 15209 inet_ntop(family,
15210 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15211 local_buf, PREFIX_STRLEN);
772270f3
QY
15212 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15213 p->u.prefix_evpn.prefix_addr
15214 .ip_prefix_length);
197cb530
PG
15215 } else {
15216 prefix2str(p, buf, sizeof(buf));
15217 }
ea47320b 15218
a4d82a8a
PZ
15219 if (bgp_static->gatewayIp.family == AF_INET
15220 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15221 inet_ntop(bgp_static->gatewayIp.family,
15222 &bgp_static->gatewayIp.u.prefix, buf2,
15223 sizeof(buf2));
ea47320b 15224 vty_out(vty,
7bcc8dac 15225 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15226 buf, rdbuf,
15227 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15228 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15229 macrouter);
15230
0a22ddfb 15231 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15232 }
15233 }
3da6fcd5
PG
15234}
15235
718e3744 15236/* Configuration of static route announcement and aggregate
15237 information. */
2b791107
DL
15238void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15239 safi_t safi)
d62a17ae 15240{
9bcb3eef 15241 struct bgp_dest *dest;
b54892e0 15242 const struct prefix *p;
d62a17ae 15243 struct bgp_static *bgp_static;
15244 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15245
2b791107
DL
15246 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15247 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15248 return;
15249 }
d62a17ae 15250
2b791107
DL
15251 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15252 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15253 return;
15254 }
d62a17ae 15255
15256 /* Network configuration. */
9bcb3eef
DS
15257 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15258 dest = bgp_route_next(dest)) {
15259 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15260 if (bgp_static == NULL)
ea47320b 15261 continue;
d62a17ae 15262
9bcb3eef 15263 p = bgp_dest_get_prefix(dest);
d62a17ae 15264
8228a9a7 15265 vty_out(vty, " network %pFX", p);
d62a17ae 15266
ea47320b
DL
15267 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15268 vty_out(vty, " label-index %u",
15269 bgp_static->label_index);
d62a17ae 15270
ea47320b
DL
15271 if (bgp_static->rmap.name)
15272 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15273
15274 if (bgp_static->backdoor)
15275 vty_out(vty, " backdoor");
718e3744 15276
ea47320b
DL
15277 vty_out(vty, "\n");
15278 }
15279
d62a17ae 15280 /* Aggregate-address configuration. */
9bcb3eef
DS
15281 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15282 dest = bgp_route_next(dest)) {
15283 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15284 if (bgp_aggregate == NULL)
ea47320b 15285 continue;
d62a17ae 15286
9bcb3eef 15287 p = bgp_dest_get_prefix(dest);
d62a17ae 15288
8228a9a7 15289 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15290
ea47320b
DL
15291 if (bgp_aggregate->as_set)
15292 vty_out(vty, " as-set");
d62a17ae 15293
ea47320b
DL
15294 if (bgp_aggregate->summary_only)
15295 vty_out(vty, " summary-only");
718e3744 15296
20894f50
DA
15297 if (bgp_aggregate->rmap.name)
15298 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15299
229757f1
DA
15300 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15301 vty_out(vty, " origin %s",
15302 bgp_origin2str(bgp_aggregate->origin));
15303
6aabb15d
RZ
15304 if (bgp_aggregate->match_med)
15305 vty_out(vty, " matching-MED-only");
15306
365ab2e7
RZ
15307 if (bgp_aggregate->suppress_map_name)
15308 vty_out(vty, " suppress-map %s",
15309 bgp_aggregate->suppress_map_name);
15310
ea47320b
DL
15311 vty_out(vty, "\n");
15312 }
d62a17ae 15313}
734b349e 15314
2b791107 15315void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15316 safi_t safi)
d62a17ae 15317{
9bcb3eef 15318 struct bgp_dest *dest;
d62a17ae 15319 struct bgp_distance *bdistance;
15320
15321 /* Distance configuration. */
15322 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15323 && bgp->distance_local[afi][safi]
15324 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15325 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15326 || bgp->distance_local[afi][safi]
15327 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15328 vty_out(vty, " distance bgp %d %d %d\n",
15329 bgp->distance_ebgp[afi][safi],
15330 bgp->distance_ibgp[afi][safi],
15331 bgp->distance_local[afi][safi]);
15332 }
734b349e 15333
9bcb3eef
DS
15334 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15335 dest = bgp_route_next(dest)) {
15336 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15337 if (bdistance != NULL)
56ca3b5b 15338 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15339 bdistance->distance, dest,
d62a17ae 15340 bdistance->access_list ? bdistance->access_list
15341 : "");
ca2e160d 15342 }
718e3744 15343}
15344
15345/* Allocate routing table structure and install commands. */
d62a17ae 15346void bgp_route_init(void)
15347{
15348 afi_t afi;
15349 safi_t safi;
15350
15351 /* Init BGP distance table. */
05c7a1cc 15352 FOREACH_AFI_SAFI (afi, safi)
960035b2 15353 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15354
15355 /* IPv4 BGP commands. */
15356 install_element(BGP_NODE, &bgp_table_map_cmd);
15357 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15358 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15359
554b3b10 15360 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15361
15362 /* IPv4 unicast configuration. */
15363 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15364 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15365 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15366
554b3b10 15367 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15368
15369 /* IPv4 multicast configuration. */
15370 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15371 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15372 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15373 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15374
15375 /* IPv4 labeled-unicast configuration. */
fb985e0c 15376 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15377 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15378
d62a17ae 15379 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15380 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15381 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15382 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15383 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15384 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15385 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15386 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15387
15388 install_element(VIEW_NODE,
15389 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15390 install_element(VIEW_NODE,
15391 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15392 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15393 install_element(VIEW_NODE,
15394 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15395#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15396 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15397#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15398 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15399 install_element(VIEW_NODE,
44c69747 15400 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15401
d62a17ae 15402 /* BGP dampening clear commands */
15403 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15404 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15405
d62a17ae 15406 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15407 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15408
15409 /* prefix count */
15410 install_element(ENABLE_NODE,
15411 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15412#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15413 install_element(ENABLE_NODE,
15414 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15415#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15416
d62a17ae 15417 /* New config IPv6 BGP commands. */
15418 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15419 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15420 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15421
554b3b10 15422 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15423
15424 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15425
fb985e0c
DA
15426 /* IPv6 labeled unicast address family. */
15427 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15428 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15429
d62a17ae 15430 install_element(BGP_NODE, &bgp_distance_cmd);
15431 install_element(BGP_NODE, &no_bgp_distance_cmd);
15432 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15433 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15434 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15435 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15436 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15437 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15438 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15439 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15440 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15441 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15442 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15443 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15444 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15445 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15446 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15447 install_element(BGP_IPV4M_NODE,
15448 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15449 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15450 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15451 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15452 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15453 install_element(BGP_IPV6_NODE,
15454 &ipv6_bgp_distance_source_access_list_cmd);
15455 install_element(BGP_IPV6_NODE,
15456 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15457 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15458 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15459 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15460 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15461 install_element(BGP_IPV6M_NODE,
15462 &ipv6_bgp_distance_source_access_list_cmd);
15463 install_element(BGP_IPV6M_NODE,
15464 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15465
ef5f4b23 15466 /* BGP dampening */
585f1adc
IR
15467 install_element(BGP_NODE, &bgp_damp_set_cmd);
15468 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15469 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15470 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15471 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15472 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15473 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15474 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15475 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15476 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15477 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15478 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15479 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15480 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15481
15482 /* Large Communities */
15483 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15484 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15485
15486 /* show bgp ipv4 flowspec detailed */
15487 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15488
2a0e69ae 15489 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15490 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15491}
15492
15493void bgp_route_finish(void)
15494{
15495 afi_t afi;
15496 safi_t safi;
15497
05c7a1cc
QY
15498 FOREACH_AFI_SAFI (afi, safi) {
15499 bgp_table_unlock(bgp_distance_table[afi][safi]);
15500 bgp_distance_table[afi][safi] = NULL;
15501 }
228da428 15502}