]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: announce locators instead of transposed SIDs
[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;
568 bgp_peer_sort_t new_sort;
569 bgp_peer_sort_t 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 */
644 if (newattr->community &&
645 community_include(newattr->community, COMMUNITY_LLGR_STALE)) {
646 if (debug)
647 zlog_debug(
648 "%s: %s wins over %s due to LLGR_STALE community",
649 pfx_buf, new_buf, exist_buf);
650 return 0;
651 }
652
653 if (existattr->community &&
654 community_include(existattr->community, COMMUNITY_LLGR_STALE)) {
655 if (debug)
656 zlog_debug(
657 "%s: %s loses to %s due to LLGR_STALE community",
658 pfx_buf, new_buf, exist_buf);
659 return 1;
660 }
661
5df26422
NS
662 new_p = bgp_dest_get_prefix(new->net);
663
d62a17ae 664 /* For EVPN routes, we cannot just go by local vs remote, we have to
665 * look at the MAC mobility sequence number, if present.
666 */
5df26422
NS
667 if ((safi == SAFI_EVPN)
668 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 669 /* This is an error condition described in RFC 7432 Section
670 * 15.2. The RFC
671 * states that in this scenario "the PE MUST alert the operator"
672 * but it
673 * does not state what other action to take. In order to provide
674 * some
675 * consistency in this scenario we are going to prefer the path
676 * with the
677 * sticky flag.
678 */
679 if (newattr->sticky != existattr->sticky) {
680 if (!debug) {
5df26422
NS
681 prefix2str(new_p, pfx_buf,
682 sizeof(*pfx_buf)
683 * PREFIX2STR_BUFFER);
18ee8310 684 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
685 new, new_buf, sizeof(new_buf));
686 bgp_path_info_path_with_addpath_rx_str(
687 exist, exist_buf, sizeof(exist_buf));
d62a17ae 688 }
689
690 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 691 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
692 if (debug)
693 zlog_debug(
694 "%s: %s wins over %s due to sticky MAC flag",
695 pfx_buf, new_buf, exist_buf);
d62a17ae 696 return 1;
697 }
698
699 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 700 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
701 if (debug)
702 zlog_debug(
703 "%s: %s loses to %s due to sticky MAC flag",
704 pfx_buf, new_buf, exist_buf);
d62a17ae 705 return 0;
706 }
707 }
128ea8ab 708
d071f237
AK
709 new_esi = bgp_evpn_attr_get_esi(newattr);
710 exist_esi = bgp_evpn_attr_get_esi(existattr);
711 if (bgp_evpn_is_esi_valid(new_esi) &&
712 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
713 same_esi = true;
714 } else {
715 same_esi = false;
716 }
717
718 /* If both paths have the same non-zero ES and
719 * one path is local it wins.
720 * PS: Note the local path wins even if the remote
721 * has the higher MM seq. The local path's
722 * MM seq will be fixed up to match the highest
723 * rem seq, subsequently.
724 */
725 if (same_esi) {
726 char esi_buf[ESI_STR_LEN];
727
728 if (bgp_evpn_is_path_local(bgp, new)) {
729 *reason = bgp_path_selection_evpn_local_path;
730 if (debug)
731 zlog_debug(
732 "%s: %s wins over %s as ES %s is same and local",
733 pfx_buf, new_buf, exist_buf,
734 esi_to_str(new_esi, esi_buf,
735 sizeof(esi_buf)));
736 return 1;
737 }
738 if (bgp_evpn_is_path_local(bgp, exist)) {
739 *reason = bgp_path_selection_evpn_local_path;
740 if (debug)
741 zlog_debug(
742 "%s: %s loses to %s as ES %s is same and local",
743 pfx_buf, new_buf, exist_buf,
744 esi_to_str(new_esi, esi_buf,
745 sizeof(esi_buf)));
746 return 0;
747 }
748 }
749
d62a17ae 750 new_mm_seq = mac_mobility_seqnum(newattr);
751 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 752
d62a17ae 753 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 754 *reason = bgp_path_selection_evpn_seq;
d62a17ae 755 if (debug)
756 zlog_debug(
757 "%s: %s wins over %s due to MM seq %u > %u",
758 pfx_buf, new_buf, exist_buf, new_mm_seq,
759 exist_mm_seq);
760 return 1;
761 }
8ff56318 762
d62a17ae 763 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 764 *reason = bgp_path_selection_evpn_seq;
d62a17ae 765 if (debug)
766 zlog_debug(
767 "%s: %s loses to %s due to MM seq %u < %u",
768 pfx_buf, new_buf, exist_buf, new_mm_seq,
769 exist_mm_seq);
770 return 0;
771 }
6d8c603a 772
d071f237
AK
773 /* if the sequence numbers and ESI are the same and one path
774 * is non-proxy it wins (over proxy)
775 */
776 new_proxy = bgp_evpn_attr_is_proxy(newattr);
777 old_proxy = bgp_evpn_attr_is_proxy(existattr);
778 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
779 old_proxy != new_proxy) {
780 if (!new_proxy) {
781 *reason = bgp_path_selection_evpn_non_proxy;
782 if (debug)
783 zlog_debug(
784 "%s: %s wins over %s, same seq/es and non-proxy",
785 pfx_buf, new_buf, exist_buf);
786 return 1;
787 }
788
789 *reason = bgp_path_selection_evpn_non_proxy;
790 if (debug)
791 zlog_debug(
792 "%s: %s loses to %s, same seq/es and non-proxy",
793 pfx_buf, new_buf, exist_buf);
794 return 0;
795 }
796
6d8c603a
AK
797 /*
798 * if sequence numbers are the same path with the lowest IP
799 * wins
800 */
801 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
802 if (nh_cmp < 0) {
fdf81fa0 803 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
804 if (debug)
805 zlog_debug(
23d0a753 806 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 807 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 808 &new->attr->nexthop);
6d8c603a
AK
809 return 1;
810 }
811 if (nh_cmp > 0) {
fdf81fa0 812 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
813 if (debug)
814 zlog_debug(
23d0a753 815 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 816 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 817 &new->attr->nexthop);
6d8c603a
AK
818 return 0;
819 }
d62a17ae 820 }
9fbdd100 821
d62a17ae 822 /* 1. Weight check. */
d62a17ae 823 new_weight = newattr->weight;
824 exist_weight = existattr->weight;
8ff56318 825
d62a17ae 826 if (new_weight > exist_weight) {
fdf81fa0 827 *reason = bgp_path_selection_weight;
d62a17ae 828 if (debug)
829 zlog_debug("%s: %s wins over %s due to weight %d > %d",
830 pfx_buf, new_buf, exist_buf, new_weight,
831 exist_weight);
832 return 1;
833 }
718e3744 834
d62a17ae 835 if (new_weight < exist_weight) {
fdf81fa0 836 *reason = bgp_path_selection_weight;
d62a17ae 837 if (debug)
838 zlog_debug("%s: %s loses to %s due to weight %d < %d",
839 pfx_buf, new_buf, exist_buf, new_weight,
840 exist_weight);
841 return 0;
842 }
9fbdd100 843
d62a17ae 844 /* 2. Local preference check. */
845 new_pref = exist_pref = bgp->default_local_pref;
846
847 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
848 new_pref = newattr->local_pref;
849 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
850 exist_pref = existattr->local_pref;
851
852 if (new_pref > exist_pref) {
fdf81fa0 853 *reason = bgp_path_selection_local_pref;
d62a17ae 854 if (debug)
855 zlog_debug(
856 "%s: %s wins over %s due to localpref %d > %d",
857 pfx_buf, new_buf, exist_buf, new_pref,
858 exist_pref);
859 return 1;
860 }
718e3744 861
d62a17ae 862 if (new_pref < exist_pref) {
fdf81fa0 863 *reason = bgp_path_selection_local_pref;
d62a17ae 864 if (debug)
865 zlog_debug(
866 "%s: %s loses to %s due to localpref %d < %d",
867 pfx_buf, new_buf, exist_buf, new_pref,
868 exist_pref);
869 return 0;
870 }
9fbdd100 871
d62a17ae 872 /* 3. Local route check. We prefer:
873 * - BGP_ROUTE_STATIC
874 * - BGP_ROUTE_AGGREGATE
875 * - BGP_ROUTE_REDISTRIBUTE
876 */
33c6e933
DS
877 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
878 new->sub_type == BGP_ROUTE_IMPORTED);
879 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
880 exist->sub_type == BGP_ROUTE_IMPORTED);
881
882 if (new_origin && !exist_origin) {
fdf81fa0 883 *reason = bgp_path_selection_local_route;
d62a17ae 884 if (debug)
885 zlog_debug(
886 "%s: %s wins over %s due to preferred BGP_ROUTE type",
887 pfx_buf, new_buf, exist_buf);
888 return 1;
889 }
718e3744 890
33c6e933 891 if (!new_origin && exist_origin) {
fdf81fa0 892 *reason = bgp_path_selection_local_route;
d62a17ae 893 if (debug)
894 zlog_debug(
895 "%s: %s loses to %s due to preferred BGP_ROUTE type",
896 pfx_buf, new_buf, exist_buf);
897 return 0;
6811845b 898 }
718e3744 899
da0c0ef7
KM
900 /* Here if these are imported routes then get ultimate pi for
901 * path compare.
902 */
903 new = bgp_get_imported_bpi_ultimate(new);
904 exist = bgp_get_imported_bpi_ultimate(exist);
905 newattr = new->attr;
906 existattr = exist->attr;
907
d62a17ae 908 /* 4. AS path length check. */
892fedb6 909 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 910 int exist_hops = aspath_count_hops(existattr->aspath);
911 int exist_confeds = aspath_count_confeds(existattr->aspath);
912
892fedb6 913 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 914 int aspath_hops;
915
916 aspath_hops = aspath_count_hops(newattr->aspath);
917 aspath_hops += aspath_count_confeds(newattr->aspath);
918
919 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 920 *reason = bgp_path_selection_confed_as_path;
d62a17ae 921 if (debug)
922 zlog_debug(
923 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
924 pfx_buf, new_buf, exist_buf,
925 aspath_hops,
926 (exist_hops + exist_confeds));
927 return 1;
928 }
929
930 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 931 *reason = bgp_path_selection_confed_as_path;
d62a17ae 932 if (debug)
933 zlog_debug(
934 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
935 pfx_buf, new_buf, exist_buf,
936 aspath_hops,
937 (exist_hops + exist_confeds));
938 return 0;
939 }
940 } else {
941 int newhops = aspath_count_hops(newattr->aspath);
942
943 if (newhops < exist_hops) {
fdf81fa0 944 *reason = bgp_path_selection_as_path;
d62a17ae 945 if (debug)
946 zlog_debug(
947 "%s: %s wins over %s due to aspath hopcount %d < %d",
948 pfx_buf, new_buf, exist_buf,
949 newhops, exist_hops);
950 return 1;
951 }
952
953 if (newhops > exist_hops) {
fdf81fa0 954 *reason = bgp_path_selection_as_path;
d62a17ae 955 if (debug)
956 zlog_debug(
957 "%s: %s loses to %s due to aspath hopcount %d > %d",
958 pfx_buf, new_buf, exist_buf,
959 newhops, exist_hops);
960 return 0;
961 }
962 }
963 }
9fbdd100 964
d62a17ae 965 /* 5. Origin check. */
966 if (newattr->origin < existattr->origin) {
fdf81fa0 967 *reason = bgp_path_selection_origin;
d62a17ae 968 if (debug)
969 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
970 pfx_buf, new_buf, exist_buf,
971 bgp_origin_long_str[newattr->origin],
972 bgp_origin_long_str[existattr->origin]);
973 return 1;
974 }
718e3744 975
d62a17ae 976 if (newattr->origin > existattr->origin) {
fdf81fa0 977 *reason = bgp_path_selection_origin;
d62a17ae 978 if (debug)
979 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
980 pfx_buf, new_buf, exist_buf,
981 bgp_origin_long_str[newattr->origin],
982 bgp_origin_long_str[existattr->origin]);
983 return 0;
984 }
718e3744 985
d62a17ae 986 /* 6. MED check. */
987 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
988 && aspath_count_hops(existattr->aspath) == 0);
989 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
990 && aspath_count_confeds(existattr->aspath) > 0
991 && aspath_count_hops(newattr->aspath) == 0
992 && aspath_count_hops(existattr->aspath) == 0);
993
892fedb6
DA
994 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
995 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 996 || aspath_cmp_left(newattr->aspath, existattr->aspath)
997 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
998 || internal_as_route) {
999 new_med = bgp_med_value(new->attr, bgp);
1000 exist_med = bgp_med_value(exist->attr, bgp);
1001
1002 if (new_med < exist_med) {
fdf81fa0 1003 *reason = bgp_path_selection_med;
d62a17ae 1004 if (debug)
1005 zlog_debug(
1006 "%s: %s wins over %s due to MED %d < %d",
1007 pfx_buf, new_buf, exist_buf, new_med,
1008 exist_med);
1009 return 1;
1010 }
8ff56318 1011
d62a17ae 1012 if (new_med > exist_med) {
fdf81fa0 1013 *reason = bgp_path_selection_med;
d62a17ae 1014 if (debug)
1015 zlog_debug(
1016 "%s: %s loses to %s due to MED %d > %d",
1017 pfx_buf, new_buf, exist_buf, new_med,
1018 exist_med);
1019 return 0;
1020 }
1021 }
9fbdd100 1022
d62a17ae 1023 /* 7. Peer type check. */
1024 new_sort = new->peer->sort;
1025 exist_sort = exist->peer->sort;
1026
1027 if (new_sort == BGP_PEER_EBGP
1028 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 1029 *reason = bgp_path_selection_peer;
d62a17ae 1030 if (debug)
1031 zlog_debug(
1032 "%s: %s wins over %s due to eBGP peer > iBGP peer",
1033 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1034 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1035 return 1;
1036 peer_sort_ret = 1;
d62a17ae 1037 }
718e3744 1038
d62a17ae 1039 if (exist_sort == BGP_PEER_EBGP
1040 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 1041 *reason = bgp_path_selection_peer;
d62a17ae 1042 if (debug)
1043 zlog_debug(
1044 "%s: %s loses to %s due to iBGP peer < eBGP peer",
1045 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1046 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1047 return 0;
1048 peer_sort_ret = 0;
d62a17ae 1049 }
8ff56318 1050
d62a17ae 1051 /* 8. IGP metric check. */
1052 newm = existm = 0;
8ff56318 1053
d62a17ae 1054 if (new->extra)
1055 newm = new->extra->igpmetric;
1056 if (exist->extra)
1057 existm = exist->extra->igpmetric;
9fbdd100 1058
d62a17ae 1059 if (newm < existm) {
ee88563a 1060 if (debug && peer_sort_ret < 0)
d62a17ae 1061 zlog_debug(
d588b995 1062 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1063 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1064 igp_metric_ret = 1;
d62a17ae 1065 }
718e3744 1066
d62a17ae 1067 if (newm > existm) {
ee88563a 1068 if (debug && peer_sort_ret < 0)
d62a17ae 1069 zlog_debug(
d588b995 1070 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1071 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1072 igp_metric_ret = 0;
5e242b0d 1073 }
5e242b0d 1074
d62a17ae 1075 /* 9. Same IGP metric. Compare the cluster list length as
1076 representative of IGP hops metric. Rewrite the metric value
1077 pair (newm, existm) with the cluster list length. Prefer the
1078 path with smaller cluster list length. */
1079 if (newm == existm) {
bf0d28dc
DS
1080 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1081 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1082 && (mpath_cfg == NULL
1083 || CHECK_FLAG(
1084 mpath_cfg->ibgp_flags,
1085 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1086 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1087 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1088
1089 if (newm < existm) {
ee88563a 1090 if (debug && peer_sort_ret < 0)
d62a17ae 1091 zlog_debug(
d588b995 1092 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1093 pfx_buf, new_buf, exist_buf,
1094 newm, existm);
ee88563a 1095 igp_metric_ret = 1;
d62a17ae 1096 }
1097
1098 if (newm > existm) {
ee88563a 1099 if (debug && peer_sort_ret < 0)
d62a17ae 1100 zlog_debug(
d588b995 1101 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1102 pfx_buf, new_buf, exist_buf,
1103 newm, existm);
ee88563a 1104 igp_metric_ret = 0;
d62a17ae 1105 }
1106 }
1107 }
31a4638f 1108
d62a17ae 1109 /* 10. confed-external vs. confed-internal */
1110 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1111 if (new_sort == BGP_PEER_CONFED
1112 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1113 *reason = bgp_path_selection_confed;
d62a17ae 1114 if (debug)
1115 zlog_debug(
1116 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1117 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1118 if (!CHECK_FLAG(bgp->flags,
1119 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1120 return 1;
1121 peer_sort_ret = 1;
d62a17ae 1122 }
718e3744 1123
d62a17ae 1124 if (exist_sort == BGP_PEER_CONFED
1125 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1126 *reason = bgp_path_selection_confed;
d62a17ae 1127 if (debug)
1128 zlog_debug(
1129 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1130 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1131 if (!CHECK_FLAG(bgp->flags,
1132 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1133 return 0;
1134 peer_sort_ret = 0;
d62a17ae 1135 }
1136 }
718e3744 1137
d62a17ae 1138 /* 11. Maximum path check. */
1139 if (newm == existm) {
1140 /* If one path has a label but the other does not, do not treat
1141 * them as equals for multipath
1142 */
a4d82a8a 1143 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1144 != (exist->extra
b57ba6d2 1145 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1146 if (debug)
1147 zlog_debug(
1148 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1149 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1150 } else if (CHECK_FLAG(bgp->flags,
1151 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1152
1153 /*
1154 * For the two paths, all comparison steps till IGP
1155 * metric
1156 * have succeeded - including AS_PATH hop count. Since
1157 * 'bgp
1158 * bestpath as-path multipath-relax' knob is on, we
1159 * don't need
1160 * an exact match of AS_PATH. Thus, mark the paths are
1161 * equal.
1162 * That will trigger both these paths to get into the
1163 * multipath
1164 * array.
1165 */
1166 *paths_eq = 1;
1167
1168 if (debug)
1169 zlog_debug(
1170 "%s: %s and %s are equal via multipath-relax",
1171 pfx_buf, new_buf, exist_buf);
1172 } else if (new->peer->sort == BGP_PEER_IBGP) {
1173 if (aspath_cmp(new->attr->aspath,
1174 exist->attr->aspath)) {
1175 *paths_eq = 1;
1176
1177 if (debug)
1178 zlog_debug(
1179 "%s: %s and %s are equal via matching aspaths",
1180 pfx_buf, new_buf, exist_buf);
1181 }
1182 } else if (new->peer->as == exist->peer->as) {
1183 *paths_eq = 1;
1184
1185 if (debug)
1186 zlog_debug(
1187 "%s: %s and %s are equal via same remote-as",
1188 pfx_buf, new_buf, exist_buf);
1189 }
1190 } else {
1191 /*
1192 * TODO: If unequal cost ibgp multipath is enabled we can
1193 * mark the paths as equal here instead of returning
1194 */
ee88563a
JM
1195
1196 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1197 * if either step 7 or 10 (peer type checks) yielded a winner,
1198 * that result was returned immediately. Returning from step 10
1199 * ignored the return value computed in steps 8 and 9 (IGP
1200 * metric checks). In order to preserve that behavior, if
1201 * peer_sort_ret is set, return that rather than igp_metric_ret.
1202 */
1203 ret = peer_sort_ret;
1204 if (peer_sort_ret < 0) {
1205 ret = igp_metric_ret;
1206 if (debug) {
1207 if (ret == 1)
1208 zlog_debug(
1209 "%s: %s wins over %s after IGP metric comparison",
1210 pfx_buf, new_buf, exist_buf);
1211 else
1212 zlog_debug(
1213 "%s: %s loses to %s after IGP metric comparison",
1214 pfx_buf, new_buf, exist_buf);
1215 }
1216 *reason = bgp_path_selection_igp_metric;
d62a17ae 1217 }
1218 return ret;
1219 }
718e3744 1220
ee88563a
JM
1221 /*
1222 * At this point, the decision whether to set *paths_eq = 1 has been
1223 * completed. If we deferred returning because of bestpath peer-type
1224 * relax configuration, return now.
1225 */
1226 if (peer_sort_ret >= 0)
1227 return peer_sort_ret;
1228
d62a17ae 1229 /* 12. If both paths are external, prefer the path that was received
1230 first (the oldest one). This step minimizes route-flap, since a
1231 newer path won't displace an older one, even if it was the
1232 preferred route based on the additional decision criteria below. */
892fedb6 1233 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1234 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1235 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1236 *reason = bgp_path_selection_older;
d62a17ae 1237 if (debug)
1238 zlog_debug(
1239 "%s: %s wins over %s due to oldest external",
1240 pfx_buf, new_buf, exist_buf);
1241 return 1;
1242 }
9fbdd100 1243
1defdda8 1244 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1245 *reason = bgp_path_selection_older;
d62a17ae 1246 if (debug)
1247 zlog_debug(
1248 "%s: %s loses to %s due to oldest external",
1249 pfx_buf, new_buf, exist_buf);
1250 return 0;
1251 }
1252 }
718e3744 1253
d62a17ae 1254 /* 13. Router-ID comparision. */
1255 /* If one of the paths is "stale", the corresponding peer router-id will
1256 * be 0 and would always win over the other path. If originator id is
1257 * used for the comparision, it will decide which path is better.
1258 */
1259 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1260 new_id.s_addr = newattr->originator_id.s_addr;
1261 else
1262 new_id.s_addr = new->peer->remote_id.s_addr;
1263 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1264 exist_id.s_addr = existattr->originator_id.s_addr;
1265 else
1266 exist_id.s_addr = exist->peer->remote_id.s_addr;
1267
1268 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1269 *reason = bgp_path_selection_router_id;
d62a17ae 1270 if (debug)
1271 zlog_debug(
1272 "%s: %s wins over %s due to Router-ID comparison",
1273 pfx_buf, new_buf, exist_buf);
1274 return 1;
1275 }
718e3744 1276
d62a17ae 1277 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1278 *reason = bgp_path_selection_router_id;
d62a17ae 1279 if (debug)
1280 zlog_debug(
1281 "%s: %s loses to %s due to Router-ID comparison",
1282 pfx_buf, new_buf, exist_buf);
1283 return 0;
1284 }
9fbdd100 1285
d62a17ae 1286 /* 14. Cluster length comparision. */
1287 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1288 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1289
1290 if (new_cluster < exist_cluster) {
fdf81fa0 1291 *reason = bgp_path_selection_cluster_length;
d62a17ae 1292 if (debug)
1293 zlog_debug(
1294 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1295 pfx_buf, new_buf, exist_buf, new_cluster,
1296 exist_cluster);
1297 return 1;
1298 }
718e3744 1299
d62a17ae 1300 if (new_cluster > exist_cluster) {
fdf81fa0 1301 *reason = bgp_path_selection_cluster_length;
d62a17ae 1302 if (debug)
1303 zlog_debug(
1304 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1305 pfx_buf, new_buf, exist_buf, new_cluster,
1306 exist_cluster);
1307 return 0;
1308 }
9fbdd100 1309
d62a17ae 1310 /* 15. Neighbor address comparision. */
1311 /* Do this only if neither path is "stale" as stale paths do not have
1312 * valid peer information (as the connection may or may not be up).
1313 */
1defdda8 1314 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1315 *reason = bgp_path_selection_stale;
d62a17ae 1316 if (debug)
1317 zlog_debug(
1318 "%s: %s wins over %s due to latter path being STALE",
1319 pfx_buf, new_buf, exist_buf);
1320 return 1;
1321 }
0de5153c 1322
1defdda8 1323 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1324 *reason = bgp_path_selection_stale;
d62a17ae 1325 if (debug)
1326 zlog_debug(
1327 "%s: %s loses to %s due to former path being STALE",
1328 pfx_buf, new_buf, exist_buf);
1329 return 0;
1330 }
718e3744 1331
d62a17ae 1332 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1333 if (new->peer->su_remote == NULL) {
1334 *reason = bgp_path_selection_local_configured;
d62a17ae 1335 return 0;
fdf81fa0
DS
1336 }
1337 if (exist->peer->su_remote == NULL) {
1338 *reason = bgp_path_selection_local_configured;
d62a17ae 1339 return 1;
fdf81fa0 1340 }
9fbdd100 1341
d62a17ae 1342 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1343
1344 if (ret == 1) {
fdf81fa0 1345 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1346 if (debug)
1347 zlog_debug(
1348 "%s: %s loses to %s due to Neighor IP comparison",
1349 pfx_buf, new_buf, exist_buf);
1350 return 0;
1351 }
1352
1353 if (ret == -1) {
fdf81fa0 1354 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1355 if (debug)
1356 zlog_debug(
1357 "%s: %s wins over %s due to Neighor IP comparison",
1358 pfx_buf, new_buf, exist_buf);
1359 return 1;
1360 }
9fbdd100 1361
fdf81fa0 1362 *reason = bgp_path_selection_default;
d62a17ae 1363 if (debug)
1364 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1365 pfx_buf, new_buf, exist_buf);
718e3744 1366
d62a17ae 1367 return 1;
718e3744 1368}
1369
d071f237
AK
1370
1371int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1372 struct bgp_path_info *exist, int *paths_eq)
1373{
1374 enum bgp_path_selection_reason reason;
1375 char pfx_buf[PREFIX2STR_BUFFER];
1376
1377 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1378 AFI_L2VPN, SAFI_EVPN, &reason);
1379}
1380
65efcfce
LB
1381/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1382 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1383 * multipath is enabled
65efcfce 1384 * This version is compatible with */
18ee8310
DS
1385int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1386 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1387 afi_t afi, safi_t safi,
1388 enum bgp_path_selection_reason *reason)
d62a17ae 1389{
1390 int paths_eq;
1391 int ret;
18ee8310 1392 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1393 afi, safi, reason);
d62a17ae 1394
1395 if (paths_eq)
1396 ret = 0;
1397 else {
1398 if (ret == 1)
1399 ret = -1;
1400 else
1401 ret = 1;
1402 }
1403 return ret;
65efcfce
LB
1404}
1405
5a1ae2c2
DS
1406static enum filter_type bgp_input_filter(struct peer *peer,
1407 const struct prefix *p,
d62a17ae 1408 struct attr *attr, afi_t afi,
1409 safi_t safi)
718e3744 1410{
d62a17ae 1411 struct bgp_filter *filter;
6401252f 1412 enum filter_type ret = FILTER_PERMIT;
718e3744 1413
d62a17ae 1414 filter = &peer->filter[afi][safi];
718e3744 1415
d62a17ae 1416#define FILTER_EXIST_WARN(F, f, filter) \
1417 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1418 zlog_debug("%s: Could not find configured input %s-list %s!", \
1419 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1420
1421 if (DISTRIBUTE_IN_NAME(filter)) {
1422 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1423
6401252f
QY
1424 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1425 == FILTER_DENY) {
1426 ret = FILTER_DENY;
1427 goto done;
1428 }
d62a17ae 1429 }
1430
1431 if (PREFIX_LIST_IN_NAME(filter)) {
1432 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1433
6401252f
QY
1434 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1435 == PREFIX_DENY) {
1436 ret = FILTER_DENY;
1437 goto done;
1438 }
d62a17ae 1439 }
1440
1441 if (FILTER_LIST_IN_NAME(filter)) {
1442 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1443
1444 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1445 == AS_FILTER_DENY) {
1446 ret = FILTER_DENY;
1447 goto done;
1448 }
d62a17ae 1449 }
1450
6401252f 1451done:
c7bb4f00 1452 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1453 char pfxprint[PREFIX2STR_BUFFER];
1454
1455 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1456 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1457 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1458 }
1459
1460 return ret;
650f76c2 1461#undef FILTER_EXIST_WARN
718e3744 1462}
1463
b8685f9b
DS
1464static enum filter_type bgp_output_filter(struct peer *peer,
1465 const struct prefix *p,
d62a17ae 1466 struct attr *attr, afi_t afi,
1467 safi_t safi)
718e3744 1468{
d62a17ae 1469 struct bgp_filter *filter;
6401252f 1470 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1471
1472 filter = &peer->filter[afi][safi];
1473
1474#define FILTER_EXIST_WARN(F, f, filter) \
1475 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1476 zlog_debug("%s: Could not find configured output %s-list %s!", \
1477 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1478
d62a17ae 1479 if (DISTRIBUTE_OUT_NAME(filter)) {
1480 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1481
6401252f
QY
1482 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1483 == FILTER_DENY) {
1484 ret = FILTER_DENY;
1485 goto done;
1486 }
d62a17ae 1487 }
1488
1489 if (PREFIX_LIST_OUT_NAME(filter)) {
1490 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1491
d62a17ae 1492 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1493 == PREFIX_DENY) {
1494 ret = FILTER_DENY;
1495 goto done;
1496 }
d62a17ae 1497 }
718e3744 1498
d62a17ae 1499 if (FILTER_LIST_OUT_NAME(filter)) {
1500 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1501
d62a17ae 1502 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1503 == AS_FILTER_DENY) {
1504 ret = FILTER_DENY;
1505 goto done;
1506 }
1507 }
1508
c7bb4f00 1509 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1510 char pfxprint[PREFIX2STR_BUFFER];
1511
1512 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1513 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1514 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1515 }
718e3744 1516
6401252f
QY
1517done:
1518 return ret;
650f76c2 1519#undef FILTER_EXIST_WARN
718e3744 1520}
1521
1522/* If community attribute includes no_export then return 1. */
3dc339cd 1523static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1524{
1525 if (attr->community) {
1526 /* NO_ADVERTISE check. */
1527 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1528 return true;
d62a17ae 1529
1530 /* NO_EXPORT check. */
1531 if (peer->sort == BGP_PEER_EBGP
1532 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1533 return true;
d62a17ae 1534
1535 /* NO_EXPORT_SUBCONFED check. */
1536 if (peer->sort == BGP_PEER_EBGP
1537 || peer->sort == BGP_PEER_CONFED)
1538 if (community_include(attr->community,
1539 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1540 return true;
d62a17ae 1541 }
3dc339cd 1542 return false;
718e3744 1543}
1544
1545/* Route reflection loop check. */
3dc339cd 1546static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1547{
d62a17ae 1548 struct in_addr cluster_id;
779fee93 1549 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1550
779fee93 1551 if (cluster) {
d62a17ae 1552 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1553 cluster_id = peer->bgp->cluster_id;
1554 else
1555 cluster_id = peer->bgp->router_id;
1556
779fee93 1557 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1558 return true;
d62a17ae 1559 }
3dc339cd 1560 return false;
718e3744 1561}
6b0655a2 1562
5a1ae2c2 1563static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1564 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1565 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1566 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1567{
d62a17ae 1568 struct bgp_filter *filter;
82b692c0
LK
1569 struct bgp_path_info rmap_path = { 0 };
1570 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1571 route_map_result_t ret;
1572 struct route_map *rmap = NULL;
718e3744 1573
d62a17ae 1574 filter = &peer->filter[afi][safi];
718e3744 1575
d62a17ae 1576 /* Apply default weight value. */
1577 if (peer->weight[afi][safi])
1578 attr->weight = peer->weight[afi][safi];
718e3744 1579
d62a17ae 1580 if (rmap_name) {
1581 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1582
d62a17ae 1583 if (rmap == NULL)
1584 return RMAP_DENY;
1585 } else {
1586 if (ROUTE_MAP_IN_NAME(filter)) {
1587 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1588
d62a17ae 1589 if (rmap == NULL)
1590 return RMAP_DENY;
1591 }
1592 }
0b16f239 1593
d62a17ae 1594 /* Route map apply. */
1595 if (rmap) {
40381db7 1596 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1597 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1598 rmap_path.peer = peer;
1599 rmap_path.attr = attr;
82b692c0 1600 rmap_path.extra = &extra;
9bcb3eef 1601 rmap_path.net = dest;
196c6b09 1602
82b692c0
LK
1603 extra.num_labels = num_labels;
1604 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1605 memcpy(extra.label, label,
1606 num_labels * sizeof(mpls_label_t));
718e3744 1607
d62a17ae 1608 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1609
d62a17ae 1610 /* Apply BGP route map to the attribute. */
1782514f 1611 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1612
d62a17ae 1613 peer->rmap_type = 0;
0b16f239 1614
1f2263be 1615 if (ret == RMAP_DENYMATCH)
d62a17ae 1616 return RMAP_DENY;
0b16f239 1617 }
d62a17ae 1618 return RMAP_PERMIT;
0b16f239
DS
1619}
1620
5f040085 1621static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1622 struct attr *attr, afi_t afi, safi_t safi,
1623 const char *rmap_name)
0b16f239 1624{
40381db7 1625 struct bgp_path_info rmap_path;
d62a17ae 1626 route_map_result_t ret;
1627 struct route_map *rmap = NULL;
d7c0a89a 1628 uint8_t rmap_type;
0b16f239 1629
b787157a
DS
1630 /*
1631 * So if we get to this point and have no rmap_name
1632 * we want to just show the output as it currently
1633 * exists.
1634 */
1635 if (!rmap_name)
1636 return RMAP_PERMIT;
0b16f239 1637
d62a17ae 1638 /* Apply default weight value. */
1639 if (peer->weight[afi][safi])
1640 attr->weight = peer->weight[afi][safi];
0b16f239 1641
b787157a 1642 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1643
b787157a
DS
1644 /*
1645 * If we have a route map name and we do not find
1646 * the routemap that means we have an implicit
1647 * deny.
1648 */
1649 if (rmap == NULL)
1650 return RMAP_DENY;
0b16f239 1651
40381db7 1652 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1653 /* Route map apply. */
b787157a 1654 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1655 rmap_path.peer = peer;
1656 rmap_path.attr = attr;
0b16f239 1657
0f672529 1658 rmap_type = peer->rmap_type;
b787157a 1659 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1660
b787157a 1661 /* Apply BGP route map to the attribute. */
1782514f 1662 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1663
0f672529 1664 peer->rmap_type = rmap_type;
b787157a
DS
1665
1666 if (ret == RMAP_DENYMATCH)
1667 /*
1668 * caller has multiple error paths with bgp_attr_flush()
1669 */
1670 return RMAP_DENY;
ac41b2a2 1671
d62a17ae 1672 return RMAP_PERMIT;
718e3744 1673}
6b0655a2 1674
5000f21c 1675/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1676static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1677 struct peer *peer, struct attr *attr)
1678{
1679 if (peer->sort == BGP_PEER_EBGP
1680 && (peer_af_flag_check(peer, afi, safi,
1681 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1682 || peer_af_flag_check(peer, afi, safi,
1683 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1684 || peer_af_flag_check(peer, afi, safi,
1685 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1686 || peer_af_flag_check(peer, afi, safi,
1687 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1688 // Take action on the entire aspath
1689 if (peer_af_flag_check(peer, afi, safi,
1690 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1691 || peer_af_flag_check(peer, afi, safi,
1692 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1693 if (peer_af_flag_check(
1694 peer, afi, safi,
1695 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1696 attr->aspath = aspath_replace_private_asns(
bf26b80e 1697 attr->aspath, bgp->as, peer->as);
d62a17ae 1698
179d5a0e
TA
1699 /*
1700 * Even if the aspath consists of just private ASNs we
1701 * need to walk the AS-Path to maintain all instances
1702 * of the peer's ASN to break possible loops.
1703 */
d62a17ae 1704 else
1705 attr->aspath = aspath_remove_private_asns(
bf26b80e 1706 attr->aspath, peer->as);
d62a17ae 1707 }
1708
1709 // 'all' was not specified so the entire aspath must be private
1710 // ASNs
1711 // for us to do anything
1712 else if (aspath_private_as_check(attr->aspath)) {
1713 if (peer_af_flag_check(
1714 peer, afi, safi,
1715 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1716 attr->aspath = aspath_replace_private_asns(
bf26b80e 1717 attr->aspath, bgp->as, peer->as);
d62a17ae 1718 else
179d5a0e
TA
1719 /*
1720 * Walk the aspath to retain any instances of
1721 * the peer_asn
1722 */
1723 attr->aspath = aspath_remove_private_asns(
1724 attr->aspath, peer->as);
d62a17ae 1725 }
1726 }
5000f21c
DS
1727}
1728
c7122e14 1729/* If this is an EBGP peer with as-override */
d62a17ae 1730static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1731 struct peer *peer, struct attr *attr)
1732{
1733 if (peer->sort == BGP_PEER_EBGP
1734 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1735 if (aspath_single_asn_check(attr->aspath, peer->as))
1736 attr->aspath = aspath_replace_specific_asn(
1737 attr->aspath, peer->as, bgp->as);
1738 }
1739}
1740
1479ed2f
DA
1741void bgp_attr_add_llgr_community(struct attr *attr)
1742{
1743 struct community *old;
1744 struct community *new;
1745 struct community *merge;
1746 struct community *llgr;
1747
1748 old = attr->community;
1749 llgr = community_str2com("llgr-stale");
1750
1751 assert(llgr);
1752
1753 if (old) {
1754 merge = community_merge(community_dup(old), llgr);
1755
1756 if (old->refcnt == 0)
1757 community_free(&old);
1758
1759 new = community_uniq_sort(merge);
1760 community_free(&merge);
1761 } else {
1762 new = community_dup(llgr);
1763 }
1764
1765 community_free(&llgr);
1766
1767 attr->community = new;
1768 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1769}
1770
7f323236
DW
1771void bgp_attr_add_gshut_community(struct attr *attr)
1772{
1773 struct community *old;
1774 struct community *new;
1775 struct community *merge;
1776 struct community *gshut;
1777
1778 old = attr->community;
1779 gshut = community_str2com("graceful-shutdown");
1780
990f4f91 1781 assert(gshut);
1782
7f323236
DW
1783 if (old) {
1784 merge = community_merge(community_dup(old), gshut);
1785
a4d82a8a 1786 if (old->refcnt == 0)
3c1f53de 1787 community_free(&old);
7f323236
DW
1788
1789 new = community_uniq_sort(merge);
3c1f53de 1790 community_free(&merge);
7f323236
DW
1791 } else {
1792 new = community_dup(gshut);
1793 }
1794
3c1f53de 1795 community_free(&gshut);
7f323236
DW
1796 attr->community = new;
1797 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1798
1799 /* When we add the graceful-shutdown community we must also
1800 * lower the local-preference */
1801 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1802 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1803}
1804
1805
e73c112e
MK
1806/* Notify BGP Conditional advertisement scanner process. */
1807void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1808{
e73c112e 1809 struct peer *peer = SUBGRP_PEER(subgrp);
e73c112e
MK
1810 afi_t afi = SUBGRP_AFI(subgrp);
1811 safi_t safi = SUBGRP_SAFI(subgrp);
e73c112e
MK
1812 struct bgp_filter *filter = &peer->filter[afi][safi];
1813
1814 if (!ADVERTISE_MAP_NAME(filter))
1815 return;
1816
52979c3b
DS
1817 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1818 return;
e73c112e 1819
52979c3b 1820 peer->advmap_table_change = true;
e73c112e
MK
1821}
1822
1823
f2ee6d5c 1824void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1825{
960035b2 1826 if (family == AF_INET) {
975a328e
DA
1827 attr->nexthop.s_addr = INADDR_ANY;
1828 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1829 }
d62a17ae 1830 if (family == AF_INET6)
1831 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1832 if (family == AF_EVPN)
1833 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1834}
1835
9bcb3eef 1836bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1837 struct update_subgroup *subgrp,
7f7940e6 1838 const struct prefix *p, struct attr *attr,
51c3a7de 1839 struct attr *post_attr)
d62a17ae 1840{
1841 struct bgp_filter *filter;
1842 struct peer *from;
1843 struct peer *peer;
1844 struct peer *onlypeer;
1845 struct bgp *bgp;
40381db7 1846 struct attr *piattr;
b68885f9 1847 route_map_result_t ret;
d62a17ae 1848 int transparent;
1849 int reflect;
1850 afi_t afi;
1851 safi_t safi;
1852 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1853 bool nh_reset = false;
1854 uint64_t cum_bw;
d62a17ae 1855
1856 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1857 return false;
d62a17ae 1858
1859 afi = SUBGRP_AFI(subgrp);
1860 safi = SUBGRP_SAFI(subgrp);
1861 peer = SUBGRP_PEER(subgrp);
1862 onlypeer = NULL;
1863 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1864 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1865
40381db7 1866 from = pi->peer;
d62a17ae 1867 filter = &peer->filter[afi][safi];
1868 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1869 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1870 : pi->attr;
3f9c7369 1871
d0bf49ec
LS
1872 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_OUT) &&
1873 peer->pmax_out[afi][safi] != 0 &&
1874 subgrp->pscount >= peer->pmax_out[afi][safi]) {
1875 if (BGP_DEBUG(update, UPDATE_OUT) ||
1876 BGP_DEBUG(update, UPDATE_PREFIX)) {
1877 zlog_debug("%s reached maximum prefix to be send (%u)",
1878 peer->host, peer->pmax_out[afi][safi]);
1879 }
1880 return false;
1881 }
1882
49e5a4a0 1883#ifdef ENABLE_BGP_VNC
d62a17ae 1884 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1885 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1886 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1887
1888 /*
1889 * direct and direct_ext type routes originate internally even
1890 * though they can have peer pointers that reference other
1891 * systems
1892 */
8228a9a7
DS
1893 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1894 __func__, p);
d62a17ae 1895 samepeer_safe = 1;
1896 }
65efcfce
LB
1897#endif
1898
ddb5b488
PZ
1899 if (((afi == AFI_IP) || (afi == AFI_IP6))
1900 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1901 && (pi->type == ZEBRA_ROUTE_BGP)
1902 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1903
1904 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1905
1906 samepeer_safe = 1;
1907 }
1908
d62a17ae 1909 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1910 * pi is valid */
1911 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1912 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1913 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1914 return false;
d62a17ae 1915 }
adbac85e 1916
d62a17ae 1917 /* If this is not the bestpath then check to see if there is an enabled
1918 * addpath
1919 * feature that requires us to advertise it */
40381db7 1920 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1921 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1922 return false;
d62a17ae 1923 }
1924 }
06370dac 1925
d62a17ae 1926 /* Aggregate-address suppress check. */
4056a5f6
RZ
1927 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1928 return false;
3f9c7369 1929
13b7e7f0
DS
1930 /*
1931 * If we are doing VRF 2 VRF leaking via the import
1932 * statement, we want to prevent the route going
1933 * off box as that the RT and RD created are localy
1934 * significant and globaly useless.
1935 */
40381db7
DS
1936 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1937 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1938 return false;
13b7e7f0 1939
d62a17ae 1940 /* If it's labeled safi, make sure the route has a valid label. */
1941 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1942 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1943 if (!bgp_is_valid_label(&label)) {
1944 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1945 zlog_debug("u%" PRIu64 ":s%" PRIu64
1946 " %pFX is filtered - no label (%p)",
d62a17ae 1947 subgrp->update_group->id, subgrp->id,
8228a9a7 1948 p, &label);
3dc339cd 1949 return false;
d62a17ae 1950 }
1951 }
cd1964ff 1952
d62a17ae 1953 /* Do not send back route to sender. */
1954 if (onlypeer && from == onlypeer) {
3dc339cd 1955 return false;
d62a17ae 1956 }
3f9c7369 1957
d62a17ae 1958 /* Do not send the default route in the BGP table if the neighbor is
1959 * configured for default-originate */
1960 if (CHECK_FLAG(peer->af_flags[afi][safi],
1961 PEER_FLAG_DEFAULT_ORIGINATE)) {
1962 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1963 return false;
d62a17ae 1964 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1965 return false;
d62a17ae 1966 }
4125bb67 1967
d62a17ae 1968 /* Transparency check. */
1969 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1970 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1971 transparent = 1;
1972 else
1973 transparent = 0;
1974
1975 /* If community is not disabled check the no-export and local. */
40381db7 1976 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1977 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1978 zlog_debug("%s: community filter check fail for %pFX",
1979 __func__, p);
3dc339cd 1980 return false;
d62a17ae 1981 }
3f9c7369 1982
d62a17ae 1983 /* If the attribute has originator-id and it is same as remote
1984 peer's id. */
40381db7
DS
1985 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1986 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1987 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1988 zlog_debug(
8228a9a7
DS
1989 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1990 onlypeer->host, p);
3dc339cd 1991 return false;
d62a17ae 1992 }
3f9c7369 1993
d62a17ae 1994 /* ORF prefix-list filter check */
1995 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1996 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1997 || CHECK_FLAG(peer->af_cap[afi][safi],
1998 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1999 if (peer->orf_plist[afi][safi]) {
2000 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
2001 == PREFIX_DENY) {
2002 if (bgp_debug_update(NULL, p,
2003 subgrp->update_group, 0))
2004 zlog_debug(
8228a9a7
DS
2005 "%s [Update:SEND] %pFX is filtered via ORF",
2006 peer->host, p);
3dc339cd 2007 return false;
d62a17ae 2008 }
2009 }
2010
2011 /* Output filter check. */
40381db7 2012 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 2013 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2014 zlog_debug("%s [Update:SEND] %pFX is filtered",
2015 peer->host, p);
3dc339cd 2016 return false;
d62a17ae 2017 }
3f9c7369 2018
d62a17ae 2019 /* AS path loop check. */
2b31007c
RZ
2020 if (onlypeer && onlypeer->as_path_loop_detection
2021 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 2022 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2023 zlog_debug(
3efd0893 2024 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 2025 onlypeer->host, onlypeer->as);
3dc339cd 2026 return false;
d62a17ae 2027 }
3f9c7369 2028
d62a17ae 2029 /* If we're a CONFED we need to loop check the CONFED ID too */
2030 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 2031 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 2032 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2033 zlog_debug(
3efd0893 2034 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 2035 peer->host, bgp->confed_id);
3dc339cd 2036 return false;
d62a17ae 2037 }
3f9c7369 2038 }
3f9c7369 2039
d62a17ae 2040 /* Route-Reflect check. */
2041 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
2042 reflect = 1;
2043 else
2044 reflect = 0;
2045
2046 /* IBGP reflection check. */
2047 if (reflect && !samepeer_safe) {
2048 /* A route from a Client peer. */
2049 if (CHECK_FLAG(from->af_flags[afi][safi],
2050 PEER_FLAG_REFLECTOR_CLIENT)) {
2051 /* Reflect to all the Non-Client peers and also to the
2052 Client peers other than the originator. Originator
2053 check
2054 is already done. So there is noting to do. */
2055 /* no bgp client-to-client reflection check. */
892fedb6
DA
2056 if (CHECK_FLAG(bgp->flags,
2057 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 2058 if (CHECK_FLAG(peer->af_flags[afi][safi],
2059 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2060 return false;
d62a17ae 2061 } else {
2062 /* A route from a Non-client peer. Reflect to all other
2063 clients. */
2064 if (!CHECK_FLAG(peer->af_flags[afi][safi],
2065 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 2066 return false;
d62a17ae 2067 }
2068 }
3f9c7369 2069
51c3a7de
DA
2070 /* For modify attribute, copy it to temporary structure.
2071 * post_attr comes from BGP conditional advertisements, where
2072 * attributes are already processed by advertise-map route-map,
2073 * and this needs to be saved instead of overwriting from the
2074 * path attributes.
2075 */
2076 if (post_attr)
2077 *attr = *post_attr;
2078 else
2079 *attr = *piattr;
d62a17ae 2080
2081 /* If local-preference is not set. */
2082 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
2083 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
2084 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2085 attr->local_pref = bgp->default_local_pref;
3f9c7369 2086 }
3f9c7369 2087
d62a17ae 2088 /* If originator-id is not set and the route is to be reflected,
2089 set the originator id */
2090 if (reflect
2091 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2092 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2093 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2094 }
3f9c7369 2095
d62a17ae 2096 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2097 */
2098 if (peer->sort == BGP_PEER_EBGP
2099 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2100 if (from != bgp->peer_self && !transparent
2101 && !CHECK_FLAG(peer->af_flags[afi][safi],
2102 PEER_FLAG_MED_UNCHANGED))
2103 attr->flag &=
2104 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2105 }
3f9c7369 2106
d62a17ae 2107 /* Since the nexthop attribute can vary per peer, it is not explicitly
2108 * set
2109 * in announce check, only certain flags and length (or number of
2110 * nexthops
2111 * -- for IPv6/MP_REACH) are set here in order to guide the update
2112 * formation
2113 * code in setting the nexthop(s) on a per peer basis in
2114 * reformat_peer().
2115 * Typically, the source nexthop in the attribute is preserved but in
2116 * the
2117 * scenarios where we know it will always be overwritten, we reset the
2118 * nexthop to "0" in an attempt to achieve better Update packing. An
2119 * example of this is when a prefix from each of 2 IBGP peers needs to
2120 * be
2121 * announced to an EBGP peer (and they have the same attributes barring
2122 * their nexthop).
2123 */
2124 if (reflect)
2125 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2126
2127#define NEXTHOP_IS_V6 \
2128 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2129 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2130 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2131 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2132
2133 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2134 * if
2135 * the peer (group) is configured to receive link-local nexthop
2136 * unchanged
c728d027
DA
2137 * and it is available in the prefix OR we're not reflecting the route,
2138 * link-local nexthop address is valid and
d62a17ae 2139 * the peer (group) to whom we're going to announce is on a shared
2140 * network
2141 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2142 * By checking if nexthop LL address is valid we are sure that
2143 * we do not announce LL address as `::`.
d62a17ae 2144 */
2145 if (NEXTHOP_IS_V6) {
2146 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2147 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2148 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2149 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
2d02e34e 2150 || (!reflect && !transparent
c728d027
DA
2151 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2152 && peer->shared_network
d62a17ae 2153 && (from == bgp->peer_self
2154 || peer->sort == BGP_PEER_EBGP))) {
2155 attr->mp_nexthop_len =
2156 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2157 }
3f9c7369 2158
d62a17ae 2159 /* Clear off link-local nexthop in source, whenever it is not
2160 * needed to
2161 * ensure more prefixes share the same attribute for
2162 * announcement.
2163 */
2164 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2165 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2166 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2167 }
3f9c7369 2168
d62a17ae 2169 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2170 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2171
2172 /* Route map & unsuppress-map apply. */
51c3a7de
DA
2173 if (!post_attr &&
2174 (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2175 struct bgp_path_info rmap_path = {0};
2176 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2177 struct attr dummy_attr = {0};
d62a17ae 2178
e34291b8 2179 /* Fill temp path_info */
9bcb3eef
DS
2180 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2181 pi, peer, attr);
16f7ce2b 2182
d62a17ae 2183 /* don't confuse inbound and outbound setting */
2184 RESET_FLAG(attr->rmap_change_flags);
2185
2186 /*
2187 * The route reflector is not allowed to modify the attributes
2188 * of the reflected IBGP routes unless explicitly allowed.
2189 */
2190 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2191 && !CHECK_FLAG(bgp->flags,
2192 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2193 dummy_attr = *attr;
40381db7 2194 rmap_path.attr = &dummy_attr;
d62a17ae 2195 }
3f9c7369 2196
d62a17ae 2197 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2198
4056a5f6 2199 if (bgp_path_suppressed(pi))
d62a17ae 2200 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2201 &rmap_path);
d62a17ae 2202 else
2203 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2204 &rmap_path);
d62a17ae 2205
2206 peer->rmap_type = 0;
2207
2208 if (ret == RMAP_DENYMATCH) {
778048bf 2209 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7 2210 zlog_debug(
02494580
DA
2211 "%s [Update:SEND] %pFX is filtered by route-map '%s'",
2212 peer->host, p,
2213 ROUTE_MAP_OUT_NAME(filter));
778048bf 2214
686826e9 2215 bgp_attr_flush(&dummy_attr);
3dc339cd 2216 return false;
d62a17ae 2217 }
3f9c7369 2218 }
3f9c7369 2219
9dac9fc8
DA
2220 /* RFC 8212 to prevent route leaks.
2221 * This specification intends to improve this situation by requiring the
2222 * explicit configuration of both BGP Import and Export Policies for any
2223 * External BGP (EBGP) session such as customers, peers, or
2224 * confederation boundaries for all enabled address families. Through
2225 * codification of the aforementioned requirement, operators will
2226 * benefit from consistent behavior across different BGP
2227 * implementations.
2228 */
1d3fdccf 2229 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
b17826b7
DS
2230 if (!bgp_outbound_policy_exists(peer, filter)) {
2231 if (monotime_since(&bgp->ebgprequirespolicywarning,
2232 NULL) > FIFTEENMINUTE2USEC ||
2233 bgp->ebgprequirespolicywarning.tv_sec == 0) {
2234 zlog_warn(
2235 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
2236 monotime(&bgp->ebgprequirespolicywarning);
2237 }
3dc339cd 2238 return false;
b17826b7 2239 }
9dac9fc8 2240
fb29348a
DA
2241 /* draft-ietf-idr-deprecate-as-set-confed-set
2242 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2243 * Eventually, This document (if approved) updates RFC 4271
2244 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2245 * and obsoletes RFC 6472.
2246 */
7f972cd8 2247 if (peer->bgp->reject_as_sets)
fb29348a 2248 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2249 return false;
fb29348a 2250
33d022bc
DA
2251 /* Codification of AS 0 Processing */
2252 if (aspath_check_as_zero(attr->aspath))
e2369003 2253 return false;
33d022bc 2254
637e5ba4 2255 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2256 if (peer->sort == BGP_PEER_IBGP
2257 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2258 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2259 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2260 } else {
2261 bgp_attr_add_gshut_community(attr);
2262 }
2263 }
2264
1479ed2f
DA
2265 /* A BGP speaker that has advertised the "Long-lived Graceful Restart
2266 * Capability" to a neighbor MUST perform the following upon receiving
2267 * a route from that neighbor with the "LLGR_STALE" community, or upon
2268 * attaching the "LLGR_STALE" community itself per Section 4.2:
2269 *
2270 * The route SHOULD NOT be advertised to any neighbor from which the
2271 * Long-lived Graceful Restart Capability has not been received.
2272 */
2273 if (attr->community &&
2274 community_include(attr->community, COMMUNITY_LLGR_STALE) &&
2275 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_RCV) &&
2276 !CHECK_FLAG(peer->cap, PEER_CAP_LLGR_ADV))
2277 return false;
2278
d62a17ae 2279 /* After route-map has been applied, we check to see if the nexthop to
2280 * be carried in the attribute (that is used for the announcement) can
2281 * be cleared off or not. We do this in all cases where we would be
2282 * setting the nexthop to "ourselves". For IPv6, we only need to
2283 * consider
2284 * the global nexthop here; the link-local nexthop would have been
2285 * cleared
2286 * already, and if not, it is required by the update formation code.
2287 * Also see earlier comments in this function.
2288 */
2289 /*
2290 * If route-map has performed some operation on the nexthop or the peer
2291 * configuration says to pass it unchanged, we cannot reset the nexthop
2292 * here, so only attempt to do it if these aren't true. Note that the
2293 * route-map handler itself might have cleared the nexthop, if for
2294 * example,
2295 * it is configured as 'peer-address'.
2296 */
2297 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2298 piattr->rmap_change_flags)
d62a17ae 2299 && !transparent
2300 && !CHECK_FLAG(peer->af_flags[afi][safi],
2301 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2302 /* We can reset the nexthop, if setting (or forcing) it to
2303 * 'self' */
2304 if (CHECK_FLAG(peer->af_flags[afi][safi],
2305 PEER_FLAG_NEXTHOP_SELF)
2306 || CHECK_FLAG(peer->af_flags[afi][safi],
2307 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2308 if (!reflect
2309 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2310 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2311 subgroup_announce_reset_nhop(
2312 (peer_cap_enhe(peer, afi, safi)
2313 ? AF_INET6
2314 : p->family),
2315 attr);
7b651a32 2316 nh_reset = true;
2317 }
d62a17ae 2318 } else if (peer->sort == BGP_PEER_EBGP) {
2319 /* Can also reset the nexthop if announcing to EBGP, but
2320 * only if
2321 * no peer in the subgroup is on a shared subnet.
2322 * Note: 3rd party nexthop currently implemented for
2323 * IPv4 only.
2324 */
737af885
BS
2325 if ((p->family == AF_INET) &&
2326 (!bgp_subgrp_multiaccess_check_v4(
2327 piattr->nexthop,
7b651a32 2328 subgrp, from))) {
d62a17ae 2329 subgroup_announce_reset_nhop(
2330 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2331 ? AF_INET6
2332 : p->family),
737af885 2333 attr);
7b651a32 2334 nh_reset = true;
2335 }
737af885
BS
2336
2337 if ((p->family == AF_INET6) &&
2338 (!bgp_subgrp_multiaccess_check_v6(
2339 piattr->mp_nexthop_global,
7b651a32 2340 subgrp, from))) {
737af885
BS
2341 subgroup_announce_reset_nhop(
2342 (peer_cap_enhe(peer, afi, safi)
2343 ? AF_INET6
2344 : p->family),
2345 attr);
7b651a32 2346 nh_reset = true;
2347 }
737af885
BS
2348
2349
2350
40381db7 2351 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2352 /*
2353 * This flag is used for leaked vpn-vrf routes
2354 */
2355 int family = p->family;
2356
2357 if (peer_cap_enhe(peer, afi, safi))
2358 family = AF_INET6;
2359
2360 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2361 zlog_debug(
1defdda8 2362 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2363 __func__, family2str(family));
2364 subgroup_announce_reset_nhop(family, attr);
7b651a32 2365 nh_reset = true;
d62a17ae 2366 }
63696f1d 2367 }
960035b2 2368
63696f1d 2369 /* If IPv6/MP and nexthop does not have any override and happens
2370 * to
2371 * be a link-local address, reset it so that we don't pass along
2372 * the
2373 * source's link-local IPv6 address to recipients who may not be
2374 * on
2375 * the same interface.
2376 */
2377 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2378 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2379 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2380 nh_reset = true;
2381 }
d62a17ae 2382 }
3f9c7369 2383
7b651a32 2384 /*
2385 * When the next hop is set to ourselves, if all multipaths have
2386 * link-bandwidth announce the cumulative bandwidth as that makes
2387 * the most sense. However, don't modify if the link-bandwidth has
2388 * been explicitly set by user policy.
2389 */
2390 if (nh_reset &&
f7e1c681 2391 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2392 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2393 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
b53e67a3
DA
2394 bgp_attr_set_ecommunity(
2395 attr,
2396 ecommunity_replace_linkbw(
2397 bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
2398 CHECK_FLAG(
2399 peer->flags,
2400 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
7b651a32 2401
3dc339cd 2402 return true;
3f9c7369
DS
2403}
2404
cc9f21da 2405static void bgp_route_select_timer_expire(struct thread *thread)
f009ff26 2406{
2407 struct afi_safi_info *info;
2408 afi_t afi;
2409 safi_t safi;
2410 struct bgp *bgp;
2411
2412 info = THREAD_ARG(thread);
2413 afi = info->afi;
2414 safi = info->safi;
2415 bgp = info->bgp;
2416
2417 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2418 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2419 safi);
f009ff26 2420
2421 bgp->gr_info[afi][safi].t_route_select = NULL;
2422
2423 XFREE(MTYPE_TMP, info);
2424
2425 /* Best path selection */
cc9f21da 2426 bgp_best_path_select_defer(bgp, afi, safi);
f009ff26 2427}
2428
9bcb3eef 2429void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2430 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2431 struct bgp_path_info_pair *result, afi_t afi,
2432 safi_t safi)
2433{
2434 struct bgp_path_info *new_select;
2435 struct bgp_path_info *old_select;
40381db7
DS
2436 struct bgp_path_info *pi;
2437 struct bgp_path_info *pi1;
2438 struct bgp_path_info *pi2;
2439 struct bgp_path_info *nextpi = NULL;
d62a17ae 2440 int paths_eq, do_mpath, debug;
2441 struct list mp_list;
2442 char pfx_buf[PREFIX2STR_BUFFER];
2443 char path_buf[PATH_ADDPATH_STR_BUFFER];
2444
2445 bgp_mp_list_init(&mp_list);
2446 do_mpath =
2447 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2448
9bcb3eef 2449 debug = bgp_debug_bestpath(dest);
d62a17ae 2450
2451 if (debug)
9bcb3eef 2452 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2453
9bcb3eef 2454 dest->reason = bgp_path_selection_none;
d62a17ae 2455 /* bgp deterministic-med */
2456 new_select = NULL;
892fedb6 2457 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2458
1defdda8 2459 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2460 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2461 pi1 = pi1->next)
9bcb3eef 2462 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2463 BGP_PATH_DMED_SELECTED);
d62a17ae 2464
9bcb3eef 2465 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2466 pi1 = pi1->next) {
40381db7 2467 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2468 continue;
40381db7 2469 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2470 continue;
ea8b2282 2471 if (pi1->peer != bgp->peer_self)
feb17238 2472 if (!peer_established(pi1->peer))
d62a17ae 2473 continue;
2474
40381db7
DS
2475 new_select = pi1;
2476 if (pi1->next) {
2477 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2478 if (CHECK_FLAG(pi2->flags,
1defdda8 2479 BGP_PATH_DMED_CHECK))
d62a17ae 2480 continue;
40381db7 2481 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2482 continue;
ea8b2282 2483 if (pi2->peer != bgp->peer_self
d62a17ae 2484 && !CHECK_FLAG(
ea8b2282
DS
2485 pi2->peer->sflags,
2486 PEER_STATUS_NSF_WAIT))
40381db7 2487 if (pi2->peer->status
d62a17ae 2488 != Established)
2489 continue;
2490
121e245d
DS
2491 if (!aspath_cmp_left(pi1->attr->aspath,
2492 pi2->attr->aspath)
2493 && !aspath_cmp_left_confed(
40381db7 2494 pi1->attr->aspath,
121e245d
DS
2495 pi2->attr->aspath))
2496 continue;
d62a17ae 2497
121e245d
DS
2498 if (bgp_path_info_cmp(
2499 bgp, pi2, new_select,
2500 &paths_eq, mpath_cfg, debug,
fdf81fa0 2501 pfx_buf, afi, safi,
9bcb3eef 2502 &dest->reason)) {
121e245d 2503 bgp_path_info_unset_flag(
9bcb3eef 2504 dest, new_select,
121e245d
DS
2505 BGP_PATH_DMED_SELECTED);
2506 new_select = pi2;
d62a17ae 2507 }
121e245d
DS
2508
2509 bgp_path_info_set_flag(
9bcb3eef 2510 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2511 }
2512 }
9bcb3eef 2513 bgp_path_info_set_flag(dest, new_select,
18ee8310 2514 BGP_PATH_DMED_CHECK);
9bcb3eef 2515 bgp_path_info_set_flag(dest, new_select,
18ee8310 2516 BGP_PATH_DMED_SELECTED);
d62a17ae 2517
2518 if (debug) {
18ee8310 2519 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2520 new_select, path_buf, sizeof(path_buf));
8228a9a7 2521 zlog_debug(
4378495a
DS
2522 "%pBD(%s): %s is the bestpath from AS %u",
2523 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2524 aspath_get_first_as(
2525 new_select->attr->aspath));
d62a17ae 2526 }
2527 }
2528 }
96450faf 2529
d62a17ae 2530 /* Check old selected route and new selected route. */
2531 old_select = NULL;
2532 new_select = NULL;
9bcb3eef 2533 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2534 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2535 enum bgp_path_selection_reason reason;
2536
40381db7
DS
2537 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2538 old_select = pi;
d62a17ae 2539
40381db7 2540 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2541 /* reap REMOVED routes, if needs be
2542 * selected route must stay for a while longer though
2543 */
40381db7
DS
2544 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2545 && (pi != old_select))
9bcb3eef 2546 bgp_path_info_reap(dest, pi);
d62a17ae 2547
ddb5b488 2548 if (debug)
40381db7
DS
2549 zlog_debug("%s: pi %p in holddown", __func__,
2550 pi);
ddb5b488 2551
d62a17ae 2552 continue;
2553 }
96450faf 2554
40381db7
DS
2555 if (pi->peer && pi->peer != bgp->peer_self
2556 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2557 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2558
2559 if (debug)
2560 zlog_debug(
40381db7
DS
2561 "%s: pi %p non self peer %s not estab state",
2562 __func__, pi, pi->peer->host);
ddb5b488 2563
d62a17ae 2564 continue;
ddb5b488 2565 }
9fbdd100 2566
892fedb6 2567 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2568 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2569 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2570 if (debug)
40381db7 2571 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2572 continue;
2573 }
9fbdd100 2574
9bcb3eef 2575 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2576
9bcb3eef 2577 reason = dest->reason;
40381db7 2578 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2579 debug, pfx_buf, afi, safi,
2580 &dest->reason)) {
19ea4cec
DS
2581 if (new_select == NULL &&
2582 reason != bgp_path_selection_none)
9bcb3eef 2583 dest->reason = reason;
40381db7 2584 new_select = pi;
d62a17ae 2585 }
2586 }
718e3744 2587
d62a17ae 2588 /* Now that we know which path is the bestpath see if any of the other
2589 * paths
2590 * qualify as multipaths
2591 */
2592 if (debug) {
2593 if (new_select)
7533cad7
QY
2594 bgp_path_info_path_with_addpath_rx_str(
2595 new_select, path_buf, sizeof(path_buf));
d62a17ae 2596 else
772270f3 2597 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2598 zlog_debug(
4378495a
DS
2599 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2600 dest, bgp->name_pretty, path_buf,
d62a17ae 2601 old_select ? old_select->peer->host : "NONE");
96450faf 2602 }
9fbdd100 2603
d62a17ae 2604 if (do_mpath && new_select) {
9bcb3eef 2605 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2606 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2607
2608 if (debug)
18ee8310 2609 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2610 pi, path_buf, sizeof(path_buf));
d62a17ae 2611
40381db7 2612 if (pi == new_select) {
d62a17ae 2613 if (debug)
2614 zlog_debug(
4378495a
DS
2615 "%pBD(%s): %s is the bestpath, add to the multipath list",
2616 dest, bgp->name_pretty,
2617 path_buf);
40381db7 2618 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2619 continue;
2620 }
2621
40381db7 2622 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2623 continue;
2624
40381db7
DS
2625 if (pi->peer && pi->peer != bgp->peer_self
2626 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2627 PEER_STATUS_NSF_WAIT))
feb17238 2628 if (!peer_established(pi->peer))
d62a17ae 2629 continue;
2630
40381db7 2631 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2632 if (debug)
2633 zlog_debug(
8228a9a7
DS
2634 "%pBD: %s has the same nexthop as the bestpath, skip it",
2635 dest, path_buf);
d62a17ae 2636 continue;
2637 }
2638
40381db7 2639 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2640 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2641 &dest->reason);
d62a17ae 2642
2643 if (paths_eq) {
2644 if (debug)
2645 zlog_debug(
8228a9a7
DS
2646 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2647 dest, path_buf);
40381db7 2648 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2649 }
2650 }
2651 }
fee0f4c6 2652
4378495a 2653 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2654 mpath_cfg);
2655 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2656 bgp_mp_list_clear(&mp_list);
96450faf 2657
9bcb3eef 2658 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2659
d62a17ae 2660 result->old = old_select;
2661 result->new = new_select;
96450faf 2662
d62a17ae 2663 return;
fee0f4c6 2664}
2665
3f9c7369
DS
2666/*
2667 * A new route/change in bestpath of an existing route. Evaluate the path
2668 * for advertisement to the subgroup.
2669 */
3dc339cd
DA
2670void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2671 struct bgp_path_info *selected,
9bcb3eef 2672 struct bgp_dest *dest,
3dc339cd 2673 uint32_t addpath_tx_id)
d62a17ae 2674{
b54892e0 2675 const struct prefix *p;
d62a17ae 2676 struct peer *onlypeer;
2677 struct attr attr;
2678 afi_t afi;
2679 safi_t safi;
a77e2f4b
S
2680 struct bgp *bgp;
2681 bool advertise;
adbac85e 2682
9bcb3eef 2683 p = bgp_dest_get_prefix(dest);
d62a17ae 2684 afi = SUBGRP_AFI(subgrp);
2685 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2686 bgp = SUBGRP_INST(subgrp);
d62a17ae 2687 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2688 : NULL);
2689
2dbe669b
DA
2690 if (BGP_DEBUG(update, UPDATE_OUT))
2691 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2692
d62a17ae 2693 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2694 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2695 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2696 return;
d62a17ae 2697
2698 memset(&attr, 0, sizeof(struct attr));
2699 /* It's initialized in bgp_announce_check() */
2700
a77e2f4b
S
2701 /* Announcement to the subgroup. If the route is filtered withdraw it.
2702 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2703 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2704 * route
d62a17ae 2705 */
a77e2f4b
S
2706 advertise = bgp_check_advertise(bgp, dest);
2707
d62a17ae 2708 if (selected) {
7f7940e6 2709 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
51c3a7de 2710 NULL)) {
a77e2f4b
S
2711 /* Route is selected, if the route is already installed
2712 * in FIB, then it is advertised
2713 */
be785e35
DS
2714 if (advertise) {
2715 if (!bgp_check_withdrawal(bgp, dest))
2716 bgp_adj_out_set_subgroup(
2717 dest, subgrp, &attr, selected);
2718 else
2719 bgp_adj_out_unset_subgroup(
2720 dest, subgrp, 1, addpath_tx_id);
2721 }
a77e2f4b 2722 } else
9bcb3eef 2723 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2724 addpath_tx_id);
d62a17ae 2725 }
2726
2727 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2728 else {
9bcb3eef 2729 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2730 }
200df115 2731}
fee0f4c6 2732
3064bf43 2733/*
e1072051 2734 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2735 * This is called at the end of route processing.
3064bf43 2736 */
9bcb3eef 2737void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2738{
40381db7 2739 struct bgp_path_info *pi;
3064bf43 2740
9bcb3eef 2741 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2742 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2743 continue;
40381db7
DS
2744 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2745 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2746 }
3064bf43 2747}
2748
2749/*
2750 * Has the route changed from the RIB's perspective? This is invoked only
2751 * if the route selection returns the same best route as earlier - to
2752 * determine if we need to update zebra or not.
2753 */
9bcb3eef 2754bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2755{
4b7e6066 2756 struct bgp_path_info *mpinfo;
d62a17ae 2757
2bb9eff4
DS
2758 /* If this is multipath, check all selected paths for any nexthop
2759 * change or attribute change. Some attribute changes (e.g., community)
2760 * aren't of relevance to the RIB, but we'll update zebra to ensure
2761 * we handle the case of BGP nexthop change. This is the behavior
2762 * when the best path has an attribute change anyway.
d62a17ae 2763 */
1defdda8 2764 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2765 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2766 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2767 return true;
d62a17ae 2768
2bb9eff4
DS
2769 /*
2770 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2771 */
18ee8310
DS
2772 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2773 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2774 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2775 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2776 return true;
d62a17ae 2777 }
3064bf43 2778
d62a17ae 2779 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2780 return false;
3064bf43 2781}
2782
d62a17ae 2783struct bgp_process_queue {
2784 struct bgp *bgp;
9bcb3eef 2785 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2786#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2787 unsigned int flags;
2788 unsigned int queued;
200df115 2789};
2790
3b0c17e1 2791static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2792 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2793 struct bgp_path_info *new_select,
2794 struct bgp_path_info *old_select)
2795{
9bcb3eef 2796 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2797
2798 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2799 return;
2800
2801 if (advertise_type5_routes(bgp, afi) && new_select
2802 && is_route_injectable_into_evpn(new_select)) {
2803
2804 /* apply the route-map */
2805 if (bgp->adv_cmd_rmap[afi][safi].map) {
2806 route_map_result_t ret;
2807 struct bgp_path_info rmap_path;
2808 struct bgp_path_info_extra rmap_path_extra;
2809 struct attr dummy_attr;
2810
2811 dummy_attr = *new_select->attr;
2812
2813 /* Fill temp path_info */
9bcb3eef 2814 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2815 new_select, new_select->peer,
2816 &dummy_attr);
2817
2818 RESET_FLAG(dummy_attr.rmap_change_flags);
2819
2820 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2821 p, &rmap_path);
3b0c17e1 2822
2823 if (ret == RMAP_DENYMATCH) {
2824 bgp_attr_flush(&dummy_attr);
2825 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2826 safi);
2827 } else
2828 bgp_evpn_advertise_type5_route(
2829 bgp, p, &dummy_attr, afi, safi);
2830 } else {
2831 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2832 afi, safi);
2833 }
2834 } else if (advertise_type5_routes(bgp, afi) && old_select
2835 && is_route_injectable_into_evpn(old_select))
2836 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2837}
2838
bb2ca692
MS
2839/*
2840 * Utility to determine whether a particular path_info should use
2841 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2842 * in a path where we basically _know_ this is a BGP-LU route.
2843 */
2844static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2845{
2846 /* Certain types get imp null; so do paths where the nexthop is
2847 * not labeled.
2848 */
2849 if (new_select->sub_type == BGP_ROUTE_STATIC
2850 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2851 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2852 return true;
2853 else if (new_select->extra == NULL ||
2854 !bgp_is_valid_label(&new_select->extra->label[0]))
2855 /* TODO -- should be configurable? */
2856 return true;
2857 else
2858 return false;
2859}
2860
3103e8d2
DS
2861/*
2862 * old_select = The old best path
2863 * new_select = the new best path
2864 *
2865 * if (!old_select && new_select)
2866 * We are sending new information on.
2867 *
2868 * if (old_select && new_select) {
2869 * if (new_select != old_select)
2870 * We have a new best path send a change
2871 * else
2872 * We've received a update with new attributes that needs
2873 * to be passed on.
2874 * }
2875 *
2876 * if (old_select && !new_select)
2877 * We have no eligible route that we can announce or the rn
2878 * is being removed.
2879 */
9bcb3eef 2880static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2881 afi_t afi, safi_t safi)
d62a17ae 2882{
4b7e6066
DS
2883 struct bgp_path_info *new_select;
2884 struct bgp_path_info *old_select;
2885 struct bgp_path_info_pair old_and_new;
ddb5b488 2886 int debug = 0;
d62a17ae 2887
892fedb6 2888 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2889 if (dest)
2890 debug = bgp_debug_bestpath(dest);
b54892e0 2891 if (debug)
f4c713ae 2892 zlog_debug(
56ca3b5b 2893 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2894 __func__, dest);
f4c713ae
LB
2895 return;
2896 }
d62a17ae 2897 /* Is it end of initial update? (after startup) */
9bcb3eef 2898 if (!dest) {
e36f61b5
DS
2899 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2900 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2901
2902 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2903 FOREACH_AFI_SAFI (afi, safi) {
2904 if (bgp_fibupd_safi(safi))
2905 bgp_zebra_announce_table(bgp, afi, safi);
2906 }
d62a17ae 2907 bgp->main_peers_update_hold = 0;
2908
2909 bgp_start_routeadv(bgp);
aac24838 2910 return;
d62a17ae 2911 }
cb1faec9 2912
9bcb3eef 2913 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2914
9bcb3eef 2915 debug = bgp_debug_bestpath(dest);
b54892e0 2916 if (debug)
4378495a
DS
2917 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2918 dest, bgp->name_pretty, afi2str(afi),
2919 safi2str(safi));
ddb5b488 2920
f009ff26 2921 /* The best path calculation for the route is deferred if
2922 * BGP_NODE_SELECT_DEFER is set
2923 */
9bcb3eef 2924 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2925 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2926 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2927 return;
2928 }
2929
d62a17ae 2930 /* Best path selection. */
9bcb3eef 2931 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2932 afi, safi);
2933 old_select = old_and_new.old;
2934 new_select = old_and_new.new;
2935
2936 /* Do we need to allocate or free labels?
2937 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2938 * necessary to do this upon changes to best path. Exceptions:
2939 * - label index has changed -> recalculate resulting label
2940 * - path_info sub_type changed -> switch to/from implicit-null
2941 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2942 */
318cac96 2943 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2944 if (new_select) {
2945 if (!old_select
2946 || bgp_label_index_differs(new_select, old_select)
57592a53 2947 || new_select->sub_type != old_select->sub_type
9bcb3eef 2948 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2949 /* Enforced penultimate hop popping:
2950 * implicit-null for local routes, aggregate
2951 * and redistributed routes
2952 */
bb2ca692 2953 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2954 if (CHECK_FLAG(
9bcb3eef 2955 dest->flags,
992dd67e
PR
2956 BGP_NODE_REGISTERED_FOR_LABEL)
2957 || CHECK_FLAG(
2958 dest->flags,
2959 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2960 bgp_unregister_for_label(dest);
70e98a7f 2961 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2962 &dest->local_label);
2963 bgp_set_valid_label(&dest->local_label);
d62a17ae 2964 } else
9bcb3eef
DS
2965 bgp_register_for_label(dest,
2966 new_select);
d62a17ae 2967 }
9bcb3eef 2968 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2969 BGP_NODE_REGISTERED_FOR_LABEL)
2970 || CHECK_FLAG(dest->flags,
2971 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2972 bgp_unregister_for_label(dest);
318cac96 2973 }
992dd67e
PR
2974 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2975 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2976 bgp_unregister_for_label(dest);
d62a17ae 2977 }
cd1964ff 2978
b54892e0 2979 if (debug)
ddb5b488 2980 zlog_debug(
4378495a
DS
2981 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2982 __func__, dest, bgp->name_pretty, afi2str(afi),
2983 safi2str(safi), old_select, new_select);
ddb5b488 2984
d62a17ae 2985 /* If best route remains the same and this is not due to user-initiated
2986 * clear, see exactly what needs to be done.
2987 */
d62a17ae 2988 if (old_select && old_select == new_select
9bcb3eef 2989 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2990 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2991 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2992 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2993#ifdef ENABLE_BGP_VNC
d62a17ae 2994 vnc_import_bgp_add_route(bgp, p, old_select);
2995 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2996#endif
bb744275 2997 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2998 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2999
be785e35
DS
3000 if (BGP_SUPPRESS_FIB_ENABLED(bgp)
3001 && new_select->sub_type == BGP_ROUTE_NORMAL)
3002 SET_FLAG(dest->flags,
3003 BGP_NODE_FIB_INSTALL_PENDING);
3004
ddb5b488
PZ
3005 if (new_select->type == ZEBRA_ROUTE_BGP
3006 && (new_select->sub_type == BGP_ROUTE_NORMAL
3007 || new_select->sub_type
3008 == BGP_ROUTE_IMPORTED))
3009
9bcb3eef 3010 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
3011 bgp, afi, safi);
3012 }
d62a17ae 3013 }
d62a17ae 3014
3015 /* If there is a change of interest to peers, reannounce the
3016 * route. */
1defdda8 3017 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 3018 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
3019 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
3020 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3021
3022 /* unicast routes must also be annouced to
3023 * labeled-unicast update-groups */
3024 if (safi == SAFI_UNICAST)
3025 group_announce_route(bgp, afi,
9bcb3eef 3026 SAFI_LABELED_UNICAST, dest,
d62a17ae 3027 new_select);
3028
1defdda8 3029 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 3030 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 3031 }
fee0f4c6 3032
3b0c17e1 3033 /* advertise/withdraw type-5 routes */
3034 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
3035 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
3036 bgp_process_evpn_route_injection(
9bcb3eef 3037 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 3038
b1875e65 3039 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
3040 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
3041 bgp_zebra_clear_route_change_flags(dest);
3042 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3043 return;
d62a17ae 3044 }
8ad7271d 3045
d62a17ae 3046 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
3047 */
9bcb3eef 3048 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 3049
3050 /* bestpath has changed; bump version */
3051 if (old_select || new_select) {
9bcb3eef 3052 bgp_bump_version(dest);
d62a17ae 3053
3054 if (!bgp->t_rmap_def_originate_eval) {
3055 bgp_lock(bgp);
3056 thread_add_timer(
3057 bm->master,
3058 update_group_refresh_default_originate_route_map,
3059 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
3060 &bgp->t_rmap_def_originate_eval);
3061 }
3062 }
3f9c7369 3063
d62a17ae 3064 if (old_select)
9bcb3eef 3065 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 3066 if (new_select) {
ddb5b488
PZ
3067 if (debug)
3068 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
3069 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
3070 bgp_path_info_unset_flag(dest, new_select,
3071 BGP_PATH_ATTR_CHANGED);
1defdda8 3072 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 3073 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 3074 }
338b3424 3075
49e5a4a0 3076#ifdef ENABLE_BGP_VNC
d62a17ae 3077 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
3078 if (old_select != new_select) {
3079 if (old_select) {
3080 vnc_import_bgp_exterior_del_route(bgp, p,
3081 old_select);
3082 vnc_import_bgp_del_route(bgp, p, old_select);
3083 }
3084 if (new_select) {
3085 vnc_import_bgp_exterior_add_route(bgp, p,
3086 new_select);
3087 vnc_import_bgp_add_route(bgp, p, new_select);
3088 }
3089 }
3090 }
65efcfce
LB
3091#endif
3092
9bcb3eef 3093 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 3094
3095 /* unicast routes must also be annouced to labeled-unicast update-groups
3096 */
3097 if (safi == SAFI_UNICAST)
9bcb3eef 3098 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 3099 new_select);
3100
3101 /* FIB update. */
3102 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
3103 && !bgp_option_check(BGP_OPT_NO_FIB)) {
be785e35 3104
d62a17ae 3105 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
3106 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 3107 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
3108 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
3109
be785e35
DS
3110 if (BGP_SUPPRESS_FIB_ENABLED(bgp))
3111 SET_FLAG(dest->flags,
3112 BGP_NODE_FIB_INSTALL_PENDING);
3113
2b659f33
MK
3114 /* if this is an evpn imported type-5 prefix,
3115 * we need to withdraw the route first to clear
3116 * the nh neigh and the RMAC entry.
3117 */
3118 if (old_select &&
3119 is_route_parent_evpn(old_select))
3120 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 3121
9bcb3eef 3122 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 3123 } else {
d62a17ae 3124 /* Withdraw the route from the kernel. */
3125 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
3126 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
3127 || old_select->sub_type == BGP_ROUTE_AGGREGATE
3128 || old_select->sub_type == BGP_ROUTE_IMPORTED))
3129
568e10ca 3130 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3131 }
718e3744 3132 }
3064bf43 3133
9bcb3eef 3134 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3135 old_select);
5424b7ba 3136
d62a17ae 3137 /* Clear any route change flags. */
9bcb3eef 3138 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3139
18ee8310 3140 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3141 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3142 bgp_path_info_reap(dest, old_select);
d62a17ae 3143
9bcb3eef 3144 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3145 return;
718e3744 3146}
3147
f009ff26 3148/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3149int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3150{
9bcb3eef 3151 struct bgp_dest *dest;
f009ff26 3152 int cnt = 0;
3153 struct afi_safi_info *thread_info;
f009ff26 3154
56c226e7
DS
3155 if (bgp->gr_info[afi][safi].t_route_select) {
3156 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3157
3158 thread_info = THREAD_ARG(t);
3159 XFREE(MTYPE_TMP, thread_info);
f009ff26 3160 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3161 }
f009ff26 3162
3163 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3164 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3165 get_afi_safi_str(afi, safi, false),
26742171 3166 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3167 }
3168
3169 /* Process the route list */
6338d242
DS
3170 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3171 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3172 dest = bgp_route_next(dest)) {
3173 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3174 continue;
3175
3176 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3177 bgp->gr_info[afi][safi].gr_deferred--;
3178 bgp_process_main_one(bgp, dest, afi, safi);
3179 cnt++;
3180 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3181 bgp_dest_unlock_node(dest);
3182 break;
f009ff26 3183 }
f009ff26 3184 }
3185
9e3b51a7 3186 /* Send EOR message when all routes are processed */
6338d242 3187 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3188 bgp_send_delayed_eor(bgp);
8c48b3b6 3189 /* Send route processing complete message to RIB */
3190 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3191 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3192 return 0;
9e3b51a7 3193 }
f009ff26 3194
3195 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3196
3197 thread_info->afi = afi;
3198 thread_info->safi = safi;
3199 thread_info->bgp = bgp;
3200
3201 /* If there are more routes to be processed, start the
3202 * selection timer
3203 */
3204 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3205 BGP_ROUTE_SELECT_DELAY,
3206 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3207 return 0;
3208}
3209
aac24838 3210static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3211{
aac24838
JB
3212 struct bgp_process_queue *pqnode = data;
3213 struct bgp *bgp = pqnode->bgp;
d62a17ae 3214 struct bgp_table *table;
9bcb3eef 3215 struct bgp_dest *dest;
aac24838
JB
3216
3217 /* eoiu marker */
3218 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3219 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3220 /* should always have dedicated wq call */
3221 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3222 return WQ_SUCCESS;
3223 }
3224
ac021f40 3225 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3226 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3227 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3228 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3229 table = bgp_dest_table(dest);
3230 /* note, new DESTs may be added as part of processing */
3231 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3232
9bcb3eef 3233 bgp_dest_unlock_node(dest);
d62a17ae 3234 bgp_table_unlock(table);
3235 }
aac24838
JB
3236
3237 return WQ_SUCCESS;
3238}
3239
3240static void bgp_processq_del(struct work_queue *wq, void *data)
3241{
3242 struct bgp_process_queue *pqnode = data;
3243
3244 bgp_unlock(pqnode->bgp);
3245
3246 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3247}
3248
b6c386bb 3249void bgp_process_queue_init(struct bgp *bgp)
200df115 3250{
b6c386bb
DS
3251 if (!bgp->process_queue) {
3252 char name[BUFSIZ];
3253
3254 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3255 bgp->process_queue = work_queue_new(bm->master, name);
3256 }
3257
3258 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3259 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3260 bgp->process_queue->spec.max_retries = 0;
3261 bgp->process_queue->spec.hold = 50;
d62a17ae 3262 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3263 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3264}
3265
cfe8d15a 3266static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3267{
3268 struct bgp_process_queue *pqnode;
3269
a4d82a8a
PZ
3270 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3271 sizeof(struct bgp_process_queue));
aac24838
JB
3272
3273 /* unlocked in bgp_processq_del */
3274 pqnode->bgp = bgp_lock(bgp);
3275 STAILQ_INIT(&pqnode->pqueue);
3276
aac24838
JB
3277 return pqnode;
3278}
3279
9bcb3eef 3280void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3281{
aac24838 3282#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3283 struct work_queue *wq = bgp->process_queue;
d62a17ae 3284 struct bgp_process_queue *pqnode;
cfe8d15a 3285 int pqnode_reuse = 0;
495f0b13 3286
d62a17ae 3287 /* already scheduled for processing? */
9bcb3eef 3288 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3289 return;
2e02b9b2 3290
f009ff26 3291 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3292 * the workqueue
3293 */
9bcb3eef 3294 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3295 if (BGP_DEBUG(update, UPDATE_OUT))
3296 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3297 dest);
f009ff26 3298 return;
3299 }
3300
46aeabed
LS
3301 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3302 if (BGP_DEBUG(update, UPDATE_OUT))
3303 zlog_debug(
3304 "Soft reconfigure table in progress for route %p",
3305 dest);
3306 return;
3307 }
3308
aac24838 3309 if (wq == NULL)
d62a17ae 3310 return;
3311
aac24838 3312 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3313 limit only if is from the same BGP view and it's not an EOIU marker
3314 */
aac24838
JB
3315 if (work_queue_item_count(wq)) {
3316 struct work_queue_item *item = work_queue_last_item(wq);
3317 pqnode = item->data;
228da428 3318
a4d82a8a
PZ
3319 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3320 || pqnode->bgp != bgp
3321 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3322 pqnode = bgp_processq_alloc(bgp);
3323 else
3324 pqnode_reuse = 1;
aac24838 3325 } else
cfe8d15a 3326 pqnode = bgp_processq_alloc(bgp);
aac24838 3327 /* all unlocked in bgp_process_wq */
9bcb3eef 3328 bgp_table_lock(bgp_dest_table(dest));
aac24838 3329
9bcb3eef
DS
3330 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3331 bgp_dest_lock_node(dest);
aac24838 3332
60466a63 3333 /* can't be enqueued twice */
9bcb3eef
DS
3334 assert(STAILQ_NEXT(dest, pq) == NULL);
3335 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3336 pqnode->queued++;
3337
cfe8d15a
LB
3338 if (!pqnode_reuse)
3339 work_queue_add(wq, pqnode);
3340
d62a17ae 3341 return;
fee0f4c6 3342}
0a486e5f 3343
d62a17ae 3344void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3345{
d62a17ae 3346 struct bgp_process_queue *pqnode;
cb1faec9 3347
b6c386bb 3348 if (bgp->process_queue == NULL)
d62a17ae 3349 return;
2e02b9b2 3350
cfe8d15a 3351 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3352
aac24838 3353 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3354 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3355}
3356
cc9f21da 3357static void bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3358{
d62a17ae 3359 struct peer *peer;
0a486e5f 3360
d62a17ae 3361 peer = THREAD_ARG(thread);
3362 peer->t_pmax_restart = NULL;
0a486e5f 3363
d62a17ae 3364 if (bgp_debug_neighbor_events(peer))
3365 zlog_debug(
3366 "%s Maximum-prefix restart timer expired, restore peering",
3367 peer->host);
0a486e5f 3368
a9bafa95 3369 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3370 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3371}
3372
9cbd06e0
DA
3373static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3374 safi_t safi)
3375{
3376 uint32_t count = 0;
f41b0459 3377 bool filtered = false;
9cbd06e0
DA
3378 struct bgp_dest *dest;
3379 struct bgp_adj_in *ain;
40bb2ccf 3380 struct attr attr = {};
9cbd06e0
DA
3381 struct bgp_table *table = peer->bgp->rib[afi][safi];
3382
3383 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3384 for (ain = dest->adj_in; ain; ain = ain->next) {
3385 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3386
3387 attr = *ain->attr;
9cbd06e0
DA
3388
3389 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3390 == FILTER_DENY)
f41b0459
DA
3391 filtered = true;
3392
3393 if (bgp_input_modifier(
3394 peer, rn_p, &attr, afi, safi,
3395 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3396 NULL, 0, NULL)
3397 == RMAP_DENY)
3398 filtered = true;
3399
3400 if (filtered)
9cbd06e0 3401 count++;
f41b0459 3402
d498917e 3403 bgp_attr_flush(&attr);
9cbd06e0
DA
3404 }
3405 }
3406
3407 return count;
3408}
3409
3dc339cd
DA
3410bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3411 int always)
718e3744 3412{
d62a17ae 3413 iana_afi_t pkt_afi;
5c525538 3414 iana_safi_t pkt_safi;
9cbd06e0
DA
3415 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3416 PEER_FLAG_MAX_PREFIX_FORCE))
3417 ? bgp_filtered_routes_count(peer, afi, safi)
3418 + peer->pcount[afi][safi]
3419 : peer->pcount[afi][safi];
9cabb64b 3420
d62a17ae 3421 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3422 return false;
e0701b79 3423
9cbd06e0 3424 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3425 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3426 PEER_STATUS_PREFIX_LIMIT)
3427 && !always)
3dc339cd 3428 return false;
e0701b79 3429
d62a17ae 3430 zlog_info(
6cde4b45 3431 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3432 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3433 peer->pmax[afi][safi]);
d62a17ae 3434 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3435
3436 if (CHECK_FLAG(peer->af_flags[afi][safi],
3437 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3438 return false;
d62a17ae 3439
3440 /* Convert AFI, SAFI to values for packet. */
3441 pkt_afi = afi_int2iana(afi);
3442 pkt_safi = safi_int2iana(safi);
3443 {
d7c0a89a 3444 uint8_t ndata[7];
d62a17ae 3445
3446 ndata[0] = (pkt_afi >> 8);
3447 ndata[1] = pkt_afi;
3448 ndata[2] = pkt_safi;
3449 ndata[3] = (peer->pmax[afi][safi] >> 24);
3450 ndata[4] = (peer->pmax[afi][safi] >> 16);
3451 ndata[5] = (peer->pmax[afi][safi] >> 8);
3452 ndata[6] = (peer->pmax[afi][safi]);
3453
3454 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3455 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3456 BGP_NOTIFY_CEASE_MAX_PREFIX,
3457 ndata, 7);
3458 }
3459
3460 /* Dynamic peers will just close their connection. */
3461 if (peer_dynamic_neighbor(peer))
3dc339cd 3462 return true;
d62a17ae 3463
3464 /* restart timer start */
3465 if (peer->pmax_restart[afi][safi]) {
3466 peer->v_pmax_restart =
3467 peer->pmax_restart[afi][safi] * 60;
3468
3469 if (bgp_debug_neighbor_events(peer))
3470 zlog_debug(
3471 "%s Maximum-prefix restart timer started for %d secs",
3472 peer->host, peer->v_pmax_restart);
3473
3474 BGP_TIMER_ON(peer->t_pmax_restart,
3475 bgp_maximum_prefix_restart_timer,
3476 peer->v_pmax_restart);
3477 }
3478
3dc339cd 3479 return true;
d62a17ae 3480 } else
3481 UNSET_FLAG(peer->af_sflags[afi][safi],
3482 PEER_STATUS_PREFIX_LIMIT);
3483
b1823b69
DS
3484 if (pcount
3485 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3486 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3487 PEER_STATUS_PREFIX_THRESHOLD)
3488 && !always)
3dc339cd 3489 return false;
d62a17ae 3490
3491 zlog_info(
6cde4b45 3492 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3493 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3494 peer->pmax[afi][safi]);
d62a17ae 3495 SET_FLAG(peer->af_sflags[afi][safi],
3496 PEER_STATUS_PREFIX_THRESHOLD);
3497 } else
3498 UNSET_FLAG(peer->af_sflags[afi][safi],
3499 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3500 return false;
718e3744 3501}
3502
b40d939b 3503/* Unconditionally remove the route from the RIB, without taking
3504 * damping into consideration (eg, because the session went down)
3505 */
9bcb3eef 3506void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3507 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3508{
f009ff26 3509
3510 struct bgp *bgp = NULL;
3511 bool delete_route = false;
3512
9bcb3eef
DS
3513 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3514 safi);
d62a17ae 3515
f009ff26 3516 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3517 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3518
f009ff26 3519 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3520 * flag
3521 */
3522 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3523 delete_route = true;
9bcb3eef 3524 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3525 delete_route = true;
f009ff26 3526 if (delete_route) {
9bcb3eef
DS
3527 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3528 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3529 bgp = pi->peer->bgp;
26742171 3530 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3531 }
3532 }
3533 }
4a11bf2c 3534
9bcb3eef
DS
3535 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3536 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3537}
3538
9bcb3eef 3539static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3540 struct peer *peer, afi_t afi, safi_t safi,
3541 struct prefix_rd *prd)
3542{
9bcb3eef 3543 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3544
d62a17ae 3545 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3546 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3547 */
b4f7f45b
IR
3548 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3549 && peer->sort == BGP_PEER_EBGP)
3550 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3551 == BGP_DAMP_SUPPRESSED) {
3552 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3553 safi);
3554 return;
d62a17ae 3555 }
3556
49e5a4a0 3557#ifdef ENABLE_BGP_VNC
d62a17ae 3558 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3559 struct bgp_dest *pdest = NULL;
d62a17ae 3560 struct bgp_table *table = NULL;
3561
9bcb3eef
DS
3562 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3563 (struct prefix *)prd);
3564 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3565 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3566
3567 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3568 peer->bgp, prd, table, p, pi);
d62a17ae 3569 }
9bcb3eef 3570 bgp_dest_unlock_node(pdest);
d62a17ae 3571 }
3572 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3573 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3574
b54892e0
DS
3575 vnc_import_bgp_del_route(peer->bgp, p, pi);
3576 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3577 }
65efcfce 3578 }
d62a17ae 3579#endif
128ea8ab 3580
d62a17ae 3581 /* If this is an EVPN route, process for un-import. */
3582 if (safi == SAFI_EVPN)
b54892e0 3583 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3584
9bcb3eef 3585 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3586}
3587
4b7e6066
DS
3588struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3589 struct peer *peer, struct attr *attr,
9bcb3eef 3590 struct bgp_dest *dest)
fb018d25 3591{
4b7e6066 3592 struct bgp_path_info *new;
fb018d25 3593
d62a17ae 3594 /* Make new BGP info. */
4b7e6066 3595 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3596 new->type = type;
3597 new->instance = instance;
3598 new->sub_type = sub_type;
3599 new->peer = peer;
3600 new->attr = attr;
3601 new->uptime = bgp_clock();
9bcb3eef 3602 new->net = dest;
d62a17ae 3603 return new;
fb018d25
DS
3604}
3605
c265ee22 3606/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3607bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3608 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3609 struct bgp_dest *dest)
d62a17ae 3610{
2dbe3fa9 3611 bool ret = false;
b099a5c8
DA
3612 bool is_bgp_static_route =
3613 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3614 : false;
d62a17ae 3615
e8442016
DS
3616 /*
3617 * Only validated for unicast and multicast currently.
3618 * Also valid for EVPN where the nexthop is an IP address.
3619 * If we are a bgp static route being checked then there is
3620 * no need to check to see if the nexthop is martian as
3621 * that it should be ok.
3622 */
3623 if (is_bgp_static_route ||
3624 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3625 return false;
d62a17ae 3626
3627 /* If NEXT_HOP is present, validate it. */
3628 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3629 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3630 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3631 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3632 return true;
d62a17ae 3633 }
c265ee22 3634
d62a17ae 3635 /* If MP_NEXTHOP is present, validate it. */
3636 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3637 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3638 * it is not an IPv6 link-local address.
0355b41d
DA
3639 *
3640 * If we receive an UPDATE with nexthop length set to 32 bytes
3641 * we shouldn't discard an UPDATE if it's set to (::).
3642 * The link-local (2st) is validated along the code path later.
d62a17ae 3643 */
3644 if (attr->mp_nexthop_len) {
3645 switch (attr->mp_nexthop_len) {
3646 case BGP_ATTR_NHLEN_IPV4:
3647 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3648 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3649 || IPV4_CLASS_DE(
3650 ntohl(attr->mp_nexthop_global_in.s_addr))
3651 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3652 dest));
d62a17ae 3653 break;
3654
3655 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3656 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3657 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3658 &attr->mp_nexthop_global)
d62a17ae 3659 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3660 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3661 &attr->mp_nexthop_global)
3662 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3663 dest));
d62a17ae 3664 break;
0355b41d
DA
3665 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3666 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3667 || IN6_IS_ADDR_MULTICAST(
3668 &attr->mp_nexthop_global)
3669 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3670 dest));
0355b41d 3671 break;
d62a17ae 3672
3673 default:
3dc339cd 3674 ret = true;
d62a17ae 3675 break;
3676 }
3677 }
c265ee22 3678
d62a17ae 3679 return ret;
3680}
3681
aade37d7 3682static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3683{
3684 struct community *old;
3685 struct community *new;
3686 struct community *merge;
aade37d7 3687 struct community *no_export;
2721dd61
DA
3688
3689 old = attr->community;
aade37d7 3690 no_export = community_str2com("no-export");
2721dd61 3691
b4efa101
DA
3692 assert(no_export);
3693
2721dd61 3694 if (old) {
aade37d7 3695 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3696
3697 if (!old->refcnt)
3698 community_free(&old);
3699
3700 new = community_uniq_sort(merge);
3701 community_free(&merge);
3702 } else {
aade37d7 3703 new = community_dup(no_export);
2721dd61
DA
3704 }
3705
aade37d7 3706 community_free(&no_export);
2721dd61
DA
3707
3708 attr->community = new;
3709 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3710}
3711
5a1ae2c2 3712int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3713 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3714 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3715 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3716 struct bgp_route_evpn *evpn)
d62a17ae 3717{
3718 int ret;
3719 int aspath_loop_count = 0;
9bcb3eef 3720 struct bgp_dest *dest;
d62a17ae 3721 struct bgp *bgp;
3722 struct attr new_attr;
3723 struct attr *attr_new;
40381db7 3724 struct bgp_path_info *pi;
4b7e6066
DS
3725 struct bgp_path_info *new;
3726 struct bgp_path_info_extra *extra;
d62a17ae 3727 const char *reason;
3728 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3729 int connected = 0;
3730 int do_loop_check = 1;
3731 int has_valid_label = 0;
7c312383 3732 afi_t nh_afi;
949b0f24 3733 uint8_t pi_type = 0;
3734 uint8_t pi_sub_type = 0;
9146341f 3735 bool force_evpn_import = false;
907707db 3736 safi_t orig_safi = safi;
949b0f24 3737
c7bb4f00 3738 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3739 char pfxprint[PREFIX2STR_BUFFER];
3740
3741 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3742 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3743 afi, safi, attr);
6401252f
QY
3744 }
3745
49e5a4a0 3746#ifdef ENABLE_BGP_VNC
d62a17ae 3747 int vnc_implicit_withdraw = 0;
65efcfce 3748#endif
d62a17ae 3749 int same_attr = 0;
718e3744 3750
907707db
MS
3751 /* Special case for BGP-LU - map LU safi to ordinary unicast safi */
3752 if (orig_safi == SAFI_LABELED_UNICAST)
3753 safi = SAFI_UNICAST;
3754
d62a17ae 3755 memset(&new_attr, 0, sizeof(struct attr));
3756 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3757 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3758
d62a17ae 3759 bgp = peer->bgp;
9bcb3eef 3760 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3761 /* TODO: Check to see if we can get rid of "is_valid_label" */
3762 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3763 has_valid_label = (num_labels > 0) ? 1 : 0;
3764 else
3765 has_valid_label = bgp_is_valid_label(label);
718e3744 3766
28f66de2
MS
3767 if (has_valid_label)
3768 assert(label != NULL);
3769
66ff6089
AD
3770 /* Update overlay index of the attribute */
3771 if (afi == AFI_L2VPN && evpn)
3772 memcpy(&attr->evpn_overlay, evpn,
3773 sizeof(struct bgp_route_evpn));
3774
d62a17ae 3775 /* When peer's soft reconfiguration enabled. Record input packet in
3776 Adj-RIBs-In. */
3777 if (!soft_reconfig
3778 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3779 && peer != bgp->peer_self)
9bcb3eef 3780 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3781
3782 /* Check previously received route. */
9bcb3eef 3783 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3784 if (pi->peer == peer && pi->type == type
3785 && pi->sub_type == sub_type
3786 && pi->addpath_rx_id == addpath_id)
d62a17ae 3787 break;
3788
3789 /* AS path local-as loop check. */
3790 if (peer->change_local_as) {
c4368918
DW
3791 if (peer->allowas_in[afi][safi])
3792 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3793 else if (!CHECK_FLAG(peer->flags,
3794 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3795 aspath_loop_count = 1;
3796
3797 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3798 > aspath_loop_count) {
b4d46cc9 3799 peer->stat_pfx_aspath_loop++;
692174a1 3800 reason = "as-path contains our own AS;";
d62a17ae 3801 goto filtered;
3802 }
718e3744 3803 }
718e3744 3804
d62a17ae 3805 /* If the peer is configured for "allowas-in origin" and the last ASN in
3806 * the
3807 * as-path is our ASN then we do not need to call aspath_loop_check
3808 */
3809 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3810 if (aspath_get_last_as(attr->aspath) == bgp->as)
3811 do_loop_check = 0;
3812
3813 /* AS path loop check. */
3814 if (do_loop_check) {
3815 if (aspath_loop_check(attr->aspath, bgp->as)
3816 > peer->allowas_in[afi][safi]
3817 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3818 && aspath_loop_check(attr->aspath, bgp->confed_id)
3819 > peer->allowas_in[afi][safi])) {
b4d46cc9 3820 peer->stat_pfx_aspath_loop++;
d62a17ae 3821 reason = "as-path contains our own AS;";
3822 goto filtered;
3823 }
3824 }
aac9ef6c 3825
d62a17ae 3826 /* Route reflector originator ID check. */
3827 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3828 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3829 peer->stat_pfx_originator_loop++;
d62a17ae 3830 reason = "originator is us;";
3831 goto filtered;
3832 }
718e3744 3833
d62a17ae 3834 /* Route reflector cluster ID check. */
3835 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3836 peer->stat_pfx_cluster_loop++;
d62a17ae 3837 reason = "reflected from the same cluster;";
3838 goto filtered;
3839 }
718e3744 3840
d62a17ae 3841 /* Apply incoming filter. */
907707db 3842 if (bgp_input_filter(peer, p, attr, afi, orig_safi) == FILTER_DENY) {
b4d46cc9 3843 peer->stat_pfx_filter++;
d62a17ae 3844 reason = "filter;";
3845 goto filtered;
3846 }
718e3744 3847
a8b72dc6
DA
3848 /* RFC 8212 to prevent route leaks.
3849 * This specification intends to improve this situation by requiring the
3850 * explicit configuration of both BGP Import and Export Policies for any
3851 * External BGP (EBGP) session such as customers, peers, or
3852 * confederation boundaries for all enabled address families. Through
3853 * codification of the aforementioned requirement, operators will
3854 * benefit from consistent behavior across different BGP
3855 * implementations.
3856 */
1d3fdccf 3857 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3858 if (!bgp_inbound_policy_exists(peer,
3859 &peer->filter[afi][safi])) {
3860 reason = "inbound policy missing";
b17826b7
DS
3861 if (monotime_since(&bgp->ebgprequirespolicywarning,
3862 NULL) > FIFTEENMINUTE2USEC ||
3863 bgp->ebgprequirespolicywarning.tv_sec == 0) {
3864 zlog_warn(
3865 "EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly");
3866 monotime(&bgp->ebgprequirespolicywarning);
3867 }
a8b72dc6
DA
3868 goto filtered;
3869 }
3870
fb29348a
DA
3871 /* draft-ietf-idr-deprecate-as-set-confed-set
3872 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3873 * Eventually, This document (if approved) updates RFC 4271
3874 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3875 * and obsoletes RFC 6472.
3876 */
7f972cd8 3877 if (peer->bgp->reject_as_sets)
fb29348a
DA
3878 if (aspath_check_as_sets(attr->aspath)) {
3879 reason =
3880 "as-path contains AS_SET or AS_CONFED_SET type;";
3881 goto filtered;
3882 }
3883
6f4f49b2 3884 new_attr = *attr;
d62a17ae 3885
3886 /* Apply incoming route-map.
3887 * NB: new_attr may now contain newly allocated values from route-map
3888 * "set"
3889 * commands, so we need bgp_attr_flush in the error paths, until we
3890 * intern
3891 * the attr (which takes over the memory references) */
907707db 3892 if (bgp_input_modifier(peer, p, &new_attr, afi, orig_safi, NULL, label,
9bcb3eef
DS
3893 num_labels, dest)
3894 == RMAP_DENY) {
b4d46cc9 3895 peer->stat_pfx_filter++;
d62a17ae 3896 reason = "route-map;";
3897 bgp_attr_flush(&new_attr);
3898 goto filtered;
3899 }
718e3744 3900
05864da7 3901 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3902 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3903 /* remove from RIB previous entry */
3904 bgp_zebra_withdraw(p, pi, bgp, safi);
3905 }
3906
7f323236
DW
3907 if (peer->sort == BGP_PEER_EBGP) {
3908
2721dd61
DA
3909 /* rfc7999:
3910 * A BGP speaker receiving an announcement tagged with the
3911 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3912 * NO_EXPORT community as defined in RFC1997, or a
3913 * similar community, to prevent propagation of the
3914 * prefix outside the local AS. The community to prevent
3915 * propagation SHOULD be chosen according to the operator's
3916 * routing policy.
3917 */
3918 if (new_attr.community
3919 && community_include(new_attr.community,
3920 COMMUNITY_BLACKHOLE))
aade37d7 3921 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3922
a4d82a8a
PZ
3923 /* If we receive the graceful-shutdown community from an eBGP
3924 * peer we must lower local-preference */
3925 if (new_attr.community
3926 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3927 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3928 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3929
a4d82a8a
PZ
3930 /* If graceful-shutdown is configured then add the GSHUT
3931 * community to all paths received from eBGP peers */
637e5ba4 3932 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3933 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3934 }
3935
949b0f24 3936 if (pi) {
3937 pi_type = pi->type;
3938 pi_sub_type = pi->sub_type;
3939 }
3940
d62a17ae 3941 /* next hop check. */
a4d82a8a 3942 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3943 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3944 &new_attr, dest)) {
b4d46cc9 3945 peer->stat_pfx_nh_invalid++;
d62a17ae 3946 reason = "martian or self next-hop;";
3947 bgp_attr_flush(&new_attr);
3948 goto filtered;
3949 }
718e3744 3950
5c14a191 3951 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3952 peer->stat_pfx_nh_invalid++;
4e802e66 3953 reason = "self mac;";
4dbf2038 3954 bgp_attr_flush(&new_attr);
4e802e66
DS
3955 goto filtered;
3956 }
3957
a1b773e2
DS
3958 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3959 * condition :
3960 * Suppress fib is enabled
3961 * BGP_OPT_NO_FIB is not enabled
3962 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3963 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3964 */
3965 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3966 && (sub_type == BGP_ROUTE_NORMAL)
3967 && (!bgp_option_check(BGP_OPT_NO_FIB))
3968 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3969 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3970
9cbd06e0
DA
3971 /* If maximum prefix count is configured and current prefix
3972 * count exeed it.
3973 */
4dbf2038
IR
3974 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0)) {
3975 bgp_attr_flush(&new_attr);
9cbd06e0 3976 return -1;
4dbf2038
IR
3977 }
3978
3979 attr_new = bgp_attr_intern(&new_attr);
9cbd06e0 3980
d62a17ae 3981 /* If the update is implicit withdraw. */
40381db7
DS
3982 if (pi) {
3983 pi->uptime = bgp_clock();
3984 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3985
9bcb3eef 3986 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3987
d62a17ae 3988 /* Same attribute comes in. */
40381db7 3989 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3990 && same_attr
d62a17ae 3991 && (!has_valid_label
40381db7 3992 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3993 num_labels * sizeof(mpls_label_t))
66ff6089 3994 == 0)) {
b4f7f45b
IR
3995 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3996 BGP_CONFIG_DAMPENING)
d62a17ae 3997 && peer->sort == BGP_PEER_EBGP
40381db7 3998 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3999 if (bgp_debug_update(peer, p, NULL, 1)) {
4000 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4001 afi, safi, prd, p, label,
4002 num_labels, addpath_id ? 1 : 0,
66ff6089 4003 addpath_id, evpn, pfx_buf,
a4d82a8a 4004 sizeof(pfx_buf));
d62a17ae 4005 zlog_debug("%s rcvd %s", peer->host,
4006 pfx_buf);
4007 }
4008
9bcb3eef 4009 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 4010 != BGP_DAMP_SUPPRESSED) {
40381db7 4011 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 4012 safi);
9bcb3eef 4013 bgp_process(bgp, dest, afi, safi);
d62a17ae 4014 }
4015 } else /* Duplicate - odd */
4016 {
4017 if (bgp_debug_update(peer, p, NULL, 1)) {
4018 if (!peer->rcvd_attr_printed) {
4019 zlog_debug(
4020 "%s rcvd UPDATE w/ attr: %s",
4021 peer->host,
4022 peer->rcvd_attr_str);
4023 peer->rcvd_attr_printed = 1;
4024 }
4025
4026 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
4027 afi, safi, prd, p, label,
4028 num_labels, addpath_id ? 1 : 0,
66ff6089 4029 addpath_id, evpn, pfx_buf,
a4d82a8a 4030 sizeof(pfx_buf));
d62a17ae 4031 zlog_debug(
4032 "%s rcvd %s...duplicate ignored",
4033 peer->host, pfx_buf);
4034 }
4035
4036 /* graceful restart STALE flag unset. */
40381db7 4037 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 4038 bgp_path_info_unset_flag(
9bcb3eef
DS
4039 dest, pi, BGP_PATH_STALE);
4040 bgp_dest_set_defer_flag(dest, false);
4041 bgp_process(bgp, dest, afi, safi);
d62a17ae 4042 }
4043 }
4044
9bcb3eef 4045 bgp_dest_unlock_node(dest);
d62a17ae 4046 bgp_attr_unintern(&attr_new);
4047
4048 return 0;
4049 }
718e3744 4050
d62a17ae 4051 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 4052 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 4053 if (bgp_debug_update(peer, p, NULL, 1)) {
4054 bgp_debug_rdpfxpath2str(
a4d82a8a 4055 afi, safi, prd, p, label, num_labels,
66ff6089 4056 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4057 pfx_buf, sizeof(pfx_buf));
d62a17ae 4058 zlog_debug(
4059 "%s rcvd %s, flapped quicker than processing",
4060 peer->host, pfx_buf);
4061 }
4062
9bcb3eef 4063 bgp_path_info_restore(dest, pi);
9146341f 4064
4065 /*
4066 * If the BGP_PATH_REMOVED flag is set, then EVPN
4067 * routes would have been unimported already when a
4068 * prior BGP withdraw processing happened. Such routes
4069 * need to be imported again, so flag accordingly.
4070 */
4071 force_evpn_import = true;
d62a17ae 4072 }
718e3744 4073
d62a17ae 4074 /* Received Logging. */
4075 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
4076 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
4077 num_labels, addpath_id ? 1 : 0,
66ff6089 4078 addpath_id, evpn, pfx_buf,
a4d82a8a 4079 sizeof(pfx_buf));
d62a17ae 4080 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4081 }
718e3744 4082
d62a17ae 4083 /* graceful restart STALE flag unset. */
f009ff26 4084 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
4085 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
4086 bgp_dest_set_defer_flag(dest, false);
f009ff26 4087 }
d62a17ae 4088
4089 /* The attribute is changed. */
9bcb3eef 4090 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 4091
4092 /* implicit withdraw, decrement aggregate and pcount here.
4093 * only if update is accepted, they'll increment below.
4094 */
40381db7 4095 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 4096
4097 /* Update bgp route dampening information. */
b4f7f45b 4098 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4099 && peer->sort == BGP_PEER_EBGP) {
4100 /* This is implicit withdraw so we should update
b4f7f45b
IR
4101 dampening
4102 information. */
40381db7 4103 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 4104 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 4105 }
49e5a4a0 4106#ifdef ENABLE_BGP_VNC
d62a17ae 4107 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4108 struct bgp_dest *pdest = NULL;
d62a17ae 4109 struct bgp_table *table = NULL;
4110
9bcb3eef
DS
4111 pdest = bgp_node_get(bgp->rib[afi][safi],
4112 (struct prefix *)prd);
4113 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4114 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4115
4116 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 4117 bgp, prd, table, p, pi);
d62a17ae 4118 }
9bcb3eef 4119 bgp_dest_unlock_node(pdest);
d62a17ae 4120 }
4121 if ((afi == AFI_IP || afi == AFI_IP6)
4122 && (safi == SAFI_UNICAST)) {
40381db7 4123 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4124 /*
4125 * Implicit withdraw case.
4126 */
4127 ++vnc_implicit_withdraw;
40381db7
DS
4128 vnc_import_bgp_del_route(bgp, p, pi);
4129 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4130 }
4131 }
65efcfce 4132#endif
128ea8ab 4133
d62a17ae 4134 /* Special handling for EVPN update of an existing route. If the
4135 * extended community attribute has changed, we need to
4136 * un-import
4137 * the route using its existing extended community. It will be
4138 * subsequently processed for import with the new extended
4139 * community.
4140 */
6f8c9c11
PR
4141 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4142 && !same_attr) {
40381db7 4143 if ((pi->attr->flag
d62a17ae 4144 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4145 && (attr_new->flag
4146 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4147 int cmp;
4148
b53e67a3
DA
4149 cmp = ecommunity_cmp(
4150 bgp_attr_get_ecommunity(pi->attr),
4151 bgp_attr_get_ecommunity(attr_new));
d62a17ae 4152 if (!cmp) {
4153 if (bgp_debug_update(peer, p, NULL, 1))
4154 zlog_debug(
4155 "Change in EXT-COMM, existing %s new %s",
4156 ecommunity_str(
b53e67a3
DA
4157 bgp_attr_get_ecommunity(
4158 pi->attr)),
d62a17ae 4159 ecommunity_str(
b53e67a3
DA
4160 bgp_attr_get_ecommunity(
4161 attr_new)));
6f8c9c11
PR
4162 if (safi == SAFI_EVPN)
4163 bgp_evpn_unimport_route(
4164 bgp, afi, safi, p, pi);
4165 else /* SAFI_MPLS_VPN */
4166 vpn_leak_to_vrf_withdraw(bgp,
4167 pi);
d62a17ae 4168 }
4169 }
4170 }
718e3744 4171
d62a17ae 4172 /* Update to new attribute. */
40381db7
DS
4173 bgp_attr_unintern(&pi->attr);
4174 pi->attr = attr_new;
d62a17ae 4175
4176 /* Update MPLS label */
4177 if (has_valid_label) {
40381db7 4178 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4179 if (extra->label != label) {
4180 memcpy(&extra->label, label,
dbd587da 4181 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4182 extra->num_labels = num_labels;
4183 }
b57ba6d2
MK
4184 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4185 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4186 }
718e3744 4187
e496b420
HS
4188 /* Update SRv6 SID */
4189 if (attr->srv6_l3vpn) {
4190 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4191 if (sid_diff(&extra->sid[0].sid,
4192 &attr->srv6_l3vpn->sid)) {
4193 sid_copy(&extra->sid[0].sid,
e496b420
HS
4194 &attr->srv6_l3vpn->sid);
4195 extra->num_sids = 1;
cc8f05df 4196
16f3db2d
RS
4197 extra->sid[0].loc_block_len = 0;
4198 extra->sid[0].loc_node_len = 0;
4199 extra->sid[0].func_len = 0;
4200 extra->sid[0].arg_len = 0;
4201
4202 if (attr->srv6_l3vpn->loc_block_len != 0) {
4203 extra->sid[0].loc_block_len =
4204 attr->srv6_l3vpn->loc_block_len;
4205 extra->sid[0].loc_node_len =
4206 attr->srv6_l3vpn->loc_node_len;
4207 extra->sid[0].func_len =
4208 attr->srv6_l3vpn->func_len;
4209 extra->sid[0].arg_len =
4210 attr->srv6_l3vpn->arg_len;
4211 }
4212
cc8f05df
RS
4213 /*
4214 * draft-ietf-bess-srv6-services-07
4215 * The part of SRv6 SID may be encoded as MPLS
4216 * Label for the efficient packing.
4217 */
4218 if (attr->srv6_l3vpn->transposition_len != 0)
4219 transpose_sid(
16f3db2d 4220 &extra->sid[0].sid,
cc8f05df
RS
4221 decode_label(label),
4222 attr->srv6_l3vpn
4223 ->transposition_offset,
4224 attr->srv6_l3vpn
4225 ->transposition_len);
e496b420
HS
4226 }
4227 } else if (attr->srv6_vpn) {
4228 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4229 if (sid_diff(&extra->sid[0].sid,
4230 &attr->srv6_vpn->sid)) {
4231 sid_copy(&extra->sid[0].sid,
4232 &attr->srv6_vpn->sid);
e496b420
HS
4233 extra->num_sids = 1;
4234 }
4235 }
4236
49e5a4a0 4237#ifdef ENABLE_BGP_VNC
d62a17ae 4238 if ((afi == AFI_IP || afi == AFI_IP6)
4239 && (safi == SAFI_UNICAST)) {
4240 if (vnc_implicit_withdraw) {
4241 /*
4242 * Add back the route with its new attributes
4243 * (e.g., nexthop).
4244 * The route is still selected, until the route
4245 * selection
4246 * queued by bgp_process actually runs. We have
4247 * to make this
4248 * update to the VNC side immediately to avoid
4249 * racing against
4250 * configuration changes (e.g., route-map
4251 * changes) which
4252 * trigger re-importation of the entire RIB.
4253 */
40381db7
DS
4254 vnc_import_bgp_add_route(bgp, p, pi);
4255 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4256 }
4257 }
65efcfce
LB
4258#endif
4259
d62a17ae 4260 /* Update bgp route dampening information. */
b4f7f45b 4261 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4262 && peer->sort == BGP_PEER_EBGP) {
4263 /* Now we do normal update dampening. */
9bcb3eef 4264 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4265 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4266 bgp_dest_unlock_node(dest);
d62a17ae 4267 return 0;
4268 }
4269 }
128ea8ab 4270
d62a17ae 4271 /* Nexthop reachability check - for unicast and
4272 * labeled-unicast.. */
7c312383
AD
4273 if (((afi == AFI_IP || afi == AFI_IP6)
4274 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4275 || (safi == SAFI_EVPN &&
4276 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4277 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4278 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4279 && !CHECK_FLAG(peer->flags,
4280 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4281 && !CHECK_FLAG(bgp->flags,
4282 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4283 connected = 1;
4284 else
4285 connected = 0;
4286
960035b2
PZ
4287 struct bgp *bgp_nexthop = bgp;
4288
40381db7
DS
4289 if (pi->extra && pi->extra->bgp_orig)
4290 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4291
7c312383
AD
4292 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4293
4294 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4295 safi, pi, NULL, connected,
4296 p)
a4d82a8a 4297 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4298 bgp_path_info_set_flag(dest, pi,
4299 BGP_PATH_VALID);
d62a17ae 4300 else {
4301 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4302 zlog_debug("%s(%pI4): NH unresolved",
4303 __func__,
4304 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4305 }
9bcb3eef 4306 bgp_path_info_unset_flag(dest, pi,
18ee8310 4307 BGP_PATH_VALID);
d62a17ae 4308 }
4309 } else
9bcb3eef 4310 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4311
49e5a4a0 4312#ifdef ENABLE_BGP_VNC
d62a17ae 4313 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4314 struct bgp_dest *pdest = NULL;
d62a17ae 4315 struct bgp_table *table = NULL;
4316
9bcb3eef
DS
4317 pdest = bgp_node_get(bgp->rib[afi][safi],
4318 (struct prefix *)prd);
4319 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4320 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4321
4322 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4323 bgp, prd, table, p, pi);
d62a17ae 4324 }
9bcb3eef 4325 bgp_dest_unlock_node(pdest);
d62a17ae 4326 }
4327#endif
718e3744 4328
d62a17ae 4329 /* If this is an EVPN route and some attribute has changed,
9146341f 4330 * or we are explicitly told to perform a route import, process
d62a17ae 4331 * route for import. If the extended community has changed, we
4332 * would
4333 * have done the un-import earlier and the import would result
4334 * in the
4335 * route getting injected into appropriate L2 VNIs. If it is
4336 * just
4337 * some other attribute change, the import will result in
4338 * updating
4339 * the attributes for the route in the VNI(s).
4340 */
9146341f 4341 if (safi == SAFI_EVPN &&
4342 (!same_attr || force_evpn_import) &&
7c312383 4343 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4344 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4345
4346 /* Process change. */
40381db7 4347 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4348
9bcb3eef
DS
4349 bgp_process(bgp, dest, afi, safi);
4350 bgp_dest_unlock_node(dest);
558d1fec 4351
ddb5b488
PZ
4352 if (SAFI_UNICAST == safi
4353 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4354 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4355
40381db7 4356 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4357 }
4358 if ((SAFI_MPLS_VPN == safi)
4359 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4360
40381db7 4361 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4362 }
4363
49e5a4a0 4364#ifdef ENABLE_BGP_VNC
d62a17ae 4365 if (SAFI_MPLS_VPN == safi) {
4366 mpls_label_t label_decoded = decode_label(label);
28070ee3 4367
d62a17ae 4368 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4369 type, sub_type, &label_decoded);
4370 }
4371 if (SAFI_ENCAP == safi) {
4372 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4373 type, sub_type, NULL);
4374 }
28070ee3
PZ
4375#endif
4376
d62a17ae 4377 return 0;
4378 } // End of implicit withdraw
718e3744 4379
d62a17ae 4380 /* Received Logging. */
4381 if (bgp_debug_update(peer, p, NULL, 1)) {
4382 if (!peer->rcvd_attr_printed) {
4383 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4384 peer->rcvd_attr_str);
4385 peer->rcvd_attr_printed = 1;
4386 }
718e3744 4387
a4d82a8a 4388 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4389 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4390 pfx_buf, sizeof(pfx_buf));
d62a17ae 4391 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4392 }
718e3744 4393
d62a17ae 4394 /* Make new BGP info. */
9bcb3eef 4395 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4396
d62a17ae 4397 /* Update MPLS label */
4398 if (has_valid_label) {
18ee8310 4399 extra = bgp_path_info_extra_get(new);
8ba71050 4400 if (extra->label != label) {
dbd587da
QY
4401 memcpy(&extra->label, label,
4402 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4403 extra->num_labels = num_labels;
4404 }
b57ba6d2
MK
4405 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4406 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4407 }
718e3744 4408
e496b420
HS
4409 /* Update SRv6 SID */
4410 if (safi == SAFI_MPLS_VPN) {
4411 extra = bgp_path_info_extra_get(new);
4412 if (attr->srv6_l3vpn) {
16f3db2d 4413 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4414 extra->num_sids = 1;
cc8f05df 4415
16f3db2d
RS
4416 extra->sid[0].loc_block_len =
4417 attr->srv6_l3vpn->loc_block_len;
4418 extra->sid[0].loc_node_len =
4419 attr->srv6_l3vpn->loc_node_len;
4420 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4421 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
4422
cc8f05df
RS
4423 /*
4424 * draft-ietf-bess-srv6-services-07
4425 * The part of SRv6 SID may be encoded as MPLS Label for
4426 * the efficient packing.
4427 */
4428 if (attr->srv6_l3vpn->transposition_len != 0)
4429 transpose_sid(
16f3db2d 4430 &extra->sid[0].sid, decode_label(label),
cc8f05df
RS
4431 attr->srv6_l3vpn->transposition_offset,
4432 attr->srv6_l3vpn->transposition_len);
e496b420 4433 } else if (attr->srv6_vpn) {
16f3db2d 4434 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4435 extra->num_sids = 1;
4436 }
4437 }
4438
d62a17ae 4439 /* Nexthop reachability check. */
7c312383
AD
4440 if (((afi == AFI_IP || afi == AFI_IP6)
4441 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4442 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4443 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4444 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4445 && !CHECK_FLAG(peer->flags,
4446 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4447 && !CHECK_FLAG(bgp->flags,
4448 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4449 connected = 1;
4450 else
4451 connected = 0;
4452
7c312383
AD
4453 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4454
4053e952 4455 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4456 connected, p)
a4d82a8a 4457 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4458 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4459 else {
4460 if (BGP_DEBUG(nht, NHT)) {
4461 char buf1[INET6_ADDRSTRLEN];
4462 inet_ntop(AF_INET,
4463 (const void *)&attr_new->nexthop,
4464 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4465 zlog_debug("%s(%s): NH unresolved", __func__,
4466 buf1);
d62a17ae 4467 }
9bcb3eef 4468 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4469 }
4470 } else
9bcb3eef 4471 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4472
d62a17ae 4473 /* Addpath ID */
4474 new->addpath_rx_id = addpath_id;
4475
4476 /* Increment prefix */
4477 bgp_aggregate_increment(bgp, p, new, afi, safi);
4478
4479 /* Register new BGP information. */
9bcb3eef 4480 bgp_path_info_add(dest, new);
d62a17ae 4481
4482 /* route_node_get lock */
9bcb3eef 4483 bgp_dest_unlock_node(dest);
558d1fec 4484
49e5a4a0 4485#ifdef ENABLE_BGP_VNC
d62a17ae 4486 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4487 struct bgp_dest *pdest = NULL;
d62a17ae 4488 struct bgp_table *table = NULL;
4489
9bcb3eef
DS
4490 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4491 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4492 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4493
4494 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4495 bgp, prd, table, p, new);
4496 }
9bcb3eef 4497 bgp_dest_unlock_node(pdest);
d62a17ae 4498 }
65efcfce
LB
4499#endif
4500
d62a17ae 4501 /* If this is an EVPN route, process for import. */
7c312383 4502 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4503 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4504
9bcb3eef 4505 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4506
d62a17ae 4507 /* Process change. */
9bcb3eef 4508 bgp_process(bgp, dest, afi, safi);
718e3744 4509
ddb5b488
PZ
4510 if (SAFI_UNICAST == safi
4511 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4512 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4513 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4514 }
4515 if ((SAFI_MPLS_VPN == safi)
4516 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4517
4518 vpn_leak_to_vrf_update(bgp, new);
4519 }
49e5a4a0 4520#ifdef ENABLE_BGP_VNC
d62a17ae 4521 if (SAFI_MPLS_VPN == safi) {
4522 mpls_label_t label_decoded = decode_label(label);
28070ee3 4523
d62a17ae 4524 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4525 sub_type, &label_decoded);
4526 }
4527 if (SAFI_ENCAP == safi) {
4528 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4529 sub_type, NULL);
4530 }
28070ee3
PZ
4531#endif
4532
d62a17ae 4533 return 0;
718e3744 4534
d62a17ae 4535/* This BGP update is filtered. Log the reason then update BGP
4536 entry. */
4537filtered:
9bcb3eef 4538 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4539
d62a17ae 4540 if (bgp_debug_update(peer, p, NULL, 1)) {
4541 if (!peer->rcvd_attr_printed) {
4542 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4543 peer->rcvd_attr_str);
4544 peer->rcvd_attr_printed = 1;
4545 }
718e3744 4546
a4d82a8a 4547 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4548 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4549 pfx_buf, sizeof(pfx_buf));
d62a17ae 4550 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4551 peer->host, pfx_buf, reason);
4552 }
128ea8ab 4553
40381db7 4554 if (pi) {
d62a17ae 4555 /* If this is an EVPN route, un-import it as it is now filtered.
4556 */
4557 if (safi == SAFI_EVPN)
40381db7 4558 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4559
ddb5b488
PZ
4560 if (SAFI_UNICAST == safi
4561 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4562 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4563
40381db7 4564 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4565 }
4566 if ((SAFI_MPLS_VPN == safi)
4567 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4568
40381db7 4569 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4570 }
4571
9bcb3eef 4572 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4573 }
4574
9bcb3eef 4575 bgp_dest_unlock_node(dest);
558d1fec 4576
49e5a4a0 4577#ifdef ENABLE_BGP_VNC
d62a17ae 4578 /*
4579 * Filtered update is treated as an implicit withdrawal (see
4580 * bgp_rib_remove()
4581 * a few lines above)
4582 */
4583 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4584 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4585 0);
4586 }
97736e32
PZ
4587#endif
4588
d62a17ae 4589 return 0;
718e3744 4590}
4591
26a3ffd6 4592int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4593 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4594 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4595 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4596{
d62a17ae 4597 struct bgp *bgp;
4598 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4599 struct bgp_dest *dest;
40381db7 4600 struct bgp_path_info *pi;
718e3744 4601
49e5a4a0 4602#ifdef ENABLE_BGP_VNC
d62a17ae 4603 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4604 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4605 0);
4606 }
28070ee3
PZ
4607#endif
4608
d62a17ae 4609 bgp = peer->bgp;
4610
4611 /* Lookup node. */
9bcb3eef 4612 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4613
4614 /* If peer is soft reconfiguration enabled. Record input packet for
4615 * further calculation.
4616 *
4617 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4618 * routes that are filtered. This tanks out Quagga RS pretty badly due
4619 * to
4620 * the iteration over all RS clients.
4621 * Since we need to remove the entry from adj_in anyway, do that first
4622 * and
4623 * if there was no entry, we don't need to do anything more.
4624 */
4625 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4626 && peer != bgp->peer_self)
9bcb3eef 4627 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4628 peer->stat_pfx_dup_withdraw++;
4629
d62a17ae 4630 if (bgp_debug_update(peer, p, NULL, 1)) {
4631 bgp_debug_rdpfxpath2str(
a4d82a8a 4632 afi, safi, prd, p, label, num_labels,
6c995628
AD
4633 addpath_id ? 1 : 0, addpath_id, NULL,
4634 pfx_buf, sizeof(pfx_buf));
d62a17ae 4635 zlog_debug(
4636 "%s withdrawing route %s not in adj-in",
4637 peer->host, pfx_buf);
4638 }
9bcb3eef 4639 bgp_dest_unlock_node(dest);
d62a17ae 4640 return 0;
4641 }
cd808e74 4642
d62a17ae 4643 /* Lookup withdrawn route. */
9bcb3eef 4644 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4645 if (pi->peer == peer && pi->type == type
4646 && pi->sub_type == sub_type
4647 && pi->addpath_rx_id == addpath_id)
d62a17ae 4648 break;
4649
4650 /* Logging. */
4651 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4652 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4653 addpath_id ? 1 : 0, addpath_id, NULL,
4654 pfx_buf, sizeof(pfx_buf));
d62a17ae 4655 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4656 pfx_buf);
4657 }
718e3744 4658
d62a17ae 4659 /* Withdraw specified route from routing table. */
40381db7 4660 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4661 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4662 if (SAFI_UNICAST == safi
4663 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4664 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4665 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4666 }
4667 if ((SAFI_MPLS_VPN == safi)
4668 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4669
40381db7 4670 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4671 }
4672 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4673 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4674 addpath_id ? 1 : 0, addpath_id, NULL,
4675 pfx_buf, sizeof(pfx_buf));
d62a17ae 4676 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4677 }
718e3744 4678
d62a17ae 4679 /* Unlock bgp_node_get() lock. */
9bcb3eef 4680 bgp_dest_unlock_node(dest);
d62a17ae 4681
4682 return 0;
718e3744 4683}
6b0655a2 4684
d62a17ae 4685void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4686 int withdraw)
718e3744 4687{
d62a17ae 4688 struct update_subgroup *subgrp;
4689 subgrp = peer_subgroup(peer, afi, safi);
4690 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4691}
6182d65b 4692
718e3744 4693
3f9c7369
DS
4694/*
4695 * bgp_stop_announce_route_timer
4696 */
d62a17ae 4697void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4698{
d62a17ae 4699 if (!paf->t_announce_route)
4700 return;
4701
50478845 4702 thread_cancel(&paf->t_announce_route);
718e3744 4703}
6b0655a2 4704
3f9c7369
DS
4705/*
4706 * bgp_announce_route_timer_expired
4707 *
4708 * Callback that is invoked when the route announcement timer for a
4709 * peer_af expires.
4710 */
cc9f21da 4711static void bgp_announce_route_timer_expired(struct thread *t)
718e3744 4712{
d62a17ae 4713 struct peer_af *paf;
4714 struct peer *peer;
558d1fec 4715
d62a17ae 4716 paf = THREAD_ARG(t);
4717 peer = paf->peer;
718e3744 4718
feb17238 4719 if (!peer_established(peer))
cc9f21da 4720 return;
3f9c7369 4721
d62a17ae 4722 if (!peer->afc_nego[paf->afi][paf->safi])
cc9f21da 4723 return;
3f9c7369 4724
d62a17ae 4725 peer_af_announce_route(paf, 1);
c5aec50b
MK
4726
4727 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4728 peer->advmap_config_change[paf->afi][paf->safi] = true;
718e3744 4729}
4730
3f9c7369
DS
4731/*
4732 * bgp_announce_route
4733 *
4734 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4735 *
4736 * if force is true we will force an update even if the update
4737 * limiting code is attempted to kick in.
3f9c7369 4738 */
e1a32ec1 4739void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4740{
4741 struct peer_af *paf;
4742 struct update_subgroup *subgrp;
4743
4744 paf = peer_af_find(peer, afi, safi);
4745 if (!paf)
4746 return;
4747 subgrp = PAF_SUBGRP(paf);
4748
4749 /*
4750 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4751 * or a refresh has already been triggered.
4752 */
4753 if (!subgrp || paf->t_announce_route)
4754 return;
4755
e1a32ec1
DS
4756 if (force)
4757 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4758
d62a17ae 4759 /*
4760 * Start a timer to stagger/delay the announce. This serves
4761 * two purposes - announcement can potentially be combined for
4762 * multiple peers and the announcement doesn't happen in the
4763 * vty context.
4764 */
4765 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4766 (subgrp->peer_count == 1)
4767 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4768 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4769 &paf->t_announce_route);
3f9c7369
DS
4770}
4771
4772/*
4773 * Announce routes from all AF tables to a peer.
4774 *
4775 * This should ONLY be called when there is a need to refresh the
4776 * routes to the peer based on a policy change for this peer alone
4777 * or a route refresh request received from the peer.
4778 * The operation will result in splitting the peer from its existing
4779 * subgroups and putting it in new subgroups.
4780 */
d62a17ae 4781void bgp_announce_route_all(struct peer *peer)
718e3744 4782{
d62a17ae 4783 afi_t afi;
4784 safi_t safi;
4785
05c7a1cc 4786 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4787 bgp_announce_route(peer, afi, safi, false);
718e3744 4788}
6b0655a2 4789
46aeabed
LS
4790/* Flag or unflag bgp_dest to determine whether it should be treated by
4791 * bgp_soft_reconfig_table_task.
4792 * Flag if flag is true. Unflag if flag is false.
4793 */
4794static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4795{
4796 struct bgp_dest *dest;
4797 struct bgp_adj_in *ain;
4798
4799 if (!table)
4800 return;
4801
4802 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4803 for (ain = dest->adj_in; ain; ain = ain->next) {
4804 if (ain->peer != NULL)
4805 break;
4806 }
4807 if (flag && ain != NULL && ain->peer != NULL)
4808 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4809 else
4810 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4811 }
4812}
4813
4814static int bgp_soft_reconfig_table_update(struct peer *peer,
4815 struct bgp_dest *dest,
4816 struct bgp_adj_in *ain, afi_t afi,
4817 safi_t safi, struct prefix_rd *prd)
4818{
4819 struct bgp_path_info *pi;
4820 uint32_t num_labels = 0;
4821 mpls_label_t *label_pnt = NULL;
4822 struct bgp_route_evpn evpn;
4823
4824 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4825 if (pi->peer == peer)
4826 break;
4827
4828 if (pi && pi->extra)
4829 num_labels = pi->extra->num_labels;
4830 if (num_labels)
4831 label_pnt = &pi->extra->label[0];
4832 if (pi)
4833 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4834 sizeof(evpn));
4835 else
4836 memset(&evpn, 0, sizeof(evpn));
4837
4838 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4839 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4840 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4841 &evpn);
4842}
4843
d62a17ae 4844static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4845 struct bgp_table *table,
4846 struct prefix_rd *prd)
718e3744 4847{
d62a17ae 4848 int ret;
9bcb3eef 4849 struct bgp_dest *dest;
d62a17ae 4850 struct bgp_adj_in *ain;
718e3744 4851
d62a17ae 4852 if (!table)
4853 table = peer->bgp->rib[afi][safi];
718e3744 4854
9bcb3eef
DS
4855 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4856 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4857 if (ain->peer != peer)
4858 continue;
8692c506 4859
46aeabed
LS
4860 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4861 afi, safi, prd);
ea47320b
DL
4862
4863 if (ret < 0) {
9bcb3eef 4864 bgp_dest_unlock_node(dest);
ea47320b 4865 return;
d62a17ae 4866 }
4867 }
718e3744 4868}
4869
46aeabed
LS
4870/* Do soft reconfig table per bgp table.
4871 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4872 * when BGP_NODE_SOFT_RECONFIG is set,
4873 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4874 * Schedule a new thread to continue the job.
4875 * Without splitting the full job into several part,
4876 * vtysh waits for the job to finish before responding to a BGP command
4877 */
cc9f21da 4878static void bgp_soft_reconfig_table_task(struct thread *thread)
46aeabed
LS
4879{
4880 uint32_t iter, max_iter;
4881 int ret;
4882 struct bgp_dest *dest;
4883 struct bgp_adj_in *ain;
4884 struct peer *peer;
4885 struct bgp_table *table;
4886 struct prefix_rd *prd;
4887 struct listnode *node, *nnode;
4888
4889 table = THREAD_ARG(thread);
4890 prd = NULL;
4891
4892 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4893 if (table->soft_reconfig_init) {
4894 /* first call of the function with a new srta structure.
4895 * Don't do any treatment this time on nodes
4896 * in order vtysh to respond quickly
4897 */
4898 max_iter = 0;
4899 }
4900
4901 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4902 dest = bgp_route_next(dest)) {
4903 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4904 continue;
4905
4906 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4907
4908 for (ain = dest->adj_in; ain; ain = ain->next) {
4909 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4910 nnode, peer)) {
4911 if (ain->peer != peer)
4912 continue;
4913
4914 ret = bgp_soft_reconfig_table_update(
4915 peer, dest, ain, table->afi,
4916 table->safi, prd);
4917 iter++;
4918
4919 if (ret < 0) {
4920 bgp_dest_unlock_node(dest);
4921 listnode_delete(
4922 table->soft_reconfig_peers,
4923 peer);
4924 bgp_announce_route(peer, table->afi,
e1a32ec1 4925 table->safi, false);
46aeabed
LS
4926 if (list_isempty(
4927 table->soft_reconfig_peers)) {
4928 list_delete(
4929 &table->soft_reconfig_peers);
4930 bgp_soft_reconfig_table_flag(
4931 table, false);
cc9f21da 4932 return;
46aeabed
LS
4933 }
4934 }
4935 }
4936 }
4937 }
4938
4939 /* we're either starting the initial iteration,
4940 * or we're going to continue an ongoing iteration
4941 */
4942 if (dest || table->soft_reconfig_init) {
4943 table->soft_reconfig_init = false;
4944 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4945 table, 0, &table->soft_reconfig_thread);
cc9f21da 4946 return;
46aeabed
LS
4947 }
4948 /* we're done, clean up the background iteration context info and
4949 schedule route annoucement
4950 */
4951 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4952 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 4953 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
4954 }
4955
4956 list_delete(&table->soft_reconfig_peers);
46aeabed
LS
4957}
4958
4959
4960/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4961 * and peer.
4962 * - bgp cannot be NULL
4963 * - if table and peer are NULL, cancel all threads within the bgp instance
4964 * - if table is NULL and peer is not,
4965 * remove peer in all threads within the bgp instance
4966 * - if peer is NULL, cancel all threads matching table within the bgp instance
4967 */
4968void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4969 const struct bgp_table *table,
4970 const struct peer *peer)
4971{
4972 struct peer *npeer;
4973 struct listnode *node, *nnode;
4974 int afi, safi;
4975 struct bgp_table *ntable;
4976
4977 if (!bgp)
4978 return;
4979
4980 FOREACH_AFI_SAFI (afi, safi) {
4981 ntable = bgp->rib[afi][safi];
4982 if (!ntable)
4983 continue;
4984 if (table && table != ntable)
4985 continue;
4986
4987 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4988 npeer)) {
4989 if (peer && peer != npeer)
4990 continue;
4991 listnode_delete(ntable->soft_reconfig_peers, npeer);
4992 }
4993
4994 if (!ntable->soft_reconfig_peers
4995 || !list_isempty(ntable->soft_reconfig_peers))
4996 continue;
4997
4998 list_delete(&ntable->soft_reconfig_peers);
4999 bgp_soft_reconfig_table_flag(ntable, false);
5000 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
5001 }
5002}
5003
d62a17ae 5004void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5005{
9bcb3eef 5006 struct bgp_dest *dest;
d62a17ae 5007 struct bgp_table *table;
46aeabed
LS
5008 struct listnode *node, *nnode;
5009 struct peer *npeer;
5010 struct peer_af *paf;
718e3744 5011
feb17238 5012 if (!peer_established(peer))
d62a17ae 5013 return;
718e3744 5014
d62a17ae 5015 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
5016 && (safi != SAFI_EVPN)) {
5017 table = peer->bgp->rib[afi][safi];
5018 if (!table)
5019 return;
5020
5021 table->soft_reconfig_init = true;
5022
5023 if (!table->soft_reconfig_peers)
5024 table->soft_reconfig_peers = list_new();
5025 npeer = NULL;
5026 /* add peer to the table soft_reconfig_peers if not already
5027 * there
5028 */
5029 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
5030 npeer)) {
5031 if (peer == npeer)
5032 break;
5033 }
5034 if (peer != npeer)
5035 listnode_add(table->soft_reconfig_peers, peer);
5036
5037 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
5038 * on table would start back at the beginning.
5039 */
5040 bgp_soft_reconfig_table_flag(table, true);
5041
5042 if (!table->soft_reconfig_thread)
5043 thread_add_event(bm->master,
5044 bgp_soft_reconfig_table_task, table, 0,
5045 &table->soft_reconfig_thread);
5046 /* Cancel bgp_announce_route_timer_expired threads.
5047 * bgp_announce_route_timer_expired threads have been scheduled
5048 * to announce routes as soon as the soft_reconfigure process
5049 * finishes.
5050 * In this case, soft_reconfigure is also scheduled by using
5051 * a thread but is planned after the
5052 * bgp_announce_route_timer_expired threads. It means that,
5053 * without cancelling the threads, the route announcement task
5054 * would run before the soft reconfiguration one. That would
5055 * useless and would block vtysh during several seconds. Route
5056 * announcements are rescheduled as soon as the soft_reconfigure
5057 * process finishes.
5058 */
5059 paf = peer_af_find(peer, afi, safi);
5060 if (paf)
5061 bgp_stop_announce_route_timer(paf);
5062 } else
9bcb3eef
DS
5063 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5064 dest = bgp_route_next(dest)) {
5065 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5066
b54892e0
DS
5067 if (table == NULL)
5068 continue;
8692c506 5069
9bcb3eef 5070 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
5071 struct prefix_rd prd;
5072
5073 prd.family = AF_UNSPEC;
5074 prd.prefixlen = 64;
5075 memcpy(&prd.val, p->u.val, 8);
5076
5077 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 5078 }
718e3744 5079}
6b0655a2 5080
228da428 5081
d62a17ae 5082struct bgp_clear_node_queue {
9bcb3eef 5083 struct bgp_dest *dest;
228da428
CC
5084};
5085
d62a17ae 5086static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 5087{
d62a17ae 5088 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 5089 struct bgp_dest *dest = cnq->dest;
d62a17ae 5090 struct peer *peer = wq->spec.data;
40381db7 5091 struct bgp_path_info *pi;
3103e8d2 5092 struct bgp *bgp;
9bcb3eef
DS
5093 afi_t afi = bgp_dest_table(dest)->afi;
5094 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 5095
9bcb3eef 5096 assert(dest && peer);
3103e8d2 5097 bgp = peer->bgp;
d62a17ae 5098
5099 /* It is possible that we have multiple paths for a prefix from a peer
5100 * if that peer is using AddPath.
5101 */
9bcb3eef 5102 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 5103 if (pi->peer != peer)
ea47320b
DL
5104 continue;
5105
5106 /* graceful restart STALE flag set. */
9af52ccf
DA
5107 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
5108 && peer->nsf[afi][safi])
5109 || CHECK_FLAG(peer->af_sflags[afi][safi],
5110 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
5111 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5112 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 5113 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
5114 else {
5115 /* If this is an EVPN route, process for
5116 * un-import. */
5117 if (safi == SAFI_EVPN)
9bcb3eef
DS
5118 bgp_evpn_unimport_route(
5119 bgp, afi, safi,
5120 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5121 /* Handle withdraw for VRF route-leaking and L3VPN */
5122 if (SAFI_UNICAST == safi
5123 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5124 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5125 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5126 bgp, pi);
960035b2 5127 }
3103e8d2 5128 if (SAFI_MPLS_VPN == safi &&
960035b2 5129 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5130 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5131 }
3103e8d2 5132
9bcb3eef 5133 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5134 }
ea47320b 5135 }
d62a17ae 5136 return WQ_SUCCESS;
200df115 5137}
5138
d62a17ae 5139static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5140{
d62a17ae 5141 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5142 struct bgp_dest *dest = cnq->dest;
5143 struct bgp_table *table = bgp_dest_table(dest);
228da428 5144
9bcb3eef 5145 bgp_dest_unlock_node(dest);
d62a17ae 5146 bgp_table_unlock(table);
5147 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5148}
5149
d62a17ae 5150static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5151{
d62a17ae 5152 struct peer *peer = wq->spec.data;
64e580a7 5153
d62a17ae 5154 /* Tickle FSM to start moving again */
5155 BGP_EVENT_ADD(peer, Clearing_Completed);
5156
5157 peer_unlock(peer); /* bgp_clear_route */
200df115 5158}
718e3744 5159
d62a17ae 5160static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5161{
d62a17ae 5162 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5163
5164 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5165#undef CLEAR_QUEUE_NAME_LEN
5166
0ce1ca80 5167 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5168 peer->clear_node_queue->spec.hold = 10;
5169 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5170 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5171 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5172 peer->clear_node_queue->spec.max_retries = 0;
5173
5174 /* we only 'lock' this peer reference when the queue is actually active
5175 */
5176 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5177}
5178
d62a17ae 5179static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5180 struct bgp_table *table)
65ca75e0 5181{
9bcb3eef 5182 struct bgp_dest *dest;
b6c386bb 5183 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5184
d62a17ae 5185 if (!table)
5186 table = peer->bgp->rib[afi][safi];
dc83d712 5187
d62a17ae 5188 /* If still no table => afi/safi isn't configured at all or smth. */
5189 if (!table)
5190 return;
dc83d712 5191
9bcb3eef 5192 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5193 struct bgp_path_info *pi, *next;
d62a17ae 5194 struct bgp_adj_in *ain;
5195 struct bgp_adj_in *ain_next;
5196
5197 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5198 * queued for every clearing peer, regardless of whether it is
5199 * relevant to the peer at hand.
5200 *
5201 * Overview: There are 3 different indices which need to be
5202 * scrubbed, potentially, when a peer is removed:
5203 *
5204 * 1 peer's routes visible via the RIB (ie accepted routes)
5205 * 2 peer's routes visible by the (optional) peer's adj-in index
5206 * 3 other routes visible by the peer's adj-out index
5207 *
5208 * 3 there is no hurry in scrubbing, once the struct peer is
5209 * removed from bgp->peer, we could just GC such deleted peer's
5210 * adj-outs at our leisure.
5211 *
5212 * 1 and 2 must be 'scrubbed' in some way, at least made
5213 * invisible via RIB index before peer session is allowed to be
5214 * brought back up. So one needs to know when such a 'search' is
5215 * complete.
5216 *
5217 * Ideally:
5218 *
5219 * - there'd be a single global queue or a single RIB walker
5220 * - rather than tracking which route_nodes still need to be
5221 * examined on a peer basis, we'd track which peers still
5222 * aren't cleared
5223 *
5224 * Given that our per-peer prefix-counts now should be reliable,
5225 * this may actually be achievable. It doesn't seem to be a huge
5226 * problem at this time,
5227 *
5228 * It is possible that we have multiple paths for a prefix from
5229 * a peer
5230 * if that peer is using AddPath.
5231 */
9bcb3eef 5232 ain = dest->adj_in;
d62a17ae 5233 while (ain) {
5234 ain_next = ain->next;
5235
6a840fd9 5236 if (ain->peer == peer)
9bcb3eef 5237 bgp_adj_in_remove(dest, ain);
d62a17ae 5238
5239 ain = ain_next;
5240 }
5241
9bcb3eef 5242 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5243 next = pi->next;
5244 if (pi->peer != peer)
d62a17ae 5245 continue;
5246
5247 if (force)
9bcb3eef 5248 bgp_path_info_reap(dest, pi);
d62a17ae 5249 else {
5250 struct bgp_clear_node_queue *cnq;
5251
5252 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5253 bgp_table_lock(bgp_dest_table(dest));
5254 bgp_dest_lock_node(dest);
d62a17ae 5255 cnq = XCALLOC(
5256 MTYPE_BGP_CLEAR_NODE_QUEUE,
5257 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5258 cnq->dest = dest;
d62a17ae 5259 work_queue_add(peer->clear_node_queue, cnq);
5260 break;
5261 }
5262 }
5263 }
5264 return;
5265}
5266
5267void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5268{
9bcb3eef 5269 struct bgp_dest *dest;
d62a17ae 5270 struct bgp_table *table;
5271
5272 if (peer->clear_node_queue == NULL)
5273 bgp_clear_node_queue_init(peer);
5274
5275 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5276 * Idle until it receives a Clearing_Completed event. This protects
5277 * against peers which flap faster than we can we clear, which could
5278 * lead to:
5279 *
5280 * a) race with routes from the new session being installed before
5281 * clear_route_node visits the node (to delete the route of that
5282 * peer)
5283 * b) resource exhaustion, clear_route_node likely leads to an entry
5284 * on the process_main queue. Fast-flapping could cause that queue
5285 * to grow and grow.
5286 */
5287
5288 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5289 * the unlock will happen upon work-queue completion; other wise, the
5290 * unlock happens at the end of this function.
5291 */
5292 if (!peer->clear_node_queue->thread)
5293 peer_lock(peer);
5294
5295 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5296 bgp_clear_route_table(peer, afi, safi, NULL);
5297 else
9bcb3eef
DS
5298 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5299 dest = bgp_route_next(dest)) {
5300 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5301 if (!table)
5302 continue;
5303
5304 bgp_clear_route_table(peer, afi, safi, table);
5305 }
d62a17ae 5306
5307 /* unlock if no nodes got added to the clear-node-queue. */
5308 if (!peer->clear_node_queue->thread)
5309 peer_unlock(peer);
718e3744 5310}
d62a17ae 5311
5312void bgp_clear_route_all(struct peer *peer)
718e3744 5313{
d62a17ae 5314 afi_t afi;
5315 safi_t safi;
718e3744 5316
05c7a1cc
QY
5317 FOREACH_AFI_SAFI (afi, safi)
5318 bgp_clear_route(peer, afi, safi);
65efcfce 5319
49e5a4a0 5320#ifdef ENABLE_BGP_VNC
d62a17ae 5321 rfapiProcessPeerDown(peer);
65efcfce 5322#endif
718e3744 5323}
5324
d62a17ae 5325void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5326{
d62a17ae 5327 struct bgp_table *table;
9bcb3eef 5328 struct bgp_dest *dest;
d62a17ae 5329 struct bgp_adj_in *ain;
5330 struct bgp_adj_in *ain_next;
718e3744 5331
d62a17ae 5332 table = peer->bgp->rib[afi][safi];
718e3744 5333
d62a17ae 5334 /* It is possible that we have multiple paths for a prefix from a peer
5335 * if that peer is using AddPath.
5336 */
9bcb3eef
DS
5337 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5338 ain = dest->adj_in;
43143c8f 5339
d62a17ae 5340 while (ain) {
5341 ain_next = ain->next;
43143c8f 5342
6a840fd9 5343 if (ain->peer == peer)
9bcb3eef 5344 bgp_adj_in_remove(dest, ain);
43143c8f 5345
d62a17ae 5346 ain = ain_next;
5347 }
5348 }
718e3744 5349}
93406d87 5350
1479ed2f
DA
5351/* If any of the routes from the peer have been marked with the NO_LLGR
5352 * community, either as sent by the peer, or as the result of a configured
5353 * policy, they MUST NOT be retained, but MUST be removed as per the normal
5354 * operation of [RFC4271].
5355 */
d62a17ae 5356void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5357{
9bcb3eef 5358 struct bgp_dest *dest;
40381db7 5359 struct bgp_path_info *pi;
d62a17ae 5360 struct bgp_table *table;
5361
9af52ccf 5362 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5363 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5364 dest = bgp_route_next(dest)) {
5365 struct bgp_dest *rm;
d62a17ae 5366
5367 /* look for neighbor in tables */
9bcb3eef 5368 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5369 if (!table)
ea47320b
DL
5370 continue;
5371
5372 for (rm = bgp_table_top(table); rm;
5373 rm = bgp_route_next(rm))
9bcb3eef 5374 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5375 pi = pi->next) {
40381db7 5376 if (pi->peer != peer)
ea47320b 5377 continue;
1479ed2f
DA
5378 if (CHECK_FLAG(
5379 peer->af_sflags[afi][safi],
5380 PEER_STATUS_LLGR_WAIT) &&
5381 pi->attr->community &&
5382 !community_include(
5383 pi->attr->community,
5384 COMMUNITY_NO_LLGR))
5385 break;
40381db7 5386 if (!CHECK_FLAG(pi->flags,
1defdda8 5387 BGP_PATH_STALE))
ea47320b
DL
5388 break;
5389
641065d4
KM
5390 /*
5391 * If this is VRF leaked route
5392 * process for withdraw.
5393 */
5394 if (pi->sub_type ==
5395 BGP_ROUTE_IMPORTED &&
5396 peer->bgp->inst_type ==
5397 BGP_INSTANCE_TYPE_DEFAULT)
5398 vpn_leak_to_vrf_withdraw(
5399 peer->bgp, pi);
5400
40381db7 5401 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5402 break;
5403 }
d62a17ae 5404 }
5405 } else {
9bcb3eef
DS
5406 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5407 dest = bgp_route_next(dest))
5408 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5409 pi = pi->next) {
40381db7 5410 if (pi->peer != peer)
ea47320b 5411 continue;
1479ed2f
DA
5412 if (CHECK_FLAG(peer->af_sflags[afi][safi],
5413 PEER_STATUS_LLGR_WAIT) &&
5414 pi->attr->community &&
5415 !community_include(pi->attr->community,
5416 COMMUNITY_NO_LLGR))
5417 break;
40381db7 5418 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5419 break;
641065d4
KM
5420 if (safi == SAFI_UNICAST &&
5421 (peer->bgp->inst_type ==
5422 BGP_INSTANCE_TYPE_VRF ||
5423 peer->bgp->inst_type ==
5424 BGP_INSTANCE_TYPE_DEFAULT))
5425 vpn_leak_from_vrf_withdraw(
5426 bgp_get_default(), peer->bgp,
5427 pi);
5428
9bcb3eef 5429 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5430 break;
5431 }
d62a17ae 5432 }
93406d87 5433}
6b0655a2 5434
9af52ccf
DA
5435void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5436{
5437 struct bgp_dest *dest, *ndest;
5438 struct bgp_path_info *pi;
5439 struct bgp_table *table;
5440
5441 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5442 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5443 dest = bgp_route_next(dest)) {
5444 table = bgp_dest_get_bgp_table_info(dest);
5445 if (!table)
5446 continue;
5447
5448 for (ndest = bgp_table_top(table); ndest;
5449 ndest = bgp_route_next(ndest)) {
5450 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5451 pi = pi->next) {
5452 if (pi->peer != peer)
5453 continue;
5454
5455 if ((CHECK_FLAG(
5456 peer->af_sflags[afi][safi],
5457 PEER_STATUS_ENHANCED_REFRESH))
5458 && !CHECK_FLAG(pi->flags,
5459 BGP_PATH_STALE)
5460 && !CHECK_FLAG(
5461 pi->flags,
5462 BGP_PATH_UNUSEABLE)) {
5463 if (bgp_debug_neighbor_events(
5464 peer))
5465 zlog_debug(
5466 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5467 peer->host,
5468 afi2str(afi),
5469 safi2str(safi),
5470 bgp_dest_get_prefix(
5471 ndest));
5472
5473 bgp_path_info_set_flag(
5474 ndest, pi,
5475 BGP_PATH_STALE);
5476 }
5477 }
5478 }
5479 }
5480 } else {
5481 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5482 dest = bgp_route_next(dest)) {
5483 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5484 pi = pi->next) {
5485 if (pi->peer != peer)
5486 continue;
5487
5488 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5489 PEER_STATUS_ENHANCED_REFRESH))
5490 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5491 && !CHECK_FLAG(pi->flags,
5492 BGP_PATH_UNUSEABLE)) {
5493 if (bgp_debug_neighbor_events(peer))
5494 zlog_debug(
5495 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5496 peer->host,
5497 afi2str(afi),
5498 safi2str(safi),
5499 bgp_dest_get_prefix(
5500 dest));
5501
5502 bgp_path_info_set_flag(dest, pi,
5503 BGP_PATH_STALE);
5504 }
5505 }
5506 }
5507 }
5508}
5509
3dc339cd 5510bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5511{
e0df4c04 5512 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5513 return true;
e0df4c04 5514
9dac9fc8
DA
5515 if (peer->sort == BGP_PEER_EBGP
5516 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5517 || FILTER_LIST_OUT_NAME(filter)
5518 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5519 return true;
5520 return false;
9dac9fc8
DA
5521}
5522
3dc339cd 5523bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5524{
e0df4c04 5525 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5526 return true;
e0df4c04 5527
9dac9fc8
DA
5528 if (peer->sort == BGP_PEER_EBGP
5529 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5530 || FILTER_LIST_IN_NAME(filter)
5531 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5532 return true;
5533 return false;
9dac9fc8
DA
5534}
5535
568e10ca 5536static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5537 safi_t safi)
bb86c601 5538{
9bcb3eef 5539 struct bgp_dest *dest;
40381db7 5540 struct bgp_path_info *pi;
4b7e6066 5541 struct bgp_path_info *next;
bb86c601 5542
9bcb3eef
DS
5543 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5544 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5545 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5546
40381db7 5547 next = pi->next;
1b7bb747
CS
5548
5549 /* Unimport EVPN routes from VRFs */
5550 if (safi == SAFI_EVPN)
5551 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5552 SAFI_EVPN, p, pi);
1b7bb747 5553
40381db7
DS
5554 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5555 && pi->type == ZEBRA_ROUTE_BGP
5556 && (pi->sub_type == BGP_ROUTE_NORMAL
5557 || pi->sub_type == BGP_ROUTE_AGGREGATE
5558 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5559
d62a17ae 5560 if (bgp_fibupd_safi(safi))
b54892e0 5561 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5562 }
9514b37d 5563
9bcb3eef 5564 bgp_path_info_reap(dest, pi);
d62a17ae 5565 }
bb86c601
LB
5566}
5567
718e3744 5568/* Delete all kernel routes. */
d62a17ae 5569void bgp_cleanup_routes(struct bgp *bgp)
5570{
5571 afi_t afi;
9bcb3eef 5572 struct bgp_dest *dest;
67009e22 5573 struct bgp_table *table;
d62a17ae 5574
5575 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5576 if (afi == AFI_L2VPN)
5577 continue;
568e10ca 5578 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5579 SAFI_UNICAST);
d62a17ae 5580 /*
5581 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5582 */
5583 if (afi != AFI_L2VPN) {
5584 safi_t safi;
5585 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5586 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5587 dest = bgp_route_next(dest)) {
5588 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5589 if (table != NULL) {
5590 bgp_cleanup_table(bgp, table, safi);
5591 bgp_table_finish(&table);
9bcb3eef
DS
5592 bgp_dest_set_bgp_table_info(dest, NULL);
5593 bgp_dest_unlock_node(dest);
d62a17ae 5594 }
5595 }
5596 safi = SAFI_ENCAP;
9bcb3eef
DS
5597 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5598 dest = bgp_route_next(dest)) {
5599 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5600 if (table != NULL) {
5601 bgp_cleanup_table(bgp, table, safi);
5602 bgp_table_finish(&table);
9bcb3eef
DS
5603 bgp_dest_set_bgp_table_info(dest, NULL);
5604 bgp_dest_unlock_node(dest);
d62a17ae 5605 }
5606 }
5607 }
5608 }
9bcb3eef
DS
5609 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5610 dest = bgp_route_next(dest)) {
5611 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5612 if (table != NULL) {
5613 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5614 bgp_table_finish(&table);
9bcb3eef
DS
5615 bgp_dest_set_bgp_table_info(dest, NULL);
5616 bgp_dest_unlock_node(dest);
d62a17ae 5617 }
bb86c601 5618 }
718e3744 5619}
5620
d62a17ae 5621void bgp_reset(void)
718e3744 5622{
d62a17ae 5623 vty_reset();
5624 bgp_zclient_reset();
5625 access_list_reset();
5626 prefix_list_reset();
718e3744 5627}
6b0655a2 5628
be92fc9f 5629bool bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5630{
d62a17ae 5631 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5632 && CHECK_FLAG(peer->af_cap[afi][safi],
5633 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5634}
5635
718e3744 5636/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5637 value. */
d62a17ae 5638int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5639 struct bgp_nlri *packet)
5640{
d7c0a89a
QY
5641 uint8_t *pnt;
5642 uint8_t *lim;
d62a17ae 5643 struct prefix p;
5644 int psize;
5645 int ret;
5646 afi_t afi;
5647 safi_t safi;
be92fc9f 5648 bool addpath_capable;
d7c0a89a 5649 uint32_t addpath_id;
d62a17ae 5650
d62a17ae 5651 pnt = packet->nlri;
5652 lim = pnt + packet->length;
5653 afi = packet->afi;
5654 safi = packet->safi;
5655 addpath_id = 0;
be92fc9f 5656 addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
d62a17ae 5657
5658 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5659 syntactic validity. If the field is syntactically incorrect,
5660 then the Error Subcode is set to Invalid Network Field. */
5661 for (; pnt < lim; pnt += psize) {
5662 /* Clear prefix structure. */
5663 memset(&p, 0, sizeof(struct prefix));
5664
be92fc9f 5665 if (addpath_capable) {
d62a17ae 5666
5667 /* When packet overflow occurs return immediately. */
761ed665 5668 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5669 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5670
a3a850a1 5671 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5672 addpath_id = ntohl(addpath_id);
d62a17ae 5673 pnt += BGP_ADDPATH_ID_LEN;
5674 }
718e3744 5675
d62a17ae 5676 /* Fetch prefix length. */
5677 p.prefixlen = *pnt++;
5678 /* afi/safi validity already verified by caller,
5679 * bgp_update_receive */
5680 p.family = afi2family(afi);
5681
5682 /* Prefix length check. */
5683 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5684 flog_err(
e50f7cfd 5685 EC_BGP_UPDATE_RCV,
14454c9f 5686 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5687 peer->host, p.prefixlen, packet->afi);
513386b5 5688 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5689 }
6b0655a2 5690
d62a17ae 5691 /* Packet size overflow check. */
5692 psize = PSIZE(p.prefixlen);
5693
5694 /* When packet overflow occur return immediately. */
5695 if (pnt + psize > lim) {
af4c2728 5696 flog_err(
e50f7cfd 5697 EC_BGP_UPDATE_RCV,
d62a17ae 5698 "%s [Error] Update packet error (prefix length %d overflows packet)",
5699 peer->host, p.prefixlen);
513386b5 5700 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5701 }
5702
5703 /* Defensive coding, double-check the psize fits in a struct
5704 * prefix */
5705 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5706 flog_err(
e50f7cfd 5707 EC_BGP_UPDATE_RCV,
d62a17ae 5708 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5709 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5710 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5711 }
5712
5713 /* Fetch prefix from NLRI packet. */
a85297a7 5714 memcpy(p.u.val, pnt, psize);
d62a17ae 5715
5716 /* Check address. */
5717 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5718 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5719 /* From RFC4271 Section 6.3:
5720 *
5721 * If a prefix in the NLRI field is semantically
5722 * incorrect
5723 * (e.g., an unexpected multicast IP address),
5724 * an error SHOULD
5725 * be logged locally, and the prefix SHOULD be
5726 * ignored.
a4d82a8a 5727 */
af4c2728 5728 flog_err(
e50f7cfd 5729 EC_BGP_UPDATE_RCV,
23d0a753
DA
5730 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5731 peer->host, &p.u.prefix4);
d62a17ae 5732 continue;
5733 }
5734 }
5735
5736 /* Check address. */
5737 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5738 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5739 flog_err(
e50f7cfd 5740 EC_BGP_UPDATE_RCV,
c0d72166
DS
5741 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5742 peer->host, &p.u.prefix6);
d62a17ae 5743
5744 continue;
5745 }
5746 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5747 flog_err(
e50f7cfd 5748 EC_BGP_UPDATE_RCV,
c0d72166
DS
5749 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5750 peer->host, &p.u.prefix6);
d62a17ae 5751
5752 continue;
5753 }
5754 }
5755
5756 /* Normal process. */
5757 if (attr)
5758 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5759 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5760 NULL, NULL, 0, 0, NULL);
d62a17ae 5761 else
5762 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5763 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5764 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5765 NULL);
d62a17ae 5766
513386b5
DA
5767 /* Do not send BGP notification twice when maximum-prefix count
5768 * overflow. */
5769 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5770 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5771
5772 /* Address family configuration mismatch. */
d62a17ae 5773 if (ret < 0)
513386b5 5774 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5775 }
5776
5777 /* Packet length consistency check. */
5778 if (pnt != lim) {
af4c2728 5779 flog_err(
e50f7cfd 5780 EC_BGP_UPDATE_RCV,
d62a17ae 5781 "%s [Error] Update packet error (prefix length mismatch with total length)",
5782 peer->host);
513386b5 5783 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5784 }
6b0655a2 5785
513386b5 5786 return BGP_NLRI_PARSE_OK;
718e3744 5787}
5788
d62a17ae 5789static struct bgp_static *bgp_static_new(void)
718e3744 5790{
d62a17ae 5791 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5792}
5793
d62a17ae 5794static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5795{
0a22ddfb 5796 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5797 route_map_counter_decrement(bgp_static->rmap.map);
5798
0a22ddfb 5799 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5800 XFREE(MTYPE_BGP_STATIC, bgp_static);
5801}
5802
5f040085 5803void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5804 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5805{
9bcb3eef 5806 struct bgp_dest *dest;
40381db7 5807 struct bgp_path_info *pi;
4b7e6066 5808 struct bgp_path_info *new;
40381db7 5809 struct bgp_path_info rmap_path;
d62a17ae 5810 struct attr attr;
5811 struct attr *attr_new;
b68885f9 5812 route_map_result_t ret;
49e5a4a0 5813#ifdef ENABLE_BGP_VNC
d62a17ae 5814 int vnc_implicit_withdraw = 0;
65efcfce 5815#endif
fee0f4c6 5816
d62a17ae 5817 assert(bgp_static);
dd8103a9 5818
9bcb3eef 5819 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5820
d62a17ae 5821 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5822
d62a17ae 5823 attr.nexthop = bgp_static->igpnexthop;
5824 attr.med = bgp_static->igpmetric;
5825 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5826
d62a17ae 5827 if (bgp_static->atomic)
5828 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5829
d62a17ae 5830 /* Store label index, if required. */
5831 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5832 attr.label_index = bgp_static->label_index;
5833 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5834 }
718e3744 5835
d62a17ae 5836 /* Apply route-map. */
5837 if (bgp_static->rmap.name) {
5838 struct attr attr_tmp = attr;
80ced710 5839
40381db7
DS
5840 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5841 rmap_path.peer = bgp->peer_self;
5842 rmap_path.attr = &attr_tmp;
fee0f4c6 5843
d62a17ae 5844 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5845
1782514f 5846 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5847
d62a17ae 5848 bgp->peer_self->rmap_type = 0;
718e3744 5849
d62a17ae 5850 if (ret == RMAP_DENYMATCH) {
5851 /* Free uninterned attribute. */
5852 bgp_attr_flush(&attr_tmp);
718e3744 5853
d62a17ae 5854 /* Unintern original. */
5855 aspath_unintern(&attr.aspath);
5856 bgp_static_withdraw(bgp, p, afi, safi);
5857 return;
5858 }
7f323236 5859
637e5ba4 5860 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5861 bgp_attr_add_gshut_community(&attr_tmp);
5862
d62a17ae 5863 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5864 } else {
5865
637e5ba4 5866 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5867 bgp_attr_add_gshut_community(&attr);
5868
d62a17ae 5869 attr_new = bgp_attr_intern(&attr);
7f323236 5870 }
718e3744 5871
9bcb3eef 5872 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5873 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5874 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5875 break;
5876
40381db7
DS
5877 if (pi) {
5878 if (attrhash_cmp(pi->attr, attr_new)
5879 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5880 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5881 bgp_dest_unlock_node(dest);
d62a17ae 5882 bgp_attr_unintern(&attr_new);
5883 aspath_unintern(&attr.aspath);
5884 return;
5885 } else {
5886 /* The attribute is changed. */
9bcb3eef 5887 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5888
5889 /* Rewrite BGP route information. */
40381db7 5890 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5891 bgp_path_info_restore(dest, pi);
d62a17ae 5892 else
40381db7 5893 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5894#ifdef ENABLE_BGP_VNC
d62a17ae 5895 if ((afi == AFI_IP || afi == AFI_IP6)
5896 && (safi == SAFI_UNICAST)) {
40381db7 5897 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5898 /*
5899 * Implicit withdraw case.
40381db7 5900 * We have to do this before pi is
d62a17ae 5901 * changed
5902 */
5903 ++vnc_implicit_withdraw;
40381db7 5904 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5905 vnc_import_bgp_exterior_del_route(
40381db7 5906 bgp, p, pi);
d62a17ae 5907 }
5908 }
65efcfce 5909#endif
40381db7
DS
5910 bgp_attr_unintern(&pi->attr);
5911 pi->attr = attr_new;
5912 pi->uptime = bgp_clock();
49e5a4a0 5913#ifdef ENABLE_BGP_VNC
d62a17ae 5914 if ((afi == AFI_IP || afi == AFI_IP6)
5915 && (safi == SAFI_UNICAST)) {
5916 if (vnc_implicit_withdraw) {
40381db7 5917 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5918 vnc_import_bgp_exterior_add_route(
40381db7 5919 bgp, p, pi);
d62a17ae 5920 }
5921 }
65efcfce 5922#endif
718e3744 5923
d62a17ae 5924 /* Nexthop reachability check. */
892fedb6 5925 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5926 && (safi == SAFI_UNICAST
5927 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5928
5929 struct bgp *bgp_nexthop = bgp;
5930
40381db7
DS
5931 if (pi->extra && pi->extra->bgp_orig)
5932 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5933
5934 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5935 afi, safi, pi, NULL,
654a5978 5936 0, p))
9bcb3eef 5937 bgp_path_info_set_flag(dest, pi,
18ee8310 5938 BGP_PATH_VALID);
d62a17ae 5939 else {
5940 if (BGP_DEBUG(nht, NHT)) {
5941 char buf1[INET6_ADDRSTRLEN];
5942 inet_ntop(p->family,
5943 &p->u.prefix, buf1,
5944 INET6_ADDRSTRLEN);
5945 zlog_debug(
5946 "%s(%s): Route not in table, not advertising",
15569c58 5947 __func__, buf1);
d62a17ae 5948 }
18ee8310 5949 bgp_path_info_unset_flag(
9bcb3eef 5950 dest, pi, BGP_PATH_VALID);
d62a17ae 5951 }
5952 } else {
5953 /* Delete the NHT structure if any, if we're
5954 * toggling between
5955 * enabling/disabling import check. We
5956 * deregister the route
5957 * from NHT to avoid overloading NHT and the
5958 * process interaction
5959 */
40381db7 5960 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5961 bgp_path_info_set_flag(dest, pi,
5962 BGP_PATH_VALID);
d62a17ae 5963 }
5964 /* Process change. */
40381db7 5965 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5966 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5967
5968 if (SAFI_UNICAST == safi
5969 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5970 || bgp->inst_type
5971 == BGP_INSTANCE_TYPE_DEFAULT)) {
5972 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5973 pi);
ddb5b488
PZ
5974 }
5975
9bcb3eef 5976 bgp_dest_unlock_node(dest);
d62a17ae 5977 aspath_unintern(&attr.aspath);
5978 return;
5979 }
718e3744 5980 }
718e3744 5981
d62a17ae 5982 /* Make new BGP info. */
5983 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5984 attr_new, dest);
d62a17ae 5985 /* Nexthop reachability check. */
892fedb6 5986 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5987 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5988 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5989 p))
9bcb3eef 5990 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5991 else {
5992 if (BGP_DEBUG(nht, NHT)) {
5993 char buf1[INET6_ADDRSTRLEN];
5994 inet_ntop(p->family, &p->u.prefix, buf1,
5995 INET6_ADDRSTRLEN);
5996 zlog_debug(
5997 "%s(%s): Route not in table, not advertising",
15569c58 5998 __func__, buf1);
d62a17ae 5999 }
9bcb3eef 6000 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 6001 }
6002 } else {
6003 /* Delete the NHT structure if any, if we're toggling between
6004 * enabling/disabling import check. We deregister the route
6005 * from NHT to avoid overloading NHT and the process interaction
6006 */
6007 bgp_unlink_nexthop(new);
6008
9bcb3eef 6009 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 6010 }
078430f6 6011
d62a17ae 6012 /* Aggregate address increment. */
6013 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 6014
d62a17ae 6015 /* Register new BGP information. */
9bcb3eef 6016 bgp_path_info_add(dest, new);
718e3744 6017
d62a17ae 6018 /* route_node_get lock */
9bcb3eef 6019 bgp_dest_unlock_node(dest);
d62a17ae 6020
6021 /* Process change. */
9bcb3eef 6022 bgp_process(bgp, dest, afi, safi);
d62a17ae 6023
ddb5b488
PZ
6024 if (SAFI_UNICAST == safi
6025 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6026 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
6027 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
6028 }
6029
d62a17ae 6030 /* Unintern original. */
6031 aspath_unintern(&attr.aspath);
718e3744 6032}
6033
5f040085 6034void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 6035 safi_t safi)
718e3744 6036{
9bcb3eef 6037 struct bgp_dest *dest;
40381db7 6038 struct bgp_path_info *pi;
718e3744 6039
9bcb3eef 6040 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 6041
d62a17ae 6042 /* Check selected route and self inserted route. */
9bcb3eef 6043 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6044 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6045 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6046 break;
6047
6048 /* Withdraw static BGP route from routing table. */
40381db7 6049 if (pi) {
ddb5b488
PZ
6050 if (SAFI_UNICAST == safi
6051 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
6052 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 6053 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 6054 }
40381db7
DS
6055 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6056 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6057 bgp_path_info_delete(dest, pi);
6058 bgp_process(bgp, dest, afi, safi);
d62a17ae 6059 }
718e3744 6060
d62a17ae 6061 /* Unlock bgp_node_lookup. */
9bcb3eef 6062 bgp_dest_unlock_node(dest);
718e3744 6063}
6064
137446f9
LB
6065/*
6066 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
6067 */
5f040085 6068static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6069 afi_t afi, safi_t safi,
6070 struct prefix_rd *prd)
718e3744 6071{
9bcb3eef 6072 struct bgp_dest *dest;
40381db7 6073 struct bgp_path_info *pi;
718e3744 6074
9bcb3eef 6075 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 6076
d62a17ae 6077 /* Check selected route and self inserted route. */
9bcb3eef 6078 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6079 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6080 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6081 break;
718e3744 6082
d62a17ae 6083 /* Withdraw static BGP route from routing table. */
40381db7 6084 if (pi) {
49e5a4a0 6085#ifdef ENABLE_BGP_VNC
d62a17ae 6086 rfapiProcessWithdraw(
40381db7 6087 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 6088 1); /* Kill, since it is an administrative change */
65efcfce 6089#endif
ddb5b488
PZ
6090 if (SAFI_MPLS_VPN == safi
6091 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6092 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 6093 }
40381db7 6094 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
6095 bgp_path_info_delete(dest, pi);
6096 bgp_process(bgp, dest, afi, safi);
d62a17ae 6097 }
718e3744 6098
d62a17ae 6099 /* Unlock bgp_node_lookup. */
9bcb3eef 6100 bgp_dest_unlock_node(dest);
718e3744 6101}
6102
5f040085 6103static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 6104 struct bgp_static *bgp_static, afi_t afi,
6105 safi_t safi)
137446f9 6106{
9bcb3eef 6107 struct bgp_dest *dest;
4b7e6066 6108 struct bgp_path_info *new;
d62a17ae 6109 struct attr *attr_new;
6110 struct attr attr = {0};
40381db7 6111 struct bgp_path_info *pi;
49e5a4a0 6112#ifdef ENABLE_BGP_VNC
d62a17ae 6113 mpls_label_t label = 0;
65efcfce 6114#endif
d7c0a89a 6115 uint32_t num_labels = 0;
137446f9 6116
d62a17ae 6117 assert(bgp_static);
137446f9 6118
b57ba6d2
MK
6119 if (bgp_static->label != MPLS_INVALID_LABEL)
6120 num_labels = 1;
9bcb3eef
DS
6121 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
6122 &bgp_static->prd);
137446f9 6123
d62a17ae 6124 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 6125
d62a17ae 6126 attr.nexthop = bgp_static->igpnexthop;
6127 attr.med = bgp_static->igpmetric;
6128 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 6129
d62a17ae 6130 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
6131 || (safi == SAFI_ENCAP)) {
6132 if (afi == AFI_IP) {
6133 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
6134 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
6135 }
6136 }
6137 if (afi == AFI_L2VPN) {
b04c1e99
IR
6138 if (bgp_static->gatewayIp.family == AF_INET) {
6139 SET_IPADDR_V4(&attr.evpn_overlay.gw_ip);
6140 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4,
860e740b
IR
6141 &bgp_static->gatewayIp.u.prefix4,
6142 IPV4_MAX_BYTELEN);
b04c1e99
IR
6143 } else if (bgp_static->gatewayIp.family == AF_INET6) {
6144 SET_IPADDR_V6(&attr.evpn_overlay.gw_ip);
6145 memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6,
860e740b
IR
6146 &bgp_static->gatewayIp.u.prefix6,
6147 IPV6_MAX_BYTELEN);
b04c1e99 6148 }
0a50c248 6149 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 6150 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
6151 struct bgp_encap_type_vxlan bet;
6152 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 6153 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 6154 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
6155 }
6156 if (bgp_static->router_mac) {
6157 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
6158 }
6159 }
6160 /* Apply route-map. */
6161 if (bgp_static->rmap.name) {
6162 struct attr attr_tmp = attr;
40381db7 6163 struct bgp_path_info rmap_path;
b68885f9 6164 route_map_result_t ret;
137446f9 6165
40381db7
DS
6166 rmap_path.peer = bgp->peer_self;
6167 rmap_path.attr = &attr_tmp;
137446f9 6168
d62a17ae 6169 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6170
1782514f 6171 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6172
d62a17ae 6173 bgp->peer_self->rmap_type = 0;
137446f9 6174
d62a17ae 6175 if (ret == RMAP_DENYMATCH) {
6176 /* Free uninterned attribute. */
6177 bgp_attr_flush(&attr_tmp);
137446f9 6178
d62a17ae 6179 /* Unintern original. */
6180 aspath_unintern(&attr.aspath);
6181 bgp_static_withdraw_safi(bgp, p, afi, safi,
6182 &bgp_static->prd);
6183 return;
6184 }
137446f9 6185
d62a17ae 6186 attr_new = bgp_attr_intern(&attr_tmp);
6187 } else {
6188 attr_new = bgp_attr_intern(&attr);
6189 }
137446f9 6190
9bcb3eef 6191 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6192 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6193 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6194 break;
6195
40381db7 6196 if (pi) {
40381db7 6197 if (attrhash_cmp(pi->attr, attr_new)
40381db7 6198 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6199 bgp_dest_unlock_node(dest);
d62a17ae 6200 bgp_attr_unintern(&attr_new);
6201 aspath_unintern(&attr.aspath);
6202 return;
6203 } else {
6204 /* The attribute is changed. */
9bcb3eef 6205 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6206
6207 /* Rewrite BGP route information. */
40381db7 6208 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6209 bgp_path_info_restore(dest, pi);
d62a17ae 6210 else
40381db7
DS
6211 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6212 bgp_attr_unintern(&pi->attr);
6213 pi->attr = attr_new;
6214 pi->uptime = bgp_clock();
49e5a4a0 6215#ifdef ENABLE_BGP_VNC
40381db7
DS
6216 if (pi->extra)
6217 label = decode_label(&pi->extra->label[0]);
65efcfce 6218#endif
137446f9 6219
d62a17ae 6220 /* Process change. */
40381db7 6221 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6222 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6223
6224 if (SAFI_MPLS_VPN == safi
6225 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6226 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6227 }
49e5a4a0 6228#ifdef ENABLE_BGP_VNC
40381db7
DS
6229 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6230 pi->attr, afi, safi, pi->type,
6231 pi->sub_type, &label);
65efcfce 6232#endif
9bcb3eef 6233 bgp_dest_unlock_node(dest);
d62a17ae 6234 aspath_unintern(&attr.aspath);
6235 return;
6236 }
6237 }
137446f9
LB
6238
6239
d62a17ae 6240 /* Make new BGP info. */
6241 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6242 attr_new, dest);
1defdda8 6243 SET_FLAG(new->flags, BGP_PATH_VALID);
53d3a0a8 6244 bgp_path_info_extra_get(new);
b57ba6d2
MK
6245 if (num_labels) {
6246 new->extra->label[0] = bgp_static->label;
6247 new->extra->num_labels = num_labels;
6248 }
49e5a4a0 6249#ifdef ENABLE_BGP_VNC
d62a17ae 6250 label = decode_label(&bgp_static->label);
65efcfce 6251#endif
137446f9 6252
d62a17ae 6253 /* Aggregate address increment. */
6254 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6255
d62a17ae 6256 /* Register new BGP information. */
9bcb3eef 6257 bgp_path_info_add(dest, new);
d62a17ae 6258 /* route_node_get lock */
9bcb3eef 6259 bgp_dest_unlock_node(dest);
137446f9 6260
d62a17ae 6261 /* Process change. */
9bcb3eef 6262 bgp_process(bgp, dest, afi, safi);
137446f9 6263
ddb5b488
PZ
6264 if (SAFI_MPLS_VPN == safi
6265 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6266 vpn_leak_to_vrf_update(bgp, new);
6267 }
49e5a4a0 6268#ifdef ENABLE_BGP_VNC
d62a17ae 6269 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6270 safi, new->type, new->sub_type, &label);
65efcfce
LB
6271#endif
6272
d62a17ae 6273 /* Unintern original. */
6274 aspath_unintern(&attr.aspath);
137446f9
LB
6275}
6276
718e3744 6277/* Configure static BGP network. When user don't run zebra, static
6278 route should be installed as valid. */
585f1adc
IR
6279static int bgp_static_set(struct vty *vty, const char *negate,
6280 const char *ip_str, afi_t afi, safi_t safi,
6281 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6282{
585f1adc
IR
6283 VTY_DECLVAR_CONTEXT(bgp, bgp);
6284 int ret;
d62a17ae 6285 struct prefix p;
6286 struct bgp_static *bgp_static;
9bcb3eef 6287 struct bgp_dest *dest;
d7c0a89a 6288 uint8_t need_update = 0;
d62a17ae 6289
585f1adc
IR
6290 /* Convert IP prefix string to struct prefix. */
6291 ret = str2prefix(ip_str, &p);
6292 if (!ret) {
6293 vty_out(vty, "%% Malformed prefix\n");
6294 return CMD_WARNING_CONFIG_FAILED;
6295 }
6296 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6297 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6298 return CMD_WARNING_CONFIG_FAILED;
6299 }
6300
d62a17ae 6301 apply_mask(&p);
718e3744 6302
e2a86ad9 6303 if (negate) {
718e3744 6304
e2a86ad9 6305 /* Set BGP static route configuration. */
9bcb3eef 6306 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6307
9bcb3eef 6308 if (!dest) {
585f1adc
IR
6309 vty_out(vty, "%% Can't find static route specified\n");
6310 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6311 }
6312
9bcb3eef 6313 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6314
e2a86ad9
DS
6315 if ((label_index != BGP_INVALID_LABEL_INDEX)
6316 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6317 vty_out(vty,
6318 "%% label-index doesn't match static route\n");
70d9b134 6319 bgp_dest_unlock_node(dest);
585f1adc 6320 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6321 }
d62a17ae 6322
e2a86ad9
DS
6323 if ((rmap && bgp_static->rmap.name)
6324 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6325 vty_out(vty,
6326 "%% route-map name doesn't match static route\n");
70d9b134 6327 bgp_dest_unlock_node(dest);
585f1adc 6328 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6329 }
718e3744 6330
e2a86ad9
DS
6331 /* Update BGP RIB. */
6332 if (!bgp_static->backdoor)
6333 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6334
e2a86ad9
DS
6335 /* Clear configuration. */
6336 bgp_static_free(bgp_static);
9bcb3eef
DS
6337 bgp_dest_set_bgp_static_info(dest, NULL);
6338 bgp_dest_unlock_node(dest);
6339 bgp_dest_unlock_node(dest);
e2a86ad9 6340 } else {
718e3744 6341
e2a86ad9 6342 /* Set BGP static route configuration. */
9bcb3eef
DS
6343 dest = bgp_node_get(bgp->route[afi][safi], &p);
6344 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6345 if (bgp_static) {
e2a86ad9 6346 /* Configuration change. */
e2a86ad9
DS
6347 /* Label index cannot be changed. */
6348 if (bgp_static->label_index != label_index) {
585f1adc
IR
6349 vty_out(vty, "%% cannot change label-index\n");
6350 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6351 }
d62a17ae 6352
e2a86ad9 6353 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6354 if (bgp_static->valid
6355 && bgp_static->backdoor != backdoor)
e2a86ad9 6356 need_update = 1;
718e3744 6357
e2a86ad9 6358 bgp_static->backdoor = backdoor;
718e3744 6359
e2a86ad9 6360 if (rmap) {
0a22ddfb
QY
6361 XFREE(MTYPE_ROUTE_MAP_NAME,
6362 bgp_static->rmap.name);
b4897fa5 6363 route_map_counter_decrement(
6364 bgp_static->rmap.map);
e2a86ad9
DS
6365 bgp_static->rmap.name =
6366 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6367 bgp_static->rmap.map =
6368 route_map_lookup_by_name(rmap);
b4897fa5 6369 route_map_counter_increment(
6370 bgp_static->rmap.map);
e2a86ad9 6371 } else {
0a22ddfb
QY
6372 XFREE(MTYPE_ROUTE_MAP_NAME,
6373 bgp_static->rmap.name);
b4897fa5 6374 route_map_counter_decrement(
6375 bgp_static->rmap.map);
e2a86ad9
DS
6376 bgp_static->rmap.map = NULL;
6377 bgp_static->valid = 0;
6378 }
9bcb3eef 6379 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6380 } else {
6381 /* New configuration. */
6382 bgp_static = bgp_static_new();
6383 bgp_static->backdoor = backdoor;
6384 bgp_static->valid = 0;
6385 bgp_static->igpmetric = 0;
975a328e 6386 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6387 bgp_static->label_index = label_index;
718e3744 6388
e2a86ad9 6389 if (rmap) {
0a22ddfb
QY
6390 XFREE(MTYPE_ROUTE_MAP_NAME,
6391 bgp_static->rmap.name);
b4897fa5 6392 route_map_counter_decrement(
6393 bgp_static->rmap.map);
e2a86ad9
DS
6394 bgp_static->rmap.name =
6395 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6396 bgp_static->rmap.map =
6397 route_map_lookup_by_name(rmap);
b4897fa5 6398 route_map_counter_increment(
6399 bgp_static->rmap.map);
e2a86ad9 6400 }
9bcb3eef 6401 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6402 }
d62a17ae 6403
e2a86ad9
DS
6404 bgp_static->valid = 1;
6405 if (need_update)
6406 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6407
e2a86ad9
DS
6408 if (!bgp_static->backdoor)
6409 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6410 }
d62a17ae 6411
585f1adc 6412 return CMD_SUCCESS;
d62a17ae 6413}
6414
6415void bgp_static_add(struct bgp *bgp)
6416{
6417 afi_t afi;
6418 safi_t safi;
9bcb3eef
DS
6419 struct bgp_dest *dest;
6420 struct bgp_dest *rm;
d62a17ae 6421 struct bgp_table *table;
6422 struct bgp_static *bgp_static;
6423
47fc6261 6424 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6425 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6426 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6427 dest = bgp_route_next(dest)) {
6428 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6429 continue;
ea47320b 6430
05c7a1cc
QY
6431 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6432 || (safi == SAFI_EVPN)) {
9bcb3eef 6433 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6434
6435 for (rm = bgp_table_top(table); rm;
6436 rm = bgp_route_next(rm)) {
a78beeb5 6437 bgp_static =
9bcb3eef 6438 bgp_dest_get_bgp_static_info(
5a8ba9fc 6439 rm);
9bcb3eef
DS
6440 bgp_static_update_safi(
6441 bgp, bgp_dest_get_prefix(rm),
6442 bgp_static, afi, safi);
d62a17ae 6443 }
05c7a1cc 6444 } else {
5a8ba9fc 6445 bgp_static_update(
9bcb3eef
DS
6446 bgp, bgp_dest_get_prefix(dest),
6447 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6448 safi);
ea47320b 6449 }
05c7a1cc 6450 }
47fc6261 6451 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6452}
6453
718e3744 6454/* Called from bgp_delete(). Delete all static routes from the BGP
6455 instance. */
d62a17ae 6456void bgp_static_delete(struct bgp *bgp)
6457{
6458 afi_t afi;
6459 safi_t safi;
9bcb3eef
DS
6460 struct bgp_dest *dest;
6461 struct bgp_dest *rm;
d62a17ae 6462 struct bgp_table *table;
6463 struct bgp_static *bgp_static;
6464
05c7a1cc 6465 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6466 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6467 dest = bgp_route_next(dest)) {
6468 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6469 continue;
ea47320b 6470
05c7a1cc
QY
6471 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6472 || (safi == SAFI_EVPN)) {
9bcb3eef 6473 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6474
6475 for (rm = bgp_table_top(table); rm;
6476 rm = bgp_route_next(rm)) {
a78beeb5 6477 bgp_static =
9bcb3eef 6478 bgp_dest_get_bgp_static_info(
5a8ba9fc 6479 rm);
c7d14ba6
PG
6480 if (!bgp_static)
6481 continue;
6482
05c7a1cc 6483 bgp_static_withdraw_safi(
9bcb3eef 6484 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6485 AFI_IP, safi,
6486 (struct prefix_rd *)
9bcb3eef
DS
6487 bgp_dest_get_prefix(
6488 dest));
ea47320b 6489 bgp_static_free(bgp_static);
811c6797 6490 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6491 NULL);
811c6797 6492 bgp_dest_unlock_node(rm);
d62a17ae 6493 }
05c7a1cc 6494 } else {
9bcb3eef 6495 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6496 bgp_static_withdraw(bgp,
9bcb3eef 6497 bgp_dest_get_prefix(dest),
b54892e0 6498 afi, safi);
05c7a1cc 6499 bgp_static_free(bgp_static);
9bcb3eef
DS
6500 bgp_dest_set_bgp_static_info(dest, NULL);
6501 bgp_dest_unlock_node(dest);
ea47320b 6502 }
05c7a1cc 6503 }
d62a17ae 6504}
6505
6506void bgp_static_redo_import_check(struct bgp *bgp)
6507{
6508 afi_t afi;
6509 safi_t safi;
9bcb3eef
DS
6510 struct bgp_dest *dest;
6511 struct bgp_dest *rm;
d62a17ae 6512 struct bgp_table *table;
6513 struct bgp_static *bgp_static;
6514
6515 /* Use this flag to force reprocessing of the route */
892fedb6 6516 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6517 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6518 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6519 dest = bgp_route_next(dest)) {
6520 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6521 continue;
ea47320b 6522
05c7a1cc
QY
6523 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6524 || (safi == SAFI_EVPN)) {
9bcb3eef 6525 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6526
6527 for (rm = bgp_table_top(table); rm;
6528 rm = bgp_route_next(rm)) {
a78beeb5 6529 bgp_static =
9bcb3eef 6530 bgp_dest_get_bgp_static_info(
5a8ba9fc 6531 rm);
9bcb3eef
DS
6532 bgp_static_update_safi(
6533 bgp, bgp_dest_get_prefix(rm),
6534 bgp_static, afi, safi);
d62a17ae 6535 }
05c7a1cc 6536 } else {
9bcb3eef
DS
6537 bgp_static = bgp_dest_get_bgp_static_info(dest);
6538 bgp_static_update(bgp,
6539 bgp_dest_get_prefix(dest),
6540 bgp_static, afi, safi);
ea47320b 6541 }
05c7a1cc
QY
6542 }
6543 }
892fedb6 6544 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6545}
6546
6547static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6548 safi_t safi)
6549{
6550 struct bgp_table *table;
9bcb3eef 6551 struct bgp_dest *dest;
40381db7 6552 struct bgp_path_info *pi;
d62a17ae 6553
dfb6fd1d
NT
6554 /* Do not install the aggregate route if BGP is in the
6555 * process of termination.
6556 */
892fedb6
DA
6557 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6558 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6559 return;
6560
d62a17ae 6561 table = bgp->rib[afi][safi];
9bcb3eef
DS
6562 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6563 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6564 if (pi->peer == bgp->peer_self
6565 && ((pi->type == ZEBRA_ROUTE_BGP
6566 && pi->sub_type == BGP_ROUTE_STATIC)
6567 || (pi->type != ZEBRA_ROUTE_BGP
6568 && pi->sub_type
d62a17ae 6569 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6570 bgp_aggregate_decrement(
6571 bgp, bgp_dest_get_prefix(dest), pi, afi,
6572 safi);
40381db7 6573 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6574 bgp_path_info_delete(dest, pi);
6575 bgp_process(bgp, dest, afi, safi);
d62a17ae 6576 }
6577 }
6578 }
ad4cbda1 6579}
6580
6581/*
6582 * Purge all networks and redistributed routes from routing table.
6583 * Invoked upon the instance going down.
6584 */
d62a17ae 6585void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6586{
d62a17ae 6587 afi_t afi;
6588 safi_t safi;
ad4cbda1 6589
05c7a1cc
QY
6590 FOREACH_AFI_SAFI (afi, safi)
6591 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6592}
6593
137446f9
LB
6594/*
6595 * gpz 110624
6596 * Currently this is used to set static routes for VPN and ENCAP.
6597 * I think it can probably be factored with bgp_static_set.
6598 */
d62a17ae 6599int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6600 const char *ip_str, const char *rd_str,
6601 const char *label_str, const char *rmap_str,
6602 int evpn_type, const char *esi, const char *gwip,
6603 const char *ethtag, const char *routermac)
6604{
6605 VTY_DECLVAR_CONTEXT(bgp, bgp);
6606 int ret;
6607 struct prefix p;
6608 struct prefix_rd prd;
9bcb3eef
DS
6609 struct bgp_dest *pdest;
6610 struct bgp_dest *dest;
d62a17ae 6611 struct bgp_table *table;
6612 struct bgp_static *bgp_static;
6613 mpls_label_t label = MPLS_INVALID_LABEL;
6614 struct prefix gw_ip;
6615
6616 /* validate ip prefix */
6617 ret = str2prefix(ip_str, &p);
6618 if (!ret) {
6619 vty_out(vty, "%% Malformed prefix\n");
6620 return CMD_WARNING_CONFIG_FAILED;
6621 }
6622 apply_mask(&p);
6623 if ((afi == AFI_L2VPN)
6624 && (bgp_build_evpn_prefix(evpn_type,
6625 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6626 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6627 return CMD_WARNING_CONFIG_FAILED;
6628 }
718e3744 6629
d62a17ae 6630 ret = str2prefix_rd(rd_str, &prd);
6631 if (!ret) {
6632 vty_out(vty, "%% Malformed rd\n");
6633 return CMD_WARNING_CONFIG_FAILED;
6634 }
718e3744 6635
d62a17ae 6636 if (label_str) {
6637 unsigned long label_val;
6638 label_val = strtoul(label_str, NULL, 10);
6639 encode_label(label_val, &label);
6640 }
9bedbb1e 6641
d62a17ae 6642 if (safi == SAFI_EVPN) {
6643 if (esi && str2esi(esi, NULL) == 0) {
6644 vty_out(vty, "%% Malformed ESI\n");
6645 return CMD_WARNING_CONFIG_FAILED;
6646 }
6647 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6648 vty_out(vty, "%% Malformed Router MAC\n");
6649 return CMD_WARNING_CONFIG_FAILED;
6650 }
6651 if (gwip) {
6652 memset(&gw_ip, 0, sizeof(struct prefix));
6653 ret = str2prefix(gwip, &gw_ip);
6654 if (!ret) {
6655 vty_out(vty, "%% Malformed GatewayIp\n");
6656 return CMD_WARNING_CONFIG_FAILED;
6657 }
6658 if ((gw_ip.family == AF_INET
3714a385 6659 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6660 (struct prefix_evpn *)&p))
6661 || (gw_ip.family == AF_INET6
3714a385 6662 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6663 (struct prefix_evpn *)&p))) {
6664 vty_out(vty,
6665 "%% GatewayIp family differs with IP prefix\n");
6666 return CMD_WARNING_CONFIG_FAILED;
6667 }
6668 }
6669 }
9bcb3eef
DS
6670 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6671 if (!bgp_dest_has_bgp_path_info_data(pdest))
6672 bgp_dest_set_bgp_table_info(pdest,
67009e22 6673 bgp_table_init(bgp, afi, safi));
9bcb3eef 6674 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6675
9bcb3eef 6676 dest = bgp_node_get(table, &p);
d62a17ae 6677
9bcb3eef 6678 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6679 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6680 bgp_dest_unlock_node(dest);
d62a17ae 6681 } else {
6682 /* New configuration. */
6683 bgp_static = bgp_static_new();
6684 bgp_static->backdoor = 0;
6685 bgp_static->valid = 0;
6686 bgp_static->igpmetric = 0;
975a328e 6687 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6688 bgp_static->label = label;
6689 bgp_static->prd = prd;
6690
6691 if (rmap_str) {
0a22ddfb 6692 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6693 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6694 bgp_static->rmap.name =
6695 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6696 bgp_static->rmap.map =
6697 route_map_lookup_by_name(rmap_str);
b4897fa5 6698 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6699 }
718e3744 6700
d62a17ae 6701 if (safi == SAFI_EVPN) {
6702 if (esi) {
6703 bgp_static->eth_s_id =
6704 XCALLOC(MTYPE_ATTR,
0a50c248 6705 sizeof(esi_t));
d62a17ae 6706 str2esi(esi, bgp_static->eth_s_id);
6707 }
6708 if (routermac) {
6709 bgp_static->router_mac =
28328ea9 6710 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6711 (void)prefix_str2mac(routermac,
6712 bgp_static->router_mac);
d62a17ae 6713 }
6714 if (gwip)
6715 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6716 }
9bcb3eef 6717 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6718
d62a17ae 6719 bgp_static->valid = 1;
6720 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6721 }
718e3744 6722
d62a17ae 6723 return CMD_SUCCESS;
718e3744 6724}
6725
6726/* Configure static BGP network. */
d62a17ae 6727int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6728 const char *ip_str, const char *rd_str,
6729 const char *label_str, int evpn_type, const char *esi,
6730 const char *gwip, const char *ethtag)
6731{
6732 VTY_DECLVAR_CONTEXT(bgp, bgp);
6733 int ret;
6734 struct prefix p;
6735 struct prefix_rd prd;
9bcb3eef
DS
6736 struct bgp_dest *pdest;
6737 struct bgp_dest *dest;
d62a17ae 6738 struct bgp_table *table;
6739 struct bgp_static *bgp_static;
6740 mpls_label_t label = MPLS_INVALID_LABEL;
6741
6742 /* Convert IP prefix string to struct prefix. */
6743 ret = str2prefix(ip_str, &p);
6744 if (!ret) {
6745 vty_out(vty, "%% Malformed prefix\n");
6746 return CMD_WARNING_CONFIG_FAILED;
6747 }
6748 apply_mask(&p);
6749 if ((afi == AFI_L2VPN)
6750 && (bgp_build_evpn_prefix(evpn_type,
6751 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6752 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6753 return CMD_WARNING_CONFIG_FAILED;
6754 }
6755 ret = str2prefix_rd(rd_str, &prd);
6756 if (!ret) {
6757 vty_out(vty, "%% Malformed rd\n");
6758 return CMD_WARNING_CONFIG_FAILED;
6759 }
718e3744 6760
d62a17ae 6761 if (label_str) {
6762 unsigned long label_val;
6763 label_val = strtoul(label_str, NULL, 10);
6764 encode_label(label_val, &label);
6765 }
718e3744 6766
9bcb3eef
DS
6767 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6768 if (!bgp_dest_has_bgp_path_info_data(pdest))
6769 bgp_dest_set_bgp_table_info(pdest,
67009e22 6770 bgp_table_init(bgp, afi, safi));
d62a17ae 6771 else
9bcb3eef
DS
6772 bgp_dest_unlock_node(pdest);
6773 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6774
9bcb3eef 6775 dest = bgp_node_lookup(table, &p);
6b0655a2 6776
9bcb3eef 6777 if (dest) {
d62a17ae 6778 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6779
9bcb3eef 6780 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6781 bgp_static_free(bgp_static);
9bcb3eef
DS
6782 bgp_dest_set_bgp_static_info(dest, NULL);
6783 bgp_dest_unlock_node(dest);
6784 bgp_dest_unlock_node(dest);
d62a17ae 6785 } else
6786 vty_out(vty, "%% Can't find the route\n");
6787
6788 return CMD_SUCCESS;
6789}
6790
6791static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6792 const char *rmap_name)
6793{
6794 VTY_DECLVAR_CONTEXT(bgp, bgp);
6795 struct bgp_rmap *rmap;
6796
6797 rmap = &bgp->table_map[afi][safi];
6798 if (rmap_name) {
0a22ddfb 6799 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6800 route_map_counter_decrement(rmap->map);
d62a17ae 6801 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6802 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6803 route_map_counter_increment(rmap->map);
d62a17ae 6804 } else {
0a22ddfb 6805 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6806 route_map_counter_decrement(rmap->map);
d62a17ae 6807 rmap->map = NULL;
6808 }
73ac8160 6809
d62a17ae 6810 if (bgp_fibupd_safi(safi))
6811 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6812
d62a17ae 6813 return CMD_SUCCESS;
73ac8160
DS
6814}
6815
d62a17ae 6816static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6817 const char *rmap_name)
73ac8160 6818{
d62a17ae 6819 VTY_DECLVAR_CONTEXT(bgp, bgp);
6820 struct bgp_rmap *rmap;
73ac8160 6821
d62a17ae 6822 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6823 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6824 route_map_counter_decrement(rmap->map);
d62a17ae 6825 rmap->map = NULL;
73ac8160 6826
d62a17ae 6827 if (bgp_fibupd_safi(safi))
6828 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6829
d62a17ae 6830 return CMD_SUCCESS;
73ac8160
DS
6831}
6832
2b791107 6833void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6834 safi_t safi)
73ac8160 6835{
d62a17ae 6836 if (bgp->table_map[afi][safi].name) {
d62a17ae 6837 vty_out(vty, " table-map %s\n",
6838 bgp->table_map[afi][safi].name);
6839 }
73ac8160
DS
6840}
6841
73ac8160
DS
6842DEFUN (bgp_table_map,
6843 bgp_table_map_cmd,
6844 "table-map WORD",
6845 "BGP table to RIB route download filter\n"
6846 "Name of the route map\n")
6847{
d62a17ae 6848 int idx_word = 1;
6849 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6850 argv[idx_word]->arg);
73ac8160
DS
6851}
6852DEFUN (no_bgp_table_map,
6853 no_bgp_table_map_cmd,
6854 "no table-map WORD",
3a2d747c 6855 NO_STR
73ac8160
DS
6856 "BGP table to RIB route download filter\n"
6857 "Name of the route map\n")
6858{
d62a17ae 6859 int idx_word = 2;
6860 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6861 argv[idx_word]->arg);
73ac8160
DS
6862}
6863
585f1adc
IR
6864DEFPY(bgp_network,
6865 bgp_network_cmd,
6866 "[no] network \
6867 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6868 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6869 backdoor$backdoor}]",
6870 NO_STR
6871 "Specify a network to announce via BGP\n"
6872 "IPv4 prefix\n"
6873 "Network number\n"
6874 "Network mask\n"
6875 "Network mask\n"
6876 "Route-map to modify the attributes\n"
6877 "Name of the route map\n"
6878 "Label index to associate with the prefix\n"
6879 "Label index value\n"
6880 "Specify a BGP backdoor route\n")
6881{
6882 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6883
6884 if (address_str) {
6885 int ret;
718e3744 6886
e2a86ad9 6887 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6888 addr_prefix_str,
6889 sizeof(addr_prefix_str));
e2a86ad9
DS
6890 if (!ret) {
6891 vty_out(vty, "%% Inconsistent address and mask\n");
6892 return CMD_WARNING_CONFIG_FAILED;
6893 }
d62a17ae 6894 }
718e3744 6895
585f1adc
IR
6896 return bgp_static_set(
6897 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6898 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6899 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6900}
6901
585f1adc
IR
6902DEFPY(ipv6_bgp_network,
6903 ipv6_bgp_network_cmd,
6904 "[no] network X:X::X:X/M$prefix \
6905 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6906 NO_STR
6907 "Specify a network to announce via BGP\n"
6908 "IPv6 prefix\n"
6909 "Route-map to modify the attributes\n"
6910 "Name of the route map\n"
6911 "Label index to associate with the prefix\n"
6912 "Label index value\n")
37a87b8f 6913{
585f1adc
IR
6914 return bgp_static_set(
6915 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6916 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6917}
6918
d62a17ae 6919static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6920{
d62a17ae 6921 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6922}
6923
d62a17ae 6924static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6925{
365ab2e7
RZ
6926 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6927 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6928 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6929 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6930 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6931}
718e3744 6932
365ab2e7
RZ
6933/**
6934 * Helper function to avoid repeated code: prepare variables for a
6935 * `route_map_apply` call.
6936 *
6937 * \returns `true` on route map match, otherwise `false`.
6938 */
6939static bool aggr_suppress_map_test(struct bgp *bgp,
6940 struct bgp_aggregate *aggregate,
6941 struct bgp_path_info *pi)
6942{
6943 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6944 route_map_result_t rmr = RMAP_DENYMATCH;
6945 struct bgp_path_info rmap_path = {};
6946 struct attr attr = {};
6947
6948 /* No route map entries created, just don't match. */
6949 if (aggregate->suppress_map == NULL)
6950 return false;
6951
6952 /* Call route map matching and return result. */
6953 attr.aspath = aspath_empty();
6954 rmap_path.peer = bgp->peer_self;
6955 rmap_path.attr = &attr;
6956
6957 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6958 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6959 bgp->peer_self->rmap_type = 0;
6960
6961 bgp_attr_flush(&attr);
afb254d7 6962 aspath_unintern(&attr.aspath);
365ab2e7
RZ
6963
6964 return rmr == RMAP_PERMITMATCH;
6965}
6966
4056a5f6
RZ
6967/** Test whether the aggregation has suppressed this path or not. */
6968static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6969 struct bgp_path_info *pi)
6970{
6971 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6972 return false;
6973
6974 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6975}
6976
6977/**
6978 * Suppress this path and keep the reference.
6979 *
6980 * \returns `true` if needs processing otherwise `false`.
6981 */
6982static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6983 struct bgp_path_info *pi)
6984{
6985 struct bgp_path_info_extra *pie;
6986
6987 /* Path is already suppressed by this aggregation. */
6988 if (aggr_suppress_exists(aggregate, pi))
6989 return false;
6990
6991 pie = bgp_path_info_extra_get(pi);
6992
6993 /* This is the first suppression, allocate memory and list it. */
6994 if (pie->aggr_suppressors == NULL)
6995 pie->aggr_suppressors = list_new();
6996
6997 listnode_add(pie->aggr_suppressors, aggregate);
6998
6999 /* Only mark for processing if suppressed. */
7000 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
7001 if (BGP_DEBUG(update, UPDATE_OUT))
7002 zlog_debug("aggregate-address suppressing: %pFX",
7003 bgp_dest_get_prefix(pi->net));
7004
4056a5f6
RZ
7005 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7006 return true;
7007 }
7008
7009 return false;
7010}
7011
7012/**
7013 * Unsuppress this path and remove the reference.
7014 *
7015 * \returns `true` if needs processing otherwise `false`.
7016 */
7017static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
7018 struct bgp_path_info *pi)
7019{
7020 /* Path wasn't suppressed. */
7021 if (!aggr_suppress_exists(aggregate, pi))
7022 return false;
7023
7024 listnode_delete(pi->extra->aggr_suppressors, aggregate);
7025
7026 /* Unsuppress and free extra memory if last item. */
7027 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
7028 if (BGP_DEBUG(update, UPDATE_OUT))
7029 zlog_debug("aggregate-address unsuppressing: %pFX",
7030 bgp_dest_get_prefix(pi->net));
7031
4056a5f6
RZ
7032 list_delete(&pi->extra->aggr_suppressors);
7033 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
7034 return true;
7035 }
7036
7037 return false;
7038}
7039
3dc339cd
DA
7040static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
7041 struct aspath *aspath,
7042 struct community *comm,
7043 struct ecommunity *ecomm,
7044 struct lcommunity *lcomm)
eaaf8adb
DS
7045{
7046 static struct aspath *ae = NULL;
7047
7048 if (!ae)
7049 ae = aspath_empty();
7050
40381db7 7051 if (!pi)
3dc339cd 7052 return false;
eaaf8adb 7053
40381db7 7054 if (origin != pi->attr->origin)
3dc339cd 7055 return false;
eaaf8adb 7056
40381db7 7057 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 7058 return false;
29f7d023 7059
40381db7 7060 if (!community_cmp(pi->attr->community, comm))
3dc339cd 7061 return false;
eaaf8adb 7062
b53e67a3 7063 if (!ecommunity_cmp(bgp_attr_get_ecommunity(pi->attr), ecomm))
3dc339cd 7064 return false;
eaaf8adb 7065
1bcf3a96 7066 if (!lcommunity_cmp(bgp_attr_get_lcommunity(pi->attr), lcomm))
3dc339cd 7067 return false;
dd18c5a9 7068
40381db7 7069 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 7070 return false;
7ce8a8e0 7071
3dc339cd 7072 return true;
eaaf8adb
DS
7073}
7074
5f040085
DS
7075static void bgp_aggregate_install(
7076 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
7077 uint8_t origin, struct aspath *aspath, struct community *community,
7078 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
7079 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 7080{
9bcb3eef 7081 struct bgp_dest *dest;
c701010e 7082 struct bgp_table *table;
6f94b685 7083 struct bgp_path_info *pi, *orig, *new;
20894f50 7084 struct attr *attr;
c701010e
DS
7085
7086 table = bgp->rib[afi][safi];
7087
9bcb3eef 7088 dest = bgp_node_get(table, p);
eaaf8adb 7089
9bcb3eef 7090 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7091 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
7092 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
7093 break;
7094
6aabb15d
RZ
7095 /*
7096 * If we have paths with different MEDs, then don't install
7097 * (or uninstall) the aggregate route.
7098 */
7099 if (aggregate->match_med && aggregate->med_mismatched)
7100 goto uninstall_aggregate_route;
7101
c701010e 7102 if (aggregate->count > 0) {
eaaf8adb
DS
7103 /*
7104 * If the aggregate information has not changed
7105 * no need to re-install it again.
7106 */
6f94b685 7107 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 7108 ecommunity, lcommunity)) {
9bcb3eef 7109 bgp_dest_unlock_node(dest);
eaaf8adb
DS
7110
7111 if (aspath)
7112 aspath_free(aspath);
7113 if (community)
3c1f53de 7114 community_free(&community);
3da2cc32
DS
7115 if (ecommunity)
7116 ecommunity_free(&ecommunity);
dd18c5a9
DS
7117 if (lcommunity)
7118 lcommunity_free(&lcommunity);
eaaf8adb
DS
7119
7120 return;
7121 }
7122
7123 /*
7124 * Mark the old as unusable
7125 */
40381db7 7126 if (pi)
9bcb3eef 7127 bgp_path_info_delete(dest, pi);
eaaf8adb 7128
20894f50
DA
7129 attr = bgp_attr_aggregate_intern(
7130 bgp, origin, aspath, community, ecommunity, lcommunity,
7131 aggregate, atomic_aggregate, p);
7132
7133 if (!attr) {
7134 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 7135 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
7136 zlog_debug("%s: %pFX null attribute", __func__,
7137 p);
20894f50
DA
7138 return;
7139 }
7140
3da2cc32 7141 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 7142 bgp->peer_self, attr, dest);
20894f50 7143
1defdda8 7144 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 7145
9bcb3eef
DS
7146 bgp_path_info_add(dest, new);
7147 bgp_process(bgp, dest, afi, safi);
c701010e 7148 } else {
6aabb15d 7149 uninstall_aggregate_route:
6f94b685 7150 for (pi = orig; pi; pi = pi->next)
40381db7
DS
7151 if (pi->peer == bgp->peer_self
7152 && pi->type == ZEBRA_ROUTE_BGP
7153 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
7154 break;
7155
7156 /* Withdraw static BGP route from routing table. */
40381db7 7157 if (pi) {
9bcb3eef
DS
7158 bgp_path_info_delete(dest, pi);
7159 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7160 }
7161 }
7162
9bcb3eef 7163 bgp_dest_unlock_node(dest);
c701010e
DS
7164}
7165
6aabb15d
RZ
7166/**
7167 * Check if the current path has different MED than other known paths.
7168 *
7169 * \returns `true` if the MED matched the others else `false`.
7170 */
7171static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7172 struct bgp *bgp, struct bgp_path_info *pi)
7173{
7174 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7175
7176 /* This is the first route being analyzed. */
7177 if (!aggregate->med_initialized) {
7178 aggregate->med_initialized = true;
7179 aggregate->med_mismatched = false;
7180 aggregate->med_matched_value = cur_med;
7181 } else {
7182 /* Check if routes with different MED showed up. */
7183 if (cur_med != aggregate->med_matched_value)
7184 aggregate->med_mismatched = true;
7185 }
7186
7187 return !aggregate->med_mismatched;
7188}
7189
7190/**
7191 * Initializes and tests all routes in the aggregate address path for MED
7192 * values.
7193 *
7194 * \returns `true` if all MEDs are the same otherwise `false`.
7195 */
7196static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7197 struct bgp *bgp, const struct prefix *p,
7198 afi_t afi, safi_t safi)
7199{
7200 struct bgp_table *table = bgp->rib[afi][safi];
7201 const struct prefix *dest_p;
7202 struct bgp_dest *dest, *top;
7203 struct bgp_path_info *pi;
7204 bool med_matched = true;
7205
7206 aggregate->med_initialized = false;
7207
7208 top = bgp_node_get(table, p);
7209 for (dest = bgp_node_get(table, p); dest;
7210 dest = bgp_route_next_until(dest, top)) {
7211 dest_p = bgp_dest_get_prefix(dest);
7212 if (dest_p->prefixlen <= p->prefixlen)
7213 continue;
7214
7215 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7216 if (BGP_PATH_HOLDDOWN(pi))
7217 continue;
7218 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7219 continue;
7220 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7221 med_matched = false;
7222 break;
7223 }
7224 }
7225 if (!med_matched)
7226 break;
7227 }
7228 bgp_dest_unlock_node(top);
7229
7230 return med_matched;
7231}
7232
7233/**
7234 * Toggles the route suppression status for this aggregate address
7235 * configuration.
7236 */
4056a5f6
RZ
7237void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7238 struct bgp *bgp, const struct prefix *p,
7239 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7240{
7241 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7242 const struct prefix *dest_p;
7243 struct bgp_dest *dest, *top;
7244 struct bgp_path_info *pi;
7245 bool toggle_suppression;
7246
7247 /* We've found a different MED we must revert any suppressed routes. */
7248 top = bgp_node_get(table, p);
7249 for (dest = bgp_node_get(table, p); dest;
7250 dest = bgp_route_next_until(dest, top)) {
7251 dest_p = bgp_dest_get_prefix(dest);
7252 if (dest_p->prefixlen <= p->prefixlen)
7253 continue;
7254
7255 toggle_suppression = false;
7256 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7257 if (BGP_PATH_HOLDDOWN(pi))
7258 continue;
7259 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7260 continue;
7261
6aabb15d
RZ
7262 /* We are toggling suppression back. */
7263 if (suppress) {
6aabb15d 7264 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7265 if (aggr_suppress_path(aggregate, pi))
7266 toggle_suppression = true;
6aabb15d
RZ
7267 continue;
7268 }
7269
6aabb15d 7270 /* Install route if there is no more suppression. */
4056a5f6 7271 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7272 toggle_suppression = true;
6aabb15d
RZ
7273 }
7274
7275 if (toggle_suppression)
7276 bgp_process(bgp, dest, afi, safi);
7277 }
7278 bgp_dest_unlock_node(top);
7279}
7280
7281/**
7282 * Aggregate address MED matching incremental test: this function is called
7283 * when the initial aggregation occurred and we are only testing a single
7284 * new path.
7285 *
7286 * In addition to testing and setting the MED validity it also installs back
7287 * suppressed routes (if summary is configured).
7288 *
7289 * Must not be called in `bgp_aggregate_route`.
7290 */
7291static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7292 struct bgp *bgp, const struct prefix *p,
7293 afi_t afi, safi_t safi,
7294 struct bgp_path_info *pi, bool is_adding)
7295{
7296 /* MED matching disabled. */
7297 if (!aggregate->match_med)
7298 return;
7299
7300 /* Aggregation with different MED, nothing to do. */
7301 if (aggregate->med_mismatched)
7302 return;
7303
7304 /*
7305 * Test the current entry:
7306 *
7307 * is_adding == true: if the new entry doesn't match then we must
7308 * install all suppressed routes.
7309 *
7310 * is_adding == false: if the entry being removed was the last
7311 * unmatching entry then we can suppress all routes.
7312 */
7313 if (!is_adding) {
7314 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7315 && aggregate->summary_only)
7316 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7317 safi, true);
7318 } else
7319 bgp_aggregate_med_match(aggregate, bgp, pi);
7320
7321 /* No mismatches, just quit. */
7322 if (!aggregate->med_mismatched)
7323 return;
7324
7325 /* Route summarization is disabled. */
7326 if (!aggregate->summary_only)
7327 return;
7328
7329 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7330}
7331
b5d58c32 7332/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7333void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7334 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7335{
7336 struct bgp_table *table;
9bcb3eef
DS
7337 struct bgp_dest *top;
7338 struct bgp_dest *dest;
d7c0a89a 7339 uint8_t origin;
d62a17ae 7340 struct aspath *aspath = NULL;
d62a17ae 7341 struct community *community = NULL;
3da2cc32 7342 struct ecommunity *ecommunity = NULL;
dd18c5a9 7343 struct lcommunity *lcommunity = NULL;
40381db7 7344 struct bgp_path_info *pi;
d62a17ae 7345 unsigned long match = 0;
d7c0a89a 7346 uint8_t atomic_aggregate = 0;
d62a17ae 7347
9f822fa2
S
7348 /* If the bgp instance is being deleted or self peer is deleted
7349 * then do not create aggregate route
7350 */
892fedb6
DA
7351 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7352 || (bgp->peer_self == NULL))
9f822fa2
S
7353 return;
7354
6aabb15d
RZ
7355 /* Initialize and test routes for MED difference. */
7356 if (aggregate->match_med)
7357 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7358
4056a5f6
RZ
7359 /*
7360 * Reset aggregate count: we might've been called from route map
7361 * update so in that case we must retest all more specific routes.
7362 *
7363 * \see `bgp_route_map_process_update`.
7364 */
7365 aggregate->count = 0;
7366 aggregate->incomplete_origin_count = 0;
7367 aggregate->incomplete_origin_count = 0;
7368 aggregate->egp_origin_count = 0;
7369
d62a17ae 7370 /* ORIGIN attribute: If at least one route among routes that are
7371 aggregated has ORIGIN with the value INCOMPLETE, then the
7372 aggregated route must have the ORIGIN attribute with the value
7373 INCOMPLETE. Otherwise, if at least one route among routes that
7374 are aggregated has ORIGIN with the value EGP, then the aggregated
7375 route must have the origin attribute with the value EGP. In all
7376 other case the value of the ORIGIN attribute of the aggregated
7377 route is INTERNAL. */
7378 origin = BGP_ORIGIN_IGP;
718e3744 7379
d62a17ae 7380 table = bgp->rib[afi][safi];
718e3744 7381
d62a17ae 7382 top = bgp_node_get(table, p);
9bcb3eef
DS
7383 for (dest = bgp_node_get(table, p); dest;
7384 dest = bgp_route_next_until(dest, top)) {
7385 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7386
9bcb3eef 7387 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7388 continue;
d62a17ae 7389
a77e2f4b
S
7390 /* If suppress fib is enabled and route not installed
7391 * in FIB, skip the route
7392 */
7393 if (!bgp_check_advertise(bgp, dest))
7394 continue;
7395
c2ff8b3e 7396 match = 0;
d62a17ae 7397
9bcb3eef 7398 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7399 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7400 continue;
718e3744 7401
40381db7 7402 if (pi->attr->flag
c2ff8b3e
DS
7403 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7404 atomic_aggregate = 1;
d62a17ae 7405
40381db7 7406 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7407 continue;
d62a17ae 7408
f273fef1
DS
7409 /*
7410 * summary-only aggregate route suppress
7411 * aggregated route announcements.
6aabb15d
RZ
7412 *
7413 * MED matching:
7414 * Don't create summaries if MED didn't match
7415 * otherwise neither the specific routes and the
7416 * aggregation will be announced.
f273fef1 7417 */
6aabb15d
RZ
7418 if (aggregate->summary_only
7419 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7420 if (aggr_suppress_path(aggregate, pi))
7421 match++;
d62a17ae 7422 }
c2ff8b3e 7423
365ab2e7
RZ
7424 /*
7425 * Suppress more specific routes that match the route
7426 * map results.
7427 *
7428 * MED matching:
7429 * Don't suppress routes if MED matching is enabled and
7430 * it mismatched otherwise we might end up with no
7431 * routes for this path.
7432 */
7433 if (aggregate->suppress_map_name
7434 && AGGREGATE_MED_VALID(aggregate)
7435 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7436 if (aggr_suppress_path(aggregate, pi))
7437 match++;
d62a17ae 7438 }
c2ff8b3e
DS
7439
7440 aggregate->count++;
7441
f273fef1
DS
7442 /*
7443 * If at least one route among routes that are
7444 * aggregated has ORIGIN with the value INCOMPLETE,
7445 * then the aggregated route MUST have the ORIGIN
7446 * attribute with the value INCOMPLETE. Otherwise, if
7447 * at least one route among routes that are aggregated
7448 * has ORIGIN with the value EGP, then the aggregated
7449 * route MUST have the ORIGIN attribute with the value
7450 * EGP.
7451 */
fc968841
NT
7452 switch (pi->attr->origin) {
7453 case BGP_ORIGIN_INCOMPLETE:
7454 aggregate->incomplete_origin_count++;
7455 break;
7456 case BGP_ORIGIN_EGP:
7457 aggregate->egp_origin_count++;
7458 break;
7459 default:
7460 /*Do nothing.
7461 */
7462 break;
7463 }
c2ff8b3e
DS
7464
7465 if (!aggregate->as_set)
7466 continue;
7467
f273fef1
DS
7468 /*
7469 * as-set aggregate route generate origin, as path,
7470 * and community aggregation.
7471 */
fc968841
NT
7472 /* Compute aggregate route's as-path.
7473 */
ef51a7d8 7474 bgp_compute_aggregate_aspath_hash(aggregate,
7475 pi->attr->aspath);
c2ff8b3e 7476
fc968841
NT
7477 /* Compute aggregate route's community.
7478 */
7479 if (pi->attr->community)
21fec674 7480 bgp_compute_aggregate_community_hash(
fc968841
NT
7481 aggregate,
7482 pi->attr->community);
dd18c5a9 7483
fc968841
NT
7484 /* Compute aggregate route's extended community.
7485 */
b53e67a3 7486 if (bgp_attr_get_ecommunity(pi->attr))
4edd83f9 7487 bgp_compute_aggregate_ecommunity_hash(
b53e67a3
DA
7488 aggregate,
7489 bgp_attr_get_ecommunity(pi->attr));
fc968841
NT
7490
7491 /* Compute aggregate route's large community.
7492 */
1bcf3a96 7493 if (bgp_attr_get_lcommunity(pi->attr))
f1eb1f05 7494 bgp_compute_aggregate_lcommunity_hash(
1bcf3a96
DA
7495 aggregate,
7496 bgp_attr_get_lcommunity(pi->attr));
d62a17ae 7497 }
c2ff8b3e 7498 if (match)
9bcb3eef 7499 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7500 }
21fec674 7501 if (aggregate->as_set) {
ef51a7d8 7502 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7503 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7504 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7505 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7506 }
7507
f1eb1f05 7508
9bcb3eef 7509 bgp_dest_unlock_node(top);
718e3744 7510
718e3744 7511
fc968841
NT
7512 if (aggregate->incomplete_origin_count > 0)
7513 origin = BGP_ORIGIN_INCOMPLETE;
7514 else if (aggregate->egp_origin_count > 0)
7515 origin = BGP_ORIGIN_EGP;
d62a17ae 7516
229757f1
DA
7517 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7518 origin = aggregate->origin;
7519
fc968841
NT
7520 if (aggregate->as_set) {
7521 if (aggregate->aspath)
7522 /* Retrieve aggregate route's as-path.
7523 */
7524 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7525
fc968841
NT
7526 if (aggregate->community)
7527 /* Retrieve aggregate route's community.
7528 */
7529 community = community_dup(aggregate->community);
3da2cc32 7530
fc968841
NT
7531 if (aggregate->ecommunity)
7532 /* Retrieve aggregate route's ecommunity.
7533 */
7534 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7535
fc968841
NT
7536 if (aggregate->lcommunity)
7537 /* Retrieve aggregate route's lcommunity.
7538 */
7539 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7540 }
718e3744 7541
c701010e 7542 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7543 ecommunity, lcommunity, atomic_aggregate,
7544 aggregate);
718e3744 7545}
7546
5f040085
DS
7547void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7548 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7549{
7550 struct bgp_table *table;
9bcb3eef
DS
7551 struct bgp_dest *top;
7552 struct bgp_dest *dest;
40381db7 7553 struct bgp_path_info *pi;
3b7db173
DS
7554 unsigned long match;
7555
7556 table = bgp->rib[afi][safi];
7557
7558 /* If routes exists below this node, generate aggregate routes. */
7559 top = bgp_node_get(table, p);
9bcb3eef
DS
7560 for (dest = bgp_node_get(table, p); dest;
7561 dest = bgp_route_next_until(dest, top)) {
7562 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7563
9bcb3eef 7564 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7565 continue;
7566 match = 0;
7567
9bcb3eef 7568 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7569 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7570 continue;
7571
40381db7 7572 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7573 continue;
7574
92b175bd
RZ
7575 /*
7576 * This route is suppressed: attempt to unsuppress it.
7577 *
7578 * `aggr_unsuppress_path` will fail if this particular
7579 * aggregate route was not the suppressor.
7580 */
7581 if (pi->extra && pi->extra->aggr_suppressors &&
7582 listcount(pi->extra->aggr_suppressors)) {
4056a5f6 7583 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7584 match++;
3b7db173 7585 }
365ab2e7 7586
3b7db173 7587 aggregate->count--;
fc968841
NT
7588
7589 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7590 aggregate->incomplete_origin_count--;
7591 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7592 aggregate->egp_origin_count--;
7593
7594 if (aggregate->as_set) {
7595 /* Remove as-path from aggregate.
7596 */
ef51a7d8 7597 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7598 aggregate,
7599 pi->attr->aspath);
7600
7601 if (pi->attr->community)
7602 /* Remove community from aggregate.
7603 */
21fec674 7604 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7605 aggregate,
7606 pi->attr->community);
7607
b53e67a3 7608 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7609 /* Remove ecommunity from aggregate.
7610 */
4edd83f9 7611 bgp_remove_ecomm_from_aggregate_hash(
b53e67a3
DA
7612 aggregate,
7613 bgp_attr_get_ecommunity(
7614 pi->attr));
fc968841 7615
1bcf3a96 7616 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7617 /* Remove lcommunity from aggregate.
7618 */
f1eb1f05 7619 bgp_remove_lcomm_from_aggregate_hash(
1bcf3a96
DA
7620 aggregate,
7621 bgp_attr_get_lcommunity(
7622 pi->attr));
fc968841 7623 }
3b7db173
DS
7624 }
7625
7626 /* If this node was suppressed, process the change. */
7627 if (match)
9bcb3eef 7628 bgp_process(bgp, dest, afi, safi);
3b7db173 7629 }
f1eb1f05 7630 if (aggregate->as_set) {
ef51a7d8 7631 aspath_free(aggregate->aspath);
7632 aggregate->aspath = NULL;
21fec674 7633 if (aggregate->community)
7634 community_free(&aggregate->community);
4edd83f9 7635 if (aggregate->ecommunity)
7636 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7637 if (aggregate->lcommunity)
7638 lcommunity_free(&aggregate->lcommunity);
7639 }
7640
9bcb3eef 7641 bgp_dest_unlock_node(top);
3b7db173 7642}
718e3744 7643
5f040085
DS
7644static void bgp_add_route_to_aggregate(struct bgp *bgp,
7645 const struct prefix *aggr_p,
fc968841
NT
7646 struct bgp_path_info *pinew, afi_t afi,
7647 safi_t safi,
7648 struct bgp_aggregate *aggregate)
7649{
7650 uint8_t origin;
7651 struct aspath *aspath = NULL;
7652 uint8_t atomic_aggregate = 0;
7653 struct community *community = NULL;
7654 struct ecommunity *ecommunity = NULL;
7655 struct lcommunity *lcommunity = NULL;
7656
a4559740 7657 /* If the bgp instance is being deleted or self peer is deleted
7658 * then do not create aggregate route
7659 */
7660 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7661 || (bgp->peer_self == NULL))
7662 return;
7663
fc968841
NT
7664 /* ORIGIN attribute: If at least one route among routes that are
7665 * aggregated has ORIGIN with the value INCOMPLETE, then the
7666 * aggregated route must have the ORIGIN attribute with the value
7667 * INCOMPLETE. Otherwise, if at least one route among routes that
7668 * are aggregated has ORIGIN with the value EGP, then the aggregated
7669 * route must have the origin attribute with the value EGP. In all
7670 * other case the value of the ORIGIN attribute of the aggregated
7671 * route is INTERNAL.
7672 */
7673 origin = BGP_ORIGIN_IGP;
7674
7675 aggregate->count++;
7676
6aabb15d
RZ
7677 /*
7678 * This must be called before `summary` check to avoid
7679 * "suppressing" twice.
7680 */
7681 if (aggregate->match_med)
7682 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7683 pinew, true);
7684
7685 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7686 aggr_suppress_path(aggregate, pinew);
fc968841 7687
365ab2e7
RZ
7688 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7689 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7690 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7691
7692 switch (pinew->attr->origin) {
7693 case BGP_ORIGIN_INCOMPLETE:
7694 aggregate->incomplete_origin_count++;
7695 break;
7696 case BGP_ORIGIN_EGP:
7697 aggregate->egp_origin_count++;
7698 break;
7699 default:
7700 /* Do nothing.
7701 */
7702 break;
7703 }
7704
7705 if (aggregate->incomplete_origin_count > 0)
7706 origin = BGP_ORIGIN_INCOMPLETE;
7707 else if (aggregate->egp_origin_count > 0)
7708 origin = BGP_ORIGIN_EGP;
7709
229757f1
DA
7710 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7711 origin = aggregate->origin;
7712
fc968841
NT
7713 if (aggregate->as_set) {
7714 /* Compute aggregate route's as-path.
7715 */
7716 bgp_compute_aggregate_aspath(aggregate,
7717 pinew->attr->aspath);
7718
7719 /* Compute aggregate route's community.
7720 */
7721 if (pinew->attr->community)
7722 bgp_compute_aggregate_community(
7723 aggregate,
7724 pinew->attr->community);
7725
7726 /* Compute aggregate route's extended community.
7727 */
b53e67a3 7728 if (bgp_attr_get_ecommunity(pinew->attr))
fc968841 7729 bgp_compute_aggregate_ecommunity(
b53e67a3
DA
7730 aggregate,
7731 bgp_attr_get_ecommunity(pinew->attr));
fc968841
NT
7732
7733 /* Compute aggregate route's large community.
7734 */
1bcf3a96 7735 if (bgp_attr_get_lcommunity(pinew->attr))
fc968841 7736 bgp_compute_aggregate_lcommunity(
1bcf3a96
DA
7737 aggregate,
7738 bgp_attr_get_lcommunity(pinew->attr));
fc968841
NT
7739
7740 /* Retrieve aggregate route's as-path.
7741 */
7742 if (aggregate->aspath)
7743 aspath = aspath_dup(aggregate->aspath);
7744
7745 /* Retrieve aggregate route's community.
7746 */
7747 if (aggregate->community)
7748 community = community_dup(aggregate->community);
7749
7750 /* Retrieve aggregate route's ecommunity.
7751 */
7752 if (aggregate->ecommunity)
7753 ecommunity = ecommunity_dup(aggregate->ecommunity);
7754
7755 /* Retrieve aggregate route's lcommunity.
7756 */
7757 if (aggregate->lcommunity)
7758 lcommunity = lcommunity_dup(aggregate->lcommunity);
7759 }
7760
7761 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7762 aspath, community, ecommunity,
7763 lcommunity, atomic_aggregate, aggregate);
7764}
7765
7766static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7767 safi_t safi,
7768 struct bgp_path_info *pi,
7769 struct bgp_aggregate *aggregate,
5f040085 7770 const struct prefix *aggr_p)
fc968841
NT
7771{
7772 uint8_t origin;
7773 struct aspath *aspath = NULL;
7774 uint8_t atomic_aggregate = 0;
7775 struct community *community = NULL;
7776 struct ecommunity *ecommunity = NULL;
7777 struct lcommunity *lcommunity = NULL;
7778 unsigned long match = 0;
7779
a4559740 7780 /* If the bgp instance is being deleted or self peer is deleted
7781 * then do not create aggregate route
7782 */
7783 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7784 || (bgp->peer_self == NULL))
7785 return;
7786
fc968841
NT
7787 if (BGP_PATH_HOLDDOWN(pi))
7788 return;
7789
7790 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7791 return;
7792
4056a5f6
RZ
7793 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7794 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7795 match++;
fc968841 7796
365ab2e7 7797 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7798 && aggr_suppress_map_test(bgp, aggregate, pi))
7799 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7800 match++;
fc968841 7801
6aabb15d 7802 /*
365ab2e7 7803 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7804 * "unsuppressing" twice.
7805 */
7806 if (aggregate->match_med)
7807 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7808 true);
7809
fc968841
NT
7810 if (aggregate->count > 0)
7811 aggregate->count--;
7812
7813 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7814 aggregate->incomplete_origin_count--;
7815 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7816 aggregate->egp_origin_count--;
7817
7818 if (aggregate->as_set) {
7819 /* Remove as-path from aggregate.
7820 */
7821 bgp_remove_aspath_from_aggregate(aggregate,
7822 pi->attr->aspath);
7823
7824 if (pi->attr->community)
7825 /* Remove community from aggregate.
7826 */
7827 bgp_remove_community_from_aggregate(
7828 aggregate,
7829 pi->attr->community);
7830
b53e67a3 7831 if (bgp_attr_get_ecommunity(pi->attr))
fc968841
NT
7832 /* Remove ecommunity from aggregate.
7833 */
7834 bgp_remove_ecommunity_from_aggregate(
b53e67a3 7835 aggregate, bgp_attr_get_ecommunity(pi->attr));
fc968841 7836
1bcf3a96 7837 if (bgp_attr_get_lcommunity(pi->attr))
fc968841
NT
7838 /* Remove lcommunity from aggregate.
7839 */
7840 bgp_remove_lcommunity_from_aggregate(
1bcf3a96 7841 aggregate, bgp_attr_get_lcommunity(pi->attr));
fc968841
NT
7842 }
7843
7844 /* If this node was suppressed, process the change. */
7845 if (match)
7846 bgp_process(bgp, pi->net, afi, safi);
7847
7848 origin = BGP_ORIGIN_IGP;
7849 if (aggregate->incomplete_origin_count > 0)
7850 origin = BGP_ORIGIN_INCOMPLETE;
7851 else if (aggregate->egp_origin_count > 0)
7852 origin = BGP_ORIGIN_EGP;
7853
229757f1
DA
7854 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7855 origin = aggregate->origin;
7856
fc968841
NT
7857 if (aggregate->as_set) {
7858 /* Retrieve aggregate route's as-path.
7859 */
7860 if (aggregate->aspath)
7861 aspath = aspath_dup(aggregate->aspath);
7862
7863 /* Retrieve aggregate route's community.
7864 */
7865 if (aggregate->community)
7866 community = community_dup(aggregate->community);
7867
7868 /* Retrieve aggregate route's ecommunity.
7869 */
7870 if (aggregate->ecommunity)
7871 ecommunity = ecommunity_dup(aggregate->ecommunity);
7872
7873 /* Retrieve aggregate route's lcommunity.
7874 */
7875 if (aggregate->lcommunity)
7876 lcommunity = lcommunity_dup(aggregate->lcommunity);
7877 }
7878
7879 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7880 aspath, community, ecommunity,
7881 lcommunity, atomic_aggregate, aggregate);
7882}
7883
5a1ae2c2 7884void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7885 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7886{
9bcb3eef
DS
7887 struct bgp_dest *child;
7888 struct bgp_dest *dest;
d62a17ae 7889 struct bgp_aggregate *aggregate;
7890 struct bgp_table *table;
718e3744 7891
d62a17ae 7892 table = bgp->aggregate[afi][safi];
f018db83 7893
d62a17ae 7894 /* No aggregates configured. */
7895 if (bgp_table_top_nolock(table) == NULL)
7896 return;
f018db83 7897
d62a17ae 7898 if (p->prefixlen == 0)
7899 return;
718e3744 7900
40381db7 7901 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7902 return;
718e3744 7903
a77e2f4b
S
7904 /* If suppress fib is enabled and route not installed
7905 * in FIB, do not update the aggregate route
7906 */
7907 if (!bgp_check_advertise(bgp, pi->net))
7908 return;
7909
d62a17ae 7910 child = bgp_node_get(table, p);
718e3744 7911
d62a17ae 7912 /* Aggregate address configuration check. */
9bcb3eef
DS
7913 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7914 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7915
9bcb3eef
DS
7916 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7917 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7918 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7919 aggregate);
d62a17ae 7920 }
b1e62edd 7921 }
9bcb3eef 7922 bgp_dest_unlock_node(child);
718e3744 7923}
7924
5a1ae2c2 7925void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7926 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7927{
9bcb3eef
DS
7928 struct bgp_dest *child;
7929 struct bgp_dest *dest;
d62a17ae 7930 struct bgp_aggregate *aggregate;
7931 struct bgp_table *table;
718e3744 7932
d62a17ae 7933 table = bgp->aggregate[afi][safi];
718e3744 7934
d62a17ae 7935 /* No aggregates configured. */
7936 if (bgp_table_top_nolock(table) == NULL)
7937 return;
718e3744 7938
d62a17ae 7939 if (p->prefixlen == 0)
7940 return;
718e3744 7941
d62a17ae 7942 child = bgp_node_get(table, p);
718e3744 7943
d62a17ae 7944 /* Aggregate address configuration check. */
9bcb3eef
DS
7945 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7946 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7947
9bcb3eef
DS
7948 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7949 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7950 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7951 aggregate, dest_p);
d62a17ae 7952 }
b1e62edd 7953 }
9bcb3eef 7954 bgp_dest_unlock_node(child);
d62a17ae 7955}
718e3744 7956
718e3744 7957/* Aggregate route attribute. */
7958#define AGGREGATE_SUMMARY_ONLY 1
7959#define AGGREGATE_AS_SET 1
fb29348a 7960#define AGGREGATE_AS_UNSET 0
718e3744 7961
229757f1
DA
7962static const char *bgp_origin2str(uint8_t origin)
7963{
7964 switch (origin) {
7965 case BGP_ORIGIN_IGP:
7966 return "igp";
7967 case BGP_ORIGIN_EGP:
7968 return "egp";
7969 case BGP_ORIGIN_INCOMPLETE:
7970 return "incomplete";
7971 }
7972 return "n/a";
7973}
7974
fdeb5a81 7975static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7976{
7977 switch (v_state) {
fdeb5a81
DS
7978 case RPKI_NOT_BEING_USED:
7979 return "not used";
7980 case RPKI_VALID:
b5b99af8 7981 return "valid";
fdeb5a81 7982 case RPKI_NOTFOUND:
b5b99af8 7983 return "not found";
fdeb5a81 7984 case RPKI_INVALID:
b5b99af8 7985 return "invalid";
b5b99af8 7986 }
fdeb5a81
DS
7987
7988 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7989 return "ERROR";
7990}
7991
585f1adc
IR
7992static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7993 afi_t afi, safi_t safi)
718e3744 7994{
585f1adc
IR
7995 VTY_DECLVAR_CONTEXT(bgp, bgp);
7996 int ret;
7997 struct prefix p;
9bcb3eef 7998 struct bgp_dest *dest;
d62a17ae 7999 struct bgp_aggregate *aggregate;
718e3744 8000
585f1adc
IR
8001 /* Convert string to prefix structure. */
8002 ret = str2prefix(prefix_str, &p);
8003 if (!ret) {
8004 vty_out(vty, "Malformed prefix\n");
8005 return CMD_WARNING_CONFIG_FAILED;
8006 }
8007 apply_mask(&p);
a4559740 8008
d62a17ae 8009 /* Old configuration check. */
585f1adc 8010 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 8011 if (!dest) {
585f1adc
IR
8012 vty_out(vty,
8013 "%% There is no aggregate-address configuration.\n");
8014 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8015 }
f6269b4f 8016
9bcb3eef 8017 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
8018 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
8019 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
8020 NULL, NULL, 0, aggregate);
d62a17ae 8021
8022 /* Unlock aggregate address configuration. */
9bcb3eef 8023 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
8024
8025 if (aggregate->community)
8026 community_free(&aggregate->community);
8027
8028 if (aggregate->community_hash) {
8029 /* Delete all communities in the hash.
8030 */
8031 hash_clean(aggregate->community_hash,
8032 bgp_aggr_community_remove);
8033 /* Free up the community_hash.
8034 */
8035 hash_free(aggregate->community_hash);
8036 }
8037
8038 if (aggregate->ecommunity)
8039 ecommunity_free(&aggregate->ecommunity);
8040
8041 if (aggregate->ecommunity_hash) {
8042 /* Delete all ecommunities in the hash.
8043 */
8044 hash_clean(aggregate->ecommunity_hash,
8045 bgp_aggr_ecommunity_remove);
8046 /* Free up the ecommunity_hash.
8047 */
8048 hash_free(aggregate->ecommunity_hash);
8049 }
8050
8051 if (aggregate->lcommunity)
8052 lcommunity_free(&aggregate->lcommunity);
8053
8054 if (aggregate->lcommunity_hash) {
8055 /* Delete all lcommunities in the hash.
8056 */
8057 hash_clean(aggregate->lcommunity_hash,
8058 bgp_aggr_lcommunity_remove);
8059 /* Free up the lcommunity_hash.
8060 */
8061 hash_free(aggregate->lcommunity_hash);
8062 }
8063
8064 if (aggregate->aspath)
8065 aspath_free(aggregate->aspath);
8066
8067 if (aggregate->aspath_hash) {
8068 /* Delete all as-paths in the hash.
8069 */
8070 hash_clean(aggregate->aspath_hash,
8071 bgp_aggr_aspath_remove);
8072 /* Free up the aspath_hash.
8073 */
8074 hash_free(aggregate->aspath_hash);
8075 }
8076
d62a17ae 8077 bgp_aggregate_free(aggregate);
9bcb3eef
DS
8078 bgp_dest_unlock_node(dest);
8079 bgp_dest_unlock_node(dest);
d62a17ae 8080
585f1adc 8081 return CMD_SUCCESS;
d62a17ae 8082}
8083
585f1adc
IR
8084static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
8085 safi_t safi, const char *rmap,
8086 uint8_t summary_only, uint8_t as_set,
8087 uint8_t origin, bool match_med,
8088 const char *suppress_map)
d62a17ae 8089{
585f1adc 8090 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 8091 int ret;
585f1adc 8092 struct prefix p;
9bcb3eef 8093 struct bgp_dest *dest;
d62a17ae 8094 struct bgp_aggregate *aggregate;
fb29348a 8095 uint8_t as_set_new = as_set;
d62a17ae 8096
365ab2e7 8097 if (suppress_map && summary_only) {
585f1adc 8098 vty_out(vty,
365ab2e7 8099 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 8100 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
8101 }
8102
585f1adc
IR
8103 /* Convert string to prefix structure. */
8104 ret = str2prefix(prefix_str, &p);
8105 if (!ret) {
8106 vty_out(vty, "Malformed prefix\n");
8107 return CMD_WARNING_CONFIG_FAILED;
8108 }
8109 apply_mask(&p);
d62a17ae 8110
585f1adc
IR
8111 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
8112 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
8113 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
8114 prefix_str);
8115 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
8116 }
8117
d62a17ae 8118 /* Old configuration check. */
585f1adc 8119 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 8120 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 8121
20894f50 8122 if (aggregate) {
585f1adc 8123 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 8124 /* try to remove the old entry */
585f1adc 8125 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 8126 if (ret) {
585f1adc 8127 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 8128 bgp_dest_unlock_node(dest);
585f1adc 8129 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 8130 }
8131 }
718e3744 8132
d62a17ae 8133 /* Make aggregate address structure. */
8134 aggregate = bgp_aggregate_new();
8135 aggregate->summary_only = summary_only;
6aabb15d 8136 aggregate->match_med = match_med;
fb29348a
DA
8137
8138 /* Network operators MUST NOT locally generate any new
8139 * announcements containing AS_SET or AS_CONFED_SET. If they have
8140 * announced routes with AS_SET or AS_CONFED_SET in them, then they
8141 * SHOULD withdraw those routes and re-announce routes for the
8142 * aggregate or component prefixes (i.e., the more-specific routes
8143 * subsumed by the previously aggregated route) without AS_SET
8144 * or AS_CONFED_SET in the updates.
8145 */
7f972cd8 8146 if (bgp->reject_as_sets) {
fb29348a
DA
8147 if (as_set == AGGREGATE_AS_SET) {
8148 as_set_new = AGGREGATE_AS_UNSET;
8149 zlog_warn(
63efca0e 8150 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 8151 __func__);
585f1adc 8152 vty_out(vty,
fb29348a
DA
8153 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
8154 }
8155 }
8156
8157 aggregate->as_set = as_set_new;
d62a17ae 8158 aggregate->safi = safi;
229757f1
DA
8159 /* Override ORIGIN attribute if defined.
8160 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8161 * to IGP which is not what rfc4271 says.
8162 * This enables the same behavior, optionally.
8163 */
8164 aggregate->origin = origin;
20894f50
DA
8165
8166 if (rmap) {
8167 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8168 route_map_counter_decrement(aggregate->rmap.map);
8169 aggregate->rmap.name =
8170 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8171 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8172 route_map_counter_increment(aggregate->rmap.map);
8173 }
365ab2e7
RZ
8174
8175 if (suppress_map) {
8176 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8177 route_map_counter_decrement(aggregate->suppress_map);
8178
8179 aggregate->suppress_map_name =
8180 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8181 aggregate->suppress_map =
8182 route_map_lookup_by_name(aggregate->suppress_map_name);
8183 route_map_counter_increment(aggregate->suppress_map);
8184 }
8185
9bcb3eef 8186 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8187
d62a17ae 8188 /* Aggregate address insert into BGP routing table. */
585f1adc 8189 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8190
585f1adc 8191 return CMD_SUCCESS;
718e3744 8192}
8193
585f1adc
IR
8194DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8195 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8196 "as-set$as_set_s"
8197 "|summary-only$summary_only"
8198 "|route-map WORD$rmap_name"
8199 "|origin <egp|igp|incomplete>$origin_s"
8200 "|matching-MED-only$match_med"
8201 "|suppress-map WORD$suppress_map"
8202 "}]",
8203 NO_STR
8204 "Configure BGP aggregate entries\n"
8205 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8206 "Generate AS set path information\n"
8207 "Filter more specific routes from updates\n"
8208 "Apply route map to aggregate network\n"
8209 "Route map name\n"
8210 "BGP origin code\n"
8211 "Remote EGP\n"
8212 "Local IGP\n"
8213 "Unknown heritage\n"
8214 "Only aggregate routes with matching MED\n"
8215 "Suppress the selected more specific routes\n"
8216 "Route map with the route selectors\n")
8217{
8218 const char *prefix_s = NULL;
554b3b10 8219 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8220 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8221 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8222 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8223
554b3b10 8224 if (addr_str) {
7533cad7
QY
8225 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8226 sizeof(prefix_buf))
554b3b10
RZ
8227 == 0) {
8228 vty_out(vty, "%% Inconsistent address and mask\n");
8229 return CMD_WARNING_CONFIG_FAILED;
8230 }
585f1adc
IR
8231 prefix_s = prefix_buf;
8232 } else
8233 prefix_s = prefix_str;
37a87b8f 8234
585f1adc
IR
8235 if (origin_s) {
8236 if (strcmp(origin_s, "egp") == 0)
8237 origin = BGP_ORIGIN_EGP;
8238 else if (strcmp(origin_s, "igp") == 0)
8239 origin = BGP_ORIGIN_IGP;
8240 else if (strcmp(origin_s, "incomplete") == 0)
8241 origin = BGP_ORIGIN_INCOMPLETE;
8242 }
90e21f35 8243
585f1adc
IR
8244 if (as_set_s)
8245 as_set = AGGREGATE_AS_SET;
554b3b10 8246
585f1adc 8247 /* Handle configuration removal, otherwise installation. */
554b3b10 8248 if (no)
585f1adc
IR
8249 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8250
8251 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8252 summary_only != NULL, as_set, origin,
8253 match_med != NULL, suppress_map);
8254}
8255
8256DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8257 "[no] aggregate-address X:X::X:X/M$prefix [{"
8258 "as-set$as_set_s"
8259 "|summary-only$summary_only"
8260 "|route-map WORD$rmap_name"
8261 "|origin <egp|igp|incomplete>$origin_s"
8262 "|matching-MED-only$match_med"
8263 "|suppress-map WORD$suppress_map"
8264 "}]",
8265 NO_STR
8266 "Configure BGP aggregate entries\n"
8267 "Aggregate prefix\n"
8268 "Generate AS set path information\n"
8269 "Filter more specific routes from updates\n"
8270 "Apply route map to aggregate network\n"
8271 "Route map name\n"
8272 "BGP origin code\n"
8273 "Remote EGP\n"
8274 "Local IGP\n"
8275 "Unknown heritage\n"
8276 "Only aggregate routes with matching MED\n"
8277 "Suppress the selected more specific routes\n"
8278 "Route map with the route selectors\n")
8279{
8280 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8281 int as_set = AGGREGATE_AS_UNSET;
8282
8283 if (origin_s) {
8284 if (strcmp(origin_s, "egp") == 0)
8285 origin = BGP_ORIGIN_EGP;
8286 else if (strcmp(origin_s, "igp") == 0)
8287 origin = BGP_ORIGIN_IGP;
8288 else if (strcmp(origin_s, "incomplete") == 0)
8289 origin = BGP_ORIGIN_INCOMPLETE;
8290 }
8291
8292 if (as_set_s)
8293 as_set = AGGREGATE_AS_SET;
8294
8295 /* Handle configuration removal, otherwise installation. */
554b3b10 8296 if (no)
585f1adc
IR
8297 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8298 SAFI_UNICAST);
554b3b10 8299
585f1adc
IR
8300 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8301 rmap_name, summary_only != NULL, as_set,
8302 origin, match_med != NULL, suppress_map);
718e3744 8303}
8304
718e3744 8305/* Redistribute route treatment. */
d62a17ae 8306void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8307 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8308 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8309 enum blackhole_type bhtype, uint32_t metric,
8310 uint8_t type, unsigned short instance,
8311 route_tag_t tag)
d62a17ae 8312{
4b7e6066 8313 struct bgp_path_info *new;
40381db7
DS
8314 struct bgp_path_info *bpi;
8315 struct bgp_path_info rmap_path;
9bcb3eef 8316 struct bgp_dest *bn;
d62a17ae 8317 struct attr attr;
8318 struct attr *new_attr;
8319 afi_t afi;
b68885f9 8320 route_map_result_t ret;
d62a17ae 8321 struct bgp_redist *red;
8322
8323 /* Make default attribute. */
8324 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8325 /*
8326 * This must not be NULL to satisfy Coverity SA
8327 */
8328 assert(attr.aspath);
9de1f7ff 8329
a4d82a8a 8330 switch (nhtype) {
9de1f7ff
DS
8331 case NEXTHOP_TYPE_IFINDEX:
8332 break;
8333 case NEXTHOP_TYPE_IPV4:
8334 case NEXTHOP_TYPE_IPV4_IFINDEX:
8335 attr.nexthop = nexthop->ipv4;
8336 break;
8337 case NEXTHOP_TYPE_IPV6:
8338 case NEXTHOP_TYPE_IPV6_IFINDEX:
8339 attr.mp_nexthop_global = nexthop->ipv6;
8340 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8341 break;
8342 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8343 switch (p->family) {
8344 case AF_INET:
9de1f7ff 8345 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8346 break;
8347 case AF_INET6:
9de1f7ff
DS
8348 memset(&attr.mp_nexthop_global, 0,
8349 sizeof(attr.mp_nexthop_global));
74489921 8350 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8351 break;
74489921 8352 }
0789eb69 8353 attr.bh_type = bhtype;
9de1f7ff 8354 break;
d62a17ae 8355 }
0789eb69 8356 attr.nh_type = nhtype;
74489921 8357 attr.nh_ifindex = ifindex;
f04a80a5 8358
d62a17ae 8359 attr.med = metric;
957f74c3 8360 attr.distance = distance;
d62a17ae 8361 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8362 attr.tag = tag;
718e3744 8363
d62a17ae 8364 afi = family2afi(p->family);
6aeb9e78 8365
d62a17ae 8366 red = bgp_redist_lookup(bgp, afi, type, instance);
8367 if (red) {
8368 struct attr attr_new;
718e3744 8369
d62a17ae 8370 /* Copy attribute for modification. */
6f4f49b2 8371 attr_new = attr;
718e3744 8372
d62a17ae 8373 if (red->redist_metric_flag)
8374 attr_new.med = red->redist_metric;
718e3744 8375
d62a17ae 8376 /* Apply route-map. */
8377 if (red->rmap.name) {
40381db7
DS
8378 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8379 rmap_path.peer = bgp->peer_self;
8380 rmap_path.attr = &attr_new;
718e3744 8381
d62a17ae 8382 SET_FLAG(bgp->peer_self->rmap_type,
8383 PEER_RMAP_TYPE_REDISTRIBUTE);
8384
1782514f 8385 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8386
8387 bgp->peer_self->rmap_type = 0;
8388
8389 if (ret == RMAP_DENYMATCH) {
8390 /* Free uninterned attribute. */
8391 bgp_attr_flush(&attr_new);
8392
8393 /* Unintern original. */
8394 aspath_unintern(&attr.aspath);
8395 bgp_redistribute_delete(bgp, p, type, instance);
8396 return;
8397 }
8398 }
8399
637e5ba4 8400 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8401 bgp_attr_add_gshut_community(&attr_new);
8402
d62a17ae 8403 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8404 SAFI_UNICAST, p, NULL);
8405
8406 new_attr = bgp_attr_intern(&attr_new);
8407
9bcb3eef 8408 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8409 if (bpi->peer == bgp->peer_self
8410 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8411 break;
8412
40381db7 8413 if (bpi) {
d62a17ae 8414 /* Ensure the (source route) type is updated. */
40381db7
DS
8415 bpi->type = type;
8416 if (attrhash_cmp(bpi->attr, new_attr)
8417 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8418 bgp_attr_unintern(&new_attr);
8419 aspath_unintern(&attr.aspath);
9bcb3eef 8420 bgp_dest_unlock_node(bn);
d62a17ae 8421 return;
8422 } else {
8423 /* The attribute is changed. */
40381db7 8424 bgp_path_info_set_flag(bn, bpi,
18ee8310 8425 BGP_PATH_ATTR_CHANGED);
d62a17ae 8426
8427 /* Rewrite BGP route information. */
40381db7
DS
8428 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8429 bgp_path_info_restore(bn, bpi);
d62a17ae 8430 else
40381db7
DS
8431 bgp_aggregate_decrement(
8432 bgp, p, bpi, afi, SAFI_UNICAST);
8433 bgp_attr_unintern(&bpi->attr);
8434 bpi->attr = new_attr;
8435 bpi->uptime = bgp_clock();
d62a17ae 8436
8437 /* Process change. */
40381db7 8438 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8439 SAFI_UNICAST);
8440 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8441 bgp_dest_unlock_node(bn);
d62a17ae 8442 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8443
8444 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8445 || (bgp->inst_type
8446 == BGP_INSTANCE_TYPE_DEFAULT)) {
8447
8448 vpn_leak_from_vrf_update(
40381db7 8449 bgp_get_default(), bgp, bpi);
ddb5b488 8450 }
d62a17ae 8451 return;
8452 }
8453 }
8454
8455 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8456 bgp->peer_self, new_attr, bn);
1defdda8 8457 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8458
8459 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8460 bgp_path_info_add(bn, new);
9bcb3eef 8461 bgp_dest_unlock_node(bn);
be785e35 8462 SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
d62a17ae 8463 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8464
8465 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8466 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8467
8468 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8469 }
d62a17ae 8470 }
8471
8472 /* Unintern original. */
8473 aspath_unintern(&attr.aspath);
718e3744 8474}
8475
d7c0a89a
QY
8476void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8477 unsigned short instance)
718e3744 8478{
d62a17ae 8479 afi_t afi;
9bcb3eef 8480 struct bgp_dest *dest;
40381db7 8481 struct bgp_path_info *pi;
d62a17ae 8482 struct bgp_redist *red;
718e3744 8483
d62a17ae 8484 afi = family2afi(p->family);
718e3744 8485
d62a17ae 8486 red = bgp_redist_lookup(bgp, afi, type, instance);
8487 if (red) {
9bcb3eef
DS
8488 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8489 SAFI_UNICAST, p, NULL);
d62a17ae 8490
9bcb3eef 8491 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8492 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8493 break;
8494
40381db7 8495 if (pi) {
ddb5b488
PZ
8496 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8497 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8498
8499 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8500 bgp, pi);
ddb5b488 8501 }
40381db7 8502 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8503 bgp_path_info_delete(dest, pi);
8504 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8505 }
9bcb3eef 8506 bgp_dest_unlock_node(dest);
d62a17ae 8507 }
8508}
8509
8510/* Withdraw specified route type's route. */
8511void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8512 unsigned short instance)
d62a17ae 8513{
9bcb3eef 8514 struct bgp_dest *dest;
40381db7 8515 struct bgp_path_info *pi;
d62a17ae 8516 struct bgp_table *table;
8517
8518 table = bgp->rib[afi][SAFI_UNICAST];
8519
9bcb3eef
DS
8520 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8521 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8522 if (pi->peer == bgp->peer_self && pi->type == type
8523 && pi->instance == instance)
d62a17ae 8524 break;
8525
40381db7 8526 if (pi) {
ddb5b488
PZ
8527 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8528 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8529
8530 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8531 bgp, pi);
ddb5b488 8532 }
9bcb3eef 8533 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8534 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8535 bgp_path_info_delete(dest, pi);
8536 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8537 }
718e3744 8538 }
718e3744 8539}
6b0655a2 8540
718e3744 8541/* Static function to display route. */
7d3cae70
DA
8542static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8543 struct vty *vty, json_object *json, bool wide)
718e3744 8544{
be054588 8545 int len = 0;
d62a17ae 8546 char buf[BUFSIZ];
718e3744 8547
d62a17ae 8548 if (p->family == AF_INET) {
c6462ff4 8549 if (!json) {
8228a9a7 8550 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8551 } else {
8552 json_object_string_add(json, "prefix",
8553 inet_ntop(p->family,
8554 &p->u.prefix, buf,
8555 BUFSIZ));
8556 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8557 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8558 json_object_int_add(json, "version", dest->version);
c6462ff4 8559 }
d62a17ae 8560 } else if (p->family == AF_ETHERNET) {
8228a9a7 8561 len = vty_out(vty, "%pFX", p);
b03b8898 8562 } else if (p->family == AF_EVPN) {
57f7feb6 8563 if (!json)
2dbe669b 8564 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8565 else
60466a63 8566 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8567 } else if (p->family == AF_FLOWSPEC) {
8568 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8569 json ?
8570 NLRI_STRING_FORMAT_JSON_SIMPLE :
8571 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8572 } else {
c6462ff4 8573 if (!json)
8228a9a7 8574 len = vty_out(vty, "%pFX", p);
50e05855
AD
8575 else {
8576 json_object_string_add(json, "prefix",
8577 inet_ntop(p->family,
8578 &p->u.prefix, buf,
8579 BUFSIZ));
8580 json_object_int_add(json, "prefixLen", p->prefixlen);
67d7e256 8581 json_object_string_addf(json, "network", "%pFX", p);
7d3cae70 8582 json_object_int_add(json, "version", dest->version);
37d4e0df 8583 }
9c92b5f7 8584 }
d62a17ae 8585
9c92b5f7 8586 if (!json) {
ae248832 8587 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8588 if (len < 1)
8589 vty_out(vty, "\n%*s", 20, " ");
8590 else
8591 vty_out(vty, "%*s", len, " ");
8592 }
718e3744 8593}
8594
d62a17ae 8595enum bgp_display_type {
8596 normal_list,
718e3744 8597};
8598
1d7260a1 8599const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8600{
8601 switch (reason) {
8602 case bgp_path_selection_none:
8603 return "Nothing to Select";
8604 case bgp_path_selection_first:
8605 return "First path received";
8606 case bgp_path_selection_evpn_sticky_mac:
8607 return "EVPN Sticky Mac";
8608 case bgp_path_selection_evpn_seq:
8609 return "EVPN sequence number";
8610 case bgp_path_selection_evpn_lower_ip:
8611 return "EVPN lower IP";
8612 case bgp_path_selection_evpn_local_path:
8613 return "EVPN local ES path";
8614 case bgp_path_selection_evpn_non_proxy:
8615 return "EVPN non proxy";
8616 case bgp_path_selection_weight:
8617 return "Weight";
8618 case bgp_path_selection_local_pref:
8619 return "Local Pref";
8620 case bgp_path_selection_local_route:
8621 return "Local Route";
8622 case bgp_path_selection_confed_as_path:
8623 return "Confederation based AS Path";
8624 case bgp_path_selection_as_path:
8625 return "AS Path";
8626 case bgp_path_selection_origin:
8627 return "Origin";
8628 case bgp_path_selection_med:
8629 return "MED";
8630 case bgp_path_selection_peer:
8631 return "Peer Type";
8632 case bgp_path_selection_confed:
8633 return "Confed Peer Type";
8634 case bgp_path_selection_igp_metric:
8635 return "IGP Metric";
8636 case bgp_path_selection_older:
8637 return "Older Path";
8638 case bgp_path_selection_router_id:
8639 return "Router ID";
8640 case bgp_path_selection_cluster_length:
bcab253c 8641 return "Cluster length";
bbb46eb5
DA
8642 case bgp_path_selection_stale:
8643 return "Path Staleness";
8644 case bgp_path_selection_local_configured:
8645 return "Locally configured route";
8646 case bgp_path_selection_neighbor_ip:
8647 return "Neighbor IP";
8648 case bgp_path_selection_default:
8649 return "Nothing left to compare";
8650 }
8651 return "Invalid (internal error)";
8652}
8653
18ee8310 8654/* Print the short form route status for a bgp_path_info */
4b7e6066 8655static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8656 struct bgp_path_info *path,
82c298be 8657 const struct prefix *p,
d62a17ae 8658 json_object *json_path)
718e3744 8659{
82c298be
DA
8660 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8661
d62a17ae 8662 if (json_path) {
b05a1c8b 8663
d62a17ae 8664 /* Route status display. */
9b6d8fcf 8665 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8666 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8667
9b6d8fcf 8668 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8669 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8670
4056a5f6 8671 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8672 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8673
9b6d8fcf
DS
8674 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8675 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8676 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8677
d62a17ae 8678 /* Selected */
9b6d8fcf 8679 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8680 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8681
9b6d8fcf 8682 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8683 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8684
bbb46eb5 8685 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8686 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8687 json_object_string_add(json_path, "selectionReason",
8688 bgp_path_selection_reason2str(
8689 path->net->reason));
8690 }
b05a1c8b 8691
9b6d8fcf 8692 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8693 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8694
d62a17ae 8695 /* Internal route. */
9b6d8fcf
DS
8696 if ((path->peer->as)
8697 && (path->peer->as == path->peer->local_as))
d62a17ae 8698 json_object_string_add(json_path, "pathFrom",
8699 "internal");
8700 else
8701 json_object_string_add(json_path, "pathFrom",
8702 "external");
b05a1c8b 8703
d62a17ae 8704 return;
8705 }
b05a1c8b 8706
82c298be
DA
8707 /* RPKI validation state */
8708 rpki_state =
8709 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8710
8711 if (rpki_state == RPKI_VALID)
8712 vty_out(vty, "V");
8713 else if (rpki_state == RPKI_INVALID)
8714 vty_out(vty, "I");
8715 else if (rpki_state == RPKI_NOTFOUND)
8716 vty_out(vty, "N");
8717
d62a17ae 8718 /* Route status display. */
9b6d8fcf 8719 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8720 vty_out(vty, "R");
9b6d8fcf 8721 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8722 vty_out(vty, "S");
4056a5f6 8723 else if (bgp_path_suppressed(path))
d62a17ae 8724 vty_out(vty, "s");
9b6d8fcf
DS
8725 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8726 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8727 vty_out(vty, "*");
8728 else
8729 vty_out(vty, " ");
8730
8731 /* Selected */
9b6d8fcf 8732 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8733 vty_out(vty, "h");
9b6d8fcf 8734 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8735 vty_out(vty, "d");
9b6d8fcf 8736 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8737 vty_out(vty, ">");
9b6d8fcf 8738 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8739 vty_out(vty, "=");
8740 else
8741 vty_out(vty, " ");
718e3744 8742
d62a17ae 8743 /* Internal route. */
9b6d8fcf
DS
8744 if (path->peer && (path->peer->as)
8745 && (path->peer->as == path->peer->local_as))
d62a17ae 8746 vty_out(vty, "i");
8747 else
8748 vty_out(vty, " ");
b40d939b 8749}
8750
2ba93fd6
DA
8751static char *bgp_nexthop_hostname(struct peer *peer,
8752 struct bgp_nexthop_cache *bnc)
25b5da8d 8753{
892fedb6 8754 if (peer->hostname
aef999a2 8755 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8756 return peer->hostname;
8757 return NULL;
8758}
8759
b40d939b 8760/* called from terminal list command */
bd494ec5 8761void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8762 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8763 json_object *json_paths, bool wide)
d62a17ae 8764{
aef999a2 8765 int len;
515c2602 8766 struct attr *attr = path->attr;
d62a17ae 8767 json_object *json_path = NULL;
8768 json_object *json_nexthops = NULL;
8769 json_object *json_nexthop_global = NULL;
8770 json_object *json_nexthop_ll = NULL;
6f214dd3 8771 json_object *json_ext_community = NULL;
9df8b37c 8772 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8773 bool nexthop_self =
9b6d8fcf 8774 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8775 bool nexthop_othervrf = false;
43089216 8776 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8777 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8778 char *nexthop_hostname =
8779 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8780 char esi_buf[ESI_STR_LEN];
d62a17ae 8781
8782 if (json_paths)
8783 json_path = json_object_new_object();
8784
8785 /* short status lead text */
82c298be 8786 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8787
8788 if (!json_paths) {
8789 /* print prefix and mask */
8790 if (!display)
7d3cae70 8791 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8792 else
ae248832 8793 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8794 } else {
7d3cae70 8795 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8796 }
47fc97cc 8797
9df8b37c
PZ
8798 /*
8799 * If vrf id of nexthop is different from that of prefix,
8800 * set up printable string to append
8801 */
9b6d8fcf 8802 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8803 const char *self = "";
8804
8805 if (nexthop_self)
8806 self = "<";
8807
8808 nexthop_othervrf = true;
9b6d8fcf 8809 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8810
9b6d8fcf 8811 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8812 snprintf(vrf_id_str, sizeof(vrf_id_str),
8813 "@%s%s", VRFID_NONE_STR, self);
8814 else
8815 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8816 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8817
9b6d8fcf
DS
8818 if (path->extra->bgp_orig->inst_type
8819 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8820
9b6d8fcf 8821 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8822 } else {
8823 const char *self = "";
8824
8825 if (nexthop_self)
8826 self = "<";
8827
8828 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8829 }
8830
445c2480
DS
8831 /*
8832 * For ENCAP and EVPN routes, nexthop address family is not
8833 * neccessarily the same as the prefix address family.
8834 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8835 * EVPN routes are also exchanged with a MP nexthop. Currently,
8836 * this
8837 * is only IPv4, the value will be present in either
8838 * attr->nexthop or
8839 * attr->mp_nexthop_global_in
8840 */
8841 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8842 char buf[BUFSIZ];
8843 char nexthop[128];
8844 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8845
8846 switch (af) {
8847 case AF_INET:
772270f3
QY
8848 snprintf(nexthop, sizeof(nexthop), "%s",
8849 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8850 BUFSIZ));
445c2480
DS
8851 break;
8852 case AF_INET6:
772270f3
QY
8853 snprintf(nexthop, sizeof(nexthop), "%s",
8854 inet_ntop(af, &attr->mp_nexthop_global, buf,
8855 BUFSIZ));
445c2480
DS
8856 break;
8857 default:
772270f3 8858 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8859 break;
d62a17ae 8860 }
d62a17ae 8861
445c2480
DS
8862 if (json_paths) {
8863 json_nexthop_global = json_object_new_object();
8864
515c2602
DA
8865 json_object_string_add(json_nexthop_global, "ip",
8866 nexthop);
8867
939a97f4 8868 if (path->peer->hostname)
515c2602
DA
8869 json_object_string_add(json_nexthop_global,
8870 "hostname",
939a97f4 8871 path->peer->hostname);
515c2602
DA
8872
8873 json_object_string_add(json_nexthop_global, "afi",
8874 (af == AF_INET) ? "ipv4"
8875 : "ipv6");
445c2480
DS
8876 json_object_boolean_true_add(json_nexthop_global,
8877 "used");
aef999a2
DA
8878 } else {
8879 if (nexthop_hostname)
8880 len = vty_out(vty, "%s(%s)%s", nexthop,
8881 nexthop_hostname, vrf_id_str);
8882 else
8883 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8884
ae248832 8885 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8886 if (len < 1)
8887 vty_out(vty, "\n%*s", 36, " ");
8888 else
8889 vty_out(vty, "%*s", len, " ");
8890 }
445c2480
DS
8891 } else if (safi == SAFI_EVPN) {
8892 if (json_paths) {
8893 json_nexthop_global = json_object_new_object();
8894
c949c771
DA
8895 json_object_string_addf(json_nexthop_global, "ip",
8896 "%pI4", &attr->nexthop);
515c2602 8897
939a97f4 8898 if (path->peer->hostname)
515c2602
DA
8899 json_object_string_add(json_nexthop_global,
8900 "hostname",
939a97f4 8901 path->peer->hostname);
515c2602 8902
a4d82a8a
PZ
8903 json_object_string_add(json_nexthop_global, "afi",
8904 "ipv4");
445c2480
DS
8905 json_object_boolean_true_add(json_nexthop_global,
8906 "used");
aef999a2
DA
8907 } else {
8908 if (nexthop_hostname)
8909 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8910 nexthop_hostname, vrf_id_str);
8911 else
8912 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8913 vrf_id_str);
8914
ae248832 8915 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8916 if (len < 1)
8917 vty_out(vty, "\n%*s", 36, " ");
8918 else
8919 vty_out(vty, "%*s", len, " ");
8920 }
d33fc23b 8921 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8922 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
8923 if (json_paths) {
8924 json_nexthop_global = json_object_new_object();
515c2602 8925
026b914a
PG
8926 json_object_string_add(json_nexthop_global,
8927 "afi", "ipv4");
c949c771
DA
8928 json_object_string_addf(json_nexthop_global,
8929 "ip", "%pI4",
8930 &attr->nexthop);
515c2602 8931
939a97f4 8932 if (path->peer->hostname)
515c2602
DA
8933 json_object_string_add(
8934 json_nexthop_global, "hostname",
939a97f4 8935 path->peer->hostname);
515c2602 8936
50e05855
AD
8937 json_object_boolean_true_add(
8938 json_nexthop_global,
026b914a
PG
8939 "used");
8940 } else {
aef999a2
DA
8941 if (nexthop_hostname)
8942 len = vty_out(vty, "%pI4(%s)%s",
8943 &attr->nexthop,
8944 nexthop_hostname,
8945 vrf_id_str);
8946 else
8947 len = vty_out(vty, "%pI4%s",
8948 &attr->nexthop,
8949 vrf_id_str);
8950
ae248832 8951 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8952 if (len < 1)
8953 vty_out(vty, "\n%*s", 36, " ");
8954 else
8955 vty_out(vty, "%*s", len, " ");
026b914a
PG
8956 }
8957 }
d33fc23b 8958 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8959 if (json_paths) {
8960 json_nexthop_global = json_object_new_object();
d62a17ae 8961
c949c771
DA
8962 json_object_string_addf(json_nexthop_global, "ip",
8963 "%pI4", &attr->nexthop);
515c2602 8964
939a97f4 8965 if (path->peer->hostname)
515c2602
DA
8966 json_object_string_add(json_nexthop_global,
8967 "hostname",
939a97f4 8968 path->peer->hostname);
445c2480 8969
a4d82a8a
PZ
8970 json_object_string_add(json_nexthop_global, "afi",
8971 "ipv4");
445c2480
DS
8972 json_object_boolean_true_add(json_nexthop_global,
8973 "used");
8974 } else {
aef999a2
DA
8975 if (nexthop_hostname)
8976 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8977 nexthop_hostname, vrf_id_str);
8978 else
8979 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8980 vrf_id_str);
9df8b37c 8981
ae248832 8982 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8983 if (len < 1)
8984 vty_out(vty, "\n%*s", 36, " ");
8985 else
8986 vty_out(vty, "%*s", len, " ");
d62a17ae 8987 }
445c2480 8988 }
b05a1c8b 8989
445c2480 8990 /* IPv6 Next Hop */
a4d82a8a 8991 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
8992 if (json_paths) {
8993 json_nexthop_global = json_object_new_object();
c949c771
DA
8994 json_object_string_addf(json_nexthop_global, "ip",
8995 "%pI6",
8996 &attr->mp_nexthop_global);
515c2602 8997
939a97f4 8998 if (path->peer->hostname)
515c2602
DA
8999 json_object_string_add(json_nexthop_global,
9000 "hostname",
939a97f4 9001 path->peer->hostname);
515c2602 9002
a4d82a8a
PZ
9003 json_object_string_add(json_nexthop_global, "afi",
9004 "ipv6");
9005 json_object_string_add(json_nexthop_global, "scope",
9006 "global");
445c2480
DS
9007
9008 /* We display both LL & GL if both have been
9009 * received */
0606039c
DA
9010 if ((attr->mp_nexthop_len
9011 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 9012 || (path->peer->conf_if)) {
a4d82a8a 9013 json_nexthop_ll = json_object_new_object();
c949c771
DA
9014 json_object_string_addf(
9015 json_nexthop_ll, "ip", "%pI6",
9016 &attr->mp_nexthop_local);
515c2602 9017
939a97f4 9018 if (path->peer->hostname)
515c2602
DA
9019 json_object_string_add(
9020 json_nexthop_ll, "hostname",
939a97f4 9021 path->peer->hostname);
515c2602 9022
a4d82a8a
PZ
9023 json_object_string_add(json_nexthop_ll, "afi",
9024 "ipv6");
9025 json_object_string_add(json_nexthop_ll, "scope",
445c2480 9026 "link-local");
d62a17ae 9027
a4d82a8a
PZ
9028 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
9029 &attr->mp_nexthop_local)
445c2480
DS
9030 != 0)
9031 && !attr->mp_nexthop_prefer_global)
d62a17ae 9032 json_object_boolean_true_add(
a4d82a8a 9033 json_nexthop_ll, "used");
445c2480
DS
9034 else
9035 json_object_boolean_true_add(
a4d82a8a 9036 json_nexthop_global, "used");
445c2480
DS
9037 } else
9038 json_object_boolean_true_add(
9039 json_nexthop_global, "used");
9040 } else {
9041 /* Display LL if LL/Global both in table unless
9042 * prefer-global is set */
0606039c
DA
9043 if (((attr->mp_nexthop_len
9044 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 9045 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
9046 || (path->peer->conf_if)) {
9047 if (path->peer->conf_if) {
a4d82a8a 9048 len = vty_out(vty, "%s",
9b6d8fcf 9049 path->peer->conf_if);
ae248832
MK
9050 /* len of IPv6 addr + max len of def
9051 * ifname */
9052 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9053
9054 if (len < 1)
a4d82a8a 9055 vty_out(vty, "\n%*s", 36, " ");
445c2480 9056 else
a4d82a8a 9057 vty_out(vty, "%*s", len, " ");
d62a17ae 9058 } else {
aef999a2
DA
9059 if (nexthop_hostname)
9060 len = vty_out(
9061 vty, "%pI6(%s)%s",
9062 &attr->mp_nexthop_local,
9063 nexthop_hostname,
9064 vrf_id_str);
9065 else
9066 len = vty_out(
9067 vty, "%pI6%s",
9068 &attr->mp_nexthop_local,
9069 vrf_id_str);
9070
ae248832 9071 len = wide ? (41 - len) : (16 - len);
d62a17ae 9072
9073 if (len < 1)
a4d82a8a 9074 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9075 else
a4d82a8a 9076 vty_out(vty, "%*s", len, " ");
d62a17ae 9077 }
445c2480 9078 } else {
aef999a2
DA
9079 if (nexthop_hostname)
9080 len = vty_out(vty, "%pI6(%s)%s",
9081 &attr->mp_nexthop_global,
9082 nexthop_hostname,
9083 vrf_id_str);
9084 else
9085 len = vty_out(vty, "%pI6%s",
9086 &attr->mp_nexthop_global,
9087 vrf_id_str);
9088
ae248832 9089 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9090
9091 if (len < 1)
9092 vty_out(vty, "\n%*s", 36, " ");
9093 else
9094 vty_out(vty, "%*s", len, " ");
d62a17ae 9095 }
9096 }
445c2480 9097 }
718e3744 9098
445c2480
DS
9099 /* MED/Metric */
9100 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9101 if (json_paths)
50e05855 9102 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9103 else if (wide)
9104 vty_out(vty, "%7u", attr->med);
0fbac0b4 9105 else
445c2480 9106 vty_out(vty, "%10u", attr->med);
ae248832
MK
9107 else if (!json_paths) {
9108 if (wide)
9109 vty_out(vty, "%*s", 7, " ");
9110 else
9111 vty_out(vty, "%*s", 10, " ");
9112 }
d62a17ae 9113
445c2480
DS
9114 /* Local Pref */
9115 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9116 if (json_paths)
50e05855 9117 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9118 attr->local_pref);
9119 else
445c2480
DS
9120 vty_out(vty, "%7u", attr->local_pref);
9121 else if (!json_paths)
9122 vty_out(vty, " ");
d62a17ae 9123
445c2480
DS
9124 if (json_paths)
9125 json_object_int_add(json_path, "weight", attr->weight);
9126 else
9127 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9128
445c2480
DS
9129 if (json_paths) {
9130 char buf[BUFSIZ];
a4d82a8a
PZ
9131 json_object_string_add(
9132 json_path, "peerId",
9b6d8fcf 9133 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9134 }
b05a1c8b 9135
445c2480
DS
9136 /* Print aspath */
9137 if (attr->aspath) {
0fbac0b4 9138 if (json_paths)
50e05855 9139 json_object_string_add(json_path, "path",
0fbac0b4
DA
9140 attr->aspath->str);
9141 else
445c2480 9142 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9143 }
f1aa5d8a 9144
445c2480
DS
9145 /* Print origin */
9146 if (json_paths)
a4d82a8a
PZ
9147 json_object_string_add(json_path, "origin",
9148 bgp_origin_long_str[attr->origin]);
445c2480
DS
9149 else
9150 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9151
9df8b37c 9152 if (json_paths) {
d071f237 9153 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9154 json_object_string_add(json_path, "esi",
9155 esi_to_str(&attr->esi,
9156 esi_buf, sizeof(esi_buf)));
9157 }
6f214dd3
CS
9158 if (safi == SAFI_EVPN &&
9159 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9160 json_ext_community = json_object_new_object();
b53e67a3
DA
9161 json_object_string_add(
9162 json_ext_community, "string",
9163 bgp_attr_get_ecommunity(attr)->str);
6f214dd3
CS
9164 json_object_object_add(json_path,
9165 "extendedCommunity",
9166 json_ext_community);
9167 }
9168
9df8b37c
PZ
9169 if (nexthop_self)
9170 json_object_boolean_true_add(json_path,
9171 "announceNexthopSelf");
9172 if (nexthop_othervrf) {
9173 json_object_string_add(json_path, "nhVrfName",
9174 nexthop_vrfname);
9175
9176 json_object_int_add(json_path, "nhVrfId",
9177 ((nexthop_vrfid == VRF_UNKNOWN)
9178 ? -1
9179 : (int)nexthop_vrfid));
9180 }
9181 }
9182
d62a17ae 9183 if (json_paths) {
9184 if (json_nexthop_global || json_nexthop_ll) {
9185 json_nexthops = json_object_new_array();
f1aa5d8a 9186
d62a17ae 9187 if (json_nexthop_global)
9188 json_object_array_add(json_nexthops,
9189 json_nexthop_global);
f1aa5d8a 9190
d62a17ae 9191 if (json_nexthop_ll)
9192 json_object_array_add(json_nexthops,
9193 json_nexthop_ll);
f1aa5d8a 9194
d62a17ae 9195 json_object_object_add(json_path, "nexthops",
9196 json_nexthops);
9197 }
9198
9199 json_object_array_add(json_paths, json_path);
9200 } else {
9201 vty_out(vty, "\n");
6f214dd3 9202
b5e140c8 9203 if (safi == SAFI_EVPN) {
d071f237 9204 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9205 /* XXX - add these params to the json out */
b5e140c8 9206 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9207 vty_out(vty, "ESI:%s",
9208 esi_to_str(&attr->esi, esi_buf,
9209 sizeof(esi_buf)));
60605cbc 9210
229587fb 9211 vty_out(vty, "\n");
b5e140c8
AK
9212 }
9213 if (attr->flag &
9214 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9215 vty_out(vty, "%*s", 20, " ");
b53e67a3
DA
9216 vty_out(vty, "%s\n",
9217 bgp_attr_get_ecommunity(attr)->str);
b5e140c8 9218 }
6f214dd3
CS
9219 }
9220
49e5a4a0 9221#ifdef ENABLE_BGP_VNC
d62a17ae 9222 /* prints an additional line, indented, with VNC info, if
9223 * present */
9224 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9225 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9226#endif
d62a17ae 9227 }
9228}
718e3744 9229
9230/* called from terminal list command */
7d3cae70
DA
9231void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9232 const struct prefix *p, struct attr *attr, safi_t safi,
9233 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9234{
9235 json_object *json_status = NULL;
9236 json_object *json_net = NULL;
aef999a2 9237 int len;
d62a17ae 9238 char buff[BUFSIZ];
dc387b0f 9239
d62a17ae 9240 /* Route status display. */
9241 if (use_json) {
9242 json_status = json_object_new_object();
9243 json_net = json_object_new_object();
9244 } else {
9245 vty_out(vty, "*");
9246 vty_out(vty, ">");
9247 vty_out(vty, " ");
9248 }
718e3744 9249
d62a17ae 9250 /* print prefix and mask */
50e05855 9251 if (use_json) {
dc387b0f
LK
9252 if (safi == SAFI_EVPN)
9253 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9254 else if (p->family == AF_INET || p->family == AF_INET6) {
9255 json_object_string_add(
9256 json_net, "addrPrefix",
9257 inet_ntop(p->family, &p->u.prefix, buff,
9258 BUFSIZ));
9259 json_object_int_add(json_net, "prefixLen",
9260 p->prefixlen);
67d7e256 9261 json_object_string_addf(json_net, "network", "%pFX", p);
dc387b0f 9262 }
50e05855 9263 } else
7d3cae70 9264 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9265
9266 /* Print attribute */
9267 if (attr) {
9268 if (use_json) {
9269 if (p->family == AF_INET
9270 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9271 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9272 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
c949c771
DA
9273 json_object_string_addf(
9274 json_net, "nextHop", "%pI4",
9275 &attr->mp_nexthop_global_in);
d62a17ae 9276 else
c949c771
DA
9277 json_object_string_addf(
9278 json_net, "nextHop", "%pI4",
9279 &attr->nexthop);
d62a17ae 9280 } else if (p->family == AF_INET6
9281 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9282 json_object_string_addf(
9283 json_net, "nextHopGlobal", "%pI6",
9284 &attr->mp_nexthop_global);
23d0a753
DA
9285 } else if (p->family == AF_EVPN
9286 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
c949c771
DA
9287 json_object_string_addf(
9288 json_net, "nextHop", "%pI4",
9289 &attr->mp_nexthop_global_in);
23d0a753 9290 }
d62a17ae 9291
9292 if (attr->flag
9293 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9294 json_object_int_add(json_net, "metric",
9295 attr->med);
9296
0fbac0b4 9297 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9298 json_object_int_add(json_net, "locPrf",
0fbac0b4 9299 attr->local_pref);
d62a17ae 9300
9301 json_object_int_add(json_net, "weight", attr->weight);
9302
9303 /* Print aspath */
0fbac0b4 9304 if (attr->aspath)
50e05855 9305 json_object_string_add(json_net, "path",
0fbac0b4 9306 attr->aspath->str);
d62a17ae 9307
9308 /* Print origin */
9309 json_object_string_add(json_net, "bgpOriginCode",
9310 bgp_origin_str[attr->origin]);
9311 } else {
9312 if (p->family == AF_INET
9313 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9314 || safi == SAFI_EVPN
9315 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9316 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9317 || safi == SAFI_EVPN)
23d0a753
DA
9318 vty_out(vty, "%-16pI4",
9319 &attr->mp_nexthop_global_in);
ae248832 9320 else if (wide)
23d0a753 9321 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9322 else
23d0a753 9323 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9324 } else if (p->family == AF_INET6
9325 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9326 char buf[BUFSIZ];
9327
9328 len = vty_out(
9329 vty, "%s",
9330 inet_ntop(AF_INET6,
9331 &attr->mp_nexthop_global, buf,
9332 BUFSIZ));
ae248832 9333 len = wide ? (41 - len) : (16 - len);
d62a17ae 9334 if (len < 1)
9335 vty_out(vty, "\n%*s", 36, " ");
9336 else
9337 vty_out(vty, "%*s", len, " ");
9338 }
9339 if (attr->flag
9340 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9341 if (wide)
9342 vty_out(vty, "%7u", attr->med);
9343 else
9344 vty_out(vty, "%10u", attr->med);
9345 else if (wide)
9346 vty_out(vty, " ");
d62a17ae 9347 else
9348 vty_out(vty, " ");
718e3744 9349
d62a17ae 9350 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9351 vty_out(vty, "%7u", attr->local_pref);
9352 else
9353 vty_out(vty, " ");
9354
9355 vty_out(vty, "%7u ", attr->weight);
9356
9357 /* Print aspath */
9358 if (attr->aspath)
9359 aspath_print_vty(vty, "%s", attr->aspath, " ");
9360
9361 /* Print origin */
9362 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9363 }
9364 }
9365 if (use_json) {
9366 json_object_boolean_true_add(json_status, "*");
9367 json_object_boolean_true_add(json_status, ">");
9368 json_object_object_add(json_net, "appliedStatusSymbols",
9369 json_status);
1608ff77 9370
dc387b0f
LK
9371 prefix2str(p, buff, PREFIX_STRLEN);
9372 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9373 } else
9374 vty_out(vty, "\n");
9375}
9376
bd494ec5 9377void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9378 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9379 json_object *json)
9380{
9381 json_object *json_out = NULL;
9382 struct attr *attr;
9383 mpls_label_t label = MPLS_INVALID_LABEL;
9384
9b6d8fcf 9385 if (!path->extra)
d62a17ae 9386 return;
9387
9388 if (json)
9389 json_out = json_object_new_object();
9390
9391 /* short status lead text */
82c298be 9392 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9393
9394 /* print prefix and mask */
9395 if (json == NULL) {
9396 if (!display)
7d3cae70 9397 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9398 else
9399 vty_out(vty, "%*s", 17, " ");
9400 }
9401
9402 /* Print attribute */
9b6d8fcf 9403 attr = path->attr;
05864da7
DS
9404 if (((p->family == AF_INET)
9405 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9406 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9407 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9408 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9409 || safi == SAFI_EVPN) {
9410 if (json)
c949c771
DA
9411 json_object_string_addf(
9412 json_out, "mpNexthopGlobalIn", "%pI4",
9413 &attr->mp_nexthop_global_in);
05864da7 9414 else
23d0a753
DA
9415 vty_out(vty, "%-16pI4",
9416 &attr->mp_nexthop_global_in);
05864da7
DS
9417 } else {
9418 if (json)
c949c771
DA
9419 json_object_string_addf(json_out, "nexthop",
9420 "%pI4", &attr->nexthop);
05864da7 9421 else
23d0a753 9422 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9423 }
9424 } else if (((p->family == AF_INET6)
9425 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9426 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9427 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9428 char buf_a[512];
9429
9430 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9431 if (json)
c949c771
DA
9432 json_object_string_addf(
9433 json_out, "mpNexthopGlobalIn", "%pI6",
9434 &attr->mp_nexthop_global);
05864da7
DS
9435 else
9436 vty_out(vty, "%s",
9437 inet_ntop(AF_INET6,
9438 &attr->mp_nexthop_global,
9439 buf_a, sizeof(buf_a)));
9440 } else if (attr->mp_nexthop_len
9441 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9442 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9443 &attr->mp_nexthop_global,
9444 &attr->mp_nexthop_local);
9445 if (json)
9446 json_object_string_add(json_out,
9447 "mpNexthopGlobalLocal",
9448 buf_a);
9449 else
9450 vty_out(vty, "%s", buf_a);
d62a17ae 9451 }
9452 }
9453
9b6d8fcf 9454 label = decode_label(&path->extra->label[0]);
d62a17ae 9455
9456 if (bgp_is_valid_label(&label)) {
9457 if (json) {
9458 json_object_int_add(json_out, "notag", label);
9459 json_object_array_add(json, json_out);
9460 } else {
9461 vty_out(vty, "notag/%d", label);
9462 vty_out(vty, "\n");
9463 }
700ddfed
PG
9464 } else if (!json)
9465 vty_out(vty, "\n");
d62a17ae 9466}
718e3744 9467
bd494ec5 9468void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9469 struct bgp_path_info *path, int display,
d62a17ae 9470 json_object *json_paths)
718e3744 9471{
d62a17ae 9472 struct attr *attr;
14f51eba 9473 char buf[BUFSIZ] = {0};
d62a17ae 9474 json_object *json_path = NULL;
14f51eba
LK
9475 json_object *json_nexthop = NULL;
9476 json_object *json_overlay = NULL;
856ca177 9477
9b6d8fcf 9478 if (!path->extra)
d62a17ae 9479 return;
718e3744 9480
14f51eba
LK
9481 if (json_paths) {
9482 json_path = json_object_new_object();
9483 json_overlay = json_object_new_object();
9484 json_nexthop = json_object_new_object();
9485 }
9486
d62a17ae 9487 /* short status lead text */
82c298be 9488 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9489
d62a17ae 9490 /* print prefix and mask */
9491 if (!display)
7d3cae70 9492 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9493 else
9494 vty_out(vty, "%*s", 17, " ");
9495
9496 /* Print attribute */
9b6d8fcf 9497 attr = path->attr;
05864da7
DS
9498 char buf1[BUFSIZ];
9499 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9500
05864da7
DS
9501 switch (af) {
9502 case AF_INET:
9503 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9504 if (!json_path) {
9505 vty_out(vty, "%-16s", buf);
9506 } else {
9507 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9508
05864da7 9509 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9510
05864da7
DS
9511 json_object_object_add(json_path, "nexthop",
9512 json_nexthop);
9513 }
9514 break;
9515 case AF_INET6:
9516 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9517 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9518 if (!json_path) {
9519 vty_out(vty, "%s(%s)", buf, buf1);
9520 } else {
9521 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9522
05864da7
DS
9523 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9524 buf1);
14f51eba 9525
05864da7 9526 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9527
05864da7
DS
9528 json_object_object_add(json_path, "nexthop",
9529 json_nexthop);
9530 }
9531 break;
9532 default:
9533 if (!json_path) {
9534 vty_out(vty, "?");
9535 } else {
9536 json_object_string_add(json_nexthop, "Error",
9537 "Unsupported address-family");
d62a17ae 9538 }
05864da7 9539 }
988258b4 9540
6c924775
DS
9541 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9542
860e740b 9543 ipaddr2str(&eo->gw_ip, buf, BUFSIZ);
14f51eba 9544
05864da7
DS
9545 if (!json_path)
9546 vty_out(vty, "/%s", buf);
9547 else
9548 json_object_string_add(json_overlay, "gw", buf);
9549
b53e67a3 9550 if (bgp_attr_get_ecommunity(attr)) {
05864da7
DS
9551 char *mac = NULL;
9552 struct ecommunity_val *routermac = ecommunity_lookup(
b53e67a3 9553 bgp_attr_get_ecommunity(attr), ECOMMUNITY_ENCODE_EVPN,
05864da7
DS
9554 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9555
9556 if (routermac)
9557 mac = ecom_mac2str((char *)routermac->val);
9558 if (mac) {
9559 if (!json_path) {
c4efd0f4 9560 vty_out(vty, "/%s", mac);
05864da7
DS
9561 } else {
9562 json_object_string_add(json_overlay, "rmac",
9563 mac);
988258b4 9564 }
05864da7 9565 XFREE(MTYPE_TMP, mac);
988258b4 9566 }
05864da7 9567 }
718e3744 9568
05864da7
DS
9569 if (!json_path) {
9570 vty_out(vty, "\n");
9571 } else {
9572 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9573
05864da7 9574 json_object_array_add(json_paths, json_path);
14f51eba 9575 }
d62a17ae 9576}
718e3744 9577
d62a17ae 9578/* dampening route */
5f040085
DS
9579static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9580 struct bgp_path_info *path, int display,
9581 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9582 json_object *json_paths)
d62a17ae 9583{
e5be8c1d 9584 struct attr *attr = path->attr;
d62a17ae 9585 int len;
9586 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9587 json_object *json_path = NULL;
9588
9589 if (use_json)
9590 json_path = json_object_new_object();
d62a17ae 9591
9592 /* short status lead text */
e5be8c1d 9593 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9594
9595 /* print prefix and mask */
9596 if (!use_json) {
9597 if (!display)
7d3cae70 9598 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9599 else
9600 vty_out(vty, "%*s", 17, " ");
d62a17ae 9601
e5be8c1d
DA
9602 len = vty_out(vty, "%s", path->peer->host);
9603 len = 17 - len;
9604
9605 if (len < 1)
d62a17ae 9606 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9607 else
9608 vty_out(vty, "%*s", len, " ");
d62a17ae 9609
9b6d8fcf
DS
9610 vty_out(vty, "%s ",
9611 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9612 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9613 use_json, NULL));
d62a17ae 9614
e5be8c1d 9615 if (attr->aspath)
05864da7 9616 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9617
05864da7
DS
9618 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9619
d62a17ae 9620 vty_out(vty, "\n");
e5be8c1d
DA
9621 } else {
9622 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9623 safi, use_json, json_path);
9624
9625 if (attr->aspath)
9626 json_object_string_add(json_path, "asPath",
9627 attr->aspath->str);
9628
9629 json_object_string_add(json_path, "origin",
9630 bgp_origin_str[attr->origin]);
9631 json_object_string_add(json_path, "peerHost", path->peer->host);
9632
9633 json_object_array_add(json_paths, json_path);
9634 }
d62a17ae 9635}
718e3744 9636
d62a17ae 9637/* flap route */
5f040085
DS
9638static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9639 struct bgp_path_info *path, int display,
9640 afi_t afi, safi_t safi, bool use_json,
31258046 9641 json_object *json_paths)
784d3a42 9642{
31258046 9643 struct attr *attr = path->attr;
d62a17ae 9644 struct bgp_damp_info *bdi;
9645 char timebuf[BGP_UPTIME_LEN];
9646 int len;
31258046 9647 json_object *json_path = NULL;
784d3a42 9648
9b6d8fcf 9649 if (!path->extra)
d62a17ae 9650 return;
784d3a42 9651
31258046
DA
9652 if (use_json)
9653 json_path = json_object_new_object();
9654
9b6d8fcf 9655 bdi = path->extra->damp_info;
784d3a42 9656
d62a17ae 9657 /* short status lead text */
31258046 9658 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9659
d62a17ae 9660 if (!use_json) {
9661 if (!display)
7d3cae70 9662 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9663 else
9664 vty_out(vty, "%*s", 17, " ");
784d3a42 9665
31258046
DA
9666 len = vty_out(vty, "%s", path->peer->host);
9667 len = 16 - len;
9668 if (len < 1)
d62a17ae 9669 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9670 else
9671 vty_out(vty, "%*s", len, " ");
784d3a42 9672
31258046
DA
9673 len = vty_out(vty, "%d", bdi->flap);
9674 len = 5 - len;
9675 if (len < 1)
d62a17ae 9676 vty_out(vty, " ");
d62a17ae 9677 else
9678 vty_out(vty, "%*s", len, " ");
d62a17ae 9679
996c9314
LB
9680 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9681 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9682
31258046
DA
9683 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9684 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9685 vty_out(vty, "%s ",
9b6d8fcf 9686 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9687 BGP_UPTIME_LEN, afi,
31258046
DA
9688 safi, use_json, NULL));
9689 else
d62a17ae 9690 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9691
31258046 9692 if (attr->aspath)
05864da7 9693 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9694
05864da7
DS
9695 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9696
d62a17ae 9697 vty_out(vty, "\n");
31258046
DA
9698 } else {
9699 json_object_string_add(json_path, "peerHost", path->peer->host);
9700 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9701
9702 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9703 json_path);
9704
9705 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9706 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9707 bgp_damp_reuse_time_vty(vty, path, timebuf,
9708 BGP_UPTIME_LEN, afi, safi,
9709 use_json, json_path);
9710
9711 if (attr->aspath)
9712 json_object_string_add(json_path, "asPath",
9713 attr->aspath->str);
9714
9715 json_object_string_add(json_path, "origin",
9716 bgp_origin_str[attr->origin]);
9717
9718 json_object_array_add(json_paths, json_path);
9719 }
d62a17ae 9720}
9721
9722static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9723 int *first, const char *header,
9724 json_object *json_adv_to)
9725{
9726 char buf1[INET6_ADDRSTRLEN];
9727 json_object *json_peer = NULL;
9728
9729 if (json_adv_to) {
9730 /* 'advertised-to' is a dictionary of peers we have advertised
9731 * this
9732 * prefix too. The key is the peer's IP or swpX, the value is
9733 * the
9734 * hostname if we know it and "" if not.
9735 */
9736 json_peer = json_object_new_object();
9737
9738 if (peer->hostname)
9739 json_object_string_add(json_peer, "hostname",
9740 peer->hostname);
9741
9742 if (peer->conf_if)
9743 json_object_object_add(json_adv_to, peer->conf_if,
9744 json_peer);
9745 else
9746 json_object_object_add(
9747 json_adv_to,
9748 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9749 json_peer);
9750 } else {
9751 if (*first) {
9752 vty_out(vty, "%s", header);
9753 *first = 0;
9754 }
9755
9756 if (peer->hostname
892fedb6 9757 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9758 if (peer->conf_if)
9759 vty_out(vty, " %s(%s)", peer->hostname,
9760 peer->conf_if);
9761 else
9762 vty_out(vty, " %s(%s)", peer->hostname,
9763 sockunion2str(&peer->su, buf1,
9764 SU_ADDRSTRLEN));
9765 } else {
9766 if (peer->conf_if)
9767 vty_out(vty, " %s", peer->conf_if);
9768 else
9769 vty_out(vty, " %s",
9770 sockunion2str(&peer->su, buf1,
9771 SU_ADDRSTRLEN));
9772 }
9773 }
784d3a42
PG
9774}
9775
dcc68b5e
MS
9776static void route_vty_out_tx_ids(struct vty *vty,
9777 struct bgp_addpath_info_data *d)
9778{
9779 int i;
9780
9781 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9782 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9783 d->addpath_tx_id[i],
9784 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9785 }
9786}
9787
5e4d4c8a 9788static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9789 struct bgp_path_info *pi,
9790 struct attr *attr,
9791 json_object *json_path)
5e4d4c8a
AK
9792{
9793 char esi_buf[ESI_STR_LEN];
9794 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9795 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9796 ATTR_ES_PEER_ROUTER);
9797 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9798 ATTR_ES_PEER_ACTIVE);
9799 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9800 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9801 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9802 if (json_path) {
9803 json_object *json_es_info = NULL;
9804
9805 json_object_string_add(
9806 json_path, "esi",
9807 esi_buf);
9808 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9809 json_es_info = json_object_new_object();
9810 if (es_local)
9811 json_object_boolean_true_add(
9812 json_es_info, "localEs");
9813 if (peer_active)
9814 json_object_boolean_true_add(
9815 json_es_info, "peerActive");
9816 if (peer_proxy)
9817 json_object_boolean_true_add(
9818 json_es_info, "peerProxy");
9819 if (peer_router)
9820 json_object_boolean_true_add(
9821 json_es_info, "peerRouter");
9822 if (attr->mm_sync_seqnum)
9823 json_object_int_add(
9824 json_es_info, "peerSeq",
9825 attr->mm_sync_seqnum);
9826 json_object_object_add(
9827 json_path, "es_info",
9828 json_es_info);
9829 }
9830 } else {
9831 if (bgp_evpn_attr_is_sync(attr))
9832 vty_out(vty,
9833 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9834 esi_buf,
9835 es_local ? "local-es":"",
9836 peer_proxy ? "proxy " : "",
9837 peer_active ? "active ":"",
9838 peer_router ? "router ":"",
9839 attr->mm_sync_seqnum);
9840 else
9841 vty_out(vty, " ESI %s %s\n",
9842 esi_buf,
9843 es_local ? "local-es":"");
9844 }
9845}
9846
4933eaaf
DS
9847void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9848 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9849 enum rpki_states rpki_curr_state,
9850 json_object *json_paths)
d62a17ae 9851{
9852 char buf[INET6_ADDRSTRLEN];
9853 char buf1[BUFSIZ];
515c2602 9854 struct attr *attr = path->attr;
d62a17ae 9855 int sockunion_vty_out(struct vty *, union sockunion *);
9856 time_t tbuf;
9857 json_object *json_bestpath = NULL;
9858 json_object *json_cluster_list = NULL;
9859 json_object *json_cluster_list_list = NULL;
9860 json_object *json_ext_community = NULL;
9861 json_object *json_last_update = NULL;
7fd077aa 9862 json_object *json_pmsi = NULL;
d62a17ae 9863 json_object *json_nexthop_global = NULL;
9864 json_object *json_nexthop_ll = NULL;
9865 json_object *json_nexthops = NULL;
9866 json_object *json_path = NULL;
9867 json_object *json_peer = NULL;
9868 json_object *json_string = NULL;
9869 json_object *json_adv_to = NULL;
9870 int first = 0;
9871 struct listnode *node, *nnode;
9872 struct peer *peer;
be92fc9f 9873 bool addpath_capable;
d62a17ae 9874 int has_adj;
9875 unsigned int first_as;
1defdda8 9876 bool nexthop_self =
9b6d8fcf 9877 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9878 int i;
2ba93fd6
DA
9879 char *nexthop_hostname =
9880 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9881
9882 if (json_paths) {
9883 json_path = json_object_new_object();
9884 json_peer = json_object_new_object();
9885 json_nexthop_global = json_object_new_object();
9886 }
9887
8304dabf
AD
9888 if (safi == SAFI_EVPN) {
9889 if (!json_paths)
9890 vty_out(vty, " Route %pRN", bn);
9891 }
9892
44c69747 9893 if (path->extra) {
b57ba6d2 9894 char tag_buf[30];
d62a17ae 9895
d62a17ae 9896 tag_buf[0] = '\0';
9b6d8fcf
DS
9897 if (path->extra && path->extra->num_labels) {
9898 bgp_evpn_label2str(path->extra->label,
9899 path->extra->num_labels, tag_buf,
a4d82a8a 9900 sizeof(tag_buf));
d62a17ae 9901 }
d7325ee7 9902 if (safi == SAFI_EVPN) {
44c69747 9903 if (!json_paths) {
44c69747
LK
9904 if (tag_buf[0] != '\0')
9905 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9906 } else {
9907 if (tag_buf[0])
9908 json_object_string_add(json_path, "VNI",
9909 tag_buf);
9910 }
d7325ee7
DD
9911 }
9912
44c69747 9913 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9914 struct bgp_path_info *parent_ri;
9bcb3eef 9915 struct bgp_dest *dest, *pdest;
d62a17ae 9916
9b6d8fcf 9917 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9918 dest = parent_ri->net;
9919 if (dest && dest->pdest) {
9920 pdest = dest->pdest;
9921 prefix_rd2str(
9922 (struct prefix_rd *)bgp_dest_get_prefix(
9923 pdest),
9924 buf1, sizeof(buf1));
d7325ee7 9925 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9926 vty_out(vty,
58bff4d1 9927 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9928 buf1,
9929 (struct prefix_evpn *)
9930 bgp_dest_get_prefix(
9931 dest),
9932 tag_buf);
58bff4d1
AK
9933 if (attr->es_flags & ATTR_ES_L3_NHG)
9934 vty_out(vty, ", L3NHG %s",
9935 (attr->es_flags
9936 & ATTR_ES_L3_NHG_ACTIVE)
9937 ? "active"
9938 : "inactive");
9939 vty_out(vty, "\n");
9940
d7325ee7 9941 } else
2dbe669b
DA
9942 vty_out(vty,
9943 " Imported from %s:%pFX\n",
9944 buf1,
9945 (struct prefix_evpn *)
9946 bgp_dest_get_prefix(
9947 dest));
d62a17ae 9948 }
9949 }
9950 }
d62a17ae 9951
8304dabf
AD
9952 if (safi == SAFI_EVPN
9953 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9954 char gwip_buf[INET6_ADDRSTRLEN];
9955
860e740b
IR
9956 ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf,
9957 sizeof(gwip_buf));
8304dabf
AD
9958
9959 if (json_paths)
9960 json_object_string_add(json_path, "gatewayIP",
9961 gwip_buf);
9962 else
9963 vty_out(vty, " Gateway IP %s", gwip_buf);
9964 }
9965
9966 if (safi == SAFI_EVPN)
9967 vty_out(vty, "\n");
9968
05864da7
DS
9969 /* Line1 display AS-path, Aggregator */
9970 if (attr->aspath) {
9971 if (json_paths) {
9972 if (!attr->aspath->json)
9973 aspath_str_update(attr->aspath, true);
9974 json_object_lock(attr->aspath->json);
9975 json_object_object_add(json_path, "aspath",
9976 attr->aspath->json);
9977 } else {
9978 if (attr->aspath->segments)
9979 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9980 else
05864da7 9981 vty_out(vty, " Local");
d62a17ae 9982 }
05864da7 9983 }
d62a17ae 9984
05864da7
DS
9985 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9986 if (json_paths)
9987 json_object_boolean_true_add(json_path, "removed");
9988 else
9989 vty_out(vty, ", (removed)");
9990 }
d62a17ae 9991
05864da7
DS
9992 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9993 if (json_paths)
9994 json_object_boolean_true_add(json_path, "stale");
9995 else
9996 vty_out(vty, ", (stale)");
9997 }
d62a17ae 9998
05864da7
DS
9999 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
10000 if (json_paths) {
10001 json_object_int_add(json_path, "aggregatorAs",
10002 attr->aggregator_as);
c949c771
DA
10003 json_object_string_addf(json_path, "aggregatorId",
10004 "%pI4", &attr->aggregator_addr);
05864da7 10005 } else {
88d495a9
DA
10006 vty_out(vty, ", (aggregated by %u %pI4)",
10007 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 10008 }
05864da7 10009 }
d62a17ae 10010
05864da7
DS
10011 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10012 PEER_FLAG_REFLECTOR_CLIENT)) {
10013 if (json_paths)
10014 json_object_boolean_true_add(json_path,
10015 "rxedFromRrClient");
10016 else
10017 vty_out(vty, ", (Received from a RR-client)");
10018 }
d62a17ae 10019
05864da7
DS
10020 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
10021 PEER_FLAG_RSERVER_CLIENT)) {
10022 if (json_paths)
10023 json_object_boolean_true_add(json_path,
10024 "rxedFromRsClient");
10025 else
10026 vty_out(vty, ", (Received from a RS-client)");
10027 }
d62a17ae 10028
05864da7
DS
10029 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10030 if (json_paths)
10031 json_object_boolean_true_add(json_path,
10032 "dampeningHistoryEntry");
10033 else
10034 vty_out(vty, ", (history entry)");
10035 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10036 if (json_paths)
10037 json_object_boolean_true_add(json_path,
10038 "dampeningSuppressed");
10039 else
10040 vty_out(vty, ", (suppressed due to dampening)");
10041 }
d62a17ae 10042
05864da7
DS
10043 if (!json_paths)
10044 vty_out(vty, "\n");
d62a17ae 10045
05864da7
DS
10046 /* Line2 display Next-hop, Neighbor, Router-id */
10047 /* Display the nexthop */
9bcb3eef 10048 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10049
10050 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10051 || bn_p->family == AF_EVPN)
05864da7
DS
10052 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10053 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
10054 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10055 || safi == SAFI_EVPN) {
515c2602 10056 if (json_paths) {
c949c771
DA
10057 json_object_string_addf(
10058 json_nexthop_global, "ip", "%pI4",
10059 &attr->mp_nexthop_global_in);
515c2602 10060
939a97f4 10061 if (path->peer->hostname)
515c2602
DA
10062 json_object_string_add(
10063 json_nexthop_global, "hostname",
939a97f4 10064 path->peer->hostname);
aef999a2
DA
10065 } else {
10066 if (nexthop_hostname)
10067 vty_out(vty, " %pI4(%s)",
10068 &attr->mp_nexthop_global_in,
10069 nexthop_hostname);
10070 else
10071 vty_out(vty, " %pI4",
10072 &attr->mp_nexthop_global_in);
10073 }
d62a17ae 10074 } else {
515c2602 10075 if (json_paths) {
c949c771
DA
10076 json_object_string_addf(json_nexthop_global,
10077 "ip", "%pI4",
10078 &attr->nexthop);
515c2602 10079
939a97f4 10080 if (path->peer->hostname)
515c2602
DA
10081 json_object_string_add(
10082 json_nexthop_global, "hostname",
939a97f4 10083 path->peer->hostname);
aef999a2
DA
10084 } else {
10085 if (nexthop_hostname)
10086 vty_out(vty, " %pI4(%s)",
10087 &attr->nexthop,
10088 nexthop_hostname);
10089 else
10090 vty_out(vty, " %pI4",
10091 &attr->nexthop);
10092 }
d62a17ae 10093 }
10094
05864da7
DS
10095 if (json_paths)
10096 json_object_string_add(json_nexthop_global, "afi",
10097 "ipv4");
10098 } else {
10099 if (json_paths) {
c949c771
DA
10100 json_object_string_addf(json_nexthop_global, "ip",
10101 "%pI6",
10102 &attr->mp_nexthop_global);
515c2602 10103
939a97f4 10104 if (path->peer->hostname)
515c2602
DA
10105 json_object_string_add(json_nexthop_global,
10106 "hostname",
939a97f4 10107 path->peer->hostname);
515c2602 10108
05864da7
DS
10109 json_object_string_add(json_nexthop_global, "afi",
10110 "ipv6");
10111 json_object_string_add(json_nexthop_global, "scope",
10112 "global");
10113 } else {
aef999a2
DA
10114 if (nexthop_hostname)
10115 vty_out(vty, " %pI6(%s)",
10116 &attr->mp_nexthop_global,
10117 nexthop_hostname);
10118 else
10119 vty_out(vty, " %pI6",
10120 &attr->mp_nexthop_global);
d62a17ae 10121 }
05864da7 10122 }
d62a17ae 10123
05864da7
DS
10124 /* Display the IGP cost or 'inaccessible' */
10125 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10126 if (json_paths)
10127 json_object_boolean_false_add(json_nexthop_global,
10128 "accessible");
10129 else
10130 vty_out(vty, " (inaccessible)");
10131 } else {
10132 if (path->extra && path->extra->igpmetric) {
d62a17ae 10133 if (json_paths)
05864da7
DS
10134 json_object_int_add(json_nexthop_global,
10135 "metric",
10136 path->extra->igpmetric);
d62a17ae 10137 else
05864da7
DS
10138 vty_out(vty, " (metric %u)",
10139 path->extra->igpmetric);
d62a17ae 10140 }
10141
05864da7 10142 /* IGP cost is 0, display this only for json */
d62a17ae 10143 else {
d62a17ae 10144 if (json_paths)
05864da7
DS
10145 json_object_int_add(json_nexthop_global,
10146 "metric", 0);
d62a17ae 10147 }
d62a17ae 10148
05864da7
DS
10149 if (json_paths)
10150 json_object_boolean_true_add(json_nexthop_global,
10151 "accessible");
10152 }
d62a17ae 10153
05864da7
DS
10154 /* Display peer "from" output */
10155 /* This path was originated locally */
10156 if (path->peer == bgp->peer_self) {
d62a17ae 10157
05864da7 10158 if (safi == SAFI_EVPN
b54892e0 10159 || (bn_p->family == AF_INET
05864da7 10160 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10161 if (json_paths)
05864da7
DS
10162 json_object_string_add(json_peer, "peerId",
10163 "0.0.0.0");
d62a17ae 10164 else
05864da7
DS
10165 vty_out(vty, " from 0.0.0.0 ");
10166 } else {
d62a17ae 10167 if (json_paths)
05864da7
DS
10168 json_object_string_add(json_peer, "peerId",
10169 "::");
d62a17ae 10170 else
05864da7 10171 vty_out(vty, " from :: ");
d62a17ae 10172 }
d62a17ae 10173
4e9a9863 10174 if (json_paths)
c949c771
DA
10175 json_object_string_addf(json_peer, "routerId", "%pI4",
10176 &bgp->router_id);
4e9a9863 10177 else
23d0a753 10178 vty_out(vty, "(%pI4)", &bgp->router_id);
05864da7 10179 }
d62a17ae 10180
05864da7
DS
10181 /* We RXed this path from one of our peers */
10182 else {
10183
10184 if (json_paths) {
10185 json_object_string_add(json_peer, "peerId",
10186 sockunion2str(&path->peer->su,
10187 buf,
10188 SU_ADDRSTRLEN));
c949c771
DA
10189 json_object_string_addf(json_peer, "routerId", "%pI4",
10190 &path->peer->remote_id);
05864da7
DS
10191
10192 if (path->peer->hostname)
10193 json_object_string_add(json_peer, "hostname",
10194 path->peer->hostname);
10195
10196 if (path->peer->domainname)
10197 json_object_string_add(json_peer, "domainname",
10198 path->peer->domainname);
10199
10200 if (path->peer->conf_if)
10201 json_object_string_add(json_peer, "interface",
10202 path->peer->conf_if);
10203 } else {
10204 if (path->peer->conf_if) {
10205 if (path->peer->hostname
892fedb6
DA
10206 && CHECK_FLAG(path->peer->bgp->flags,
10207 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10208 vty_out(vty, " from %s(%s)",
10209 path->peer->hostname,
10210 path->peer->conf_if);
d62a17ae 10211 else
05864da7 10212 vty_out(vty, " from %s",
9b6d8fcf 10213 path->peer->conf_if);
d62a17ae 10214 } else {
05864da7 10215 if (path->peer->hostname
892fedb6
DA
10216 && CHECK_FLAG(path->peer->bgp->flags,
10217 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10218 vty_out(vty, " from %s(%s)",
10219 path->peer->hostname,
10220 path->peer->host);
d62a17ae 10221 else
05864da7
DS
10222 vty_out(vty, " from %s",
10223 sockunion2str(&path->peer->su,
10224 buf,
10225 SU_ADDRSTRLEN));
d62a17ae 10226 }
d62a17ae 10227
05864da7 10228 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10229 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10230 else
10231 vty_out(vty, " (%s)",
10232 inet_ntop(AF_INET,
10233 &path->peer->remote_id, buf1,
10234 sizeof(buf1)));
d62a17ae 10235 }
05864da7 10236 }
9df8b37c 10237
05864da7
DS
10238 /*
10239 * Note when vrfid of nexthop is different from that of prefix
10240 */
10241 if (path->extra && path->extra->bgp_orig) {
10242 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10243
05864da7
DS
10244 if (json_paths) {
10245 const char *vn;
9df8b37c 10246
05864da7
DS
10247 if (path->extra->bgp_orig->inst_type
10248 == BGP_INSTANCE_TYPE_DEFAULT)
10249 vn = VRF_DEFAULT_NAME;
10250 else
10251 vn = path->extra->bgp_orig->name;
9df8b37c 10252
05864da7 10253 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10254
05864da7
DS
10255 if (nexthop_vrfid == VRF_UNKNOWN) {
10256 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10257 } else {
05864da7
DS
10258 json_object_int_add(json_path, "nhVrfId",
10259 (int)nexthop_vrfid);
9df8b37c 10260 }
05864da7
DS
10261 } else {
10262 if (nexthop_vrfid == VRF_UNKNOWN)
10263 vty_out(vty, " vrf ?");
137147c6
DS
10264 else {
10265 struct vrf *vrf;
10266
10267 vrf = vrf_lookup_by_id(nexthop_vrfid);
10268 vty_out(vty, " vrf %s(%u)",
10269 VRF_LOGNAME(vrf), nexthop_vrfid);
10270 }
9df8b37c 10271 }
05864da7 10272 }
9df8b37c 10273
05864da7
DS
10274 if (nexthop_self) {
10275 if (json_paths) {
10276 json_object_boolean_true_add(json_path,
10277 "announceNexthopSelf");
10278 } else {
10279 vty_out(vty, " announce-nh-self");
9df8b37c 10280 }
05864da7 10281 }
9df8b37c 10282
05864da7
DS
10283 if (!json_paths)
10284 vty_out(vty, "\n");
d62a17ae 10285
05864da7
DS
10286 /* display the link-local nexthop */
10287 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10288 if (json_paths) {
10289 json_nexthop_ll = json_object_new_object();
c949c771
DA
10290 json_object_string_addf(json_nexthop_ll, "ip", "%pI6",
10291 &attr->mp_nexthop_local);
515c2602 10292
939a97f4 10293 if (path->peer->hostname)
515c2602
DA
10294 json_object_string_add(json_nexthop_ll,
10295 "hostname",
939a97f4 10296 path->peer->hostname);
515c2602 10297
05864da7
DS
10298 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10299 json_object_string_add(json_nexthop_ll, "scope",
10300 "link-local");
d62a17ae 10301
05864da7
DS
10302 json_object_boolean_true_add(json_nexthop_ll,
10303 "accessible");
d62a17ae 10304
05864da7 10305 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10306 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10307 "used");
10308 else
10309 json_object_boolean_true_add(
10310 json_nexthop_global, "used");
10311 } else {
10312 vty_out(vty, " (%s) %s\n",
10313 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10314 buf, INET6_ADDRSTRLEN),
10315 attr->mp_nexthop_prefer_global
10316 ? "(prefer-global)"
10317 : "(used)");
d62a17ae 10318 }
05864da7
DS
10319 }
10320 /* If we do not have a link-local nexthop then we must flag the
10321 global as "used" */
10322 else {
10323 if (json_paths)
10324 json_object_boolean_true_add(json_nexthop_global,
10325 "used");
10326 }
d62a17ae 10327
b5e140c8 10328 if (safi == SAFI_EVPN &&
5e4d4c8a 10329 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10330 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10331 }
10332
05864da7
DS
10333 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10334 * Int/Ext/Local, Atomic, best */
10335 if (json_paths)
10336 json_object_string_add(json_path, "origin",
10337 bgp_origin_long_str[attr->origin]);
10338 else
10339 vty_out(vty, " Origin %s",
10340 bgp_origin_long_str[attr->origin]);
9df8b37c 10341
05864da7 10342 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10343 if (json_paths)
05864da7 10344 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10345 else
05864da7
DS
10346 vty_out(vty, ", metric %u", attr->med);
10347 }
9df8b37c 10348
05864da7
DS
10349 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10350 if (json_paths)
0fbac0b4 10351 json_object_int_add(json_path, "locPrf",
05864da7
DS
10352 attr->local_pref);
10353 else
10354 vty_out(vty, ", localpref %u", attr->local_pref);
10355 }
9df8b37c 10356
05864da7
DS
10357 if (attr->weight != 0) {
10358 if (json_paths)
10359 json_object_int_add(json_path, "weight", attr->weight);
10360 else
10361 vty_out(vty, ", weight %u", attr->weight);
10362 }
9df8b37c 10363
05864da7
DS
10364 if (attr->tag != 0) {
10365 if (json_paths)
10366 json_object_int_add(json_path, "tag", attr->tag);
10367 else
10368 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10369 }
9df8b37c 10370
05864da7
DS
10371 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10372 if (json_paths)
10373 json_object_boolean_false_add(json_path, "valid");
10374 else
10375 vty_out(vty, ", invalid");
10376 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10377 if (json_paths)
10378 json_object_boolean_true_add(json_path, "valid");
10379 else
10380 vty_out(vty, ", valid");
10381 }
9df8b37c 10382
7d3cae70
DA
10383 if (json_paths)
10384 json_object_int_add(json_path, "version", bn->version);
10385
05864da7
DS
10386 if (path->peer != bgp->peer_self) {
10387 if (path->peer->as == path->peer->local_as) {
10388 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10389 if (json_paths)
10390 json_object_string_add(
10391 json_peer, "type",
10392 "confed-internal");
d62a17ae 10393 else
05864da7 10394 vty_out(vty, ", confed-internal");
d62a17ae 10395 } else {
05864da7
DS
10396 if (json_paths)
10397 json_object_string_add(
10398 json_peer, "type", "internal");
10399 else
10400 vty_out(vty, ", internal");
9df8b37c 10401 }
05864da7
DS
10402 } else {
10403 if (bgp_confederation_peers_check(bgp,
10404 path->peer->as)) {
10405 if (json_paths)
10406 json_object_string_add(
10407 json_peer, "type",
10408 "confed-external");
d62a17ae 10409 else
05864da7 10410 vty_out(vty, ", confed-external");
d62a17ae 10411 } else {
05864da7
DS
10412 if (json_paths)
10413 json_object_string_add(
10414 json_peer, "type", "external");
10415 else
10416 vty_out(vty, ", external");
d62a17ae 10417 }
10418 }
05864da7
DS
10419 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10420 if (json_paths) {
10421 json_object_boolean_true_add(json_path, "aggregated");
10422 json_object_boolean_true_add(json_path, "local");
10423 } else {
10424 vty_out(vty, ", aggregated, local");
10425 }
10426 } else if (path->type != ZEBRA_ROUTE_BGP) {
10427 if (json_paths)
10428 json_object_boolean_true_add(json_path, "sourced");
10429 else
10430 vty_out(vty, ", sourced");
10431 } else {
10432 if (json_paths) {
10433 json_object_boolean_true_add(json_path, "sourced");
10434 json_object_boolean_true_add(json_path, "local");
10435 } else {
10436 vty_out(vty, ", sourced, local");
d62a17ae 10437 }
05864da7 10438 }
718e3744 10439
05864da7 10440 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10441 if (json_paths)
05864da7
DS
10442 json_object_boolean_true_add(json_path,
10443 "atomicAggregate");
d62a17ae 10444 else
05864da7
DS
10445 vty_out(vty, ", atomic-aggregate");
10446 }
d62a17ae 10447
05864da7
DS
10448 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10449 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10450 && bgp_path_info_mpath_count(path))) {
10451 if (json_paths)
10452 json_object_boolean_true_add(json_path, "multipath");
10453 else
10454 vty_out(vty, ", multipath");
10455 }
50e05855 10456
05864da7
DS
10457 // Mark the bestpath(s)
10458 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10459 first_as = aspath_get_first_as(attr->aspath);
718e3744 10460
05864da7
DS
10461 if (json_paths) {
10462 if (!json_bestpath)
10463 json_bestpath = json_object_new_object();
10464 json_object_int_add(json_bestpath, "bestpathFromAs",
10465 first_as);
10466 } else {
10467 if (first_as)
10468 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10469 else
05864da7 10470 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10471 }
05864da7 10472 }
718e3744 10473
05864da7
DS
10474 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10475 if (json_paths) {
10476 if (!json_bestpath)
10477 json_bestpath = json_object_new_object();
10478 json_object_boolean_true_add(json_bestpath, "overall");
10479 json_object_string_add(
10480 json_bestpath, "selectionReason",
10481 bgp_path_selection_reason2str(bn->reason));
10482 } else {
10483 vty_out(vty, ", best");
10484 vty_out(vty, " (%s)",
10485 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10486 }
05864da7 10487 }
718e3744 10488
4027d19b 10489 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10490 if (json_paths)
10491 json_object_string_add(
10492 json_path, "rpkiValidationState",
4027d19b 10493 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10494 else
1d327209 10495 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10496 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10497 }
10498
05864da7
DS
10499 if (json_bestpath)
10500 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10501
05864da7
DS
10502 if (!json_paths)
10503 vty_out(vty, "\n");
10504
10505 /* Line 4 display Community */
29e72930 10506 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10507 if (json_paths) {
10508 if (!attr->community->json)
10509 community_str(attr->community, true);
10510 json_object_lock(attr->community->json);
10511 json_object_object_add(json_path, "community",
10512 attr->community->json);
10513 } else {
10514 vty_out(vty, " Community: %s\n",
10515 attr->community->str);
d62a17ae 10516 }
05864da7 10517 }
718e3744 10518
05864da7
DS
10519 /* Line 5 display Extended-community */
10520 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10521 if (json_paths) {
10522 json_ext_community = json_object_new_object();
b53e67a3
DA
10523 json_object_string_add(
10524 json_ext_community, "string",
10525 bgp_attr_get_ecommunity(attr)->str);
05864da7
DS
10526 json_object_object_add(json_path, "extendedCommunity",
10527 json_ext_community);
d62a17ae 10528 } else {
05864da7 10529 vty_out(vty, " Extended Community: %s\n",
b53e67a3 10530 bgp_attr_get_ecommunity(attr)->str);
d62a17ae 10531 }
05864da7 10532 }
718e3744 10533
05864da7
DS
10534 /* Line 6 display Large community */
10535 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10536 if (json_paths) {
1bcf3a96
DA
10537 if (!bgp_attr_get_lcommunity(attr)->json)
10538 lcommunity_str(bgp_attr_get_lcommunity(attr),
10539 true);
10540 json_object_lock(bgp_attr_get_lcommunity(attr)->json);
10541 json_object_object_add(
10542 json_path, "largeCommunity",
10543 bgp_attr_get_lcommunity(attr)->json);
05864da7
DS
10544 } else {
10545 vty_out(vty, " Large Community: %s\n",
1bcf3a96 10546 bgp_attr_get_lcommunity(attr)->str);
d62a17ae 10547 }
05864da7 10548 }
718e3744 10549
05864da7
DS
10550 /* Line 7 display Originator, Cluster-id */
10551 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10552 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10553 char buf[BUFSIZ] = {0};
10554
05864da7 10555 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10556 if (json_paths)
c949c771
DA
10557 json_object_string_addf(json_path,
10558 "originatorId", "%pI4",
10559 &attr->originator_id);
d62a17ae 10560 else
23d0a753
DA
10561 vty_out(vty, " Originator: %pI4",
10562 &attr->originator_id);
d62a17ae 10563 }
856ca177 10564
05864da7 10565 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10566 struct cluster_list *cluster =
10567 bgp_attr_get_cluster(attr);
05864da7 10568 int i;
d62a17ae 10569
10570 if (json_paths) {
05864da7
DS
10571 json_cluster_list = json_object_new_object();
10572 json_cluster_list_list =
10573 json_object_new_array();
10574
779fee93 10575 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10576 json_string = json_object_new_string(
779fee93
DS
10577 inet_ntop(AF_INET,
10578 &cluster->list[i],
10579 buf, sizeof(buf)));
05864da7
DS
10580 json_object_array_add(
10581 json_cluster_list_list,
10582 json_string);
10583 }
718e3744 10584
05864da7
DS
10585 /*
10586 * struct cluster_list does not have
10587 * "str" variable like aspath and community
10588 * do. Add this someday if someone asks
10589 * for it.
10590 * json_object_string_add(json_cluster_list,
779fee93 10591 * "string", cluster->str);
05864da7
DS
10592 */
10593 json_object_object_add(json_cluster_list,
10594 "list",
10595 json_cluster_list_list);
10596 json_object_object_add(json_path, "clusterList",
10597 json_cluster_list);
0dc8ee70 10598 } else {
05864da7
DS
10599 vty_out(vty, ", Cluster list: ");
10600
779fee93 10601 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10602 vty_out(vty, "%pI4 ",
779fee93 10603 &cluster->list[i]);
05864da7 10604 }
0dc8ee70 10605 }
d62a17ae 10606 }
718e3744 10607
d62a17ae 10608 if (!json_paths)
10609 vty_out(vty, "\n");
05864da7 10610 }
d62a17ae 10611
05864da7 10612 if (path->extra && path->extra->damp_info)
b4f7f45b 10613 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10614
05864da7
DS
10615 /* Remote Label */
10616 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10617 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10618 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10619
05864da7
DS
10620 if (json_paths)
10621 json_object_int_add(json_path, "remoteLabel", label);
10622 else
10623 vty_out(vty, " Remote label: %d\n", label);
10624 }
d62a17ae 10625
e496b420
HS
10626 /* Remote SID */
10627 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10628 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10629 if (json_paths)
10630 json_object_string_add(json_path, "remoteSid", buf);
10631 else
10632 vty_out(vty, " Remote SID: %s\n", buf);
10633 }
10634
05864da7
DS
10635 /* Label Index */
10636 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10637 if (json_paths)
10638 json_object_int_add(json_path, "labelIndex",
10639 attr->label_index);
10640 else
10641 vty_out(vty, " Label Index: %d\n",
10642 attr->label_index);
10643 }
d62a17ae 10644
05864da7
DS
10645 /* Line 8 display Addpath IDs */
10646 if (path->addpath_rx_id
10647 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10648 if (json_paths) {
10649 json_object_int_add(json_path, "addpathRxId",
10650 path->addpath_rx_id);
d62a17ae 10651
05864da7
DS
10652 /* Keep backwards compatibility with the old API
10653 * by putting TX All's ID in the old field
10654 */
10655 json_object_int_add(
10656 json_path, "addpathTxId",
10657 path->tx_addpath
10658 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10659
05864da7
DS
10660 /* ... but create a specific field for each
10661 * strategy
10662 */
10663 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10664 json_object_int_add(
10665 json_path,
10666 bgp_addpath_names(i)->id_json_name,
10667 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10668 }
05864da7
DS
10669 } else {
10670 vty_out(vty, " AddPath ID: RX %u, ",
10671 path->addpath_rx_id);
d62a17ae 10672
05864da7 10673 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10674 }
05864da7 10675 }
520d5d76 10676
05864da7
DS
10677 /* If we used addpath to TX a non-bestpath we need to display
10678 * "Advertised to" on a path-by-path basis
10679 */
10680 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10681 first = 1;
dcc68b5e 10682
05864da7
DS
10683 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10684 addpath_capable =
10685 bgp_addpath_encode_tx(peer, afi, safi);
10686 has_adj = bgp_adj_out_lookup(
10687 peer, path->net,
10688 bgp_addpath_id_for_peer(peer, afi, safi,
10689 &path->tx_addpath));
10690
10691 if ((addpath_capable && has_adj)
10692 || (!addpath_capable && has_adj
10693 && CHECK_FLAG(path->flags,
10694 BGP_PATH_SELECTED))) {
10695 if (json_path && !json_adv_to)
10696 json_adv_to = json_object_new_object();
dcc68b5e 10697
05864da7
DS
10698 route_vty_out_advertised_to(
10699 vty, peer, &first,
10700 " Advertised to:", json_adv_to);
d62a17ae 10701 }
10702 }
718e3744 10703
05864da7
DS
10704 if (json_path) {
10705 if (json_adv_to) {
10706 json_object_object_add(
10707 json_path, "advertisedTo", json_adv_to);
d62a17ae 10708 }
05864da7
DS
10709 } else {
10710 if (!first) {
10711 vty_out(vty, "\n");
d62a17ae 10712 }
10713 }
05864da7 10714 }
b05a1c8b 10715
05864da7
DS
10716 /* Line 9 display Uptime */
10717 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10718 if (json_paths) {
10719 json_last_update = json_object_new_object();
10720 json_object_int_add(json_last_update, "epoch", tbuf);
10721 json_object_string_add(json_last_update, "string",
10722 ctime(&tbuf));
10723 json_object_object_add(json_path, "lastUpdate",
10724 json_last_update);
10725 } else
10726 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10727
05864da7
DS
10728 /* Line 10 display PMSI tunnel attribute, if present */
10729 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10730 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10731 bgp_attr_get_pmsi_tnl_type(attr),
10732 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10733
05864da7
DS
10734 if (json_paths) {
10735 json_pmsi = json_object_new_object();
10736 json_object_string_add(json_pmsi, "tunnelType", str);
10737 json_object_int_add(json_pmsi, "label",
10738 label2vni(&attr->label));
10739 json_object_object_add(json_path, "pmsi", json_pmsi);
10740 } else
10741 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10742 str, label2vni(&attr->label));
d62a17ae 10743 }
f1aa5d8a 10744
848e8cf6
DA
10745 if (path->peer->t_gr_restart &&
10746 CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
10747 unsigned long gr_remaining =
10748 thread_timer_remain_second(path->peer->t_gr_restart);
10749
10750 if (json_paths) {
10751 json_object_int_add(json_path,
10752 "gracefulRestartSecondsRemaining",
10753 gr_remaining);
10754 } else
10755 vty_out(vty,
10756 " Time until Graceful Restart stale route deleted: %lu\n",
10757 gr_remaining);
10758 }
10759
48ebba04
DA
10760 if (path->peer->t_llgr_stale[afi][safi] && attr->community &&
10761 community_include(attr->community, COMMUNITY_LLGR_STALE)) {
10762 unsigned long llgr_remaining = thread_timer_remain_second(
10763 path->peer->t_llgr_stale[afi][safi]);
d92646a4 10764
48ebba04
DA
10765 if (json_paths) {
10766 json_object_int_add(json_path, "llgrSecondsRemaining",
10767 llgr_remaining);
10768 } else
10769 vty_out(vty,
10770 " Time until Long-lived stale route deleted: %lu\n",
10771 llgr_remaining);
10772 }
10773
92269aa2
DS
10774 /* Output some debug about internal state of the dest flags */
10775 if (json_paths) {
10776 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10777 json_object_boolean_true_add(json_path, "processScheduled");
10778 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10779 json_object_boolean_true_add(json_path, "userCleared");
10780 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10781 json_object_boolean_true_add(json_path, "labelChanged");
10782 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10783 json_object_boolean_true_add(json_path, "registeredForLabel");
10784 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10785 json_object_boolean_true_add(json_path, "selectDefered");
10786 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10787 json_object_boolean_true_add(json_path, "fibInstalled");
10788 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10789 json_object_boolean_true_add(json_path, "fibPending");
92269aa2 10790
d62a17ae 10791 if (json_nexthop_global || json_nexthop_ll) {
10792 json_nexthops = json_object_new_array();
f1aa5d8a 10793
d62a17ae 10794 if (json_nexthop_global)
10795 json_object_array_add(json_nexthops,
10796 json_nexthop_global);
f1aa5d8a 10797
d62a17ae 10798 if (json_nexthop_ll)
10799 json_object_array_add(json_nexthops,
10800 json_nexthop_ll);
f1aa5d8a 10801
d62a17ae 10802 json_object_object_add(json_path, "nexthops",
10803 json_nexthops);
10804 }
10805
10806 json_object_object_add(json_path, "peer", json_peer);
10807 json_object_array_add(json_paths, json_path);
05864da7 10808 }
b366b518
BB
10809}
10810
96ade3ed 10811#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10812#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10813#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10814
a4d82a8a 10815static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10816 afi_t afi, safi_t safi, enum bgp_show_type type,
10817 bool use_json);
7f323236
DW
10818static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10819 const char *comstr, int exact, afi_t afi,
96c81f66 10820 safi_t safi, uint16_t show_flags);
d62a17ae 10821
1ae44dfc 10822static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10823 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10824 void *output_arg, const char *rd, int is_last,
96f3485c 10825 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10826 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10827 enum rpki_states rpki_target_state)
d62a17ae 10828{
40381db7 10829 struct bgp_path_info *pi;
9bcb3eef 10830 struct bgp_dest *dest;
2aad8c42
MS
10831 bool header = true;
10832 bool json_detail_header = false;
d62a17ae 10833 int display;
1ae44dfc
LB
10834 unsigned long output_count = 0;
10835 unsigned long total_count = 0;
d62a17ae 10836 struct prefix *p;
d62a17ae 10837 json_object *json_paths = NULL;
10838 int first = 1;
96f3485c
MK
10839 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10840 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10841 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10842
1ae44dfc 10843 if (output_cum && *output_cum != 0)
2aad8c42 10844 header = false;
1ae44dfc 10845
9386b588 10846 if (use_json && !*json_header_depth) {
96f3485c
MK
10847 if (all)
10848 *json_header_depth = 1;
10849 else {
10850 vty_out(vty, "{\n");
10851 *json_header_depth = 2;
10852 }
10853
d62a17ae 10854 vty_out(vty,
23d0a753
DA
10855 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10856 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10857 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10858 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10859 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10860 ? VRF_DEFAULT_NAME
10861 : bgp->name,
10862 table->version, &bgp->router_id,
01eced22 10863 bgp->default_local_pref, bgp->as);
9386b588 10864 if (rd) {
445c2480 10865 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10866 ++*json_header_depth;
10867 }
d62a17ae 10868 }
718e3744 10869
445c2480
DS
10870 if (use_json && rd) {
10871 vty_out(vty, " \"%s\" : { ", rd);
10872 }
10873
2aad8c42
MS
10874 /* Check for 'json detail', where we need header output once per dest */
10875 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10876 type != bgp_show_type_dampend_paths &&
10877 type != bgp_show_type_damp_neighbor &&
10878 type != bgp_show_type_flap_statistics &&
10879 type != bgp_show_type_flap_neighbor)
10880 json_detail_header = true;
10881
d62a17ae 10882 /* Start processing of routes. */
9bcb3eef
DS
10883 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10884 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10885 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10886 bool json_detail = json_detail_header;
b54892e0 10887
9bcb3eef 10888 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10889 if (pi == NULL)
98ce9a06 10890 continue;
d62a17ae 10891
98ce9a06 10892 display = 0;
98ce9a06
DS
10893 if (use_json)
10894 json_paths = json_object_new_array();
10895 else
10896 json_paths = NULL;
d62a17ae 10897
6f94b685 10898 for (; pi; pi = pi->next) {
98ce9a06 10899 total_count++;
1e2ce4f1 10900
7d3cae70
DA
10901 if (type == bgp_show_type_prefix_version) {
10902 uint32_t version =
10903 strtoul(output_arg, NULL, 10);
10904 if (dest->version < version)
10905 continue;
10906 }
10907
a70a28a5
DA
10908 if (type == bgp_show_type_community_alias) {
10909 char *alias = output_arg;
10910 char **communities;
10911 int num;
10912 bool found = false;
10913
10914 if (pi->attr->community) {
10915 frrstr_split(pi->attr->community->str,
10916 " ", &communities, &num);
10917 for (int i = 0; i < num; i++) {
10918 const char *com2alias =
10919 bgp_community2alias(
10920 communities[i]);
cd9cc0e6
IR
10921 if (!found
10922 && strcmp(alias, com2alias)
10923 == 0)
a70a28a5 10924 found = true;
cd9cc0e6
IR
10925 XFREE(MTYPE_TMP,
10926 communities[i]);
a70a28a5 10927 }
cd9cc0e6 10928 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10929 }
10930
1bcf3a96
DA
10931 if (!found &&
10932 bgp_attr_get_lcommunity(pi->attr)) {
10933 frrstr_split(bgp_attr_get_lcommunity(
10934 pi->attr)
10935 ->str,
a70a28a5
DA
10936 " ", &communities, &num);
10937 for (int i = 0; i < num; i++) {
10938 const char *com2alias =
10939 bgp_community2alias(
10940 communities[i]);
cd9cc0e6
IR
10941 if (!found
10942 && strcmp(alias, com2alias)
10943 == 0)
a70a28a5 10944 found = true;
cd9cc0e6
IR
10945 XFREE(MTYPE_TMP,
10946 communities[i]);
a70a28a5 10947 }
cd9cc0e6 10948 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10949 }
10950
10951 if (!found)
10952 continue;
10953 }
10954
1e2ce4f1
DS
10955 if (type == bgp_show_type_rpki) {
10956 if (dest_p->family == AF_INET
10957 || dest_p->family == AF_INET6)
4027d19b 10958 rpki_curr_state = hook_call(
1e2ce4f1
DS
10959 bgp_rpki_prefix_status,
10960 pi->peer, pi->attr, dest_p);
4027d19b
DS
10961 if (rpki_target_state != RPKI_NOT_BEING_USED
10962 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10963 continue;
10964 }
10965
98ce9a06
DS
10966 if (type == bgp_show_type_flap_statistics
10967 || type == bgp_show_type_flap_neighbor
10968 || type == bgp_show_type_dampend_paths
10969 || type == bgp_show_type_damp_neighbor) {
40381db7 10970 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10971 continue;
10972 }
10973 if (type == bgp_show_type_regexp) {
10974 regex_t *regex = output_arg;
d62a17ae 10975
40381db7 10976 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10977 == REG_NOMATCH)
10978 continue;
10979 }
10980 if (type == bgp_show_type_prefix_list) {
10981 struct prefix_list *plist = output_arg;
d62a17ae 10982
9bcb3eef 10983 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10984 != PREFIX_PERMIT)
10985 continue;
10986 }
10987 if (type == bgp_show_type_filter_list) {
10988 struct as_list *as_list = output_arg;
d62a17ae 10989
40381db7 10990 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10991 != AS_FILTER_PERMIT)
10992 continue;
10993 }
10994 if (type == bgp_show_type_route_map) {
10995 struct route_map *rmap = output_arg;
9b6d8fcf 10996 struct bgp_path_info path;
98ce9a06 10997 struct attr dummy_attr;
b68885f9 10998 route_map_result_t ret;
d62a17ae 10999
6f4f49b2 11000 dummy_attr = *pi->attr;
d62a17ae 11001
40381db7 11002 path.peer = pi->peer;
9b6d8fcf 11003 path.attr = &dummy_attr;
d62a17ae 11004
1782514f 11005 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 11006 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
11007 if (ret == RMAP_DENYMATCH)
11008 continue;
11009 }
11010 if (type == bgp_show_type_neighbor
11011 || type == bgp_show_type_flap_neighbor
11012 || type == bgp_show_type_damp_neighbor) {
11013 union sockunion *su = output_arg;
11014
40381db7
DS
11015 if (pi->peer == NULL
11016 || pi->peer->su_remote == NULL
11017 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
11018 continue;
11019 }
11020 if (type == bgp_show_type_cidr_only) {
d7c0a89a 11021 uint32_t destination;
d62a17ae 11022
9bcb3eef 11023 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 11024 if (IN_CLASSC(destination)
9bcb3eef 11025 && dest_p->prefixlen == 24)
98ce9a06
DS
11026 continue;
11027 if (IN_CLASSB(destination)
9bcb3eef 11028 && dest_p->prefixlen == 16)
98ce9a06
DS
11029 continue;
11030 if (IN_CLASSA(destination)
9bcb3eef 11031 && dest_p->prefixlen == 8)
98ce9a06
DS
11032 continue;
11033 }
11034 if (type == bgp_show_type_prefix_longer) {
f7813c7c 11035 p = output_arg;
9bcb3eef 11036 if (!prefix_match(p, dest_p))
98ce9a06
DS
11037 continue;
11038 }
11039 if (type == bgp_show_type_community_all) {
40381db7 11040 if (!pi->attr->community)
98ce9a06
DS
11041 continue;
11042 }
11043 if (type == bgp_show_type_community) {
11044 struct community *com = output_arg;
d62a17ae 11045
40381db7
DS
11046 if (!pi->attr->community
11047 || !community_match(pi->attr->community,
98ce9a06
DS
11048 com))
11049 continue;
11050 }
11051 if (type == bgp_show_type_community_exact) {
11052 struct community *com = output_arg;
d62a17ae 11053
40381db7
DS
11054 if (!pi->attr->community
11055 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
11056 continue;
11057 }
11058 if (type == bgp_show_type_community_list) {
11059 struct community_list *list = output_arg;
d62a17ae 11060
40381db7 11061 if (!community_list_match(pi->attr->community,
a4d82a8a 11062 list))
98ce9a06
DS
11063 continue;
11064 }
a4d82a8a 11065 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11066 struct community_list *list = output_arg;
d62a17ae 11067
98ce9a06 11068 if (!community_list_exact_match(
40381db7 11069 pi->attr->community, list))
98ce9a06
DS
11070 continue;
11071 }
11072 if (type == bgp_show_type_lcommunity) {
11073 struct lcommunity *lcom = output_arg;
d62a17ae 11074
1bcf3a96
DA
11075 if (!bgp_attr_get_lcommunity(pi->attr) ||
11076 !lcommunity_match(
11077 bgp_attr_get_lcommunity(pi->attr),
11078 lcom))
98ce9a06
DS
11079 continue;
11080 }
36a206db 11081
11082 if (type == bgp_show_type_lcommunity_exact) {
11083 struct lcommunity *lcom = output_arg;
11084
1bcf3a96
DA
11085 if (!bgp_attr_get_lcommunity(pi->attr) ||
11086 !lcommunity_cmp(
11087 bgp_attr_get_lcommunity(pi->attr),
11088 lcom))
36a206db 11089 continue;
11090 }
98ce9a06
DS
11091 if (type == bgp_show_type_lcommunity_list) {
11092 struct community_list *list = output_arg;
d62a17ae 11093
1bcf3a96
DA
11094 if (!lcommunity_list_match(
11095 bgp_attr_get_lcommunity(pi->attr),
11096 list))
98ce9a06
DS
11097 continue;
11098 }
36a206db 11099 if (type
11100 == bgp_show_type_lcommunity_list_exact) {
11101 struct community_list *list = output_arg;
11102
11103 if (!lcommunity_list_exact_match(
1bcf3a96
DA
11104 bgp_attr_get_lcommunity(pi->attr),
11105 list))
36a206db 11106 continue;
11107 }
98ce9a06 11108 if (type == bgp_show_type_lcommunity_all) {
1bcf3a96 11109 if (!bgp_attr_get_lcommunity(pi->attr))
98ce9a06
DS
11110 continue;
11111 }
11112 if (type == bgp_show_type_dampend_paths
11113 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11114 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11115 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11116 continue;
11117 }
11118
11119 if (!use_json && header) {
23d0a753
DA
11120 vty_out(vty,
11121 "BGP table version is %" PRIu64
11122 ", local router ID is %pI4, vrf id ",
11123 table->version, &bgp->router_id);
9df8b37c
PZ
11124 if (bgp->vrf_id == VRF_UNKNOWN)
11125 vty_out(vty, "%s", VRFID_NONE_STR);
11126 else
11127 vty_out(vty, "%u", bgp->vrf_id);
11128 vty_out(vty, "\n");
01eced22
AD
11129 vty_out(vty, "Default local pref %u, ",
11130 bgp->default_local_pref);
11131 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11132 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11133 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11134 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11135 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11136 if (type == bgp_show_type_dampend_paths
11137 || type == bgp_show_type_damp_neighbor)
98ce9a06 11138 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11139 else if (type == bgp_show_type_flap_statistics
11140 || type == bgp_show_type_flap_neighbor)
98ce9a06 11141 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11142 else
ae248832
MK
11143 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11144 : BGP_SHOW_HEADER));
2aad8c42
MS
11145 header = false;
11146
11147 } else if (json_detail && json_paths != NULL) {
11148 const struct prefix_rd *prd;
11149 json_object *jtemp;
11150
11151 /* Use common detail header, for most types;
11152 * need a json 'object'.
11153 */
11154
11155 jtemp = json_object_new_object();
11156 prd = bgp_rd_from_dest(dest, safi);
11157
11158 route_vty_out_detail_header(
11159 vty, bgp, dest, prd, table->afi,
11160 safi, jtemp);
11161
11162 json_object_array_add(json_paths, jtemp);
11163
11164 json_detail = false;
d62a17ae 11165 }
2aad8c42 11166
98ce9a06
DS
11167 if (rd != NULL && !display && !output_count) {
11168 if (!use_json)
11169 vty_out(vty,
11170 "Route Distinguisher: %s\n",
11171 rd);
d62a17ae 11172 }
98ce9a06
DS
11173 if (type == bgp_show_type_dampend_paths
11174 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11175 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11176 AFI_IP, safi, use_json,
11177 json_paths);
98ce9a06
DS
11178 else if (type == bgp_show_type_flap_statistics
11179 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11180 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11181 AFI_IP, safi, use_json,
11182 json_paths);
f280c93b
DA
11183 else {
11184 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11185 route_vty_out_detail(
11186 vty, bgp, dest, pi,
11187 family2afi(dest_p->family),
11188 safi, RPKI_NOT_BEING_USED,
11189 json_paths);
11190 else
11191 route_vty_out(vty, dest_p, pi, display,
11192 safi, json_paths, wide);
11193 }
98ce9a06 11194 display++;
d62a17ae 11195 }
11196
98ce9a06
DS
11197 if (display) {
11198 output_count++;
11199 if (!use_json)
11200 continue;
11201
625d2931 11202 /* encode prefix */
9bcb3eef 11203 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11204 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11205
1840384b 11206
b54892e0
DS
11207 bgp_fs_nlri_get_string(
11208 (unsigned char *)
9bcb3eef
DS
11209 dest_p->u.prefix_flowspec.ptr,
11210 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11211 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11212 family2afi(dest_p->u
11213 .prefix_flowspec.family));
625d2931 11214 if (first)
b54892e0 11215 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11216 dest_p->u.prefix_flowspec
b54892e0 11217 .prefixlen);
625d2931 11218 else
b54892e0 11219 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11220 dest_p->u.prefix_flowspec
b54892e0 11221 .prefixlen);
625d2931 11222 } else {
625d2931 11223 if (first)
1b78780b 11224 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11225 else
1b78780b 11226 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11227 }
3757f964 11228 vty_json(vty, json_paths);
449feb8e 11229 json_paths = NULL;
98ce9a06 11230 first = 0;
1f83ed02
DS
11231 } else
11232 json_object_free(json_paths);
98ce9a06
DS
11233 }
11234
1ae44dfc
LB
11235 if (output_cum) {
11236 output_count += *output_cum;
11237 *output_cum = output_count;
11238 }
11239 if (total_cum) {
11240 total_count += *total_cum;
11241 *total_cum = total_count;
11242 }
d62a17ae 11243 if (use_json) {
9386b588 11244 if (rd) {
a4d82a8a 11245 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11246 }
11247 if (is_last) {
a4d82a8a
PZ
11248 unsigned long i;
11249 for (i = 0; i < *json_header_depth; ++i)
11250 vty_out(vty, " } ");
96f3485c
MK
11251 if (!all)
11252 vty_out(vty, "\n");
9386b588 11253 }
d62a17ae 11254 } else {
1ae44dfc
LB
11255 if (is_last) {
11256 /* No route is displayed */
11257 if (output_count == 0) {
11258 if (type == bgp_show_type_normal)
11259 vty_out(vty,
11260 "No BGP prefixes displayed, %ld exist\n",
11261 total_count);
11262 } else
d62a17ae 11263 vty_out(vty,
1ae44dfc
LB
11264 "\nDisplayed %ld routes and %ld total paths\n",
11265 output_count, total_count);
11266 }
d62a17ae 11267 }
718e3744 11268
d62a17ae 11269 return CMD_SUCCESS;
718e3744 11270}
11271
1ae44dfc
LB
11272int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11273 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11274 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11275{
9bcb3eef 11276 struct bgp_dest *dest, *next;
1ae44dfc
LB
11277 unsigned long output_cum = 0;
11278 unsigned long total_cum = 0;
9386b588 11279 unsigned long json_header_depth = 0;
67009e22 11280 struct bgp_table *itable;
0136788c 11281 bool show_msg;
96c81f66 11282 uint16_t show_flags = 0;
0136788c
LB
11283
11284 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11285
96f3485c
MK
11286 if (use_json)
11287 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11288
9bcb3eef
DS
11289 for (dest = bgp_table_top(table); dest; dest = next) {
11290 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11291
9bcb3eef
DS
11292 next = bgp_route_next(dest);
11293 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11294 continue;
67009e22 11295
9bcb3eef 11296 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11297 if (itable != NULL) {
1ae44dfc 11298 struct prefix_rd prd;
06b9f471 11299 char rd[RD_ADDRSTRLEN];
1ae44dfc 11300
9bcb3eef 11301 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11302 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11303 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11304 rd, next == NULL, &output_cum,
11305 &total_cum, &json_header_depth,
1e2ce4f1 11306 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11307 if (next == NULL)
11308 show_msg = false;
1ae44dfc
LB
11309 }
11310 }
0136788c
LB
11311 if (show_msg) {
11312 if (output_cum == 0)
11313 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11314 total_cum);
11315 else
11316 vty_out(vty,
11317 "\nDisplayed %ld routes and %ld total paths\n",
11318 output_cum, total_cum);
11319 }
1ae44dfc
LB
11320 return CMD_SUCCESS;
11321}
2aad8c42 11322
d62a17ae 11323static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11324 enum bgp_show_type type, void *output_arg,
96c81f66 11325 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11326{
d62a17ae 11327 struct bgp_table *table;
9386b588 11328 unsigned long json_header_depth = 0;
96f3485c 11329 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11330
d62a17ae 11331 if (bgp == NULL) {
11332 bgp = bgp_get_default();
11333 }
fee0f4c6 11334
d62a17ae 11335 if (bgp == NULL) {
11336 if (!use_json)
11337 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11338 else
11339 vty_out(vty, "{}\n");
d62a17ae 11340 return CMD_WARNING;
11341 }
4dd6177e 11342
cd8c2a27
MS
11343 /* Labeled-unicast routes live in the unicast table. */
11344 if (safi == SAFI_LABELED_UNICAST)
11345 safi = SAFI_UNICAST;
11346
1ae44dfc 11347 table = bgp->rib[afi][safi];
d62a17ae 11348 /* use MPLS and ENCAP specific shows until they are merged */
11349 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11350 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11351 output_arg, use_json);
d62a17ae 11352 }
dba3c1d3
PG
11353
11354 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11355 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11356 output_arg, use_json,
11357 1, NULL, NULL);
11358 }
fee0f4c6 11359
96f3485c 11360 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11361 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11362 rpki_target_state);
fee0f4c6 11363}
11364
d62a17ae 11365static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11366 safi_t safi, uint16_t show_flags)
f186de26 11367{
d62a17ae 11368 struct listnode *node, *nnode;
11369 struct bgp *bgp;
11370 int is_first = 1;
9f049418 11371 bool route_output = false;
96f3485c 11372 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11373
d62a17ae 11374 if (use_json)
11375 vty_out(vty, "{\n");
9f689658 11376
d62a17ae 11377 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11378 route_output = true;
d62a17ae 11379 if (use_json) {
11380 if (!is_first)
11381 vty_out(vty, ",\n");
11382 else
11383 is_first = 0;
11384
11385 vty_out(vty, "\"%s\":",
11386 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11387 ? VRF_DEFAULT_NAME
d62a17ae 11388 : bgp->name);
11389 } else {
11390 vty_out(vty, "\nInstance %s:\n",
11391 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11392 ? VRF_DEFAULT_NAME
d62a17ae 11393 : bgp->name);
11394 }
11395 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11396 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11397 }
9f689658 11398
d62a17ae 11399 if (use_json)
11400 vty_out(vty, "}\n");
9f049418
DS
11401 else if (!route_output)
11402 vty_out(vty, "%% BGP instance not found\n");
f186de26 11403}
11404
718e3744 11405/* Header of detailed BGP route information */
d62a17ae 11406void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11407 struct bgp_dest *dest,
11408 const struct prefix_rd *prd,
d62a17ae 11409 afi_t afi, safi_t safi, json_object *json)
11410{
40381db7 11411 struct bgp_path_info *pi;
b54892e0 11412 const struct prefix *p;
d62a17ae 11413 struct peer *peer;
11414 struct listnode *node, *nnode;
06b9f471 11415 char buf1[RD_ADDRSTRLEN];
d62a17ae 11416 int count = 0;
11417 int best = 0;
11418 int suppress = 0;
c5f1e1b2
C
11419 int accept_own = 0;
11420 int route_filter_translated_v4 = 0;
11421 int route_filter_v4 = 0;
11422 int route_filter_translated_v6 = 0;
11423 int route_filter_v6 = 0;
11424 int llgr_stale = 0;
11425 int no_llgr = 0;
11426 int accept_own_nexthop = 0;
11427 int blackhole = 0;
d62a17ae 11428 int no_export = 0;
11429 int no_advertise = 0;
11430 int local_as = 0;
c5f1e1b2 11431 int no_peer = 0;
d62a17ae 11432 int first = 1;
11433 int has_valid_label = 0;
11434 mpls_label_t label = 0;
11435 json_object *json_adv_to = NULL;
9bedbb1e 11436
9bcb3eef
DS
11437 p = bgp_dest_get_prefix(dest);
11438 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11439
11440 if (has_valid_label)
9bcb3eef 11441 label = label_pton(&dest->local_label);
d62a17ae 11442
44c69747 11443 if (safi == SAFI_EVPN) {
d62a17ae 11444
44c69747 11445 if (!json) {
2dbe669b 11446 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11447 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11448 : "",
2dbe669b 11449 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11450 } else {
11451 json_object_string_add(json, "rd",
11452 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11453 "");
11454 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11455 }
11456 } else {
11457 if (!json) {
9119ef3a
DA
11458 vty_out(vty,
11459 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11460 "\n",
d62a17ae 11461 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11462 ? prefix_rd2str(prd, buf1,
11463 sizeof(buf1))
11464 : ""),
9119ef3a
DA
11465 safi == SAFI_MPLS_VPN ? ":" : "", p,
11466 dest->version);
cd1964ff 11467
9119ef3a 11468 } else {
67d7e256 11469 json_object_string_addf(json, "prefix", "%pFX", p);
9119ef3a
DA
11470 json_object_int_add(json, "version", dest->version);
11471
11472 }
44c69747
LK
11473 }
11474
11475 if (has_valid_label) {
11476 if (json)
11477 json_object_int_add(json, "localLabel", label);
11478 else
d62a17ae 11479 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11480 }
11481
11482 if (!json)
d62a17ae 11483 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11484 vty_out(vty, "not allocated\n");
718e3744 11485
9bcb3eef 11486 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11487 count++;
40381db7 11488 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11489 best = count;
4056a5f6 11490 if (bgp_path_suppressed(pi))
d62a17ae 11491 suppress = 1;
cee9c031 11492
40381db7 11493 if (pi->attr->community == NULL)
cee9c031
QY
11494 continue;
11495
11496 no_advertise += community_include(
40381db7
DS
11497 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11498 no_export += community_include(pi->attr->community,
cee9c031 11499 COMMUNITY_NO_EXPORT);
40381db7 11500 local_as += community_include(pi->attr->community,
cee9c031 11501 COMMUNITY_LOCAL_AS);
40381db7 11502 accept_own += community_include(pi->attr->community,
cee9c031
QY
11503 COMMUNITY_ACCEPT_OWN);
11504 route_filter_translated_v4 += community_include(
40381db7 11505 pi->attr->community,
cee9c031
QY
11506 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11507 route_filter_translated_v6 += community_include(
40381db7 11508 pi->attr->community,
cee9c031
QY
11509 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11510 route_filter_v4 += community_include(
40381db7 11511 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11512 route_filter_v6 += community_include(
40381db7
DS
11513 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11514 llgr_stale += community_include(pi->attr->community,
cee9c031 11515 COMMUNITY_LLGR_STALE);
40381db7 11516 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11517 COMMUNITY_NO_LLGR);
11518 accept_own_nexthop +=
40381db7 11519 community_include(pi->attr->community,
cee9c031 11520 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11521 blackhole += community_include(pi->attr->community,
cee9c031 11522 COMMUNITY_BLACKHOLE);
40381db7 11523 no_peer += community_include(pi->attr->community,
cee9c031 11524 COMMUNITY_NO_PEER);
d62a17ae 11525 }
718e3744 11526 }
718e3744 11527
d62a17ae 11528 if (!json) {
11529 vty_out(vty, "Paths: (%d available", count);
11530 if (best) {
11531 vty_out(vty, ", best #%d", best);
b84060bb
PG
11532 if (safi == SAFI_UNICAST) {
11533 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11534 vty_out(vty, ", table %s",
11535 VRF_DEFAULT_NAME);
11536 else
11537 vty_out(vty, ", vrf %s",
11538 bgp->name);
11539 }
d62a17ae 11540 } else
11541 vty_out(vty, ", no best path");
11542
c5f1e1b2
C
11543 if (accept_own)
11544 vty_out(vty,
11545 ", accept own local route exported and imported in different VRF");
11546 else if (route_filter_translated_v4)
11547 vty_out(vty,
11548 ", mark translated RTs for VPNv4 route filtering");
11549 else if (route_filter_v4)
11550 vty_out(vty,
11551 ", attach RT as-is for VPNv4 route filtering");
11552 else if (route_filter_translated_v6)
11553 vty_out(vty,
11554 ", mark translated RTs for VPNv6 route filtering");
11555 else if (route_filter_v6)
11556 vty_out(vty,
11557 ", attach RT as-is for VPNv6 route filtering");
11558 else if (llgr_stale)
11559 vty_out(vty,
1479ed2f 11560 ", mark routes to be retained for a longer time. Requires support for Long-lived BGP Graceful Restart");
c5f1e1b2
C
11561 else if (no_llgr)
11562 vty_out(vty,
11563 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11564 else if (accept_own_nexthop)
11565 vty_out(vty,
11566 ", accept local nexthop");
11567 else if (blackhole)
11568 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11569 else if (no_export)
11570 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11571 else if (no_advertise)
11572 vty_out(vty, ", not advertised to any peer");
d62a17ae 11573 else if (local_as)
11574 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11575 else if (no_peer)
11576 vty_out(vty,
11577 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11578
11579 if (suppress)
11580 vty_out(vty,
11581 ", Advertisements suppressed by an aggregate.");
11582 vty_out(vty, ")\n");
11583 }
718e3744 11584
d62a17ae 11585 /* If we are not using addpath then we can display Advertised to and
11586 * that will
11587 * show what peers we advertised the bestpath to. If we are using
11588 * addpath
11589 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11590 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11591 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11592 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11593 if (json && !json_adv_to)
11594 json_adv_to = json_object_new_object();
11595
11596 route_vty_out_advertised_to(
11597 vty, peer, &first,
11598 " Advertised to non peer-group peers:\n ",
11599 json_adv_to);
11600 }
11601 }
11602
11603 if (json) {
11604 if (json_adv_to) {
11605 json_object_object_add(json, "advertisedTo",
11606 json_adv_to);
11607 }
11608 } else {
11609 if (first)
11610 vty_out(vty, " Not advertised to any peer");
11611 vty_out(vty, "\n");
11612 }
11613 }
718e3744 11614}
11615
edfee30d 11616static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11617 struct bgp_dest *bgp_node, struct vty *vty,
11618 struct bgp *bgp, afi_t afi, safi_t safi,
11619 json_object *json, enum bgp_path_type pathtype,
4027d19b 11620 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11621{
11622 struct bgp_path_info *pi;
11623 int header = 1;
11624 char rdbuf[RD_ADDRSTRLEN];
11625 json_object *json_header = NULL;
11626 json_object *json_paths = NULL;
4933eaaf 11627 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11628
9bcb3eef 11629 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11630 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11631
11632 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11633 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11634 pi->peer, pi->attr, p);
4933eaaf 11635
4027d19b
DS
11636 if (rpki_target_state != RPKI_NOT_BEING_USED
11637 && rpki_curr_state != rpki_target_state)
4933eaaf 11638 continue;
44c69747
LK
11639
11640 if (json && !json_paths) {
11641 /* Instantiate json_paths only if path is valid */
11642 json_paths = json_object_new_array();
11643 if (pfx_rd) {
11644 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11645 json_header = json_object_new_object();
11646 } else
11647 json_header = json;
11648 }
11649
11650 if (header) {
11651 route_vty_out_detail_header(
11652 vty, bgp, bgp_node, pfx_rd,
11653 AFI_IP, safi, json_header);
11654 header = 0;
11655 }
11656 (*display)++;
11657
11658 if (pathtype == BGP_PATH_SHOW_ALL
11659 || (pathtype == BGP_PATH_SHOW_BESTPATH
11660 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11661 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11662 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11663 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11664 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11665 safi, rpki_curr_state, json_paths);
44c69747
LK
11666 }
11667
11668 if (json && json_paths) {
11669 json_object_object_add(json_header, "paths", json_paths);
11670
11671 if (pfx_rd)
11672 json_object_object_add(json, rdbuf, json_header);
11673 }
11674}
11675
2aad8c42
MS
11676/*
11677 * Return rd based on safi
11678 */
11679static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11680 safi_t safi)
11681{
11682 switch (safi) {
11683 case SAFI_MPLS_VPN:
11684 case SAFI_ENCAP:
11685 case SAFI_EVPN:
11686 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11687 default:
11688 return NULL;
11689
11690 }
11691}
11692
718e3744 11693/* Display specified route of BGP table. */
d62a17ae 11694static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11695 struct bgp_table *rib, const char *ip_str,
11696 afi_t afi, safi_t safi,
4027d19b 11697 enum rpki_states rpki_target_state,
d62a17ae 11698 struct prefix_rd *prd, int prefix_check,
9f049418 11699 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11700{
11701 int ret;
d62a17ae 11702 int display = 0;
11703 struct prefix match;
9bcb3eef
DS
11704 struct bgp_dest *dest;
11705 struct bgp_dest *rm;
d62a17ae 11706 struct bgp_table *table;
11707 json_object *json = NULL;
11708 json_object *json_paths = NULL;
11709
11710 /* Check IP address argument. */
11711 ret = str2prefix(ip_str, &match);
11712 if (!ret) {
11713 vty_out(vty, "address is malformed\n");
11714 return CMD_WARNING;
11715 }
718e3744 11716
d62a17ae 11717 match.family = afi2family(afi);
b05a1c8b 11718
44c69747 11719 if (use_json)
d62a17ae 11720 json = json_object_new_object();
718e3744 11721
44c69747 11722 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11723 for (dest = bgp_table_top(rib); dest;
11724 dest = bgp_route_next(dest)) {
11725 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11726
9bcb3eef 11727 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11728 continue;
9bcb3eef 11729 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11730 if (!table)
ea47320b 11731 continue;
d62a17ae 11732
4953391b
DA
11733 rm = bgp_node_match(table, &match);
11734 if (rm == NULL)
ea47320b 11735 continue;
d62a17ae 11736
9bcb3eef 11737 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11738 if (prefix_check
b54892e0 11739 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11740 bgp_dest_unlock_node(rm);
ea47320b
DL
11741 continue;
11742 }
d62a17ae 11743
9bcb3eef 11744 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11745 bgp, afi, safi, json, pathtype,
4027d19b 11746 &display, rpki_target_state);
44c69747 11747
9bcb3eef 11748 bgp_dest_unlock_node(rm);
44c69747
LK
11749 }
11750 } else if (safi == SAFI_EVPN) {
9bcb3eef 11751 struct bgp_dest *longest_pfx;
cded3b72 11752 bool is_exact_pfxlen_match = false;
44c69747 11753
9bcb3eef
DS
11754 for (dest = bgp_table_top(rib); dest;
11755 dest = bgp_route_next(dest)) {
11756 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11757
9bcb3eef 11758 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11759 continue;
9bcb3eef 11760 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11761 if (!table)
11762 continue;
11763
11764 longest_pfx = NULL;
cded3b72 11765 is_exact_pfxlen_match = false;
44c69747
LK
11766 /*
11767 * Search through all the prefixes for a match. The
11768 * pfx's are enumerated in ascending order of pfxlens.
11769 * So, the last pfx match is the longest match. Set
11770 * is_exact_pfxlen_match when we get exact pfxlen match
11771 */
11772 for (rm = bgp_table_top(table); rm;
11773 rm = bgp_route_next(rm)) {
b54892e0 11774 const struct prefix *rm_p =
9bcb3eef 11775 bgp_dest_get_prefix(rm);
44c69747
LK
11776 /*
11777 * Get prefixlen of the ip-prefix within type5
11778 * evpn route
11779 */
b54892e0
DS
11780 if (evpn_type5_prefix_match(rm_p, &match)
11781 && rm->info) {
44c69747
LK
11782 longest_pfx = rm;
11783 int type5_pfxlen =
b54892e0
DS
11784 bgp_evpn_get_type5_prefixlen(
11785 rm_p);
44c69747 11786 if (type5_pfxlen == match.prefixlen) {
cded3b72 11787 is_exact_pfxlen_match = true;
9bcb3eef 11788 bgp_dest_unlock_node(rm);
44c69747
LK
11789 break;
11790 }
d62a17ae 11791 }
11792 }
ea47320b 11793
44c69747
LK
11794 if (!longest_pfx)
11795 continue;
11796
11797 if (prefix_check && !is_exact_pfxlen_match)
11798 continue;
11799
11800 rm = longest_pfx;
9bcb3eef 11801 bgp_dest_lock_node(rm);
44c69747 11802
9bcb3eef 11803 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11804 bgp, afi, safi, json, pathtype,
4027d19b 11805 &display, rpki_target_state);
44c69747 11806
9bcb3eef 11807 bgp_dest_unlock_node(rm);
d62a17ae 11808 }
98a9dbc7 11809 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11810 if (use_json)
11811 json_paths = json_object_new_array();
11812
63a0b7a9
PG
11813 display = bgp_flowspec_display_match_per_ip(afi, rib,
11814 &match, prefix_check,
11815 vty,
11816 use_json,
11817 json_paths);
d5f20468
SP
11818 if (use_json) {
11819 if (display)
11820 json_object_object_add(json, "paths",
11821 json_paths);
11822 else
11823 json_object_free(json_paths);
11824 }
d62a17ae 11825 } else {
4953391b
DA
11826 dest = bgp_node_match(rib, &match);
11827 if (dest != NULL) {
9bcb3eef 11828 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11829 if (!prefix_check
9bcb3eef
DS
11830 || dest_p->prefixlen == match.prefixlen) {
11831 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11832 safi, json, pathtype,
4027d19b 11833 &display, rpki_target_state);
d62a17ae 11834 }
11835
9bcb3eef 11836 bgp_dest_unlock_node(dest);
d62a17ae 11837 }
11838 }
e5eee9af 11839
d62a17ae 11840 if (use_json) {
75eeda93 11841 vty_json(vty, json);
d62a17ae 11842 } else {
11843 if (!display) {
11844 vty_out(vty, "%% Network not in table\n");
11845 return CMD_WARNING;
11846 }
11847 }
b05a1c8b 11848
d62a17ae 11849 return CMD_SUCCESS;
718e3744 11850}
11851
fee0f4c6 11852/* Display specified route of Main RIB */
d62a17ae 11853static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11854 afi_t afi, safi_t safi, struct prefix_rd *prd,
11855 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11856 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11857{
9b86009a 11858 if (!bgp) {
d62a17ae 11859 bgp = bgp_get_default();
9b86009a
RW
11860 if (!bgp) {
11861 if (!use_json)
11862 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11863 else
11864 vty_out(vty, "{}\n");
9b86009a
RW
11865 return CMD_WARNING;
11866 }
11867 }
d62a17ae 11868
11869 /* labeled-unicast routes live in the unicast table */
11870 if (safi == SAFI_LABELED_UNICAST)
11871 safi = SAFI_UNICAST;
11872
11873 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11874 afi, safi, rpki_target_state, prd,
8aa22bbb 11875 prefix_check, pathtype, use_json);
d62a17ae 11876}
11877
11878static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11879 struct cmd_token **argv, bool exact, afi_t afi,
11880 safi_t safi, bool uj)
d62a17ae 11881{
11882 struct lcommunity *lcom;
11883 struct buffer *b;
11884 int i;
11885 char *str;
11886 int first = 0;
96c81f66 11887 uint16_t show_flags = 0;
4f28b2b5 11888 int ret;
96f3485c
MK
11889
11890 if (uj)
11891 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11892
11893 b = buffer_new(1024);
11894 for (i = 0; i < argc; i++) {
11895 if (first)
11896 buffer_putc(b, ' ');
11897 else {
11898 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11899 first = 1;
11900 buffer_putstr(b, argv[i]->arg);
11901 }
11902 }
11903 }
11904 buffer_putc(b, '\0');
57d187bc 11905
d62a17ae 11906 str = buffer_getstr(b);
11907 buffer_free(b);
57d187bc 11908
d62a17ae 11909 lcom = lcommunity_str2com(str);
11910 XFREE(MTYPE_TMP, str);
11911 if (!lcom) {
11912 vty_out(vty, "%% Large-community malformed\n");
11913 return CMD_WARNING;
11914 }
57d187bc 11915
4f28b2b5 11916 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11917 (exact ? bgp_show_type_lcommunity_exact
11918 : bgp_show_type_lcommunity),
11919 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11920
11921 lcommunity_free(&lcom);
11922 return ret;
57d187bc
JS
11923}
11924
d62a17ae 11925static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11926 const char *lcom, bool exact, afi_t afi,
11927 safi_t safi, bool uj)
57d187bc 11928{
d62a17ae 11929 struct community_list *list;
96c81f66 11930 uint16_t show_flags = 0;
96f3485c
MK
11931
11932 if (uj)
11933 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11934
57d187bc 11935
e237b0d2 11936 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11937 LARGE_COMMUNITY_LIST_MASTER);
11938 if (list == NULL) {
11939 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11940 lcom);
11941 return CMD_WARNING;
11942 }
57d187bc 11943
36a206db 11944 return bgp_show(vty, bgp, afi, safi,
11945 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11946 : bgp_show_type_lcommunity_list),
1e2ce4f1 11947 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11948}
11949
52951b63
DS
11950DEFUN (show_ip_bgp_large_community_list,
11951 show_ip_bgp_large_community_list_cmd,
77a3a95e 11952 "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
11953 SHOW_STR
11954 IP_STR
11955 BGP_STR
11956 BGP_INSTANCE_HELP_STR
9bedbb1e 11957 BGP_AFI_HELP_STR
4dd6177e 11958 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11959 "Display routes matching the large-community-list\n"
11960 "large-community-list number\n"
11961 "large-community-list name\n"
36a206db 11962 "Exact match of the large-communities\n"
52951b63
DS
11963 JSON_STR)
11964{
d62a17ae 11965 afi_t afi = AFI_IP6;
11966 safi_t safi = SAFI_UNICAST;
11967 int idx = 0;
36a206db 11968 bool exact_match = 0;
4d678463 11969 struct bgp *bgp = NULL;
9f049418 11970 bool uj = use_json(argc, argv);
d62a17ae 11971
ef3364f0
DA
11972 if (uj)
11973 argc--;
4d678463 11974
ef3364f0
DA
11975 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11976 &bgp, uj);
11977 if (!idx)
11978 return CMD_WARNING;
d62a17ae 11979
11980 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11981
11982 const char *clist_number_or_name = argv[++idx]->arg;
11983
11984 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11985 exact_match = 1;
11986
11987 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11988 exact_match, afi, safi, uj);
52951b63
DS
11989}
11990DEFUN (show_ip_bgp_large_community,
11991 show_ip_bgp_large_community_cmd,
36a206db 11992 "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
11993 SHOW_STR
11994 IP_STR
11995 BGP_STR
11996 BGP_INSTANCE_HELP_STR
9bedbb1e 11997 BGP_AFI_HELP_STR
4dd6177e 11998 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11999 "Display routes matching the large-communities\n"
12000 "List of large-community numbers\n"
36a206db 12001 "Exact match of the large-communities\n"
52951b63
DS
12002 JSON_STR)
12003{
d62a17ae 12004 afi_t afi = AFI_IP6;
12005 safi_t safi = SAFI_UNICAST;
12006 int idx = 0;
36a206db 12007 bool exact_match = 0;
4d678463 12008 struct bgp *bgp = NULL;
9f049418 12009 bool uj = use_json(argc, argv);
96c81f66 12010 uint16_t show_flags = 0;
d62a17ae 12011
96f3485c
MK
12012 if (uj) {
12013 argc--;
12014 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12015 }
4d678463 12016
96f3485c
MK
12017 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12018 &bgp, uj);
12019 if (!idx)
12020 return CMD_WARNING;
d62a17ae 12021
36a206db 12022 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
12023 if (argv_find(argv, argc, "exact-match", &idx))
12024 exact_match = 1;
12025 return bgp_show_lcommunity(vty, bgp, argc, argv,
12026 exact_match, afi, safi, uj);
12027 } else
d62a17ae 12028 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
12029 bgp_show_type_lcommunity_all, NULL, show_flags,
12030 RPKI_NOT_BEING_USED);
52951b63
DS
12031}
12032
71f1613a
DA
12033static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12034 safi_t safi, struct json_object *json_array);
d62a17ae 12035static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 12036 safi_t safi, struct json_object *json);
e01ca200 12037
7b2ff250 12038
9ab0cf58
PG
12039DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
12040 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
12041 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
12042 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
12043{
12044 bool uj = use_json(argc, argv);
12045 struct bgp *bgp = NULL;
ec76a1d1
DA
12046 safi_t safi = SAFI_UNICAST;
12047 afi_t afi = AFI_IP6;
4265b261 12048 int idx = 0;
6c9d22e2
PG
12049 struct json_object *json_all = NULL;
12050 struct json_object *json_afi_safi = NULL;
4265b261
PG
12051
12052 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12053 &bgp, false);
71f1613a 12054 if (!idx)
4265b261 12055 return CMD_WARNING;
6c9d22e2 12056
4265b261 12057 if (uj)
6c9d22e2 12058 json_all = json_object_new_object();
4265b261 12059
9ab0cf58
PG
12060 FOREACH_AFI_SAFI (afi, safi) {
12061 /*
12062 * So limit output to those afi/safi pairs that
12063 * actually have something interesting in them
12064 */
12065 if (strmatch(get_afi_safi_str(afi, safi, true),
12066 "Unknown")) {
12067 continue;
12068 }
12069 if (uj) {
12070 json_afi_safi = json_object_new_array();
12071 json_object_object_add(
12072 json_all,
12073 get_afi_safi_str(afi, safi, true),
12074 json_afi_safi);
12075 } else {
12076 json_afi_safi = NULL;
6c9d22e2 12077 }
9ab0cf58
PG
12078
12079 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 12080 }
6c9d22e2 12081
3757f964
DA
12082 if (uj)
12083 vty_json(vty, json_all);
6c9d22e2 12084
4265b261
PG
12085 return CMD_SUCCESS;
12086}
12087
7b2ff250 12088/* BGP route print out function without JSON */
14718643
PG
12089DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12090 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12091 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12092 SHOW_STR
12093 IP_STR
12094 BGP_STR
12095 BGP_INSTANCE_HELP_STR
12096 L2VPN_HELP_STR
12097 EVPN_HELP_STR
12098 "BGP RIB advertisement statistics\n"
12099 JSON_STR)
12100{
ec76a1d1
DA
12101 afi_t afi = AFI_IP6;
12102 safi_t safi = SAFI_UNICAST;
14718643
PG
12103 struct bgp *bgp = NULL;
12104 int idx = 0, ret;
12105 bool uj = use_json(argc, argv);
12106 struct json_object *json_afi_safi = NULL, *json = NULL;
12107
12108 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12109 &bgp, false);
12110 if (!idx)
12111 return CMD_WARNING;
12112
12113 if (uj)
12114 json_afi_safi = json_object_new_array();
12115 else
12116 json_afi_safi = NULL;
12117
12118 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12119
12120 if (uj) {
12121 json = json_object_new_object();
12122 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12123 json_afi_safi);
3757f964 12124 vty_json(vty, json);
14718643
PG
12125 }
12126 return ret;
12127}
12128
893cccd0 12129/* BGP route print out function without JSON */
9ab0cf58
PG
12130DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12131 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12132 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12133 "]]\
893cccd0 12134 statistics [json]",
9ab0cf58
PG
12135 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12136 BGP_SAFI_WITH_LABEL_HELP_STR
12137 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12138{
ec76a1d1
DA
12139 afi_t afi = AFI_IP6;
12140 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12141 struct bgp *bgp = NULL;
12142 int idx = 0, ret;
12143 bool uj = use_json(argc, argv);
6c9d22e2 12144 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12145
12146 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12147 &bgp, false);
12148 if (!idx)
12149 return CMD_WARNING;
6c9d22e2 12150
893cccd0 12151 if (uj)
6c9d22e2
PG
12152 json_afi_safi = json_object_new_array();
12153 else
12154 json_afi_safi = NULL;
12155
12156 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12157
12158 if (uj) {
12159 json = json_object_new_object();
12160 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12161 json_afi_safi);
3757f964 12162 vty_json(vty, json);
893cccd0
PG
12163 }
12164 return ret;
893cccd0 12165}
7b2ff250 12166
fe0f234d 12167DEFPY(show_ip_bgp_dampening_params, show_ip_bgp_dampening_params_cmd,
9ab0cf58
PG
12168 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12169 " [" BGP_SAFI_WITH_LABEL_CMD_STR
fe0f234d 12170 "]] [all$all] dampening parameters [json]",
9ab0cf58
PG
12171 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12172 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12173 "Display the entries for all address families\n"
9ab0cf58
PG
12174 "Display detailed information about dampening\n"
12175 "Display detail of configured dampening parameters\n"
fe0f234d 12176 JSON_STR)
718e3744 12177{
d62a17ae 12178 afi_t afi = AFI_IP6;
12179 safi_t safi = SAFI_UNICAST;
d62a17ae 12180 struct bgp *bgp = NULL;
12181 int idx = 0;
96c81f66 12182 uint16_t show_flags = 0;
fe0f234d
RW
12183 bool uj = use_json(argc, argv);
12184
12185 if (uj) {
12186 argc--;
12187 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12188 }
96f3485c
MK
12189
12190 /* [<ipv4|ipv6> [all]] */
12191 if (all) {
12192 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12193 if (argv_find(argv, argc, "ipv4", &idx))
12194 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12195
12196 if (argv_find(argv, argc, "ipv6", &idx))
12197 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12198 }
d62a17ae 12199
12200 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12201 &bgp, false);
d62a17ae 12202 if (!idx)
12203 return CMD_WARNING;
12204
fe0f234d 12205 return bgp_show_dampening_parameters(vty, afi, safi, show_flags);
7b2ff250
DW
12206}
12207
fe0f234d
RW
12208/* BGP route print out function */
12209DEFPY(show_ip_bgp, show_ip_bgp_cmd,
a70a28a5
DA
12210 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12211 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12212 "]]\
96f3485c 12213 [all$all]\
cf4898bc
QY
12214 [cidr-only\
12215 |dampening <flap-statistics|dampened-paths>\
12216 |community [AA:NN|local-AS|no-advertise|no-export\
12217 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12218 |accept-own|accept-own-nexthop|route-filter-v6\
12219 |route-filter-v4|route-filter-translated-v6\
12220 |route-filter-translated-v4] [exact-match]\
70799983 12221 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
a7129347 12222 |filter-list AS_PATH_FILTER_NAME\
6deaf579 12223 |prefix-list WORD\
bf1a944a 12224 |route-map WORD\
1e2ce4f1 12225 |rpki <invalid|valid|notfound>\
7d3cae70 12226 |version (1-4294967295)\
b4ad2fae 12227 |alias ALIAS_NAME\
39c3c736
RW
12228 |A.B.C.D/M longer-prefixes\
12229 |X:X::X:X/M longer-prefixes\
f280c93b 12230 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12231 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12232 BGP_SAFI_WITH_LABEL_HELP_STR
12233 "Display the entries for all address families\n"
12234 "Display only routes with non-natural netmasks\n"
12235 "Display detailed information about dampening\n"
12236 "Display flap statistics of routes\n"
12237 "Display paths suppressed due to dampening\n"
12238 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12239 "Do not send outside local AS (well-known community)\n"
12240 "Do not advertise to any peer (well-known community)\n"
12241 "Do not export to next AS (well-known community)\n"
12242 "Graceful shutdown (well-known community)\n"
12243 "Do not export to any peer (well-known community)\n"
12244 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12245 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12246 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12247 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12248 "Should accept VPN route with local nexthop (well-known community)\n"
12249 "RT VPNv6 route filtering (well-known community)\n"
12250 "RT VPNv4 route filtering (well-known community)\n"
12251 "RT translated VPNv6 route filtering (well-known community)\n"
12252 "RT translated VPNv4 route filtering (well-known community)\n"
12253 "Exact match of the communities\n"
70799983
RW
12254 "Community-list number\n"
12255 "Community-list name\n"
12256 "Display routes matching the community-list\n"
12257 "Exact match of the communities\n"
a7129347
RW
12258 "Display routes conforming to the filter-list\n"
12259 "Regular expression access list name\n"
6deaf579
RW
12260 "Display routes conforming to the prefix-list\n"
12261 "Prefix-list name\n"
bf1a944a
RW
12262 "Display routes matching the route-map\n"
12263 "A route-map to match on\n"
a70a28a5
DA
12264 "RPKI route types\n"
12265 "A valid path as determined by rpki\n"
12266 "A invalid path as determined by rpki\n"
12267 "A path that has no rpki data\n"
12268 "Display prefixes with matching version numbers\n"
12269 "Version number and above\n"
12270 "Display prefixes with matching BGP community alias\n"
39c3c736
RW
12271 "BGP community alias\n"
12272 "IPv4 prefix\n"
12273 "Display route and more specific routes\n"
12274 "IPv6 prefix\n"
12275 "Display route and more specific routes\n"
12276 JSON_STR
a70a28a5
DA
12277 "Display detailed version of JSON output\n"
12278 "Increase table width for longer prefixes\n")
7b2ff250
DW
12279{
12280 afi_t afi = AFI_IP6;
12281 safi_t safi = SAFI_UNICAST;
12282 enum bgp_show_type sh_type = bgp_show_type_normal;
2391833e 12283 void *output_arg = NULL;
7b2ff250
DW
12284 struct bgp *bgp = NULL;
12285 int idx = 0;
d0086e8e 12286 int exact_match = 0;
96f3485c
MK
12287 char *community = NULL;
12288 bool first = true;
96c81f66 12289 uint16_t show_flags = 0;
4027d19b 12290 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
cd44428d 12291 struct prefix p;
96f3485c
MK
12292
12293 if (uj) {
9f049418 12294 argc--;
96f3485c
MK
12295 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12296 }
12297
f280c93b
DA
12298 if (detail)
12299 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12300
96f3485c
MK
12301 /* [<ipv4|ipv6> [all]] */
12302 if (all) {
12303 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12304
12305 if (argv_find(argv, argc, "ipv4", &idx))
12306 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12307
12308 if (argv_find(argv, argc, "ipv6", &idx))
12309 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12310 }
12311
12312 if (wide)
12313 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12314
12315 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12316 &bgp, uj);
7b2ff250
DW
12317 if (!idx)
12318 return CMD_WARNING;
12319
7b2ff250 12320 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12321 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12322
12323 if (argv_find(argv, argc, "dampening", &idx)) {
12324 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12325 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12326 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12327 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12328 }
12329
12330 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12331 char *maybecomm = NULL;
d0086e8e 12332
79bc257a
RW
12333 if (idx + 1 < argc) {
12334 if (argv[idx + 1]->type == VARIABLE_TKN)
12335 maybecomm = argv[idx + 1]->arg;
12336 else
12337 maybecomm = argv[idx + 1]->text;
12338 }
12339
cf4898bc
QY
12340 if (maybecomm && !strmatch(maybecomm, "json")
12341 && !strmatch(maybecomm, "exact-match"))
12342 community = maybecomm;
d0086e8e 12343
cf4898bc
QY
12344 if (argv_find(argv, argc, "exact-match", &idx))
12345 exact_match = 1;
d0086e8e 12346
96f3485c
MK
12347 if (!community)
12348 sh_type = bgp_show_type_community_all;
12349 }
12350
70799983
RW
12351 if (argv_find(argv, argc, "community-list", &idx)) {
12352 const char *clist_number_or_name = argv[++idx]->arg;
12353 struct community_list *list;
12354
12355 if (argv_find(argv, argc, "exact-match", &idx))
12356 exact_match = 1;
12357
12358 list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
12359 COMMUNITY_LIST_MASTER);
12360 if (list == NULL) {
12361 vty_out(vty,
12362 "%% %s is not a valid community-list name\n",
12363 clist_number_or_name);
12364 return CMD_WARNING;
12365 }
12366
12367 if (exact_match)
12368 sh_type = bgp_show_type_community_list_exact;
12369 else
12370 sh_type = bgp_show_type_community_list;
12371 output_arg = list;
12372 }
12373
a7129347
RW
12374 if (argv_find(argv, argc, "filter-list", &idx)) {
12375 const char *filter = argv[++idx]->arg;
12376 struct as_list *as_list;
12377
12378 as_list = as_list_lookup(filter);
12379 if (as_list == NULL) {
12380 vty_out(vty,
12381 "%% %s is not a valid AS-path access-list name\n",
12382 filter);
12383 return CMD_WARNING;
12384 }
12385
12386 sh_type = bgp_show_type_filter_list;
12387 output_arg = as_list;
12388 }
12389
6deaf579
RW
12390 if (argv_find(argv, argc, "prefix-list", &idx)) {
12391 const char *prefix_list_str = argv[++idx]->arg;
12392 struct prefix_list *plist;
12393
12394 plist = prefix_list_lookup(afi, prefix_list_str);
12395 if (plist == NULL) {
12396 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12397 prefix_list_str);
12398 return CMD_WARNING;
12399 }
12400
12401 sh_type = bgp_show_type_prefix_list;
12402 output_arg = plist;
12403 }
12404
bf1a944a
RW
12405 if (argv_find(argv, argc, "route-map", &idx)) {
12406 const char *rmap_str = argv[++idx]->arg;
12407 struct route_map *rmap;
12408
12409 rmap = route_map_lookup_by_name(rmap_str);
12410 if (!rmap) {
12411 vty_out(vty, "%% %s is not a valid route-map name\n",
12412 rmap_str);
12413 return CMD_WARNING;
12414 }
12415
12416 sh_type = bgp_show_type_route_map;
12417 output_arg = rmap;
12418 }
12419
1e2ce4f1
DS
12420 if (argv_find(argv, argc, "rpki", &idx)) {
12421 sh_type = bgp_show_type_rpki;
12422 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12423 rpki_target_state = RPKI_VALID;
1e2ce4f1 12424 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12425 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12426 }
12427
7d3cae70
DA
12428 /* Display prefixes with matching version numbers */
12429 if (argv_find(argv, argc, "version", &idx)) {
12430 sh_type = bgp_show_type_prefix_version;
2391833e 12431 output_arg = argv[idx + 1]->arg;
7d3cae70
DA
12432 }
12433
a70a28a5
DA
12434 /* Display prefixes with matching BGP community alias */
12435 if (argv_find(argv, argc, "alias", &idx)) {
12436 sh_type = bgp_show_type_community_alias;
2391833e 12437 output_arg = argv[idx + 1]->arg;
a70a28a5
DA
12438 }
12439
39c3c736
RW
12440 /* prefix-longer */
12441 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12442 || argv_find(argv, argc, "X:X::X:X/M", &idx)) {
12443 const char *prefix_str = argv[idx]->arg;
39c3c736
RW
12444
12445 if (!str2prefix(prefix_str, &p)) {
12446 vty_out(vty, "%% Malformed Prefix\n");
12447 return CMD_WARNING;
12448 }
12449
12450 sh_type = bgp_show_type_prefix_longer;
12451 output_arg = &p;
a70a28a5
DA
12452 }
12453
96f3485c
MK
12454 if (!all) {
12455 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12456 if (community)
12457 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12458 exact_match, afi, safi,
12459 show_flags);
2391833e 12460 else
a70a28a5 12461 return bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12462 output_arg, show_flags,
a70a28a5 12463 rpki_target_state);
96f3485c
MK
12464 } else {
12465 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12466 * AFI_IP6 */
12467
12468 if (uj)
12469 vty_out(vty, "{\n");
12470
12471 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12472 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12473 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12474 ? AFI_IP
12475 : AFI_IP6;
12476 FOREACH_SAFI (safi) {
96f3485c
MK
12477 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12478 continue;
12479
12480 if (uj) {
12481 if (first)
12482 first = false;
12483 else
12484 vty_out(vty, ",\n");
12485 vty_out(vty, "\"%s\":{\n",
12486 get_afi_safi_str(afi, safi,
12487 true));
12488 } else
12489 vty_out(vty,
12490 "\nFor address family: %s\n",
12491 get_afi_safi_str(afi, safi,
12492 false));
12493
12494 if (community)
12495 bgp_show_community(vty, bgp, community,
12496 exact_match, afi,
12497 safi, show_flags);
12498 else
12499 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12500 output_arg, show_flags,
4027d19b 12501 rpki_target_state);
96f3485c
MK
12502 if (uj)
12503 vty_out(vty, "}\n");
12504 }
12505 } else {
12506 /* show <ip> bgp all: for each AFI and SAFI*/
12507 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12508 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12509 continue;
12510
12511 if (uj) {
12512 if (first)
12513 first = false;
12514 else
12515 vty_out(vty, ",\n");
d0086e8e 12516
96f3485c
MK
12517 vty_out(vty, "\"%s\":{\n",
12518 get_afi_safi_str(afi, safi,
12519 true));
12520 } else
12521 vty_out(vty,
12522 "\nFor address family: %s\n",
12523 get_afi_safi_str(afi, safi,
12524 false));
12525
12526 if (community)
12527 bgp_show_community(vty, bgp, community,
12528 exact_match, afi,
12529 safi, show_flags);
12530 else
12531 bgp_show(vty, bgp, afi, safi, sh_type,
2391833e 12532 output_arg, show_flags,
4027d19b 12533 rpki_target_state);
96f3485c
MK
12534 if (uj)
12535 vty_out(vty, "}\n");
12536 }
12537 }
12538 if (uj)
12539 vty_out(vty, "}\n");
12540 }
12541 return CMD_SUCCESS;
a636c635 12542}
47fc97cc 12543
718e3744 12544DEFUN (show_ip_bgp_route,
12545 show_ip_bgp_route_cmd,
8aa22bbb 12546 "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 12547 SHOW_STR
12548 IP_STR
12549 BGP_STR
a636c635 12550 BGP_INSTANCE_HELP_STR
4f280b15 12551 BGP_AFI_HELP_STR
4dd6177e 12552 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12553 "Network in the BGP routing table to display\n"
0c7b1b01 12554 "IPv4 prefix\n"
8c3deaae 12555 "Network in the BGP routing table to display\n"
0c7b1b01 12556 "IPv6 prefix\n"
4092b06c 12557 "Display only the bestpath\n"
b05a1c8b 12558 "Display only multipaths\n"
8aa22bbb
DS
12559 "Display only paths that match the specified rpki state\n"
12560 "A valid path as determined by rpki\n"
12561 "A invalid path as determined by rpki\n"
12562 "A path that has no rpki data\n"
9973d184 12563 JSON_STR)
4092b06c 12564{
d62a17ae 12565 int prefix_check = 0;
ae19d7dd 12566
d62a17ae 12567 afi_t afi = AFI_IP6;
12568 safi_t safi = SAFI_UNICAST;
12569 char *prefix = NULL;
12570 struct bgp *bgp = NULL;
12571 enum bgp_path_type path_type;
9f049418 12572 bool uj = use_json(argc, argv);
b05a1c8b 12573
d62a17ae 12574 int idx = 0;
ae19d7dd 12575
d62a17ae 12576 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12577 &bgp, uj);
d62a17ae 12578 if (!idx)
12579 return CMD_WARNING;
c41247f5 12580
d62a17ae 12581 if (!bgp) {
12582 vty_out(vty,
12583 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12584 return CMD_WARNING;
12585 }
a636c635 12586
d62a17ae 12587 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12588 if (argv_find(argv, argc, "A.B.C.D", &idx)
12589 || argv_find(argv, argc, "X:X::X:X", &idx))
12590 prefix_check = 0;
12591 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12592 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12593 prefix_check = 1;
12594
12595 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12596 && afi != AFI_IP6) {
12597 vty_out(vty,
12598 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12599 return CMD_WARNING;
12600 }
12601 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12602 && afi != AFI_IP) {
12603 vty_out(vty,
12604 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12605 return CMD_WARNING;
12606 }
12607
12608 prefix = argv[idx]->arg;
12609
12610 /* [<bestpath|multipath>] */
12611 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12612 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12613 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12614 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12615 else
360660c6 12616 path_type = BGP_PATH_SHOW_ALL;
a636c635 12617
d62a17ae 12618 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12619 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12620}
12621
8c3deaae
QY
12622DEFUN (show_ip_bgp_regexp,
12623 show_ip_bgp_regexp_cmd,
3e5b31b3 12624 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12625 SHOW_STR
12626 IP_STR
12627 BGP_STR
b00b230a 12628 BGP_INSTANCE_HELP_STR
4f280b15 12629 BGP_AFI_HELP_STR
4dd6177e 12630 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12631 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12632 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12633 JSON_STR)
8c3deaae 12634{
d62a17ae 12635 afi_t afi = AFI_IP6;
12636 safi_t safi = SAFI_UNICAST;
12637 struct bgp *bgp = NULL;
3e5b31b3
DA
12638 bool uj = use_json(argc, argv);
12639 char *regstr = NULL;
8c3deaae 12640
d62a17ae 12641 int idx = 0;
12642 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12643 &bgp, false);
d62a17ae 12644 if (!idx)
12645 return CMD_WARNING;
8c3deaae 12646
d62a17ae 12647 // get index of regex
3e5b31b3
DA
12648 if (argv_find(argv, argc, "REGEX", &idx))
12649 regstr = argv[idx]->arg;
8c3deaae 12650
5f71d11c 12651 assert(regstr);
3e5b31b3
DA
12652 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12653 bgp_show_type_regexp, uj);
8c3deaae
QY
12654}
12655
ae248832 12656DEFPY (show_ip_bgp_instance_all,
a636c635 12657 show_ip_bgp_instance_all_cmd,
ae248832 12658 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12659 SHOW_STR
a636c635 12660 IP_STR
4092b06c 12661 BGP_STR
a636c635 12662 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12663 BGP_AFI_HELP_STR
4dd6177e 12664 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12665 JSON_STR
12666 "Increase table width for longer prefixes\n")
4092b06c 12667{
54d05dea 12668 afi_t afi = AFI_IP6;
d62a17ae 12669 safi_t safi = SAFI_UNICAST;
12670 struct bgp *bgp = NULL;
d62a17ae 12671 int idx = 0;
96c81f66 12672 uint16_t show_flags = 0;
ae19d7dd 12673
96f3485c 12674 if (uj) {
d62a17ae 12675 argc--;
96f3485c
MK
12676 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12677 }
12678
12679 if (wide)
12680 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12681
9f049418
DS
12682 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12683 &bgp, uj);
12684 if (!idx)
12685 return CMD_WARNING;
12686
96f3485c 12687 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12688 return CMD_SUCCESS;
e3e29b32
LB
12689}
12690
a4d82a8a 12691static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12692 afi_t afi, safi_t safi, enum bgp_show_type type,
12693 bool use_json)
718e3744 12694{
d62a17ae 12695 regex_t *regex;
12696 int rc;
96c81f66 12697 uint16_t show_flags = 0;
96f3485c
MK
12698
12699 if (use_json)
12700 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12701
c3900853 12702 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12703 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12704 regstr);
12705 return CMD_WARNING_CONFIG_FAILED;
12706 }
12707
d62a17ae 12708 regex = bgp_regcomp(regstr);
12709 if (!regex) {
12710 vty_out(vty, "Can't compile regexp %s\n", regstr);
12711 return CMD_WARNING;
12712 }
a636c635 12713
1e2ce4f1
DS
12714 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12715 RPKI_NOT_BEING_USED);
d62a17ae 12716 bgp_regex_free(regex);
12717 return rc;
e3e29b32
LB
12718}
12719
7f323236
DW
12720static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12721 const char *comstr, int exact, afi_t afi,
96c81f66 12722 safi_t safi, uint16_t show_flags)
d62a17ae 12723{
12724 struct community *com;
d62a17ae 12725 int ret = 0;
12726
7f323236 12727 com = community_str2com(comstr);
d62a17ae 12728 if (!com) {
7f323236 12729 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12730 return CMD_WARNING;
12731 }
12732
12733 ret = bgp_show(vty, bgp, afi, safi,
12734 (exact ? bgp_show_type_community_exact
12735 : bgp_show_type_community),
1e2ce4f1 12736 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12737 community_free(&com);
46c3ce83 12738
d62a17ae 12739 return ret;
718e3744 12740}
12741
d62a17ae 12742enum bgp_stats {
12743 BGP_STATS_MAXBITLEN = 0,
12744 BGP_STATS_RIB,
12745 BGP_STATS_PREFIXES,
12746 BGP_STATS_TOTPLEN,
12747 BGP_STATS_UNAGGREGATEABLE,
12748 BGP_STATS_MAX_AGGREGATEABLE,
12749 BGP_STATS_AGGREGATES,
12750 BGP_STATS_SPACE,
12751 BGP_STATS_ASPATH_COUNT,
12752 BGP_STATS_ASPATH_MAXHOPS,
12753 BGP_STATS_ASPATH_TOTHOPS,
12754 BGP_STATS_ASPATH_MAXSIZE,
12755 BGP_STATS_ASPATH_TOTSIZE,
12756 BGP_STATS_ASN_HIGHEST,
12757 BGP_STATS_MAX,
a636c635 12758};
2815e61f 12759
9ab0cf58 12760#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12761#define TABLE_STATS_IDX_JSON 1
12762
12763static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12764 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12765 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12766 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12767 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12768 "unaggregateablePrefixes"},
12769 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12770 "maximumAggregateablePrefixes"},
12771 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12772 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12773 [BGP_STATS_SPACE] = {"Address space advertised",
12774 "addressSpaceAdvertised"},
9ab0cf58
PG
12775 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12776 "advertisementsWithPaths"},
12777 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12778 "longestAsPath"},
12779 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12780 "largestAsPath"},
12781 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12782 "averageAsPathLengthHops"},
12783 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12784 "averageAsPathSizeBytes"},
12785 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12786 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12787};
2815e61f 12788
d62a17ae 12789struct bgp_table_stats {
12790 struct bgp_table *table;
12791 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12792 double total_space;
ff7924f6
PJ
12793};
12794
9bcb3eef 12795static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12796 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12797{
9bcb3eef 12798 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12799 struct bgp_path_info *pi;
b54892e0 12800 const struct prefix *rn_p;
d62a17ae 12801
9bcb3eef 12802 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12803 return;
d62a17ae 12804
9bcb3eef 12805 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12806 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12807 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12808
9c14ec72 12809 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12810 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12811 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12812
9bcb3eef 12813 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12814 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12815 /* announced address space */
12816 if (space)
b54892e0 12817 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12818 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12819 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12820
9c14ec72 12821
9bcb3eef 12822 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12823 ts->counts[BGP_STATS_RIB]++;
12824
05864da7
DS
12825 if (CHECK_FLAG(pi->attr->flag,
12826 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12827 ts->counts[BGP_STATS_AGGREGATES]++;
12828
12829 /* as-path stats */
05864da7 12830 if (pi->attr->aspath) {
9c14ec72
RW
12831 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12832 unsigned int size = aspath_size(pi->attr->aspath);
12833 as_t highest = aspath_highest(pi->attr->aspath);
12834
12835 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12836
12837 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12838 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12839
12840 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12841 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12842
12843 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12844 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12845 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12846 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12847 }
12848 }
12849}
12850
cc9f21da 12851static void bgp_table_stats_walker(struct thread *t)
9c14ec72 12852{
9bcb3eef
DS
12853 struct bgp_dest *dest, *ndest;
12854 struct bgp_dest *top;
9c14ec72
RW
12855 struct bgp_table_stats *ts = THREAD_ARG(t);
12856 unsigned int space = 0;
12857
12858 if (!(top = bgp_table_top(ts->table)))
cc9f21da 12859 return;
9c14ec72
RW
12860
12861 switch (ts->table->afi) {
12862 case AFI_IP:
12863 space = IPV4_MAX_BITLEN;
12864 break;
12865 case AFI_IP6:
12866 space = IPV6_MAX_BITLEN;
12867 break;
3ba7b4af
TA
12868 case AFI_L2VPN:
12869 space = EVPN_ROUTE_PREFIXLEN;
12870 break;
9c14ec72 12871 default:
cc9f21da 12872 return;
9c14ec72
RW
12873 }
12874
12875 ts->counts[BGP_STATS_MAXBITLEN] = space;
12876
9bcb3eef 12877 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12878 if (ts->table->safi == SAFI_MPLS_VPN
12879 || ts->table->safi == SAFI_ENCAP
12880 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12881 struct bgp_table *table;
12882
9bcb3eef 12883 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12884 if (!table)
12885 continue;
12886
12887 top = bgp_table_top(table);
9bcb3eef
DS
12888 for (ndest = bgp_table_top(table); ndest;
12889 ndest = bgp_route_next(ndest))
12890 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12891 } else {
9bcb3eef 12892 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12893 }
12894 }
2815e61f 12895}
ff7924f6 12896
71f1613a
DA
12897static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12898 struct json_object *json_array)
12899{
12900 struct listnode *node, *nnode;
12901 struct bgp *bgp;
12902
12903 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12904 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12905}
12906
12907static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12908 safi_t safi, struct json_object *json_array)
2815e61f 12909{
d62a17ae 12910 struct bgp_table_stats ts;
12911 unsigned int i;
893cccd0
PG
12912 int ret = CMD_SUCCESS;
12913 char temp_buf[20];
6c9d22e2
PG
12914 struct json_object *json = NULL;
12915
12916 if (json_array)
12917 json = json_object_new_object();
019386c2 12918
d62a17ae 12919 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12920 char warning_msg[50];
12921
12922 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12923 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12924 safi);
6c9d22e2
PG
12925
12926 if (!json)
893cccd0
PG
12927 vty_out(vty, "%s\n", warning_msg);
12928 else
9ab0cf58 12929 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12930
893cccd0
PG
12931 ret = CMD_WARNING;
12932 goto end_table_stats;
d62a17ae 12933 }
019386c2 12934
893cccd0 12935 if (!json)
5290ceab
DA
12936 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12937 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12938 else
12939 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12940
d62a17ae 12941 /* labeled-unicast routes live in the unicast table */
12942 if (safi == SAFI_LABELED_UNICAST)
12943 safi = SAFI_UNICAST;
019386c2 12944
d62a17ae 12945 memset(&ts, 0, sizeof(ts));
12946 ts.table = bgp->rib[afi][safi];
12947 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12948
d62a17ae 12949 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12950 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12951 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12952 continue;
12953
12954 switch (i) {
d62a17ae 12955 case BGP_STATS_ASPATH_TOTHOPS:
12956 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12957 if (!json) {
9ab0cf58
PG
12958 snprintf(
12959 temp_buf, sizeof(temp_buf), "%12.2f",
12960 ts.counts[i]
12961 ? (float)ts.counts[i]
12962 / (float)ts.counts
12963 [BGP_STATS_ASPATH_COUNT]
12964 : 0);
893cccd0 12965 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12966 table_stats_strs[i]
12967 [TABLE_STATS_IDX_VTY],
893cccd0 12968 temp_buf);
9ab0cf58
PG
12969 } else {
12970 json_object_double_add(
12971 json,
12972 table_stats_strs[i]
12973 [TABLE_STATS_IDX_JSON],
12974 ts.counts[i]
12975 ? (double)ts.counts[i]
12976 / (double)ts.counts
d62a17ae 12977 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12978 : 0);
12979 }
d62a17ae 12980 break;
12981 case BGP_STATS_TOTPLEN:
6c9d22e2 12982 if (!json) {
9ab0cf58
PG
12983 snprintf(
12984 temp_buf, sizeof(temp_buf), "%12.2f",
12985 ts.counts[i]
12986 ? (float)ts.counts[i]
12987 / (float)ts.counts
12988 [BGP_STATS_PREFIXES]
12989 : 0);
893cccd0 12990 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12991 table_stats_strs[i]
12992 [TABLE_STATS_IDX_VTY],
893cccd0 12993 temp_buf);
9ab0cf58
PG
12994 } else {
12995 json_object_double_add(
12996 json,
12997 table_stats_strs[i]
12998 [TABLE_STATS_IDX_JSON],
12999 ts.counts[i]
13000 ? (double)ts.counts[i]
13001 / (double)ts.counts
d62a17ae 13002 [BGP_STATS_PREFIXES]
9ab0cf58
PG
13003 : 0);
13004 }
d62a17ae 13005 break;
13006 case BGP_STATS_SPACE:
6c9d22e2
PG
13007 if (!json) {
13008 snprintf(temp_buf, sizeof(temp_buf), "%12g",
13009 ts.total_space);
893cccd0 13010 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
13011 table_stats_strs[i]
13012 [TABLE_STATS_IDX_VTY],
893cccd0 13013 temp_buf);
9ab0cf58
PG
13014 } else {
13015 json_object_double_add(
13016 json,
13017 table_stats_strs[i]
13018 [TABLE_STATS_IDX_JSON],
13019 (double)ts.total_space);
13020 }
8d0ab76d 13021 if (afi == AFI_IP6) {
6c9d22e2
PG
13022 if (!json) {
13023 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13024 "%12g",
13025 ts.total_space
13026 * pow(2.0, -128 + 32));
6c9d22e2
PG
13027 vty_out(vty, "%30s: %s\n",
13028 "/32 equivalent %s\n",
13029 temp_buf);
9ab0cf58
PG
13030 } else {
13031 json_object_double_add(
13032 json, "/32equivalent",
13033 (double)(ts.total_space
13034 * pow(2.0,
13035 -128 + 32)));
13036 }
6c9d22e2
PG
13037 if (!json) {
13038 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13039 "%12g",
13040 ts.total_space
13041 * pow(2.0, -128 + 48));
6c9d22e2
PG
13042 vty_out(vty, "%30s: %s\n",
13043 "/48 equivalent %s\n",
13044 temp_buf);
9ab0cf58
PG
13045 } else {
13046 json_object_double_add(
13047 json, "/48equivalent",
13048 (double)(ts.total_space
13049 * pow(2.0,
13050 -128 + 48)));
13051 }
8d0ab76d 13052 } else {
6c9d22e2
PG
13053 if (!json) {
13054 snprintf(temp_buf, sizeof(temp_buf),
13055 "%12.2f",
9ab0cf58
PG
13056 ts.total_space * 100.
13057 * pow(2.0, -32));
6c9d22e2 13058 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13059 "% announced ", temp_buf);
13060 } else {
13061 json_object_double_add(
13062 json, "%announced",
13063 (double)(ts.total_space * 100.
13064 * pow(2.0, -32)));
13065 }
6c9d22e2
PG
13066 if (!json) {
13067 snprintf(temp_buf, sizeof(temp_buf),
13068 "%12.2f",
9ab0cf58
PG
13069 ts.total_space
13070 * pow(2.0, -32 + 8));
6c9d22e2
PG
13071 vty_out(vty, "%30s: %s\n",
13072 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13073 } else {
13074 json_object_double_add(
13075 json, "/8equivalent",
13076 (double)(ts.total_space
13077 * pow(2.0, -32 + 8)));
13078 }
6c9d22e2
PG
13079 if (!json) {
13080 snprintf(temp_buf, sizeof(temp_buf),
13081 "%12.2f",
9ab0cf58
PG
13082 ts.total_space
13083 * pow(2.0, -32 + 24));
6c9d22e2 13084 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13085 "/24 equivalent ", temp_buf);
13086 } else {
13087 json_object_double_add(
13088 json, "/24equivalent",
13089 (double)(ts.total_space
13090 * pow(2.0, -32 + 24)));
13091 }
8d0ab76d 13092 }
d62a17ae 13093 break;
13094 default:
6c9d22e2
PG
13095 if (!json) {
13096 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13097 ts.counts[i]);
893cccd0 13098 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13099 table_stats_strs[i]
13100 [TABLE_STATS_IDX_VTY],
13101 temp_buf);
13102 } else {
13103 json_object_int_add(
13104 json,
13105 table_stats_strs[i]
13106 [TABLE_STATS_IDX_JSON],
13107 ts.counts[i]);
13108 }
d62a17ae 13109 }
893cccd0
PG
13110 if (!json)
13111 vty_out(vty, "\n");
d62a17ae 13112 }
9ab0cf58 13113end_table_stats:
6c9d22e2
PG
13114 if (json)
13115 json_object_array_add(json_array, json);
893cccd0 13116 return ret;
d62a17ae 13117}
13118
71f1613a
DA
13119static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13120 safi_t safi, struct json_object *json_array)
13121{
13122 if (!bgp) {
13123 bgp_table_stats_all(vty, afi, safi, json_array);
13124 return CMD_SUCCESS;
13125 }
13126
13127 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13128}
13129
d62a17ae 13130enum bgp_pcounts {
13131 PCOUNT_ADJ_IN = 0,
13132 PCOUNT_DAMPED,
13133 PCOUNT_REMOVED,
13134 PCOUNT_HISTORY,
13135 PCOUNT_STALE,
13136 PCOUNT_VALID,
13137 PCOUNT_ALL,
13138 PCOUNT_COUNTED,
7e3d9632 13139 PCOUNT_BPATH_SELECTED,
d62a17ae 13140 PCOUNT_PFCNT, /* the figure we display to users */
13141 PCOUNT_MAX,
a636c635 13142};
718e3744 13143
2b64873d 13144static const char *const pcount_strs[] = {
9d303b37
DL
13145 [PCOUNT_ADJ_IN] = "Adj-in",
13146 [PCOUNT_DAMPED] = "Damped",
13147 [PCOUNT_REMOVED] = "Removed",
13148 [PCOUNT_HISTORY] = "History",
13149 [PCOUNT_STALE] = "Stale",
13150 [PCOUNT_VALID] = "Valid",
13151 [PCOUNT_ALL] = "All RIB",
13152 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13153 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13154 [PCOUNT_PFCNT] = "Useable",
13155 [PCOUNT_MAX] = NULL,
a636c635 13156};
718e3744 13157
d62a17ae 13158struct peer_pcounts {
13159 unsigned int count[PCOUNT_MAX];
13160 const struct peer *peer;
13161 const struct bgp_table *table;
54317cba 13162 safi_t safi;
a636c635 13163};
47fc97cc 13164
9bcb3eef 13165static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13166{
54317cba
JW
13167 const struct bgp_adj_in *ain;
13168 const struct bgp_path_info *pi;
d62a17ae 13169 const struct peer *peer = pc->peer;
13170
54317cba
JW
13171 for (ain = rn->adj_in; ain; ain = ain->next)
13172 if (ain->peer == peer)
13173 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13174
9bcb3eef 13175 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13176
54317cba
JW
13177 if (pi->peer != peer)
13178 continue;
d62a17ae 13179
54317cba 13180 pc->count[PCOUNT_ALL]++;
d62a17ae 13181
54317cba
JW
13182 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13183 pc->count[PCOUNT_DAMPED]++;
13184 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13185 pc->count[PCOUNT_HISTORY]++;
13186 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13187 pc->count[PCOUNT_REMOVED]++;
13188 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13189 pc->count[PCOUNT_STALE]++;
13190 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13191 pc->count[PCOUNT_VALID]++;
13192 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13193 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13194 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13195 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13196
13197 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13198 pc->count[PCOUNT_COUNTED]++;
13199 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13200 flog_err(
13201 EC_LIB_DEVELOPMENT,
13202 "Attempting to count but flags say it is unusable");
13203 } else {
40381db7 13204 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13205 flog_err(
13206 EC_LIB_DEVELOPMENT,
13207 "Not counted but flags say we should");
d62a17ae 13208 }
13209 }
54317cba
JW
13210}
13211
cc9f21da 13212static void bgp_peer_count_walker(struct thread *t)
54317cba 13213{
9bcb3eef 13214 struct bgp_dest *rn, *rm;
54317cba
JW
13215 const struct bgp_table *table;
13216 struct peer_pcounts *pc = THREAD_ARG(t);
13217
13218 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13219 || pc->safi == SAFI_EVPN) {
13220 /* Special handling for 2-level routing tables. */
13221 for (rn = bgp_table_top(pc->table); rn;
13222 rn = bgp_route_next(rn)) {
9bcb3eef 13223 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13224 if (table != NULL)
13225 for (rm = bgp_table_top(table); rm;
13226 rm = bgp_route_next(rm))
13227 bgp_peer_count_proc(rm, pc);
13228 }
13229 } else
13230 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13231 bgp_peer_count_proc(rn, pc);
718e3744 13232}
13233
d62a17ae 13234static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13235 safi_t safi, bool use_json)
856ca177 13236{
d62a17ae 13237 struct peer_pcounts pcounts = {.peer = peer};
13238 unsigned int i;
13239 json_object *json = NULL;
13240 json_object *json_loop = NULL;
856ca177 13241
d62a17ae 13242 if (use_json) {
13243 json = json_object_new_object();
13244 json_loop = json_object_new_object();
13245 }
718e3744 13246
d62a17ae 13247 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13248 || !peer->bgp->rib[afi][safi]) {
13249 if (use_json) {
13250 json_object_string_add(
13251 json, "warning",
13252 "No such neighbor or address family");
13253 vty_out(vty, "%s\n", json_object_to_json_string(json));
13254 json_object_free(json);
d5f20468 13255 json_object_free(json_loop);
d62a17ae 13256 } else
13257 vty_out(vty, "%% No such neighbor or address family\n");
13258
13259 return CMD_WARNING;
13260 }
2a71e9ce 13261
d62a17ae 13262 memset(&pcounts, 0, sizeof(pcounts));
13263 pcounts.peer = peer;
13264 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13265 pcounts.safi = safi;
d62a17ae 13266
13267 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13268 * stats for the thread-walk (i.e. ensure this can't be blamed on
13269 * on just vty_read()).
13270 */
d62a17ae 13271 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13272
13273 if (use_json) {
13274 json_object_string_add(json, "prefixCountsFor", peer->host);
13275 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13276 get_afi_safi_str(afi, safi, true));
d62a17ae 13277 json_object_int_add(json, "pfxCounter",
13278 peer->pcount[afi][safi]);
13279
13280 for (i = 0; i < PCOUNT_MAX; i++)
13281 json_object_int_add(json_loop, pcount_strs[i],
13282 pcounts.count[i]);
13283
13284 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13285
13286 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13287 json_object_string_add(json, "pfxctDriftFor",
13288 peer->host);
13289 json_object_string_add(
13290 json, "recommended",
13291 "Please report this bug, with the above command output");
13292 }
75eeda93 13293 vty_json(vty, json);
d62a17ae 13294 } else {
13295
13296 if (peer->hostname
892fedb6 13297 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13298 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13299 peer->hostname, peer->host,
5cb5f4d0 13300 get_afi_safi_str(afi, safi, false));
d62a17ae 13301 } else {
13302 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13303 get_afi_safi_str(afi, safi, false));
d62a17ae 13304 }
13305
6cde4b45 13306 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13307 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13308
13309 for (i = 0; i < PCOUNT_MAX; i++)
13310 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13311 pcounts.count[i]);
13312
13313 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13314 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13315 vty_out(vty,
13316 "Please report this bug, with the above command output\n");
13317 }
13318 }
13319
13320 return CMD_SUCCESS;
718e3744 13321}
13322
a636c635
DW
13323DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13324 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13325 "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 13326 SHOW_STR
13327 IP_STR
13328 BGP_STR
8386ac43 13329 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13330 BGP_AFI_HELP_STR
13331 BGP_SAFI_HELP_STR
0b16f239
DS
13332 "Detailed information on TCP and BGP neighbor connections\n"
13333 "Neighbor to display information about\n"
13334 "Neighbor to display information about\n"
91d37724 13335 "Neighbor on BGP configured interface\n"
a636c635 13336 "Display detailed prefix count information\n"
9973d184 13337 JSON_STR)
0b16f239 13338{
d62a17ae 13339 afi_t afi = AFI_IP6;
13340 safi_t safi = SAFI_UNICAST;
13341 struct peer *peer;
13342 int idx = 0;
13343 struct bgp *bgp = NULL;
9f049418
DS
13344 bool uj = use_json(argc, argv);
13345
13346 if (uj)
13347 argc--;
856ca177 13348
d62a17ae 13349 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13350 &bgp, uj);
d62a17ae 13351 if (!idx)
13352 return CMD_WARNING;
0b16f239 13353
d62a17ae 13354 argv_find(argv, argc, "neighbors", &idx);
13355 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13356 if (!peer)
13357 return CMD_WARNING;
bb46e94f 13358
29c8d9da 13359 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13360}
0b16f239 13361
d6902373
PG
13362#ifdef KEEP_OLD_VPN_COMMANDS
13363DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13364 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13365 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13366 SHOW_STR
13367 IP_STR
13368 BGP_STR
d6902373 13369 BGP_VPNVX_HELP_STR
91d37724 13370 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13371 "Detailed information on TCP and BGP neighbor connections\n"
13372 "Neighbor to display information about\n"
13373 "Neighbor to display information about\n"
91d37724 13374 "Neighbor on BGP configured interface\n"
a636c635 13375 "Display detailed prefix count information\n"
9973d184 13376 JSON_STR)
a636c635 13377{
d62a17ae 13378 int idx_peer = 6;
13379 struct peer *peer;
9f049418 13380 bool uj = use_json(argc, argv);
a636c635 13381
d62a17ae 13382 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13383 if (!peer)
13384 return CMD_WARNING;
13385
13386 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13387}
13388
d6902373
PG
13389DEFUN (show_ip_bgp_vpn_all_route_prefix,
13390 show_ip_bgp_vpn_all_route_prefix_cmd,
13391 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13392 SHOW_STR
13393 IP_STR
13394 BGP_STR
d6902373 13395 BGP_VPNVX_HELP_STR
91d37724
QY
13396 "Display information about all VPNv4 NLRIs\n"
13397 "Network in the BGP routing table to display\n"
3a2d747c 13398 "Network in the BGP routing table to display\n"
9973d184 13399 JSON_STR)
91d37724 13400{
d62a17ae 13401 int idx = 0;
13402 char *network = NULL;
13403 struct bgp *bgp = bgp_get_default();
13404 if (!bgp) {
13405 vty_out(vty, "Can't find default instance\n");
13406 return CMD_WARNING;
13407 }
87e34b58 13408
d62a17ae 13409 if (argv_find(argv, argc, "A.B.C.D", &idx))
13410 network = argv[idx]->arg;
13411 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13412 network = argv[idx]->arg;
13413 else {
13414 vty_out(vty, "Unable to figure out Network\n");
13415 return CMD_WARNING;
13416 }
87e34b58 13417
d62a17ae 13418 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13419 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13420 use_json(argc, argv));
91d37724 13421}
d6902373 13422#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13423
44c69747
LK
13424DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13425 show_bgp_l2vpn_evpn_route_prefix_cmd,
13426 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13427 SHOW_STR
4c63a661
PG
13428 BGP_STR
13429 L2VPN_HELP_STR
13430 EVPN_HELP_STR
44c69747
LK
13431 "Network in the BGP routing table to display\n"
13432 "Network in the BGP routing table to display\n"
4c63a661
PG
13433 "Network in the BGP routing table to display\n"
13434 "Network in the BGP routing table to display\n"
13435 JSON_STR)
13436{
d62a17ae 13437 int idx = 0;
13438 char *network = NULL;
44c69747 13439 int prefix_check = 0;
a636c635 13440
44c69747
LK
13441 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13442 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13443 network = argv[idx]->arg;
44c69747 13444 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13445 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13446 network = argv[idx]->arg;
44c69747
LK
13447 prefix_check = 1;
13448 } else {
d62a17ae 13449 vty_out(vty, "Unable to figure out Network\n");
13450 return CMD_WARNING;
13451 }
44c69747
LK
13452 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13453 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13454 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13455}
13456
2f9bc755
DS
13457static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13458 struct bgp_table *table, int *header1,
13459 int *header2, json_object *json,
13460 json_object *json_scode,
13461 json_object *json_ocode, bool wide)
13462{
13463 uint64_t version = table ? table->version : 0;
13464
13465 if (*header1) {
13466 if (json) {
13467 json_object_int_add(json, "bgpTableVersion", version);
c949c771
DA
13468 json_object_string_addf(json, "bgpLocalRouterId",
13469 "%pI4", &bgp->router_id);
2f9bc755
DS
13470 json_object_int_add(json, "defaultLocPrf",
13471 bgp->default_local_pref);
13472 json_object_int_add(json, "localAS", bgp->as);
13473 json_object_object_add(json, "bgpStatusCodes",
13474 json_scode);
13475 json_object_object_add(json, "bgpOriginCodes",
13476 json_ocode);
13477 } else {
13478 vty_out(vty,
23d0a753
DA
13479 "BGP table version is %" PRIu64
13480 ", local router ID is %pI4, vrf id ",
13481 version, &bgp->router_id);
2f9bc755
DS
13482 if (bgp->vrf_id == VRF_UNKNOWN)
13483 vty_out(vty, "%s", VRFID_NONE_STR);
13484 else
13485 vty_out(vty, "%u", bgp->vrf_id);
13486 vty_out(vty, "\n");
13487 vty_out(vty, "Default local pref %u, ",
13488 bgp->default_local_pref);
13489 vty_out(vty, "local AS %u\n", bgp->as);
13490 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13491 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13492 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13493 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13494 }
13495 *header1 = 0;
13496 }
13497 if (*header2) {
13498 if (!json)
13499 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13500 : BGP_SHOW_HEADER));
13501 *header2 = 0;
13502 }
13503}
13504
d9478df0
TA
13505static void
13506show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13507 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13508 const char *rmap_name, json_object *json, json_object *json_ar,
13509 json_object *json_scode, json_object *json_ocode,
96c81f66 13510 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13511 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13512{
d62a17ae 13513 struct bgp_adj_in *ain;
13514 struct bgp_adj_out *adj;
9bcb3eef 13515 struct bgp_dest *dest;
d62a17ae 13516 struct bgp *bgp;
d62a17ae 13517 struct attr attr;
13518 int ret;
13519 struct update_subgroup *subgrp;
d62a17ae 13520 struct peer_af *paf;
f99def61 13521 bool route_filtered;
96f3485c
MK
13522 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13523 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13524 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13525 || (safi == SAFI_EVPN))
13526 ? true
13527 : false;
a636c635 13528
d62a17ae 13529 bgp = peer->bgp;
a636c635 13530
d62a17ae 13531 subgrp = peer_subgroup(peer, afi, safi);
13532
6392aaa6 13533 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13534 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
13535 if (use_json) {
13536 json_object_int_add(json, "bgpTableVersion",
13537 table->version);
c949c771
DA
13538 json_object_string_addf(json, "bgpLocalRouterId",
13539 "%pI4", &bgp->router_id);
01eced22
AD
13540 json_object_int_add(json, "defaultLocPrf",
13541 bgp->default_local_pref);
13542 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13543 json_object_object_add(json, "bgpStatusCodes",
13544 json_scode);
13545 json_object_object_add(json, "bgpOriginCodes",
13546 json_ocode);
07d0c4ed
DA
13547 json_object_string_add(
13548 json, "bgpOriginatingDefaultNetwork",
13549 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13550 } else {
23d0a753
DA
13551 vty_out(vty,
13552 "BGP table version is %" PRIu64
13553 ", local router ID is %pI4, vrf id ",
13554 table->version, &bgp->router_id);
9df8b37c
PZ
13555 if (bgp->vrf_id == VRF_UNKNOWN)
13556 vty_out(vty, "%s", VRFID_NONE_STR);
13557 else
13558 vty_out(vty, "%u", bgp->vrf_id);
13559 vty_out(vty, "\n");
01eced22
AD
13560 vty_out(vty, "Default local pref %u, ",
13561 bgp->default_local_pref);
13562 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13563 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13564 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13565 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13566 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13567
07d0c4ed
DA
13568 vty_out(vty, "Originating default network %s\n\n",
13569 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13570 }
d9478df0 13571 *header1 = 0;
d62a17ae 13572 }
a636c635 13573
9bcb3eef 13574 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13575 if (type == bgp_show_adj_route_received
13576 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13577 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13578 if (ain->peer != peer)
ea47320b 13579 continue;
6392aaa6 13580
d9478df0
TA
13581 show_adj_route_header(vty, bgp, table, header1,
13582 header2, json, json_scode,
13583 json_ocode, wide);
13584
13585 if ((safi == SAFI_MPLS_VPN)
13586 || (safi == SAFI_ENCAP)
13587 || (safi == SAFI_EVPN)) {
13588 if (use_json)
13589 json_object_string_add(
13590 json_ar, "rd", rd_str);
13591 else if (show_rd && rd_str) {
13592 vty_out(vty,
13593 "Route Distinguisher: %s\n",
13594 rd_str);
13595 show_rd = false;
13596 }
13597 }
6392aaa6 13598
6f4f49b2 13599 attr = *ain->attr;
f99def61
AD
13600 route_filtered = false;
13601
13602 /* Filter prefix using distribute list,
13603 * filter list or prefix list
13604 */
b54892e0 13605 const struct prefix *rn_p =
9bcb3eef 13606 bgp_dest_get_prefix(dest);
b54892e0
DS
13607 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13608 safi))
13609 == FILTER_DENY)
f99def61
AD
13610 route_filtered = true;
13611
13612 /* Filter prefix using route-map */
b54892e0
DS
13613 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13614 safi, rmap_name, NULL,
13615 0, NULL);
6392aaa6 13616
13c8e163
AD
13617 if (type == bgp_show_adj_route_filtered &&
13618 !route_filtered && ret != RMAP_DENY) {
d498917e 13619 bgp_attr_flush(&attr);
6392aaa6 13620 continue;
d62a17ae 13621 }
6392aaa6 13622
d9478df0
TA
13623 if (type == bgp_show_adj_route_received
13624 && (route_filtered || ret == RMAP_DENY))
13625 (*filtered_count)++;
6392aaa6 13626
7d3cae70 13627 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13628 use_json, json_ar, wide);
d498917e 13629 bgp_attr_flush(&attr);
d9478df0 13630 (*output_count)++;
d62a17ae 13631 }
6392aaa6 13632 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13633 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13634 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13635 if (paf->peer != peer || !adj->attr)
924c3f6a 13636 continue;
d62a17ae 13637
d9478df0
TA
13638 show_adj_route_header(vty, bgp, table,
13639 header1, header2,
13640 json, json_scode,
13641 json_ocode, wide);
d62a17ae 13642
b54892e0 13643 const struct prefix *rn_p =
9bcb3eef 13644 bgp_dest_get_prefix(dest);
b54892e0 13645
6f4f49b2 13646 attr = *adj->attr;
b755861b 13647 ret = bgp_output_modifier(
b54892e0 13648 peer, rn_p, &attr, afi, safi,
b755861b 13649 rmap_name);
f46d8e1e 13650
b755861b 13651 if (ret != RMAP_DENY) {
d9478df0
TA
13652 if ((safi == SAFI_MPLS_VPN)
13653 || (safi == SAFI_ENCAP)
13654 || (safi == SAFI_EVPN)) {
13655 if (use_json)
13656 json_object_string_add(
13657 json_ar,
13658 "rd",
13659 rd_str);
13660 else if (show_rd
13661 && rd_str) {
13662 vty_out(vty,
13663 "Route Distinguisher: %s\n",
13664 rd_str);
13665 show_rd = false;
13666 }
13667 }
b54892e0 13668 route_vty_out_tmp(
7d3cae70
DA
13669 vty, dest, rn_p, &attr,
13670 safi, use_json, json_ar,
ae248832 13671 wide);
d9478df0 13672 (*output_count)++;
b755861b 13673 } else {
d9478df0 13674 (*filtered_count)++;
a2addae8 13675 }
b755861b 13676
d498917e 13677 bgp_attr_flush(&attr);
924c3f6a 13678 }
f20ce998
DS
13679 } else if (type == bgp_show_adj_route_bestpath) {
13680 struct bgp_path_info *pi;
13681
d9478df0
TA
13682 show_adj_route_header(vty, bgp, table, header1, header2,
13683 json, json_scode, json_ocode,
13684 wide);
f20ce998
DS
13685
13686 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13687 pi = pi->next) {
13688 if (pi->peer != peer)
13689 continue;
13690
13691 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13692 continue;
13693
7d3cae70 13694 route_vty_out_tmp(vty, dest,
f20ce998
DS
13695 bgp_dest_get_prefix(dest),
13696 pi->attr, safi, use_json,
13697 json_ar, wide);
d9478df0 13698 (*output_count)++;
f20ce998 13699 }
d62a17ae 13700 }
13701 }
a636c635 13702}
2a71e9ce 13703
d62a17ae 13704static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13705 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13706 const char *rmap_name, uint16_t show_flags)
0b16f239 13707{
d9478df0
TA
13708 struct bgp *bgp;
13709 struct bgp_table *table;
d62a17ae 13710 json_object *json = NULL;
d9478df0
TA
13711 json_object *json_scode = NULL;
13712 json_object *json_ocode = NULL;
13713 json_object *json_ar = NULL;
96f3485c 13714 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13715
d9478df0
TA
13716 /* Init BGP headers here so they're only displayed once
13717 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13718 */
13719 int header1 = 1;
13720 int header2 = 1;
13721
13722 /*
13723 * Initialize variables for each RD
13724 * All prefixes under an RD is aggregated within "json_routes"
13725 */
13726 char rd_str[BUFSIZ] = {0};
13727 json_object *json_routes = NULL;
13728
13729
13730 /* For 2-tier tables, prefix counts need to be
13731 * maintained across multiple runs of show_adj_route()
13732 */
13733 unsigned long output_count_per_rd;
13734 unsigned long filtered_count_per_rd;
13735 unsigned long output_count = 0;
13736 unsigned long filtered_count = 0;
13737
13738 if (use_json) {
d62a17ae 13739 json = json_object_new_object();
d9478df0
TA
13740 json_ar = json_object_new_object();
13741 json_scode = json_object_new_object();
13742 json_ocode = json_object_new_object();
13743
13744 json_object_string_add(json_scode, "suppressed", "s");
13745 json_object_string_add(json_scode, "damped", "d");
13746 json_object_string_add(json_scode, "history", "h");
13747 json_object_string_add(json_scode, "valid", "*");
13748 json_object_string_add(json_scode, "best", ">");
13749 json_object_string_add(json_scode, "multipath", "=");
13750 json_object_string_add(json_scode, "internal", "i");
13751 json_object_string_add(json_scode, "ribFailure", "r");
13752 json_object_string_add(json_scode, "stale", "S");
13753 json_object_string_add(json_scode, "removed", "R");
13754
13755 json_object_string_add(json_ocode, "igp", "i");
13756 json_object_string_add(json_ocode, "egp", "e");
13757 json_object_string_add(json_ocode, "incomplete", "?");
13758 }
0b16f239 13759
d62a17ae 13760 if (!peer || !peer->afc[afi][safi]) {
13761 if (use_json) {
13762 json_object_string_add(
13763 json, "warning",
13764 "No such neighbor or address family");
13765 vty_out(vty, "%s\n", json_object_to_json_string(json));
13766 json_object_free(json);
690c3134
MW
13767 json_object_free(json_ar);
13768 json_object_free(json_scode);
13769 json_object_free(json_ocode);
d62a17ae 13770 } else
13771 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13772
d62a17ae 13773 return CMD_WARNING;
13774 }
13775
6392aaa6
PM
13776 if ((type == bgp_show_adj_route_received
13777 || type == bgp_show_adj_route_filtered)
d62a17ae 13778 && !CHECK_FLAG(peer->af_flags[afi][safi],
13779 PEER_FLAG_SOFT_RECONFIG)) {
13780 if (use_json) {
13781 json_object_string_add(
13782 json, "warning",
13783 "Inbound soft reconfiguration not enabled");
13784 vty_out(vty, "%s\n", json_object_to_json_string(json));
13785 json_object_free(json);
690c3134
MW
13786 json_object_free(json_ar);
13787 json_object_free(json_scode);
13788 json_object_free(json_ocode);
d62a17ae 13789 } else
13790 vty_out(vty,
13791 "%% Inbound soft reconfiguration not enabled\n");
13792
13793 return CMD_WARNING;
13794 }
0b16f239 13795
d9478df0
TA
13796 bgp = peer->bgp;
13797
13798 /* labeled-unicast routes live in the unicast table */
13799 if (safi == SAFI_LABELED_UNICAST)
13800 table = bgp->rib[afi][SAFI_UNICAST];
13801 else
13802 table = bgp->rib[afi][safi];
13803
13804 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13805 || (safi == SAFI_EVPN)) {
13806
13807 struct bgp_dest *dest;
13808
13809 for (dest = bgp_table_top(table); dest;
13810 dest = bgp_route_next(dest)) {
13811 table = bgp_dest_get_bgp_table_info(dest);
13812 if (!table)
13813 continue;
13814
13815 output_count_per_rd = 0;
13816 filtered_count_per_rd = 0;
13817
13818 if (use_json)
13819 json_routes = json_object_new_object();
13820
13821 const struct prefix_rd *prd;
13822 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13823 dest);
13824
13825 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13826
13827 show_adj_route(vty, peer, table, afi, safi, type,
13828 rmap_name, json, json_routes, json_scode,
13829 json_ocode, show_flags, &header1,
13830 &header2, rd_str, &output_count_per_rd,
13831 &filtered_count_per_rd);
13832
13833 /* Don't include an empty RD in the output! */
13834 if (json_routes && (output_count_per_rd > 0))
13835 json_object_object_add(json_ar, rd_str,
13836 json_routes);
13837
13838 output_count += output_count_per_rd;
13839 filtered_count += filtered_count_per_rd;
13840 }
13841 } else
13842 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13843 json, json_ar, json_scode, json_ocode,
13844 show_flags, &header1, &header2, rd_str,
13845 &output_count, &filtered_count);
13846
13847 if (use_json) {
c1984955
TA
13848 if (type == bgp_show_adj_route_advertised)
13849 json_object_object_add(json, "advertisedRoutes",
13850 json_ar);
13851 else
13852 json_object_object_add(json, "receivedRoutes", json_ar);
d9478df0
TA
13853 json_object_int_add(json, "totalPrefixCounter", output_count);
13854 json_object_int_add(json, "filteredPrefixCounter",
13855 filtered_count);
13856
690c3134
MW
13857 /*
13858 * These fields only give up ownership to `json` when `header1`
13859 * is used (set to zero). See code in `show_adj_route` and
13860 * `show_adj_route_header`.
13861 */
13862 if (header1 == 1) {
d9478df0
TA
13863 json_object_free(json_scode);
13864 json_object_free(json_ocode);
13865 }
13866
75eeda93 13867 vty_json(vty, json);
d9478df0
TA
13868 } else if (output_count > 0) {
13869 if (filtered_count > 0)
13870 vty_out(vty,
13871 "\nTotal number of prefixes %ld (%ld filtered)\n",
13872 output_count, filtered_count);
13873 else
13874 vty_out(vty, "\nTotal number of prefixes %ld\n",
13875 output_count);
13876 }
0b16f239 13877
d62a17ae 13878 return CMD_SUCCESS;
a636c635 13879}
50ef26d4 13880
f20ce998
DS
13881DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13882 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13883 "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]",
13884 SHOW_STR
13885 IP_STR
13886 BGP_STR
13887 BGP_INSTANCE_HELP_STR
13888 BGP_AFI_HELP_STR
13889 BGP_SAFI_WITH_LABEL_HELP_STR
13890 "Detailed information on TCP and BGP neighbor connections\n"
13891 "Neighbor to display information about\n"
13892 "Neighbor to display information about\n"
13893 "Neighbor on BGP configured interface\n"
13894 "Display the routes selected by best path\n"
13895 JSON_STR
13896 "Increase table width for longer prefixes\n")
13897{
13898 afi_t afi = AFI_IP6;
13899 safi_t safi = SAFI_UNICAST;
13900 char *rmap_name = NULL;
13901 char *peerstr = NULL;
13902 struct bgp *bgp = NULL;
13903 struct peer *peer;
13904 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13905 int idx = 0;
96c81f66 13906 uint16_t show_flags = 0;
96f3485c
MK
13907
13908 if (uj)
13909 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13910
13911 if (wide)
13912 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13913
13914 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13915 &bgp, uj);
13916
13917 if (!idx)
13918 return CMD_WARNING;
13919
13920 argv_find(argv, argc, "neighbors", &idx);
13921 peerstr = argv[++idx]->arg;
13922
13923 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13924 if (!peer)
13925 return CMD_WARNING;
13926
96f3485c
MK
13927 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13928 show_flags);
f20ce998
DS
13929}
13930
ae248832 13931DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13932 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13933 "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 WORD] [json$uj | wide$wide]",
718e3744 13934 SHOW_STR
13935 IP_STR
13936 BGP_STR
a636c635 13937 BGP_INSTANCE_HELP_STR
7395a2c9 13938 BGP_AFI_HELP_STR
4dd6177e 13939 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13940 "Display the entries for all address families\n"
718e3744 13941 "Detailed information on TCP and BGP neighbor connections\n"
13942 "Neighbor to display information about\n"
13943 "Neighbor to display information about\n"
91d37724 13944 "Neighbor on BGP configured interface\n"
a636c635 13945 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13946 "Display the received routes from neighbor\n"
13947 "Display the filtered routes received from neighbor\n"
a636c635
DW
13948 "Route-map to modify the attributes\n"
13949 "Name of the route map\n"
ae248832
MK
13950 JSON_STR
13951 "Increase table width for longer prefixes\n")
718e3744 13952{
d62a17ae 13953 afi_t afi = AFI_IP6;
13954 safi_t safi = SAFI_UNICAST;
13955 char *rmap_name = NULL;
13956 char *peerstr = NULL;
d62a17ae 13957 struct bgp *bgp = NULL;
13958 struct peer *peer;
6392aaa6 13959 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13960 int idx = 0;
96f3485c 13961 bool first = true;
96c81f66 13962 uint16_t show_flags = 0;
6392aaa6 13963
96f3485c 13964 if (uj) {
d62a17ae 13965 argc--;
96f3485c
MK
13966 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13967 }
13968
13969 if (all) {
13970 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13971 if (argv_find(argv, argc, "ipv4", &idx))
13972 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13973
13974 if (argv_find(argv, argc, "ipv6", &idx))
13975 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13976 }
13977
13978 if (wide)
13979 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13980
9f049418
DS
13981 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13982 &bgp, uj);
13983 if (!idx)
13984 return CMD_WARNING;
13985
d62a17ae 13986 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13987 argv_find(argv, argc, "neighbors", &idx);
13988 peerstr = argv[++idx]->arg;
8c3deaae 13989
d62a17ae 13990 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13991 if (!peer)
13992 return CMD_WARNING;
856ca177 13993
d62a17ae 13994 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13995 type = bgp_show_adj_route_advertised;
13996 else if (argv_find(argv, argc, "received-routes", &idx))
13997 type = bgp_show_adj_route_received;
13998 else if (argv_find(argv, argc, "filtered-routes", &idx))
13999 type = bgp_show_adj_route_filtered;
14000
d62a17ae 14001 if (argv_find(argv, argc, "route-map", &idx))
14002 rmap_name = argv[++idx]->arg;
95cbbd2a 14003
96f3485c
MK
14004 if (!all)
14005 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14006 show_flags);
14007 if (uj)
14008 vty_out(vty, "{\n");
14009
14010 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14011 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14012 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14013 : AFI_IP6;
14014 FOREACH_SAFI (safi) {
96f3485c
MK
14015 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14016 continue;
14017
14018 if (uj) {
14019 if (first)
14020 first = false;
14021 else
14022 vty_out(vty, ",\n");
14023 vty_out(vty, "\"%s\":",
14024 get_afi_safi_str(afi, safi, true));
14025 } else
14026 vty_out(vty, "\nFor address family: %s\n",
14027 get_afi_safi_str(afi, safi, false));
14028
14029 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14030 show_flags);
14031 }
14032 } else {
14033 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
14034 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14035 continue;
14036
14037 if (uj) {
14038 if (first)
14039 first = false;
14040 else
14041 vty_out(vty, ",\n");
14042 vty_out(vty, "\"%s\":",
14043 get_afi_safi_str(afi, safi, true));
14044 } else
14045 vty_out(vty, "\nFor address family: %s\n",
14046 get_afi_safi_str(afi, safi, false));
14047
14048 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14049 show_flags);
14050 }
14051 }
14052 if (uj)
14053 vty_out(vty, "}\n");
14054
14055 return CMD_SUCCESS;
95cbbd2a
ML
14056}
14057
718e3744 14058DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14059 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14060 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14061 SHOW_STR
14062 IP_STR
14063 BGP_STR
d3120452 14064 BGP_INSTANCE_HELP_STR
8c3deaae
QY
14065 "Address Family\n"
14066 "Address Family\n"
718e3744 14067 "Address Family modifier\n"
14068 "Detailed information on TCP and BGP neighbor connections\n"
14069 "Neighbor to display information about\n"
14070 "Neighbor to display information about\n"
91d37724 14071 "Neighbor on BGP configured interface\n"
718e3744 14072 "Display information received from a BGP neighbor\n"
856ca177 14073 "Display the prefixlist filter\n"
9973d184 14074 JSON_STR)
718e3744 14075{
d62a17ae 14076 afi_t afi = AFI_IP6;
14077 safi_t safi = SAFI_UNICAST;
14078 char *peerstr = NULL;
d62a17ae 14079 char name[BUFSIZ];
d62a17ae 14080 struct peer *peer;
d3120452 14081 int count;
d62a17ae 14082 int idx = 0;
d3120452
IR
14083 struct bgp *bgp = NULL;
14084 bool uj = use_json(argc, argv);
14085
14086 if (uj)
14087 argc--;
14088
14089 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14090 &bgp, uj);
14091 if (!idx)
14092 return CMD_WARNING;
d62a17ae 14093
d62a17ae 14094 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14095 argv_find(argv, argc, "neighbors", &idx);
14096 peerstr = argv[++idx]->arg;
14097
d3120452
IR
14098 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14099 if (!peer)
14100 return CMD_WARNING;
718e3744 14101
4ced1a2c 14102 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14103 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14104 if (count) {
14105 if (!uj)
14106 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14107 get_afi_safi_str(afi, safi, false));
d62a17ae 14108 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14109 } else {
14110 if (uj)
14111 vty_out(vty, "{}\n");
14112 else
14113 vty_out(vty, "No functional output\n");
14114 }
718e3744 14115
d62a17ae 14116 return CMD_SUCCESS;
14117}
14118
14119static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14120 afi_t afi, safi_t safi,
9f049418 14121 enum bgp_show_type type, bool use_json)
d62a17ae 14122{
96c81f66 14123 uint16_t show_flags = 0;
96f3485c
MK
14124
14125 if (use_json)
14126 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14127
d62a17ae 14128 if (!peer || !peer->afc[afi][safi]) {
14129 if (use_json) {
14130 json_object *json_no = NULL;
14131 json_no = json_object_new_object();
14132 json_object_string_add(
14133 json_no, "warning",
14134 "No such neighbor or address family");
14135 vty_out(vty, "%s\n",
14136 json_object_to_json_string(json_no));
14137 json_object_free(json_no);
14138 } else
14139 vty_out(vty, "%% No such neighbor or address family\n");
14140 return CMD_WARNING;
14141 }
47fc97cc 14142
7daf25a3
TA
14143 /* labeled-unicast routes live in the unicast table */
14144 if (safi == SAFI_LABELED_UNICAST)
14145 safi = SAFI_UNICAST;
14146
1e2ce4f1
DS
14147 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14148 RPKI_NOT_BEING_USED);
718e3744 14149}
14150
dba3c1d3
PG
14151DEFUN (show_ip_bgp_flowspec_routes_detailed,
14152 show_ip_bgp_flowspec_routes_detailed_cmd,
14153 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14154 SHOW_STR
14155 IP_STR
14156 BGP_STR
14157 BGP_INSTANCE_HELP_STR
14158 BGP_AFI_HELP_STR
14159 "SAFI Flowspec\n"
14160 "Detailed information on flowspec entries\n"
14161 JSON_STR)
14162{
458c1475 14163 afi_t afi = AFI_IP6;
dba3c1d3
PG
14164 safi_t safi = SAFI_UNICAST;
14165 struct bgp *bgp = NULL;
14166 int idx = 0;
9f049418 14167 bool uj = use_json(argc, argv);
96c81f66 14168 uint16_t show_flags = 0;
9f049418 14169
96f3485c 14170 if (uj) {
9f049418 14171 argc--;
96f3485c
MK
14172 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14173 }
dba3c1d3
PG
14174
14175 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14176 &bgp, uj);
dba3c1d3
PG
14177 if (!idx)
14178 return CMD_WARNING;
14179
96f3485c 14180 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14181 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14182}
14183
718e3744 14184DEFUN (show_ip_bgp_neighbor_routes,
14185 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14186 "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 14187 SHOW_STR
14188 IP_STR
14189 BGP_STR
8386ac43 14190 BGP_INSTANCE_HELP_STR
4f280b15 14191 BGP_AFI_HELP_STR
4dd6177e 14192 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14193 "Detailed information on TCP and BGP neighbor connections\n"
14194 "Neighbor to display information about\n"
14195 "Neighbor to display information about\n"
91d37724 14196 "Neighbor on BGP configured interface\n"
2525cf39 14197 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14198 "Display the dampened routes received from neighbor\n"
14199 "Display routes learned from neighbor\n"
9973d184 14200 JSON_STR)
718e3744 14201{
d62a17ae 14202 char *peerstr = NULL;
14203 struct bgp *bgp = NULL;
14204 afi_t afi = AFI_IP6;
14205 safi_t safi = SAFI_UNICAST;
14206 struct peer *peer;
14207 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14208 int idx = 0;
9f049418
DS
14209 bool uj = use_json(argc, argv);
14210
14211 if (uj)
14212 argc--;
bb46e94f 14213
d62a17ae 14214 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14215 &bgp, uj);
d62a17ae 14216 if (!idx)
14217 return CMD_WARNING;
c493f2d8 14218
d62a17ae 14219 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14220 argv_find(argv, argc, "neighbors", &idx);
14221 peerstr = argv[++idx]->arg;
8c3deaae 14222
d62a17ae 14223 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14224 if (!peer)
d62a17ae 14225 return CMD_WARNING;
bb46e94f 14226
d62a17ae 14227 if (argv_find(argv, argc, "flap-statistics", &idx))
14228 sh_type = bgp_show_type_flap_neighbor;
14229 else if (argv_find(argv, argc, "dampened-routes", &idx))
14230 sh_type = bgp_show_type_damp_neighbor;
14231 else if (argv_find(argv, argc, "routes", &idx))
14232 sh_type = bgp_show_type_neighbor;
2525cf39 14233
d62a17ae 14234 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14235}
6b0655a2 14236
734b349e 14237struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14238
d62a17ae 14239struct bgp_distance {
14240 /* Distance value for the IP source prefix. */
d7c0a89a 14241 uint8_t distance;
718e3744 14242
d62a17ae 14243 /* Name of the access-list to be matched. */
14244 char *access_list;
718e3744 14245};
14246
4f280b15
LB
14247DEFUN (show_bgp_afi_vpn_rd_route,
14248 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14249 "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
14250 SHOW_STR
14251 BGP_STR
14252 BGP_AFI_HELP_STR
14253 "Address Family modifier\n"
14254 "Display information for a route distinguisher\n"
14255 "Route Distinguisher\n"
a111dd97 14256 "All Route Distinguishers\n"
7395a2c9
DS
14257 "Network in the BGP routing table to display\n"
14258 "Network in the BGP routing table to display\n"
14259 JSON_STR)
4f280b15 14260{
d62a17ae 14261 int ret;
14262 struct prefix_rd prd;
14263 afi_t afi = AFI_MAX;
14264 int idx = 0;
4f280b15 14265
ff6566f3
DS
14266 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14267 vty_out(vty, "%% Malformed Address Family\n");
14268 return CMD_WARNING;
14269 }
14270
a111dd97
TA
14271 if (!strcmp(argv[5]->arg, "all"))
14272 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14273 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14274 RPKI_NOT_BEING_USED,
14275 use_json(argc, argv));
14276
d62a17ae 14277 ret = str2prefix_rd(argv[5]->arg, &prd);
14278 if (!ret) {
14279 vty_out(vty, "%% Malformed Route Distinguisher\n");
14280 return CMD_WARNING;
14281 }
ff6566f3 14282
d62a17ae 14283 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14284 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14285 use_json(argc, argv));
4f280b15
LB
14286}
14287
d62a17ae 14288static struct bgp_distance *bgp_distance_new(void)
718e3744 14289{
d62a17ae 14290 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14291}
14292
d62a17ae 14293static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14294{
d62a17ae 14295 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14296}
14297
585f1adc
IR
14298static int bgp_distance_set(struct vty *vty, const char *distance_str,
14299 const char *ip_str, const char *access_list_str)
718e3744 14300{
d62a17ae 14301 int ret;
585f1adc
IR
14302 afi_t afi;
14303 safi_t safi;
d62a17ae 14304 struct prefix p;
585f1adc 14305 uint8_t distance;
9bcb3eef 14306 struct bgp_dest *dest;
d62a17ae 14307 struct bgp_distance *bdistance;
718e3744 14308
585f1adc
IR
14309 afi = bgp_node_afi(vty);
14310 safi = bgp_node_safi(vty);
14311
d62a17ae 14312 ret = str2prefix(ip_str, &p);
14313 if (ret == 0) {
585f1adc 14314 vty_out(vty, "Malformed prefix\n");
d62a17ae 14315 return CMD_WARNING_CONFIG_FAILED;
14316 }
718e3744 14317
585f1adc
IR
14318 distance = atoi(distance_str);
14319
d62a17ae 14320 /* Get BGP distance node. */
9bcb3eef
DS
14321 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14322 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14323 if (bdistance)
9bcb3eef 14324 bgp_dest_unlock_node(dest);
ca2e160d 14325 else {
d62a17ae 14326 bdistance = bgp_distance_new();
9bcb3eef 14327 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14328 }
718e3744 14329
d62a17ae 14330 /* Set distance value. */
14331 bdistance->distance = distance;
718e3744 14332
d62a17ae 14333 /* Reset access-list configuration. */
e1b36e13 14334 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14335 if (access_list_str)
14336 bdistance->access_list =
14337 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14338
d62a17ae 14339 return CMD_SUCCESS;
718e3744 14340}
14341
585f1adc
IR
14342static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14343 const char *ip_str, const char *access_list_str)
718e3744 14344{
d62a17ae 14345 int ret;
585f1adc
IR
14346 afi_t afi;
14347 safi_t safi;
d62a17ae 14348 struct prefix p;
585f1adc 14349 int distance;
9bcb3eef 14350 struct bgp_dest *dest;
d62a17ae 14351 struct bgp_distance *bdistance;
718e3744 14352
585f1adc
IR
14353 afi = bgp_node_afi(vty);
14354 safi = bgp_node_safi(vty);
14355
d62a17ae 14356 ret = str2prefix(ip_str, &p);
14357 if (ret == 0) {
585f1adc 14358 vty_out(vty, "Malformed prefix\n");
d62a17ae 14359 return CMD_WARNING_CONFIG_FAILED;
14360 }
718e3744 14361
9bcb3eef
DS
14362 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14363 if (!dest) {
585f1adc 14364 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14365 return CMD_WARNING_CONFIG_FAILED;
14366 }
718e3744 14367
9bcb3eef 14368 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14369 distance = atoi(distance_str);
1f9a9fff 14370
d62a17ae 14371 if (bdistance->distance != distance) {
585f1adc 14372 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14373 bgp_dest_unlock_node(dest);
d62a17ae 14374 return CMD_WARNING_CONFIG_FAILED;
14375 }
718e3744 14376
0a22ddfb 14377 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14378 bgp_distance_free(bdistance);
718e3744 14379
9bcb3eef
DS
14380 bgp_dest_set_bgp_path_info(dest, NULL);
14381 bgp_dest_unlock_node(dest);
14382 bgp_dest_unlock_node(dest);
718e3744 14383
d62a17ae 14384 return CMD_SUCCESS;
718e3744 14385}
14386
718e3744 14387/* Apply BGP information to distance method. */
b8685f9b 14388uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14389 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14390{
9bcb3eef 14391 struct bgp_dest *dest;
801bb996 14392 struct prefix q = {0};
d62a17ae 14393 struct peer *peer;
14394 struct bgp_distance *bdistance;
14395 struct access_list *alist;
14396 struct bgp_static *bgp_static;
14397
14398 if (!bgp)
14399 return 0;
14400
40381db7 14401 peer = pinfo->peer;
d62a17ae 14402
7b7d48e5
DS
14403 if (pinfo->attr->distance)
14404 return pinfo->attr->distance;
14405
801bb996
CS
14406 /* Check source address.
14407 * Note: for aggregate route, peer can have unspec af type.
14408 */
14409 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14410 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14411 return 0;
14412
9bcb3eef
DS
14413 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14414 if (dest) {
14415 bdistance = bgp_dest_get_bgp_distance_info(dest);
14416 bgp_dest_unlock_node(dest);
d62a17ae 14417
14418 if (bdistance->access_list) {
14419 alist = access_list_lookup(afi, bdistance->access_list);
14420 if (alist
14421 && access_list_apply(alist, p) == FILTER_PERMIT)
14422 return bdistance->distance;
14423 } else
14424 return bdistance->distance;
718e3744 14425 }
718e3744 14426
d62a17ae 14427 /* Backdoor check. */
9bcb3eef
DS
14428 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14429 if (dest) {
14430 bgp_static = bgp_dest_get_bgp_static_info(dest);
14431 bgp_dest_unlock_node(dest);
718e3744 14432
d62a17ae 14433 if (bgp_static->backdoor) {
14434 if (bgp->distance_local[afi][safi])
14435 return bgp->distance_local[afi][safi];
14436 else
14437 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14438 }
718e3744 14439 }
718e3744 14440
d62a17ae 14441 if (peer->sort == BGP_PEER_EBGP) {
14442 if (bgp->distance_ebgp[afi][safi])
14443 return bgp->distance_ebgp[afi][safi];
14444 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14445 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14446 if (bgp->distance_ibgp[afi][safi])
14447 return bgp->distance_ibgp[afi][safi];
14448 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14449 } else {
14450 if (bgp->distance_local[afi][safi])
14451 return bgp->distance_local[afi][safi];
14452 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14453 }
718e3744 14454}
14455
a612fb77
DA
14456/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14457 * we should tell ZEBRA update the routes for a specific
14458 * AFI/SAFI to reflect changes in RIB.
14459 */
585f1adc
IR
14460static void bgp_announce_routes_distance_update(struct bgp *bgp,
14461 afi_t update_afi,
14462 safi_t update_safi)
a612fb77
DA
14463{
14464 afi_t afi;
14465 safi_t safi;
14466
14467 FOREACH_AFI_SAFI (afi, safi) {
14468 if (!bgp_fibupd_safi(safi))
14469 continue;
14470
8b54bc30
DA
14471 if (afi != update_afi && safi != update_safi)
14472 continue;
14473
14474 if (BGP_DEBUG(zebra, ZEBRA))
14475 zlog_debug(
14476 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14477 __func__, afi, safi);
14478 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14479 }
14480}
14481
585f1adc
IR
14482DEFUN (bgp_distance,
14483 bgp_distance_cmd,
14484 "distance bgp (1-255) (1-255) (1-255)",
14485 "Define an administrative distance\n"
14486 "BGP distance\n"
14487 "Distance for routes external to the AS\n"
14488 "Distance for routes internal to the AS\n"
14489 "Distance for local routes\n")
718e3744 14490{
585f1adc 14491 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14492 int idx_number = 2;
14493 int idx_number_2 = 3;
14494 int idx_number_3 = 4;
585f1adc
IR
14495 int distance_ebgp = atoi(argv[idx_number]->arg);
14496 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14497 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14498 afi_t afi;
14499 safi_t safi;
718e3744 14500
d62a17ae 14501 afi = bgp_node_afi(vty);
14502 safi = bgp_node_safi(vty);
718e3744 14503
585f1adc
IR
14504 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14505 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14506 || bgp->distance_local[afi][safi] != distance_local) {
14507 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14508 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14509 bgp->distance_local[afi][safi] = distance_local;
14510 bgp_announce_routes_distance_update(bgp, afi, safi);
14511 }
14512 return CMD_SUCCESS;
14513}
37a87b8f 14514
585f1adc
IR
14515DEFUN (no_bgp_distance,
14516 no_bgp_distance_cmd,
14517 "no distance bgp [(1-255) (1-255) (1-255)]",
14518 NO_STR
14519 "Define an administrative distance\n"
14520 "BGP distance\n"
14521 "Distance for routes external to the AS\n"
14522 "Distance for routes internal to the AS\n"
14523 "Distance for local routes\n")
718e3744 14524{
585f1adc 14525 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14526 afi_t afi;
14527 safi_t safi;
37a87b8f
CS
14528
14529 afi = bgp_node_afi(vty);
14530 safi = bgp_node_safi(vty);
14531
585f1adc
IR
14532 if (bgp->distance_ebgp[afi][safi] != 0
14533 || bgp->distance_ibgp[afi][safi] != 0
14534 || bgp->distance_local[afi][safi] != 0) {
14535 bgp->distance_ebgp[afi][safi] = 0;
14536 bgp->distance_ibgp[afi][safi] = 0;
14537 bgp->distance_local[afi][safi] = 0;
14538 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14539 }
585f1adc
IR
14540 return CMD_SUCCESS;
14541}
37a87b8f 14542
37a87b8f 14543
585f1adc
IR
14544DEFUN (bgp_distance_source,
14545 bgp_distance_source_cmd,
14546 "distance (1-255) A.B.C.D/M",
14547 "Define an administrative distance\n"
14548 "Administrative distance\n"
14549 "IP source prefix\n")
14550{
14551 int idx_number = 1;
14552 int idx_ipv4_prefixlen = 2;
14553 bgp_distance_set(vty, argv[idx_number]->arg,
14554 argv[idx_ipv4_prefixlen]->arg, NULL);
14555 return CMD_SUCCESS;
734b349e
MZ
14556}
14557
585f1adc
IR
14558DEFUN (no_bgp_distance_source,
14559 no_bgp_distance_source_cmd,
14560 "no distance (1-255) A.B.C.D/M",
14561 NO_STR
14562 "Define an administrative distance\n"
14563 "Administrative distance\n"
14564 "IP source prefix\n")
37a87b8f 14565{
585f1adc
IR
14566 int idx_number = 2;
14567 int idx_ipv4_prefixlen = 3;
14568 bgp_distance_unset(vty, argv[idx_number]->arg,
14569 argv[idx_ipv4_prefixlen]->arg, NULL);
14570 return CMD_SUCCESS;
37a87b8f
CS
14571}
14572
585f1adc
IR
14573DEFUN (bgp_distance_source_access_list,
14574 bgp_distance_source_access_list_cmd,
14575 "distance (1-255) A.B.C.D/M WORD",
14576 "Define an administrative distance\n"
14577 "Administrative distance\n"
14578 "IP source prefix\n"
14579 "Access list name\n")
37a87b8f 14580{
585f1adc
IR
14581 int idx_number = 1;
14582 int idx_ipv4_prefixlen = 2;
14583 int idx_word = 3;
14584 bgp_distance_set(vty, argv[idx_number]->arg,
14585 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14586 return CMD_SUCCESS;
14587}
718e3744 14588
585f1adc
IR
14589DEFUN (no_bgp_distance_source_access_list,
14590 no_bgp_distance_source_access_list_cmd,
14591 "no distance (1-255) A.B.C.D/M WORD",
14592 NO_STR
14593 "Define an administrative distance\n"
14594 "Administrative distance\n"
14595 "IP source prefix\n"
14596 "Access list name\n")
14597{
14598 int idx_number = 2;
14599 int idx_ipv4_prefixlen = 3;
14600 int idx_word = 4;
14601 bgp_distance_unset(vty, argv[idx_number]->arg,
14602 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14603 return CMD_SUCCESS;
14604}
37a87b8f 14605
585f1adc
IR
14606DEFUN (ipv6_bgp_distance_source,
14607 ipv6_bgp_distance_source_cmd,
14608 "distance (1-255) X:X::X:X/M",
14609 "Define an administrative distance\n"
14610 "Administrative distance\n"
14611 "IP source prefix\n")
14612{
14613 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14614 return CMD_SUCCESS;
14615}
7ebe9748 14616
585f1adc
IR
14617DEFUN (no_ipv6_bgp_distance_source,
14618 no_ipv6_bgp_distance_source_cmd,
14619 "no distance (1-255) X:X::X:X/M",
14620 NO_STR
14621 "Define an administrative distance\n"
14622 "Administrative distance\n"
14623 "IP source prefix\n")
14624{
14625 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14626 return CMD_SUCCESS;
14627}
37a87b8f 14628
585f1adc
IR
14629DEFUN (ipv6_bgp_distance_source_access_list,
14630 ipv6_bgp_distance_source_access_list_cmd,
14631 "distance (1-255) X:X::X:X/M WORD",
14632 "Define an administrative distance\n"
14633 "Administrative distance\n"
14634 "IP source prefix\n"
14635 "Access list name\n")
14636{
14637 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14638 return CMD_SUCCESS;
718e3744 14639}
14640
585f1adc
IR
14641DEFUN (no_ipv6_bgp_distance_source_access_list,
14642 no_ipv6_bgp_distance_source_access_list_cmd,
14643 "no distance (1-255) X:X::X:X/M WORD",
14644 NO_STR
14645 "Define an administrative distance\n"
14646 "Administrative distance\n"
14647 "IP source prefix\n"
14648 "Access list name\n")
718e3744 14649{
585f1adc
IR
14650 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14651 return CMD_SUCCESS;
14652}
37a87b8f 14653
585f1adc
IR
14654DEFUN (bgp_damp_set,
14655 bgp_damp_set_cmd,
a30fec23 14656 "bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14657 "BGP Specific commands\n"
14658 "Enable route-flap dampening\n"
14659 "Half-life time for the penalty\n"
14660 "Value to start reusing a route\n"
14661 "Value to start suppressing a route\n"
14662 "Maximum duration to suppress a stable route\n")
14663{
14664 VTY_DECLVAR_CONTEXT(bgp, bgp);
14665 int idx_half_life = 2;
14666 int idx_reuse = 3;
14667 int idx_suppress = 4;
14668 int idx_max_suppress = 5;
37a87b8f
CS
14669 int half = DEFAULT_HALF_LIFE * 60;
14670 int reuse = DEFAULT_REUSE;
14671 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14672 int max = 4 * half;
14673
14674 if (argc == 6) {
14675 half = atoi(argv[idx_half_life]->arg) * 60;
14676 reuse = atoi(argv[idx_reuse]->arg);
14677 suppress = atoi(argv[idx_suppress]->arg);
14678 max = atoi(argv[idx_max_suppress]->arg) * 60;
14679 } else if (argc == 3) {
14680 half = atoi(argv[idx_half_life]->arg) * 60;
14681 max = 4 * half;
14682 }
14683
14684 /*
14685 * These can't be 0 but our SA doesn't understand the
14686 * way our cli is constructed
14687 */
14688 assert(reuse);
14689 assert(half);
14690 if (suppress < reuse) {
14691 vty_out(vty,
14692 "Suppress value cannot be less than reuse value \n");
14693 return 0;
14694 }
14695
14696 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14697 reuse, suppress, max);
14698}
14699
14700DEFUN (bgp_damp_unset,
14701 bgp_damp_unset_cmd,
a30fec23 14702 "no bgp dampening [(1-45) [(1-20000) (1-50000) (1-255)]]",
585f1adc
IR
14703 NO_STR
14704 "BGP Specific commands\n"
14705 "Enable route-flap dampening\n"
14706 "Half-life time for the penalty\n"
14707 "Value to start reusing a route\n"
14708 "Value to start suppressing a route\n"
14709 "Maximum duration to suppress a stable route\n")
14710{
14711 VTY_DECLVAR_CONTEXT(bgp, bgp);
14712 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14713}
14714
718e3744 14715/* Display specified route of BGP table. */
d62a17ae 14716static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14717 const char *ip_str, afi_t afi, safi_t safi,
14718 struct prefix_rd *prd, int prefix_check)
14719{
14720 int ret;
14721 struct prefix match;
9bcb3eef
DS
14722 struct bgp_dest *dest;
14723 struct bgp_dest *rm;
40381db7
DS
14724 struct bgp_path_info *pi;
14725 struct bgp_path_info *pi_temp;
d62a17ae 14726 struct bgp *bgp;
14727 struct bgp_table *table;
14728
14729 /* BGP structure lookup. */
14730 if (view_name) {
14731 bgp = bgp_lookup_by_name(view_name);
14732 if (bgp == NULL) {
14733 vty_out(vty, "%% Can't find BGP instance %s\n",
14734 view_name);
14735 return CMD_WARNING;
14736 }
14737 } else {
14738 bgp = bgp_get_default();
14739 if (bgp == NULL) {
14740 vty_out(vty, "%% No BGP process is configured\n");
14741 return CMD_WARNING;
14742 }
718e3744 14743 }
718e3744 14744
d62a17ae 14745 /* Check IP address argument. */
14746 ret = str2prefix(ip_str, &match);
14747 if (!ret) {
14748 vty_out(vty, "%% address is malformed\n");
14749 return CMD_WARNING;
14750 }
718e3744 14751
d62a17ae 14752 match.family = afi2family(afi);
14753
14754 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14755 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14756 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14757 dest = bgp_route_next(dest)) {
14758 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14759
9bcb3eef 14760 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14761 continue;
9bcb3eef 14762 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14763 if (!table)
ea47320b 14764 continue;
4953391b
DA
14765 rm = bgp_node_match(table, &match);
14766 if (rm == NULL)
ea47320b 14767 continue;
d62a17ae 14768
9bcb3eef 14769 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14770
ea47320b 14771 if (!prefix_check
b54892e0 14772 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14773 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14774 while (pi) {
14775 if (pi->extra && pi->extra->damp_info) {
14776 pi_temp = pi->next;
ea47320b 14777 bgp_damp_info_free(
19971c9a 14778 pi->extra->damp_info,
5c8846f6 14779 1, afi, safi);
40381db7 14780 pi = pi_temp;
ea47320b 14781 } else
40381db7 14782 pi = pi->next;
d62a17ae 14783 }
ea47320b
DL
14784 }
14785
9bcb3eef 14786 bgp_dest_unlock_node(rm);
d62a17ae 14787 }
14788 } else {
4953391b
DA
14789 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14790 if (dest != NULL) {
9bcb3eef 14791 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14792
d62a17ae 14793 if (!prefix_check
9bcb3eef
DS
14794 || dest_p->prefixlen == match.prefixlen) {
14795 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14796 while (pi) {
14797 if (pi->extra && pi->extra->damp_info) {
14798 pi_temp = pi->next;
d62a17ae 14799 bgp_damp_info_free(
19971c9a 14800 pi->extra->damp_info,
5c8846f6 14801 1, afi, safi);
40381db7 14802 pi = pi_temp;
d62a17ae 14803 } else
40381db7 14804 pi = pi->next;
d62a17ae 14805 }
14806 }
14807
9bcb3eef 14808 bgp_dest_unlock_node(dest);
d62a17ae 14809 }
14810 }
718e3744 14811
d62a17ae 14812 return CMD_SUCCESS;
718e3744 14813}
14814
14815DEFUN (clear_ip_bgp_dampening,
14816 clear_ip_bgp_dampening_cmd,
14817 "clear ip bgp dampening",
14818 CLEAR_STR
14819 IP_STR
14820 BGP_STR
14821 "Clear route flap dampening information\n")
14822{
b4f7f45b 14823 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14824 return CMD_SUCCESS;
718e3744 14825}
14826
14827DEFUN (clear_ip_bgp_dampening_prefix,
14828 clear_ip_bgp_dampening_prefix_cmd,
14829 "clear ip bgp dampening A.B.C.D/M",
14830 CLEAR_STR
14831 IP_STR
14832 BGP_STR
14833 "Clear route flap dampening information\n"
0c7b1b01 14834 "IPv4 prefix\n")
718e3744 14835{
d62a17ae 14836 int idx_ipv4_prefixlen = 4;
14837 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14838 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14839}
14840
14841DEFUN (clear_ip_bgp_dampening_address,
14842 clear_ip_bgp_dampening_address_cmd,
14843 "clear ip bgp dampening A.B.C.D",
14844 CLEAR_STR
14845 IP_STR
14846 BGP_STR
14847 "Clear route flap dampening information\n"
14848 "Network to clear damping information\n")
14849{
d62a17ae 14850 int idx_ipv4 = 4;
14851 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14852 SAFI_UNICAST, NULL, 0);
718e3744 14853}
14854
14855DEFUN (clear_ip_bgp_dampening_address_mask,
14856 clear_ip_bgp_dampening_address_mask_cmd,
14857 "clear ip bgp dampening A.B.C.D A.B.C.D",
14858 CLEAR_STR
14859 IP_STR
14860 BGP_STR
14861 "Clear route flap dampening information\n"
14862 "Network to clear damping information\n"
14863 "Network mask\n")
14864{
d62a17ae 14865 int idx_ipv4 = 4;
14866 int idx_ipv4_2 = 5;
14867 int ret;
14868 char prefix_str[BUFSIZ];
718e3744 14869
d62a17ae 14870 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14871 prefix_str, sizeof(prefix_str));
d62a17ae 14872 if (!ret) {
14873 vty_out(vty, "%% Inconsistent address and mask\n");
14874 return CMD_WARNING;
14875 }
718e3744 14876
d62a17ae 14877 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14878 NULL, 0);
718e3744 14879}
6b0655a2 14880
e3b78da8 14881static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14882{
14883 struct vty *vty = arg;
e3b78da8 14884 struct peer *peer = bucket->data;
825d9834
DS
14885 char buf[SU_ADDRSTRLEN];
14886
14887 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14888 sockunion2str(&peer->su, buf, sizeof(buf)));
14889}
14890
2a0e69ae
DS
14891DEFUN (show_bgp_listeners,
14892 show_bgp_listeners_cmd,
14893 "show bgp listeners",
14894 SHOW_STR
14895 BGP_STR
14896 "Display Listen Sockets and who created them\n")
14897{
14898 bgp_dump_listener_info(vty);
14899
14900 return CMD_SUCCESS;
14901}
14902
825d9834
DS
14903DEFUN (show_bgp_peerhash,
14904 show_bgp_peerhash_cmd,
14905 "show bgp peerhash",
14906 SHOW_STR
14907 BGP_STR
14908 "Display information about the BGP peerhash\n")
14909{
14910 struct list *instances = bm->bgp;
14911 struct listnode *node;
14912 struct bgp *bgp;
14913
14914 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14915 vty_out(vty, "BGP: %s\n", bgp->name);
14916 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14917 vty);
14918 }
14919
14920 return CMD_SUCCESS;
14921}
14922
587ff0fd 14923/* also used for encap safi */
2b791107
DL
14924static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14925 afi_t afi, safi_t safi)
d62a17ae 14926{
9bcb3eef
DS
14927 struct bgp_dest *pdest;
14928 struct bgp_dest *dest;
d62a17ae 14929 struct bgp_table *table;
b54892e0
DS
14930 const struct prefix *p;
14931 const struct prefix_rd *prd;
d62a17ae 14932 struct bgp_static *bgp_static;
14933 mpls_label_t label;
d62a17ae 14934 char rdbuf[RD_ADDRSTRLEN];
14935
14936 /* Network configuration. */
9bcb3eef
DS
14937 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14938 pdest = bgp_route_next(pdest)) {
14939 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14940 if (!table)
ea47320b 14941 continue;
d62a17ae 14942
9bcb3eef
DS
14943 for (dest = bgp_table_top(table); dest;
14944 dest = bgp_route_next(dest)) {
14945 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14946 if (bgp_static == NULL)
ea47320b 14947 continue;
d62a17ae 14948
9bcb3eef
DS
14949 p = bgp_dest_get_prefix(dest);
14950 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14951 pdest);
d62a17ae 14952
ea47320b 14953 /* "network" configuration display. */
06b9f471 14954 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14955 label = decode_label(&bgp_static->label);
14956
8228a9a7 14957 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14958 if (safi == SAFI_MPLS_VPN)
14959 vty_out(vty, " label %u", label);
14960
14961 if (bgp_static->rmap.name)
14962 vty_out(vty, " route-map %s",
14963 bgp_static->rmap.name);
e2a86ad9
DS
14964
14965 if (bgp_static->backdoor)
14966 vty_out(vty, " backdoor");
14967
ea47320b
DL
14968 vty_out(vty, "\n");
14969 }
14970 }
d62a17ae 14971}
14972
2b791107
DL
14973static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14974 afi_t afi, safi_t safi)
d62a17ae 14975{
9bcb3eef
DS
14976 struct bgp_dest *pdest;
14977 struct bgp_dest *dest;
d62a17ae 14978 struct bgp_table *table;
b54892e0
DS
14979 const struct prefix *p;
14980 const struct prefix_rd *prd;
d62a17ae 14981 struct bgp_static *bgp_static;
ff44f570 14982 char buf[PREFIX_STRLEN * 2];
d62a17ae 14983 char buf2[SU_ADDRSTRLEN];
14984 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14985 char esi_buf[ESI_BYTES];
d62a17ae 14986
14987 /* Network configuration. */
9bcb3eef
DS
14988 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14989 pdest = bgp_route_next(pdest)) {
14990 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14991 if (!table)
ea47320b 14992 continue;
d62a17ae 14993
9bcb3eef
DS
14994 for (dest = bgp_table_top(table); dest;
14995 dest = bgp_route_next(dest)) {
14996 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14997 if (bgp_static == NULL)
ea47320b 14998 continue;
d62a17ae 14999
ea47320b 15000 char *macrouter = NULL;
d62a17ae 15001
ea47320b
DL
15002 if (bgp_static->router_mac)
15003 macrouter = prefix_mac2str(
15004 bgp_static->router_mac, NULL, 0);
15005 if (bgp_static->eth_s_id)
0a50c248
AK
15006 esi_to_str(bgp_static->eth_s_id,
15007 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15008 p = bgp_dest_get_prefix(dest);
15009 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15010
ea47320b 15011 /* "network" configuration display. */
06b9f471 15012 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15013 if (p->u.prefix_evpn.route_type == 5) {
15014 char local_buf[PREFIX_STRLEN];
3714a385 15015 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15016 struct prefix_evpn *)p)
15017 ? AF_INET
15018 : AF_INET6;
3714a385 15019 inet_ntop(family,
15020 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15021 local_buf, PREFIX_STRLEN);
772270f3
QY
15022 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15023 p->u.prefix_evpn.prefix_addr
15024 .ip_prefix_length);
197cb530
PG
15025 } else {
15026 prefix2str(p, buf, sizeof(buf));
15027 }
ea47320b 15028
a4d82a8a
PZ
15029 if (bgp_static->gatewayIp.family == AF_INET
15030 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15031 inet_ntop(bgp_static->gatewayIp.family,
15032 &bgp_static->gatewayIp.u.prefix, buf2,
15033 sizeof(buf2));
ea47320b 15034 vty_out(vty,
7bcc8dac 15035 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15036 buf, rdbuf,
15037 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15038 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15039 macrouter);
15040
0a22ddfb 15041 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15042 }
15043 }
3da6fcd5
PG
15044}
15045
718e3744 15046/* Configuration of static route announcement and aggregate
15047 information. */
2b791107
DL
15048void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15049 safi_t safi)
d62a17ae 15050{
9bcb3eef 15051 struct bgp_dest *dest;
b54892e0 15052 const struct prefix *p;
d62a17ae 15053 struct bgp_static *bgp_static;
15054 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15055
2b791107
DL
15056 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15057 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15058 return;
15059 }
d62a17ae 15060
2b791107
DL
15061 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15062 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15063 return;
15064 }
d62a17ae 15065
15066 /* Network configuration. */
9bcb3eef
DS
15067 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15068 dest = bgp_route_next(dest)) {
15069 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15070 if (bgp_static == NULL)
ea47320b 15071 continue;
d62a17ae 15072
9bcb3eef 15073 p = bgp_dest_get_prefix(dest);
d62a17ae 15074
8228a9a7 15075 vty_out(vty, " network %pFX", p);
d62a17ae 15076
ea47320b
DL
15077 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15078 vty_out(vty, " label-index %u",
15079 bgp_static->label_index);
d62a17ae 15080
ea47320b
DL
15081 if (bgp_static->rmap.name)
15082 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15083
15084 if (bgp_static->backdoor)
15085 vty_out(vty, " backdoor");
718e3744 15086
ea47320b
DL
15087 vty_out(vty, "\n");
15088 }
15089
d62a17ae 15090 /* Aggregate-address configuration. */
9bcb3eef
DS
15091 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15092 dest = bgp_route_next(dest)) {
15093 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15094 if (bgp_aggregate == NULL)
ea47320b 15095 continue;
d62a17ae 15096
9bcb3eef 15097 p = bgp_dest_get_prefix(dest);
d62a17ae 15098
8228a9a7 15099 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15100
ea47320b
DL
15101 if (bgp_aggregate->as_set)
15102 vty_out(vty, " as-set");
d62a17ae 15103
ea47320b
DL
15104 if (bgp_aggregate->summary_only)
15105 vty_out(vty, " summary-only");
718e3744 15106
20894f50
DA
15107 if (bgp_aggregate->rmap.name)
15108 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15109
229757f1
DA
15110 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15111 vty_out(vty, " origin %s",
15112 bgp_origin2str(bgp_aggregate->origin));
15113
6aabb15d
RZ
15114 if (bgp_aggregate->match_med)
15115 vty_out(vty, " matching-MED-only");
15116
365ab2e7
RZ
15117 if (bgp_aggregate->suppress_map_name)
15118 vty_out(vty, " suppress-map %s",
15119 bgp_aggregate->suppress_map_name);
15120
ea47320b
DL
15121 vty_out(vty, "\n");
15122 }
d62a17ae 15123}
734b349e 15124
2b791107 15125void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15126 safi_t safi)
d62a17ae 15127{
9bcb3eef 15128 struct bgp_dest *dest;
d62a17ae 15129 struct bgp_distance *bdistance;
15130
15131 /* Distance configuration. */
15132 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15133 && bgp->distance_local[afi][safi]
15134 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15135 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15136 || bgp->distance_local[afi][safi]
15137 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15138 vty_out(vty, " distance bgp %d %d %d\n",
15139 bgp->distance_ebgp[afi][safi],
15140 bgp->distance_ibgp[afi][safi],
15141 bgp->distance_local[afi][safi]);
15142 }
734b349e 15143
9bcb3eef
DS
15144 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15145 dest = bgp_route_next(dest)) {
15146 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15147 if (bdistance != NULL)
56ca3b5b 15148 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15149 bdistance->distance, dest,
d62a17ae 15150 bdistance->access_list ? bdistance->access_list
15151 : "");
ca2e160d 15152 }
718e3744 15153}
15154
15155/* Allocate routing table structure and install commands. */
d62a17ae 15156void bgp_route_init(void)
15157{
15158 afi_t afi;
15159 safi_t safi;
15160
15161 /* Init BGP distance table. */
05c7a1cc 15162 FOREACH_AFI_SAFI (afi, safi)
960035b2 15163 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15164
15165 /* IPv4 BGP commands. */
15166 install_element(BGP_NODE, &bgp_table_map_cmd);
15167 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15168 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15169
554b3b10 15170 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15171
15172 /* IPv4 unicast configuration. */
15173 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15174 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15175 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15176
554b3b10 15177 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15178
15179 /* IPv4 multicast configuration. */
15180 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15181 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15182 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15183 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15184
15185 /* IPv4 labeled-unicast configuration. */
fb985e0c 15186 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15187 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15188
d62a17ae 15189 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
893cccd0 15190 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15191 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
fe0f234d
RW
15192 install_element(VIEW_NODE, &show_ip_bgp_dampening_params_cmd);
15193 install_element(VIEW_NODE, &show_ip_bgp_cmd);
d62a17ae 15194 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15195 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15196 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15197
15198 install_element(VIEW_NODE,
15199 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15200 install_element(VIEW_NODE,
15201 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15202 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15203 install_element(VIEW_NODE,
15204 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15205#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15206 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15207#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15208 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15209 install_element(VIEW_NODE,
44c69747 15210 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15211
d62a17ae 15212 /* BGP dampening clear commands */
15213 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15214 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15215
d62a17ae 15216 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15217 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15218
15219 /* prefix count */
15220 install_element(ENABLE_NODE,
15221 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15222#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15223 install_element(ENABLE_NODE,
15224 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15225#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15226
d62a17ae 15227 /* New config IPv6 BGP commands. */
15228 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15229 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15230 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15231
554b3b10 15232 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15233
15234 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15235
fb985e0c
DA
15236 /* IPv6 labeled unicast address family. */
15237 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15238 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15239
d62a17ae 15240 install_element(BGP_NODE, &bgp_distance_cmd);
15241 install_element(BGP_NODE, &no_bgp_distance_cmd);
15242 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15243 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15244 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15245 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15246 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15247 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15248 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15249 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15250 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15251 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15252 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15253 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15254 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15255 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15256 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15257 install_element(BGP_IPV4M_NODE,
15258 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15259 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15260 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15261 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15262 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15263 install_element(BGP_IPV6_NODE,
15264 &ipv6_bgp_distance_source_access_list_cmd);
15265 install_element(BGP_IPV6_NODE,
15266 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15267 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15268 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15269 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15270 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15271 install_element(BGP_IPV6M_NODE,
15272 &ipv6_bgp_distance_source_access_list_cmd);
15273 install_element(BGP_IPV6M_NODE,
15274 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15275
ef5f4b23 15276 /* BGP dampening */
585f1adc
IR
15277 install_element(BGP_NODE, &bgp_damp_set_cmd);
15278 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15279 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15280 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15281 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15282 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15283 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15284 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15285 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15286 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15287 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15288 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15289 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15290 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15291
15292 /* Large Communities */
15293 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15294 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15295
15296 /* show bgp ipv4 flowspec detailed */
15297 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15298
2a0e69ae 15299 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15300 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15301}
15302
15303void bgp_route_finish(void)
15304{
15305 afi_t afi;
15306 safi_t safi;
15307
05c7a1cc
QY
15308 FOREACH_AFI_SAFI (afi, safi) {
15309 bgp_table_unlock(bgp_distance_table[afi][safi]);
15310 bgp_distance_table[afi][safi] = NULL;
15311 }
228da428 15312}