]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #7828 from mobash-rasool/pim-fixes-3
[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"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
6401252f 73#include "bgpd/bgp_trace.h"
718e3744 74
49e5a4a0 75#ifdef ENABLE_BGP_VNC
f8b6f499
LB
76#include "bgpd/rfapi/rfapi_backend.h"
77#include "bgpd/rfapi/vnc_import_bgp.h"
78#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 79#endif
aee875b5
PG
80#include "bgpd/bgp_encap_types.h"
81#include "bgpd/bgp_encap_tlv.h"
684a7227 82#include "bgpd/bgp_evpn.h"
0a50c248 83#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 84#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 85#include "bgpd/bgp_flowspec.h"
98a9dbc7 86#include "bgpd/bgp_flowspec_util.h"
45918cfb 87#include "bgpd/bgp_pbr.h"
37a87b8f
CS
88#include "northbound.h"
89#include "northbound_cli.h"
90#include "bgpd/bgp_nb.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
718e3744 96/* Extern from bgp_dump.c */
dde72586
SH
97extern const char *bgp_origin_str[];
98extern const char *bgp_origin_long_str[];
3742de8d 99
b7d08f5a 100/* PMSI strings. */
101#define PMSI_TNLTYPE_STR_NO_INFO "No info"
102#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
103static const struct message bgp_pmsi_tnltype_str[] = {
104 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
105 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
106 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
107 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
108 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
109 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
110 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
111 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 112 {0}
113};
b7d08f5a 114
9df8b37c
PZ
115#define VRFID_NONE_STR "-"
116
4a11bf2c 117DEFINE_HOOK(bgp_process,
9bcb3eef
DS
118 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
119 struct peer *peer, bool withdraw),
120 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c 121
4056a5f6
RZ
122/** Test if path is suppressed. */
123static bool bgp_path_suppressed(struct bgp_path_info *pi)
124{
125 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
126 return false;
127
128 return listcount(pi->extra->aggr_suppressors) > 0;
129}
4a11bf2c 130
9bcb3eef 131struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 132 safi_t safi, const struct prefix *p,
d62a17ae 133 struct prefix_rd *prd)
134{
9bcb3eef
DS
135 struct bgp_dest *dest;
136 struct bgp_dest *pdest = NULL;
d62a17ae 137
138 assert(table);
d62a17ae 139
140 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
141 || (safi == SAFI_EVPN)) {
9bcb3eef 142 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 143
9bcb3eef
DS
144 if (!bgp_dest_has_bgp_path_info_data(pdest))
145 bgp_dest_set_bgp_table_info(
146 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 147 else
9bcb3eef
DS
148 bgp_dest_unlock_node(pdest);
149 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 150 }
718e3744 151
9bcb3eef 152 dest = bgp_node_get(table, p);
718e3744 153
d62a17ae 154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN))
9bcb3eef 156 dest->pdest = pdest;
718e3744 157
9bcb3eef 158 return dest;
718e3744 159}
6b0655a2 160
9bcb3eef 161struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 162 safi_t safi, const struct prefix *p,
d62a17ae 163 struct prefix_rd *prd)
128ea8ab 164{
9bcb3eef
DS
165 struct bgp_dest *dest;
166 struct bgp_dest *pdest = NULL;
128ea8ab 167
d62a17ae 168 if (!table)
169 return NULL;
128ea8ab 170
d62a17ae 171 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
172 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
173 pdest = bgp_node_lookup(table, (struct prefix *)prd);
174 if (!pdest)
d62a17ae 175 return NULL;
128ea8ab 176
9bcb3eef
DS
177 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
178 bgp_dest_unlock_node(pdest);
d62a17ae 179 return NULL;
180 }
128ea8ab 181
9bcb3eef 182 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 183 }
128ea8ab 184
9bcb3eef 185 dest = bgp_node_lookup(table, p);
128ea8ab 186
9bcb3eef 187 return dest;
128ea8ab 188}
189
18ee8310
DS
190/* Allocate bgp_path_info_extra */
191static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 192{
4b7e6066
DS
193 struct bgp_path_info_extra *new;
194 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
195 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
196 new->label[0] = MPLS_INVALID_LABEL;
197 new->num_labels = 0;
3e3708cb
PG
198 new->bgp_fs_pbr = NULL;
199 new->bgp_fs_iprule = NULL;
d62a17ae 200 return new;
fb982c25
PJ
201}
202
a2e219fe 203void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 204{
4b7e6066 205 struct bgp_path_info_extra *e;
d62a17ae 206
c93a3b77
DS
207 if (!extra || !*extra)
208 return;
d62a17ae 209
c93a3b77
DS
210 e = *extra;
211 if (e->damp_info)
a935f597
DA
212 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
213 e->damp_info->safi);
d62a17ae 214
c93a3b77
DS
215 e->damp_info = NULL;
216 if (e->parent) {
40381db7 217 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 218
40381db7 219 if (bpi->net) {
0e70e6c8
DL
220 /* FIXME: since multiple e may have the same e->parent
221 * and e->parent->net is holding a refcount for each
222 * of them, we need to do some fudging here.
223 *
40381db7
DS
224 * WARNING: if bpi->net->lock drops to 0, bpi may be
225 * freed as well (because bpi->net was holding the
226 * last reference to bpi) => write after free!
0e70e6c8
DL
227 */
228 unsigned refcount;
229
40381db7 230 bpi = bgp_path_info_lock(bpi);
c10e14e9 231 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 232 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 233 if (!refcount)
40381db7
DS
234 bpi->net = NULL;
235 bgp_path_info_unlock(bpi);
0e70e6c8 236 }
18ee8310 237 bgp_path_info_unlock(e->parent);
c93a3b77 238 e->parent = NULL;
d62a17ae 239 }
c93a3b77
DS
240
241 if (e->bgp_orig)
242 bgp_unlock(e->bgp_orig);
c26edcda 243
ff3bf9a4
DS
244 if (e->aggr_suppressors)
245 list_delete(&e->aggr_suppressors);
246
26c03e43
AK
247 if (e->es_info)
248 bgp_evpn_path_es_info_free(e->es_info);
249
ce3c0614
PG
250 if ((*extra)->bgp_fs_iprule)
251 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 252 if ((*extra)->bgp_fs_pbr)
6a154c88 253 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 254 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
255}
256
18ee8310
DS
257/* Get bgp_path_info extra information for the given bgp_path_info, lazy
258 * allocated if required.
fb982c25 259 */
40381db7 260struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 261{
40381db7
DS
262 if (!pi->extra)
263 pi->extra = bgp_path_info_extra_new();
264 return pi->extra;
fb982c25
PJ
265}
266
718e3744 267/* Free bgp route information. */
9b6d8fcf 268static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 269{
05864da7 270 bgp_attr_unintern(&path->attr);
fb018d25 271
9b6d8fcf
DS
272 bgp_unlink_nexthop(path);
273 bgp_path_info_extra_free(&path->extra);
274 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
275 if (path->net)
276 bgp_addpath_free_info_data(&path->tx_addpath,
277 &path->net->tx_addpath);
718e3744 278
9b6d8fcf 279 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 280
9b6d8fcf 281 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 282}
283
9b6d8fcf 284struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 285{
9b6d8fcf
DS
286 path->lock++;
287 return path;
200df115 288}
289
9b6d8fcf 290struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 291{
9b6d8fcf
DS
292 assert(path && path->lock > 0);
293 path->lock--;
d62a17ae 294
9b6d8fcf 295 if (path->lock == 0) {
200df115 296#if 0
297 zlog_debug ("%s: unlocked and freeing", __func__);
298 zlog_backtrace (LOG_DEBUG);
299#endif
9b6d8fcf 300 bgp_path_info_free(path);
d62a17ae 301 return NULL;
302 }
200df115 303
304#if 0
9b6d8fcf 305 if (path->lock == 1)
200df115 306 {
307 zlog_debug ("%s: unlocked to 1", __func__);
308 zlog_backtrace (LOG_DEBUG);
309 }
310#endif
d62a17ae 311
9b6d8fcf 312 return path;
200df115 313}
314
f009ff26 315/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 316static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 317{
318 struct peer *peer;
319 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 320 bool set_flag = false;
f009ff26 321 struct bgp *bgp = NULL;
322 struct bgp_table *table = NULL;
323 afi_t afi = 0;
324 safi_t safi = 0;
f009ff26 325
326 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
327 * then the route selection is deferred
328 */
9bcb3eef 329 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 330 return 0;
331
9bcb3eef 332 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 333 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 334 zlog_debug(
56ca3b5b
DL
335 "Route %pBD is in workqueue and being processed, not deferred.",
336 dest);
b54892e0 337
5f9c1aa2 338 return 0;
339 }
340
9bcb3eef 341 table = bgp_dest_table(dest);
f009ff26 342 if (table) {
343 bgp = table->bgp;
344 afi = table->afi;
345 safi = table->safi;
346 }
347
9bcb3eef 348 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 349 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
350 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
351 continue;
352
353 /* Route selection is deferred if there is a stale path which
354 * which indicates peer is in restart mode
355 */
36235319
QY
356 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
357 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 358 set_flag = true;
f009ff26 359 } else {
360 /* If the peer is graceful restart capable and peer is
361 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
362 */
363 peer = old_pi->peer;
36235319
QY
364 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
365 && BGP_PEER_RESTARTING_MODE(peer)
366 && (old_pi
367 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 368 set_flag = true;
f009ff26 369 }
370 }
371 if (set_flag)
372 break;
373 }
374
375 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
376 * is active
377 */
2ba1fe69 378 if (set_flag && table) {
f009ff26 379 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
380 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
381 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 382 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 383 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
384 zlog_debug("DEFER route %pBD, dest %p", dest,
385 dest);
f009ff26 386 return 0;
387 }
388 }
389 return -1;
390}
391
9bcb3eef 392void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 393{
4b7e6066 394 struct bgp_path_info *top;
718e3744 395
9bcb3eef 396 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 397
6f94b685 398 pi->next = top;
40381db7 399 pi->prev = NULL;
d62a17ae 400 if (top)
40381db7 401 top->prev = pi;
9bcb3eef 402 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 403
40381db7 404 bgp_path_info_lock(pi);
9bcb3eef 405 bgp_dest_lock_node(dest);
40381db7 406 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 407 bgp_dest_set_defer_flag(dest, false);
718e3744 408}
409
d62a17ae 410/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 411 completion callback *only* */
9bcb3eef 412void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 413{
40381db7
DS
414 if (pi->next)
415 pi->next->prev = pi->prev;
416 if (pi->prev)
417 pi->prev->next = pi->next;
d62a17ae 418 else
9bcb3eef 419 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 420
40381db7
DS
421 bgp_path_info_mpath_dequeue(pi);
422 bgp_path_info_unlock(pi);
9bcb3eef 423 bgp_dest_unlock_node(dest);
718e3744 424}
425
9bcb3eef 426void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 427{
9bcb3eef 428 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 429 /* set of previous already took care of pcount */
40381db7 430 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 431}
432
18ee8310 433/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
434 called when a route is deleted and then quickly re-added before the
435 deletion has been processed */
9bcb3eef 436void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 437{
9bcb3eef 438 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 439 /* unset of previous already took care of pcount */
40381db7 440 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
441}
442
d62a17ae 443/* Adjust pcount as required */
9bcb3eef 444static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 445{
d62a17ae 446 struct bgp_table *table;
67174041 447
9bcb3eef 448 assert(dest && bgp_dest_table(dest));
40381db7 449 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 450
9bcb3eef 451 table = bgp_dest_table(dest);
67174041 452
40381db7 453 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 454 return;
455
40381db7
DS
456 if (!BGP_PATH_COUNTABLE(pi)
457 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 458
40381db7 459 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 460
461 /* slight hack, but more robust against errors. */
40381db7
DS
462 if (pi->peer->pcount[table->afi][table->safi])
463 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 464 else
450971aa 465 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 466 "Asked to decrement 0 prefix count for peer");
40381db7
DS
467 } else if (BGP_PATH_COUNTABLE(pi)
468 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
469 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
470 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 471 }
1a392d46
PJ
472}
473
40381db7
DS
474static int bgp_label_index_differs(struct bgp_path_info *pi1,
475 struct bgp_path_info *pi2)
28d58fd7 476{
40381db7 477 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 478}
1a392d46 479
18ee8310 480/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
481 * This is here primarily to keep prefix-count in check.
482 */
9bcb3eef 483void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 484 uint32_t flag)
1a392d46 485{
40381db7 486 SET_FLAG(pi->flags, flag);
d62a17ae 487
488 /* early bath if we know it's not a flag that changes countability state
489 */
490 if (!CHECK_FLAG(flag,
1defdda8 491 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 492 return;
493
9bcb3eef 494 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
495}
496
9bcb3eef 497void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 498 uint32_t flag)
1a392d46 499{
40381db7 500 UNSET_FLAG(pi->flags, flag);
d62a17ae 501
502 /* early bath if we know it's not a flag that changes countability state
503 */
504 if (!CHECK_FLAG(flag,
1defdda8 505 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 506 return;
507
9bcb3eef 508 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
509}
510
718e3744 511/* Get MED value. If MED value is missing and "bgp bestpath
512 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 513static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 514{
515 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
516 return attr->med;
517 else {
892fedb6 518 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 519 return BGP_MED_MAX;
520 else
521 return 0;
522 }
718e3744 523}
524
40381db7 525void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 526{
40381db7
DS
527 if (pi->addpath_rx_id)
528 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
529 pi->addpath_rx_id);
d62a17ae 530 else
40381db7 531 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 532}
9fbdd100 533
d62a17ae 534/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
535 */
18ee8310
DS
536static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
537 struct bgp_path_info *exist, int *paths_eq,
538 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
539 char *pfx_buf, afi_t afi, safi_t safi,
540 enum bgp_path_selection_reason *reason)
d62a17ae 541{
542 struct attr *newattr, *existattr;
543 bgp_peer_sort_t new_sort;
544 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
545 uint32_t new_pref;
546 uint32_t exist_pref;
547 uint32_t new_med;
548 uint32_t exist_med;
549 uint32_t new_weight;
550 uint32_t exist_weight;
d62a17ae 551 uint32_t newm, existm;
552 struct in_addr new_id;
553 struct in_addr exist_id;
554 int new_cluster;
555 int exist_cluster;
556 int internal_as_route;
557 int confed_as_route;
04d14c8b 558 int ret = 0;
d62a17ae 559 char new_buf[PATH_ADDPATH_STR_BUFFER];
560 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
561 uint32_t new_mm_seq;
562 uint32_t exist_mm_seq;
6d8c603a 563 int nh_cmp;
d071f237
AK
564 esi_t *exist_esi;
565 esi_t *new_esi;
566 bool same_esi;
567 bool old_proxy;
568 bool new_proxy;
33c6e933 569 bool new_origin, exist_origin;
d62a17ae 570
571 *paths_eq = 0;
572
573 /* 0. Null check. */
574 if (new == NULL) {
fdf81fa0 575 *reason = bgp_path_selection_none;
d62a17ae 576 if (debug)
577 zlog_debug("%s: new is NULL", pfx_buf);
578 return 0;
579 }
2ec1e66f 580
d62a17ae 581 if (debug)
18ee8310 582 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 583
d62a17ae 584 if (exist == NULL) {
fdf81fa0 585 *reason = bgp_path_selection_first;
d62a17ae 586 if (debug)
587 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
588 new_buf);
589 return 1;
590 }
2ec1e66f 591
d62a17ae 592 if (debug) {
18ee8310 593 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 594 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
595 pfx_buf, new_buf, new->flags, exist_buf,
596 exist->flags);
597 }
8ff56318 598
d62a17ae 599 newattr = new->attr;
600 existattr = exist->attr;
601
602 /* For EVPN routes, we cannot just go by local vs remote, we have to
603 * look at the MAC mobility sequence number, if present.
604 */
605 if (safi == SAFI_EVPN) {
606 /* This is an error condition described in RFC 7432 Section
607 * 15.2. The RFC
608 * states that in this scenario "the PE MUST alert the operator"
609 * but it
610 * does not state what other action to take. In order to provide
611 * some
612 * consistency in this scenario we are going to prefer the path
613 * with the
614 * sticky flag.
615 */
616 if (newattr->sticky != existattr->sticky) {
617 if (!debug) {
9bcb3eef
DS
618 prefix2str(
619 bgp_dest_get_prefix(new->net), pfx_buf,
620 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
621 bgp_path_info_path_with_addpath_rx_str(new,
622 new_buf);
623 bgp_path_info_path_with_addpath_rx_str(
624 exist, exist_buf);
d62a17ae 625 }
626
627 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 628 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
629 if (debug)
630 zlog_debug(
631 "%s: %s wins over %s due to sticky MAC flag",
632 pfx_buf, new_buf, exist_buf);
d62a17ae 633 return 1;
634 }
635
636 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 637 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
638 if (debug)
639 zlog_debug(
640 "%s: %s loses to %s due to sticky MAC flag",
641 pfx_buf, new_buf, exist_buf);
d62a17ae 642 return 0;
643 }
644 }
128ea8ab 645
d071f237
AK
646 new_esi = bgp_evpn_attr_get_esi(newattr);
647 exist_esi = bgp_evpn_attr_get_esi(existattr);
648 if (bgp_evpn_is_esi_valid(new_esi) &&
649 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
650 same_esi = true;
651 } else {
652 same_esi = false;
653 }
654
655 /* If both paths have the same non-zero ES and
656 * one path is local it wins.
657 * PS: Note the local path wins even if the remote
658 * has the higher MM seq. The local path's
659 * MM seq will be fixed up to match the highest
660 * rem seq, subsequently.
661 */
662 if (same_esi) {
663 char esi_buf[ESI_STR_LEN];
664
665 if (bgp_evpn_is_path_local(bgp, new)) {
666 *reason = bgp_path_selection_evpn_local_path;
667 if (debug)
668 zlog_debug(
669 "%s: %s wins over %s as ES %s is same and local",
670 pfx_buf, new_buf, exist_buf,
671 esi_to_str(new_esi, esi_buf,
672 sizeof(esi_buf)));
673 return 1;
674 }
675 if (bgp_evpn_is_path_local(bgp, exist)) {
676 *reason = bgp_path_selection_evpn_local_path;
677 if (debug)
678 zlog_debug(
679 "%s: %s loses to %s as ES %s is same and local",
680 pfx_buf, new_buf, exist_buf,
681 esi_to_str(new_esi, esi_buf,
682 sizeof(esi_buf)));
683 return 0;
684 }
685 }
686
d62a17ae 687 new_mm_seq = mac_mobility_seqnum(newattr);
688 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 689
d62a17ae 690 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 691 *reason = bgp_path_selection_evpn_seq;
d62a17ae 692 if (debug)
693 zlog_debug(
694 "%s: %s wins over %s due to MM seq %u > %u",
695 pfx_buf, new_buf, exist_buf, new_mm_seq,
696 exist_mm_seq);
697 return 1;
698 }
8ff56318 699
d62a17ae 700 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 701 *reason = bgp_path_selection_evpn_seq;
d62a17ae 702 if (debug)
703 zlog_debug(
704 "%s: %s loses to %s due to MM seq %u < %u",
705 pfx_buf, new_buf, exist_buf, new_mm_seq,
706 exist_mm_seq);
707 return 0;
708 }
6d8c603a 709
d071f237
AK
710 /* if the sequence numbers and ESI are the same and one path
711 * is non-proxy it wins (over proxy)
712 */
713 new_proxy = bgp_evpn_attr_is_proxy(newattr);
714 old_proxy = bgp_evpn_attr_is_proxy(existattr);
715 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
716 old_proxy != new_proxy) {
717 if (!new_proxy) {
718 *reason = bgp_path_selection_evpn_non_proxy;
719 if (debug)
720 zlog_debug(
721 "%s: %s wins over %s, same seq/es and non-proxy",
722 pfx_buf, new_buf, exist_buf);
723 return 1;
724 }
725
726 *reason = bgp_path_selection_evpn_non_proxy;
727 if (debug)
728 zlog_debug(
729 "%s: %s loses to %s, same seq/es and non-proxy",
730 pfx_buf, new_buf, exist_buf);
731 return 0;
732 }
733
6d8c603a
AK
734 /*
735 * if sequence numbers are the same path with the lowest IP
736 * wins
737 */
738 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
739 if (nh_cmp < 0) {
fdf81fa0 740 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
741 if (debug)
742 zlog_debug(
23d0a753 743 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 744 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 745 &new->attr->nexthop);
6d8c603a
AK
746 return 1;
747 }
748 if (nh_cmp > 0) {
fdf81fa0 749 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
750 if (debug)
751 zlog_debug(
23d0a753 752 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 753 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 754 &new->attr->nexthop);
6d8c603a
AK
755 return 0;
756 }
d62a17ae 757 }
9fbdd100 758
d62a17ae 759 /* 1. Weight check. */
d62a17ae 760 new_weight = newattr->weight;
761 exist_weight = existattr->weight;
8ff56318 762
d62a17ae 763 if (new_weight > exist_weight) {
fdf81fa0 764 *reason = bgp_path_selection_weight;
d62a17ae 765 if (debug)
766 zlog_debug("%s: %s wins over %s due to weight %d > %d",
767 pfx_buf, new_buf, exist_buf, new_weight,
768 exist_weight);
769 return 1;
770 }
718e3744 771
d62a17ae 772 if (new_weight < exist_weight) {
fdf81fa0 773 *reason = bgp_path_selection_weight;
d62a17ae 774 if (debug)
775 zlog_debug("%s: %s loses to %s due to weight %d < %d",
776 pfx_buf, new_buf, exist_buf, new_weight,
777 exist_weight);
778 return 0;
779 }
9fbdd100 780
d62a17ae 781 /* 2. Local preference check. */
782 new_pref = exist_pref = bgp->default_local_pref;
783
784 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
785 new_pref = newattr->local_pref;
786 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
787 exist_pref = existattr->local_pref;
788
789 if (new_pref > exist_pref) {
fdf81fa0 790 *reason = bgp_path_selection_local_pref;
d62a17ae 791 if (debug)
792 zlog_debug(
793 "%s: %s wins over %s due to localpref %d > %d",
794 pfx_buf, new_buf, exist_buf, new_pref,
795 exist_pref);
796 return 1;
797 }
718e3744 798
d62a17ae 799 if (new_pref < exist_pref) {
fdf81fa0 800 *reason = bgp_path_selection_local_pref;
d62a17ae 801 if (debug)
802 zlog_debug(
803 "%s: %s loses to %s due to localpref %d < %d",
804 pfx_buf, new_buf, exist_buf, new_pref,
805 exist_pref);
806 return 0;
807 }
9fbdd100 808
d62a17ae 809 /* 3. Local route check. We prefer:
810 * - BGP_ROUTE_STATIC
811 * - BGP_ROUTE_AGGREGATE
812 * - BGP_ROUTE_REDISTRIBUTE
813 */
33c6e933
DS
814 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
815 new->sub_type == BGP_ROUTE_IMPORTED);
816 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
817 exist->sub_type == BGP_ROUTE_IMPORTED);
818
819 if (new_origin && !exist_origin) {
fdf81fa0 820 *reason = bgp_path_selection_local_route;
d62a17ae 821 if (debug)
822 zlog_debug(
823 "%s: %s wins over %s due to preferred BGP_ROUTE type",
824 pfx_buf, new_buf, exist_buf);
825 return 1;
826 }
718e3744 827
33c6e933 828 if (!new_origin && exist_origin) {
fdf81fa0 829 *reason = bgp_path_selection_local_route;
d62a17ae 830 if (debug)
831 zlog_debug(
832 "%s: %s loses to %s due to preferred BGP_ROUTE type",
833 pfx_buf, new_buf, exist_buf);
834 return 0;
6811845b 835 }
718e3744 836
d62a17ae 837 /* 4. AS path length check. */
892fedb6 838 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 839 int exist_hops = aspath_count_hops(existattr->aspath);
840 int exist_confeds = aspath_count_confeds(existattr->aspath);
841
892fedb6 842 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 843 int aspath_hops;
844
845 aspath_hops = aspath_count_hops(newattr->aspath);
846 aspath_hops += aspath_count_confeds(newattr->aspath);
847
848 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 849 *reason = bgp_path_selection_confed_as_path;
d62a17ae 850 if (debug)
851 zlog_debug(
852 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
853 pfx_buf, new_buf, exist_buf,
854 aspath_hops,
855 (exist_hops + exist_confeds));
856 return 1;
857 }
858
859 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 860 *reason = bgp_path_selection_confed_as_path;
d62a17ae 861 if (debug)
862 zlog_debug(
863 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
864 pfx_buf, new_buf, exist_buf,
865 aspath_hops,
866 (exist_hops + exist_confeds));
867 return 0;
868 }
869 } else {
870 int newhops = aspath_count_hops(newattr->aspath);
871
872 if (newhops < exist_hops) {
fdf81fa0 873 *reason = bgp_path_selection_as_path;
d62a17ae 874 if (debug)
875 zlog_debug(
876 "%s: %s wins over %s due to aspath hopcount %d < %d",
877 pfx_buf, new_buf, exist_buf,
878 newhops, exist_hops);
879 return 1;
880 }
881
882 if (newhops > exist_hops) {
fdf81fa0 883 *reason = bgp_path_selection_as_path;
d62a17ae 884 if (debug)
885 zlog_debug(
886 "%s: %s loses to %s due to aspath hopcount %d > %d",
887 pfx_buf, new_buf, exist_buf,
888 newhops, exist_hops);
889 return 0;
890 }
891 }
892 }
9fbdd100 893
d62a17ae 894 /* 5. Origin check. */
895 if (newattr->origin < existattr->origin) {
fdf81fa0 896 *reason = bgp_path_selection_origin;
d62a17ae 897 if (debug)
898 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
899 pfx_buf, new_buf, exist_buf,
900 bgp_origin_long_str[newattr->origin],
901 bgp_origin_long_str[existattr->origin]);
902 return 1;
903 }
718e3744 904
d62a17ae 905 if (newattr->origin > existattr->origin) {
fdf81fa0 906 *reason = bgp_path_selection_origin;
d62a17ae 907 if (debug)
908 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
909 pfx_buf, new_buf, exist_buf,
910 bgp_origin_long_str[newattr->origin],
911 bgp_origin_long_str[existattr->origin]);
912 return 0;
913 }
718e3744 914
d62a17ae 915 /* 6. MED check. */
916 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
917 && aspath_count_hops(existattr->aspath) == 0);
918 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
919 && aspath_count_confeds(existattr->aspath) > 0
920 && aspath_count_hops(newattr->aspath) == 0
921 && aspath_count_hops(existattr->aspath) == 0);
922
892fedb6
DA
923 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
924 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 925 || aspath_cmp_left(newattr->aspath, existattr->aspath)
926 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
927 || internal_as_route) {
928 new_med = bgp_med_value(new->attr, bgp);
929 exist_med = bgp_med_value(exist->attr, bgp);
930
931 if (new_med < exist_med) {
fdf81fa0 932 *reason = bgp_path_selection_med;
d62a17ae 933 if (debug)
934 zlog_debug(
935 "%s: %s wins over %s due to MED %d < %d",
936 pfx_buf, new_buf, exist_buf, new_med,
937 exist_med);
938 return 1;
939 }
8ff56318 940
d62a17ae 941 if (new_med > exist_med) {
fdf81fa0 942 *reason = bgp_path_selection_med;
d62a17ae 943 if (debug)
944 zlog_debug(
945 "%s: %s loses to %s due to MED %d > %d",
946 pfx_buf, new_buf, exist_buf, new_med,
947 exist_med);
948 return 0;
949 }
950 }
9fbdd100 951
d62a17ae 952 /* 7. Peer type check. */
953 new_sort = new->peer->sort;
954 exist_sort = exist->peer->sort;
955
956 if (new_sort == BGP_PEER_EBGP
957 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 958 *reason = bgp_path_selection_peer;
d62a17ae 959 if (debug)
960 zlog_debug(
961 "%s: %s wins over %s due to eBGP peer > iBGP peer",
962 pfx_buf, new_buf, exist_buf);
963 return 1;
964 }
718e3744 965
d62a17ae 966 if (exist_sort == BGP_PEER_EBGP
967 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 968 *reason = bgp_path_selection_peer;
d62a17ae 969 if (debug)
970 zlog_debug(
971 "%s: %s loses to %s due to iBGP peer < eBGP peer",
972 pfx_buf, new_buf, exist_buf);
973 return 0;
974 }
8ff56318 975
d62a17ae 976 /* 8. IGP metric check. */
977 newm = existm = 0;
8ff56318 978
d62a17ae 979 if (new->extra)
980 newm = new->extra->igpmetric;
981 if (exist->extra)
982 existm = exist->extra->igpmetric;
9fbdd100 983
d62a17ae 984 if (newm < existm) {
985 if (debug)
986 zlog_debug(
987 "%s: %s wins over %s due to IGP metric %d < %d",
988 pfx_buf, new_buf, exist_buf, newm, existm);
989 ret = 1;
990 }
718e3744 991
d62a17ae 992 if (newm > existm) {
993 if (debug)
994 zlog_debug(
995 "%s: %s loses to %s due to IGP metric %d > %d",
996 pfx_buf, new_buf, exist_buf, newm, existm);
997 ret = 0;
5e242b0d 998 }
5e242b0d 999
d62a17ae 1000 /* 9. Same IGP metric. Compare the cluster list length as
1001 representative of IGP hops metric. Rewrite the metric value
1002 pair (newm, existm) with the cluster list length. Prefer the
1003 path with smaller cluster list length. */
1004 if (newm == existm) {
bf0d28dc
DS
1005 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1006 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1007 && (mpath_cfg == NULL
1008 || CHECK_FLAG(
1009 mpath_cfg->ibgp_flags,
1010 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1011 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1012 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1013
1014 if (newm < existm) {
1015 if (debug)
1016 zlog_debug(
1017 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1018 pfx_buf, new_buf, exist_buf,
1019 newm, existm);
1020 ret = 1;
1021 }
1022
1023 if (newm > existm) {
1024 if (debug)
1025 zlog_debug(
1026 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1027 pfx_buf, new_buf, exist_buf,
1028 newm, existm);
1029 ret = 0;
1030 }
1031 }
1032 }
31a4638f 1033
d62a17ae 1034 /* 10. confed-external vs. confed-internal */
1035 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1036 if (new_sort == BGP_PEER_CONFED
1037 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1038 *reason = bgp_path_selection_confed;
d62a17ae 1039 if (debug)
1040 zlog_debug(
1041 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1042 pfx_buf, new_buf, exist_buf);
1043 return 1;
1044 }
718e3744 1045
d62a17ae 1046 if (exist_sort == BGP_PEER_CONFED
1047 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1048 *reason = bgp_path_selection_confed;
d62a17ae 1049 if (debug)
1050 zlog_debug(
1051 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1052 pfx_buf, new_buf, exist_buf);
1053 return 0;
1054 }
1055 }
718e3744 1056
d62a17ae 1057 /* 11. Maximum path check. */
1058 if (newm == existm) {
1059 /* If one path has a label but the other does not, do not treat
1060 * them as equals for multipath
1061 */
a4d82a8a 1062 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1063 != (exist->extra
b57ba6d2 1064 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1065 if (debug)
1066 zlog_debug(
1067 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1068 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1069 } else if (CHECK_FLAG(bgp->flags,
1070 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1071
1072 /*
1073 * For the two paths, all comparison steps till IGP
1074 * metric
1075 * have succeeded - including AS_PATH hop count. Since
1076 * 'bgp
1077 * bestpath as-path multipath-relax' knob is on, we
1078 * don't need
1079 * an exact match of AS_PATH. Thus, mark the paths are
1080 * equal.
1081 * That will trigger both these paths to get into the
1082 * multipath
1083 * array.
1084 */
1085 *paths_eq = 1;
1086
1087 if (debug)
1088 zlog_debug(
1089 "%s: %s and %s are equal via multipath-relax",
1090 pfx_buf, new_buf, exist_buf);
1091 } else if (new->peer->sort == BGP_PEER_IBGP) {
1092 if (aspath_cmp(new->attr->aspath,
1093 exist->attr->aspath)) {
1094 *paths_eq = 1;
1095
1096 if (debug)
1097 zlog_debug(
1098 "%s: %s and %s are equal via matching aspaths",
1099 pfx_buf, new_buf, exist_buf);
1100 }
1101 } else if (new->peer->as == exist->peer->as) {
1102 *paths_eq = 1;
1103
1104 if (debug)
1105 zlog_debug(
1106 "%s: %s and %s are equal via same remote-as",
1107 pfx_buf, new_buf, exist_buf);
1108 }
1109 } else {
1110 /*
1111 * TODO: If unequal cost ibgp multipath is enabled we can
1112 * mark the paths as equal here instead of returning
1113 */
1114 if (debug) {
1115 if (ret == 1)
1116 zlog_debug(
1117 "%s: %s wins over %s after IGP metric comparison",
1118 pfx_buf, new_buf, exist_buf);
1119 else
1120 zlog_debug(
1121 "%s: %s loses to %s after IGP metric comparison",
1122 pfx_buf, new_buf, exist_buf);
1123 }
fdf81fa0 1124 *reason = bgp_path_selection_igp_metric;
d62a17ae 1125 return ret;
1126 }
718e3744 1127
d62a17ae 1128 /* 12. If both paths are external, prefer the path that was received
1129 first (the oldest one). This step minimizes route-flap, since a
1130 newer path won't displace an older one, even if it was the
1131 preferred route based on the additional decision criteria below. */
892fedb6 1132 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1133 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1134 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1135 *reason = bgp_path_selection_older;
d62a17ae 1136 if (debug)
1137 zlog_debug(
1138 "%s: %s wins over %s due to oldest external",
1139 pfx_buf, new_buf, exist_buf);
1140 return 1;
1141 }
9fbdd100 1142
1defdda8 1143 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1144 *reason = bgp_path_selection_older;
d62a17ae 1145 if (debug)
1146 zlog_debug(
1147 "%s: %s loses to %s due to oldest external",
1148 pfx_buf, new_buf, exist_buf);
1149 return 0;
1150 }
1151 }
718e3744 1152
d62a17ae 1153 /* 13. Router-ID comparision. */
1154 /* If one of the paths is "stale", the corresponding peer router-id will
1155 * be 0 and would always win over the other path. If originator id is
1156 * used for the comparision, it will decide which path is better.
1157 */
1158 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1159 new_id.s_addr = newattr->originator_id.s_addr;
1160 else
1161 new_id.s_addr = new->peer->remote_id.s_addr;
1162 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1163 exist_id.s_addr = existattr->originator_id.s_addr;
1164 else
1165 exist_id.s_addr = exist->peer->remote_id.s_addr;
1166
1167 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1168 *reason = bgp_path_selection_router_id;
d62a17ae 1169 if (debug)
1170 zlog_debug(
1171 "%s: %s wins over %s due to Router-ID comparison",
1172 pfx_buf, new_buf, exist_buf);
1173 return 1;
1174 }
718e3744 1175
d62a17ae 1176 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1177 *reason = bgp_path_selection_router_id;
d62a17ae 1178 if (debug)
1179 zlog_debug(
1180 "%s: %s loses to %s due to Router-ID comparison",
1181 pfx_buf, new_buf, exist_buf);
1182 return 0;
1183 }
9fbdd100 1184
d62a17ae 1185 /* 14. Cluster length comparision. */
1186 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1187 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1188
1189 if (new_cluster < exist_cluster) {
fdf81fa0 1190 *reason = bgp_path_selection_cluster_length;
d62a17ae 1191 if (debug)
1192 zlog_debug(
1193 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1194 pfx_buf, new_buf, exist_buf, new_cluster,
1195 exist_cluster);
1196 return 1;
1197 }
718e3744 1198
d62a17ae 1199 if (new_cluster > exist_cluster) {
fdf81fa0 1200 *reason = bgp_path_selection_cluster_length;
d62a17ae 1201 if (debug)
1202 zlog_debug(
1203 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1204 pfx_buf, new_buf, exist_buf, new_cluster,
1205 exist_cluster);
1206 return 0;
1207 }
9fbdd100 1208
d62a17ae 1209 /* 15. Neighbor address comparision. */
1210 /* Do this only if neither path is "stale" as stale paths do not have
1211 * valid peer information (as the connection may or may not be up).
1212 */
1defdda8 1213 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1214 *reason = bgp_path_selection_stale;
d62a17ae 1215 if (debug)
1216 zlog_debug(
1217 "%s: %s wins over %s due to latter path being STALE",
1218 pfx_buf, new_buf, exist_buf);
1219 return 1;
1220 }
0de5153c 1221
1defdda8 1222 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1223 *reason = bgp_path_selection_stale;
d62a17ae 1224 if (debug)
1225 zlog_debug(
1226 "%s: %s loses to %s due to former path being STALE",
1227 pfx_buf, new_buf, exist_buf);
1228 return 0;
1229 }
718e3744 1230
d62a17ae 1231 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1232 if (new->peer->su_remote == NULL) {
1233 *reason = bgp_path_selection_local_configured;
d62a17ae 1234 return 0;
fdf81fa0
DS
1235 }
1236 if (exist->peer->su_remote == NULL) {
1237 *reason = bgp_path_selection_local_configured;
d62a17ae 1238 return 1;
fdf81fa0 1239 }
9fbdd100 1240
d62a17ae 1241 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1242
1243 if (ret == 1) {
fdf81fa0 1244 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s loses to %s due to Neighor IP comparison",
1248 pfx_buf, new_buf, exist_buf);
1249 return 0;
1250 }
1251
1252 if (ret == -1) {
fdf81fa0 1253 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1254 if (debug)
1255 zlog_debug(
1256 "%s: %s wins over %s due to Neighor IP comparison",
1257 pfx_buf, new_buf, exist_buf);
1258 return 1;
1259 }
9fbdd100 1260
fdf81fa0 1261 *reason = bgp_path_selection_default;
d62a17ae 1262 if (debug)
1263 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1264 pfx_buf, new_buf, exist_buf);
718e3744 1265
d62a17ae 1266 return 1;
718e3744 1267}
1268
d071f237
AK
1269
1270int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1271 struct bgp_path_info *exist, int *paths_eq)
1272{
1273 enum bgp_path_selection_reason reason;
1274 char pfx_buf[PREFIX2STR_BUFFER];
1275
1276 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1277 AFI_L2VPN, SAFI_EVPN, &reason);
1278}
1279
65efcfce
LB
1280/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1281 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1282 * multipath is enabled
65efcfce 1283 * This version is compatible with */
18ee8310
DS
1284int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1285 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1286 afi_t afi, safi_t safi,
1287 enum bgp_path_selection_reason *reason)
d62a17ae 1288{
1289 int paths_eq;
1290 int ret;
18ee8310 1291 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1292 afi, safi, reason);
d62a17ae 1293
1294 if (paths_eq)
1295 ret = 0;
1296 else {
1297 if (ret == 1)
1298 ret = -1;
1299 else
1300 ret = 1;
1301 }
1302 return ret;
65efcfce
LB
1303}
1304
5a1ae2c2
DS
1305static enum filter_type bgp_input_filter(struct peer *peer,
1306 const struct prefix *p,
d62a17ae 1307 struct attr *attr, afi_t afi,
1308 safi_t safi)
718e3744 1309{
d62a17ae 1310 struct bgp_filter *filter;
6401252f 1311 enum filter_type ret = FILTER_PERMIT;
718e3744 1312
d62a17ae 1313 filter = &peer->filter[afi][safi];
718e3744 1314
d62a17ae 1315#define FILTER_EXIST_WARN(F, f, filter) \
1316 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1317 zlog_debug("%s: Could not find configured input %s-list %s!", \
1318 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1319
1320 if (DISTRIBUTE_IN_NAME(filter)) {
1321 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1322
6401252f
QY
1323 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1324 == FILTER_DENY) {
1325 ret = FILTER_DENY;
1326 goto done;
1327 }
d62a17ae 1328 }
1329
1330 if (PREFIX_LIST_IN_NAME(filter)) {
1331 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1332
6401252f
QY
1333 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1334 == PREFIX_DENY) {
1335 ret = FILTER_DENY;
1336 goto done;
1337 }
d62a17ae 1338 }
1339
1340 if (FILTER_LIST_IN_NAME(filter)) {
1341 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1342
1343 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1344 == AS_FILTER_DENY) {
1345 ret = FILTER_DENY;
1346 goto done;
1347 }
d62a17ae 1348 }
1349
6401252f 1350done:
c7bb4f00 1351 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1352 char pfxprint[PREFIX2STR_BUFFER];
1353
1354 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1355 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1356 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1357 }
1358
1359 return ret;
650f76c2 1360#undef FILTER_EXIST_WARN
718e3744 1361}
1362
b8685f9b
DS
1363static enum filter_type bgp_output_filter(struct peer *peer,
1364 const struct prefix *p,
d62a17ae 1365 struct attr *attr, afi_t afi,
1366 safi_t safi)
718e3744 1367{
d62a17ae 1368 struct bgp_filter *filter;
6401252f 1369 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1370
1371 filter = &peer->filter[afi][safi];
1372
1373#define FILTER_EXIST_WARN(F, f, filter) \
1374 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1375 zlog_debug("%s: Could not find configured output %s-list %s!", \
1376 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1377
d62a17ae 1378 if (DISTRIBUTE_OUT_NAME(filter)) {
1379 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1380
6401252f
QY
1381 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1382 == FILTER_DENY) {
1383 ret = FILTER_DENY;
1384 goto done;
1385 }
d62a17ae 1386 }
1387
1388 if (PREFIX_LIST_OUT_NAME(filter)) {
1389 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1390
d62a17ae 1391 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1392 == PREFIX_DENY) {
1393 ret = FILTER_DENY;
1394 goto done;
1395 }
d62a17ae 1396 }
718e3744 1397
d62a17ae 1398 if (FILTER_LIST_OUT_NAME(filter)) {
1399 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1400
d62a17ae 1401 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1402 == AS_FILTER_DENY) {
1403 ret = FILTER_DENY;
1404 goto done;
1405 }
1406 }
1407
c7bb4f00 1408 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1409 char pfxprint[PREFIX2STR_BUFFER];
1410
1411 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1412 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1413 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1414 }
718e3744 1415
6401252f
QY
1416done:
1417 return ret;
650f76c2 1418#undef FILTER_EXIST_WARN
718e3744 1419}
1420
1421/* If community attribute includes no_export then return 1. */
3dc339cd 1422static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1423{
1424 if (attr->community) {
1425 /* NO_ADVERTISE check. */
1426 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1427 return true;
d62a17ae 1428
1429 /* NO_EXPORT check. */
1430 if (peer->sort == BGP_PEER_EBGP
1431 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1432 return true;
d62a17ae 1433
1434 /* NO_EXPORT_SUBCONFED check. */
1435 if (peer->sort == BGP_PEER_EBGP
1436 || peer->sort == BGP_PEER_CONFED)
1437 if (community_include(attr->community,
1438 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1439 return true;
d62a17ae 1440 }
3dc339cd 1441 return false;
718e3744 1442}
1443
1444/* Route reflection loop check. */
3dc339cd 1445static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1446{
d62a17ae 1447 struct in_addr cluster_id;
779fee93 1448 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1449
779fee93 1450 if (cluster) {
d62a17ae 1451 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1452 cluster_id = peer->bgp->cluster_id;
1453 else
1454 cluster_id = peer->bgp->router_id;
1455
779fee93 1456 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1457 return true;
d62a17ae 1458 }
3dc339cd 1459 return false;
718e3744 1460}
6b0655a2 1461
5a1ae2c2 1462static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1463 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1464 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1465 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1466{
d62a17ae 1467 struct bgp_filter *filter;
82b692c0
LK
1468 struct bgp_path_info rmap_path = { 0 };
1469 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1470 route_map_result_t ret;
1471 struct route_map *rmap = NULL;
718e3744 1472
d62a17ae 1473 filter = &peer->filter[afi][safi];
718e3744 1474
d62a17ae 1475 /* Apply default weight value. */
1476 if (peer->weight[afi][safi])
1477 attr->weight = peer->weight[afi][safi];
718e3744 1478
d62a17ae 1479 if (rmap_name) {
1480 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1481
d62a17ae 1482 if (rmap == NULL)
1483 return RMAP_DENY;
1484 } else {
1485 if (ROUTE_MAP_IN_NAME(filter)) {
1486 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1487
d62a17ae 1488 if (rmap == NULL)
1489 return RMAP_DENY;
1490 }
1491 }
0b16f239 1492
d62a17ae 1493 /* Route map apply. */
1494 if (rmap) {
40381db7 1495 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1496 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1497 rmap_path.peer = peer;
1498 rmap_path.attr = attr;
82b692c0 1499 rmap_path.extra = &extra;
9bcb3eef 1500 rmap_path.net = dest;
196c6b09 1501
82b692c0
LK
1502 extra.num_labels = num_labels;
1503 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1504 memcpy(extra.label, label,
1505 num_labels * sizeof(mpls_label_t));
718e3744 1506
d62a17ae 1507 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1508
d62a17ae 1509 /* Apply BGP route map to the attribute. */
1782514f 1510 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1511
d62a17ae 1512 peer->rmap_type = 0;
0b16f239 1513
1f2263be 1514 if (ret == RMAP_DENYMATCH)
d62a17ae 1515 return RMAP_DENY;
0b16f239 1516 }
d62a17ae 1517 return RMAP_PERMIT;
0b16f239
DS
1518}
1519
5f040085 1520static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1521 struct attr *attr, afi_t afi, safi_t safi,
1522 const char *rmap_name)
0b16f239 1523{
40381db7 1524 struct bgp_path_info rmap_path;
d62a17ae 1525 route_map_result_t ret;
1526 struct route_map *rmap = NULL;
d7c0a89a 1527 uint8_t rmap_type;
0b16f239 1528
b787157a
DS
1529 /*
1530 * So if we get to this point and have no rmap_name
1531 * we want to just show the output as it currently
1532 * exists.
1533 */
1534 if (!rmap_name)
1535 return RMAP_PERMIT;
0b16f239 1536
d62a17ae 1537 /* Apply default weight value. */
1538 if (peer->weight[afi][safi])
1539 attr->weight = peer->weight[afi][safi];
0b16f239 1540
b787157a 1541 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1542
b787157a
DS
1543 /*
1544 * If we have a route map name and we do not find
1545 * the routemap that means we have an implicit
1546 * deny.
1547 */
1548 if (rmap == NULL)
1549 return RMAP_DENY;
0b16f239 1550
40381db7 1551 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1552 /* Route map apply. */
b787157a 1553 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1554 rmap_path.peer = peer;
1555 rmap_path.attr = attr;
0b16f239 1556
0f672529 1557 rmap_type = peer->rmap_type;
b787157a 1558 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1559
b787157a 1560 /* Apply BGP route map to the attribute. */
1782514f 1561 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1562
0f672529 1563 peer->rmap_type = rmap_type;
b787157a
DS
1564
1565 if (ret == RMAP_DENYMATCH)
1566 /*
1567 * caller has multiple error paths with bgp_attr_flush()
1568 */
1569 return RMAP_DENY;
ac41b2a2 1570
d62a17ae 1571 return RMAP_PERMIT;
718e3744 1572}
6b0655a2 1573
5000f21c 1574/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1575static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1576 struct peer *peer, struct attr *attr)
1577{
1578 if (peer->sort == BGP_PEER_EBGP
1579 && (peer_af_flag_check(peer, afi, safi,
1580 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1581 || peer_af_flag_check(peer, afi, safi,
1582 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1583 || peer_af_flag_check(peer, afi, safi,
1584 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1585 || peer_af_flag_check(peer, afi, safi,
1586 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1587 // Take action on the entire aspath
1588 if (peer_af_flag_check(peer, afi, safi,
1589 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1590 || peer_af_flag_check(peer, afi, safi,
1591 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1592 if (peer_af_flag_check(
1593 peer, afi, safi,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1595 attr->aspath = aspath_replace_private_asns(
bf26b80e 1596 attr->aspath, bgp->as, peer->as);
d62a17ae 1597
1598 // The entire aspath consists of private ASNs so create
1599 // an empty aspath
1600 else if (aspath_private_as_check(attr->aspath))
1601 attr->aspath = aspath_empty_get();
1602
1603 // There are some public and some private ASNs, remove
1604 // the private ASNs
1605 else
1606 attr->aspath = aspath_remove_private_asns(
bf26b80e 1607 attr->aspath, peer->as);
d62a17ae 1608 }
1609
1610 // 'all' was not specified so the entire aspath must be private
1611 // ASNs
1612 // for us to do anything
1613 else if (aspath_private_as_check(attr->aspath)) {
1614 if (peer_af_flag_check(
1615 peer, afi, safi,
1616 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1617 attr->aspath = aspath_replace_private_asns(
bf26b80e 1618 attr->aspath, bgp->as, peer->as);
d62a17ae 1619 else
1620 attr->aspath = aspath_empty_get();
1621 }
1622 }
5000f21c
DS
1623}
1624
c7122e14 1625/* If this is an EBGP peer with as-override */
d62a17ae 1626static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1627 struct peer *peer, struct attr *attr)
1628{
1629 if (peer->sort == BGP_PEER_EBGP
1630 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1631 if (aspath_single_asn_check(attr->aspath, peer->as))
1632 attr->aspath = aspath_replace_specific_asn(
1633 attr->aspath, peer->as, bgp->as);
1634 }
1635}
1636
7f323236
DW
1637void bgp_attr_add_gshut_community(struct attr *attr)
1638{
1639 struct community *old;
1640 struct community *new;
1641 struct community *merge;
1642 struct community *gshut;
1643
1644 old = attr->community;
1645 gshut = community_str2com("graceful-shutdown");
1646
990f4f91 1647 assert(gshut);
1648
7f323236
DW
1649 if (old) {
1650 merge = community_merge(community_dup(old), gshut);
1651
a4d82a8a 1652 if (old->refcnt == 0)
3c1f53de 1653 community_free(&old);
7f323236
DW
1654
1655 new = community_uniq_sort(merge);
3c1f53de 1656 community_free(&merge);
7f323236
DW
1657 } else {
1658 new = community_dup(gshut);
1659 }
1660
3c1f53de 1661 community_free(&gshut);
7f323236
DW
1662 attr->community = new;
1663 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1664
1665 /* When we add the graceful-shutdown community we must also
1666 * lower the local-preference */
1667 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1668 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1669}
1670
1671
e73c112e
MK
1672/* Notify BGP Conditional advertisement scanner process. */
1673void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1674{
1675 struct peer *temp_peer;
1676 struct peer *peer = SUBGRP_PEER(subgrp);
1677 struct listnode *temp_node, *temp_nnode = NULL;
1678 afi_t afi = SUBGRP_AFI(subgrp);
1679 safi_t safi = SUBGRP_SAFI(subgrp);
1680 struct bgp *bgp = SUBGRP_INST(subgrp);
1681 struct bgp_filter *filter = &peer->filter[afi][safi];
1682
1683 if (!ADVERTISE_MAP_NAME(filter))
1684 return;
1685
1686 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1687 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1688 continue;
1689
1690 if (peer != temp_peer)
1691 continue;
1692
1693 temp_peer->advmap_table_change = true;
1694 break;
1695 }
1696}
1697
1698
f2ee6d5c 1699void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1700{
960035b2 1701 if (family == AF_INET) {
975a328e
DA
1702 attr->nexthop.s_addr = INADDR_ANY;
1703 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1704 }
d62a17ae 1705 if (family == AF_INET6)
1706 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1707 if (family == AF_EVPN)
1708 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1709}
1710
9bcb3eef 1711bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1712 struct update_subgroup *subgrp,
7f7940e6
MK
1713 const struct prefix *p, struct attr *attr,
1714 bool skip_rmap_check)
d62a17ae 1715{
1716 struct bgp_filter *filter;
1717 struct peer *from;
1718 struct peer *peer;
1719 struct peer *onlypeer;
1720 struct bgp *bgp;
40381db7 1721 struct attr *piattr;
b68885f9 1722 route_map_result_t ret;
d62a17ae 1723 int transparent;
1724 int reflect;
1725 afi_t afi;
1726 safi_t safi;
1727 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1728 bool nh_reset = false;
1729 uint64_t cum_bw;
d62a17ae 1730
1731 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1732 return false;
d62a17ae 1733
1734 afi = SUBGRP_AFI(subgrp);
1735 safi = SUBGRP_SAFI(subgrp);
1736 peer = SUBGRP_PEER(subgrp);
1737 onlypeer = NULL;
1738 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1739 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1740
40381db7 1741 from = pi->peer;
d62a17ae 1742 filter = &peer->filter[afi][safi];
1743 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1744 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1745 : pi->attr;
3f9c7369 1746
49e5a4a0 1747#ifdef ENABLE_BGP_VNC
d62a17ae 1748 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1749 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1750 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1751
1752 /*
1753 * direct and direct_ext type routes originate internally even
1754 * though they can have peer pointers that reference other
1755 * systems
1756 */
8228a9a7
DS
1757 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1758 __func__, p);
d62a17ae 1759 samepeer_safe = 1;
1760 }
65efcfce
LB
1761#endif
1762
ddb5b488
PZ
1763 if (((afi == AFI_IP) || (afi == AFI_IP6))
1764 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1765 && (pi->type == ZEBRA_ROUTE_BGP)
1766 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1767
1768 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1769
1770 samepeer_safe = 1;
1771 }
1772
d62a17ae 1773 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1774 * pi is valid */
1775 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1776 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1777 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1778 return false;
d62a17ae 1779 }
adbac85e 1780
d62a17ae 1781 /* If this is not the bestpath then check to see if there is an enabled
1782 * addpath
1783 * feature that requires us to advertise it */
40381db7 1784 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1785 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1786 return false;
d62a17ae 1787 }
1788 }
06370dac 1789
d62a17ae 1790 /* Aggregate-address suppress check. */
4056a5f6
RZ
1791 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1792 return false;
3f9c7369 1793
13b7e7f0
DS
1794 /*
1795 * If we are doing VRF 2 VRF leaking via the import
1796 * statement, we want to prevent the route going
1797 * off box as that the RT and RD created are localy
1798 * significant and globaly useless.
1799 */
40381db7
DS
1800 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1801 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1802 return false;
13b7e7f0 1803
d62a17ae 1804 /* If it's labeled safi, make sure the route has a valid label. */
1805 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1806 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1807 if (!bgp_is_valid_label(&label)) {
1808 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1809 zlog_debug("u%" PRIu64 ":s%" PRIu64
1810 " %pFX is filtered - no label (%p)",
d62a17ae 1811 subgrp->update_group->id, subgrp->id,
8228a9a7 1812 p, &label);
3dc339cd 1813 return false;
d62a17ae 1814 }
1815 }
cd1964ff 1816
d62a17ae 1817 /* Do not send back route to sender. */
1818 if (onlypeer && from == onlypeer) {
3dc339cd 1819 return false;
d62a17ae 1820 }
3f9c7369 1821
d62a17ae 1822 /* Do not send the default route in the BGP table if the neighbor is
1823 * configured for default-originate */
1824 if (CHECK_FLAG(peer->af_flags[afi][safi],
1825 PEER_FLAG_DEFAULT_ORIGINATE)) {
1826 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1827 return false;
d62a17ae 1828 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1829 return false;
d62a17ae 1830 }
4125bb67 1831
d62a17ae 1832 /* Transparency check. */
1833 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1834 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1835 transparent = 1;
1836 else
1837 transparent = 0;
1838
1839 /* If community is not disabled check the no-export and local. */
40381db7 1840 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1841 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
84c320dc 1842 zlog_debug("%s: community filter check fail", __func__);
3dc339cd 1843 return false;
d62a17ae 1844 }
3f9c7369 1845
d62a17ae 1846 /* If the attribute has originator-id and it is same as remote
1847 peer's id. */
40381db7
DS
1848 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1849 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1850 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1851 zlog_debug(
8228a9a7
DS
1852 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1853 onlypeer->host, p);
3dc339cd 1854 return false;
d62a17ae 1855 }
3f9c7369 1856
d62a17ae 1857 /* ORF prefix-list filter check */
1858 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1859 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1860 || CHECK_FLAG(peer->af_cap[afi][safi],
1861 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1862 if (peer->orf_plist[afi][safi]) {
1863 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1864 == PREFIX_DENY) {
1865 if (bgp_debug_update(NULL, p,
1866 subgrp->update_group, 0))
1867 zlog_debug(
8228a9a7
DS
1868 "%s [Update:SEND] %pFX is filtered via ORF",
1869 peer->host, p);
3dc339cd 1870 return false;
d62a17ae 1871 }
1872 }
1873
1874 /* Output filter check. */
40381db7 1875 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1876 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1877 zlog_debug("%s [Update:SEND] %pFX is filtered",
1878 peer->host, p);
3dc339cd 1879 return false;
d62a17ae 1880 }
3f9c7369 1881
d62a17ae 1882 /* AS path loop check. */
2b31007c
RZ
1883 if (onlypeer && onlypeer->as_path_loop_detection
1884 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1885 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1886 zlog_debug(
3efd0893 1887 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1888 onlypeer->host, onlypeer->as);
3dc339cd 1889 return false;
d62a17ae 1890 }
3f9c7369 1891
d62a17ae 1892 /* If we're a CONFED we need to loop check the CONFED ID too */
1893 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1894 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1895 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1896 zlog_debug(
3efd0893 1897 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1898 peer->host, bgp->confed_id);
3dc339cd 1899 return false;
d62a17ae 1900 }
3f9c7369 1901 }
3f9c7369 1902
d62a17ae 1903 /* Route-Reflect check. */
1904 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1905 reflect = 1;
1906 else
1907 reflect = 0;
1908
1909 /* IBGP reflection check. */
1910 if (reflect && !samepeer_safe) {
1911 /* A route from a Client peer. */
1912 if (CHECK_FLAG(from->af_flags[afi][safi],
1913 PEER_FLAG_REFLECTOR_CLIENT)) {
1914 /* Reflect to all the Non-Client peers and also to the
1915 Client peers other than the originator. Originator
1916 check
1917 is already done. So there is noting to do. */
1918 /* no bgp client-to-client reflection check. */
892fedb6
DA
1919 if (CHECK_FLAG(bgp->flags,
1920 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1921 if (CHECK_FLAG(peer->af_flags[afi][safi],
1922 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1923 return false;
d62a17ae 1924 } else {
1925 /* A route from a Non-client peer. Reflect to all other
1926 clients. */
1927 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1928 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1929 return false;
d62a17ae 1930 }
1931 }
3f9c7369 1932
d62a17ae 1933 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1934 *attr = *piattr;
d62a17ae 1935
1936 /* If local-preference is not set. */
1937 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1938 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1939 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1940 attr->local_pref = bgp->default_local_pref;
3f9c7369 1941 }
3f9c7369 1942
d62a17ae 1943 /* If originator-id is not set and the route is to be reflected,
1944 set the originator id */
1945 if (reflect
1946 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1947 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1948 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1949 }
3f9c7369 1950
d62a17ae 1951 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1952 */
1953 if (peer->sort == BGP_PEER_EBGP
1954 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1955 if (from != bgp->peer_self && !transparent
1956 && !CHECK_FLAG(peer->af_flags[afi][safi],
1957 PEER_FLAG_MED_UNCHANGED))
1958 attr->flag &=
1959 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1960 }
3f9c7369 1961
d62a17ae 1962 /* Since the nexthop attribute can vary per peer, it is not explicitly
1963 * set
1964 * in announce check, only certain flags and length (or number of
1965 * nexthops
1966 * -- for IPv6/MP_REACH) are set here in order to guide the update
1967 * formation
1968 * code in setting the nexthop(s) on a per peer basis in
1969 * reformat_peer().
1970 * Typically, the source nexthop in the attribute is preserved but in
1971 * the
1972 * scenarios where we know it will always be overwritten, we reset the
1973 * nexthop to "0" in an attempt to achieve better Update packing. An
1974 * example of this is when a prefix from each of 2 IBGP peers needs to
1975 * be
1976 * announced to an EBGP peer (and they have the same attributes barring
1977 * their nexthop).
1978 */
1979 if (reflect)
1980 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1981
1982#define NEXTHOP_IS_V6 \
1983 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1984 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1985 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1986 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1987
1988 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1989 * if
1990 * the peer (group) is configured to receive link-local nexthop
1991 * unchanged
c728d027
DA
1992 * and it is available in the prefix OR we're not reflecting the route,
1993 * link-local nexthop address is valid and
d62a17ae 1994 * the peer (group) to whom we're going to announce is on a shared
1995 * network
1996 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1997 * By checking if nexthop LL address is valid we are sure that
1998 * we do not announce LL address as `::`.
d62a17ae 1999 */
2000 if (NEXTHOP_IS_V6) {
2001 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2002 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2003 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2004 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2005 || (!reflect
2006 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2007 && peer->shared_network
d62a17ae 2008 && (from == bgp->peer_self
2009 || peer->sort == BGP_PEER_EBGP))) {
2010 attr->mp_nexthop_len =
2011 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2012 }
3f9c7369 2013
d62a17ae 2014 /* Clear off link-local nexthop in source, whenever it is not
2015 * needed to
2016 * ensure more prefixes share the same attribute for
2017 * announcement.
2018 */
2019 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2020 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2021 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2022 }
3f9c7369 2023
d62a17ae 2024 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2025 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2026
2027 /* Route map & unsuppress-map apply. */
7f7940e6 2028 if (!skip_rmap_check
e73c112e 2029 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2030 struct bgp_path_info rmap_path = {0};
2031 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2032 struct attr dummy_attr = {0};
d62a17ae 2033
e34291b8 2034 /* Fill temp path_info */
9bcb3eef
DS
2035 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2036 pi, peer, attr);
16f7ce2b 2037
d62a17ae 2038 /* don't confuse inbound and outbound setting */
2039 RESET_FLAG(attr->rmap_change_flags);
2040
2041 /*
2042 * The route reflector is not allowed to modify the attributes
2043 * of the reflected IBGP routes unless explicitly allowed.
2044 */
2045 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2046 && !CHECK_FLAG(bgp->flags,
2047 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2048 dummy_attr = *attr;
40381db7 2049 rmap_path.attr = &dummy_attr;
d62a17ae 2050 }
3f9c7369 2051
d62a17ae 2052 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2053
4056a5f6 2054 if (bgp_path_suppressed(pi))
d62a17ae 2055 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2056 &rmap_path);
d62a17ae 2057 else
2058 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2059 &rmap_path);
d62a17ae 2060
2061 peer->rmap_type = 0;
2062
2063 if (ret == RMAP_DENYMATCH) {
778048bf 2064 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2065 zlog_debug(
2066 "%s [Update:SEND] %pFX is filtered by route-map",
2067 peer->host, p);
778048bf 2068
d62a17ae 2069 bgp_attr_flush(attr);
3dc339cd 2070 return false;
d62a17ae 2071 }
3f9c7369 2072 }
3f9c7369 2073
9dac9fc8
DA
2074 /* RFC 8212 to prevent route leaks.
2075 * This specification intends to improve this situation by requiring the
2076 * explicit configuration of both BGP Import and Export Policies for any
2077 * External BGP (EBGP) session such as customers, peers, or
2078 * confederation boundaries for all enabled address families. Through
2079 * codification of the aforementioned requirement, operators will
2080 * benefit from consistent behavior across different BGP
2081 * implementations.
2082 */
1d3fdccf 2083 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2084 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2085 return false;
9dac9fc8 2086
fb29348a
DA
2087 /* draft-ietf-idr-deprecate-as-set-confed-set
2088 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2089 * Eventually, This document (if approved) updates RFC 4271
2090 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2091 * and obsoletes RFC 6472.
2092 */
7f972cd8 2093 if (peer->bgp->reject_as_sets)
fb29348a 2094 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2095 return false;
fb29348a 2096
33d022bc
DA
2097 /* Codification of AS 0 Processing */
2098 if (aspath_check_as_zero(attr->aspath))
e2369003 2099 return false;
33d022bc 2100
637e5ba4 2101 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2102 if (peer->sort == BGP_PEER_IBGP
2103 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2104 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2105 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2106 } else {
2107 bgp_attr_add_gshut_community(attr);
2108 }
2109 }
2110
d62a17ae 2111 /* After route-map has been applied, we check to see if the nexthop to
2112 * be carried in the attribute (that is used for the announcement) can
2113 * be cleared off or not. We do this in all cases where we would be
2114 * setting the nexthop to "ourselves". For IPv6, we only need to
2115 * consider
2116 * the global nexthop here; the link-local nexthop would have been
2117 * cleared
2118 * already, and if not, it is required by the update formation code.
2119 * Also see earlier comments in this function.
2120 */
2121 /*
2122 * If route-map has performed some operation on the nexthop or the peer
2123 * configuration says to pass it unchanged, we cannot reset the nexthop
2124 * here, so only attempt to do it if these aren't true. Note that the
2125 * route-map handler itself might have cleared the nexthop, if for
2126 * example,
2127 * it is configured as 'peer-address'.
2128 */
2129 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2130 piattr->rmap_change_flags)
d62a17ae 2131 && !transparent
2132 && !CHECK_FLAG(peer->af_flags[afi][safi],
2133 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2134 /* We can reset the nexthop, if setting (or forcing) it to
2135 * 'self' */
2136 if (CHECK_FLAG(peer->af_flags[afi][safi],
2137 PEER_FLAG_NEXTHOP_SELF)
2138 || CHECK_FLAG(peer->af_flags[afi][safi],
2139 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2140 if (!reflect
2141 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2142 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2143 subgroup_announce_reset_nhop(
2144 (peer_cap_enhe(peer, afi, safi)
2145 ? AF_INET6
2146 : p->family),
2147 attr);
7b651a32 2148 nh_reset = true;
2149 }
d62a17ae 2150 } else if (peer->sort == BGP_PEER_EBGP) {
2151 /* Can also reset the nexthop if announcing to EBGP, but
2152 * only if
2153 * no peer in the subgroup is on a shared subnet.
2154 * Note: 3rd party nexthop currently implemented for
2155 * IPv4 only.
2156 */
737af885
BS
2157 if ((p->family == AF_INET) &&
2158 (!bgp_subgrp_multiaccess_check_v4(
2159 piattr->nexthop,
7b651a32 2160 subgrp, from))) {
d62a17ae 2161 subgroup_announce_reset_nhop(
2162 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2163 ? AF_INET6
2164 : p->family),
737af885 2165 attr);
7b651a32 2166 nh_reset = true;
2167 }
737af885
BS
2168
2169 if ((p->family == AF_INET6) &&
2170 (!bgp_subgrp_multiaccess_check_v6(
2171 piattr->mp_nexthop_global,
7b651a32 2172 subgrp, from))) {
737af885
BS
2173 subgroup_announce_reset_nhop(
2174 (peer_cap_enhe(peer, afi, safi)
2175 ? AF_INET6
2176 : p->family),
2177 attr);
7b651a32 2178 nh_reset = true;
2179 }
737af885
BS
2180
2181
2182
40381db7 2183 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2184 /*
2185 * This flag is used for leaked vpn-vrf routes
2186 */
2187 int family = p->family;
2188
2189 if (peer_cap_enhe(peer, afi, safi))
2190 family = AF_INET6;
2191
2192 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2193 zlog_debug(
1defdda8 2194 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2195 __func__, family2str(family));
2196 subgroup_announce_reset_nhop(family, attr);
7b651a32 2197 nh_reset = true;
d62a17ae 2198 }
63696f1d 2199 }
960035b2 2200
63696f1d 2201 /* If IPv6/MP and nexthop does not have any override and happens
2202 * to
2203 * be a link-local address, reset it so that we don't pass along
2204 * the
2205 * source's link-local IPv6 address to recipients who may not be
2206 * on
2207 * the same interface.
2208 */
2209 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2210 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2211 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2212 nh_reset = true;
2213 }
d62a17ae 2214 }
3f9c7369 2215
7b651a32 2216 /*
2217 * When the next hop is set to ourselves, if all multipaths have
2218 * link-bandwidth announce the cumulative bandwidth as that makes
2219 * the most sense. However, don't modify if the link-bandwidth has
2220 * been explicitly set by user policy.
2221 */
2222 if (nh_reset &&
f7e1c681 2223 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2224 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2225 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2226 attr->ecommunity = ecommunity_replace_linkbw(
2227 bgp->as, attr->ecommunity, cum_bw);
2228
3dc339cd 2229 return true;
3f9c7369
DS
2230}
2231
f009ff26 2232static int bgp_route_select_timer_expire(struct thread *thread)
2233{
2234 struct afi_safi_info *info;
2235 afi_t afi;
2236 safi_t safi;
2237 struct bgp *bgp;
2238
2239 info = THREAD_ARG(thread);
2240 afi = info->afi;
2241 safi = info->safi;
2242 bgp = info->bgp;
2243
2244 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2245 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2246 safi);
f009ff26 2247
2248 bgp->gr_info[afi][safi].t_route_select = NULL;
2249
2250 XFREE(MTYPE_TMP, info);
2251
2252 /* Best path selection */
2253 return bgp_best_path_select_defer(bgp, afi, safi);
2254}
2255
9bcb3eef 2256void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2257 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2258 struct bgp_path_info_pair *result, afi_t afi,
2259 safi_t safi)
2260{
2261 struct bgp_path_info *new_select;
2262 struct bgp_path_info *old_select;
40381db7
DS
2263 struct bgp_path_info *pi;
2264 struct bgp_path_info *pi1;
2265 struct bgp_path_info *pi2;
2266 struct bgp_path_info *nextpi = NULL;
d62a17ae 2267 int paths_eq, do_mpath, debug;
2268 struct list mp_list;
2269 char pfx_buf[PREFIX2STR_BUFFER];
2270 char path_buf[PATH_ADDPATH_STR_BUFFER];
2271
2272 bgp_mp_list_init(&mp_list);
2273 do_mpath =
2274 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2275
9bcb3eef 2276 debug = bgp_debug_bestpath(dest);
d62a17ae 2277
2278 if (debug)
9bcb3eef 2279 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2280
9bcb3eef 2281 dest->reason = bgp_path_selection_none;
d62a17ae 2282 /* bgp deterministic-med */
2283 new_select = NULL;
892fedb6 2284 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2285
1defdda8 2286 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2287 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2288 pi1 = pi1->next)
9bcb3eef 2289 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2290 BGP_PATH_DMED_SELECTED);
d62a17ae 2291
9bcb3eef 2292 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2293 pi1 = pi1->next) {
40381db7 2294 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2295 continue;
40381db7 2296 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2297 continue;
ea8b2282 2298 if (pi1->peer != bgp->peer_self)
40381db7 2299 if (pi1->peer->status != Established)
d62a17ae 2300 continue;
2301
40381db7
DS
2302 new_select = pi1;
2303 if (pi1->next) {
2304 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2305 if (CHECK_FLAG(pi2->flags,
1defdda8 2306 BGP_PATH_DMED_CHECK))
d62a17ae 2307 continue;
40381db7 2308 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2309 continue;
ea8b2282 2310 if (pi2->peer != bgp->peer_self
d62a17ae 2311 && !CHECK_FLAG(
ea8b2282
DS
2312 pi2->peer->sflags,
2313 PEER_STATUS_NSF_WAIT))
40381db7 2314 if (pi2->peer->status
d62a17ae 2315 != Established)
2316 continue;
2317
121e245d
DS
2318 if (!aspath_cmp_left(pi1->attr->aspath,
2319 pi2->attr->aspath)
2320 && !aspath_cmp_left_confed(
40381db7 2321 pi1->attr->aspath,
121e245d
DS
2322 pi2->attr->aspath))
2323 continue;
d62a17ae 2324
121e245d
DS
2325 if (bgp_path_info_cmp(
2326 bgp, pi2, new_select,
2327 &paths_eq, mpath_cfg, debug,
fdf81fa0 2328 pfx_buf, afi, safi,
9bcb3eef 2329 &dest->reason)) {
121e245d 2330 bgp_path_info_unset_flag(
9bcb3eef 2331 dest, new_select,
121e245d
DS
2332 BGP_PATH_DMED_SELECTED);
2333 new_select = pi2;
d62a17ae 2334 }
121e245d
DS
2335
2336 bgp_path_info_set_flag(
9bcb3eef 2337 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2338 }
2339 }
9bcb3eef 2340 bgp_path_info_set_flag(dest, new_select,
18ee8310 2341 BGP_PATH_DMED_CHECK);
9bcb3eef 2342 bgp_path_info_set_flag(dest, new_select,
18ee8310 2343 BGP_PATH_DMED_SELECTED);
d62a17ae 2344
2345 if (debug) {
18ee8310
DS
2346 bgp_path_info_path_with_addpath_rx_str(
2347 new_select, path_buf);
8228a9a7
DS
2348 zlog_debug(
2349 "%pBD: %s is the bestpath from AS %u",
2350 dest, path_buf,
2351 aspath_get_first_as(
2352 new_select->attr->aspath));
d62a17ae 2353 }
2354 }
2355 }
96450faf 2356
d62a17ae 2357 /* Check old selected route and new selected route. */
2358 old_select = NULL;
2359 new_select = NULL;
9bcb3eef 2360 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2361 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2362 enum bgp_path_selection_reason reason;
2363
40381db7
DS
2364 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2365 old_select = pi;
d62a17ae 2366
40381db7 2367 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2368 /* reap REMOVED routes, if needs be
2369 * selected route must stay for a while longer though
2370 */
40381db7
DS
2371 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2372 && (pi != old_select))
9bcb3eef 2373 bgp_path_info_reap(dest, pi);
d62a17ae 2374
ddb5b488 2375 if (debug)
40381db7
DS
2376 zlog_debug("%s: pi %p in holddown", __func__,
2377 pi);
ddb5b488 2378
d62a17ae 2379 continue;
2380 }
96450faf 2381
40381db7
DS
2382 if (pi->peer && pi->peer != bgp->peer_self
2383 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2384 if (pi->peer->status != Established) {
ddb5b488
PZ
2385
2386 if (debug)
2387 zlog_debug(
40381db7
DS
2388 "%s: pi %p non self peer %s not estab state",
2389 __func__, pi, pi->peer->host);
ddb5b488 2390
d62a17ae 2391 continue;
ddb5b488 2392 }
9fbdd100 2393
892fedb6 2394 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2395 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2396 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2397 if (debug)
40381db7 2398 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2399 continue;
2400 }
9fbdd100 2401
9bcb3eef 2402 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2403
9bcb3eef 2404 reason = dest->reason;
40381db7 2405 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2406 debug, pfx_buf, afi, safi,
2407 &dest->reason)) {
19ea4cec
DS
2408 if (new_select == NULL &&
2409 reason != bgp_path_selection_none)
9bcb3eef 2410 dest->reason = reason;
40381db7 2411 new_select = pi;
d62a17ae 2412 }
2413 }
718e3744 2414
d62a17ae 2415 /* Now that we know which path is the bestpath see if any of the other
2416 * paths
2417 * qualify as multipaths
2418 */
2419 if (debug) {
2420 if (new_select)
18ee8310
DS
2421 bgp_path_info_path_with_addpath_rx_str(new_select,
2422 path_buf);
d62a17ae 2423 else
772270f3 2424 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2425 zlog_debug(
8228a9a7
DS
2426 "%pBD: After path selection, newbest is %s oldbest was %s",
2427 dest, path_buf,
d62a17ae 2428 old_select ? old_select->peer->host : "NONE");
96450faf 2429 }
9fbdd100 2430
d62a17ae 2431 if (do_mpath && new_select) {
9bcb3eef 2432 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2433 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2434
2435 if (debug)
18ee8310 2436 bgp_path_info_path_with_addpath_rx_str(
40381db7 2437 pi, path_buf);
d62a17ae 2438
40381db7 2439 if (pi == new_select) {
d62a17ae 2440 if (debug)
2441 zlog_debug(
8228a9a7
DS
2442 "%pBD: %s is the bestpath, add to the multipath list",
2443 dest, path_buf);
40381db7 2444 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2445 continue;
2446 }
2447
40381db7 2448 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2449 continue;
2450
40381db7
DS
2451 if (pi->peer && pi->peer != bgp->peer_self
2452 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2453 PEER_STATUS_NSF_WAIT))
40381db7 2454 if (pi->peer->status != Established)
d62a17ae 2455 continue;
2456
40381db7 2457 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2458 if (debug)
2459 zlog_debug(
8228a9a7
DS
2460 "%pBD: %s has the same nexthop as the bestpath, skip it",
2461 dest, path_buf);
d62a17ae 2462 continue;
2463 }
2464
40381db7 2465 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2466 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2467 &dest->reason);
d62a17ae 2468
2469 if (paths_eq) {
2470 if (debug)
2471 zlog_debug(
8228a9a7
DS
2472 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2473 dest, path_buf);
40381db7 2474 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2475 }
2476 }
2477 }
fee0f4c6 2478
9bcb3eef 2479 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2480 mpath_cfg);
2481 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2482 bgp_mp_list_clear(&mp_list);
96450faf 2483
9bcb3eef 2484 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2485
d62a17ae 2486 result->old = old_select;
2487 result->new = new_select;
96450faf 2488
d62a17ae 2489 return;
fee0f4c6 2490}
2491
3f9c7369
DS
2492/*
2493 * A new route/change in bestpath of an existing route. Evaluate the path
2494 * for advertisement to the subgroup.
2495 */
3dc339cd
DA
2496void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2497 struct bgp_path_info *selected,
9bcb3eef 2498 struct bgp_dest *dest,
3dc339cd 2499 uint32_t addpath_tx_id)
d62a17ae 2500{
b54892e0 2501 const struct prefix *p;
d62a17ae 2502 struct peer *onlypeer;
2503 struct attr attr;
2504 afi_t afi;
2505 safi_t safi;
a77e2f4b
S
2506 struct bgp *bgp;
2507 bool advertise;
adbac85e 2508
9bcb3eef 2509 p = bgp_dest_get_prefix(dest);
d62a17ae 2510 afi = SUBGRP_AFI(subgrp);
2511 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2512 bgp = SUBGRP_INST(subgrp);
d62a17ae 2513 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2514 : NULL);
2515
2dbe669b
DA
2516 if (BGP_DEBUG(update, UPDATE_OUT))
2517 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2518
d62a17ae 2519 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2520 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2521 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2522 return;
d62a17ae 2523
2524 memset(&attr, 0, sizeof(struct attr));
2525 /* It's initialized in bgp_announce_check() */
2526
a77e2f4b
S
2527 /* Announcement to the subgroup. If the route is filtered withdraw it.
2528 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2529 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2530 * route
d62a17ae 2531 */
a77e2f4b
S
2532 advertise = bgp_check_advertise(bgp, dest);
2533
d62a17ae 2534 if (selected) {
7f7940e6 2535 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2536 false)) {
2537 /* Route is selected, if the route is already installed
2538 * in FIB, then it is advertised
2539 */
2540 if (advertise)
2541 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2542 selected);
2543 } else
9bcb3eef 2544 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2545 addpath_tx_id);
d62a17ae 2546 }
2547
2548 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2549 else {
9bcb3eef 2550 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2551 }
200df115 2552}
fee0f4c6 2553
3064bf43 2554/*
e1072051 2555 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2556 * This is called at the end of route processing.
3064bf43 2557 */
9bcb3eef 2558void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2559{
40381db7 2560 struct bgp_path_info *pi;
3064bf43 2561
9bcb3eef 2562 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2563 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2564 continue;
40381db7
DS
2565 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2566 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2567 }
3064bf43 2568}
2569
2570/*
2571 * Has the route changed from the RIB's perspective? This is invoked only
2572 * if the route selection returns the same best route as earlier - to
2573 * determine if we need to update zebra or not.
2574 */
9bcb3eef 2575bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2576{
4b7e6066 2577 struct bgp_path_info *mpinfo;
d62a17ae 2578
2bb9eff4
DS
2579 /* If this is multipath, check all selected paths for any nexthop
2580 * change or attribute change. Some attribute changes (e.g., community)
2581 * aren't of relevance to the RIB, but we'll update zebra to ensure
2582 * we handle the case of BGP nexthop change. This is the behavior
2583 * when the best path has an attribute change anyway.
d62a17ae 2584 */
1defdda8 2585 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2586 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2587 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2588 return true;
d62a17ae 2589
2bb9eff4
DS
2590 /*
2591 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2592 */
18ee8310
DS
2593 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2594 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2595 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2596 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2597 return true;
d62a17ae 2598 }
3064bf43 2599
d62a17ae 2600 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2601 return false;
3064bf43 2602}
2603
d62a17ae 2604struct bgp_process_queue {
2605 struct bgp *bgp;
9bcb3eef 2606 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2607#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2608 unsigned int flags;
2609 unsigned int queued;
200df115 2610};
2611
3b0c17e1 2612static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2613 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2614 struct bgp_path_info *new_select,
2615 struct bgp_path_info *old_select)
2616{
9bcb3eef 2617 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2618
2619 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2620 return;
2621
2622 if (advertise_type5_routes(bgp, afi) && new_select
2623 && is_route_injectable_into_evpn(new_select)) {
2624
2625 /* apply the route-map */
2626 if (bgp->adv_cmd_rmap[afi][safi].map) {
2627 route_map_result_t ret;
2628 struct bgp_path_info rmap_path;
2629 struct bgp_path_info_extra rmap_path_extra;
2630 struct attr dummy_attr;
2631
2632 dummy_attr = *new_select->attr;
2633
2634 /* Fill temp path_info */
9bcb3eef 2635 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2636 new_select, new_select->peer,
2637 &dummy_attr);
2638
2639 RESET_FLAG(dummy_attr.rmap_change_flags);
2640
2641 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2642 p, &rmap_path);
3b0c17e1 2643
2644 if (ret == RMAP_DENYMATCH) {
2645 bgp_attr_flush(&dummy_attr);
2646 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2647 safi);
2648 } else
2649 bgp_evpn_advertise_type5_route(
2650 bgp, p, &dummy_attr, afi, safi);
2651 } else {
2652 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2653 afi, safi);
2654 }
2655 } else if (advertise_type5_routes(bgp, afi) && old_select
2656 && is_route_injectable_into_evpn(old_select))
2657 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2658}
2659
3103e8d2
DS
2660/*
2661 * old_select = The old best path
2662 * new_select = the new best path
2663 *
2664 * if (!old_select && new_select)
2665 * We are sending new information on.
2666 *
2667 * if (old_select && new_select) {
2668 * if (new_select != old_select)
2669 * We have a new best path send a change
2670 * else
2671 * We've received a update with new attributes that needs
2672 * to be passed on.
2673 * }
2674 *
2675 * if (old_select && !new_select)
2676 * We have no eligible route that we can announce or the rn
2677 * is being removed.
2678 */
9bcb3eef 2679static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2680 afi_t afi, safi_t safi)
d62a17ae 2681{
4b7e6066
DS
2682 struct bgp_path_info *new_select;
2683 struct bgp_path_info *old_select;
2684 struct bgp_path_info_pair old_and_new;
ddb5b488 2685 int debug = 0;
d62a17ae 2686
892fedb6 2687 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2688 if (dest)
2689 debug = bgp_debug_bestpath(dest);
b54892e0 2690 if (debug)
f4c713ae 2691 zlog_debug(
56ca3b5b 2692 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2693 __func__, dest);
f4c713ae
LB
2694 return;
2695 }
d62a17ae 2696 /* Is it end of initial update? (after startup) */
9bcb3eef 2697 if (!dest) {
d62a17ae 2698 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2699 sizeof(bgp->update_delay_zebra_resume_time));
2700
2701 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2702 FOREACH_AFI_SAFI (afi, safi) {
2703 if (bgp_fibupd_safi(safi))
2704 bgp_zebra_announce_table(bgp, afi, safi);
2705 }
d62a17ae 2706 bgp->main_peers_update_hold = 0;
2707
2708 bgp_start_routeadv(bgp);
aac24838 2709 return;
d62a17ae 2710 }
cb1faec9 2711
9bcb3eef 2712 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2713
9bcb3eef 2714 debug = bgp_debug_bestpath(dest);
b54892e0 2715 if (debug)
56ca3b5b 2716 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2717 afi2str(afi), safi2str(safi));
ddb5b488 2718
f009ff26 2719 /* The best path calculation for the route is deferred if
2720 * BGP_NODE_SELECT_DEFER is set
2721 */
9bcb3eef 2722 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2723 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2724 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2725 return;
2726 }
2727
d62a17ae 2728 /* Best path selection. */
9bcb3eef 2729 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2730 afi, safi);
2731 old_select = old_and_new.old;
2732 new_select = old_and_new.new;
2733
2734 /* Do we need to allocate or free labels?
2735 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2736 * necessary to do this upon changes to best path. Exceptions:
2737 * - label index has changed -> recalculate resulting label
2738 * - path_info sub_type changed -> switch to/from implicit-null
2739 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2740 */
318cac96 2741 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2742 if (new_select) {
2743 if (!old_select
2744 || bgp_label_index_differs(new_select, old_select)
57592a53 2745 || new_select->sub_type != old_select->sub_type
9bcb3eef 2746 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2747 /* Enforced penultimate hop popping:
2748 * implicit-null for local routes, aggregate
2749 * and redistributed routes
2750 */
d62a17ae 2751 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2752 || new_select->sub_type
2753 == BGP_ROUTE_AGGREGATE
2754 || new_select->sub_type
2755 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2756 if (CHECK_FLAG(
9bcb3eef 2757 dest->flags,
992dd67e
PR
2758 BGP_NODE_REGISTERED_FOR_LABEL)
2759 || CHECK_FLAG(
2760 dest->flags,
2761 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2762 bgp_unregister_for_label(dest);
70e98a7f 2763 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2764 &dest->local_label);
2765 bgp_set_valid_label(&dest->local_label);
d62a17ae 2766 } else
9bcb3eef
DS
2767 bgp_register_for_label(dest,
2768 new_select);
d62a17ae 2769 }
9bcb3eef 2770 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2771 BGP_NODE_REGISTERED_FOR_LABEL)
2772 || CHECK_FLAG(dest->flags,
2773 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2774 bgp_unregister_for_label(dest);
318cac96 2775 }
992dd67e
PR
2776 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2777 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2778 bgp_unregister_for_label(dest);
d62a17ae 2779 }
cd1964ff 2780
b54892e0 2781 if (debug)
ddb5b488 2782 zlog_debug(
56ca3b5b 2783 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2784 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2785 old_select, new_select);
ddb5b488 2786
d62a17ae 2787 /* If best route remains the same and this is not due to user-initiated
2788 * clear, see exactly what needs to be done.
2789 */
d62a17ae 2790 if (old_select && old_select == new_select
9bcb3eef 2791 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2792 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2793 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2794 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2795#ifdef ENABLE_BGP_VNC
d62a17ae 2796 vnc_import_bgp_add_route(bgp, p, old_select);
2797 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2798#endif
bb744275 2799 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2800 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2801
2802 if (new_select->type == ZEBRA_ROUTE_BGP
2803 && (new_select->sub_type == BGP_ROUTE_NORMAL
2804 || new_select->sub_type
2805 == BGP_ROUTE_IMPORTED))
2806
9bcb3eef 2807 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2808 bgp, afi, safi);
2809 }
d62a17ae 2810 }
d62a17ae 2811
2812 /* If there is a change of interest to peers, reannounce the
2813 * route. */
1defdda8 2814 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2815 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2816 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2817 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2818
2819 /* unicast routes must also be annouced to
2820 * labeled-unicast update-groups */
2821 if (safi == SAFI_UNICAST)
2822 group_announce_route(bgp, afi,
9bcb3eef 2823 SAFI_LABELED_UNICAST, dest,
d62a17ae 2824 new_select);
2825
1defdda8 2826 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2827 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2828 }
fee0f4c6 2829
3b0c17e1 2830 /* advertise/withdraw type-5 routes */
2831 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2832 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2833 bgp_process_evpn_route_injection(
9bcb3eef 2834 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2835
b1875e65 2836 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2837 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2838 bgp_zebra_clear_route_change_flags(dest);
2839 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2840 return;
d62a17ae 2841 }
8ad7271d 2842
d62a17ae 2843 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2844 */
9bcb3eef 2845 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2846
2847 /* bestpath has changed; bump version */
2848 if (old_select || new_select) {
9bcb3eef 2849 bgp_bump_version(dest);
d62a17ae 2850
2851 if (!bgp->t_rmap_def_originate_eval) {
2852 bgp_lock(bgp);
2853 thread_add_timer(
2854 bm->master,
2855 update_group_refresh_default_originate_route_map,
2856 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2857 &bgp->t_rmap_def_originate_eval);
2858 }
2859 }
3f9c7369 2860
d62a17ae 2861 if (old_select)
9bcb3eef 2862 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2863 if (new_select) {
ddb5b488
PZ
2864 if (debug)
2865 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2866 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2867 bgp_path_info_unset_flag(dest, new_select,
2868 BGP_PATH_ATTR_CHANGED);
1defdda8 2869 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2870 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2871 }
338b3424 2872
49e5a4a0 2873#ifdef ENABLE_BGP_VNC
d62a17ae 2874 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2875 if (old_select != new_select) {
2876 if (old_select) {
2877 vnc_import_bgp_exterior_del_route(bgp, p,
2878 old_select);
2879 vnc_import_bgp_del_route(bgp, p, old_select);
2880 }
2881 if (new_select) {
2882 vnc_import_bgp_exterior_add_route(bgp, p,
2883 new_select);
2884 vnc_import_bgp_add_route(bgp, p, new_select);
2885 }
2886 }
2887 }
65efcfce
LB
2888#endif
2889
9bcb3eef 2890 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2891
2892 /* unicast routes must also be annouced to labeled-unicast update-groups
2893 */
2894 if (safi == SAFI_UNICAST)
9bcb3eef 2895 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2896 new_select);
2897
2898 /* FIB update. */
2899 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2900 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2901 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2902 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2903 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2904 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2905
2906 /* if this is an evpn imported type-5 prefix,
2907 * we need to withdraw the route first to clear
2908 * the nh neigh and the RMAC entry.
2909 */
2910 if (old_select &&
2911 is_route_parent_evpn(old_select))
2912 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2913
9bcb3eef 2914 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2915 } else {
d62a17ae 2916 /* Withdraw the route from the kernel. */
2917 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2918 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2919 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2920 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2921
568e10ca 2922 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2923 }
718e3744 2924 }
3064bf43 2925
9bcb3eef 2926 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2927 old_select);
5424b7ba 2928
d62a17ae 2929 /* Clear any route change flags. */
9bcb3eef 2930 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2931
18ee8310 2932 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2933 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2934 bgp_path_info_reap(dest, old_select);
d62a17ae 2935
9bcb3eef 2936 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2937 return;
718e3744 2938}
2939
f009ff26 2940/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2941int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2942{
9bcb3eef 2943 struct bgp_dest *dest;
f009ff26 2944 int cnt = 0;
2945 struct afi_safi_info *thread_info;
f009ff26 2946
56c226e7
DS
2947 if (bgp->gr_info[afi][safi].t_route_select) {
2948 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2949
2950 thread_info = THREAD_ARG(t);
2951 XFREE(MTYPE_TMP, thread_info);
f009ff26 2952 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2953 }
f009ff26 2954
2955 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2956 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2957 get_afi_safi_str(afi, safi, false),
26742171 2958 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2959 }
2960
2961 /* Process the route list */
6338d242
DS
2962 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2963 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2964 dest = bgp_route_next(dest)) {
2965 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2966 continue;
2967
2968 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2969 bgp->gr_info[afi][safi].gr_deferred--;
2970 bgp_process_main_one(bgp, dest, afi, safi);
2971 cnt++;
2972 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2973 bgp_dest_unlock_node(dest);
2974 break;
f009ff26 2975 }
f009ff26 2976 }
2977
9e3b51a7 2978 /* Send EOR message when all routes are processed */
6338d242 2979 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2980 bgp_send_delayed_eor(bgp);
8c48b3b6 2981 /* Send route processing complete message to RIB */
2982 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2983 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2984 return 0;
9e3b51a7 2985 }
f009ff26 2986
2987 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2988
2989 thread_info->afi = afi;
2990 thread_info->safi = safi;
2991 thread_info->bgp = bgp;
2992
2993 /* If there are more routes to be processed, start the
2994 * selection timer
2995 */
2996 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2997 BGP_ROUTE_SELECT_DELAY,
2998 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2999 return 0;
3000}
3001
aac24838 3002static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3003{
aac24838
JB
3004 struct bgp_process_queue *pqnode = data;
3005 struct bgp *bgp = pqnode->bgp;
d62a17ae 3006 struct bgp_table *table;
9bcb3eef 3007 struct bgp_dest *dest;
aac24838
JB
3008
3009 /* eoiu marker */
3010 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3011 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3012 /* should always have dedicated wq call */
3013 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3014 return WQ_SUCCESS;
3015 }
3016
ac021f40 3017 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3018 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3019 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3020 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3021 table = bgp_dest_table(dest);
3022 /* note, new DESTs may be added as part of processing */
3023 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3024
9bcb3eef 3025 bgp_dest_unlock_node(dest);
d62a17ae 3026 bgp_table_unlock(table);
3027 }
aac24838
JB
3028
3029 return WQ_SUCCESS;
3030}
3031
3032static void bgp_processq_del(struct work_queue *wq, void *data)
3033{
3034 struct bgp_process_queue *pqnode = data;
3035
3036 bgp_unlock(pqnode->bgp);
3037
3038 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3039}
3040
b6c386bb 3041void bgp_process_queue_init(struct bgp *bgp)
200df115 3042{
b6c386bb
DS
3043 if (!bgp->process_queue) {
3044 char name[BUFSIZ];
3045
3046 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3047 bgp->process_queue = work_queue_new(bm->master, name);
3048 }
3049
3050 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3051 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3052 bgp->process_queue->spec.max_retries = 0;
3053 bgp->process_queue->spec.hold = 50;
d62a17ae 3054 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3055 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3056}
3057
cfe8d15a 3058static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3059{
3060 struct bgp_process_queue *pqnode;
3061
a4d82a8a
PZ
3062 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3063 sizeof(struct bgp_process_queue));
aac24838
JB
3064
3065 /* unlocked in bgp_processq_del */
3066 pqnode->bgp = bgp_lock(bgp);
3067 STAILQ_INIT(&pqnode->pqueue);
3068
aac24838
JB
3069 return pqnode;
3070}
3071
9bcb3eef 3072void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3073{
aac24838 3074#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3075 struct work_queue *wq = bgp->process_queue;
d62a17ae 3076 struct bgp_process_queue *pqnode;
cfe8d15a 3077 int pqnode_reuse = 0;
495f0b13 3078
d62a17ae 3079 /* already scheduled for processing? */
9bcb3eef 3080 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3081 return;
2e02b9b2 3082
f009ff26 3083 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3084 * the workqueue
3085 */
9bcb3eef 3086 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3087 if (BGP_DEBUG(update, UPDATE_OUT))
3088 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3089 dest);
f009ff26 3090 return;
3091 }
3092
aac24838 3093 if (wq == NULL)
d62a17ae 3094 return;
3095
aac24838 3096 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3097 limit only if is from the same BGP view and it's not an EOIU marker
3098 */
aac24838
JB
3099 if (work_queue_item_count(wq)) {
3100 struct work_queue_item *item = work_queue_last_item(wq);
3101 pqnode = item->data;
228da428 3102
a4d82a8a
PZ
3103 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3104 || pqnode->bgp != bgp
3105 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3106 pqnode = bgp_processq_alloc(bgp);
3107 else
3108 pqnode_reuse = 1;
aac24838 3109 } else
cfe8d15a 3110 pqnode = bgp_processq_alloc(bgp);
aac24838 3111 /* all unlocked in bgp_process_wq */
9bcb3eef 3112 bgp_table_lock(bgp_dest_table(dest));
aac24838 3113
9bcb3eef
DS
3114 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3115 bgp_dest_lock_node(dest);
aac24838 3116
60466a63 3117 /* can't be enqueued twice */
9bcb3eef
DS
3118 assert(STAILQ_NEXT(dest, pq) == NULL);
3119 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3120 pqnode->queued++;
3121
cfe8d15a
LB
3122 if (!pqnode_reuse)
3123 work_queue_add(wq, pqnode);
3124
d62a17ae 3125 return;
fee0f4c6 3126}
0a486e5f 3127
d62a17ae 3128void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3129{
d62a17ae 3130 struct bgp_process_queue *pqnode;
cb1faec9 3131
b6c386bb 3132 if (bgp->process_queue == NULL)
d62a17ae 3133 return;
2e02b9b2 3134
cfe8d15a 3135 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3136
aac24838 3137 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3138 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3139}
3140
d62a17ae 3141static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3142{
d62a17ae 3143 struct peer *peer;
0a486e5f 3144
d62a17ae 3145 peer = THREAD_ARG(thread);
3146 peer->t_pmax_restart = NULL;
0a486e5f 3147
d62a17ae 3148 if (bgp_debug_neighbor_events(peer))
3149 zlog_debug(
3150 "%s Maximum-prefix restart timer expired, restore peering",
3151 peer->host);
0a486e5f 3152
a9bafa95 3153 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3154 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3155
d62a17ae 3156 return 0;
0a486e5f 3157}
3158
9cbd06e0
DA
3159static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3160 safi_t safi)
3161{
3162 uint32_t count = 0;
f41b0459 3163 bool filtered = false;
9cbd06e0
DA
3164 struct bgp_dest *dest;
3165 struct bgp_adj_in *ain;
40bb2ccf 3166 struct attr attr = {};
9cbd06e0
DA
3167 struct bgp_table *table = peer->bgp->rib[afi][safi];
3168
3169 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3170 for (ain = dest->adj_in; ain; ain = ain->next) {
3171 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3172
3173 attr = *ain->attr;
9cbd06e0
DA
3174
3175 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3176 == FILTER_DENY)
f41b0459
DA
3177 filtered = true;
3178
3179 if (bgp_input_modifier(
3180 peer, rn_p, &attr, afi, safi,
3181 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3182 NULL, 0, NULL)
3183 == RMAP_DENY)
3184 filtered = true;
3185
3186 if (filtered)
9cbd06e0 3187 count++;
f41b0459
DA
3188
3189 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3190 }
3191 }
3192
3193 return count;
3194}
3195
3dc339cd
DA
3196bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3197 int always)
718e3744 3198{
d62a17ae 3199 iana_afi_t pkt_afi;
5c525538 3200 iana_safi_t pkt_safi;
9cbd06e0
DA
3201 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3202 PEER_FLAG_MAX_PREFIX_FORCE))
3203 ? bgp_filtered_routes_count(peer, afi, safi)
3204 + peer->pcount[afi][safi]
3205 : peer->pcount[afi][safi];
9cabb64b 3206
d62a17ae 3207 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3208 return false;
e0701b79 3209
9cbd06e0 3210 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3211 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3212 PEER_STATUS_PREFIX_LIMIT)
3213 && !always)
3dc339cd 3214 return false;
e0701b79 3215
d62a17ae 3216 zlog_info(
6cde4b45 3217 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3218 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3219 peer->pmax[afi][safi]);
d62a17ae 3220 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3221
3222 if (CHECK_FLAG(peer->af_flags[afi][safi],
3223 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3224 return false;
d62a17ae 3225
3226 /* Convert AFI, SAFI to values for packet. */
3227 pkt_afi = afi_int2iana(afi);
3228 pkt_safi = safi_int2iana(safi);
3229 {
d7c0a89a 3230 uint8_t ndata[7];
d62a17ae 3231
3232 ndata[0] = (pkt_afi >> 8);
3233 ndata[1] = pkt_afi;
3234 ndata[2] = pkt_safi;
3235 ndata[3] = (peer->pmax[afi][safi] >> 24);
3236 ndata[4] = (peer->pmax[afi][safi] >> 16);
3237 ndata[5] = (peer->pmax[afi][safi] >> 8);
3238 ndata[6] = (peer->pmax[afi][safi]);
3239
3240 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3241 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3242 BGP_NOTIFY_CEASE_MAX_PREFIX,
3243 ndata, 7);
3244 }
3245
3246 /* Dynamic peers will just close their connection. */
3247 if (peer_dynamic_neighbor(peer))
3dc339cd 3248 return true;
d62a17ae 3249
3250 /* restart timer start */
3251 if (peer->pmax_restart[afi][safi]) {
3252 peer->v_pmax_restart =
3253 peer->pmax_restart[afi][safi] * 60;
3254
3255 if (bgp_debug_neighbor_events(peer))
3256 zlog_debug(
3257 "%s Maximum-prefix restart timer started for %d secs",
3258 peer->host, peer->v_pmax_restart);
3259
3260 BGP_TIMER_ON(peer->t_pmax_restart,
3261 bgp_maximum_prefix_restart_timer,
3262 peer->v_pmax_restart);
3263 }
3264
3dc339cd 3265 return true;
d62a17ae 3266 } else
3267 UNSET_FLAG(peer->af_sflags[afi][safi],
3268 PEER_STATUS_PREFIX_LIMIT);
3269
b1823b69
DS
3270 if (pcount
3271 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3272 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3273 PEER_STATUS_PREFIX_THRESHOLD)
3274 && !always)
3dc339cd 3275 return false;
d62a17ae 3276
3277 zlog_info(
6cde4b45 3278 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3279 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3280 peer->pmax[afi][safi]);
d62a17ae 3281 SET_FLAG(peer->af_sflags[afi][safi],
3282 PEER_STATUS_PREFIX_THRESHOLD);
3283 } else
3284 UNSET_FLAG(peer->af_sflags[afi][safi],
3285 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3286 return false;
718e3744 3287}
3288
b40d939b 3289/* Unconditionally remove the route from the RIB, without taking
3290 * damping into consideration (eg, because the session went down)
3291 */
9bcb3eef 3292void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3293 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3294{
f009ff26 3295
3296 struct bgp *bgp = NULL;
3297 bool delete_route = false;
3298
9bcb3eef
DS
3299 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3300 safi);
d62a17ae 3301
f009ff26 3302 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3303 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3304
f009ff26 3305 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3306 * flag
3307 */
3308 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3309 delete_route = true;
9bcb3eef 3310 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3311 delete_route = true;
f009ff26 3312 if (delete_route) {
9bcb3eef
DS
3313 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3314 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3315 bgp = pi->peer->bgp;
26742171 3316 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3317 }
3318 }
3319 }
4a11bf2c 3320
9bcb3eef
DS
3321 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3322 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3323}
3324
9bcb3eef 3325static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3326 struct peer *peer, afi_t afi, safi_t safi,
3327 struct prefix_rd *prd)
3328{
9bcb3eef 3329 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3330
d62a17ae 3331 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3332 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3333 */
3334 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3335 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3336 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3337 == BGP_DAMP_SUPPRESSED) {
b54892e0 3338 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3339 safi);
3340 return;
3341 }
3342
49e5a4a0 3343#ifdef ENABLE_BGP_VNC
d62a17ae 3344 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3345 struct bgp_dest *pdest = NULL;
d62a17ae 3346 struct bgp_table *table = NULL;
3347
9bcb3eef
DS
3348 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3349 (struct prefix *)prd);
3350 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3351 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3352
3353 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3354 peer->bgp, prd, table, p, pi);
d62a17ae 3355 }
9bcb3eef 3356 bgp_dest_unlock_node(pdest);
d62a17ae 3357 }
3358 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3359 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3360
b54892e0
DS
3361 vnc_import_bgp_del_route(peer->bgp, p, pi);
3362 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3363 }
65efcfce 3364 }
d62a17ae 3365#endif
128ea8ab 3366
d62a17ae 3367 /* If this is an EVPN route, process for un-import. */
3368 if (safi == SAFI_EVPN)
b54892e0 3369 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3370
9bcb3eef 3371 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3372}
3373
4b7e6066
DS
3374struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3375 struct peer *peer, struct attr *attr,
9bcb3eef 3376 struct bgp_dest *dest)
fb018d25 3377{
4b7e6066 3378 struct bgp_path_info *new;
fb018d25 3379
d62a17ae 3380 /* Make new BGP info. */
4b7e6066 3381 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3382 new->type = type;
3383 new->instance = instance;
3384 new->sub_type = sub_type;
3385 new->peer = peer;
3386 new->attr = attr;
3387 new->uptime = bgp_clock();
9bcb3eef 3388 new->net = dest;
d62a17ae 3389 return new;
fb018d25
DS
3390}
3391
d62a17ae 3392static void overlay_index_update(struct attr *attr,
d62a17ae 3393 union gw_addr *gw_ip)
684a7227 3394{
d62a17ae 3395 if (!attr)
3396 return;
d62a17ae 3397 if (gw_ip == NULL) {
6c924775
DS
3398 struct bgp_route_evpn eo;
3399
3400 memset(&eo, 0, sizeof(eo));
3401 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3402 } else {
6c924775
DS
3403 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3404
3405 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3406 }
684a7227
PG
3407}
3408
40381db7 3409static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3410 union gw_addr *gw_ip)
3411{
6c924775
DS
3412 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3413 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3414 union {
0a50c248 3415 esi_t esi;
11ebf4ed
DS
3416 union gw_addr ip;
3417 } temp;
d62a17ae 3418
3419 if (afi != AFI_L2VPN)
3420 return true;
11ebf4ed 3421
6c924775 3422 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3423
3424 if (gw_ip == NULL) {
3425 memset(&temp, 0, sizeof(temp));
40381db7 3426 path_gw_ip_remote = &temp.ip;
11ebf4ed 3427 } else
40381db7 3428 path_gw_ip_remote = gw_ip;
11ebf4ed 3429
6c924775 3430 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3431}
3432
c265ee22 3433/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3434bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3435 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3436 struct bgp_dest *dest)
d62a17ae 3437{
2dbe3fa9 3438 bool ret = false;
b099a5c8
DA
3439 bool is_bgp_static_route =
3440 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3441 : false;
d62a17ae 3442
e8442016
DS
3443 /*
3444 * Only validated for unicast and multicast currently.
3445 * Also valid for EVPN where the nexthop is an IP address.
3446 * If we are a bgp static route being checked then there is
3447 * no need to check to see if the nexthop is martian as
3448 * that it should be ok.
3449 */
3450 if (is_bgp_static_route ||
3451 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3452 return false;
d62a17ae 3453
3454 /* If NEXT_HOP is present, validate it. */
3455 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3456 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3457 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3458 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3459 return true;
d62a17ae 3460 }
c265ee22 3461
d62a17ae 3462 /* If MP_NEXTHOP is present, validate it. */
3463 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3464 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3465 * it is not an IPv6 link-local address.
0355b41d
DA
3466 *
3467 * If we receive an UPDATE with nexthop length set to 32 bytes
3468 * we shouldn't discard an UPDATE if it's set to (::).
3469 * The link-local (2st) is validated along the code path later.
d62a17ae 3470 */
3471 if (attr->mp_nexthop_len) {
3472 switch (attr->mp_nexthop_len) {
3473 case BGP_ATTR_NHLEN_IPV4:
3474 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3475 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3476 || IPV4_CLASS_DE(
3477 ntohl(attr->mp_nexthop_global_in.s_addr))
3478 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3479 dest));
d62a17ae 3480 break;
3481
3482 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3483 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3484 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3485 &attr->mp_nexthop_global)
d62a17ae 3486 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3487 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3488 &attr->mp_nexthop_global)
3489 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3490 dest));
d62a17ae 3491 break;
0355b41d
DA
3492 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3493 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3494 || IN6_IS_ADDR_MULTICAST(
3495 &attr->mp_nexthop_global)
3496 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3497 dest));
0355b41d 3498 break;
d62a17ae 3499
3500 default:
3dc339cd 3501 ret = true;
d62a17ae 3502 break;
3503 }
3504 }
c265ee22 3505
d62a17ae 3506 return ret;
3507}
3508
5a1ae2c2 3509int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3510 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3511 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3512 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3513 struct bgp_route_evpn *evpn)
d62a17ae 3514{
3515 int ret;
3516 int aspath_loop_count = 0;
9bcb3eef 3517 struct bgp_dest *dest;
d62a17ae 3518 struct bgp *bgp;
3519 struct attr new_attr;
3520 struct attr *attr_new;
40381db7 3521 struct bgp_path_info *pi;
4b7e6066
DS
3522 struct bgp_path_info *new;
3523 struct bgp_path_info_extra *extra;
d62a17ae 3524 const char *reason;
3525 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3526 int connected = 0;
3527 int do_loop_check = 1;
3528 int has_valid_label = 0;
7c312383 3529 afi_t nh_afi;
949b0f24 3530 uint8_t pi_type = 0;
3531 uint8_t pi_sub_type = 0;
3532
c7bb4f00 3533 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3534 char pfxprint[PREFIX2STR_BUFFER];
3535
3536 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3537 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3538 afi, safi, attr);
6401252f
QY
3539 }
3540
49e5a4a0 3541#ifdef ENABLE_BGP_VNC
d62a17ae 3542 int vnc_implicit_withdraw = 0;
65efcfce 3543#endif
d62a17ae 3544 int same_attr = 0;
718e3744 3545
d62a17ae 3546 memset(&new_attr, 0, sizeof(struct attr));
3547 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3548 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3549
d62a17ae 3550 bgp = peer->bgp;
9bcb3eef 3551 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3552 /* TODO: Check to see if we can get rid of "is_valid_label" */
3553 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3554 has_valid_label = (num_labels > 0) ? 1 : 0;
3555 else
3556 has_valid_label = bgp_is_valid_label(label);
718e3744 3557
28f66de2
MS
3558 if (has_valid_label)
3559 assert(label != NULL);
3560
a77e2f4b
S
3561 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3562 * condition :
3563 * Suppress fib is enabled
3564 * BGP_OPT_NO_FIB is not enabled
3565 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3566 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3567 */
3568 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3569 (sub_type == BGP_ROUTE_NORMAL) &&
3570 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3571 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3572 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3573
d62a17ae 3574 /* When peer's soft reconfiguration enabled. Record input packet in
3575 Adj-RIBs-In. */
3576 if (!soft_reconfig
3577 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3578 && peer != bgp->peer_self)
9bcb3eef 3579 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3580
3581 /* Check previously received route. */
9bcb3eef 3582 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3583 if (pi->peer == peer && pi->type == type
3584 && pi->sub_type == sub_type
3585 && pi->addpath_rx_id == addpath_id)
d62a17ae 3586 break;
3587
3588 /* AS path local-as loop check. */
3589 if (peer->change_local_as) {
c4368918
DW
3590 if (peer->allowas_in[afi][safi])
3591 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3592 else if (!CHECK_FLAG(peer->flags,
3593 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3594 aspath_loop_count = 1;
3595
3596 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3597 > aspath_loop_count) {
b4d46cc9 3598 peer->stat_pfx_aspath_loop++;
9bcb3eef 3599 reason = "as-path contains our own AS A;";
d62a17ae 3600 goto filtered;
3601 }
718e3744 3602 }
718e3744 3603
d62a17ae 3604 /* If the peer is configured for "allowas-in origin" and the last ASN in
3605 * the
3606 * as-path is our ASN then we do not need to call aspath_loop_check
3607 */
3608 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3609 if (aspath_get_last_as(attr->aspath) == bgp->as)
3610 do_loop_check = 0;
3611
3612 /* AS path loop check. */
3613 if (do_loop_check) {
3614 if (aspath_loop_check(attr->aspath, bgp->as)
3615 > peer->allowas_in[afi][safi]
3616 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3617 && aspath_loop_check(attr->aspath, bgp->confed_id)
3618 > peer->allowas_in[afi][safi])) {
b4d46cc9 3619 peer->stat_pfx_aspath_loop++;
d62a17ae 3620 reason = "as-path contains our own AS;";
3621 goto filtered;
3622 }
3623 }
aac9ef6c 3624
d62a17ae 3625 /* Route reflector originator ID check. */
3626 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3627 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3628 peer->stat_pfx_originator_loop++;
d62a17ae 3629 reason = "originator is us;";
3630 goto filtered;
3631 }
718e3744 3632
d62a17ae 3633 /* Route reflector cluster ID check. */
3634 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3635 peer->stat_pfx_cluster_loop++;
d62a17ae 3636 reason = "reflected from the same cluster;";
3637 goto filtered;
3638 }
718e3744 3639
d62a17ae 3640 /* Apply incoming filter. */
3641 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3642 peer->stat_pfx_filter++;
d62a17ae 3643 reason = "filter;";
3644 goto filtered;
3645 }
718e3744 3646
a8b72dc6
DA
3647 /* RFC 8212 to prevent route leaks.
3648 * This specification intends to improve this situation by requiring the
3649 * explicit configuration of both BGP Import and Export Policies for any
3650 * External BGP (EBGP) session such as customers, peers, or
3651 * confederation boundaries for all enabled address families. Through
3652 * codification of the aforementioned requirement, operators will
3653 * benefit from consistent behavior across different BGP
3654 * implementations.
3655 */
1d3fdccf 3656 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3657 if (!bgp_inbound_policy_exists(peer,
3658 &peer->filter[afi][safi])) {
3659 reason = "inbound policy missing";
3660 goto filtered;
3661 }
3662
fb29348a
DA
3663 /* draft-ietf-idr-deprecate-as-set-confed-set
3664 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3665 * Eventually, This document (if approved) updates RFC 4271
3666 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3667 * and obsoletes RFC 6472.
3668 */
7f972cd8 3669 if (peer->bgp->reject_as_sets)
fb29348a
DA
3670 if (aspath_check_as_sets(attr->aspath)) {
3671 reason =
3672 "as-path contains AS_SET or AS_CONFED_SET type;";
3673 goto filtered;
3674 }
3675
6f4f49b2 3676 new_attr = *attr;
d62a17ae 3677
3678 /* Apply incoming route-map.
3679 * NB: new_attr may now contain newly allocated values from route-map
3680 * "set"
3681 * commands, so we need bgp_attr_flush in the error paths, until we
3682 * intern
3683 * the attr (which takes over the memory references) */
9bcb3eef
DS
3684 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3685 num_labels, dest)
3686 == RMAP_DENY) {
b4d46cc9 3687 peer->stat_pfx_filter++;
d62a17ae 3688 reason = "route-map;";
3689 bgp_attr_flush(&new_attr);
3690 goto filtered;
3691 }
718e3744 3692
05864da7 3693 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3694 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3695 /* remove from RIB previous entry */
3696 bgp_zebra_withdraw(p, pi, bgp, safi);
3697 }
3698
7f323236
DW
3699 if (peer->sort == BGP_PEER_EBGP) {
3700
a4d82a8a
PZ
3701 /* If we receive the graceful-shutdown community from an eBGP
3702 * peer we must lower local-preference */
3703 if (new_attr.community
3704 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3705 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3706 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3707
a4d82a8a
PZ
3708 /* If graceful-shutdown is configured then add the GSHUT
3709 * community to all paths received from eBGP peers */
637e5ba4 3710 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3711 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3712 }
3713
949b0f24 3714 if (pi) {
3715 pi_type = pi->type;
3716 pi_sub_type = pi->sub_type;
3717 }
3718
d62a17ae 3719 /* next hop check. */
a4d82a8a 3720 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3721 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3722 &new_attr, dest)) {
b4d46cc9 3723 peer->stat_pfx_nh_invalid++;
d62a17ae 3724 reason = "martian or self next-hop;";
3725 bgp_attr_flush(&new_attr);
3726 goto filtered;
3727 }
718e3744 3728
5c14a191 3729 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3730 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3731 reason = "self mac;";
3732 goto filtered;
3733 }
3734
1e9be514
QY
3735 /* Update Overlay Index */
3736 if (afi == AFI_L2VPN) {
3737 overlay_index_update(&new_attr,
3738 evpn == NULL ? NULL : &evpn->gw_ip);
3739 }
3740
d62a17ae 3741 attr_new = bgp_attr_intern(&new_attr);
3742
9cbd06e0
DA
3743 /* If maximum prefix count is configured and current prefix
3744 * count exeed it.
3745 */
3746 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3747 return -1;
3748
d62a17ae 3749 /* If the update is implicit withdraw. */
40381db7
DS
3750 if (pi) {
3751 pi->uptime = bgp_clock();
3752 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3753
9bcb3eef 3754 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3755
d62a17ae 3756 /* Same attribute comes in. */
40381db7
DS
3757 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3758 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3759 && (!has_valid_label
40381db7 3760 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3761 num_labels * sizeof(mpls_label_t))
d62a17ae 3762 == 0)
3763 && (overlay_index_equal(
0a50c248 3764 afi, pi,
d62a17ae 3765 evpn == NULL ? NULL : &evpn->gw_ip))) {
3766 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3767 BGP_CONFIG_DAMPENING)
3768 && peer->sort == BGP_PEER_EBGP
40381db7 3769 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3770 if (bgp_debug_update(peer, p, NULL, 1)) {
3771 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3772 afi, safi, prd, p, label,
3773 num_labels, addpath_id ? 1 : 0,
3774 addpath_id, pfx_buf,
3775 sizeof(pfx_buf));
d62a17ae 3776 zlog_debug("%s rcvd %s", peer->host,
3777 pfx_buf);
3778 }
3779
9bcb3eef 3780 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3781 != BGP_DAMP_SUPPRESSED) {
40381db7 3782 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3783 safi);
9bcb3eef 3784 bgp_process(bgp, dest, afi, safi);
d62a17ae 3785 }
3786 } else /* Duplicate - odd */
3787 {
3788 if (bgp_debug_update(peer, p, NULL, 1)) {
3789 if (!peer->rcvd_attr_printed) {
3790 zlog_debug(
3791 "%s rcvd UPDATE w/ attr: %s",
3792 peer->host,
3793 peer->rcvd_attr_str);
3794 peer->rcvd_attr_printed = 1;
3795 }
3796
3797 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3798 afi, safi, prd, p, label,
3799 num_labels, addpath_id ? 1 : 0,
3800 addpath_id, pfx_buf,
3801 sizeof(pfx_buf));
d62a17ae 3802 zlog_debug(
3803 "%s rcvd %s...duplicate ignored",
3804 peer->host, pfx_buf);
3805 }
3806
3807 /* graceful restart STALE flag unset. */
40381db7 3808 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3809 bgp_path_info_unset_flag(
9bcb3eef
DS
3810 dest, pi, BGP_PATH_STALE);
3811 bgp_dest_set_defer_flag(dest, false);
3812 bgp_process(bgp, dest, afi, safi);
d62a17ae 3813 }
3814 }
3815
9bcb3eef 3816 bgp_dest_unlock_node(dest);
d62a17ae 3817 bgp_attr_unintern(&attr_new);
3818
3819 return 0;
3820 }
718e3744 3821
d62a17ae 3822 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3823 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3824 if (bgp_debug_update(peer, p, NULL, 1)) {
3825 bgp_debug_rdpfxpath2str(
a4d82a8a 3826 afi, safi, prd, p, label, num_labels,
d62a17ae 3827 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3828 sizeof(pfx_buf));
3829 zlog_debug(
3830 "%s rcvd %s, flapped quicker than processing",
3831 peer->host, pfx_buf);
3832 }
3833
9bcb3eef 3834 bgp_path_info_restore(dest, pi);
d62a17ae 3835 }
718e3744 3836
d62a17ae 3837 /* Received Logging. */
3838 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3839 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3840 num_labels, addpath_id ? 1 : 0,
3841 addpath_id, pfx_buf,
3842 sizeof(pfx_buf));
d62a17ae 3843 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3844 }
718e3744 3845
d62a17ae 3846 /* graceful restart STALE flag unset. */
f009ff26 3847 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3848 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3849 bgp_dest_set_defer_flag(dest, false);
f009ff26 3850 }
d62a17ae 3851
3852 /* The attribute is changed. */
9bcb3eef 3853 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3854
3855 /* implicit withdraw, decrement aggregate and pcount here.
3856 * only if update is accepted, they'll increment below.
3857 */
40381db7 3858 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3859
3860 /* Update bgp route dampening information. */
3861 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3862 && peer->sort == BGP_PEER_EBGP) {
3863 /* This is implicit withdraw so we should update
3864 dampening
3865 information. */
40381db7 3866 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3867 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3868 }
49e5a4a0 3869#ifdef ENABLE_BGP_VNC
d62a17ae 3870 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3871 struct bgp_dest *pdest = NULL;
d62a17ae 3872 struct bgp_table *table = NULL;
3873
9bcb3eef
DS
3874 pdest = bgp_node_get(bgp->rib[afi][safi],
3875 (struct prefix *)prd);
3876 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3877 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3878
3879 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3880 bgp, prd, table, p, pi);
d62a17ae 3881 }
9bcb3eef 3882 bgp_dest_unlock_node(pdest);
d62a17ae 3883 }
3884 if ((afi == AFI_IP || afi == AFI_IP6)
3885 && (safi == SAFI_UNICAST)) {
40381db7 3886 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3887 /*
3888 * Implicit withdraw case.
3889 */
3890 ++vnc_implicit_withdraw;
40381db7
DS
3891 vnc_import_bgp_del_route(bgp, p, pi);
3892 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3893 }
3894 }
65efcfce 3895#endif
128ea8ab 3896
d62a17ae 3897 /* Special handling for EVPN update of an existing route. If the
3898 * extended community attribute has changed, we need to
3899 * un-import
3900 * the route using its existing extended community. It will be
3901 * subsequently processed for import with the new extended
3902 * community.
3903 */
6f8c9c11
PR
3904 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3905 && !same_attr) {
40381db7 3906 if ((pi->attr->flag
d62a17ae 3907 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3908 && (attr_new->flag
3909 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3910 int cmp;
3911
40381db7 3912 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3913 attr_new->ecommunity);
3914 if (!cmp) {
3915 if (bgp_debug_update(peer, p, NULL, 1))
3916 zlog_debug(
3917 "Change in EXT-COMM, existing %s new %s",
3918 ecommunity_str(
40381db7 3919 pi->attr->ecommunity),
d62a17ae 3920 ecommunity_str(
3921 attr_new->ecommunity));
6f8c9c11
PR
3922 if (safi == SAFI_EVPN)
3923 bgp_evpn_unimport_route(
3924 bgp, afi, safi, p, pi);
3925 else /* SAFI_MPLS_VPN */
3926 vpn_leak_to_vrf_withdraw(bgp,
3927 pi);
d62a17ae 3928 }
3929 }
3930 }
718e3744 3931
d62a17ae 3932 /* Update to new attribute. */
40381db7
DS
3933 bgp_attr_unintern(&pi->attr);
3934 pi->attr = attr_new;
d62a17ae 3935
3936 /* Update MPLS label */
3937 if (has_valid_label) {
40381db7 3938 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3939 if (extra->label != label) {
3940 memcpy(&extra->label, label,
dbd587da 3941 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3942 extra->num_labels = num_labels;
3943 }
b57ba6d2
MK
3944 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3945 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3946 }
718e3744 3947
e496b420
HS
3948 /* Update SRv6 SID */
3949 if (attr->srv6_l3vpn) {
3950 extra = bgp_path_info_extra_get(pi);
3951 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3952 sid_copy(&extra->sid[0],
3953 &attr->srv6_l3vpn->sid);
3954 extra->num_sids = 1;
3955 }
3956 } else if (attr->srv6_vpn) {
3957 extra = bgp_path_info_extra_get(pi);
3958 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3959 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3960 extra->num_sids = 1;
3961 }
3962 }
3963
49e5a4a0 3964#ifdef ENABLE_BGP_VNC
d62a17ae 3965 if ((afi == AFI_IP || afi == AFI_IP6)
3966 && (safi == SAFI_UNICAST)) {
3967 if (vnc_implicit_withdraw) {
3968 /*
3969 * Add back the route with its new attributes
3970 * (e.g., nexthop).
3971 * The route is still selected, until the route
3972 * selection
3973 * queued by bgp_process actually runs. We have
3974 * to make this
3975 * update to the VNC side immediately to avoid
3976 * racing against
3977 * configuration changes (e.g., route-map
3978 * changes) which
3979 * trigger re-importation of the entire RIB.
3980 */
40381db7
DS
3981 vnc_import_bgp_add_route(bgp, p, pi);
3982 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3983 }
3984 }
65efcfce
LB
3985#endif
3986
d62a17ae 3987 /* Update bgp route dampening information. */
3988 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3989 && peer->sort == BGP_PEER_EBGP) {
3990 /* Now we do normal update dampening. */
9bcb3eef 3991 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3992 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3993 bgp_dest_unlock_node(dest);
d62a17ae 3994 return 0;
3995 }
3996 }
128ea8ab 3997
d62a17ae 3998 /* Nexthop reachability check - for unicast and
3999 * labeled-unicast.. */
7c312383
AD
4000 if (((afi == AFI_IP || afi == AFI_IP6)
4001 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4002 || (safi == SAFI_EVPN &&
4003 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4004 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4005 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4006 && !CHECK_FLAG(peer->flags,
4007 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4008 && !CHECK_FLAG(bgp->flags,
4009 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4010 connected = 1;
4011 else
4012 connected = 0;
4013
960035b2
PZ
4014 struct bgp *bgp_nexthop = bgp;
4015
40381db7
DS
4016 if (pi->extra && pi->extra->bgp_orig)
4017 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4018
7c312383
AD
4019 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4020
4021 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4022 pi, NULL, connected)
a4d82a8a 4023 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4024 bgp_path_info_set_flag(dest, pi,
4025 BGP_PATH_VALID);
d62a17ae 4026 else {
4027 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4028 zlog_debug("%s(%pI4): NH unresolved",
4029 __func__,
4030 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4031 }
9bcb3eef 4032 bgp_path_info_unset_flag(dest, pi,
18ee8310 4033 BGP_PATH_VALID);
d62a17ae 4034 }
4035 } else
9bcb3eef 4036 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4037
49e5a4a0 4038#ifdef ENABLE_BGP_VNC
d62a17ae 4039 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4040 struct bgp_dest *pdest = NULL;
d62a17ae 4041 struct bgp_table *table = NULL;
4042
9bcb3eef
DS
4043 pdest = bgp_node_get(bgp->rib[afi][safi],
4044 (struct prefix *)prd);
4045 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4046 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4047
4048 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4049 bgp, prd, table, p, pi);
d62a17ae 4050 }
9bcb3eef 4051 bgp_dest_unlock_node(pdest);
d62a17ae 4052 }
4053#endif
718e3744 4054
d62a17ae 4055 /* If this is an EVPN route and some attribute has changed,
4056 * process
4057 * route for import. If the extended community has changed, we
4058 * would
4059 * have done the un-import earlier and the import would result
4060 * in the
4061 * route getting injected into appropriate L2 VNIs. If it is
4062 * just
4063 * some other attribute change, the import will result in
4064 * updating
4065 * the attributes for the route in the VNI(s).
4066 */
7c312383
AD
4067 if (safi == SAFI_EVPN && !same_attr &&
4068 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4069 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4070
4071 /* Process change. */
40381db7 4072 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4073
9bcb3eef
DS
4074 bgp_process(bgp, dest, afi, safi);
4075 bgp_dest_unlock_node(dest);
558d1fec 4076
ddb5b488
PZ
4077 if (SAFI_UNICAST == safi
4078 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4079 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4080
40381db7 4081 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4082 }
4083 if ((SAFI_MPLS_VPN == safi)
4084 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4085
40381db7 4086 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4087 }
4088
49e5a4a0 4089#ifdef ENABLE_BGP_VNC
d62a17ae 4090 if (SAFI_MPLS_VPN == safi) {
4091 mpls_label_t label_decoded = decode_label(label);
28070ee3 4092
d62a17ae 4093 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4094 type, sub_type, &label_decoded);
4095 }
4096 if (SAFI_ENCAP == safi) {
4097 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4098 type, sub_type, NULL);
4099 }
28070ee3
PZ
4100#endif
4101
d62a17ae 4102 return 0;
4103 } // End of implicit withdraw
718e3744 4104
d62a17ae 4105 /* Received Logging. */
4106 if (bgp_debug_update(peer, p, NULL, 1)) {
4107 if (!peer->rcvd_attr_printed) {
4108 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4109 peer->rcvd_attr_str);
4110 peer->rcvd_attr_printed = 1;
4111 }
718e3744 4112
a4d82a8a 4113 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4114 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4115 sizeof(pfx_buf));
4116 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4117 }
718e3744 4118
d62a17ae 4119 /* Make new BGP info. */
9bcb3eef 4120 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4121
d62a17ae 4122 /* Update MPLS label */
4123 if (has_valid_label) {
18ee8310 4124 extra = bgp_path_info_extra_get(new);
8ba71050 4125 if (extra->label != label) {
dbd587da
QY
4126 memcpy(&extra->label, label,
4127 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4128 extra->num_labels = num_labels;
4129 }
b57ba6d2
MK
4130 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4131 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4132 }
718e3744 4133
e496b420
HS
4134 /* Update SRv6 SID */
4135 if (safi == SAFI_MPLS_VPN) {
4136 extra = bgp_path_info_extra_get(new);
4137 if (attr->srv6_l3vpn) {
4138 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4139 extra->num_sids = 1;
4140 } else if (attr->srv6_vpn) {
4141 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4142 extra->num_sids = 1;
4143 }
4144 }
4145
d62a17ae 4146 /* Update Overlay Index */
4147 if (afi == AFI_L2VPN) {
4148 overlay_index_update(new->attr,
d62a17ae 4149 evpn == NULL ? NULL : &evpn->gw_ip);
4150 }
4151 /* Nexthop reachability check. */
7c312383
AD
4152 if (((afi == AFI_IP || afi == AFI_IP6)
4153 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4154 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4155 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4156 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4157 && !CHECK_FLAG(peer->flags,
4158 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4159 && !CHECK_FLAG(bgp->flags,
4160 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4161 connected = 1;
4162 else
4163 connected = 0;
4164
7c312383
AD
4165 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4166
4167 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4168 connected)
a4d82a8a 4169 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4170 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4171 else {
4172 if (BGP_DEBUG(nht, NHT)) {
4173 char buf1[INET6_ADDRSTRLEN];
4174 inet_ntop(AF_INET,
4175 (const void *)&attr_new->nexthop,
4176 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4177 zlog_debug("%s(%s): NH unresolved", __func__,
4178 buf1);
d62a17ae 4179 }
9bcb3eef 4180 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4181 }
4182 } else
9bcb3eef 4183 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4184
d62a17ae 4185 /* Addpath ID */
4186 new->addpath_rx_id = addpath_id;
4187
4188 /* Increment prefix */
4189 bgp_aggregate_increment(bgp, p, new, afi, safi);
4190
4191 /* Register new BGP information. */
9bcb3eef 4192 bgp_path_info_add(dest, new);
d62a17ae 4193
4194 /* route_node_get lock */
9bcb3eef 4195 bgp_dest_unlock_node(dest);
558d1fec 4196
49e5a4a0 4197#ifdef ENABLE_BGP_VNC
d62a17ae 4198 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4199 struct bgp_dest *pdest = NULL;
d62a17ae 4200 struct bgp_table *table = NULL;
4201
9bcb3eef
DS
4202 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4203 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4204 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4205
4206 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4207 bgp, prd, table, p, new);
4208 }
9bcb3eef 4209 bgp_dest_unlock_node(pdest);
d62a17ae 4210 }
65efcfce
LB
4211#endif
4212
d62a17ae 4213 /* If this is an EVPN route, process for import. */
7c312383 4214 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4215 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4216
9bcb3eef 4217 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4218
d62a17ae 4219 /* Process change. */
9bcb3eef 4220 bgp_process(bgp, dest, afi, safi);
718e3744 4221
ddb5b488
PZ
4222 if (SAFI_UNICAST == safi
4223 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4224 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4225 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4226 }
4227 if ((SAFI_MPLS_VPN == safi)
4228 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4229
4230 vpn_leak_to_vrf_update(bgp, new);
4231 }
49e5a4a0 4232#ifdef ENABLE_BGP_VNC
d62a17ae 4233 if (SAFI_MPLS_VPN == safi) {
4234 mpls_label_t label_decoded = decode_label(label);
28070ee3 4235
d62a17ae 4236 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4237 sub_type, &label_decoded);
4238 }
4239 if (SAFI_ENCAP == safi) {
4240 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4241 sub_type, NULL);
4242 }
28070ee3
PZ
4243#endif
4244
d62a17ae 4245 return 0;
718e3744 4246
d62a17ae 4247/* This BGP update is filtered. Log the reason then update BGP
4248 entry. */
4249filtered:
9bcb3eef 4250 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4251
d62a17ae 4252 if (bgp_debug_update(peer, p, NULL, 1)) {
4253 if (!peer->rcvd_attr_printed) {
4254 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4255 peer->rcvd_attr_str);
4256 peer->rcvd_attr_printed = 1;
4257 }
718e3744 4258
a4d82a8a 4259 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4260 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4261 sizeof(pfx_buf));
4262 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4263 peer->host, pfx_buf, reason);
4264 }
128ea8ab 4265
40381db7 4266 if (pi) {
d62a17ae 4267 /* If this is an EVPN route, un-import it as it is now filtered.
4268 */
4269 if (safi == SAFI_EVPN)
40381db7 4270 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4271
ddb5b488
PZ
4272 if (SAFI_UNICAST == safi
4273 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4274 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4275
40381db7 4276 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4277 }
4278 if ((SAFI_MPLS_VPN == safi)
4279 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4280
40381db7 4281 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4282 }
4283
9bcb3eef 4284 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4285 }
4286
9bcb3eef 4287 bgp_dest_unlock_node(dest);
558d1fec 4288
49e5a4a0 4289#ifdef ENABLE_BGP_VNC
d62a17ae 4290 /*
4291 * Filtered update is treated as an implicit withdrawal (see
4292 * bgp_rib_remove()
4293 * a few lines above)
4294 */
4295 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4296 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4297 0);
4298 }
97736e32
PZ
4299#endif
4300
d62a17ae 4301 return 0;
718e3744 4302}
4303
26a3ffd6 4304int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4305 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4306 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4307 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4308{
d62a17ae 4309 struct bgp *bgp;
4310 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4311 struct bgp_dest *dest;
40381db7 4312 struct bgp_path_info *pi;
718e3744 4313
49e5a4a0 4314#ifdef ENABLE_BGP_VNC
d62a17ae 4315 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4316 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4317 0);
4318 }
28070ee3
PZ
4319#endif
4320
d62a17ae 4321 bgp = peer->bgp;
4322
4323 /* Lookup node. */
9bcb3eef 4324 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4325
4326 /* If peer is soft reconfiguration enabled. Record input packet for
4327 * further calculation.
4328 *
4329 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4330 * routes that are filtered. This tanks out Quagga RS pretty badly due
4331 * to
4332 * the iteration over all RS clients.
4333 * Since we need to remove the entry from adj_in anyway, do that first
4334 * and
4335 * if there was no entry, we don't need to do anything more.
4336 */
4337 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4338 && peer != bgp->peer_self)
9bcb3eef 4339 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4340 peer->stat_pfx_dup_withdraw++;
4341
d62a17ae 4342 if (bgp_debug_update(peer, p, NULL, 1)) {
4343 bgp_debug_rdpfxpath2str(
a4d82a8a 4344 afi, safi, prd, p, label, num_labels,
d62a17ae 4345 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4346 sizeof(pfx_buf));
4347 zlog_debug(
4348 "%s withdrawing route %s not in adj-in",
4349 peer->host, pfx_buf);
4350 }
9bcb3eef 4351 bgp_dest_unlock_node(dest);
d62a17ae 4352 return 0;
4353 }
cd808e74 4354
d62a17ae 4355 /* Lookup withdrawn route. */
9bcb3eef 4356 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4357 if (pi->peer == peer && pi->type == type
4358 && pi->sub_type == sub_type
4359 && pi->addpath_rx_id == addpath_id)
d62a17ae 4360 break;
4361
4362 /* Logging. */
4363 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4364 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4365 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4366 sizeof(pfx_buf));
4367 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4368 pfx_buf);
4369 }
718e3744 4370
d62a17ae 4371 /* Withdraw specified route from routing table. */
40381db7 4372 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4373 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4374 if (SAFI_UNICAST == safi
4375 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4376 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4377 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4378 }
4379 if ((SAFI_MPLS_VPN == safi)
4380 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4381
40381db7 4382 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4383 }
4384 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4385 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4386 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4387 sizeof(pfx_buf));
4388 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4389 }
718e3744 4390
d62a17ae 4391 /* Unlock bgp_node_get() lock. */
9bcb3eef 4392 bgp_dest_unlock_node(dest);
d62a17ae 4393
4394 return 0;
718e3744 4395}
6b0655a2 4396
d62a17ae 4397void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4398 int withdraw)
718e3744 4399{
d62a17ae 4400 struct update_subgroup *subgrp;
4401 subgrp = peer_subgroup(peer, afi, safi);
4402 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4403}
6182d65b 4404
718e3744 4405
3f9c7369
DS
4406/*
4407 * bgp_stop_announce_route_timer
4408 */
d62a17ae 4409void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4410{
d62a17ae 4411 if (!paf->t_announce_route)
4412 return;
4413
50478845 4414 thread_cancel(&paf->t_announce_route);
718e3744 4415}
6b0655a2 4416
3f9c7369
DS
4417/*
4418 * bgp_announce_route_timer_expired
4419 *
4420 * Callback that is invoked when the route announcement timer for a
4421 * peer_af expires.
4422 */
d62a17ae 4423static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4424{
d62a17ae 4425 struct peer_af *paf;
4426 struct peer *peer;
558d1fec 4427
d62a17ae 4428 paf = THREAD_ARG(t);
4429 peer = paf->peer;
718e3744 4430
d62a17ae 4431 if (peer->status != Established)
4432 return 0;
3f9c7369 4433
d62a17ae 4434 if (!peer->afc_nego[paf->afi][paf->safi])
4435 return 0;
3f9c7369 4436
d62a17ae 4437 peer_af_announce_route(paf, 1);
c5aec50b
MK
4438
4439 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4440 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4441
d62a17ae 4442 return 0;
718e3744 4443}
4444
3f9c7369
DS
4445/*
4446 * bgp_announce_route
4447 *
4448 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4449 */
d62a17ae 4450void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4451{
4452 struct peer_af *paf;
4453 struct update_subgroup *subgrp;
4454
4455 paf = peer_af_find(peer, afi, safi);
4456 if (!paf)
4457 return;
4458 subgrp = PAF_SUBGRP(paf);
4459
4460 /*
4461 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4462 * or a refresh has already been triggered.
4463 */
4464 if (!subgrp || paf->t_announce_route)
4465 return;
4466
4467 /*
4468 * Start a timer to stagger/delay the announce. This serves
4469 * two purposes - announcement can potentially be combined for
4470 * multiple peers and the announcement doesn't happen in the
4471 * vty context.
4472 */
4473 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4474 (subgrp->peer_count == 1)
4475 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4476 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4477 &paf->t_announce_route);
3f9c7369
DS
4478}
4479
4480/*
4481 * Announce routes from all AF tables to a peer.
4482 *
4483 * This should ONLY be called when there is a need to refresh the
4484 * routes to the peer based on a policy change for this peer alone
4485 * or a route refresh request received from the peer.
4486 * The operation will result in splitting the peer from its existing
4487 * subgroups and putting it in new subgroups.
4488 */
d62a17ae 4489void bgp_announce_route_all(struct peer *peer)
718e3744 4490{
d62a17ae 4491 afi_t afi;
4492 safi_t safi;
4493
05c7a1cc
QY
4494 FOREACH_AFI_SAFI (afi, safi)
4495 bgp_announce_route(peer, afi, safi);
718e3744 4496}
6b0655a2 4497
d62a17ae 4498static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4499 struct bgp_table *table,
4500 struct prefix_rd *prd)
718e3744 4501{
d62a17ae 4502 int ret;
9bcb3eef 4503 struct bgp_dest *dest;
d62a17ae 4504 struct bgp_adj_in *ain;
718e3744 4505
d62a17ae 4506 if (!table)
4507 table = peer->bgp->rib[afi][safi];
718e3744 4508
9bcb3eef
DS
4509 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4510 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4511 if (ain->peer != peer)
4512 continue;
8692c506 4513
d7d15889 4514 struct bgp_path_info *pi;
d7c0a89a 4515 uint32_t num_labels = 0;
b57ba6d2 4516 mpls_label_t *label_pnt = NULL;
8cb687c2 4517 struct bgp_route_evpn evpn;
b57ba6d2 4518
9bcb3eef 4519 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4520 pi = pi->next)
4521 if (pi->peer == peer)
4522 break;
4523
40381db7
DS
4524 if (pi && pi->extra)
4525 num_labels = pi->extra->num_labels;
b57ba6d2 4526 if (num_labels)
40381db7 4527 label_pnt = &pi->extra->label[0];
8cb687c2 4528 if (pi)
6c924775
DS
4529 memcpy(&evpn,
4530 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4531 sizeof(evpn));
4532 else
4533 memset(&evpn, 0, sizeof(evpn));
8692c506 4534
9bcb3eef
DS
4535 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4536 ain->addpath_rx_id, ain->attr, afi,
4537 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4538 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4539 num_labels, 1, &evpn);
ea47320b
DL
4540
4541 if (ret < 0) {
9bcb3eef 4542 bgp_dest_unlock_node(dest);
ea47320b 4543 return;
d62a17ae 4544 }
4545 }
718e3744 4546}
4547
d62a17ae 4548void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4549{
9bcb3eef 4550 struct bgp_dest *dest;
d62a17ae 4551 struct bgp_table *table;
718e3744 4552
d62a17ae 4553 if (peer->status != Established)
4554 return;
718e3744 4555
d62a17ae 4556 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4557 && (safi != SAFI_EVPN))
4558 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4559 else
9bcb3eef
DS
4560 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4561 dest = bgp_route_next(dest)) {
4562 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4563
b54892e0
DS
4564 if (table == NULL)
4565 continue;
8692c506 4566
9bcb3eef 4567 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4568 struct prefix_rd prd;
4569
4570 prd.family = AF_UNSPEC;
4571 prd.prefixlen = 64;
4572 memcpy(&prd.val, p->u.val, 8);
4573
4574 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4575 }
718e3744 4576}
6b0655a2 4577
228da428 4578
d62a17ae 4579struct bgp_clear_node_queue {
9bcb3eef 4580 struct bgp_dest *dest;
228da428
CC
4581};
4582
d62a17ae 4583static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4584{
d62a17ae 4585 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4586 struct bgp_dest *dest = cnq->dest;
d62a17ae 4587 struct peer *peer = wq->spec.data;
40381db7 4588 struct bgp_path_info *pi;
3103e8d2 4589 struct bgp *bgp;
9bcb3eef
DS
4590 afi_t afi = bgp_dest_table(dest)->afi;
4591 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4592
9bcb3eef 4593 assert(dest && peer);
3103e8d2 4594 bgp = peer->bgp;
d62a17ae 4595
4596 /* It is possible that we have multiple paths for a prefix from a peer
4597 * if that peer is using AddPath.
4598 */
9bcb3eef 4599 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4600 if (pi->peer != peer)
ea47320b
DL
4601 continue;
4602
4603 /* graceful restart STALE flag set. */
4604 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4605 && peer->nsf[afi][safi]
40381db7
DS
4606 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4607 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4608 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4609 else {
4610 /* If this is an EVPN route, process for
4611 * un-import. */
4612 if (safi == SAFI_EVPN)
9bcb3eef
DS
4613 bgp_evpn_unimport_route(
4614 bgp, afi, safi,
4615 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4616 /* Handle withdraw for VRF route-leaking and L3VPN */
4617 if (SAFI_UNICAST == safi
4618 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4619 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4620 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4621 bgp, pi);
960035b2 4622 }
3103e8d2 4623 if (SAFI_MPLS_VPN == safi &&
960035b2 4624 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4625 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4626 }
3103e8d2 4627
9bcb3eef 4628 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4629 }
ea47320b 4630 }
d62a17ae 4631 return WQ_SUCCESS;
200df115 4632}
4633
d62a17ae 4634static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4635{
d62a17ae 4636 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4637 struct bgp_dest *dest = cnq->dest;
4638 struct bgp_table *table = bgp_dest_table(dest);
228da428 4639
9bcb3eef 4640 bgp_dest_unlock_node(dest);
d62a17ae 4641 bgp_table_unlock(table);
4642 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4643}
4644
d62a17ae 4645static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4646{
d62a17ae 4647 struct peer *peer = wq->spec.data;
64e580a7 4648
d62a17ae 4649 /* Tickle FSM to start moving again */
4650 BGP_EVENT_ADD(peer, Clearing_Completed);
4651
4652 peer_unlock(peer); /* bgp_clear_route */
200df115 4653}
718e3744 4654
d62a17ae 4655static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4656{
d62a17ae 4657 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4658
4659 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4660#undef CLEAR_QUEUE_NAME_LEN
4661
0ce1ca80 4662 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4663 peer->clear_node_queue->spec.hold = 10;
4664 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4665 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4666 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4667 peer->clear_node_queue->spec.max_retries = 0;
4668
4669 /* we only 'lock' this peer reference when the queue is actually active
4670 */
4671 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4672}
4673
d62a17ae 4674static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4675 struct bgp_table *table)
65ca75e0 4676{
9bcb3eef 4677 struct bgp_dest *dest;
b6c386bb 4678 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4679
d62a17ae 4680 if (!table)
4681 table = peer->bgp->rib[afi][safi];
dc83d712 4682
d62a17ae 4683 /* If still no table => afi/safi isn't configured at all or smth. */
4684 if (!table)
4685 return;
dc83d712 4686
9bcb3eef 4687 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4688 struct bgp_path_info *pi, *next;
d62a17ae 4689 struct bgp_adj_in *ain;
4690 struct bgp_adj_in *ain_next;
4691
4692 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4693 * queued for every clearing peer, regardless of whether it is
4694 * relevant to the peer at hand.
4695 *
4696 * Overview: There are 3 different indices which need to be
4697 * scrubbed, potentially, when a peer is removed:
4698 *
4699 * 1 peer's routes visible via the RIB (ie accepted routes)
4700 * 2 peer's routes visible by the (optional) peer's adj-in index
4701 * 3 other routes visible by the peer's adj-out index
4702 *
4703 * 3 there is no hurry in scrubbing, once the struct peer is
4704 * removed from bgp->peer, we could just GC such deleted peer's
4705 * adj-outs at our leisure.
4706 *
4707 * 1 and 2 must be 'scrubbed' in some way, at least made
4708 * invisible via RIB index before peer session is allowed to be
4709 * brought back up. So one needs to know when such a 'search' is
4710 * complete.
4711 *
4712 * Ideally:
4713 *
4714 * - there'd be a single global queue or a single RIB walker
4715 * - rather than tracking which route_nodes still need to be
4716 * examined on a peer basis, we'd track which peers still
4717 * aren't cleared
4718 *
4719 * Given that our per-peer prefix-counts now should be reliable,
4720 * this may actually be achievable. It doesn't seem to be a huge
4721 * problem at this time,
4722 *
4723 * It is possible that we have multiple paths for a prefix from
4724 * a peer
4725 * if that peer is using AddPath.
4726 */
9bcb3eef 4727 ain = dest->adj_in;
d62a17ae 4728 while (ain) {
4729 ain_next = ain->next;
4730
4731 if (ain->peer == peer) {
9bcb3eef
DS
4732 bgp_adj_in_remove(dest, ain);
4733 bgp_dest_unlock_node(dest);
d62a17ae 4734 }
4735
4736 ain = ain_next;
4737 }
4738
9bcb3eef 4739 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4740 next = pi->next;
4741 if (pi->peer != peer)
d62a17ae 4742 continue;
4743
4744 if (force)
9bcb3eef 4745 bgp_path_info_reap(dest, pi);
d62a17ae 4746 else {
4747 struct bgp_clear_node_queue *cnq;
4748
4749 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4750 bgp_table_lock(bgp_dest_table(dest));
4751 bgp_dest_lock_node(dest);
d62a17ae 4752 cnq = XCALLOC(
4753 MTYPE_BGP_CLEAR_NODE_QUEUE,
4754 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4755 cnq->dest = dest;
d62a17ae 4756 work_queue_add(peer->clear_node_queue, cnq);
4757 break;
4758 }
4759 }
4760 }
4761 return;
4762}
4763
4764void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4765{
9bcb3eef 4766 struct bgp_dest *dest;
d62a17ae 4767 struct bgp_table *table;
4768
4769 if (peer->clear_node_queue == NULL)
4770 bgp_clear_node_queue_init(peer);
4771
4772 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4773 * Idle until it receives a Clearing_Completed event. This protects
4774 * against peers which flap faster than we can we clear, which could
4775 * lead to:
4776 *
4777 * a) race with routes from the new session being installed before
4778 * clear_route_node visits the node (to delete the route of that
4779 * peer)
4780 * b) resource exhaustion, clear_route_node likely leads to an entry
4781 * on the process_main queue. Fast-flapping could cause that queue
4782 * to grow and grow.
4783 */
4784
4785 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4786 * the unlock will happen upon work-queue completion; other wise, the
4787 * unlock happens at the end of this function.
4788 */
4789 if (!peer->clear_node_queue->thread)
4790 peer_lock(peer);
4791
4792 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4793 bgp_clear_route_table(peer, afi, safi, NULL);
4794 else
9bcb3eef
DS
4795 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4796 dest = bgp_route_next(dest)) {
4797 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4798 if (!table)
4799 continue;
4800
4801 bgp_clear_route_table(peer, afi, safi, table);
4802 }
d62a17ae 4803
4804 /* unlock if no nodes got added to the clear-node-queue. */
4805 if (!peer->clear_node_queue->thread)
4806 peer_unlock(peer);
718e3744 4807}
d62a17ae 4808
4809void bgp_clear_route_all(struct peer *peer)
718e3744 4810{
d62a17ae 4811 afi_t afi;
4812 safi_t safi;
718e3744 4813
05c7a1cc
QY
4814 FOREACH_AFI_SAFI (afi, safi)
4815 bgp_clear_route(peer, afi, safi);
65efcfce 4816
49e5a4a0 4817#ifdef ENABLE_BGP_VNC
d62a17ae 4818 rfapiProcessPeerDown(peer);
65efcfce 4819#endif
718e3744 4820}
4821
d62a17ae 4822void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4823{
d62a17ae 4824 struct bgp_table *table;
9bcb3eef 4825 struct bgp_dest *dest;
d62a17ae 4826 struct bgp_adj_in *ain;
4827 struct bgp_adj_in *ain_next;
718e3744 4828
d62a17ae 4829 table = peer->bgp->rib[afi][safi];
718e3744 4830
d62a17ae 4831 /* It is possible that we have multiple paths for a prefix from a peer
4832 * if that peer is using AddPath.
4833 */
9bcb3eef
DS
4834 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4835 ain = dest->adj_in;
43143c8f 4836
d62a17ae 4837 while (ain) {
4838 ain_next = ain->next;
43143c8f 4839
d62a17ae 4840 if (ain->peer == peer) {
9bcb3eef
DS
4841 bgp_adj_in_remove(dest, ain);
4842 bgp_dest_unlock_node(dest);
d62a17ae 4843 }
43143c8f 4844
d62a17ae 4845 ain = ain_next;
4846 }
4847 }
718e3744 4848}
93406d87 4849
d62a17ae 4850void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4851{
9bcb3eef 4852 struct bgp_dest *dest;
40381db7 4853 struct bgp_path_info *pi;
d62a17ae 4854 struct bgp_table *table;
4855
4856 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4857 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4858 dest = bgp_route_next(dest)) {
4859 struct bgp_dest *rm;
d62a17ae 4860
4861 /* look for neighbor in tables */
9bcb3eef 4862 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4863 if (!table)
ea47320b
DL
4864 continue;
4865
4866 for (rm = bgp_table_top(table); rm;
4867 rm = bgp_route_next(rm))
9bcb3eef 4868 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4869 pi = pi->next) {
40381db7 4870 if (pi->peer != peer)
ea47320b 4871 continue;
40381db7 4872 if (!CHECK_FLAG(pi->flags,
1defdda8 4873 BGP_PATH_STALE))
ea47320b
DL
4874 break;
4875
40381db7 4876 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4877 break;
4878 }
d62a17ae 4879 }
4880 } else {
9bcb3eef
DS
4881 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4882 dest = bgp_route_next(dest))
4883 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4884 pi = pi->next) {
40381db7 4885 if (pi->peer != peer)
ea47320b 4886 continue;
40381db7 4887 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4888 break;
9bcb3eef 4889 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4890 break;
4891 }
d62a17ae 4892 }
93406d87 4893}
6b0655a2 4894
3dc339cd 4895bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4896{
e0df4c04 4897 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4898 return true;
e0df4c04 4899
9dac9fc8
DA
4900 if (peer->sort == BGP_PEER_EBGP
4901 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4902 || FILTER_LIST_OUT_NAME(filter)
4903 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4904 return true;
4905 return false;
9dac9fc8
DA
4906}
4907
3dc339cd 4908bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4909{
e0df4c04 4910 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4911 return true;
e0df4c04 4912
9dac9fc8
DA
4913 if (peer->sort == BGP_PEER_EBGP
4914 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4915 || FILTER_LIST_IN_NAME(filter)
4916 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4917 return true;
4918 return false;
9dac9fc8
DA
4919}
4920
568e10ca 4921static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4922 safi_t safi)
bb86c601 4923{
9bcb3eef 4924 struct bgp_dest *dest;
40381db7 4925 struct bgp_path_info *pi;
4b7e6066 4926 struct bgp_path_info *next;
bb86c601 4927
9bcb3eef
DS
4928 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4929 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4930 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4931
40381db7 4932 next = pi->next;
1b7bb747
CS
4933
4934 /* Unimport EVPN routes from VRFs */
4935 if (safi == SAFI_EVPN)
4936 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4937 SAFI_EVPN, p, pi);
1b7bb747 4938
40381db7
DS
4939 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4940 && pi->type == ZEBRA_ROUTE_BGP
4941 && (pi->sub_type == BGP_ROUTE_NORMAL
4942 || pi->sub_type == BGP_ROUTE_AGGREGATE
4943 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4944
d62a17ae 4945 if (bgp_fibupd_safi(safi))
b54892e0 4946 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4947 }
9514b37d 4948
9bcb3eef 4949 bgp_path_info_reap(dest, pi);
d62a17ae 4950 }
bb86c601
LB
4951}
4952
718e3744 4953/* Delete all kernel routes. */
d62a17ae 4954void bgp_cleanup_routes(struct bgp *bgp)
4955{
4956 afi_t afi;
9bcb3eef 4957 struct bgp_dest *dest;
67009e22 4958 struct bgp_table *table;
d62a17ae 4959
4960 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4961 if (afi == AFI_L2VPN)
4962 continue;
568e10ca 4963 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4964 SAFI_UNICAST);
d62a17ae 4965 /*
4966 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4967 */
4968 if (afi != AFI_L2VPN) {
4969 safi_t safi;
4970 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4971 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4972 dest = bgp_route_next(dest)) {
4973 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4974 if (table != NULL) {
4975 bgp_cleanup_table(bgp, table, safi);
4976 bgp_table_finish(&table);
9bcb3eef
DS
4977 bgp_dest_set_bgp_table_info(dest, NULL);
4978 bgp_dest_unlock_node(dest);
d62a17ae 4979 }
4980 }
4981 safi = SAFI_ENCAP;
9bcb3eef
DS
4982 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4983 dest = bgp_route_next(dest)) {
4984 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4985 if (table != NULL) {
4986 bgp_cleanup_table(bgp, table, safi);
4987 bgp_table_finish(&table);
9bcb3eef
DS
4988 bgp_dest_set_bgp_table_info(dest, NULL);
4989 bgp_dest_unlock_node(dest);
d62a17ae 4990 }
4991 }
4992 }
4993 }
9bcb3eef
DS
4994 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4995 dest = bgp_route_next(dest)) {
4996 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4997 if (table != NULL) {
4998 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4999 bgp_table_finish(&table);
9bcb3eef
DS
5000 bgp_dest_set_bgp_table_info(dest, NULL);
5001 bgp_dest_unlock_node(dest);
d62a17ae 5002 }
bb86c601 5003 }
718e3744 5004}
5005
d62a17ae 5006void bgp_reset(void)
718e3744 5007{
d62a17ae 5008 vty_reset();
5009 bgp_zclient_reset();
5010 access_list_reset();
5011 prefix_list_reset();
718e3744 5012}
6b0655a2 5013
d62a17ae 5014static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5015{
d62a17ae 5016 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5017 && CHECK_FLAG(peer->af_cap[afi][safi],
5018 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5019}
5020
718e3744 5021/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5022 value. */
d62a17ae 5023int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5024 struct bgp_nlri *packet)
5025{
d7c0a89a
QY
5026 uint8_t *pnt;
5027 uint8_t *lim;
d62a17ae 5028 struct prefix p;
5029 int psize;
5030 int ret;
5031 afi_t afi;
5032 safi_t safi;
5033 int addpath_encoded;
d7c0a89a 5034 uint32_t addpath_id;
d62a17ae 5035
d62a17ae 5036 pnt = packet->nlri;
5037 lim = pnt + packet->length;
5038 afi = packet->afi;
5039 safi = packet->safi;
5040 addpath_id = 0;
5041 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5042
5043 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5044 syntactic validity. If the field is syntactically incorrect,
5045 then the Error Subcode is set to Invalid Network Field. */
5046 for (; pnt < lim; pnt += psize) {
5047 /* Clear prefix structure. */
5048 memset(&p, 0, sizeof(struct prefix));
5049
5050 if (addpath_encoded) {
5051
5052 /* When packet overflow occurs return immediately. */
761ed665 5053 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5054 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5055
a3a850a1 5056 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5057 addpath_id = ntohl(addpath_id);
d62a17ae 5058 pnt += BGP_ADDPATH_ID_LEN;
5059 }
718e3744 5060
d62a17ae 5061 /* Fetch prefix length. */
5062 p.prefixlen = *pnt++;
5063 /* afi/safi validity already verified by caller,
5064 * bgp_update_receive */
5065 p.family = afi2family(afi);
5066
5067 /* Prefix length check. */
5068 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5069 flog_err(
e50f7cfd 5070 EC_BGP_UPDATE_RCV,
14454c9f 5071 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5072 peer->host, p.prefixlen, packet->afi);
513386b5 5073 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5074 }
6b0655a2 5075
d62a17ae 5076 /* Packet size overflow check. */
5077 psize = PSIZE(p.prefixlen);
5078
5079 /* When packet overflow occur return immediately. */
5080 if (pnt + psize > lim) {
af4c2728 5081 flog_err(
e50f7cfd 5082 EC_BGP_UPDATE_RCV,
d62a17ae 5083 "%s [Error] Update packet error (prefix length %d overflows packet)",
5084 peer->host, p.prefixlen);
513386b5 5085 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5086 }
5087
5088 /* Defensive coding, double-check the psize fits in a struct
5089 * prefix */
5090 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5091 flog_err(
e50f7cfd 5092 EC_BGP_UPDATE_RCV,
d62a17ae 5093 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5094 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5095 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5096 }
5097
5098 /* Fetch prefix from NLRI packet. */
a85297a7 5099 memcpy(p.u.val, pnt, psize);
d62a17ae 5100
5101 /* Check address. */
5102 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5103 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5104 /* From RFC4271 Section 6.3:
5105 *
5106 * If a prefix in the NLRI field is semantically
5107 * incorrect
5108 * (e.g., an unexpected multicast IP address),
5109 * an error SHOULD
5110 * be logged locally, and the prefix SHOULD be
5111 * ignored.
a4d82a8a 5112 */
af4c2728 5113 flog_err(
e50f7cfd 5114 EC_BGP_UPDATE_RCV,
23d0a753
DA
5115 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5116 peer->host, &p.u.prefix4);
d62a17ae 5117 continue;
5118 }
5119 }
5120
5121 /* Check address. */
5122 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5123 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5124 char buf[BUFSIZ];
5125
af4c2728 5126 flog_err(
e50f7cfd 5127 EC_BGP_UPDATE_RCV,
d62a17ae 5128 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5129 peer->host,
5130 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5131 BUFSIZ));
5132
5133 continue;
5134 }
5135 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5136 char buf[BUFSIZ];
5137
af4c2728 5138 flog_err(
e50f7cfd 5139 EC_BGP_UPDATE_RCV,
d62a17ae 5140 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5141 peer->host,
5142 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5143 BUFSIZ));
5144
5145 continue;
5146 }
5147 }
5148
5149 /* Normal process. */
5150 if (attr)
5151 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5152 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5153 NULL, NULL, 0, 0, NULL);
d62a17ae 5154 else
5155 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5156 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5157 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5158 NULL);
d62a17ae 5159
513386b5
DA
5160 /* Do not send BGP notification twice when maximum-prefix count
5161 * overflow. */
5162 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5163 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5164
5165 /* Address family configuration mismatch. */
d62a17ae 5166 if (ret < 0)
513386b5 5167 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5168 }
5169
5170 /* Packet length consistency check. */
5171 if (pnt != lim) {
af4c2728 5172 flog_err(
e50f7cfd 5173 EC_BGP_UPDATE_RCV,
d62a17ae 5174 "%s [Error] Update packet error (prefix length mismatch with total length)",
5175 peer->host);
513386b5 5176 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5177 }
6b0655a2 5178
513386b5 5179 return BGP_NLRI_PARSE_OK;
718e3744 5180}
5181
d62a17ae 5182static struct bgp_static *bgp_static_new(void)
718e3744 5183{
d62a17ae 5184 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5185}
5186
d62a17ae 5187static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5188{
0a22ddfb 5189 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5190 route_map_counter_decrement(bgp_static->rmap.map);
5191
0a22ddfb 5192 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5193 XFREE(MTYPE_BGP_STATIC, bgp_static);
5194}
5195
5f040085 5196void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5197 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5198{
9bcb3eef 5199 struct bgp_dest *dest;
40381db7 5200 struct bgp_path_info *pi;
4b7e6066 5201 struct bgp_path_info *new;
40381db7 5202 struct bgp_path_info rmap_path;
d62a17ae 5203 struct attr attr;
5204 struct attr *attr_new;
b68885f9 5205 route_map_result_t ret;
49e5a4a0 5206#ifdef ENABLE_BGP_VNC
d62a17ae 5207 int vnc_implicit_withdraw = 0;
65efcfce 5208#endif
fee0f4c6 5209
d62a17ae 5210 assert(bgp_static);
dd8103a9 5211
9bcb3eef 5212 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5213
d62a17ae 5214 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5215
d62a17ae 5216 attr.nexthop = bgp_static->igpnexthop;
5217 attr.med = bgp_static->igpmetric;
5218 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5219
d62a17ae 5220 if (bgp_static->atomic)
5221 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5222
d62a17ae 5223 /* Store label index, if required. */
5224 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5225 attr.label_index = bgp_static->label_index;
5226 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5227 }
718e3744 5228
d62a17ae 5229 /* Apply route-map. */
5230 if (bgp_static->rmap.name) {
5231 struct attr attr_tmp = attr;
80ced710 5232
40381db7
DS
5233 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5234 rmap_path.peer = bgp->peer_self;
5235 rmap_path.attr = &attr_tmp;
fee0f4c6 5236
d62a17ae 5237 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5238
1782514f 5239 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5240
d62a17ae 5241 bgp->peer_self->rmap_type = 0;
718e3744 5242
d62a17ae 5243 if (ret == RMAP_DENYMATCH) {
5244 /* Free uninterned attribute. */
5245 bgp_attr_flush(&attr_tmp);
718e3744 5246
d62a17ae 5247 /* Unintern original. */
5248 aspath_unintern(&attr.aspath);
5249 bgp_static_withdraw(bgp, p, afi, safi);
5250 return;
5251 }
7f323236 5252
637e5ba4 5253 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5254 bgp_attr_add_gshut_community(&attr_tmp);
5255
d62a17ae 5256 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5257 } else {
5258
637e5ba4 5259 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5260 bgp_attr_add_gshut_community(&attr);
5261
d62a17ae 5262 attr_new = bgp_attr_intern(&attr);
7f323236 5263 }
718e3744 5264
9bcb3eef 5265 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5266 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5267 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5268 break;
5269
40381db7
DS
5270 if (pi) {
5271 if (attrhash_cmp(pi->attr, attr_new)
5272 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5273 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5274 bgp_dest_unlock_node(dest);
d62a17ae 5275 bgp_attr_unintern(&attr_new);
5276 aspath_unintern(&attr.aspath);
5277 return;
5278 } else {
5279 /* The attribute is changed. */
9bcb3eef 5280 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5281
5282 /* Rewrite BGP route information. */
40381db7 5283 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5284 bgp_path_info_restore(dest, pi);
d62a17ae 5285 else
40381db7 5286 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5287#ifdef ENABLE_BGP_VNC
d62a17ae 5288 if ((afi == AFI_IP || afi == AFI_IP6)
5289 && (safi == SAFI_UNICAST)) {
40381db7 5290 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5291 /*
5292 * Implicit withdraw case.
40381db7 5293 * We have to do this before pi is
d62a17ae 5294 * changed
5295 */
5296 ++vnc_implicit_withdraw;
40381db7 5297 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5298 vnc_import_bgp_exterior_del_route(
40381db7 5299 bgp, p, pi);
d62a17ae 5300 }
5301 }
65efcfce 5302#endif
40381db7
DS
5303 bgp_attr_unintern(&pi->attr);
5304 pi->attr = attr_new;
5305 pi->uptime = bgp_clock();
49e5a4a0 5306#ifdef ENABLE_BGP_VNC
d62a17ae 5307 if ((afi == AFI_IP || afi == AFI_IP6)
5308 && (safi == SAFI_UNICAST)) {
5309 if (vnc_implicit_withdraw) {
40381db7 5310 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5311 vnc_import_bgp_exterior_add_route(
40381db7 5312 bgp, p, pi);
d62a17ae 5313 }
5314 }
65efcfce 5315#endif
718e3744 5316
d62a17ae 5317 /* Nexthop reachability check. */
892fedb6 5318 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5319 && (safi == SAFI_UNICAST
5320 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5321
5322 struct bgp *bgp_nexthop = bgp;
5323
40381db7
DS
5324 if (pi->extra && pi->extra->bgp_orig)
5325 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5326
5327 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5328 afi, pi, NULL, 0))
9bcb3eef 5329 bgp_path_info_set_flag(dest, pi,
18ee8310 5330 BGP_PATH_VALID);
d62a17ae 5331 else {
5332 if (BGP_DEBUG(nht, NHT)) {
5333 char buf1[INET6_ADDRSTRLEN];
5334 inet_ntop(p->family,
5335 &p->u.prefix, buf1,
5336 INET6_ADDRSTRLEN);
5337 zlog_debug(
5338 "%s(%s): Route not in table, not advertising",
15569c58 5339 __func__, buf1);
d62a17ae 5340 }
18ee8310 5341 bgp_path_info_unset_flag(
9bcb3eef 5342 dest, pi, BGP_PATH_VALID);
d62a17ae 5343 }
5344 } else {
5345 /* Delete the NHT structure if any, if we're
5346 * toggling between
5347 * enabling/disabling import check. We
5348 * deregister the route
5349 * from NHT to avoid overloading NHT and the
5350 * process interaction
5351 */
40381db7 5352 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5353 bgp_path_info_set_flag(dest, pi,
5354 BGP_PATH_VALID);
d62a17ae 5355 }
5356 /* Process change. */
40381db7 5357 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5358 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5359
5360 if (SAFI_UNICAST == safi
5361 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5362 || bgp->inst_type
5363 == BGP_INSTANCE_TYPE_DEFAULT)) {
5364 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5365 pi);
ddb5b488
PZ
5366 }
5367
9bcb3eef 5368 bgp_dest_unlock_node(dest);
d62a17ae 5369 aspath_unintern(&attr.aspath);
5370 return;
5371 }
718e3744 5372 }
718e3744 5373
d62a17ae 5374 /* Make new BGP info. */
5375 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5376 attr_new, dest);
d62a17ae 5377 /* Nexthop reachability check. */
892fedb6 5378 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5379 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5380 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5381 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5382 else {
5383 if (BGP_DEBUG(nht, NHT)) {
5384 char buf1[INET6_ADDRSTRLEN];
5385 inet_ntop(p->family, &p->u.prefix, buf1,
5386 INET6_ADDRSTRLEN);
5387 zlog_debug(
5388 "%s(%s): Route not in table, not advertising",
15569c58 5389 __func__, buf1);
d62a17ae 5390 }
9bcb3eef 5391 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5392 }
5393 } else {
5394 /* Delete the NHT structure if any, if we're toggling between
5395 * enabling/disabling import check. We deregister the route
5396 * from NHT to avoid overloading NHT and the process interaction
5397 */
5398 bgp_unlink_nexthop(new);
5399
9bcb3eef 5400 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5401 }
078430f6 5402
d62a17ae 5403 /* Aggregate address increment. */
5404 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5405
d62a17ae 5406 /* Register new BGP information. */
9bcb3eef 5407 bgp_path_info_add(dest, new);
718e3744 5408
d62a17ae 5409 /* route_node_get lock */
9bcb3eef 5410 bgp_dest_unlock_node(dest);
d62a17ae 5411
5412 /* Process change. */
9bcb3eef 5413 bgp_process(bgp, dest, afi, safi);
d62a17ae 5414
ddb5b488
PZ
5415 if (SAFI_UNICAST == safi
5416 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5417 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5418 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5419 }
5420
d62a17ae 5421 /* Unintern original. */
5422 aspath_unintern(&attr.aspath);
718e3744 5423}
5424
5f040085 5425void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5426 safi_t safi)
718e3744 5427{
9bcb3eef 5428 struct bgp_dest *dest;
40381db7 5429 struct bgp_path_info *pi;
718e3744 5430
9bcb3eef 5431 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5432
d62a17ae 5433 /* Check selected route and self inserted route. */
9bcb3eef 5434 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5435 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5436 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5437 break;
5438
5439 /* Withdraw static BGP route from routing table. */
40381db7 5440 if (pi) {
ddb5b488
PZ
5441 if (SAFI_UNICAST == safi
5442 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5443 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5444 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5445 }
40381db7
DS
5446 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5447 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5448 bgp_path_info_delete(dest, pi);
5449 bgp_process(bgp, dest, afi, safi);
d62a17ae 5450 }
718e3744 5451
d62a17ae 5452 /* Unlock bgp_node_lookup. */
9bcb3eef 5453 bgp_dest_unlock_node(dest);
718e3744 5454}
5455
137446f9
LB
5456/*
5457 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5458 */
5f040085 5459static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5460 afi_t afi, safi_t safi,
5461 struct prefix_rd *prd)
718e3744 5462{
9bcb3eef 5463 struct bgp_dest *dest;
40381db7 5464 struct bgp_path_info *pi;
718e3744 5465
9bcb3eef 5466 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5467
d62a17ae 5468 /* Check selected route and self inserted route. */
9bcb3eef 5469 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5470 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5471 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5472 break;
718e3744 5473
d62a17ae 5474 /* Withdraw static BGP route from routing table. */
40381db7 5475 if (pi) {
49e5a4a0 5476#ifdef ENABLE_BGP_VNC
d62a17ae 5477 rfapiProcessWithdraw(
40381db7 5478 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5479 1); /* Kill, since it is an administrative change */
65efcfce 5480#endif
ddb5b488
PZ
5481 if (SAFI_MPLS_VPN == safi
5482 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5483 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5484 }
40381db7 5485 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5486 bgp_path_info_delete(dest, pi);
5487 bgp_process(bgp, dest, afi, safi);
d62a17ae 5488 }
718e3744 5489
d62a17ae 5490 /* Unlock bgp_node_lookup. */
9bcb3eef 5491 bgp_dest_unlock_node(dest);
718e3744 5492}
5493
5f040085 5494static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5495 struct bgp_static *bgp_static, afi_t afi,
5496 safi_t safi)
137446f9 5497{
9bcb3eef 5498 struct bgp_dest *dest;
4b7e6066 5499 struct bgp_path_info *new;
d62a17ae 5500 struct attr *attr_new;
5501 struct attr attr = {0};
40381db7 5502 struct bgp_path_info *pi;
49e5a4a0 5503#ifdef ENABLE_BGP_VNC
d62a17ae 5504 mpls_label_t label = 0;
65efcfce 5505#endif
d7c0a89a 5506 uint32_t num_labels = 0;
d62a17ae 5507 union gw_addr add;
137446f9 5508
d62a17ae 5509 assert(bgp_static);
137446f9 5510
b57ba6d2
MK
5511 if (bgp_static->label != MPLS_INVALID_LABEL)
5512 num_labels = 1;
9bcb3eef
DS
5513 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5514 &bgp_static->prd);
137446f9 5515
d62a17ae 5516 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5517
d62a17ae 5518 attr.nexthop = bgp_static->igpnexthop;
5519 attr.med = bgp_static->igpmetric;
5520 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5521
d62a17ae 5522 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5523 || (safi == SAFI_ENCAP)) {
5524 if (afi == AFI_IP) {
5525 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5526 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5527 }
5528 }
5529 if (afi == AFI_L2VPN) {
5530 if (bgp_static->gatewayIp.family == AF_INET)
5531 add.ipv4.s_addr =
5532 bgp_static->gatewayIp.u.prefix4.s_addr;
5533 else if (bgp_static->gatewayIp.family == AF_INET6)
5534 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5535 sizeof(struct in6_addr));
0a50c248 5536 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5537 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5538 struct bgp_encap_type_vxlan bet;
5539 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5540 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5541 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5542 }
5543 if (bgp_static->router_mac) {
5544 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5545 }
5546 }
5547 /* Apply route-map. */
5548 if (bgp_static->rmap.name) {
5549 struct attr attr_tmp = attr;
40381db7 5550 struct bgp_path_info rmap_path;
b68885f9 5551 route_map_result_t ret;
137446f9 5552
40381db7
DS
5553 rmap_path.peer = bgp->peer_self;
5554 rmap_path.attr = &attr_tmp;
137446f9 5555
d62a17ae 5556 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5557
1782514f 5558 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5559
d62a17ae 5560 bgp->peer_self->rmap_type = 0;
137446f9 5561
d62a17ae 5562 if (ret == RMAP_DENYMATCH) {
5563 /* Free uninterned attribute. */
5564 bgp_attr_flush(&attr_tmp);
137446f9 5565
d62a17ae 5566 /* Unintern original. */
5567 aspath_unintern(&attr.aspath);
5568 bgp_static_withdraw_safi(bgp, p, afi, safi,
5569 &bgp_static->prd);
5570 return;
5571 }
137446f9 5572
d62a17ae 5573 attr_new = bgp_attr_intern(&attr_tmp);
5574 } else {
5575 attr_new = bgp_attr_intern(&attr);
5576 }
137446f9 5577
9bcb3eef 5578 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5579 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5580 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5581 break;
5582
40381db7 5583 if (pi) {
d62a17ae 5584 memset(&add, 0, sizeof(union gw_addr));
40381db7 5585 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5586 && overlay_index_equal(afi, pi, &add)
40381db7 5587 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5588 bgp_dest_unlock_node(dest);
d62a17ae 5589 bgp_attr_unintern(&attr_new);
5590 aspath_unintern(&attr.aspath);
5591 return;
5592 } else {
5593 /* The attribute is changed. */
9bcb3eef 5594 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5595
5596 /* Rewrite BGP route information. */
40381db7 5597 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5598 bgp_path_info_restore(dest, pi);
d62a17ae 5599 else
40381db7
DS
5600 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5601 bgp_attr_unintern(&pi->attr);
5602 pi->attr = attr_new;
5603 pi->uptime = bgp_clock();
49e5a4a0 5604#ifdef ENABLE_BGP_VNC
40381db7
DS
5605 if (pi->extra)
5606 label = decode_label(&pi->extra->label[0]);
65efcfce 5607#endif
137446f9 5608
d62a17ae 5609 /* Process change. */
40381db7 5610 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5611 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5612
5613 if (SAFI_MPLS_VPN == safi
5614 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5615 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5616 }
49e5a4a0 5617#ifdef ENABLE_BGP_VNC
40381db7
DS
5618 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5619 pi->attr, afi, safi, pi->type,
5620 pi->sub_type, &label);
65efcfce 5621#endif
9bcb3eef 5622 bgp_dest_unlock_node(dest);
d62a17ae 5623 aspath_unintern(&attr.aspath);
5624 return;
5625 }
5626 }
137446f9
LB
5627
5628
d62a17ae 5629 /* Make new BGP info. */
5630 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5631 attr_new, dest);
1defdda8 5632 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5633 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5634 if (num_labels) {
5635 new->extra->label[0] = bgp_static->label;
5636 new->extra->num_labels = num_labels;
5637 }
49e5a4a0 5638#ifdef ENABLE_BGP_VNC
d62a17ae 5639 label = decode_label(&bgp_static->label);
65efcfce 5640#endif
137446f9 5641
d62a17ae 5642 /* Aggregate address increment. */
5643 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5644
d62a17ae 5645 /* Register new BGP information. */
9bcb3eef 5646 bgp_path_info_add(dest, new);
d62a17ae 5647 /* route_node_get lock */
9bcb3eef 5648 bgp_dest_unlock_node(dest);
137446f9 5649
d62a17ae 5650 /* Process change. */
9bcb3eef 5651 bgp_process(bgp, dest, afi, safi);
137446f9 5652
ddb5b488
PZ
5653 if (SAFI_MPLS_VPN == safi
5654 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5655 vpn_leak_to_vrf_update(bgp, new);
5656 }
49e5a4a0 5657#ifdef ENABLE_BGP_VNC
d62a17ae 5658 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5659 safi, new->type, new->sub_type, &label);
65efcfce
LB
5660#endif
5661
d62a17ae 5662 /* Unintern original. */
5663 aspath_unintern(&attr.aspath);
137446f9
LB
5664}
5665
718e3744 5666/* Configure static BGP network. When user don't run zebra, static
5667 route should be installed as valid. */
37a87b8f
CS
5668int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5669 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5670 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5671{
d62a17ae 5672 struct prefix p;
5673 struct bgp_static *bgp_static;
9bcb3eef 5674 struct bgp_dest *dest;
d7c0a89a 5675 uint8_t need_update = 0;
d62a17ae 5676
37a87b8f 5677 prefix_copy(&p, pfx);
d62a17ae 5678 apply_mask(&p);
718e3744 5679
e2a86ad9 5680 if (negate) {
718e3744 5681
e2a86ad9 5682 /* Set BGP static route configuration. */
9bcb3eef 5683 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5684
9bcb3eef 5685 if (!dest) {
37a87b8f
CS
5686 snprintf(errmsg, errmsg_len,
5687 "Can't find static route specified\n");
5688 return -1;
d62a17ae 5689 }
5690
9bcb3eef 5691 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5692
e2a86ad9
DS
5693 if ((label_index != BGP_INVALID_LABEL_INDEX)
5694 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5695 snprintf(errmsg, errmsg_len,
5696 "label-index doesn't match static route\n");
5697 return -1;
d62a17ae 5698 }
d62a17ae 5699
e2a86ad9
DS
5700 if ((rmap && bgp_static->rmap.name)
5701 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5702 snprintf(errmsg, errmsg_len,
5703 "route-map name doesn't match static route\n");
5704 return -1;
d62a17ae 5705 }
718e3744 5706
e2a86ad9
DS
5707 /* Update BGP RIB. */
5708 if (!bgp_static->backdoor)
5709 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5710
e2a86ad9
DS
5711 /* Clear configuration. */
5712 bgp_static_free(bgp_static);
9bcb3eef
DS
5713 bgp_dest_set_bgp_static_info(dest, NULL);
5714 bgp_dest_unlock_node(dest);
5715 bgp_dest_unlock_node(dest);
e2a86ad9 5716 } else {
718e3744 5717
e2a86ad9 5718 /* Set BGP static route configuration. */
9bcb3eef
DS
5719 dest = bgp_node_get(bgp->route[afi][safi], &p);
5720 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5721 if (bgp_static) {
e2a86ad9 5722 /* Configuration change. */
e2a86ad9
DS
5723 /* Label index cannot be changed. */
5724 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5725 snprintf(errmsg, errmsg_len,
5726 "cannot change label-index\n");
5727 return -1;
e2a86ad9 5728 }
d62a17ae 5729
e2a86ad9 5730 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5731 if (bgp_static->valid
5732 && bgp_static->backdoor != backdoor)
e2a86ad9 5733 need_update = 1;
718e3744 5734
e2a86ad9 5735 bgp_static->backdoor = backdoor;
718e3744 5736
e2a86ad9 5737 if (rmap) {
0a22ddfb
QY
5738 XFREE(MTYPE_ROUTE_MAP_NAME,
5739 bgp_static->rmap.name);
b4897fa5 5740 route_map_counter_decrement(
5741 bgp_static->rmap.map);
e2a86ad9
DS
5742 bgp_static->rmap.name =
5743 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5744 bgp_static->rmap.map =
5745 route_map_lookup_by_name(rmap);
b4897fa5 5746 route_map_counter_increment(
5747 bgp_static->rmap.map);
e2a86ad9 5748 } else {
0a22ddfb
QY
5749 XFREE(MTYPE_ROUTE_MAP_NAME,
5750 bgp_static->rmap.name);
b4897fa5 5751 route_map_counter_decrement(
5752 bgp_static->rmap.map);
e2a86ad9
DS
5753 bgp_static->rmap.map = NULL;
5754 bgp_static->valid = 0;
5755 }
9bcb3eef 5756 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5757 } else {
5758 /* New configuration. */
5759 bgp_static = bgp_static_new();
5760 bgp_static->backdoor = backdoor;
5761 bgp_static->valid = 0;
5762 bgp_static->igpmetric = 0;
975a328e 5763 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5764 bgp_static->label_index = label_index;
718e3744 5765
e2a86ad9 5766 if (rmap) {
0a22ddfb
QY
5767 XFREE(MTYPE_ROUTE_MAP_NAME,
5768 bgp_static->rmap.name);
b4897fa5 5769 route_map_counter_decrement(
5770 bgp_static->rmap.map);
e2a86ad9
DS
5771 bgp_static->rmap.name =
5772 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5773 bgp_static->rmap.map =
5774 route_map_lookup_by_name(rmap);
b4897fa5 5775 route_map_counter_increment(
5776 bgp_static->rmap.map);
e2a86ad9 5777 }
9bcb3eef 5778 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5779 }
d62a17ae 5780
e2a86ad9
DS
5781 bgp_static->valid = 1;
5782 if (need_update)
5783 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5784
e2a86ad9
DS
5785 if (!bgp_static->backdoor)
5786 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5787 }
d62a17ae 5788
37a87b8f 5789 return 0;
d62a17ae 5790}
5791
5792void bgp_static_add(struct bgp *bgp)
5793{
5794 afi_t afi;
5795 safi_t safi;
9bcb3eef
DS
5796 struct bgp_dest *dest;
5797 struct bgp_dest *rm;
d62a17ae 5798 struct bgp_table *table;
5799 struct bgp_static *bgp_static;
5800
05c7a1cc 5801 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5802 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5803 dest = bgp_route_next(dest)) {
5804 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5805 continue;
ea47320b 5806
05c7a1cc
QY
5807 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5808 || (safi == SAFI_EVPN)) {
9bcb3eef 5809 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5810
5811 for (rm = bgp_table_top(table); rm;
5812 rm = bgp_route_next(rm)) {
a78beeb5 5813 bgp_static =
9bcb3eef 5814 bgp_dest_get_bgp_static_info(
5a8ba9fc 5815 rm);
9bcb3eef
DS
5816 bgp_static_update_safi(
5817 bgp, bgp_dest_get_prefix(rm),
5818 bgp_static, afi, safi);
d62a17ae 5819 }
05c7a1cc 5820 } else {
5a8ba9fc 5821 bgp_static_update(
9bcb3eef
DS
5822 bgp, bgp_dest_get_prefix(dest),
5823 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5824 safi);
ea47320b 5825 }
05c7a1cc 5826 }
6aeb9e78
DS
5827}
5828
718e3744 5829/* Called from bgp_delete(). Delete all static routes from the BGP
5830 instance. */
d62a17ae 5831void bgp_static_delete(struct bgp *bgp)
5832{
5833 afi_t afi;
5834 safi_t safi;
9bcb3eef
DS
5835 struct bgp_dest *dest;
5836 struct bgp_dest *rm;
d62a17ae 5837 struct bgp_table *table;
5838 struct bgp_static *bgp_static;
5839
05c7a1cc 5840 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5841 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5842 dest = bgp_route_next(dest)) {
5843 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5844 continue;
ea47320b 5845
05c7a1cc
QY
5846 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5847 || (safi == SAFI_EVPN)) {
9bcb3eef 5848 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5849
5850 for (rm = bgp_table_top(table); rm;
5851 rm = bgp_route_next(rm)) {
a78beeb5 5852 bgp_static =
9bcb3eef 5853 bgp_dest_get_bgp_static_info(
5a8ba9fc 5854 rm);
c7d14ba6
PG
5855 if (!bgp_static)
5856 continue;
5857
05c7a1cc 5858 bgp_static_withdraw_safi(
9bcb3eef 5859 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5860 AFI_IP, safi,
5861 (struct prefix_rd *)
9bcb3eef
DS
5862 bgp_dest_get_prefix(
5863 dest));
ea47320b 5864 bgp_static_free(bgp_static);
811c6797 5865 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5866 NULL);
811c6797 5867 bgp_dest_unlock_node(rm);
d62a17ae 5868 }
05c7a1cc 5869 } else {
9bcb3eef 5870 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5871 bgp_static_withdraw(bgp,
9bcb3eef 5872 bgp_dest_get_prefix(dest),
b54892e0 5873 afi, safi);
05c7a1cc 5874 bgp_static_free(bgp_static);
9bcb3eef
DS
5875 bgp_dest_set_bgp_static_info(dest, NULL);
5876 bgp_dest_unlock_node(dest);
ea47320b 5877 }
05c7a1cc 5878 }
d62a17ae 5879}
5880
5881void bgp_static_redo_import_check(struct bgp *bgp)
5882{
5883 afi_t afi;
5884 safi_t safi;
9bcb3eef
DS
5885 struct bgp_dest *dest;
5886 struct bgp_dest *rm;
d62a17ae 5887 struct bgp_table *table;
5888 struct bgp_static *bgp_static;
5889
5890 /* Use this flag to force reprocessing of the route */
892fedb6 5891 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5892 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5893 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5894 dest = bgp_route_next(dest)) {
5895 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5896 continue;
ea47320b 5897
05c7a1cc
QY
5898 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5899 || (safi == SAFI_EVPN)) {
9bcb3eef 5900 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5901
5902 for (rm = bgp_table_top(table); rm;
5903 rm = bgp_route_next(rm)) {
a78beeb5 5904 bgp_static =
9bcb3eef 5905 bgp_dest_get_bgp_static_info(
5a8ba9fc 5906 rm);
9bcb3eef
DS
5907 bgp_static_update_safi(
5908 bgp, bgp_dest_get_prefix(rm),
5909 bgp_static, afi, safi);
d62a17ae 5910 }
05c7a1cc 5911 } else {
9bcb3eef
DS
5912 bgp_static = bgp_dest_get_bgp_static_info(dest);
5913 bgp_static_update(bgp,
5914 bgp_dest_get_prefix(dest),
5915 bgp_static, afi, safi);
ea47320b 5916 }
05c7a1cc
QY
5917 }
5918 }
892fedb6 5919 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5920}
5921
5922static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5923 safi_t safi)
5924{
5925 struct bgp_table *table;
9bcb3eef 5926 struct bgp_dest *dest;
40381db7 5927 struct bgp_path_info *pi;
d62a17ae 5928
dfb6fd1d
NT
5929 /* Do not install the aggregate route if BGP is in the
5930 * process of termination.
5931 */
892fedb6
DA
5932 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5933 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5934 return;
5935
d62a17ae 5936 table = bgp->rib[afi][safi];
9bcb3eef
DS
5937 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5938 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5939 if (pi->peer == bgp->peer_self
5940 && ((pi->type == ZEBRA_ROUTE_BGP
5941 && pi->sub_type == BGP_ROUTE_STATIC)
5942 || (pi->type != ZEBRA_ROUTE_BGP
5943 && pi->sub_type
d62a17ae 5944 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5945 bgp_aggregate_decrement(
5946 bgp, bgp_dest_get_prefix(dest), pi, afi,
5947 safi);
40381db7 5948 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5949 bgp_path_info_delete(dest, pi);
5950 bgp_process(bgp, dest, afi, safi);
d62a17ae 5951 }
5952 }
5953 }
ad4cbda1 5954}
5955
5956/*
5957 * Purge all networks and redistributed routes from routing table.
5958 * Invoked upon the instance going down.
5959 */
d62a17ae 5960void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5961{
d62a17ae 5962 afi_t afi;
5963 safi_t safi;
ad4cbda1 5964
05c7a1cc
QY
5965 FOREACH_AFI_SAFI (afi, safi)
5966 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5967}
5968
137446f9
LB
5969/*
5970 * gpz 110624
5971 * Currently this is used to set static routes for VPN and ENCAP.
5972 * I think it can probably be factored with bgp_static_set.
5973 */
d62a17ae 5974int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5975 const char *ip_str, const char *rd_str,
5976 const char *label_str, const char *rmap_str,
5977 int evpn_type, const char *esi, const char *gwip,
5978 const char *ethtag, const char *routermac)
5979{
5980 VTY_DECLVAR_CONTEXT(bgp, bgp);
5981 int ret;
5982 struct prefix p;
5983 struct prefix_rd prd;
9bcb3eef
DS
5984 struct bgp_dest *pdest;
5985 struct bgp_dest *dest;
d62a17ae 5986 struct bgp_table *table;
5987 struct bgp_static *bgp_static;
5988 mpls_label_t label = MPLS_INVALID_LABEL;
5989 struct prefix gw_ip;
5990
5991 /* validate ip prefix */
5992 ret = str2prefix(ip_str, &p);
5993 if (!ret) {
5994 vty_out(vty, "%% Malformed prefix\n");
5995 return CMD_WARNING_CONFIG_FAILED;
5996 }
5997 apply_mask(&p);
5998 if ((afi == AFI_L2VPN)
5999 && (bgp_build_evpn_prefix(evpn_type,
6000 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6001 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6002 return CMD_WARNING_CONFIG_FAILED;
6003 }
718e3744 6004
d62a17ae 6005 ret = str2prefix_rd(rd_str, &prd);
6006 if (!ret) {
6007 vty_out(vty, "%% Malformed rd\n");
6008 return CMD_WARNING_CONFIG_FAILED;
6009 }
718e3744 6010
d62a17ae 6011 if (label_str) {
6012 unsigned long label_val;
6013 label_val = strtoul(label_str, NULL, 10);
6014 encode_label(label_val, &label);
6015 }
9bedbb1e 6016
d62a17ae 6017 if (safi == SAFI_EVPN) {
6018 if (esi && str2esi(esi, NULL) == 0) {
6019 vty_out(vty, "%% Malformed ESI\n");
6020 return CMD_WARNING_CONFIG_FAILED;
6021 }
6022 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6023 vty_out(vty, "%% Malformed Router MAC\n");
6024 return CMD_WARNING_CONFIG_FAILED;
6025 }
6026 if (gwip) {
6027 memset(&gw_ip, 0, sizeof(struct prefix));
6028 ret = str2prefix(gwip, &gw_ip);
6029 if (!ret) {
6030 vty_out(vty, "%% Malformed GatewayIp\n");
6031 return CMD_WARNING_CONFIG_FAILED;
6032 }
6033 if ((gw_ip.family == AF_INET
3714a385 6034 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6035 (struct prefix_evpn *)&p))
6036 || (gw_ip.family == AF_INET6
3714a385 6037 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6038 (struct prefix_evpn *)&p))) {
6039 vty_out(vty,
6040 "%% GatewayIp family differs with IP prefix\n");
6041 return CMD_WARNING_CONFIG_FAILED;
6042 }
6043 }
6044 }
9bcb3eef
DS
6045 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6046 if (!bgp_dest_has_bgp_path_info_data(pdest))
6047 bgp_dest_set_bgp_table_info(pdest,
67009e22 6048 bgp_table_init(bgp, afi, safi));
9bcb3eef 6049 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6050
9bcb3eef 6051 dest = bgp_node_get(table, &p);
d62a17ae 6052
9bcb3eef 6053 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6054 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6055 bgp_dest_unlock_node(dest);
d62a17ae 6056 } else {
6057 /* New configuration. */
6058 bgp_static = bgp_static_new();
6059 bgp_static->backdoor = 0;
6060 bgp_static->valid = 0;
6061 bgp_static->igpmetric = 0;
975a328e 6062 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6063 bgp_static->label = label;
6064 bgp_static->prd = prd;
6065
6066 if (rmap_str) {
0a22ddfb 6067 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6068 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6069 bgp_static->rmap.name =
6070 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6071 bgp_static->rmap.map =
6072 route_map_lookup_by_name(rmap_str);
b4897fa5 6073 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6074 }
718e3744 6075
d62a17ae 6076 if (safi == SAFI_EVPN) {
6077 if (esi) {
6078 bgp_static->eth_s_id =
6079 XCALLOC(MTYPE_ATTR,
0a50c248 6080 sizeof(esi_t));
d62a17ae 6081 str2esi(esi, bgp_static->eth_s_id);
6082 }
6083 if (routermac) {
6084 bgp_static->router_mac =
28328ea9 6085 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6086 (void)prefix_str2mac(routermac,
6087 bgp_static->router_mac);
d62a17ae 6088 }
6089 if (gwip)
6090 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6091 }
9bcb3eef 6092 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6093
d62a17ae 6094 bgp_static->valid = 1;
6095 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6096 }
718e3744 6097
d62a17ae 6098 return CMD_SUCCESS;
718e3744 6099}
6100
6101/* Configure static BGP network. */
d62a17ae 6102int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6103 const char *ip_str, const char *rd_str,
6104 const char *label_str, int evpn_type, const char *esi,
6105 const char *gwip, const char *ethtag)
6106{
6107 VTY_DECLVAR_CONTEXT(bgp, bgp);
6108 int ret;
6109 struct prefix p;
6110 struct prefix_rd prd;
9bcb3eef
DS
6111 struct bgp_dest *pdest;
6112 struct bgp_dest *dest;
d62a17ae 6113 struct bgp_table *table;
6114 struct bgp_static *bgp_static;
6115 mpls_label_t label = MPLS_INVALID_LABEL;
6116
6117 /* Convert IP prefix string to struct prefix. */
6118 ret = str2prefix(ip_str, &p);
6119 if (!ret) {
6120 vty_out(vty, "%% Malformed prefix\n");
6121 return CMD_WARNING_CONFIG_FAILED;
6122 }
6123 apply_mask(&p);
6124 if ((afi == AFI_L2VPN)
6125 && (bgp_build_evpn_prefix(evpn_type,
6126 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6127 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6128 return CMD_WARNING_CONFIG_FAILED;
6129 }
6130 ret = str2prefix_rd(rd_str, &prd);
6131 if (!ret) {
6132 vty_out(vty, "%% Malformed rd\n");
6133 return CMD_WARNING_CONFIG_FAILED;
6134 }
718e3744 6135
d62a17ae 6136 if (label_str) {
6137 unsigned long label_val;
6138 label_val = strtoul(label_str, NULL, 10);
6139 encode_label(label_val, &label);
6140 }
718e3744 6141
9bcb3eef
DS
6142 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6143 if (!bgp_dest_has_bgp_path_info_data(pdest))
6144 bgp_dest_set_bgp_table_info(pdest,
67009e22 6145 bgp_table_init(bgp, afi, safi));
d62a17ae 6146 else
9bcb3eef
DS
6147 bgp_dest_unlock_node(pdest);
6148 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6149
9bcb3eef 6150 dest = bgp_node_lookup(table, &p);
6b0655a2 6151
9bcb3eef 6152 if (dest) {
d62a17ae 6153 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6154
9bcb3eef 6155 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6156 bgp_static_free(bgp_static);
9bcb3eef
DS
6157 bgp_dest_set_bgp_static_info(dest, NULL);
6158 bgp_dest_unlock_node(dest);
6159 bgp_dest_unlock_node(dest);
d62a17ae 6160 } else
6161 vty_out(vty, "%% Can't find the route\n");
6162
6163 return CMD_SUCCESS;
6164}
6165
6166static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6167 const char *rmap_name)
6168{
6169 VTY_DECLVAR_CONTEXT(bgp, bgp);
6170 struct bgp_rmap *rmap;
6171
6172 rmap = &bgp->table_map[afi][safi];
6173 if (rmap_name) {
0a22ddfb 6174 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6175 route_map_counter_decrement(rmap->map);
d62a17ae 6176 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6177 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6178 route_map_counter_increment(rmap->map);
d62a17ae 6179 } else {
0a22ddfb 6180 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6181 route_map_counter_decrement(rmap->map);
d62a17ae 6182 rmap->map = NULL;
6183 }
73ac8160 6184
d62a17ae 6185 if (bgp_fibupd_safi(safi))
6186 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6187
d62a17ae 6188 return CMD_SUCCESS;
73ac8160
DS
6189}
6190
d62a17ae 6191static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6192 const char *rmap_name)
73ac8160 6193{
d62a17ae 6194 VTY_DECLVAR_CONTEXT(bgp, bgp);
6195 struct bgp_rmap *rmap;
73ac8160 6196
d62a17ae 6197 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6198 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6199 route_map_counter_decrement(rmap->map);
d62a17ae 6200 rmap->map = NULL;
73ac8160 6201
d62a17ae 6202 if (bgp_fibupd_safi(safi))
6203 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6204
d62a17ae 6205 return CMD_SUCCESS;
73ac8160
DS
6206}
6207
2b791107 6208void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6209 safi_t safi)
73ac8160 6210{
d62a17ae 6211 if (bgp->table_map[afi][safi].name) {
d62a17ae 6212 vty_out(vty, " table-map %s\n",
6213 bgp->table_map[afi][safi].name);
6214 }
73ac8160
DS
6215}
6216
73ac8160
DS
6217DEFUN (bgp_table_map,
6218 bgp_table_map_cmd,
6219 "table-map WORD",
6220 "BGP table to RIB route download filter\n"
6221 "Name of the route map\n")
6222{
d62a17ae 6223 int idx_word = 1;
6224 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6225 argv[idx_word]->arg);
73ac8160
DS
6226}
6227DEFUN (no_bgp_table_map,
6228 no_bgp_table_map_cmd,
6229 "no table-map WORD",
3a2d747c 6230 NO_STR
73ac8160
DS
6231 "BGP table to RIB route download filter\n"
6232 "Name of the route map\n")
6233{
d62a17ae 6234 int idx_word = 2;
6235 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6236 argv[idx_word]->arg);
73ac8160
DS
6237}
6238
37a87b8f
CS
6239DEFPY_YANG (bgp_network, bgp_network_cmd,
6240 "[no] network \
6241 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6242 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6243 backdoor$backdoor}]",
6244 NO_STR
6245 "Specify a network to announce via BGP\n"
6246 "IPv4 prefix\n"
6247 "Network number\n"
6248 "Network mask\n"
6249 "Network mask\n"
6250 "Route-map to modify the attributes\n"
6251 "Name of the route map\n"
6252 "Label index to associate with the prefix\n"
6253 "Label index value\n"
6254 "Specify a BGP backdoor route\n")
6255{
6256 char addr_prefix_str[PREFIX_STRLEN];
6257 char base_xpath[XPATH_MAXLEN];
6258 afi_t afi;
6259 safi_t safi;
e2a86ad9
DS
6260
6261 if (address_str) {
6262 int ret;
718e3744 6263
e2a86ad9
DS
6264 ret = netmask_str2prefix_str(address_str, netmask_str,
6265 addr_prefix_str);
6266 if (!ret) {
6267 vty_out(vty, "%% Inconsistent address and mask\n");
6268 return CMD_WARNING_CONFIG_FAILED;
6269 }
d62a17ae 6270 }
718e3744 6271
37a87b8f
CS
6272 afi = bgp_node_afi(vty);
6273 safi = bgp_node_safi(vty);
6274
6275 if (no) {
6276 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6277 } else {
6278 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6279
6280 if (map_name)
6281 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6282 NB_OP_CREATE, map_name);
6283 else
6284 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6285 NB_OP_DESTROY, NULL);
6286
6287 if (label_index_str)
6288 nb_cli_enqueue_change(vty, "./label-index",
6289 NB_OP_MODIFY, label_index_str);
6290
6291 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6292 backdoor ? "true" : "false");
6293 }
6294
6295 snprintf(
6296 base_xpath, sizeof(base_xpath),
6297 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6298 yang_afi_safi_value2identity(afi, safi),
6299 bgp_afi_safi_get_container_str(afi, safi),
6300 address_str ? addr_prefix_str : prefix_str);
6301
6302 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6303}
6304
37a87b8f
CS
6305DEFPY_YANG (ipv6_bgp_network,
6306 ipv6_bgp_network_cmd,
6307 "[no] network X:X::X:X/M$prefix \
6308 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6309 NO_STR
6310 "Specify a network to announce via BGP\n"
6311 "IPv6 prefix\n"
6312 "Route-map to modify the attributes\n"
6313 "Name of the route map\n"
6314 "Label index to associate with the prefix\n"
6315 "Label index value\n")
6316{
6317 char base_xpath[XPATH_MAXLEN];
6318 afi_t afi;
6319 safi_t safi;
6320
6321 afi = bgp_node_afi(vty);
6322 safi = bgp_node_safi(vty);
6323
6324 if (no) {
6325 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6326 } else {
6327 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6328
6329 if (map_name)
6330 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6331 NB_OP_MODIFY, map_name);
6332 else
6333 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6334 NB_OP_DESTROY, NULL);
6335
6336 if (label_index_str)
6337 nb_cli_enqueue_change(vty, "./label-index",
6338 NB_OP_MODIFY, label_index_str);
6339 }
6340
6341 snprintf(
6342 base_xpath, sizeof(base_xpath),
6343 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6344 yang_afi_safi_value2identity(afi, safi),
6345 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6346
6347 return nb_cli_apply_changes(vty, base_xpath);
6348}
6349
6350void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6351 struct lyd_node *dnode,
6352 bool show_defaults)
718e3744 6353{
37a87b8f
CS
6354 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6355
6356 if (yang_dnode_exists(dnode, "./label-index"))
6357 vty_out(vty, " label-index %s",
6358 yang_dnode_get_string(dnode, "./label-index"));
6359
6360 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6361 vty_out(vty, " route-map %s",
6362 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6363
6364 if (yang_dnode_get_bool(dnode, "./backdoor"))
6365 vty_out(vty, " backdoor");
6366
6367 vty_out(vty, "\n");
1b6d5c7e
VV
6368}
6369
d62a17ae 6370static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6371{
d62a17ae 6372 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6373}
6374
d62a17ae 6375static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6376{
365ab2e7
RZ
6377 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6378 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6379 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6380 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6381 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6382}
718e3744 6383
365ab2e7
RZ
6384/**
6385 * Helper function to avoid repeated code: prepare variables for a
6386 * `route_map_apply` call.
6387 *
6388 * \returns `true` on route map match, otherwise `false`.
6389 */
6390static bool aggr_suppress_map_test(struct bgp *bgp,
6391 struct bgp_aggregate *aggregate,
6392 struct bgp_path_info *pi)
6393{
6394 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6395 route_map_result_t rmr = RMAP_DENYMATCH;
6396 struct bgp_path_info rmap_path = {};
6397 struct attr attr = {};
6398
6399 /* No route map entries created, just don't match. */
6400 if (aggregate->suppress_map == NULL)
6401 return false;
6402
6403 /* Call route map matching and return result. */
6404 attr.aspath = aspath_empty();
6405 rmap_path.peer = bgp->peer_self;
6406 rmap_path.attr = &attr;
6407
6408 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6409 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6410 bgp->peer_self->rmap_type = 0;
6411
6412 bgp_attr_flush(&attr);
6413
6414 return rmr == RMAP_PERMITMATCH;
6415}
6416
4056a5f6
RZ
6417/** Test whether the aggregation has suppressed this path or not. */
6418static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6419 struct bgp_path_info *pi)
6420{
6421 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6422 return false;
6423
6424 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6425}
6426
6427/**
6428 * Suppress this path and keep the reference.
6429 *
6430 * \returns `true` if needs processing otherwise `false`.
6431 */
6432static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6433 struct bgp_path_info *pi)
6434{
6435 struct bgp_path_info_extra *pie;
6436
6437 /* Path is already suppressed by this aggregation. */
6438 if (aggr_suppress_exists(aggregate, pi))
6439 return false;
6440
6441 pie = bgp_path_info_extra_get(pi);
6442
6443 /* This is the first suppression, allocate memory and list it. */
6444 if (pie->aggr_suppressors == NULL)
6445 pie->aggr_suppressors = list_new();
6446
6447 listnode_add(pie->aggr_suppressors, aggregate);
6448
6449 /* Only mark for processing if suppressed. */
6450 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6451 if (BGP_DEBUG(update, UPDATE_OUT))
6452 zlog_debug("aggregate-address suppressing: %pFX",
6453 bgp_dest_get_prefix(pi->net));
6454
4056a5f6
RZ
6455 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6456 return true;
6457 }
6458
6459 return false;
6460}
6461
6462/**
6463 * Unsuppress this path and remove the reference.
6464 *
6465 * \returns `true` if needs processing otherwise `false`.
6466 */
6467static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6468 struct bgp_path_info *pi)
6469{
6470 /* Path wasn't suppressed. */
6471 if (!aggr_suppress_exists(aggregate, pi))
6472 return false;
6473
6474 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6475
6476 /* Unsuppress and free extra memory if last item. */
6477 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6478 if (BGP_DEBUG(update, UPDATE_OUT))
6479 zlog_debug("aggregate-address unsuppressing: %pFX",
6480 bgp_dest_get_prefix(pi->net));
6481
4056a5f6
RZ
6482 list_delete(&pi->extra->aggr_suppressors);
6483 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6484 return true;
6485 }
6486
6487 return false;
6488}
6489
3dc339cd
DA
6490static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6491 struct aspath *aspath,
6492 struct community *comm,
6493 struct ecommunity *ecomm,
6494 struct lcommunity *lcomm)
eaaf8adb
DS
6495{
6496 static struct aspath *ae = NULL;
6497
6498 if (!ae)
6499 ae = aspath_empty();
6500
40381db7 6501 if (!pi)
3dc339cd 6502 return false;
eaaf8adb 6503
40381db7 6504 if (origin != pi->attr->origin)
3dc339cd 6505 return false;
eaaf8adb 6506
40381db7 6507 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6508 return false;
29f7d023 6509
40381db7 6510 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6511 return false;
eaaf8adb 6512
3da2cc32 6513 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6514 return false;
eaaf8adb 6515
dd18c5a9 6516 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6517 return false;
dd18c5a9 6518
40381db7 6519 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6520 return false;
7ce8a8e0 6521
3dc339cd 6522 return true;
eaaf8adb
DS
6523}
6524
5f040085
DS
6525static void bgp_aggregate_install(
6526 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6527 uint8_t origin, struct aspath *aspath, struct community *community,
6528 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6529 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6530{
9bcb3eef 6531 struct bgp_dest *dest;
c701010e 6532 struct bgp_table *table;
6f94b685 6533 struct bgp_path_info *pi, *orig, *new;
20894f50 6534 struct attr *attr;
c701010e
DS
6535
6536 table = bgp->rib[afi][safi];
6537
9bcb3eef 6538 dest = bgp_node_get(table, p);
eaaf8adb 6539
9bcb3eef 6540 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6541 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6542 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6543 break;
6544
6aabb15d
RZ
6545 /*
6546 * If we have paths with different MEDs, then don't install
6547 * (or uninstall) the aggregate route.
6548 */
6549 if (aggregate->match_med && aggregate->med_mismatched)
6550 goto uninstall_aggregate_route;
6551
c701010e 6552 if (aggregate->count > 0) {
eaaf8adb
DS
6553 /*
6554 * If the aggregate information has not changed
6555 * no need to re-install it again.
6556 */
6f94b685 6557 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6558 ecommunity, lcommunity)) {
9bcb3eef 6559 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6560
6561 if (aspath)
6562 aspath_free(aspath);
6563 if (community)
3c1f53de 6564 community_free(&community);
3da2cc32
DS
6565 if (ecommunity)
6566 ecommunity_free(&ecommunity);
dd18c5a9
DS
6567 if (lcommunity)
6568 lcommunity_free(&lcommunity);
eaaf8adb
DS
6569
6570 return;
6571 }
6572
6573 /*
6574 * Mark the old as unusable
6575 */
40381db7 6576 if (pi)
9bcb3eef 6577 bgp_path_info_delete(dest, pi);
eaaf8adb 6578
20894f50
DA
6579 attr = bgp_attr_aggregate_intern(
6580 bgp, origin, aspath, community, ecommunity, lcommunity,
6581 aggregate, atomic_aggregate, p);
6582
6583 if (!attr) {
6584 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6585 return;
6586 }
6587
3da2cc32 6588 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6589 bgp->peer_self, attr, dest);
20894f50 6590
1defdda8 6591 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6592
9bcb3eef
DS
6593 bgp_path_info_add(dest, new);
6594 bgp_process(bgp, dest, afi, safi);
c701010e 6595 } else {
6aabb15d 6596 uninstall_aggregate_route:
6f94b685 6597 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6598 if (pi->peer == bgp->peer_self
6599 && pi->type == ZEBRA_ROUTE_BGP
6600 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6601 break;
6602
6603 /* Withdraw static BGP route from routing table. */
40381db7 6604 if (pi) {
9bcb3eef
DS
6605 bgp_path_info_delete(dest, pi);
6606 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6607 }
6608 }
6609
9bcb3eef 6610 bgp_dest_unlock_node(dest);
c701010e
DS
6611}
6612
6aabb15d
RZ
6613/**
6614 * Check if the current path has different MED than other known paths.
6615 *
6616 * \returns `true` if the MED matched the others else `false`.
6617 */
6618static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6619 struct bgp *bgp, struct bgp_path_info *pi)
6620{
6621 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6622
6623 /* This is the first route being analyzed. */
6624 if (!aggregate->med_initialized) {
6625 aggregate->med_initialized = true;
6626 aggregate->med_mismatched = false;
6627 aggregate->med_matched_value = cur_med;
6628 } else {
6629 /* Check if routes with different MED showed up. */
6630 if (cur_med != aggregate->med_matched_value)
6631 aggregate->med_mismatched = true;
6632 }
6633
6634 return !aggregate->med_mismatched;
6635}
6636
6637/**
6638 * Initializes and tests all routes in the aggregate address path for MED
6639 * values.
6640 *
6641 * \returns `true` if all MEDs are the same otherwise `false`.
6642 */
6643static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6644 struct bgp *bgp, const struct prefix *p,
6645 afi_t afi, safi_t safi)
6646{
6647 struct bgp_table *table = bgp->rib[afi][safi];
6648 const struct prefix *dest_p;
6649 struct bgp_dest *dest, *top;
6650 struct bgp_path_info *pi;
6651 bool med_matched = true;
6652
6653 aggregate->med_initialized = false;
6654
6655 top = bgp_node_get(table, p);
6656 for (dest = bgp_node_get(table, p); dest;
6657 dest = bgp_route_next_until(dest, top)) {
6658 dest_p = bgp_dest_get_prefix(dest);
6659 if (dest_p->prefixlen <= p->prefixlen)
6660 continue;
6661
6662 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6663 if (BGP_PATH_HOLDDOWN(pi))
6664 continue;
6665 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6666 continue;
6667 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6668 med_matched = false;
6669 break;
6670 }
6671 }
6672 if (!med_matched)
6673 break;
6674 }
6675 bgp_dest_unlock_node(top);
6676
6677 return med_matched;
6678}
6679
6680/**
6681 * Toggles the route suppression status for this aggregate address
6682 * configuration.
6683 */
4056a5f6
RZ
6684void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6685 struct bgp *bgp, const struct prefix *p,
6686 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6687{
6688 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6689 const struct prefix *dest_p;
6690 struct bgp_dest *dest, *top;
6691 struct bgp_path_info *pi;
6692 bool toggle_suppression;
6693
6694 /* We've found a different MED we must revert any suppressed routes. */
6695 top = bgp_node_get(table, p);
6696 for (dest = bgp_node_get(table, p); dest;
6697 dest = bgp_route_next_until(dest, top)) {
6698 dest_p = bgp_dest_get_prefix(dest);
6699 if (dest_p->prefixlen <= p->prefixlen)
6700 continue;
6701
6702 toggle_suppression = false;
6703 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6704 if (BGP_PATH_HOLDDOWN(pi))
6705 continue;
6706 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6707 continue;
6708
6aabb15d
RZ
6709 /* We are toggling suppression back. */
6710 if (suppress) {
6aabb15d 6711 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6712 if (aggr_suppress_path(aggregate, pi))
6713 toggle_suppression = true;
6aabb15d
RZ
6714 continue;
6715 }
6716
6aabb15d 6717 /* Install route if there is no more suppression. */
4056a5f6 6718 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6719 toggle_suppression = true;
6aabb15d
RZ
6720 }
6721
6722 if (toggle_suppression)
6723 bgp_process(bgp, dest, afi, safi);
6724 }
6725 bgp_dest_unlock_node(top);
6726}
6727
6728/**
6729 * Aggregate address MED matching incremental test: this function is called
6730 * when the initial aggregation occurred and we are only testing a single
6731 * new path.
6732 *
6733 * In addition to testing and setting the MED validity it also installs back
6734 * suppressed routes (if summary is configured).
6735 *
6736 * Must not be called in `bgp_aggregate_route`.
6737 */
6738static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6739 struct bgp *bgp, const struct prefix *p,
6740 afi_t afi, safi_t safi,
6741 struct bgp_path_info *pi, bool is_adding)
6742{
6743 /* MED matching disabled. */
6744 if (!aggregate->match_med)
6745 return;
6746
6747 /* Aggregation with different MED, nothing to do. */
6748 if (aggregate->med_mismatched)
6749 return;
6750
6751 /*
6752 * Test the current entry:
6753 *
6754 * is_adding == true: if the new entry doesn't match then we must
6755 * install all suppressed routes.
6756 *
6757 * is_adding == false: if the entry being removed was the last
6758 * unmatching entry then we can suppress all routes.
6759 */
6760 if (!is_adding) {
6761 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6762 && aggregate->summary_only)
6763 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6764 safi, true);
6765 } else
6766 bgp_aggregate_med_match(aggregate, bgp, pi);
6767
6768 /* No mismatches, just quit. */
6769 if (!aggregate->med_mismatched)
6770 return;
6771
6772 /* Route summarization is disabled. */
6773 if (!aggregate->summary_only)
6774 return;
6775
6776 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6777}
6778
b5d58c32 6779/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6780void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6781 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6782{
6783 struct bgp_table *table;
9bcb3eef
DS
6784 struct bgp_dest *top;
6785 struct bgp_dest *dest;
d7c0a89a 6786 uint8_t origin;
d62a17ae 6787 struct aspath *aspath = NULL;
d62a17ae 6788 struct community *community = NULL;
3da2cc32 6789 struct ecommunity *ecommunity = NULL;
dd18c5a9 6790 struct lcommunity *lcommunity = NULL;
40381db7 6791 struct bgp_path_info *pi;
d62a17ae 6792 unsigned long match = 0;
d7c0a89a 6793 uint8_t atomic_aggregate = 0;
d62a17ae 6794
9f822fa2
S
6795 /* If the bgp instance is being deleted or self peer is deleted
6796 * then do not create aggregate route
6797 */
892fedb6
DA
6798 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6799 || (bgp->peer_self == NULL))
9f822fa2
S
6800 return;
6801
6aabb15d
RZ
6802 /* Initialize and test routes for MED difference. */
6803 if (aggregate->match_med)
6804 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6805
4056a5f6
RZ
6806 /*
6807 * Reset aggregate count: we might've been called from route map
6808 * update so in that case we must retest all more specific routes.
6809 *
6810 * \see `bgp_route_map_process_update`.
6811 */
6812 aggregate->count = 0;
6813 aggregate->incomplete_origin_count = 0;
6814 aggregate->incomplete_origin_count = 0;
6815 aggregate->egp_origin_count = 0;
6816
d62a17ae 6817 /* ORIGIN attribute: If at least one route among routes that are
6818 aggregated has ORIGIN with the value INCOMPLETE, then the
6819 aggregated route must have the ORIGIN attribute with the value
6820 INCOMPLETE. Otherwise, if at least one route among routes that
6821 are aggregated has ORIGIN with the value EGP, then the aggregated
6822 route must have the origin attribute with the value EGP. In all
6823 other case the value of the ORIGIN attribute of the aggregated
6824 route is INTERNAL. */
6825 origin = BGP_ORIGIN_IGP;
718e3744 6826
d62a17ae 6827 table = bgp->rib[afi][safi];
718e3744 6828
d62a17ae 6829 top = bgp_node_get(table, p);
9bcb3eef
DS
6830 for (dest = bgp_node_get(table, p); dest;
6831 dest = bgp_route_next_until(dest, top)) {
6832 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6833
9bcb3eef 6834 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6835 continue;
d62a17ae 6836
a77e2f4b
S
6837 /* If suppress fib is enabled and route not installed
6838 * in FIB, skip the route
6839 */
6840 if (!bgp_check_advertise(bgp, dest))
6841 continue;
6842
c2ff8b3e 6843 match = 0;
d62a17ae 6844
9bcb3eef 6845 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6846 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6847 continue;
718e3744 6848
40381db7 6849 if (pi->attr->flag
c2ff8b3e
DS
6850 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6851 atomic_aggregate = 1;
d62a17ae 6852
40381db7 6853 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6854 continue;
d62a17ae 6855
f273fef1
DS
6856 /*
6857 * summary-only aggregate route suppress
6858 * aggregated route announcements.
6aabb15d
RZ
6859 *
6860 * MED matching:
6861 * Don't create summaries if MED didn't match
6862 * otherwise neither the specific routes and the
6863 * aggregation will be announced.
f273fef1 6864 */
6aabb15d
RZ
6865 if (aggregate->summary_only
6866 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6867 if (aggr_suppress_path(aggregate, pi))
6868 match++;
d62a17ae 6869 }
c2ff8b3e 6870
365ab2e7
RZ
6871 /*
6872 * Suppress more specific routes that match the route
6873 * map results.
6874 *
6875 * MED matching:
6876 * Don't suppress routes if MED matching is enabled and
6877 * it mismatched otherwise we might end up with no
6878 * routes for this path.
6879 */
6880 if (aggregate->suppress_map_name
6881 && AGGREGATE_MED_VALID(aggregate)
6882 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
6883 if (aggr_suppress_path(aggregate, pi))
6884 match++;
d62a17ae 6885 }
c2ff8b3e
DS
6886
6887 aggregate->count++;
6888
f273fef1
DS
6889 /*
6890 * If at least one route among routes that are
6891 * aggregated has ORIGIN with the value INCOMPLETE,
6892 * then the aggregated route MUST have the ORIGIN
6893 * attribute with the value INCOMPLETE. Otherwise, if
6894 * at least one route among routes that are aggregated
6895 * has ORIGIN with the value EGP, then the aggregated
6896 * route MUST have the ORIGIN attribute with the value
6897 * EGP.
6898 */
fc968841
NT
6899 switch (pi->attr->origin) {
6900 case BGP_ORIGIN_INCOMPLETE:
6901 aggregate->incomplete_origin_count++;
6902 break;
6903 case BGP_ORIGIN_EGP:
6904 aggregate->egp_origin_count++;
6905 break;
6906 default:
6907 /*Do nothing.
6908 */
6909 break;
6910 }
c2ff8b3e
DS
6911
6912 if (!aggregate->as_set)
6913 continue;
6914
f273fef1
DS
6915 /*
6916 * as-set aggregate route generate origin, as path,
6917 * and community aggregation.
6918 */
fc968841
NT
6919 /* Compute aggregate route's as-path.
6920 */
ef51a7d8 6921 bgp_compute_aggregate_aspath_hash(aggregate,
6922 pi->attr->aspath);
c2ff8b3e 6923
fc968841
NT
6924 /* Compute aggregate route's community.
6925 */
6926 if (pi->attr->community)
21fec674 6927 bgp_compute_aggregate_community_hash(
fc968841
NT
6928 aggregate,
6929 pi->attr->community);
dd18c5a9 6930
fc968841
NT
6931 /* Compute aggregate route's extended community.
6932 */
6933 if (pi->attr->ecommunity)
4edd83f9 6934 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6935 aggregate,
6936 pi->attr->ecommunity);
6937
6938 /* Compute aggregate route's large community.
6939 */
6940 if (pi->attr->lcommunity)
f1eb1f05 6941 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6942 aggregate,
6943 pi->attr->lcommunity);
d62a17ae 6944 }
c2ff8b3e 6945 if (match)
9bcb3eef 6946 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6947 }
21fec674 6948 if (aggregate->as_set) {
ef51a7d8 6949 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6950 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6951 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6952 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6953 }
6954
f1eb1f05 6955
9bcb3eef 6956 bgp_dest_unlock_node(top);
718e3744 6957
718e3744 6958
fc968841
NT
6959 if (aggregate->incomplete_origin_count > 0)
6960 origin = BGP_ORIGIN_INCOMPLETE;
6961 else if (aggregate->egp_origin_count > 0)
6962 origin = BGP_ORIGIN_EGP;
d62a17ae 6963
229757f1
DA
6964 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6965 origin = aggregate->origin;
6966
fc968841
NT
6967 if (aggregate->as_set) {
6968 if (aggregate->aspath)
6969 /* Retrieve aggregate route's as-path.
6970 */
6971 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6972
fc968841
NT
6973 if (aggregate->community)
6974 /* Retrieve aggregate route's community.
6975 */
6976 community = community_dup(aggregate->community);
3da2cc32 6977
fc968841
NT
6978 if (aggregate->ecommunity)
6979 /* Retrieve aggregate route's ecommunity.
6980 */
6981 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6982
fc968841
NT
6983 if (aggregate->lcommunity)
6984 /* Retrieve aggregate route's lcommunity.
6985 */
6986 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6987 }
718e3744 6988
c701010e 6989 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6990 ecommunity, lcommunity, atomic_aggregate,
6991 aggregate);
718e3744 6992}
6993
5f040085
DS
6994void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6995 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6996{
6997 struct bgp_table *table;
9bcb3eef
DS
6998 struct bgp_dest *top;
6999 struct bgp_dest *dest;
40381db7 7000 struct bgp_path_info *pi;
3b7db173
DS
7001 unsigned long match;
7002
7003 table = bgp->rib[afi][safi];
7004
7005 /* If routes exists below this node, generate aggregate routes. */
7006 top = bgp_node_get(table, p);
9bcb3eef
DS
7007 for (dest = bgp_node_get(table, p); dest;
7008 dest = bgp_route_next_until(dest, top)) {
7009 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7010
9bcb3eef 7011 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7012 continue;
7013 match = 0;
7014
9bcb3eef 7015 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7016 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7017 continue;
7018
40381db7 7019 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7020 continue;
7021
6aabb15d
RZ
7022 if (aggregate->summary_only && pi->extra
7023 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7024 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7025 match++;
3b7db173 7026 }
3b7db173 7027
365ab2e7
RZ
7028 if (aggregate->suppress_map_name
7029 && AGGREGATE_MED_VALID(aggregate)
7030 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7031 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7032 match++;
3b7db173 7033 }
365ab2e7 7034
3b7db173 7035 aggregate->count--;
fc968841
NT
7036
7037 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7038 aggregate->incomplete_origin_count--;
7039 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7040 aggregate->egp_origin_count--;
7041
7042 if (aggregate->as_set) {
7043 /* Remove as-path from aggregate.
7044 */
ef51a7d8 7045 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7046 aggregate,
7047 pi->attr->aspath);
7048
7049 if (pi->attr->community)
7050 /* Remove community from aggregate.
7051 */
21fec674 7052 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7053 aggregate,
7054 pi->attr->community);
7055
7056 if (pi->attr->ecommunity)
7057 /* Remove ecommunity from aggregate.
7058 */
4edd83f9 7059 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7060 aggregate,
7061 pi->attr->ecommunity);
7062
7063 if (pi->attr->lcommunity)
7064 /* Remove lcommunity from aggregate.
7065 */
f1eb1f05 7066 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7067 aggregate,
7068 pi->attr->lcommunity);
7069 }
3b7db173
DS
7070 }
7071
7072 /* If this node was suppressed, process the change. */
7073 if (match)
9bcb3eef 7074 bgp_process(bgp, dest, afi, safi);
3b7db173 7075 }
f1eb1f05 7076 if (aggregate->as_set) {
ef51a7d8 7077 aspath_free(aggregate->aspath);
7078 aggregate->aspath = NULL;
21fec674 7079 if (aggregate->community)
7080 community_free(&aggregate->community);
4edd83f9 7081 if (aggregate->ecommunity)
7082 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7083 if (aggregate->lcommunity)
7084 lcommunity_free(&aggregate->lcommunity);
7085 }
7086
9bcb3eef 7087 bgp_dest_unlock_node(top);
3b7db173 7088}
718e3744 7089
5f040085
DS
7090static void bgp_add_route_to_aggregate(struct bgp *bgp,
7091 const struct prefix *aggr_p,
fc968841
NT
7092 struct bgp_path_info *pinew, afi_t afi,
7093 safi_t safi,
7094 struct bgp_aggregate *aggregate)
7095{
7096 uint8_t origin;
7097 struct aspath *aspath = NULL;
7098 uint8_t atomic_aggregate = 0;
7099 struct community *community = NULL;
7100 struct ecommunity *ecommunity = NULL;
7101 struct lcommunity *lcommunity = NULL;
7102
7103 /* ORIGIN attribute: If at least one route among routes that are
7104 * aggregated has ORIGIN with the value INCOMPLETE, then the
7105 * aggregated route must have the ORIGIN attribute with the value
7106 * INCOMPLETE. Otherwise, if at least one route among routes that
7107 * are aggregated has ORIGIN with the value EGP, then the aggregated
7108 * route must have the origin attribute with the value EGP. In all
7109 * other case the value of the ORIGIN attribute of the aggregated
7110 * route is INTERNAL.
7111 */
7112 origin = BGP_ORIGIN_IGP;
7113
7114 aggregate->count++;
7115
6aabb15d
RZ
7116 /*
7117 * This must be called before `summary` check to avoid
7118 * "suppressing" twice.
7119 */
7120 if (aggregate->match_med)
7121 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7122 pinew, true);
7123
7124 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7125 aggr_suppress_path(aggregate, pinew);
fc968841 7126
365ab2e7
RZ
7127 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7128 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7129 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7130
7131 switch (pinew->attr->origin) {
7132 case BGP_ORIGIN_INCOMPLETE:
7133 aggregate->incomplete_origin_count++;
7134 break;
7135 case BGP_ORIGIN_EGP:
7136 aggregate->egp_origin_count++;
7137 break;
7138 default:
7139 /* Do nothing.
7140 */
7141 break;
7142 }
7143
7144 if (aggregate->incomplete_origin_count > 0)
7145 origin = BGP_ORIGIN_INCOMPLETE;
7146 else if (aggregate->egp_origin_count > 0)
7147 origin = BGP_ORIGIN_EGP;
7148
229757f1
DA
7149 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7150 origin = aggregate->origin;
7151
fc968841
NT
7152 if (aggregate->as_set) {
7153 /* Compute aggregate route's as-path.
7154 */
7155 bgp_compute_aggregate_aspath(aggregate,
7156 pinew->attr->aspath);
7157
7158 /* Compute aggregate route's community.
7159 */
7160 if (pinew->attr->community)
7161 bgp_compute_aggregate_community(
7162 aggregate,
7163 pinew->attr->community);
7164
7165 /* Compute aggregate route's extended community.
7166 */
7167 if (pinew->attr->ecommunity)
7168 bgp_compute_aggregate_ecommunity(
7169 aggregate,
7170 pinew->attr->ecommunity);
7171
7172 /* Compute aggregate route's large community.
7173 */
7174 if (pinew->attr->lcommunity)
7175 bgp_compute_aggregate_lcommunity(
7176 aggregate,
7177 pinew->attr->lcommunity);
7178
7179 /* Retrieve aggregate route's as-path.
7180 */
7181 if (aggregate->aspath)
7182 aspath = aspath_dup(aggregate->aspath);
7183
7184 /* Retrieve aggregate route's community.
7185 */
7186 if (aggregate->community)
7187 community = community_dup(aggregate->community);
7188
7189 /* Retrieve aggregate route's ecommunity.
7190 */
7191 if (aggregate->ecommunity)
7192 ecommunity = ecommunity_dup(aggregate->ecommunity);
7193
7194 /* Retrieve aggregate route's lcommunity.
7195 */
7196 if (aggregate->lcommunity)
7197 lcommunity = lcommunity_dup(aggregate->lcommunity);
7198 }
7199
7200 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7201 aspath, community, ecommunity,
7202 lcommunity, atomic_aggregate, aggregate);
7203}
7204
7205static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7206 safi_t safi,
7207 struct bgp_path_info *pi,
7208 struct bgp_aggregate *aggregate,
5f040085 7209 const struct prefix *aggr_p)
fc968841
NT
7210{
7211 uint8_t origin;
7212 struct aspath *aspath = NULL;
7213 uint8_t atomic_aggregate = 0;
7214 struct community *community = NULL;
7215 struct ecommunity *ecommunity = NULL;
7216 struct lcommunity *lcommunity = NULL;
7217 unsigned long match = 0;
7218
7219 if (BGP_PATH_HOLDDOWN(pi))
7220 return;
7221
7222 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7223 return;
7224
4056a5f6
RZ
7225 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7226 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7227 match++;
fc968841 7228
365ab2e7 7229 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7230 && aggr_suppress_map_test(bgp, aggregate, pi))
7231 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7232 match++;
fc968841 7233
6aabb15d 7234 /*
365ab2e7 7235 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7236 * "unsuppressing" twice.
7237 */
7238 if (aggregate->match_med)
7239 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7240 true);
7241
fc968841
NT
7242 if (aggregate->count > 0)
7243 aggregate->count--;
7244
7245 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7246 aggregate->incomplete_origin_count--;
7247 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7248 aggregate->egp_origin_count--;
7249
7250 if (aggregate->as_set) {
7251 /* Remove as-path from aggregate.
7252 */
7253 bgp_remove_aspath_from_aggregate(aggregate,
7254 pi->attr->aspath);
7255
7256 if (pi->attr->community)
7257 /* Remove community from aggregate.
7258 */
7259 bgp_remove_community_from_aggregate(
7260 aggregate,
7261 pi->attr->community);
7262
7263 if (pi->attr->ecommunity)
7264 /* Remove ecommunity from aggregate.
7265 */
7266 bgp_remove_ecommunity_from_aggregate(
7267 aggregate,
7268 pi->attr->ecommunity);
7269
7270 if (pi->attr->lcommunity)
7271 /* Remove lcommunity from aggregate.
7272 */
7273 bgp_remove_lcommunity_from_aggregate(
7274 aggregate,
7275 pi->attr->lcommunity);
7276 }
7277
7278 /* If this node was suppressed, process the change. */
7279 if (match)
7280 bgp_process(bgp, pi->net, afi, safi);
7281
7282 origin = BGP_ORIGIN_IGP;
7283 if (aggregate->incomplete_origin_count > 0)
7284 origin = BGP_ORIGIN_INCOMPLETE;
7285 else if (aggregate->egp_origin_count > 0)
7286 origin = BGP_ORIGIN_EGP;
7287
229757f1
DA
7288 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7289 origin = aggregate->origin;
7290
fc968841
NT
7291 if (aggregate->as_set) {
7292 /* Retrieve aggregate route's as-path.
7293 */
7294 if (aggregate->aspath)
7295 aspath = aspath_dup(aggregate->aspath);
7296
7297 /* Retrieve aggregate route's community.
7298 */
7299 if (aggregate->community)
7300 community = community_dup(aggregate->community);
7301
7302 /* Retrieve aggregate route's ecommunity.
7303 */
7304 if (aggregate->ecommunity)
7305 ecommunity = ecommunity_dup(aggregate->ecommunity);
7306
7307 /* Retrieve aggregate route's lcommunity.
7308 */
7309 if (aggregate->lcommunity)
7310 lcommunity = lcommunity_dup(aggregate->lcommunity);
7311 }
7312
7313 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7314 aspath, community, ecommunity,
7315 lcommunity, atomic_aggregate, aggregate);
7316}
7317
5a1ae2c2 7318void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7319 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7320{
9bcb3eef
DS
7321 struct bgp_dest *child;
7322 struct bgp_dest *dest;
d62a17ae 7323 struct bgp_aggregate *aggregate;
7324 struct bgp_table *table;
718e3744 7325
d62a17ae 7326 table = bgp->aggregate[afi][safi];
f018db83 7327
d62a17ae 7328 /* No aggregates configured. */
7329 if (bgp_table_top_nolock(table) == NULL)
7330 return;
f018db83 7331
d62a17ae 7332 if (p->prefixlen == 0)
7333 return;
718e3744 7334
40381db7 7335 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7336 return;
718e3744 7337
a77e2f4b
S
7338 /* If suppress fib is enabled and route not installed
7339 * in FIB, do not update the aggregate route
7340 */
7341 if (!bgp_check_advertise(bgp, pi->net))
7342 return;
7343
d62a17ae 7344 child = bgp_node_get(table, p);
718e3744 7345
d62a17ae 7346 /* Aggregate address configuration check. */
9bcb3eef
DS
7347 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7348 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7349
9bcb3eef
DS
7350 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7351 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7352 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7353 aggregate);
d62a17ae 7354 }
b1e62edd 7355 }
9bcb3eef 7356 bgp_dest_unlock_node(child);
718e3744 7357}
7358
5a1ae2c2 7359void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7360 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7361{
9bcb3eef
DS
7362 struct bgp_dest *child;
7363 struct bgp_dest *dest;
d62a17ae 7364 struct bgp_aggregate *aggregate;
7365 struct bgp_table *table;
718e3744 7366
d62a17ae 7367 table = bgp->aggregate[afi][safi];
718e3744 7368
d62a17ae 7369 /* No aggregates configured. */
7370 if (bgp_table_top_nolock(table) == NULL)
7371 return;
718e3744 7372
d62a17ae 7373 if (p->prefixlen == 0)
7374 return;
718e3744 7375
d62a17ae 7376 child = bgp_node_get(table, p);
718e3744 7377
d62a17ae 7378 /* Aggregate address configuration check. */
9bcb3eef
DS
7379 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7380 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7381
9bcb3eef
DS
7382 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7383 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7384 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7385 aggregate, dest_p);
d62a17ae 7386 }
b1e62edd 7387 }
9bcb3eef 7388 bgp_dest_unlock_node(child);
d62a17ae 7389}
718e3744 7390
718e3744 7391/* Aggregate route attribute. */
7392#define AGGREGATE_SUMMARY_ONLY 1
7393#define AGGREGATE_AS_SET 1
fb29348a 7394#define AGGREGATE_AS_UNSET 0
718e3744 7395
229757f1
DA
7396static const char *bgp_origin2str(uint8_t origin)
7397{
7398 switch (origin) {
7399 case BGP_ORIGIN_IGP:
7400 return "igp";
7401 case BGP_ORIGIN_EGP:
7402 return "egp";
7403 case BGP_ORIGIN_INCOMPLETE:
7404 return "incomplete";
7405 }
7406 return "n/a";
7407}
7408
37a87b8f
CS
7409int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7410 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7411{
9bcb3eef 7412 struct bgp_dest *dest;
d62a17ae 7413 struct bgp_aggregate *aggregate;
718e3744 7414
37a87b8f 7415 apply_mask(prefix);
d62a17ae 7416 /* Old configuration check. */
37a87b8f 7417 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7418 if (!dest) {
37a87b8f
CS
7419 snprintf(errmsg, errmsg_len,
7420 "There is no aggregate-address configuration.\n");
7421 return -1;
d62a17ae 7422 }
f6269b4f 7423
9bcb3eef 7424 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7425 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7426 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7427 0, aggregate);
d62a17ae 7428
7429 /* Unlock aggregate address configuration. */
9bcb3eef 7430 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7431
7432 if (aggregate->community)
7433 community_free(&aggregate->community);
7434
7435 if (aggregate->community_hash) {
7436 /* Delete all communities in the hash.
7437 */
7438 hash_clean(aggregate->community_hash,
7439 bgp_aggr_community_remove);
7440 /* Free up the community_hash.
7441 */
7442 hash_free(aggregate->community_hash);
7443 }
7444
7445 if (aggregate->ecommunity)
7446 ecommunity_free(&aggregate->ecommunity);
7447
7448 if (aggregate->ecommunity_hash) {
7449 /* Delete all ecommunities in the hash.
7450 */
7451 hash_clean(aggregate->ecommunity_hash,
7452 bgp_aggr_ecommunity_remove);
7453 /* Free up the ecommunity_hash.
7454 */
7455 hash_free(aggregate->ecommunity_hash);
7456 }
7457
7458 if (aggregate->lcommunity)
7459 lcommunity_free(&aggregate->lcommunity);
7460
7461 if (aggregate->lcommunity_hash) {
7462 /* Delete all lcommunities in the hash.
7463 */
7464 hash_clean(aggregate->lcommunity_hash,
7465 bgp_aggr_lcommunity_remove);
7466 /* Free up the lcommunity_hash.
7467 */
7468 hash_free(aggregate->lcommunity_hash);
7469 }
7470
7471 if (aggregate->aspath)
7472 aspath_free(aggregate->aspath);
7473
7474 if (aggregate->aspath_hash) {
7475 /* Delete all as-paths in the hash.
7476 */
7477 hash_clean(aggregate->aspath_hash,
7478 bgp_aggr_aspath_remove);
7479 /* Free up the aspath_hash.
7480 */
7481 hash_free(aggregate->aspath_hash);
7482 }
7483
d62a17ae 7484 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7485 bgp_dest_unlock_node(dest);
7486 bgp_dest_unlock_node(dest);
d62a17ae 7487
37a87b8f 7488 return 0;
d62a17ae 7489}
7490
37a87b8f
CS
7491int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7492 safi_t safi, const char *rmap, uint8_t summary_only,
7493 uint8_t as_set, uint8_t origin, bool match_med,
7494 const char *suppress_map,
7495 char *errmsg, size_t errmsg_len)
d62a17ae 7496{
d62a17ae 7497 int ret;
9bcb3eef 7498 struct bgp_dest *dest;
d62a17ae 7499 struct bgp_aggregate *aggregate;
fb29348a 7500 uint8_t as_set_new = as_set;
37a87b8f 7501 char buf[PREFIX2STR_BUFFER];
d62a17ae 7502
365ab2e7 7503 if (suppress_map && summary_only) {
37a87b8f 7504 snprintf(errmsg, errmsg_len,
365ab2e7 7505 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7506 return -1;
365ab2e7
RZ
7507 }
7508
37a87b8f 7509 apply_mask(prefix);
d62a17ae 7510
37a87b8f
CS
7511 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7512 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7513 snprintf(
7514 errmsg, errmsg_len,
7515 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7516 prefix2str(prefix, buf, PREFIX_STRLEN));
7517 return -1;
3624ac81
DS
7518 }
7519
d62a17ae 7520 /* Old configuration check. */
37a87b8f 7521 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7522 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7523
20894f50 7524 if (aggregate) {
37a87b8f
CS
7525 snprintf(errmsg, errmsg_len,
7526 "There is already same aggregate network.\n");
d62a17ae 7527 /* try to remove the old entry */
37a87b8f
CS
7528 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7529 errmsg_len);
d62a17ae 7530 if (ret) {
37a87b8f
CS
7531 snprintf(errmsg, errmsg_len,
7532 "Error deleting aggregate.\n");
9bcb3eef 7533 bgp_dest_unlock_node(dest);
37a87b8f 7534 return -1;
d62a17ae 7535 }
7536 }
718e3744 7537
d62a17ae 7538 /* Make aggregate address structure. */
7539 aggregate = bgp_aggregate_new();
7540 aggregate->summary_only = summary_only;
6aabb15d 7541 aggregate->match_med = match_med;
fb29348a
DA
7542
7543 /* Network operators MUST NOT locally generate any new
7544 * announcements containing AS_SET or AS_CONFED_SET. If they have
7545 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7546 * SHOULD withdraw those routes and re-announce routes for the
7547 * aggregate or component prefixes (i.e., the more-specific routes
7548 * subsumed by the previously aggregated route) without AS_SET
7549 * or AS_CONFED_SET in the updates.
7550 */
7f972cd8 7551 if (bgp->reject_as_sets) {
fb29348a
DA
7552 if (as_set == AGGREGATE_AS_SET) {
7553 as_set_new = AGGREGATE_AS_UNSET;
7554 zlog_warn(
63efca0e 7555 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7556 __func__);
37a87b8f
CS
7557 snprintf(
7558 errmsg, errmsg_len,
fb29348a
DA
7559 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7560 }
7561 }
7562
7563 aggregate->as_set = as_set_new;
d62a17ae 7564 aggregate->safi = safi;
229757f1
DA
7565 /* Override ORIGIN attribute if defined.
7566 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7567 * to IGP which is not what rfc4271 says.
7568 * This enables the same behavior, optionally.
7569 */
7570 aggregate->origin = origin;
20894f50
DA
7571
7572 if (rmap) {
7573 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7574 route_map_counter_decrement(aggregate->rmap.map);
7575 aggregate->rmap.name =
7576 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7577 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7578 route_map_counter_increment(aggregate->rmap.map);
7579 }
365ab2e7
RZ
7580
7581 if (suppress_map) {
7582 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7583 route_map_counter_decrement(aggregate->suppress_map);
7584
7585 aggregate->suppress_map_name =
7586 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7587 aggregate->suppress_map =
7588 route_map_lookup_by_name(aggregate->suppress_map_name);
7589 route_map_counter_increment(aggregate->suppress_map);
7590 }
7591
9bcb3eef 7592 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7593
d62a17ae 7594 /* Aggregate address insert into BGP routing table. */
37a87b8f 7595 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7596
37a87b8f 7597 return 0;
718e3744 7598}
7599
37a87b8f
CS
7600DEFPY_YANG(
7601 aggregate_addressv4, aggregate_addressv4_cmd,
7602 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7603 "as-set$as_set_s"
7604 "|summary-only$summary_only"
7605 "|route-map WORD$rmap_name"
7606 "|origin <egp|igp|incomplete>$origin_s"
7607 "|matching-MED-only$match_med"
90e21f35 7608 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7609 "}",
7610 NO_STR
7611 "Configure BGP aggregate entries\n"
7612 "Aggregate prefix\n"
7613 "Aggregate address\n"
7614 "Aggregate mask\n"
7615 "Generate AS set path information\n"
7616 "Filter more specific routes from updates\n"
7617 "Apply route map to aggregate network\n"
7618 "Route map name\n"
7619 "BGP origin code\n"
7620 "Remote EGP\n"
7621 "Local IGP\n"
7622 "Unknown heritage\n"
7623 "Only aggregate routes with matching MED\n"
90e21f35
CS
7624 "Suppress the selected more specific routes\n"
7625 "Route map with the route selectors\n")
37a87b8f
CS
7626{
7627 char base_xpath[XPATH_MAXLEN];
554b3b10 7628 safi_t safi = bgp_node_safi(vty);
554b3b10 7629 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7630
554b3b10
RZ
7631 if (addr_str) {
7632 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7633 == 0) {
7634 vty_out(vty, "%% Inconsistent address and mask\n");
7635 return CMD_WARNING_CONFIG_FAILED;
7636 }
37a87b8f
CS
7637 } else {
7638 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7639 }
7640
37a87b8f
CS
7641 if (!no && origin_s)
7642 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7643
7644 if (!no && as_set_s)
7645 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7646 else
7647 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7648
7649 if (!no && summary_only)
7650 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7651 "true");
7652 else
7653 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7654 "false");
7655
fa423774
CS
7656 if (!no && match_med)
7657 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7658 else
7659 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7660 "false");
7661
37a87b8f
CS
7662 if (rmap_name)
7663 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7664 rmap_name);
7665 else
7666 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7667 NB_OP_DESTROY, NULL);
7668
90e21f35
CS
7669 if (suppress_map)
7670 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7671 suppress_map);
7672 else
7673 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7674 NULL);
7675
37a87b8f
CS
7676 snprintf(
7677 base_xpath, sizeof(base_xpath),
7678 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7679 yang_afi_safi_value2identity(AFI_IP, safi),
7680 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7681
554b3b10 7682 if (no)
37a87b8f
CS
7683 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7684 else
7685 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7686
7687 return nb_cli_apply_changes(vty, base_xpath);
7688}
7689
7690DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7691 "[no] aggregate-address X:X::X:X/M$prefix {"
7692 "as-set$as_set_s"
7693 "|summary-only$summary_only"
7694 "|route-map WORD$rmap_name"
7695 "|origin <egp|igp|incomplete>$origin_s"
7696 "|matching-MED-only$match_med"
90e21f35 7697 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7698 "}",
7699 NO_STR
7700 "Configure BGP aggregate entries\n"
7701 "Aggregate prefix\n"
7702 "Generate AS set path information\n"
7703 "Filter more specific routes from updates\n"
7704 "Apply route map to aggregate network\n"
7705 "Route map name\n"
7706 "BGP origin code\n"
7707 "Remote EGP\n"
7708 "Local IGP\n"
7709 "Unknown heritage\n"
7710 "Only aggregate routes with matching MED\n"
7711 "Suppress the selected more specific routes\n"
90e21f35 7712 "Route map with the route selectors\n")
37a87b8f
CS
7713{
7714 char base_xpath[XPATH_MAXLEN];
7715 safi_t safi = bgp_node_safi(vty);
7716
7717 if (!no && origin_s)
7718 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7719
7720 if (!no && as_set_s)
7721 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7722 else
7723 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7724
7725 if (!no && summary_only)
7726 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7727 "true");
7728 else
7729 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7730 "false");
7731
fa423774
CS
7732 if (!no && match_med)
7733 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7734 else
7735 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7736 "false");
7737
37a87b8f
CS
7738 if (rmap_name)
7739 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7740 rmap_name);
7741
90e21f35
CS
7742 if (suppress_map)
7743 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7744 suppress_map);
7745 else
7746 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7747 NULL);
7748
37a87b8f
CS
7749 snprintf(
7750 base_xpath, sizeof(base_xpath),
7751 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7752 yang_afi_safi_value2identity(AFI_IP6, safi),
7753 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7754
554b3b10 7755 if (no)
37a87b8f
CS
7756 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7757 else
7758 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7759
37a87b8f
CS
7760 return nb_cli_apply_changes(vty, base_xpath);
7761}
7762
7763void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7764 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7765{
7766 uint8_t origin;
7767
7768 vty_out(vty, " aggregate-address %s",
7769 yang_dnode_get_string(dnode, "./prefix"));
7770
7771 if (yang_dnode_get_bool(dnode, "./as-set"))
7772 vty_out(vty, " as-set");
7773
7774 if (yang_dnode_get_bool(dnode, "./summary-only"))
7775 vty_out(vty, " summary-only");
7776
7777 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7778 vty_out(vty, " route-map %s",
7779 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7780
7781 origin = yang_dnode_get_enum(dnode, "./origin");
7782 if (origin != BGP_ORIGIN_UNSPECIFIED)
7783 vty_out(vty, " origin %s", bgp_origin2str(origin));
7784
fa423774
CS
7785 if (yang_dnode_get_bool(dnode, "./match-med"))
7786 vty_out(vty, " matching-MED-only");
7787
37a87b8f 7788 vty_out(vty, "\n");
718e3744 7789}
7790
718e3744 7791/* Redistribute route treatment. */
d62a17ae 7792void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7793 const union g_addr *nexthop, ifindex_t ifindex,
7794 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7795 uint8_t type, unsigned short instance,
7796 route_tag_t tag)
d62a17ae 7797{
4b7e6066 7798 struct bgp_path_info *new;
40381db7
DS
7799 struct bgp_path_info *bpi;
7800 struct bgp_path_info rmap_path;
9bcb3eef 7801 struct bgp_dest *bn;
d62a17ae 7802 struct attr attr;
7803 struct attr *new_attr;
7804 afi_t afi;
b68885f9 7805 route_map_result_t ret;
d62a17ae 7806 struct bgp_redist *red;
7807
7808 /* Make default attribute. */
7809 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7810 /*
7811 * This must not be NULL to satisfy Coverity SA
7812 */
7813 assert(attr.aspath);
9de1f7ff 7814
a4d82a8a 7815 switch (nhtype) {
9de1f7ff
DS
7816 case NEXTHOP_TYPE_IFINDEX:
7817 break;
7818 case NEXTHOP_TYPE_IPV4:
7819 case NEXTHOP_TYPE_IPV4_IFINDEX:
7820 attr.nexthop = nexthop->ipv4;
7821 break;
7822 case NEXTHOP_TYPE_IPV6:
7823 case NEXTHOP_TYPE_IPV6_IFINDEX:
7824 attr.mp_nexthop_global = nexthop->ipv6;
7825 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7826 break;
7827 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7828 switch (p->family) {
7829 case AF_INET:
9de1f7ff 7830 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7831 break;
7832 case AF_INET6:
9de1f7ff
DS
7833 memset(&attr.mp_nexthop_global, 0,
7834 sizeof(attr.mp_nexthop_global));
74489921 7835 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7836 break;
74489921 7837 }
9de1f7ff 7838 break;
d62a17ae 7839 }
74489921 7840 attr.nh_ifindex = ifindex;
f04a80a5 7841
d62a17ae 7842 attr.med = metric;
7843 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7844 attr.tag = tag;
718e3744 7845
d62a17ae 7846 afi = family2afi(p->family);
6aeb9e78 7847
d62a17ae 7848 red = bgp_redist_lookup(bgp, afi, type, instance);
7849 if (red) {
7850 struct attr attr_new;
718e3744 7851
d62a17ae 7852 /* Copy attribute for modification. */
6f4f49b2 7853 attr_new = attr;
718e3744 7854
d62a17ae 7855 if (red->redist_metric_flag)
7856 attr_new.med = red->redist_metric;
718e3744 7857
d62a17ae 7858 /* Apply route-map. */
7859 if (red->rmap.name) {
40381db7
DS
7860 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7861 rmap_path.peer = bgp->peer_self;
7862 rmap_path.attr = &attr_new;
718e3744 7863
d62a17ae 7864 SET_FLAG(bgp->peer_self->rmap_type,
7865 PEER_RMAP_TYPE_REDISTRIBUTE);
7866
1782514f 7867 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 7868
7869 bgp->peer_self->rmap_type = 0;
7870
7871 if (ret == RMAP_DENYMATCH) {
7872 /* Free uninterned attribute. */
7873 bgp_attr_flush(&attr_new);
7874
7875 /* Unintern original. */
7876 aspath_unintern(&attr.aspath);
7877 bgp_redistribute_delete(bgp, p, type, instance);
7878 return;
7879 }
7880 }
7881
637e5ba4 7882 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
7883 bgp_attr_add_gshut_community(&attr_new);
7884
d62a17ae 7885 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7886 SAFI_UNICAST, p, NULL);
7887
7888 new_attr = bgp_attr_intern(&attr_new);
7889
9bcb3eef 7890 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7891 if (bpi->peer == bgp->peer_self
7892 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7893 break;
7894
40381db7 7895 if (bpi) {
d62a17ae 7896 /* Ensure the (source route) type is updated. */
40381db7
DS
7897 bpi->type = type;
7898 if (attrhash_cmp(bpi->attr, new_attr)
7899 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7900 bgp_attr_unintern(&new_attr);
7901 aspath_unintern(&attr.aspath);
9bcb3eef 7902 bgp_dest_unlock_node(bn);
d62a17ae 7903 return;
7904 } else {
7905 /* The attribute is changed. */
40381db7 7906 bgp_path_info_set_flag(bn, bpi,
18ee8310 7907 BGP_PATH_ATTR_CHANGED);
d62a17ae 7908
7909 /* Rewrite BGP route information. */
40381db7
DS
7910 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7911 bgp_path_info_restore(bn, bpi);
d62a17ae 7912 else
40381db7
DS
7913 bgp_aggregate_decrement(
7914 bgp, p, bpi, afi, SAFI_UNICAST);
7915 bgp_attr_unintern(&bpi->attr);
7916 bpi->attr = new_attr;
7917 bpi->uptime = bgp_clock();
d62a17ae 7918
7919 /* Process change. */
40381db7 7920 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7921 SAFI_UNICAST);
7922 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7923 bgp_dest_unlock_node(bn);
d62a17ae 7924 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7925
7926 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7927 || (bgp->inst_type
7928 == BGP_INSTANCE_TYPE_DEFAULT)) {
7929
7930 vpn_leak_from_vrf_update(
40381db7 7931 bgp_get_default(), bgp, bpi);
ddb5b488 7932 }
d62a17ae 7933 return;
7934 }
7935 }
7936
7937 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7938 bgp->peer_self, new_attr, bn);
1defdda8 7939 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7940
7941 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7942 bgp_path_info_add(bn, new);
9bcb3eef 7943 bgp_dest_unlock_node(bn);
d62a17ae 7944 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7945
7946 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7947 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7948
7949 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7950 }
d62a17ae 7951 }
7952
7953 /* Unintern original. */
7954 aspath_unintern(&attr.aspath);
718e3744 7955}
7956
d7c0a89a
QY
7957void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7958 unsigned short instance)
718e3744 7959{
d62a17ae 7960 afi_t afi;
9bcb3eef 7961 struct bgp_dest *dest;
40381db7 7962 struct bgp_path_info *pi;
d62a17ae 7963 struct bgp_redist *red;
718e3744 7964
d62a17ae 7965 afi = family2afi(p->family);
718e3744 7966
d62a17ae 7967 red = bgp_redist_lookup(bgp, afi, type, instance);
7968 if (red) {
9bcb3eef
DS
7969 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7970 SAFI_UNICAST, p, NULL);
d62a17ae 7971
9bcb3eef 7972 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7973 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7974 break;
7975
40381db7 7976 if (pi) {
ddb5b488
PZ
7977 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7978 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7979
7980 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7981 bgp, pi);
ddb5b488 7982 }
40381db7 7983 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7984 bgp_path_info_delete(dest, pi);
7985 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7986 }
9bcb3eef 7987 bgp_dest_unlock_node(dest);
d62a17ae 7988 }
7989}
7990
7991/* Withdraw specified route type's route. */
7992void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7993 unsigned short instance)
d62a17ae 7994{
9bcb3eef 7995 struct bgp_dest *dest;
40381db7 7996 struct bgp_path_info *pi;
d62a17ae 7997 struct bgp_table *table;
7998
7999 table = bgp->rib[afi][SAFI_UNICAST];
8000
9bcb3eef
DS
8001 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8002 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8003 if (pi->peer == bgp->peer_self && pi->type == type
8004 && pi->instance == instance)
d62a17ae 8005 break;
8006
40381db7 8007 if (pi) {
ddb5b488
PZ
8008 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8009 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8010
8011 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8012 bgp, pi);
ddb5b488 8013 }
9bcb3eef 8014 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8015 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8016 bgp_path_info_delete(dest, pi);
8017 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8018 }
718e3744 8019 }
718e3744 8020}
6b0655a2 8021
718e3744 8022/* Static function to display route. */
bd494ec5 8023static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8024 json_object *json, bool wide)
718e3744 8025{
be054588 8026 int len = 0;
d62a17ae 8027 char buf[BUFSIZ];
50e05855 8028 char buf2[BUFSIZ];
718e3744 8029
d62a17ae 8030 if (p->family == AF_INET) {
c6462ff4 8031 if (!json) {
8228a9a7 8032 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8033 } else {
8034 json_object_string_add(json, "prefix",
8035 inet_ntop(p->family,
8036 &p->u.prefix, buf,
8037 BUFSIZ));
8038 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8039 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8040 json_object_string_add(json, "network", buf2);
c6462ff4 8041 }
d62a17ae 8042 } else if (p->family == AF_ETHERNET) {
8228a9a7 8043 len = vty_out(vty, "%pFX", p);
b03b8898 8044 } else if (p->family == AF_EVPN) {
57f7feb6 8045 if (!json)
2dbe669b 8046 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8047 else
60466a63 8048 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8049 } else if (p->family == AF_FLOWSPEC) {
8050 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8051 json ?
8052 NLRI_STRING_FORMAT_JSON_SIMPLE :
8053 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8054 } else {
c6462ff4 8055 if (!json)
8228a9a7 8056 len = vty_out(vty, "%pFX", p);
50e05855
AD
8057 else {
8058 json_object_string_add(json, "prefix",
8059 inet_ntop(p->family,
8060 &p->u.prefix, buf,
8061 BUFSIZ));
8062 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8063 prefix2str(p, buf2, PREFIX_STRLEN);
8064 json_object_string_add(json, "network", buf2);
8065 }
9c92b5f7 8066 }
d62a17ae 8067
9c92b5f7 8068 if (!json) {
ae248832 8069 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8070 if (len < 1)
8071 vty_out(vty, "\n%*s", 20, " ");
8072 else
8073 vty_out(vty, "%*s", len, " ");
8074 }
718e3744 8075}
8076
d62a17ae 8077enum bgp_display_type {
8078 normal_list,
718e3744 8079};
8080
bbb46eb5
DA
8081static const char *
8082bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8083{
8084 switch (reason) {
8085 case bgp_path_selection_none:
8086 return "Nothing to Select";
8087 case bgp_path_selection_first:
8088 return "First path received";
8089 case bgp_path_selection_evpn_sticky_mac:
8090 return "EVPN Sticky Mac";
8091 case bgp_path_selection_evpn_seq:
8092 return "EVPN sequence number";
8093 case bgp_path_selection_evpn_lower_ip:
8094 return "EVPN lower IP";
8095 case bgp_path_selection_evpn_local_path:
8096 return "EVPN local ES path";
8097 case bgp_path_selection_evpn_non_proxy:
8098 return "EVPN non proxy";
8099 case bgp_path_selection_weight:
8100 return "Weight";
8101 case bgp_path_selection_local_pref:
8102 return "Local Pref";
8103 case bgp_path_selection_local_route:
8104 return "Local Route";
8105 case bgp_path_selection_confed_as_path:
8106 return "Confederation based AS Path";
8107 case bgp_path_selection_as_path:
8108 return "AS Path";
8109 case bgp_path_selection_origin:
8110 return "Origin";
8111 case bgp_path_selection_med:
8112 return "MED";
8113 case bgp_path_selection_peer:
8114 return "Peer Type";
8115 case bgp_path_selection_confed:
8116 return "Confed Peer Type";
8117 case bgp_path_selection_igp_metric:
8118 return "IGP Metric";
8119 case bgp_path_selection_older:
8120 return "Older Path";
8121 case bgp_path_selection_router_id:
8122 return "Router ID";
8123 case bgp_path_selection_cluster_length:
8124 return "Cluser length";
8125 case bgp_path_selection_stale:
8126 return "Path Staleness";
8127 case bgp_path_selection_local_configured:
8128 return "Locally configured route";
8129 case bgp_path_selection_neighbor_ip:
8130 return "Neighbor IP";
8131 case bgp_path_selection_default:
8132 return "Nothing left to compare";
8133 }
8134 return "Invalid (internal error)";
8135}
8136
18ee8310 8137/* Print the short form route status for a bgp_path_info */
4b7e6066 8138static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8139 struct bgp_path_info *path,
d62a17ae 8140 json_object *json_path)
718e3744 8141{
d62a17ae 8142 if (json_path) {
b05a1c8b 8143
d62a17ae 8144 /* Route status display. */
9b6d8fcf 8145 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8146 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8147
9b6d8fcf 8148 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8149 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8150
4056a5f6 8151 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8152 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8153
9b6d8fcf
DS
8154 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8155 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8156 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8157
d62a17ae 8158 /* Selected */
9b6d8fcf 8159 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8160 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8161
9b6d8fcf 8162 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8163 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8164
bbb46eb5 8165 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8166 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8167 json_object_string_add(json_path, "selectionReason",
8168 bgp_path_selection_reason2str(
8169 path->net->reason));
8170 }
b05a1c8b 8171
9b6d8fcf 8172 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8173 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8174
d62a17ae 8175 /* Internal route. */
9b6d8fcf
DS
8176 if ((path->peer->as)
8177 && (path->peer->as == path->peer->local_as))
d62a17ae 8178 json_object_string_add(json_path, "pathFrom",
8179 "internal");
8180 else
8181 json_object_string_add(json_path, "pathFrom",
8182 "external");
b05a1c8b 8183
d62a17ae 8184 return;
8185 }
b05a1c8b 8186
d62a17ae 8187 /* Route status display. */
9b6d8fcf 8188 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8189 vty_out(vty, "R");
9b6d8fcf 8190 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8191 vty_out(vty, "S");
4056a5f6 8192 else if (bgp_path_suppressed(path))
d62a17ae 8193 vty_out(vty, "s");
9b6d8fcf
DS
8194 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8195 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8196 vty_out(vty, "*");
8197 else
8198 vty_out(vty, " ");
8199
8200 /* Selected */
9b6d8fcf 8201 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8202 vty_out(vty, "h");
9b6d8fcf 8203 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8204 vty_out(vty, "d");
9b6d8fcf 8205 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8206 vty_out(vty, ">");
9b6d8fcf 8207 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8208 vty_out(vty, "=");
8209 else
8210 vty_out(vty, " ");
718e3744 8211
d62a17ae 8212 /* Internal route. */
9b6d8fcf
DS
8213 if (path->peer && (path->peer->as)
8214 && (path->peer->as == path->peer->local_as))
d62a17ae 8215 vty_out(vty, "i");
8216 else
8217 vty_out(vty, " ");
b40d939b 8218}
8219
2ba93fd6
DA
8220static char *bgp_nexthop_hostname(struct peer *peer,
8221 struct bgp_nexthop_cache *bnc)
25b5da8d 8222{
892fedb6 8223 if (peer->hostname
aef999a2 8224 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8225 return peer->hostname;
8226 return NULL;
8227}
8228
b40d939b 8229/* called from terminal list command */
bd494ec5 8230void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8231 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8232 json_object *json_paths, bool wide)
d62a17ae 8233{
aef999a2 8234 int len;
515c2602 8235 struct attr *attr = path->attr;
d62a17ae 8236 json_object *json_path = NULL;
8237 json_object *json_nexthops = NULL;
8238 json_object *json_nexthop_global = NULL;
8239 json_object *json_nexthop_ll = NULL;
6f214dd3 8240 json_object *json_ext_community = NULL;
9df8b37c 8241 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8242 bool nexthop_self =
9b6d8fcf 8243 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8244 bool nexthop_othervrf = false;
43089216 8245 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8246 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8247 char *nexthop_hostname =
8248 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8249 char esi_buf[ESI_STR_LEN];
d62a17ae 8250
8251 if (json_paths)
8252 json_path = json_object_new_object();
8253
8254 /* short status lead text */
9b6d8fcf 8255 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8256
8257 if (!json_paths) {
8258 /* print prefix and mask */
8259 if (!display)
ae248832 8260 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8261 else
ae248832 8262 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8263 } else {
ae248832 8264 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8265 }
47fc97cc 8266
9df8b37c
PZ
8267 /*
8268 * If vrf id of nexthop is different from that of prefix,
8269 * set up printable string to append
8270 */
9b6d8fcf 8271 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8272 const char *self = "";
8273
8274 if (nexthop_self)
8275 self = "<";
8276
8277 nexthop_othervrf = true;
9b6d8fcf 8278 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8279
9b6d8fcf 8280 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8281 snprintf(vrf_id_str, sizeof(vrf_id_str),
8282 "@%s%s", VRFID_NONE_STR, self);
8283 else
8284 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8285 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8286
9b6d8fcf
DS
8287 if (path->extra->bgp_orig->inst_type
8288 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8289
9b6d8fcf 8290 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8291 } else {
8292 const char *self = "";
8293
8294 if (nexthop_self)
8295 self = "<";
8296
8297 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8298 }
8299
445c2480
DS
8300 /*
8301 * For ENCAP and EVPN routes, nexthop address family is not
8302 * neccessarily the same as the prefix address family.
8303 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8304 * EVPN routes are also exchanged with a MP nexthop. Currently,
8305 * this
8306 * is only IPv4, the value will be present in either
8307 * attr->nexthop or
8308 * attr->mp_nexthop_global_in
8309 */
8310 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8311 char buf[BUFSIZ];
8312 char nexthop[128];
8313 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8314
8315 switch (af) {
8316 case AF_INET:
772270f3
QY
8317 snprintf(nexthop, sizeof(nexthop), "%s",
8318 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8319 BUFSIZ));
445c2480
DS
8320 break;
8321 case AF_INET6:
772270f3
QY
8322 snprintf(nexthop, sizeof(nexthop), "%s",
8323 inet_ntop(af, &attr->mp_nexthop_global, buf,
8324 BUFSIZ));
445c2480
DS
8325 break;
8326 default:
772270f3 8327 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8328 break;
d62a17ae 8329 }
d62a17ae 8330
445c2480
DS
8331 if (json_paths) {
8332 json_nexthop_global = json_object_new_object();
8333
515c2602
DA
8334 json_object_string_add(json_nexthop_global, "ip",
8335 nexthop);
8336
939a97f4 8337 if (path->peer->hostname)
515c2602
DA
8338 json_object_string_add(json_nexthop_global,
8339 "hostname",
939a97f4 8340 path->peer->hostname);
515c2602
DA
8341
8342 json_object_string_add(json_nexthop_global, "afi",
8343 (af == AF_INET) ? "ipv4"
8344 : "ipv6");
445c2480
DS
8345 json_object_boolean_true_add(json_nexthop_global,
8346 "used");
aef999a2
DA
8347 } else {
8348 if (nexthop_hostname)
8349 len = vty_out(vty, "%s(%s)%s", nexthop,
8350 nexthop_hostname, vrf_id_str);
8351 else
8352 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8353
ae248832 8354 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8355 if (len < 1)
8356 vty_out(vty, "\n%*s", 36, " ");
8357 else
8358 vty_out(vty, "%*s", len, " ");
8359 }
445c2480
DS
8360 } else if (safi == SAFI_EVPN) {
8361 if (json_paths) {
23d0a753
DA
8362 char buf[BUFSIZ] = {0};
8363
445c2480
DS
8364 json_nexthop_global = json_object_new_object();
8365
515c2602 8366 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8367 inet_ntop(AF_INET,
8368 &attr->nexthop, buf,
8369 sizeof(buf)));
515c2602 8370
939a97f4 8371 if (path->peer->hostname)
515c2602
DA
8372 json_object_string_add(json_nexthop_global,
8373 "hostname",
939a97f4 8374 path->peer->hostname);
515c2602 8375
a4d82a8a
PZ
8376 json_object_string_add(json_nexthop_global, "afi",
8377 "ipv4");
445c2480
DS
8378 json_object_boolean_true_add(json_nexthop_global,
8379 "used");
aef999a2
DA
8380 } else {
8381 if (nexthop_hostname)
8382 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8383 nexthop_hostname, vrf_id_str);
8384 else
8385 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8386 vrf_id_str);
8387
ae248832 8388 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8389 if (len < 1)
8390 vty_out(vty, "\n%*s", 36, " ");
8391 else
8392 vty_out(vty, "%*s", len, " ");
8393 }
d33fc23b 8394 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8395 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8396 if (json_paths) {
23d0a753
DA
8397 char buf[BUFSIZ] = {0};
8398
026b914a 8399 json_nexthop_global = json_object_new_object();
515c2602 8400
026b914a
PG
8401 json_object_string_add(json_nexthop_global,
8402 "afi", "ipv4");
515c2602
DA
8403 json_object_string_add(
8404 json_nexthop_global, "ip",
23d0a753
DA
8405 inet_ntop(AF_INET, &attr->nexthop, buf,
8406 sizeof(buf)));
515c2602 8407
939a97f4 8408 if (path->peer->hostname)
515c2602
DA
8409 json_object_string_add(
8410 json_nexthop_global, "hostname",
939a97f4 8411 path->peer->hostname);
515c2602 8412
50e05855
AD
8413 json_object_boolean_true_add(
8414 json_nexthop_global,
026b914a
PG
8415 "used");
8416 } else {
aef999a2
DA
8417 if (nexthop_hostname)
8418 len = vty_out(vty, "%pI4(%s)%s",
8419 &attr->nexthop,
8420 nexthop_hostname,
8421 vrf_id_str);
8422 else
8423 len = vty_out(vty, "%pI4%s",
8424 &attr->nexthop,
8425 vrf_id_str);
8426
ae248832 8427 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8428 if (len < 1)
8429 vty_out(vty, "\n%*s", 36, " ");
8430 else
8431 vty_out(vty, "%*s", len, " ");
026b914a
PG
8432 }
8433 }
d33fc23b 8434 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8435 if (json_paths) {
23d0a753
DA
8436 char buf[BUFSIZ] = {0};
8437
445c2480 8438 json_nexthop_global = json_object_new_object();
d62a17ae 8439
515c2602 8440 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8441 inet_ntop(AF_INET,
8442 &attr->nexthop, buf,
8443 sizeof(buf)));
515c2602 8444
939a97f4 8445 if (path->peer->hostname)
515c2602
DA
8446 json_object_string_add(json_nexthop_global,
8447 "hostname",
939a97f4 8448 path->peer->hostname);
445c2480 8449
a4d82a8a
PZ
8450 json_object_string_add(json_nexthop_global, "afi",
8451 "ipv4");
445c2480
DS
8452 json_object_boolean_true_add(json_nexthop_global,
8453 "used");
8454 } else {
aef999a2
DA
8455 if (nexthop_hostname)
8456 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8457 nexthop_hostname, vrf_id_str);
8458 else
8459 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8460 vrf_id_str);
9df8b37c 8461
ae248832 8462 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8463 if (len < 1)
8464 vty_out(vty, "\n%*s", 36, " ");
8465 else
8466 vty_out(vty, "%*s", len, " ");
d62a17ae 8467 }
445c2480 8468 }
b05a1c8b 8469
445c2480 8470 /* IPv6 Next Hop */
a4d82a8a 8471 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8472 char buf[BUFSIZ];
d62a17ae 8473
445c2480
DS
8474 if (json_paths) {
8475 json_nexthop_global = json_object_new_object();
a4d82a8a 8476 json_object_string_add(
515c2602
DA
8477 json_nexthop_global, "ip",
8478 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8479 buf, BUFSIZ));
8480
939a97f4 8481 if (path->peer->hostname)
515c2602
DA
8482 json_object_string_add(json_nexthop_global,
8483 "hostname",
939a97f4 8484 path->peer->hostname);
515c2602 8485
a4d82a8a
PZ
8486 json_object_string_add(json_nexthop_global, "afi",
8487 "ipv6");
8488 json_object_string_add(json_nexthop_global, "scope",
8489 "global");
445c2480
DS
8490
8491 /* We display both LL & GL if both have been
8492 * received */
0606039c
DA
8493 if ((attr->mp_nexthop_len
8494 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8495 || (path->peer->conf_if)) {
a4d82a8a 8496 json_nexthop_ll = json_object_new_object();
d62a17ae 8497 json_object_string_add(
515c2602
DA
8498 json_nexthop_ll, "ip",
8499 inet_ntop(AF_INET6,
8500 &attr->mp_nexthop_local, buf,
8501 BUFSIZ));
8502
939a97f4 8503 if (path->peer->hostname)
515c2602
DA
8504 json_object_string_add(
8505 json_nexthop_ll, "hostname",
939a97f4 8506 path->peer->hostname);
515c2602 8507
a4d82a8a
PZ
8508 json_object_string_add(json_nexthop_ll, "afi",
8509 "ipv6");
8510 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8511 "link-local");
d62a17ae 8512
a4d82a8a
PZ
8513 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8514 &attr->mp_nexthop_local)
445c2480
DS
8515 != 0)
8516 && !attr->mp_nexthop_prefer_global)
d62a17ae 8517 json_object_boolean_true_add(
a4d82a8a 8518 json_nexthop_ll, "used");
445c2480
DS
8519 else
8520 json_object_boolean_true_add(
a4d82a8a 8521 json_nexthop_global, "used");
445c2480
DS
8522 } else
8523 json_object_boolean_true_add(
8524 json_nexthop_global, "used");
8525 } else {
8526 /* Display LL if LL/Global both in table unless
8527 * prefer-global is set */
0606039c
DA
8528 if (((attr->mp_nexthop_len
8529 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8530 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8531 || (path->peer->conf_if)) {
8532 if (path->peer->conf_if) {
a4d82a8a 8533 len = vty_out(vty, "%s",
9b6d8fcf 8534 path->peer->conf_if);
ae248832
MK
8535 /* len of IPv6 addr + max len of def
8536 * ifname */
8537 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8538
8539 if (len < 1)
a4d82a8a 8540 vty_out(vty, "\n%*s", 36, " ");
445c2480 8541 else
a4d82a8a 8542 vty_out(vty, "%*s", len, " ");
d62a17ae 8543 } else {
aef999a2
DA
8544 if (nexthop_hostname)
8545 len = vty_out(
8546 vty, "%pI6(%s)%s",
8547 &attr->mp_nexthop_local,
8548 nexthop_hostname,
8549 vrf_id_str);
8550 else
8551 len = vty_out(
8552 vty, "%pI6%s",
8553 &attr->mp_nexthop_local,
8554 vrf_id_str);
8555
ae248832 8556 len = wide ? (41 - len) : (16 - len);
d62a17ae 8557
8558 if (len < 1)
a4d82a8a 8559 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8560 else
a4d82a8a 8561 vty_out(vty, "%*s", len, " ");
d62a17ae 8562 }
445c2480 8563 } else {
aef999a2
DA
8564 if (nexthop_hostname)
8565 len = vty_out(vty, "%pI6(%s)%s",
8566 &attr->mp_nexthop_global,
8567 nexthop_hostname,
8568 vrf_id_str);
8569 else
8570 len = vty_out(vty, "%pI6%s",
8571 &attr->mp_nexthop_global,
8572 vrf_id_str);
8573
ae248832 8574 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8575
8576 if (len < 1)
8577 vty_out(vty, "\n%*s", 36, " ");
8578 else
8579 vty_out(vty, "%*s", len, " ");
d62a17ae 8580 }
8581 }
445c2480 8582 }
718e3744 8583
445c2480
DS
8584 /* MED/Metric */
8585 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8586 if (json_paths)
50e05855 8587 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8588 else if (wide)
8589 vty_out(vty, "%7u", attr->med);
0fbac0b4 8590 else
445c2480 8591 vty_out(vty, "%10u", attr->med);
ae248832
MK
8592 else if (!json_paths) {
8593 if (wide)
8594 vty_out(vty, "%*s", 7, " ");
8595 else
8596 vty_out(vty, "%*s", 10, " ");
8597 }
d62a17ae 8598
445c2480
DS
8599 /* Local Pref */
8600 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8601 if (json_paths)
50e05855 8602 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8603 attr->local_pref);
8604 else
445c2480
DS
8605 vty_out(vty, "%7u", attr->local_pref);
8606 else if (!json_paths)
8607 vty_out(vty, " ");
d62a17ae 8608
445c2480
DS
8609 if (json_paths)
8610 json_object_int_add(json_path, "weight", attr->weight);
8611 else
8612 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8613
445c2480
DS
8614 if (json_paths) {
8615 char buf[BUFSIZ];
a4d82a8a
PZ
8616 json_object_string_add(
8617 json_path, "peerId",
9b6d8fcf 8618 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8619 }
b05a1c8b 8620
445c2480
DS
8621 /* Print aspath */
8622 if (attr->aspath) {
0fbac0b4 8623 if (json_paths)
50e05855 8624 json_object_string_add(json_path, "path",
0fbac0b4
DA
8625 attr->aspath->str);
8626 else
445c2480 8627 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8628 }
f1aa5d8a 8629
445c2480
DS
8630 /* Print origin */
8631 if (json_paths)
a4d82a8a
PZ
8632 json_object_string_add(json_path, "origin",
8633 bgp_origin_long_str[attr->origin]);
445c2480
DS
8634 else
8635 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8636
9df8b37c 8637 if (json_paths) {
d071f237 8638 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8639 json_object_string_add(json_path, "esi",
8640 esi_to_str(&attr->esi,
8641 esi_buf, sizeof(esi_buf)));
8642 }
6f214dd3
CS
8643 if (safi == SAFI_EVPN &&
8644 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8645 json_ext_community = json_object_new_object();
8646 json_object_string_add(json_ext_community,
8647 "string",
8648 attr->ecommunity->str);
8649 json_object_object_add(json_path,
8650 "extendedCommunity",
8651 json_ext_community);
8652 }
8653
9df8b37c
PZ
8654 if (nexthop_self)
8655 json_object_boolean_true_add(json_path,
8656 "announceNexthopSelf");
8657 if (nexthop_othervrf) {
8658 json_object_string_add(json_path, "nhVrfName",
8659 nexthop_vrfname);
8660
8661 json_object_int_add(json_path, "nhVrfId",
8662 ((nexthop_vrfid == VRF_UNKNOWN)
8663 ? -1
8664 : (int)nexthop_vrfid));
8665 }
8666 }
8667
d62a17ae 8668 if (json_paths) {
8669 if (json_nexthop_global || json_nexthop_ll) {
8670 json_nexthops = json_object_new_array();
f1aa5d8a 8671
d62a17ae 8672 if (json_nexthop_global)
8673 json_object_array_add(json_nexthops,
8674 json_nexthop_global);
f1aa5d8a 8675
d62a17ae 8676 if (json_nexthop_ll)
8677 json_object_array_add(json_nexthops,
8678 json_nexthop_ll);
f1aa5d8a 8679
d62a17ae 8680 json_object_object_add(json_path, "nexthops",
8681 json_nexthops);
8682 }
8683
8684 json_object_array_add(json_paths, json_path);
8685 } else {
8686 vty_out(vty, "\n");
6f214dd3 8687
b5e140c8 8688 if (safi == SAFI_EVPN) {
229587fb
AK
8689 struct bgp_path_es_info *path_es_info = NULL;
8690
8691 if (path->extra)
8692 path_es_info = path->extra->es_info;
8693
d071f237 8694 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8695 /* XXX - add these params to the json out */
b5e140c8 8696 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8697 vty_out(vty, "ESI:%s",
8698 esi_to_str(&attr->esi, esi_buf,
8699 sizeof(esi_buf)));
8700 if (path_es_info && path_es_info->es)
8701 vty_out(vty, " VNI: %u",
8702 path_es_info->vni);
8703 vty_out(vty, "\n");
b5e140c8
AK
8704 }
8705 if (attr->flag &
8706 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8707 vty_out(vty, "%*s", 20, " ");
8708 vty_out(vty, "%s\n", attr->ecommunity->str);
8709 }
6f214dd3
CS
8710 }
8711
49e5a4a0 8712#ifdef ENABLE_BGP_VNC
d62a17ae 8713 /* prints an additional line, indented, with VNC info, if
8714 * present */
8715 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8716 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8717#endif
d62a17ae 8718 }
8719}
718e3744 8720
8721/* called from terminal list command */
5f040085
DS
8722void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8723 struct attr *attr, safi_t safi, bool use_json,
ae248832 8724 json_object *json_ar, bool wide)
d62a17ae 8725{
8726 json_object *json_status = NULL;
8727 json_object *json_net = NULL;
aef999a2 8728 int len;
d62a17ae 8729 char buff[BUFSIZ];
dc387b0f 8730
d62a17ae 8731 /* Route status display. */
8732 if (use_json) {
8733 json_status = json_object_new_object();
8734 json_net = json_object_new_object();
8735 } else {
8736 vty_out(vty, "*");
8737 vty_out(vty, ">");
8738 vty_out(vty, " ");
8739 }
718e3744 8740
d62a17ae 8741 /* print prefix and mask */
50e05855 8742 if (use_json) {
dc387b0f
LK
8743 if (safi == SAFI_EVPN)
8744 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8745 else if (p->family == AF_INET || p->family == AF_INET6) {
8746 json_object_string_add(
8747 json_net, "addrPrefix",
8748 inet_ntop(p->family, &p->u.prefix, buff,
8749 BUFSIZ));
8750 json_object_int_add(json_net, "prefixLen",
8751 p->prefixlen);
8752 prefix2str(p, buff, PREFIX_STRLEN);
8753 json_object_string_add(json_net, "network", buff);
8754 }
50e05855 8755 } else
ae248832 8756 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8757
8758 /* Print attribute */
8759 if (attr) {
8760 if (use_json) {
23d0a753
DA
8761 char buf[BUFSIZ] = {0};
8762
d62a17ae 8763 if (p->family == AF_INET
8764 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8765 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8766 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8767 json_object_string_add(
8768 json_net, "nextHop",
23d0a753
DA
8769 inet_ntop(
8770 AF_INET,
8771 &attr->mp_nexthop_global_in,
8772 buf, sizeof(buf)));
d62a17ae 8773 else
8774 json_object_string_add(
8775 json_net, "nextHop",
23d0a753
DA
8776 inet_ntop(AF_INET,
8777 &attr->nexthop, buf,
8778 sizeof(buf)));
d62a17ae 8779 } else if (p->family == AF_INET6
8780 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8781 char buf[BUFSIZ];
8782
8783 json_object_string_add(
aa0a10fc 8784 json_net, "nextHopGlobal",
d62a17ae 8785 inet_ntop(AF_INET6,
8786 &attr->mp_nexthop_global, buf,
8787 BUFSIZ));
23d0a753
DA
8788 } else if (p->family == AF_EVPN
8789 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8790 char buf[BUFSIZ] = {0};
8791
8792 json_object_string_add(
8793 json_net, "nextHop",
8794 inet_ntop(AF_INET,
8795 &attr->mp_nexthop_global_in,
8796 buf, sizeof(buf)));
8797 }
d62a17ae 8798
8799 if (attr->flag
8800 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8801 json_object_int_add(json_net, "metric",
8802 attr->med);
8803
0fbac0b4 8804 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8805 json_object_int_add(json_net, "locPrf",
0fbac0b4 8806 attr->local_pref);
d62a17ae 8807
8808 json_object_int_add(json_net, "weight", attr->weight);
8809
8810 /* Print aspath */
0fbac0b4 8811 if (attr->aspath)
50e05855 8812 json_object_string_add(json_net, "path",
0fbac0b4 8813 attr->aspath->str);
d62a17ae 8814
8815 /* Print origin */
8816 json_object_string_add(json_net, "bgpOriginCode",
8817 bgp_origin_str[attr->origin]);
8818 } else {
8819 if (p->family == AF_INET
8820 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8821 || safi == SAFI_EVPN
8822 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8823 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8824 || safi == SAFI_EVPN)
23d0a753
DA
8825 vty_out(vty, "%-16pI4",
8826 &attr->mp_nexthop_global_in);
ae248832 8827 else if (wide)
23d0a753 8828 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8829 else
23d0a753 8830 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8831 } else if (p->family == AF_INET6
8832 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8833 char buf[BUFSIZ];
8834
8835 len = vty_out(
8836 vty, "%s",
8837 inet_ntop(AF_INET6,
8838 &attr->mp_nexthop_global, buf,
8839 BUFSIZ));
ae248832 8840 len = wide ? (41 - len) : (16 - len);
d62a17ae 8841 if (len < 1)
8842 vty_out(vty, "\n%*s", 36, " ");
8843 else
8844 vty_out(vty, "%*s", len, " ");
8845 }
8846 if (attr->flag
8847 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8848 if (wide)
8849 vty_out(vty, "%7u", attr->med);
8850 else
8851 vty_out(vty, "%10u", attr->med);
8852 else if (wide)
8853 vty_out(vty, " ");
d62a17ae 8854 else
8855 vty_out(vty, " ");
718e3744 8856
d62a17ae 8857 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8858 vty_out(vty, "%7u", attr->local_pref);
8859 else
8860 vty_out(vty, " ");
8861
8862 vty_out(vty, "%7u ", attr->weight);
8863
8864 /* Print aspath */
8865 if (attr->aspath)
8866 aspath_print_vty(vty, "%s", attr->aspath, " ");
8867
8868 /* Print origin */
8869 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8870 }
8871 }
8872 if (use_json) {
8873 json_object_boolean_true_add(json_status, "*");
8874 json_object_boolean_true_add(json_status, ">");
8875 json_object_object_add(json_net, "appliedStatusSymbols",
8876 json_status);
1608ff77 8877
dc387b0f
LK
8878 prefix2str(p, buff, PREFIX_STRLEN);
8879 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8880 } else
8881 vty_out(vty, "\n");
8882}
8883
bd494ec5 8884void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8885 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8886 json_object *json)
8887{
8888 json_object *json_out = NULL;
8889 struct attr *attr;
8890 mpls_label_t label = MPLS_INVALID_LABEL;
8891
9b6d8fcf 8892 if (!path->extra)
d62a17ae 8893 return;
8894
8895 if (json)
8896 json_out = json_object_new_object();
8897
8898 /* short status lead text */
9b6d8fcf 8899 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8900
8901 /* print prefix and mask */
8902 if (json == NULL) {
8903 if (!display)
ae248832 8904 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8905 else
8906 vty_out(vty, "%*s", 17, " ");
8907 }
8908
8909 /* Print attribute */
9b6d8fcf 8910 attr = path->attr;
05864da7
DS
8911 if (((p->family == AF_INET)
8912 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8913 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8914 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
8915 char buf[BUFSIZ] = {0};
8916
05864da7
DS
8917 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8918 || safi == SAFI_EVPN) {
8919 if (json)
8920 json_object_string_add(
8921 json_out, "mpNexthopGlobalIn",
23d0a753
DA
8922 inet_ntop(AF_INET,
8923 &attr->mp_nexthop_global_in,
8924 buf, sizeof(buf)));
05864da7 8925 else
23d0a753
DA
8926 vty_out(vty, "%-16pI4",
8927 &attr->mp_nexthop_global_in);
05864da7
DS
8928 } else {
8929 if (json)
8930 json_object_string_add(
8931 json_out, "nexthop",
23d0a753
DA
8932 inet_ntop(AF_INET, &attr->nexthop, buf,
8933 sizeof(buf)));
05864da7 8934 else
23d0a753 8935 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
8936 }
8937 } else if (((p->family == AF_INET6)
8938 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8939 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8940 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8941 char buf_a[512];
8942
8943 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8944 if (json)
8945 json_object_string_add(
8946 json_out, "mpNexthopGlobalIn",
8947 inet_ntop(AF_INET6,
8948 &attr->mp_nexthop_global,
8949 buf_a, sizeof(buf_a)));
8950 else
8951 vty_out(vty, "%s",
8952 inet_ntop(AF_INET6,
8953 &attr->mp_nexthop_global,
8954 buf_a, sizeof(buf_a)));
8955 } else if (attr->mp_nexthop_len
8956 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8957 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8958 &attr->mp_nexthop_global,
8959 &attr->mp_nexthop_local);
8960 if (json)
8961 json_object_string_add(json_out,
8962 "mpNexthopGlobalLocal",
8963 buf_a);
8964 else
8965 vty_out(vty, "%s", buf_a);
d62a17ae 8966 }
8967 }
8968
9b6d8fcf 8969 label = decode_label(&path->extra->label[0]);
d62a17ae 8970
8971 if (bgp_is_valid_label(&label)) {
8972 if (json) {
8973 json_object_int_add(json_out, "notag", label);
8974 json_object_array_add(json, json_out);
8975 } else {
8976 vty_out(vty, "notag/%d", label);
8977 vty_out(vty, "\n");
8978 }
8979 }
8980}
718e3744 8981
bd494ec5 8982void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8983 struct bgp_path_info *path, int display,
d62a17ae 8984 json_object *json_paths)
718e3744 8985{
d62a17ae 8986 struct attr *attr;
14f51eba 8987 char buf[BUFSIZ] = {0};
d62a17ae 8988 json_object *json_path = NULL;
14f51eba
LK
8989 json_object *json_nexthop = NULL;
8990 json_object *json_overlay = NULL;
856ca177 8991
9b6d8fcf 8992 if (!path->extra)
d62a17ae 8993 return;
718e3744 8994
14f51eba
LK
8995 if (json_paths) {
8996 json_path = json_object_new_object();
8997 json_overlay = json_object_new_object();
8998 json_nexthop = json_object_new_object();
8999 }
9000
d62a17ae 9001 /* short status lead text */
9b6d8fcf 9002 route_vty_short_status_out(vty, path, json_path);
856ca177 9003
d62a17ae 9004 /* print prefix and mask */
9005 if (!display)
ae248832 9006 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9007 else
9008 vty_out(vty, "%*s", 17, " ");
9009
9010 /* Print attribute */
9b6d8fcf 9011 attr = path->attr;
05864da7
DS
9012 char buf1[BUFSIZ];
9013 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9014
05864da7
DS
9015 switch (af) {
9016 case AF_INET:
9017 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9018 if (!json_path) {
9019 vty_out(vty, "%-16s", buf);
9020 } else {
9021 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9022
05864da7 9023 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9024
05864da7
DS
9025 json_object_object_add(json_path, "nexthop",
9026 json_nexthop);
9027 }
9028 break;
9029 case AF_INET6:
9030 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9031 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9032 if (!json_path) {
9033 vty_out(vty, "%s(%s)", buf, buf1);
9034 } else {
9035 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9036
05864da7
DS
9037 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9038 buf1);
14f51eba 9039
05864da7 9040 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9041
05864da7
DS
9042 json_object_object_add(json_path, "nexthop",
9043 json_nexthop);
9044 }
9045 break;
9046 default:
9047 if (!json_path) {
9048 vty_out(vty, "?");
9049 } else {
9050 json_object_string_add(json_nexthop, "Error",
9051 "Unsupported address-family");
d62a17ae 9052 }
05864da7 9053 }
988258b4 9054
6c924775
DS
9055 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9056
9057 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9058 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9059 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9060 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9061
05864da7
DS
9062 if (!json_path)
9063 vty_out(vty, "/%s", buf);
9064 else
9065 json_object_string_add(json_overlay, "gw", buf);
9066
9067 if (attr->ecommunity) {
9068 char *mac = NULL;
9069 struct ecommunity_val *routermac = ecommunity_lookup(
9070 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9071 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9072
9073 if (routermac)
9074 mac = ecom_mac2str((char *)routermac->val);
9075 if (mac) {
9076 if (!json_path) {
c4efd0f4 9077 vty_out(vty, "/%s", mac);
05864da7
DS
9078 } else {
9079 json_object_string_add(json_overlay, "rmac",
9080 mac);
988258b4 9081 }
05864da7 9082 XFREE(MTYPE_TMP, mac);
988258b4 9083 }
05864da7 9084 }
718e3744 9085
05864da7
DS
9086 if (!json_path) {
9087 vty_out(vty, "\n");
9088 } else {
9089 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9090
05864da7 9091 json_object_array_add(json_paths, json_path);
14f51eba 9092 }
d62a17ae 9093}
718e3744 9094
d62a17ae 9095/* dampening route */
5f040085
DS
9096static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9097 struct bgp_path_info *path, int display,
9098 afi_t afi, safi_t safi, bool use_json,
9099 json_object *json)
d62a17ae 9100{
9101 struct attr *attr;
9102 int len;
9103 char timebuf[BGP_UPTIME_LEN];
9104
9105 /* short status lead text */
9b6d8fcf 9106 route_vty_short_status_out(vty, path, json);
d62a17ae 9107
9108 /* print prefix and mask */
9109 if (!use_json) {
9110 if (!display)
ae248832 9111 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9112 else
9113 vty_out(vty, "%*s", 17, " ");
9114 }
9115
9b6d8fcf 9116 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9117 len = 17 - len;
9118 if (len < 1) {
9119 if (!use_json)
9120 vty_out(vty, "\n%*s", 34, " ");
9121 } else {
9122 if (use_json)
9123 json_object_int_add(json, "peerHost", len);
9124 else
9125 vty_out(vty, "%*s", len, " ");
9126 }
9127
9128 if (use_json)
a935f597
DA
9129 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9130 safi, use_json, json);
d62a17ae 9131 else
9b6d8fcf
DS
9132 vty_out(vty, "%s ",
9133 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9134 BGP_UPTIME_LEN, afi, safi,
9135 use_json, json));
d62a17ae 9136
9137 /* Print attribute */
9b6d8fcf 9138 attr = path->attr;
d62a17ae 9139
05864da7
DS
9140 /* Print aspath */
9141 if (attr->aspath) {
d62a17ae 9142 if (use_json)
05864da7
DS
9143 json_object_string_add(json, "asPath",
9144 attr->aspath->str);
d62a17ae 9145 else
05864da7 9146 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9147 }
05864da7
DS
9148
9149 /* Print origin */
9150 if (use_json)
9151 json_object_string_add(json, "origin",
9152 bgp_origin_str[attr->origin]);
9153 else
9154 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9155
d62a17ae 9156 if (!use_json)
9157 vty_out(vty, "\n");
9158}
718e3744 9159
d62a17ae 9160/* flap route */
5f040085
DS
9161static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9162 struct bgp_path_info *path, int display,
9163 afi_t afi, safi_t safi, bool use_json,
9164 json_object *json)
784d3a42 9165{
d62a17ae 9166 struct attr *attr;
9167 struct bgp_damp_info *bdi;
9168 char timebuf[BGP_UPTIME_LEN];
9169 int len;
784d3a42 9170
9b6d8fcf 9171 if (!path->extra)
d62a17ae 9172 return;
784d3a42 9173
9b6d8fcf 9174 bdi = path->extra->damp_info;
784d3a42 9175
d62a17ae 9176 /* short status lead text */
9b6d8fcf 9177 route_vty_short_status_out(vty, path, json);
784d3a42 9178
d62a17ae 9179 /* print prefix and mask */
9180 if (!use_json) {
9181 if (!display)
ae248832 9182 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9183 else
9184 vty_out(vty, "%*s", 17, " ");
9185 }
784d3a42 9186
9b6d8fcf 9187 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9188 len = 16 - len;
9189 if (len < 1) {
9190 if (!use_json)
9191 vty_out(vty, "\n%*s", 33, " ");
9192 } else {
9193 if (use_json)
9194 json_object_int_add(json, "peerHost", len);
9195 else
9196 vty_out(vty, "%*s", len, " ");
9197 }
784d3a42 9198
d62a17ae 9199 len = vty_out(vty, "%d", bdi->flap);
9200 len = 5 - len;
9201 if (len < 1) {
9202 if (!use_json)
9203 vty_out(vty, " ");
9204 } else {
9205 if (use_json)
9206 json_object_int_add(json, "bdiFlap", len);
9207 else
9208 vty_out(vty, "%*s", len, " ");
9209 }
9210
9211 if (use_json)
9212 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9213 json);
9214 else
996c9314
LB
9215 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9216 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9217
9b6d8fcf
DS
9218 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9219 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9220 if (use_json)
9b6d8fcf 9221 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9222 BGP_UPTIME_LEN, afi, safi,
9223 use_json, json);
d62a17ae 9224 else
9225 vty_out(vty, "%s ",
9b6d8fcf 9226 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9227 BGP_UPTIME_LEN, afi,
9228 safi, use_json, json));
d62a17ae 9229 } else {
9230 if (!use_json)
9231 vty_out(vty, "%*s ", 8, " ");
9232 }
9233
9234 /* Print attribute */
9b6d8fcf 9235 attr = path->attr;
d62a17ae 9236
05864da7
DS
9237 /* Print aspath */
9238 if (attr->aspath) {
d62a17ae 9239 if (use_json)
05864da7
DS
9240 json_object_string_add(json, "asPath",
9241 attr->aspath->str);
d62a17ae 9242 else
05864da7 9243 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9244 }
05864da7
DS
9245
9246 /* Print origin */
9247 if (use_json)
9248 json_object_string_add(json, "origin",
9249 bgp_origin_str[attr->origin]);
9250 else
9251 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9252
d62a17ae 9253 if (!use_json)
9254 vty_out(vty, "\n");
9255}
9256
9257static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9258 int *first, const char *header,
9259 json_object *json_adv_to)
9260{
9261 char buf1[INET6_ADDRSTRLEN];
9262 json_object *json_peer = NULL;
9263
9264 if (json_adv_to) {
9265 /* 'advertised-to' is a dictionary of peers we have advertised
9266 * this
9267 * prefix too. The key is the peer's IP or swpX, the value is
9268 * the
9269 * hostname if we know it and "" if not.
9270 */
9271 json_peer = json_object_new_object();
9272
9273 if (peer->hostname)
9274 json_object_string_add(json_peer, "hostname",
9275 peer->hostname);
9276
9277 if (peer->conf_if)
9278 json_object_object_add(json_adv_to, peer->conf_if,
9279 json_peer);
9280 else
9281 json_object_object_add(
9282 json_adv_to,
9283 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9284 json_peer);
9285 } else {
9286 if (*first) {
9287 vty_out(vty, "%s", header);
9288 *first = 0;
9289 }
9290
9291 if (peer->hostname
892fedb6 9292 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9293 if (peer->conf_if)
9294 vty_out(vty, " %s(%s)", peer->hostname,
9295 peer->conf_if);
9296 else
9297 vty_out(vty, " %s(%s)", peer->hostname,
9298 sockunion2str(&peer->su, buf1,
9299 SU_ADDRSTRLEN));
9300 } else {
9301 if (peer->conf_if)
9302 vty_out(vty, " %s", peer->conf_if);
9303 else
9304 vty_out(vty, " %s",
9305 sockunion2str(&peer->su, buf1,
9306 SU_ADDRSTRLEN));
9307 }
9308 }
784d3a42
PG
9309}
9310
dcc68b5e
MS
9311static void route_vty_out_tx_ids(struct vty *vty,
9312 struct bgp_addpath_info_data *d)
9313{
9314 int i;
9315
9316 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9317 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9318 d->addpath_tx_id[i],
9319 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9320 }
9321}
9322
5e4d4c8a 9323static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9324 struct bgp_path_info *pi,
9325 struct attr *attr,
9326 json_object *json_path)
5e4d4c8a
AK
9327{
9328 char esi_buf[ESI_STR_LEN];
9329 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9330 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9331 ATTR_ES_PEER_ROUTER);
9332 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9333 ATTR_ES_PEER_ACTIVE);
9334 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9335 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9336 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9337 if (json_path) {
9338 json_object *json_es_info = NULL;
9339
9340 json_object_string_add(
9341 json_path, "esi",
9342 esi_buf);
9343 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9344 json_es_info = json_object_new_object();
9345 if (es_local)
9346 json_object_boolean_true_add(
9347 json_es_info, "localEs");
9348 if (peer_active)
9349 json_object_boolean_true_add(
9350 json_es_info, "peerActive");
9351 if (peer_proxy)
9352 json_object_boolean_true_add(
9353 json_es_info, "peerProxy");
9354 if (peer_router)
9355 json_object_boolean_true_add(
9356 json_es_info, "peerRouter");
9357 if (attr->mm_sync_seqnum)
9358 json_object_int_add(
9359 json_es_info, "peerSeq",
9360 attr->mm_sync_seqnum);
9361 json_object_object_add(
9362 json_path, "es_info",
9363 json_es_info);
9364 }
9365 } else {
9366 if (bgp_evpn_attr_is_sync(attr))
9367 vty_out(vty,
9368 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9369 esi_buf,
9370 es_local ? "local-es":"",
9371 peer_proxy ? "proxy " : "",
9372 peer_active ? "active ":"",
9373 peer_router ? "router ":"",
9374 attr->mm_sync_seqnum);
9375 else
9376 vty_out(vty, " ESI %s %s\n",
9377 esi_buf,
9378 es_local ? "local-es":"");
9379 }
9380}
9381
9382void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9383 struct bgp_dest *bn, struct bgp_path_info *path,
9384 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9385{
9386 char buf[INET6_ADDRSTRLEN];
9387 char buf1[BUFSIZ];
515c2602 9388 struct attr *attr = path->attr;
d62a17ae 9389 int sockunion_vty_out(struct vty *, union sockunion *);
9390 time_t tbuf;
9391 json_object *json_bestpath = NULL;
9392 json_object *json_cluster_list = NULL;
9393 json_object *json_cluster_list_list = NULL;
9394 json_object *json_ext_community = NULL;
9395 json_object *json_last_update = NULL;
7fd077aa 9396 json_object *json_pmsi = NULL;
d62a17ae 9397 json_object *json_nexthop_global = NULL;
9398 json_object *json_nexthop_ll = NULL;
9399 json_object *json_nexthops = NULL;
9400 json_object *json_path = NULL;
9401 json_object *json_peer = NULL;
9402 json_object *json_string = NULL;
9403 json_object *json_adv_to = NULL;
9404 int first = 0;
9405 struct listnode *node, *nnode;
9406 struct peer *peer;
9407 int addpath_capable;
9408 int has_adj;
9409 unsigned int first_as;
1defdda8 9410 bool nexthop_self =
9b6d8fcf 9411 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9412 int i;
2ba93fd6
DA
9413 char *nexthop_hostname =
9414 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9415
9416 if (json_paths) {
9417 json_path = json_object_new_object();
9418 json_peer = json_object_new_object();
9419 json_nexthop_global = json_object_new_object();
9420 }
9421
44c69747 9422 if (path->extra) {
b57ba6d2 9423 char tag_buf[30];
d62a17ae 9424
d62a17ae 9425 tag_buf[0] = '\0';
9b6d8fcf
DS
9426 if (path->extra && path->extra->num_labels) {
9427 bgp_evpn_label2str(path->extra->label,
9428 path->extra->num_labels, tag_buf,
a4d82a8a 9429 sizeof(tag_buf));
d62a17ae 9430 }
d7325ee7 9431 if (safi == SAFI_EVPN) {
44c69747 9432 if (!json_paths) {
2dbe669b
DA
9433 vty_out(vty, " Route %pFX",
9434 (struct prefix_evpn *)
9435 bgp_dest_get_prefix(bn));
44c69747
LK
9436 if (tag_buf[0] != '\0')
9437 vty_out(vty, " VNI %s", tag_buf);
9438 vty_out(vty, "\n");
9439 } else {
9440 if (tag_buf[0])
9441 json_object_string_add(json_path, "VNI",
9442 tag_buf);
9443 }
d7325ee7
DD
9444 }
9445
44c69747 9446 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9447 struct bgp_path_info *parent_ri;
9bcb3eef 9448 struct bgp_dest *dest, *pdest;
d62a17ae 9449
9b6d8fcf 9450 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9451 dest = parent_ri->net;
9452 if (dest && dest->pdest) {
9453 pdest = dest->pdest;
9454 prefix_rd2str(
9455 (struct prefix_rd *)bgp_dest_get_prefix(
9456 pdest),
9457 buf1, sizeof(buf1));
d7325ee7 9458 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9459 vty_out(vty,
9460 " Imported from %s:%pFX, VNI %s\n",
9461 buf1,
9462 (struct prefix_evpn *)
9463 bgp_dest_get_prefix(
9464 dest),
9465 tag_buf);
d7325ee7 9466 } else
2dbe669b
DA
9467 vty_out(vty,
9468 " Imported from %s:%pFX\n",
9469 buf1,
9470 (struct prefix_evpn *)
9471 bgp_dest_get_prefix(
9472 dest));
d62a17ae 9473 }
9474 }
9475 }
d62a17ae 9476
05864da7
DS
9477 /* Line1 display AS-path, Aggregator */
9478 if (attr->aspath) {
9479 if (json_paths) {
9480 if (!attr->aspath->json)
9481 aspath_str_update(attr->aspath, true);
9482 json_object_lock(attr->aspath->json);
9483 json_object_object_add(json_path, "aspath",
9484 attr->aspath->json);
9485 } else {
9486 if (attr->aspath->segments)
9487 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9488 else
05864da7 9489 vty_out(vty, " Local");
d62a17ae 9490 }
05864da7 9491 }
d62a17ae 9492
05864da7
DS
9493 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9494 if (json_paths)
9495 json_object_boolean_true_add(json_path, "removed");
9496 else
9497 vty_out(vty, ", (removed)");
9498 }
d62a17ae 9499
05864da7
DS
9500 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9501 if (json_paths)
9502 json_object_boolean_true_add(json_path, "stale");
9503 else
9504 vty_out(vty, ", (stale)");
9505 }
d62a17ae 9506
05864da7
DS
9507 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9508 if (json_paths) {
23d0a753
DA
9509 char buf[BUFSIZ] = {0};
9510
05864da7
DS
9511 json_object_int_add(json_path, "aggregatorAs",
9512 attr->aggregator_as);
23d0a753
DA
9513 json_object_string_add(json_path, "aggregatorId",
9514 inet_ntop(AF_INET,
9515 &attr->aggregator_addr,
9516 buf, sizeof(buf)));
87c82131
DA
9517 if (attr->aggregator_as == BGP_AS_ZERO)
9518 json_object_boolean_true_add(
9519 json_path, "aggregatorAsMalformed");
9520 else
9521 json_object_boolean_false_add(
9522 json_path, "aggregatorAsMalformed");
05864da7 9523 } else {
87c82131
DA
9524 if (attr->aggregator_as == BGP_AS_ZERO)
9525 vty_out(vty,
23d0a753 9526 ", (aggregated by %u(malformed) %pI4)",
87c82131 9527 attr->aggregator_as,
23d0a753 9528 &attr->aggregator_addr);
87c82131 9529 else
23d0a753 9530 vty_out(vty, ", (aggregated by %u %pI4)",
87c82131 9531 attr->aggregator_as,
23d0a753 9532 &attr->aggregator_addr);
d62a17ae 9533 }
05864da7 9534 }
d62a17ae 9535
05864da7
DS
9536 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9537 PEER_FLAG_REFLECTOR_CLIENT)) {
9538 if (json_paths)
9539 json_object_boolean_true_add(json_path,
9540 "rxedFromRrClient");
9541 else
9542 vty_out(vty, ", (Received from a RR-client)");
9543 }
d62a17ae 9544
05864da7
DS
9545 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9546 PEER_FLAG_RSERVER_CLIENT)) {
9547 if (json_paths)
9548 json_object_boolean_true_add(json_path,
9549 "rxedFromRsClient");
9550 else
9551 vty_out(vty, ", (Received from a RS-client)");
9552 }
d62a17ae 9553
05864da7
DS
9554 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9555 if (json_paths)
9556 json_object_boolean_true_add(json_path,
9557 "dampeningHistoryEntry");
9558 else
9559 vty_out(vty, ", (history entry)");
9560 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9561 if (json_paths)
9562 json_object_boolean_true_add(json_path,
9563 "dampeningSuppressed");
9564 else
9565 vty_out(vty, ", (suppressed due to dampening)");
9566 }
d62a17ae 9567
05864da7
DS
9568 if (!json_paths)
9569 vty_out(vty, "\n");
d62a17ae 9570
05864da7
DS
9571 /* Line2 display Next-hop, Neighbor, Router-id */
9572 /* Display the nexthop */
9bcb3eef 9573 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9574
9575 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9576 || bn_p->family == AF_EVPN)
05864da7
DS
9577 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9578 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9579 char buf[BUFSIZ] = {0};
9580
05864da7
DS
9581 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9582 || safi == SAFI_EVPN) {
515c2602 9583 if (json_paths) {
d62a17ae 9584 json_object_string_add(
515c2602 9585 json_nexthop_global, "ip",
23d0a753
DA
9586 inet_ntop(AF_INET,
9587 &attr->mp_nexthop_global_in,
9588 buf, sizeof(buf)));
515c2602 9589
939a97f4 9590 if (path->peer->hostname)
515c2602
DA
9591 json_object_string_add(
9592 json_nexthop_global, "hostname",
939a97f4 9593 path->peer->hostname);
aef999a2
DA
9594 } else {
9595 if (nexthop_hostname)
9596 vty_out(vty, " %pI4(%s)",
9597 &attr->mp_nexthop_global_in,
9598 nexthop_hostname);
9599 else
9600 vty_out(vty, " %pI4",
9601 &attr->mp_nexthop_global_in);
9602 }
d62a17ae 9603 } else {
515c2602 9604 if (json_paths) {
05864da7 9605 json_object_string_add(
515c2602 9606 json_nexthop_global, "ip",
23d0a753
DA
9607 inet_ntop(AF_INET, &attr->nexthop, buf,
9608 sizeof(buf)));
515c2602 9609
939a97f4 9610 if (path->peer->hostname)
515c2602
DA
9611 json_object_string_add(
9612 json_nexthop_global, "hostname",
939a97f4 9613 path->peer->hostname);
aef999a2
DA
9614 } else {
9615 if (nexthop_hostname)
9616 vty_out(vty, " %pI4(%s)",
9617 &attr->nexthop,
9618 nexthop_hostname);
9619 else
9620 vty_out(vty, " %pI4",
9621 &attr->nexthop);
9622 }
d62a17ae 9623 }
9624
05864da7
DS
9625 if (json_paths)
9626 json_object_string_add(json_nexthop_global, "afi",
9627 "ipv4");
9628 } else {
9629 if (json_paths) {
9630 json_object_string_add(
515c2602
DA
9631 json_nexthop_global, "ip",
9632 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9633 buf, INET6_ADDRSTRLEN));
9634
939a97f4 9635 if (path->peer->hostname)
515c2602
DA
9636 json_object_string_add(json_nexthop_global,
9637 "hostname",
939a97f4 9638 path->peer->hostname);
515c2602 9639
05864da7
DS
9640 json_object_string_add(json_nexthop_global, "afi",
9641 "ipv6");
9642 json_object_string_add(json_nexthop_global, "scope",
9643 "global");
9644 } else {
aef999a2
DA
9645 if (nexthop_hostname)
9646 vty_out(vty, " %pI6(%s)",
9647 &attr->mp_nexthop_global,
9648 nexthop_hostname);
9649 else
9650 vty_out(vty, " %pI6",
9651 &attr->mp_nexthop_global);
d62a17ae 9652 }
05864da7 9653 }
d62a17ae 9654
05864da7
DS
9655 /* Display the IGP cost or 'inaccessible' */
9656 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9657 if (json_paths)
9658 json_object_boolean_false_add(json_nexthop_global,
9659 "accessible");
9660 else
9661 vty_out(vty, " (inaccessible)");
9662 } else {
9663 if (path->extra && path->extra->igpmetric) {
d62a17ae 9664 if (json_paths)
05864da7
DS
9665 json_object_int_add(json_nexthop_global,
9666 "metric",
9667 path->extra->igpmetric);
d62a17ae 9668 else
05864da7
DS
9669 vty_out(vty, " (metric %u)",
9670 path->extra->igpmetric);
d62a17ae 9671 }
9672
05864da7 9673 /* IGP cost is 0, display this only for json */
d62a17ae 9674 else {
d62a17ae 9675 if (json_paths)
05864da7
DS
9676 json_object_int_add(json_nexthop_global,
9677 "metric", 0);
d62a17ae 9678 }
d62a17ae 9679
05864da7
DS
9680 if (json_paths)
9681 json_object_boolean_true_add(json_nexthop_global,
9682 "accessible");
9683 }
d62a17ae 9684
05864da7
DS
9685 /* Display peer "from" output */
9686 /* This path was originated locally */
9687 if (path->peer == bgp->peer_self) {
d62a17ae 9688
05864da7 9689 if (safi == SAFI_EVPN
b54892e0 9690 || (bn_p->family == AF_INET
05864da7 9691 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9692 if (json_paths)
05864da7
DS
9693 json_object_string_add(json_peer, "peerId",
9694 "0.0.0.0");
d62a17ae 9695 else
05864da7
DS
9696 vty_out(vty, " from 0.0.0.0 ");
9697 } else {
d62a17ae 9698 if (json_paths)
05864da7
DS
9699 json_object_string_add(json_peer, "peerId",
9700 "::");
d62a17ae 9701 else
05864da7 9702 vty_out(vty, " from :: ");
d62a17ae 9703 }
d62a17ae 9704
23d0a753
DA
9705 if (json_paths) {
9706 char buf[BUFSIZ] = {0};
9707
05864da7 9708 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9709 inet_ntop(AF_INET,
9710 &bgp->router_id, buf,
9711 sizeof(buf)));
9712 } else {
9713 vty_out(vty, "(%pI4)", &bgp->router_id);
9714 }
05864da7 9715 }
d62a17ae 9716
05864da7
DS
9717 /* We RXed this path from one of our peers */
9718 else {
9719
9720 if (json_paths) {
9721 json_object_string_add(json_peer, "peerId",
9722 sockunion2str(&path->peer->su,
9723 buf,
9724 SU_ADDRSTRLEN));
9725 json_object_string_add(json_peer, "routerId",
9726 inet_ntop(AF_INET,
9727 &path->peer->remote_id,
9728 buf1, sizeof(buf1)));
9729
9730 if (path->peer->hostname)
9731 json_object_string_add(json_peer, "hostname",
9732 path->peer->hostname);
9733
9734 if (path->peer->domainname)
9735 json_object_string_add(json_peer, "domainname",
9736 path->peer->domainname);
9737
9738 if (path->peer->conf_if)
9739 json_object_string_add(json_peer, "interface",
9740 path->peer->conf_if);
9741 } else {
9742 if (path->peer->conf_if) {
9743 if (path->peer->hostname
892fedb6
DA
9744 && CHECK_FLAG(path->peer->bgp->flags,
9745 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9746 vty_out(vty, " from %s(%s)",
9747 path->peer->hostname,
9748 path->peer->conf_if);
d62a17ae 9749 else
05864da7 9750 vty_out(vty, " from %s",
9b6d8fcf 9751 path->peer->conf_if);
d62a17ae 9752 } else {
05864da7 9753 if (path->peer->hostname
892fedb6
DA
9754 && CHECK_FLAG(path->peer->bgp->flags,
9755 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9756 vty_out(vty, " from %s(%s)",
9757 path->peer->hostname,
9758 path->peer->host);
d62a17ae 9759 else
05864da7
DS
9760 vty_out(vty, " from %s",
9761 sockunion2str(&path->peer->su,
9762 buf,
9763 SU_ADDRSTRLEN));
d62a17ae 9764 }
d62a17ae 9765
05864da7 9766 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9767 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9768 else
9769 vty_out(vty, " (%s)",
9770 inet_ntop(AF_INET,
9771 &path->peer->remote_id, buf1,
9772 sizeof(buf1)));
d62a17ae 9773 }
05864da7 9774 }
9df8b37c 9775
05864da7
DS
9776 /*
9777 * Note when vrfid of nexthop is different from that of prefix
9778 */
9779 if (path->extra && path->extra->bgp_orig) {
9780 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9781
05864da7
DS
9782 if (json_paths) {
9783 const char *vn;
9df8b37c 9784
05864da7
DS
9785 if (path->extra->bgp_orig->inst_type
9786 == BGP_INSTANCE_TYPE_DEFAULT)
9787 vn = VRF_DEFAULT_NAME;
9788 else
9789 vn = path->extra->bgp_orig->name;
9df8b37c 9790
05864da7 9791 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9792
05864da7
DS
9793 if (nexthop_vrfid == VRF_UNKNOWN) {
9794 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9795 } else {
05864da7
DS
9796 json_object_int_add(json_path, "nhVrfId",
9797 (int)nexthop_vrfid);
9df8b37c 9798 }
05864da7
DS
9799 } else {
9800 if (nexthop_vrfid == VRF_UNKNOWN)
9801 vty_out(vty, " vrf ?");
137147c6
DS
9802 else {
9803 struct vrf *vrf;
9804
9805 vrf = vrf_lookup_by_id(nexthop_vrfid);
9806 vty_out(vty, " vrf %s(%u)",
9807 VRF_LOGNAME(vrf), nexthop_vrfid);
9808 }
9df8b37c 9809 }
05864da7 9810 }
9df8b37c 9811
05864da7
DS
9812 if (nexthop_self) {
9813 if (json_paths) {
9814 json_object_boolean_true_add(json_path,
9815 "announceNexthopSelf");
9816 } else {
9817 vty_out(vty, " announce-nh-self");
9df8b37c 9818 }
05864da7 9819 }
9df8b37c 9820
05864da7
DS
9821 if (!json_paths)
9822 vty_out(vty, "\n");
d62a17ae 9823
05864da7
DS
9824 /* display the link-local nexthop */
9825 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9826 if (json_paths) {
9827 json_nexthop_ll = json_object_new_object();
9828 json_object_string_add(
515c2602
DA
9829 json_nexthop_ll, "ip",
9830 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9831 buf, INET6_ADDRSTRLEN));
9832
939a97f4 9833 if (path->peer->hostname)
515c2602
DA
9834 json_object_string_add(json_nexthop_ll,
9835 "hostname",
939a97f4 9836 path->peer->hostname);
515c2602 9837
05864da7
DS
9838 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9839 json_object_string_add(json_nexthop_ll, "scope",
9840 "link-local");
d62a17ae 9841
05864da7
DS
9842 json_object_boolean_true_add(json_nexthop_ll,
9843 "accessible");
d62a17ae 9844
05864da7 9845 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9846 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9847 "used");
9848 else
9849 json_object_boolean_true_add(
9850 json_nexthop_global, "used");
9851 } else {
9852 vty_out(vty, " (%s) %s\n",
9853 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9854 buf, INET6_ADDRSTRLEN),
9855 attr->mp_nexthop_prefer_global
9856 ? "(prefer-global)"
9857 : "(used)");
d62a17ae 9858 }
05864da7
DS
9859 }
9860 /* If we do not have a link-local nexthop then we must flag the
9861 global as "used" */
9862 else {
9863 if (json_paths)
9864 json_object_boolean_true_add(json_nexthop_global,
9865 "used");
9866 }
d62a17ae 9867
b5e140c8 9868 if (safi == SAFI_EVPN &&
5e4d4c8a 9869 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9870 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
9871 }
9872
05864da7
DS
9873 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9874 * Int/Ext/Local, Atomic, best */
9875 if (json_paths)
9876 json_object_string_add(json_path, "origin",
9877 bgp_origin_long_str[attr->origin]);
9878 else
9879 vty_out(vty, " Origin %s",
9880 bgp_origin_long_str[attr->origin]);
9df8b37c 9881
05864da7 9882 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9883 if (json_paths)
05864da7 9884 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9885 else
05864da7
DS
9886 vty_out(vty, ", metric %u", attr->med);
9887 }
9df8b37c 9888
05864da7
DS
9889 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9890 if (json_paths)
0fbac0b4 9891 json_object_int_add(json_path, "locPrf",
05864da7
DS
9892 attr->local_pref);
9893 else
9894 vty_out(vty, ", localpref %u", attr->local_pref);
9895 }
9df8b37c 9896
05864da7
DS
9897 if (attr->weight != 0) {
9898 if (json_paths)
9899 json_object_int_add(json_path, "weight", attr->weight);
9900 else
9901 vty_out(vty, ", weight %u", attr->weight);
9902 }
9df8b37c 9903
05864da7
DS
9904 if (attr->tag != 0) {
9905 if (json_paths)
9906 json_object_int_add(json_path, "tag", attr->tag);
9907 else
9908 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9909 }
9df8b37c 9910
05864da7
DS
9911 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9912 if (json_paths)
9913 json_object_boolean_false_add(json_path, "valid");
9914 else
9915 vty_out(vty, ", invalid");
9916 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9917 if (json_paths)
9918 json_object_boolean_true_add(json_path, "valid");
9919 else
9920 vty_out(vty, ", valid");
9921 }
9df8b37c 9922
05864da7
DS
9923 if (path->peer != bgp->peer_self) {
9924 if (path->peer->as == path->peer->local_as) {
9925 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9926 if (json_paths)
9927 json_object_string_add(
9928 json_peer, "type",
9929 "confed-internal");
d62a17ae 9930 else
05864da7 9931 vty_out(vty, ", confed-internal");
d62a17ae 9932 } else {
05864da7
DS
9933 if (json_paths)
9934 json_object_string_add(
9935 json_peer, "type", "internal");
9936 else
9937 vty_out(vty, ", internal");
9df8b37c 9938 }
05864da7
DS
9939 } else {
9940 if (bgp_confederation_peers_check(bgp,
9941 path->peer->as)) {
9942 if (json_paths)
9943 json_object_string_add(
9944 json_peer, "type",
9945 "confed-external");
d62a17ae 9946 else
05864da7 9947 vty_out(vty, ", confed-external");
d62a17ae 9948 } else {
05864da7
DS
9949 if (json_paths)
9950 json_object_string_add(
9951 json_peer, "type", "external");
9952 else
9953 vty_out(vty, ", external");
d62a17ae 9954 }
9955 }
05864da7
DS
9956 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9957 if (json_paths) {
9958 json_object_boolean_true_add(json_path, "aggregated");
9959 json_object_boolean_true_add(json_path, "local");
9960 } else {
9961 vty_out(vty, ", aggregated, local");
9962 }
9963 } else if (path->type != ZEBRA_ROUTE_BGP) {
9964 if (json_paths)
9965 json_object_boolean_true_add(json_path, "sourced");
9966 else
9967 vty_out(vty, ", sourced");
9968 } else {
9969 if (json_paths) {
9970 json_object_boolean_true_add(json_path, "sourced");
9971 json_object_boolean_true_add(json_path, "local");
9972 } else {
9973 vty_out(vty, ", sourced, local");
d62a17ae 9974 }
05864da7 9975 }
718e3744 9976
05864da7 9977 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9978 if (json_paths)
05864da7
DS
9979 json_object_boolean_true_add(json_path,
9980 "atomicAggregate");
d62a17ae 9981 else
05864da7
DS
9982 vty_out(vty, ", atomic-aggregate");
9983 }
d62a17ae 9984
05864da7
DS
9985 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9986 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9987 && bgp_path_info_mpath_count(path))) {
9988 if (json_paths)
9989 json_object_boolean_true_add(json_path, "multipath");
9990 else
9991 vty_out(vty, ", multipath");
9992 }
50e05855 9993
05864da7
DS
9994 // Mark the bestpath(s)
9995 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9996 first_as = aspath_get_first_as(attr->aspath);
718e3744 9997
05864da7
DS
9998 if (json_paths) {
9999 if (!json_bestpath)
10000 json_bestpath = json_object_new_object();
10001 json_object_int_add(json_bestpath, "bestpathFromAs",
10002 first_as);
10003 } else {
10004 if (first_as)
10005 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10006 else
05864da7 10007 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10008 }
05864da7 10009 }
718e3744 10010
05864da7
DS
10011 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10012 if (json_paths) {
10013 if (!json_bestpath)
10014 json_bestpath = json_object_new_object();
10015 json_object_boolean_true_add(json_bestpath, "overall");
10016 json_object_string_add(
10017 json_bestpath, "selectionReason",
10018 bgp_path_selection_reason2str(bn->reason));
10019 } else {
10020 vty_out(vty, ", best");
10021 vty_out(vty, " (%s)",
10022 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10023 }
05864da7 10024 }
718e3744 10025
05864da7
DS
10026 if (json_bestpath)
10027 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10028
05864da7
DS
10029 if (!json_paths)
10030 vty_out(vty, "\n");
10031
10032 /* Line 4 display Community */
10033 if (attr->community) {
10034 if (json_paths) {
10035 if (!attr->community->json)
10036 community_str(attr->community, true);
10037 json_object_lock(attr->community->json);
10038 json_object_object_add(json_path, "community",
10039 attr->community->json);
10040 } else {
10041 vty_out(vty, " Community: %s\n",
10042 attr->community->str);
d62a17ae 10043 }
05864da7 10044 }
718e3744 10045
05864da7
DS
10046 /* Line 5 display Extended-community */
10047 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10048 if (json_paths) {
10049 json_ext_community = json_object_new_object();
10050 json_object_string_add(json_ext_community, "string",
10051 attr->ecommunity->str);
10052 json_object_object_add(json_path, "extendedCommunity",
10053 json_ext_community);
d62a17ae 10054 } else {
05864da7
DS
10055 vty_out(vty, " Extended Community: %s\n",
10056 attr->ecommunity->str);
d62a17ae 10057 }
05864da7 10058 }
718e3744 10059
05864da7
DS
10060 /* Line 6 display Large community */
10061 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10062 if (json_paths) {
10063 if (!attr->lcommunity->json)
10064 lcommunity_str(attr->lcommunity, true);
10065 json_object_lock(attr->lcommunity->json);
10066 json_object_object_add(json_path, "largeCommunity",
10067 attr->lcommunity->json);
10068 } else {
10069 vty_out(vty, " Large Community: %s\n",
10070 attr->lcommunity->str);
d62a17ae 10071 }
05864da7 10072 }
718e3744 10073
05864da7
DS
10074 /* Line 7 display Originator, Cluster-id */
10075 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10076 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10077 char buf[BUFSIZ] = {0};
10078
05864da7 10079 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10080 if (json_paths)
05864da7
DS
10081 json_object_string_add(
10082 json_path, "originatorId",
23d0a753
DA
10083 inet_ntop(AF_INET, &attr->originator_id,
10084 buf, sizeof(buf)));
d62a17ae 10085 else
23d0a753
DA
10086 vty_out(vty, " Originator: %pI4",
10087 &attr->originator_id);
d62a17ae 10088 }
856ca177 10089
05864da7 10090 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10091 struct cluster_list *cluster =
10092 bgp_attr_get_cluster(attr);
05864da7 10093 int i;
d62a17ae 10094
10095 if (json_paths) {
05864da7
DS
10096 json_cluster_list = json_object_new_object();
10097 json_cluster_list_list =
10098 json_object_new_array();
10099
779fee93 10100 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10101 json_string = json_object_new_string(
779fee93
DS
10102 inet_ntop(AF_INET,
10103 &cluster->list[i],
10104 buf, sizeof(buf)));
05864da7
DS
10105 json_object_array_add(
10106 json_cluster_list_list,
10107 json_string);
10108 }
718e3744 10109
05864da7
DS
10110 /*
10111 * struct cluster_list does not have
10112 * "str" variable like aspath and community
10113 * do. Add this someday if someone asks
10114 * for it.
10115 * json_object_string_add(json_cluster_list,
779fee93 10116 * "string", cluster->str);
05864da7
DS
10117 */
10118 json_object_object_add(json_cluster_list,
10119 "list",
10120 json_cluster_list_list);
10121 json_object_object_add(json_path, "clusterList",
10122 json_cluster_list);
0dc8ee70 10123 } else {
05864da7
DS
10124 vty_out(vty, ", Cluster list: ");
10125
779fee93 10126 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10127 vty_out(vty, "%pI4 ",
779fee93 10128 &cluster->list[i]);
05864da7 10129 }
0dc8ee70 10130 }
d62a17ae 10131 }
718e3744 10132
d62a17ae 10133 if (!json_paths)
10134 vty_out(vty, "\n");
05864da7 10135 }
d62a17ae 10136
05864da7 10137 if (path->extra && path->extra->damp_info)
a935f597 10138 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10139
05864da7
DS
10140 /* Remote Label */
10141 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10142 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10143 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10144
05864da7
DS
10145 if (json_paths)
10146 json_object_int_add(json_path, "remoteLabel", label);
10147 else
10148 vty_out(vty, " Remote label: %d\n", label);
10149 }
d62a17ae 10150
e496b420
HS
10151 /* Remote SID */
10152 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10153 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10154 if (json_paths)
10155 json_object_string_add(json_path, "remoteSid", buf);
10156 else
10157 vty_out(vty, " Remote SID: %s\n", buf);
10158 }
10159
05864da7
DS
10160 /* Label Index */
10161 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10162 if (json_paths)
10163 json_object_int_add(json_path, "labelIndex",
10164 attr->label_index);
10165 else
10166 vty_out(vty, " Label Index: %d\n",
10167 attr->label_index);
10168 }
d62a17ae 10169
05864da7
DS
10170 /* Line 8 display Addpath IDs */
10171 if (path->addpath_rx_id
10172 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10173 if (json_paths) {
10174 json_object_int_add(json_path, "addpathRxId",
10175 path->addpath_rx_id);
d62a17ae 10176
05864da7
DS
10177 /* Keep backwards compatibility with the old API
10178 * by putting TX All's ID in the old field
10179 */
10180 json_object_int_add(
10181 json_path, "addpathTxId",
10182 path->tx_addpath
10183 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10184
05864da7
DS
10185 /* ... but create a specific field for each
10186 * strategy
10187 */
10188 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10189 json_object_int_add(
10190 json_path,
10191 bgp_addpath_names(i)->id_json_name,
10192 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10193 }
05864da7
DS
10194 } else {
10195 vty_out(vty, " AddPath ID: RX %u, ",
10196 path->addpath_rx_id);
d62a17ae 10197
05864da7 10198 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10199 }
05864da7 10200 }
520d5d76 10201
05864da7
DS
10202 /* If we used addpath to TX a non-bestpath we need to display
10203 * "Advertised to" on a path-by-path basis
10204 */
10205 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10206 first = 1;
dcc68b5e 10207
05864da7
DS
10208 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10209 addpath_capable =
10210 bgp_addpath_encode_tx(peer, afi, safi);
10211 has_adj = bgp_adj_out_lookup(
10212 peer, path->net,
10213 bgp_addpath_id_for_peer(peer, afi, safi,
10214 &path->tx_addpath));
10215
10216 if ((addpath_capable && has_adj)
10217 || (!addpath_capable && has_adj
10218 && CHECK_FLAG(path->flags,
10219 BGP_PATH_SELECTED))) {
10220 if (json_path && !json_adv_to)
10221 json_adv_to = json_object_new_object();
dcc68b5e 10222
05864da7
DS
10223 route_vty_out_advertised_to(
10224 vty, peer, &first,
10225 " Advertised to:", json_adv_to);
d62a17ae 10226 }
10227 }
718e3744 10228
05864da7
DS
10229 if (json_path) {
10230 if (json_adv_to) {
10231 json_object_object_add(
10232 json_path, "advertisedTo", json_adv_to);
d62a17ae 10233 }
05864da7
DS
10234 } else {
10235 if (!first) {
10236 vty_out(vty, "\n");
d62a17ae 10237 }
10238 }
05864da7 10239 }
b05a1c8b 10240
05864da7
DS
10241 /* Line 9 display Uptime */
10242 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10243 if (json_paths) {
10244 json_last_update = json_object_new_object();
10245 json_object_int_add(json_last_update, "epoch", tbuf);
10246 json_object_string_add(json_last_update, "string",
10247 ctime(&tbuf));
10248 json_object_object_add(json_path, "lastUpdate",
10249 json_last_update);
10250 } else
10251 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10252
05864da7
DS
10253 /* Line 10 display PMSI tunnel attribute, if present */
10254 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10255 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10256 bgp_attr_get_pmsi_tnl_type(attr),
10257 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10258
05864da7
DS
10259 if (json_paths) {
10260 json_pmsi = json_object_new_object();
10261 json_object_string_add(json_pmsi, "tunnelType", str);
10262 json_object_int_add(json_pmsi, "label",
10263 label2vni(&attr->label));
10264 json_object_object_add(json_path, "pmsi", json_pmsi);
10265 } else
10266 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10267 str, label2vni(&attr->label));
d62a17ae 10268 }
f1aa5d8a 10269
92269aa2
DS
10270 /* Output some debug about internal state of the dest flags */
10271 if (json_paths) {
10272 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10273 json_object_boolean_true_add(json_path, "processScheduled");
10274 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10275 json_object_boolean_true_add(json_path, "userCleared");
10276 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10277 json_object_boolean_true_add(json_path, "labelChanged");
10278 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10279 json_object_boolean_true_add(json_path, "registeredForLabel");
10280 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10281 json_object_boolean_true_add(json_path, "selectDefered");
10282 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10283 json_object_boolean_true_add(json_path, "fibInstalled");
10284 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10285 json_object_boolean_true_add(json_path, "fibPending");
10286 }
10287
d62a17ae 10288 /* We've constructed the json object for this path, add it to the json
10289 * array of paths
10290 */
10291 if (json_paths) {
10292 if (json_nexthop_global || json_nexthop_ll) {
10293 json_nexthops = json_object_new_array();
f1aa5d8a 10294
d62a17ae 10295 if (json_nexthop_global)
10296 json_object_array_add(json_nexthops,
10297 json_nexthop_global);
f1aa5d8a 10298
d62a17ae 10299 if (json_nexthop_ll)
10300 json_object_array_add(json_nexthops,
10301 json_nexthop_ll);
f1aa5d8a 10302
d62a17ae 10303 json_object_object_add(json_path, "nexthops",
10304 json_nexthops);
10305 }
10306
10307 json_object_object_add(json_path, "peer", json_peer);
10308 json_object_array_add(json_paths, json_path);
05864da7 10309 }
b366b518
BB
10310}
10311
96ade3ed 10312#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10313#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10314#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10315
d62a17ae 10316static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10317 const char *prefix_list_str, afi_t afi,
10318 safi_t safi, enum bgp_show_type type);
10319static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10320 const char *filter, afi_t afi, safi_t safi,
10321 enum bgp_show_type type);
10322static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10323 const char *rmap_str, afi_t afi, safi_t safi,
10324 enum bgp_show_type type);
10325static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10326 const char *com, int exact, afi_t afi,
10327 safi_t safi);
10328static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10329 const char *prefix, afi_t afi, safi_t safi,
10330 enum bgp_show_type type);
a4d82a8a 10331static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10332 afi_t afi, safi_t safi, enum bgp_show_type type,
10333 bool use_json);
7f323236
DW
10334static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10335 const char *comstr, int exact, afi_t afi,
96f3485c 10336 safi_t safi, uint8_t show_flags);
d62a17ae 10337
1ae44dfc
LB
10338
10339static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10340 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10341 void *output_arg, char *rd, int is_last,
10342 unsigned long *output_cum, unsigned long *total_cum,
10343 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10344{
40381db7 10345 struct bgp_path_info *pi;
9bcb3eef 10346 struct bgp_dest *dest;
d62a17ae 10347 int header = 1;
10348 int display;
1ae44dfc
LB
10349 unsigned long output_count = 0;
10350 unsigned long total_count = 0;
d62a17ae 10351 struct prefix *p;
d62a17ae 10352 json_object *json_paths = NULL;
10353 int first = 1;
96f3485c
MK
10354 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10355 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10356 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10357
1ae44dfc
LB
10358 if (output_cum && *output_cum != 0)
10359 header = 0;
10360
9386b588 10361 if (use_json && !*json_header_depth) {
96f3485c
MK
10362 if (all)
10363 *json_header_depth = 1;
10364 else {
10365 vty_out(vty, "{\n");
10366 *json_header_depth = 2;
10367 }
10368
d62a17ae 10369 vty_out(vty,
23d0a753
DA
10370 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10371 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10372 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10373 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10374 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10375 ? VRF_DEFAULT_NAME
10376 : bgp->name,
10377 table->version, &bgp->router_id,
01eced22 10378 bgp->default_local_pref, bgp->as);
9386b588 10379 if (rd) {
445c2480 10380 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10381 ++*json_header_depth;
10382 }
d62a17ae 10383 }
718e3744 10384
445c2480
DS
10385 if (use_json && rd) {
10386 vty_out(vty, " \"%s\" : { ", rd);
10387 }
10388
d62a17ae 10389 /* Start processing of routes. */
9bcb3eef
DS
10390 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10391 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10392
9bcb3eef 10393 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10394 if (pi == NULL)
98ce9a06 10395 continue;
d62a17ae 10396
98ce9a06 10397 display = 0;
98ce9a06
DS
10398 if (use_json)
10399 json_paths = json_object_new_array();
10400 else
10401 json_paths = NULL;
d62a17ae 10402
6f94b685 10403 for (; pi; pi = pi->next) {
98ce9a06
DS
10404 total_count++;
10405 if (type == bgp_show_type_flap_statistics
10406 || type == bgp_show_type_flap_neighbor
10407 || type == bgp_show_type_dampend_paths
10408 || type == bgp_show_type_damp_neighbor) {
40381db7 10409 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10410 continue;
10411 }
10412 if (type == bgp_show_type_regexp) {
10413 regex_t *regex = output_arg;
d62a17ae 10414
40381db7 10415 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10416 == REG_NOMATCH)
10417 continue;
10418 }
10419 if (type == bgp_show_type_prefix_list) {
10420 struct prefix_list *plist = output_arg;
d62a17ae 10421
9bcb3eef 10422 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10423 != PREFIX_PERMIT)
10424 continue;
10425 }
10426 if (type == bgp_show_type_filter_list) {
10427 struct as_list *as_list = output_arg;
d62a17ae 10428
40381db7 10429 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10430 != AS_FILTER_PERMIT)
10431 continue;
10432 }
10433 if (type == bgp_show_type_route_map) {
10434 struct route_map *rmap = output_arg;
9b6d8fcf 10435 struct bgp_path_info path;
98ce9a06 10436 struct attr dummy_attr;
b68885f9 10437 route_map_result_t ret;
d62a17ae 10438
6f4f49b2 10439 dummy_attr = *pi->attr;
d62a17ae 10440
40381db7 10441 path.peer = pi->peer;
9b6d8fcf 10442 path.attr = &dummy_attr;
d62a17ae 10443
1782514f 10444 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10445 if (ret == RMAP_DENYMATCH)
10446 continue;
10447 }
10448 if (type == bgp_show_type_neighbor
10449 || type == bgp_show_type_flap_neighbor
10450 || type == bgp_show_type_damp_neighbor) {
10451 union sockunion *su = output_arg;
10452
40381db7
DS
10453 if (pi->peer == NULL
10454 || pi->peer->su_remote == NULL
10455 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10456 continue;
10457 }
10458 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10459 uint32_t destination;
d62a17ae 10460
9bcb3eef 10461 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10462 if (IN_CLASSC(destination)
9bcb3eef 10463 && dest_p->prefixlen == 24)
98ce9a06
DS
10464 continue;
10465 if (IN_CLASSB(destination)
9bcb3eef 10466 && dest_p->prefixlen == 16)
98ce9a06
DS
10467 continue;
10468 if (IN_CLASSA(destination)
9bcb3eef 10469 && dest_p->prefixlen == 8)
98ce9a06
DS
10470 continue;
10471 }
10472 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10473 p = output_arg;
9bcb3eef 10474 if (!prefix_match(p, dest_p))
98ce9a06
DS
10475 continue;
10476 }
10477 if (type == bgp_show_type_community_all) {
40381db7 10478 if (!pi->attr->community)
98ce9a06
DS
10479 continue;
10480 }
10481 if (type == bgp_show_type_community) {
10482 struct community *com = output_arg;
d62a17ae 10483
40381db7
DS
10484 if (!pi->attr->community
10485 || !community_match(pi->attr->community,
98ce9a06
DS
10486 com))
10487 continue;
10488 }
10489 if (type == bgp_show_type_community_exact) {
10490 struct community *com = output_arg;
d62a17ae 10491
40381db7
DS
10492 if (!pi->attr->community
10493 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10494 continue;
10495 }
10496 if (type == bgp_show_type_community_list) {
10497 struct community_list *list = output_arg;
d62a17ae 10498
40381db7 10499 if (!community_list_match(pi->attr->community,
a4d82a8a 10500 list))
98ce9a06
DS
10501 continue;
10502 }
a4d82a8a 10503 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10504 struct community_list *list = output_arg;
d62a17ae 10505
98ce9a06 10506 if (!community_list_exact_match(
40381db7 10507 pi->attr->community, list))
98ce9a06
DS
10508 continue;
10509 }
10510 if (type == bgp_show_type_lcommunity) {
10511 struct lcommunity *lcom = output_arg;
d62a17ae 10512
40381db7
DS
10513 if (!pi->attr->lcommunity
10514 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10515 lcom))
10516 continue;
10517 }
36a206db 10518
10519 if (type == bgp_show_type_lcommunity_exact) {
10520 struct lcommunity *lcom = output_arg;
10521
10522 if (!pi->attr->lcommunity
10523 || !lcommunity_cmp(pi->attr->lcommunity,
10524 lcom))
10525 continue;
10526 }
98ce9a06
DS
10527 if (type == bgp_show_type_lcommunity_list) {
10528 struct community_list *list = output_arg;
d62a17ae 10529
40381db7 10530 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10531 list))
98ce9a06
DS
10532 continue;
10533 }
36a206db 10534 if (type
10535 == bgp_show_type_lcommunity_list_exact) {
10536 struct community_list *list = output_arg;
10537
10538 if (!lcommunity_list_exact_match(
10539 pi->attr->lcommunity, list))
10540 continue;
10541 }
98ce9a06 10542 if (type == bgp_show_type_lcommunity_all) {
40381db7 10543 if (!pi->attr->lcommunity)
98ce9a06
DS
10544 continue;
10545 }
10546 if (type == bgp_show_type_dampend_paths
10547 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10548 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10549 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10550 continue;
10551 }
10552
10553 if (!use_json && header) {
23d0a753
DA
10554 vty_out(vty,
10555 "BGP table version is %" PRIu64
10556 ", local router ID is %pI4, vrf id ",
10557 table->version, &bgp->router_id);
9df8b37c
PZ
10558 if (bgp->vrf_id == VRF_UNKNOWN)
10559 vty_out(vty, "%s", VRFID_NONE_STR);
10560 else
10561 vty_out(vty, "%u", bgp->vrf_id);
10562 vty_out(vty, "\n");
01eced22
AD
10563 vty_out(vty, "Default local pref %u, ",
10564 bgp->default_local_pref);
10565 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10566 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10567 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10568 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10569 if (type == bgp_show_type_dampend_paths
10570 || type == bgp_show_type_damp_neighbor)
98ce9a06 10571 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10572 else if (type == bgp_show_type_flap_statistics
10573 || type == bgp_show_type_flap_neighbor)
98ce9a06 10574 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10575 else
ae248832
MK
10576 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10577 : BGP_SHOW_HEADER));
98ce9a06 10578 header = 0;
d62a17ae 10579 }
98ce9a06
DS
10580 if (rd != NULL && !display && !output_count) {
10581 if (!use_json)
10582 vty_out(vty,
10583 "Route Distinguisher: %s\n",
10584 rd);
d62a17ae 10585 }
98ce9a06
DS
10586 if (type == bgp_show_type_dampend_paths
10587 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10588 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10589 AFI_IP, safi, use_json,
10590 json_paths);
98ce9a06
DS
10591 else if (type == bgp_show_type_flap_statistics
10592 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10593 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10594 AFI_IP, safi, use_json,
10595 json_paths);
98ce9a06 10596 else
9bcb3eef 10597 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10598 json_paths, wide);
98ce9a06 10599 display++;
d62a17ae 10600 }
10601
98ce9a06
DS
10602 if (display) {
10603 output_count++;
10604 if (!use_json)
10605 continue;
10606
625d2931 10607 /* encode prefix */
9bcb3eef 10608 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10609 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10610
1840384b 10611
b54892e0
DS
10612 bgp_fs_nlri_get_string(
10613 (unsigned char *)
9bcb3eef
DS
10614 dest_p->u.prefix_flowspec.ptr,
10615 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10616 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10617 family2afi(dest_p->u
10618 .prefix_flowspec.family));
625d2931 10619 if (first)
b54892e0 10620 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10621 dest_p->u.prefix_flowspec
b54892e0 10622 .prefixlen);
625d2931 10623 else
b54892e0 10624 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10625 dest_p->u.prefix_flowspec
b54892e0 10626 .prefixlen);
625d2931 10627 } else {
625d2931 10628 if (first)
1b78780b 10629 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10630 else
1b78780b 10631 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10632 }
98ce9a06 10633 vty_out(vty, "%s",
f4ec52f7
DA
10634 json_object_to_json_string_ext(
10635 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10636 json_object_free(json_paths);
449feb8e 10637 json_paths = NULL;
98ce9a06 10638 first = 0;
1f83ed02
DS
10639 } else
10640 json_object_free(json_paths);
98ce9a06
DS
10641 }
10642
1ae44dfc
LB
10643 if (output_cum) {
10644 output_count += *output_cum;
10645 *output_cum = output_count;
10646 }
10647 if (total_cum) {
10648 total_count += *total_cum;
10649 *total_cum = total_count;
10650 }
d62a17ae 10651 if (use_json) {
9386b588 10652 if (rd) {
a4d82a8a 10653 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10654 }
10655 if (is_last) {
a4d82a8a
PZ
10656 unsigned long i;
10657 for (i = 0; i < *json_header_depth; ++i)
10658 vty_out(vty, " } ");
96f3485c
MK
10659 if (!all)
10660 vty_out(vty, "\n");
9386b588 10661 }
d62a17ae 10662 } else {
1ae44dfc
LB
10663 if (is_last) {
10664 /* No route is displayed */
10665 if (output_count == 0) {
10666 if (type == bgp_show_type_normal)
10667 vty_out(vty,
10668 "No BGP prefixes displayed, %ld exist\n",
10669 total_count);
10670 } else
d62a17ae 10671 vty_out(vty,
1ae44dfc
LB
10672 "\nDisplayed %ld routes and %ld total paths\n",
10673 output_count, total_count);
10674 }
d62a17ae 10675 }
718e3744 10676
d62a17ae 10677 return CMD_SUCCESS;
718e3744 10678}
10679
1ae44dfc
LB
10680int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10681 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10682 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10683{
9bcb3eef 10684 struct bgp_dest *dest, *next;
1ae44dfc
LB
10685 unsigned long output_cum = 0;
10686 unsigned long total_cum = 0;
9386b588 10687 unsigned long json_header_depth = 0;
67009e22 10688 struct bgp_table *itable;
0136788c 10689 bool show_msg;
96f3485c 10690 uint8_t show_flags = 0;
0136788c
LB
10691
10692 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10693
96f3485c
MK
10694 if (use_json)
10695 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10696
9bcb3eef
DS
10697 for (dest = bgp_table_top(table); dest; dest = next) {
10698 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10699
9bcb3eef
DS
10700 next = bgp_route_next(dest);
10701 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10702 continue;
67009e22 10703
9bcb3eef 10704 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10705 if (itable != NULL) {
1ae44dfc 10706 struct prefix_rd prd;
06b9f471 10707 char rd[RD_ADDRSTRLEN];
1ae44dfc 10708
9bcb3eef 10709 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10710 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10711 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10712 rd, next == NULL, &output_cum,
10713 &total_cum, &json_header_depth,
10714 show_flags);
0136788c
LB
10715 if (next == NULL)
10716 show_msg = false;
1ae44dfc
LB
10717 }
10718 }
0136788c
LB
10719 if (show_msg) {
10720 if (output_cum == 0)
10721 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10722 total_cum);
10723 else
10724 vty_out(vty,
10725 "\nDisplayed %ld routes and %ld total paths\n",
10726 output_cum, total_cum);
10727 }
1ae44dfc
LB
10728 return CMD_SUCCESS;
10729}
d62a17ae 10730static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10731 enum bgp_show_type type, void *output_arg,
10732 uint8_t show_flags)
fee0f4c6 10733{
d62a17ae 10734 struct bgp_table *table;
9386b588 10735 unsigned long json_header_depth = 0;
96f3485c 10736 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10737
d62a17ae 10738 if (bgp == NULL) {
10739 bgp = bgp_get_default();
10740 }
fee0f4c6 10741
d62a17ae 10742 if (bgp == NULL) {
10743 if (!use_json)
10744 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10745 else
10746 vty_out(vty, "{}\n");
d62a17ae 10747 return CMD_WARNING;
10748 }
4dd6177e 10749
1ae44dfc 10750 table = bgp->rib[afi][safi];
d62a17ae 10751 /* use MPLS and ENCAP specific shows until they are merged */
10752 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10753 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10754 output_arg, use_json);
d62a17ae 10755 }
dba3c1d3
PG
10756
10757 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10758 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10759 output_arg, use_json,
10760 1, NULL, NULL);
10761 }
d62a17ae 10762 /* labeled-unicast routes live in the unicast table */
10763 else if (safi == SAFI_LABELED_UNICAST)
10764 safi = SAFI_UNICAST;
fee0f4c6 10765
96f3485c
MK
10766 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10767 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10768}
10769
d62a17ae 10770static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10771 safi_t safi, uint8_t show_flags)
f186de26 10772{
d62a17ae 10773 struct listnode *node, *nnode;
10774 struct bgp *bgp;
10775 int is_first = 1;
9f049418 10776 bool route_output = false;
96f3485c 10777 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10778
d62a17ae 10779 if (use_json)
10780 vty_out(vty, "{\n");
9f689658 10781
d62a17ae 10782 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10783 route_output = true;
d62a17ae 10784 if (use_json) {
10785 if (!is_first)
10786 vty_out(vty, ",\n");
10787 else
10788 is_first = 0;
10789
10790 vty_out(vty, "\"%s\":",
10791 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10792 ? VRF_DEFAULT_NAME
d62a17ae 10793 : bgp->name);
10794 } else {
10795 vty_out(vty, "\nInstance %s:\n",
10796 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10797 ? VRF_DEFAULT_NAME
d62a17ae 10798 : bgp->name);
10799 }
10800 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10801 show_flags);
d62a17ae 10802 }
9f689658 10803
d62a17ae 10804 if (use_json)
10805 vty_out(vty, "}\n");
9f049418
DS
10806 else if (!route_output)
10807 vty_out(vty, "%% BGP instance not found\n");
f186de26 10808}
10809
718e3744 10810/* Header of detailed BGP route information */
d62a17ae 10811void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10812 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10813 afi_t afi, safi_t safi, json_object *json)
10814{
40381db7 10815 struct bgp_path_info *pi;
b54892e0 10816 const struct prefix *p;
d62a17ae 10817 struct peer *peer;
10818 struct listnode *node, *nnode;
06b9f471 10819 char buf1[RD_ADDRSTRLEN];
0291c246 10820 char prefix_str[BUFSIZ];
d62a17ae 10821 int count = 0;
10822 int best = 0;
10823 int suppress = 0;
c5f1e1b2
C
10824 int accept_own = 0;
10825 int route_filter_translated_v4 = 0;
10826 int route_filter_v4 = 0;
10827 int route_filter_translated_v6 = 0;
10828 int route_filter_v6 = 0;
10829 int llgr_stale = 0;
10830 int no_llgr = 0;
10831 int accept_own_nexthop = 0;
10832 int blackhole = 0;
d62a17ae 10833 int no_export = 0;
10834 int no_advertise = 0;
10835 int local_as = 0;
c5f1e1b2 10836 int no_peer = 0;
d62a17ae 10837 int first = 1;
10838 int has_valid_label = 0;
10839 mpls_label_t label = 0;
10840 json_object *json_adv_to = NULL;
9bedbb1e 10841
9bcb3eef
DS
10842 p = bgp_dest_get_prefix(dest);
10843 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10844
10845 if (has_valid_label)
9bcb3eef 10846 label = label_pton(&dest->local_label);
d62a17ae 10847
44c69747 10848 if (safi == SAFI_EVPN) {
d62a17ae 10849
44c69747 10850 if (!json) {
2dbe669b 10851 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10852 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10853 : "",
2dbe669b 10854 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10855 } else {
10856 json_object_string_add(json, "rd",
10857 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10858 "");
10859 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10860 }
10861 } else {
10862 if (!json) {
8228a9a7 10863 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 10864 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
10865 ? prefix_rd2str(prd, buf1,
10866 sizeof(buf1))
10867 : ""),
10868 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 10869
44c69747
LK
10870 } else
10871 json_object_string_add(json, "prefix",
10872 prefix2str(p, prefix_str, sizeof(prefix_str)));
10873 }
10874
10875 if (has_valid_label) {
10876 if (json)
10877 json_object_int_add(json, "localLabel", label);
10878 else
d62a17ae 10879 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10880 }
10881
10882 if (!json)
d62a17ae 10883 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10884 vty_out(vty, "not allocated\n");
718e3744 10885
9bcb3eef 10886 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10887 count++;
40381db7 10888 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10889 best = count;
4056a5f6 10890 if (bgp_path_suppressed(pi))
d62a17ae 10891 suppress = 1;
cee9c031 10892
40381db7 10893 if (pi->attr->community == NULL)
cee9c031
QY
10894 continue;
10895
10896 no_advertise += community_include(
40381db7
DS
10897 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10898 no_export += community_include(pi->attr->community,
cee9c031 10899 COMMUNITY_NO_EXPORT);
40381db7 10900 local_as += community_include(pi->attr->community,
cee9c031 10901 COMMUNITY_LOCAL_AS);
40381db7 10902 accept_own += community_include(pi->attr->community,
cee9c031
QY
10903 COMMUNITY_ACCEPT_OWN);
10904 route_filter_translated_v4 += community_include(
40381db7 10905 pi->attr->community,
cee9c031
QY
10906 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10907 route_filter_translated_v6 += community_include(
40381db7 10908 pi->attr->community,
cee9c031
QY
10909 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10910 route_filter_v4 += community_include(
40381db7 10911 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10912 route_filter_v6 += community_include(
40381db7
DS
10913 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10914 llgr_stale += community_include(pi->attr->community,
cee9c031 10915 COMMUNITY_LLGR_STALE);
40381db7 10916 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10917 COMMUNITY_NO_LLGR);
10918 accept_own_nexthop +=
40381db7 10919 community_include(pi->attr->community,
cee9c031 10920 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10921 blackhole += community_include(pi->attr->community,
cee9c031 10922 COMMUNITY_BLACKHOLE);
40381db7 10923 no_peer += community_include(pi->attr->community,
cee9c031 10924 COMMUNITY_NO_PEER);
d62a17ae 10925 }
718e3744 10926 }
718e3744 10927
d62a17ae 10928 if (!json) {
10929 vty_out(vty, "Paths: (%d available", count);
10930 if (best) {
10931 vty_out(vty, ", best #%d", best);
b84060bb
PG
10932 if (safi == SAFI_UNICAST) {
10933 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10934 vty_out(vty, ", table %s",
10935 VRF_DEFAULT_NAME);
10936 else
10937 vty_out(vty, ", vrf %s",
10938 bgp->name);
10939 }
d62a17ae 10940 } else
10941 vty_out(vty, ", no best path");
10942
c5f1e1b2
C
10943 if (accept_own)
10944 vty_out(vty,
10945 ", accept own local route exported and imported in different VRF");
10946 else if (route_filter_translated_v4)
10947 vty_out(vty,
10948 ", mark translated RTs for VPNv4 route filtering");
10949 else if (route_filter_v4)
10950 vty_out(vty,
10951 ", attach RT as-is for VPNv4 route filtering");
10952 else if (route_filter_translated_v6)
10953 vty_out(vty,
10954 ", mark translated RTs for VPNv6 route filtering");
10955 else if (route_filter_v6)
10956 vty_out(vty,
10957 ", attach RT as-is for VPNv6 route filtering");
10958 else if (llgr_stale)
10959 vty_out(vty,
10960 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10961 else if (no_llgr)
10962 vty_out(vty,
10963 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10964 else if (accept_own_nexthop)
10965 vty_out(vty,
10966 ", accept local nexthop");
10967 else if (blackhole)
10968 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10969 else if (no_export)
10970 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10971 else if (no_advertise)
10972 vty_out(vty, ", not advertised to any peer");
d62a17ae 10973 else if (local_as)
10974 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10975 else if (no_peer)
10976 vty_out(vty,
10977 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10978
10979 if (suppress)
10980 vty_out(vty,
10981 ", Advertisements suppressed by an aggregate.");
10982 vty_out(vty, ")\n");
10983 }
718e3744 10984
d62a17ae 10985 /* If we are not using addpath then we can display Advertised to and
10986 * that will
10987 * show what peers we advertised the bestpath to. If we are using
10988 * addpath
10989 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10990 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10991 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10992 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10993 if (json && !json_adv_to)
10994 json_adv_to = json_object_new_object();
10995
10996 route_vty_out_advertised_to(
10997 vty, peer, &first,
10998 " Advertised to non peer-group peers:\n ",
10999 json_adv_to);
11000 }
11001 }
11002
11003 if (json) {
11004 if (json_adv_to) {
11005 json_object_object_add(json, "advertisedTo",
11006 json_adv_to);
11007 }
11008 } else {
11009 if (first)
11010 vty_out(vty, " Not advertised to any peer");
11011 vty_out(vty, "\n");
11012 }
11013 }
718e3744 11014}
11015
44c69747 11016static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11017 struct bgp_dest *bgp_node, struct vty *vty,
11018 struct bgp *bgp, afi_t afi, safi_t safi,
11019 json_object *json, enum bgp_path_type pathtype,
11020 int *display)
44c69747
LK
11021{
11022 struct bgp_path_info *pi;
11023 int header = 1;
11024 char rdbuf[RD_ADDRSTRLEN];
11025 json_object *json_header = NULL;
11026 json_object *json_paths = NULL;
11027
9bcb3eef 11028 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
11029
11030 if (json && !json_paths) {
11031 /* Instantiate json_paths only if path is valid */
11032 json_paths = json_object_new_array();
11033 if (pfx_rd) {
11034 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11035 json_header = json_object_new_object();
11036 } else
11037 json_header = json;
11038 }
11039
11040 if (header) {
11041 route_vty_out_detail_header(
11042 vty, bgp, bgp_node, pfx_rd,
11043 AFI_IP, safi, json_header);
11044 header = 0;
11045 }
11046 (*display)++;
11047
11048 if (pathtype == BGP_PATH_SHOW_ALL
11049 || (pathtype == BGP_PATH_SHOW_BESTPATH
11050 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11051 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11052 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11053 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11054 route_vty_out_detail(vty, bgp, bgp_node,
11055 pi, AFI_IP, safi,
11056 json_paths);
11057 }
11058
11059 if (json && json_paths) {
11060 json_object_object_add(json_header, "paths", json_paths);
11061
11062 if (pfx_rd)
11063 json_object_object_add(json, rdbuf, json_header);
11064 }
11065}
11066
718e3744 11067/* Display specified route of BGP table. */
d62a17ae 11068static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11069 struct bgp_table *rib, const char *ip_str,
11070 afi_t afi, safi_t safi,
11071 struct prefix_rd *prd, int prefix_check,
9f049418 11072 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11073{
11074 int ret;
d62a17ae 11075 int display = 0;
11076 struct prefix match;
9bcb3eef
DS
11077 struct bgp_dest *dest;
11078 struct bgp_dest *rm;
d62a17ae 11079 struct bgp_table *table;
11080 json_object *json = NULL;
11081 json_object *json_paths = NULL;
11082
11083 /* Check IP address argument. */
11084 ret = str2prefix(ip_str, &match);
11085 if (!ret) {
11086 vty_out(vty, "address is malformed\n");
11087 return CMD_WARNING;
11088 }
718e3744 11089
d62a17ae 11090 match.family = afi2family(afi);
b05a1c8b 11091
44c69747 11092 if (use_json)
d62a17ae 11093 json = json_object_new_object();
718e3744 11094
44c69747 11095 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11096 for (dest = bgp_table_top(rib); dest;
11097 dest = bgp_route_next(dest)) {
11098 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11099
9bcb3eef 11100 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11101 continue;
9bcb3eef 11102 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11103 if (!table)
ea47320b 11104 continue;
d62a17ae 11105
ea47320b
DL
11106 if ((rm = bgp_node_match(table, &match)) == NULL)
11107 continue;
d62a17ae 11108
9bcb3eef 11109 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11110 if (prefix_check
b54892e0 11111 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11112 bgp_dest_unlock_node(rm);
ea47320b
DL
11113 continue;
11114 }
d62a17ae 11115
9bcb3eef 11116 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11117 bgp, afi, safi, json, pathtype,
11118 &display);
44c69747 11119
9bcb3eef 11120 bgp_dest_unlock_node(rm);
44c69747
LK
11121 }
11122 } else if (safi == SAFI_EVPN) {
9bcb3eef 11123 struct bgp_dest *longest_pfx;
cded3b72 11124 bool is_exact_pfxlen_match = false;
44c69747 11125
9bcb3eef
DS
11126 for (dest = bgp_table_top(rib); dest;
11127 dest = bgp_route_next(dest)) {
11128 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11129
9bcb3eef 11130 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11131 continue;
9bcb3eef 11132 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11133 if (!table)
11134 continue;
11135
11136 longest_pfx = NULL;
cded3b72 11137 is_exact_pfxlen_match = false;
44c69747
LK
11138 /*
11139 * Search through all the prefixes for a match. The
11140 * pfx's are enumerated in ascending order of pfxlens.
11141 * So, the last pfx match is the longest match. Set
11142 * is_exact_pfxlen_match when we get exact pfxlen match
11143 */
11144 for (rm = bgp_table_top(table); rm;
11145 rm = bgp_route_next(rm)) {
b54892e0 11146 const struct prefix *rm_p =
9bcb3eef 11147 bgp_dest_get_prefix(rm);
44c69747
LK
11148 /*
11149 * Get prefixlen of the ip-prefix within type5
11150 * evpn route
11151 */
b54892e0
DS
11152 if (evpn_type5_prefix_match(rm_p, &match)
11153 && rm->info) {
44c69747
LK
11154 longest_pfx = rm;
11155 int type5_pfxlen =
b54892e0
DS
11156 bgp_evpn_get_type5_prefixlen(
11157 rm_p);
44c69747 11158 if (type5_pfxlen == match.prefixlen) {
cded3b72 11159 is_exact_pfxlen_match = true;
9bcb3eef 11160 bgp_dest_unlock_node(rm);
44c69747
LK
11161 break;
11162 }
d62a17ae 11163 }
11164 }
ea47320b 11165
44c69747
LK
11166 if (!longest_pfx)
11167 continue;
11168
11169 if (prefix_check && !is_exact_pfxlen_match)
11170 continue;
11171
11172 rm = longest_pfx;
9bcb3eef 11173 bgp_dest_lock_node(rm);
44c69747 11174
9bcb3eef 11175 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11176 bgp, afi, safi, json, pathtype,
11177 &display);
44c69747 11178
9bcb3eef 11179 bgp_dest_unlock_node(rm);
d62a17ae 11180 }
98a9dbc7 11181 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11182 if (use_json)
11183 json_paths = json_object_new_array();
11184
63a0b7a9
PG
11185 display = bgp_flowspec_display_match_per_ip(afi, rib,
11186 &match, prefix_check,
11187 vty,
11188 use_json,
11189 json_paths);
44c69747
LK
11190 if (use_json && display)
11191 json_object_object_add(json, "paths", json_paths);
d62a17ae 11192 } else {
9bcb3eef
DS
11193 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11194 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11195 if (!prefix_check
9bcb3eef
DS
11196 || dest_p->prefixlen == match.prefixlen) {
11197 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11198 safi, json, pathtype,
11199 &display);
d62a17ae 11200 }
11201
9bcb3eef 11202 bgp_dest_unlock_node(dest);
d62a17ae 11203 }
11204 }
e5eee9af 11205
d62a17ae 11206 if (use_json) {
996c9314 11207 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11208 json, JSON_C_TO_STRING_PRETTY |
11209 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11210 json_object_free(json);
11211 } else {
11212 if (!display) {
11213 vty_out(vty, "%% Network not in table\n");
11214 return CMD_WARNING;
11215 }
11216 }
b05a1c8b 11217
d62a17ae 11218 return CMD_SUCCESS;
718e3744 11219}
11220
fee0f4c6 11221/* Display specified route of Main RIB */
d62a17ae 11222static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11223 afi_t afi, safi_t safi, struct prefix_rd *prd,
11224 int prefix_check, enum bgp_path_type pathtype,
9f049418 11225 bool use_json)
d62a17ae 11226{
9b86009a 11227 if (!bgp) {
d62a17ae 11228 bgp = bgp_get_default();
9b86009a
RW
11229 if (!bgp) {
11230 if (!use_json)
11231 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11232 else
11233 vty_out(vty, "{}\n");
9b86009a
RW
11234 return CMD_WARNING;
11235 }
11236 }
d62a17ae 11237
11238 /* labeled-unicast routes live in the unicast table */
11239 if (safi == SAFI_LABELED_UNICAST)
11240 safi = SAFI_UNICAST;
11241
11242 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11243 afi, safi, prd, prefix_check, pathtype,
11244 use_json);
11245}
11246
11247static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11248 struct cmd_token **argv, bool exact, afi_t afi,
11249 safi_t safi, bool uj)
d62a17ae 11250{
11251 struct lcommunity *lcom;
11252 struct buffer *b;
11253 int i;
11254 char *str;
11255 int first = 0;
96f3485c 11256 uint8_t show_flags = 0;
4f28b2b5 11257 int ret;
96f3485c
MK
11258
11259 if (uj)
11260 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11261
11262 b = buffer_new(1024);
11263 for (i = 0; i < argc; i++) {
11264 if (first)
11265 buffer_putc(b, ' ');
11266 else {
11267 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11268 first = 1;
11269 buffer_putstr(b, argv[i]->arg);
11270 }
11271 }
11272 }
11273 buffer_putc(b, '\0');
57d187bc 11274
d62a17ae 11275 str = buffer_getstr(b);
11276 buffer_free(b);
57d187bc 11277
d62a17ae 11278 lcom = lcommunity_str2com(str);
11279 XFREE(MTYPE_TMP, str);
11280 if (!lcom) {
11281 vty_out(vty, "%% Large-community malformed\n");
11282 return CMD_WARNING;
11283 }
57d187bc 11284
4f28b2b5 11285 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11286 (exact ? bgp_show_type_lcommunity_exact
ae248832 11287 : bgp_show_type_lcommunity),
96f3485c 11288 lcom, show_flags);
4f28b2b5
DS
11289
11290 lcommunity_free(&lcom);
11291 return ret;
57d187bc
JS
11292}
11293
d62a17ae 11294static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11295 const char *lcom, bool exact, afi_t afi,
11296 safi_t safi, bool uj)
57d187bc 11297{
d62a17ae 11298 struct community_list *list;
96f3485c
MK
11299 uint8_t show_flags = 0;
11300
11301 if (uj)
11302 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11303
57d187bc 11304
e237b0d2 11305 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11306 LARGE_COMMUNITY_LIST_MASTER);
11307 if (list == NULL) {
11308 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11309 lcom);
11310 return CMD_WARNING;
11311 }
57d187bc 11312
36a206db 11313 return bgp_show(vty, bgp, afi, safi,
11314 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11315 : bgp_show_type_lcommunity_list),
96f3485c 11316 list, show_flags);
fee0f4c6 11317}
11318
52951b63
DS
11319DEFUN (show_ip_bgp_large_community_list,
11320 show_ip_bgp_large_community_list_cmd,
36a206db 11321 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|WORD> [exact-match] [json]",
52951b63
DS
11322 SHOW_STR
11323 IP_STR
11324 BGP_STR
11325 BGP_INSTANCE_HELP_STR
9bedbb1e 11326 BGP_AFI_HELP_STR
4dd6177e 11327 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11328 "Display routes matching the large-community-list\n"
11329 "large-community-list number\n"
11330 "large-community-list name\n"
36a206db 11331 "Exact match of the large-communities\n"
52951b63
DS
11332 JSON_STR)
11333{
d62a17ae 11334 afi_t afi = AFI_IP6;
11335 safi_t safi = SAFI_UNICAST;
11336 int idx = 0;
36a206db 11337 bool exact_match = 0;
4d678463 11338 struct bgp *bgp = NULL;
9f049418 11339 bool uj = use_json(argc, argv);
d62a17ae 11340
4d678463
KA
11341 if (uj)
11342 argc--;
11343
11344 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11345 &bgp, uj);
11346 if (!idx)
11347 return CMD_WARNING;
d62a17ae 11348
11349 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11350
11351 const char *clist_number_or_name = argv[++idx]->arg;
11352
11353 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11354 exact_match = 1;
11355
11356 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11357 exact_match, afi, safi, uj);
52951b63
DS
11358}
11359DEFUN (show_ip_bgp_large_community,
11360 show_ip_bgp_large_community_cmd,
36a206db 11361 "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
11362 SHOW_STR
11363 IP_STR
11364 BGP_STR
11365 BGP_INSTANCE_HELP_STR
9bedbb1e 11366 BGP_AFI_HELP_STR
4dd6177e 11367 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11368 "Display routes matching the large-communities\n"
11369 "List of large-community numbers\n"
36a206db 11370 "Exact match of the large-communities\n"
52951b63
DS
11371 JSON_STR)
11372{
d62a17ae 11373 afi_t afi = AFI_IP6;
11374 safi_t safi = SAFI_UNICAST;
11375 int idx = 0;
36a206db 11376 bool exact_match = 0;
4d678463 11377 struct bgp *bgp = NULL;
9f049418 11378 bool uj = use_json(argc, argv);
96f3485c 11379 uint8_t show_flags = 0;
d62a17ae 11380
96f3485c
MK
11381 if (uj) {
11382 argc--;
11383 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11384 }
4d678463 11385
96f3485c
MK
11386 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11387 &bgp, uj);
11388 if (!idx)
11389 return CMD_WARNING;
d62a17ae 11390
36a206db 11391 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11392 if (argv_find(argv, argc, "exact-match", &idx))
11393 exact_match = 1;
11394 return bgp_show_lcommunity(vty, bgp, argc, argv,
11395 exact_match, afi, safi, uj);
11396 } else
d62a17ae 11397 return bgp_show(vty, bgp, afi, safi,
96f3485c 11398 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11399}
11400
71f1613a
DA
11401static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11402 safi_t safi, struct json_object *json_array);
d62a17ae 11403static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11404 safi_t safi, struct json_object *json);
e01ca200 11405
7b2ff250 11406
9ab0cf58
PG
11407DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11408 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11409 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11410 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11411{
11412 bool uj = use_json(argc, argv);
11413 struct bgp *bgp = NULL;
ec76a1d1
DA
11414 safi_t safi = SAFI_UNICAST;
11415 afi_t afi = AFI_IP6;
4265b261 11416 int idx = 0;
6c9d22e2
PG
11417 struct json_object *json_all = NULL;
11418 struct json_object *json_afi_safi = NULL;
4265b261
PG
11419
11420 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11421 &bgp, false);
71f1613a 11422 if (!idx)
4265b261 11423 return CMD_WARNING;
6c9d22e2 11424
4265b261 11425 if (uj)
6c9d22e2 11426 json_all = json_object_new_object();
4265b261 11427
9ab0cf58
PG
11428 FOREACH_AFI_SAFI (afi, safi) {
11429 /*
11430 * So limit output to those afi/safi pairs that
11431 * actually have something interesting in them
11432 */
11433 if (strmatch(get_afi_safi_str(afi, safi, true),
11434 "Unknown")) {
11435 continue;
11436 }
11437 if (uj) {
11438 json_afi_safi = json_object_new_array();
11439 json_object_object_add(
11440 json_all,
11441 get_afi_safi_str(afi, safi, true),
11442 json_afi_safi);
11443 } else {
11444 json_afi_safi = NULL;
6c9d22e2 11445 }
9ab0cf58
PG
11446
11447 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11448 }
6c9d22e2
PG
11449
11450 if (uj) {
9ab0cf58
PG
11451 vty_out(vty, "%s",
11452 json_object_to_json_string_ext(
11453 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11454 json_object_free(json_all);
4265b261 11455 }
6c9d22e2 11456
4265b261
PG
11457 return CMD_SUCCESS;
11458}
11459
7b2ff250 11460/* BGP route print out function without JSON */
14718643
PG
11461DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11462 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11463 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11464 SHOW_STR
11465 IP_STR
11466 BGP_STR
11467 BGP_INSTANCE_HELP_STR
11468 L2VPN_HELP_STR
11469 EVPN_HELP_STR
11470 "BGP RIB advertisement statistics\n"
11471 JSON_STR)
11472{
ec76a1d1
DA
11473 afi_t afi = AFI_IP6;
11474 safi_t safi = SAFI_UNICAST;
14718643
PG
11475 struct bgp *bgp = NULL;
11476 int idx = 0, ret;
11477 bool uj = use_json(argc, argv);
11478 struct json_object *json_afi_safi = NULL, *json = NULL;
11479
11480 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11481 &bgp, false);
11482 if (!idx)
11483 return CMD_WARNING;
11484
11485 if (uj)
11486 json_afi_safi = json_object_new_array();
11487 else
11488 json_afi_safi = NULL;
11489
11490 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11491
11492 if (uj) {
11493 json = json_object_new_object();
11494 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11495 json_afi_safi);
11496 vty_out(vty, "%s", json_object_to_json_string_ext(
11497 json, JSON_C_TO_STRING_PRETTY));
11498 json_object_free(json);
11499 }
11500 return ret;
11501}
11502
893cccd0 11503/* BGP route print out function without JSON */
9ab0cf58
PG
11504DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11505 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11506 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11507 "]]\
893cccd0 11508 statistics [json]",
9ab0cf58
PG
11509 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11510 BGP_SAFI_WITH_LABEL_HELP_STR
11511 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11512{
ec76a1d1
DA
11513 afi_t afi = AFI_IP6;
11514 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11515 struct bgp *bgp = NULL;
11516 int idx = 0, ret;
11517 bool uj = use_json(argc, argv);
6c9d22e2 11518 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11519
11520 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11521 &bgp, false);
11522 if (!idx)
11523 return CMD_WARNING;
6c9d22e2 11524
893cccd0 11525 if (uj)
6c9d22e2
PG
11526 json_afi_safi = json_object_new_array();
11527 else
11528 json_afi_safi = NULL;
11529
11530 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11531
11532 if (uj) {
11533 json = json_object_new_object();
11534 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11535 json_afi_safi);
9ab0cf58
PG
11536 vty_out(vty, "%s",
11537 json_object_to_json_string_ext(
11538 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11539 json_object_free(json);
11540 }
11541 return ret;
893cccd0 11542}
7b2ff250
DW
11543
11544/* BGP route print out function without JSON */
96f3485c 11545DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11546 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11547 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11548 "]]\
96f3485c 11549 <[all$all] dampening <parameters>\
7b2ff250
DW
11550 |route-map WORD\
11551 |prefix-list WORD\
11552 |filter-list WORD\
7b2ff250
DW
11553 |community-list <(1-500)|WORD> [exact-match]\
11554 |A.B.C.D/M longer-prefixes\
11555 |X:X::X:X/M longer-prefixes\
893cccd0 11556 >",
9ab0cf58
PG
11557 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11558 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11559 "Display the entries for all address families\n"
9ab0cf58
PG
11560 "Display detailed information about dampening\n"
11561 "Display detail of configured dampening parameters\n"
11562 "Display routes matching the route-map\n"
11563 "A route-map to match on\n"
11564 "Display routes conforming to the prefix-list\n"
11565 "Prefix-list name\n"
11566 "Display routes conforming to the filter-list\n"
11567 "Regular expression access list name\n"
11568 "Display routes matching the community-list\n"
11569 "community-list number\n"
11570 "community-list name\n"
11571 "Exact match of the communities\n"
11572 "IPv4 prefix\n"
11573 "Display route and more specific routes\n"
11574 "IPv6 prefix\n"
11575 "Display route and more specific routes\n")
718e3744 11576{
d62a17ae 11577 afi_t afi = AFI_IP6;
11578 safi_t safi = SAFI_UNICAST;
11579 int exact_match = 0;
d62a17ae 11580 struct bgp *bgp = NULL;
11581 int idx = 0;
96f3485c
MK
11582 uint8_t show_flags = 0;
11583
11584 /* [<ipv4|ipv6> [all]] */
11585 if (all) {
11586 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11587 if (argv_find(argv, argc, "ipv4", &idx))
11588 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11589
11590 if (argv_find(argv, argc, "ipv6", &idx))
11591 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11592 }
d62a17ae 11593
11594 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11595 &bgp, false);
d62a17ae 11596 if (!idx)
11597 return CMD_WARNING;
11598
d62a17ae 11599 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11600 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11601 return bgp_show_dampening_parameters(vty, afi, safi,
11602 show_flags);
d62a17ae 11603 }
c016b6c7 11604
d62a17ae 11605 if (argv_find(argv, argc, "prefix-list", &idx))
11606 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11607 safi, bgp_show_type_prefix_list);
11608
11609 if (argv_find(argv, argc, "filter-list", &idx))
11610 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11611 safi, bgp_show_type_filter_list);
11612
d62a17ae 11613 if (argv_find(argv, argc, "route-map", &idx))
11614 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11615 safi, bgp_show_type_route_map);
11616
d62a17ae 11617 if (argv_find(argv, argc, "community-list", &idx)) {
11618 const char *clist_number_or_name = argv[++idx]->arg;
11619 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11620 exact_match = 1;
11621 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11622 exact_match, afi, safi);
11623 }
11624 /* prefix-longer */
11625 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11626 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11627 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11628 safi,
11629 bgp_show_type_prefix_longer);
11630
7b2ff250
DW
11631 return CMD_WARNING;
11632}
11633
11634/* BGP route print out function with JSON */
ae248832 11635DEFPY (show_ip_bgp_json,
7b2ff250
DW
11636 show_ip_bgp_json_cmd,
11637 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11638 [all$all]\
cf4898bc
QY
11639 [cidr-only\
11640 |dampening <flap-statistics|dampened-paths>\
11641 |community [AA:NN|local-AS|no-advertise|no-export\
11642 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11643 |accept-own|accept-own-nexthop|route-filter-v6\
11644 |route-filter-v4|route-filter-translated-v6\
11645 |route-filter-translated-v4] [exact-match]\
ae248832 11646 ] [json$uj | wide$wide]",
7b2ff250
DW
11647 SHOW_STR
11648 IP_STR
11649 BGP_STR
11650 BGP_INSTANCE_HELP_STR
11651 BGP_AFI_HELP_STR
11652 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11653 "Display the entries for all address families\n"
7b2ff250
DW
11654 "Display only routes with non-natural netmasks\n"
11655 "Display detailed information about dampening\n"
11656 "Display flap statistics of routes\n"
11657 "Display paths suppressed due to dampening\n"
11658 "Display routes matching the communities\n"
d0086e8e
AD
11659 COMMUNITY_AANN_STR
11660 "Do not send outside local AS (well-known community)\n"
11661 "Do not advertise to any peer (well-known community)\n"
11662 "Do not export to next AS (well-known community)\n"
11663 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11664 "Do not export to any peer (well-known community)\n"
11665 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11666 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11667 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11668 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11669 "Should accept VPN route with local nexthop (well-known community)\n"
11670 "RT VPNv6 route filtering (well-known community)\n"
11671 "RT VPNv4 route filtering (well-known community)\n"
11672 "RT translated VPNv6 route filtering (well-known community)\n"
11673 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11674 "Exact match of the communities\n"
ae248832
MK
11675 JSON_STR
11676 "Increase table width for longer prefixes\n")
7b2ff250
DW
11677{
11678 afi_t afi = AFI_IP6;
11679 safi_t safi = SAFI_UNICAST;
11680 enum bgp_show_type sh_type = bgp_show_type_normal;
11681 struct bgp *bgp = NULL;
11682 int idx = 0;
d0086e8e 11683 int exact_match = 0;
96f3485c
MK
11684 char *community = NULL;
11685 bool first = true;
11686 uint8_t show_flags = 0;
9f049418 11687
96f3485c
MK
11688
11689 if (uj) {
9f049418 11690 argc--;
96f3485c
MK
11691 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11692 }
11693
11694 /* [<ipv4|ipv6> [all]] */
11695 if (all) {
11696 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11697
11698 if (argv_find(argv, argc, "ipv4", &idx))
11699 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11700
11701 if (argv_find(argv, argc, "ipv6", &idx))
11702 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11703 }
11704
11705 if (wide)
11706 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11707
11708 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11709 &bgp, uj);
7b2ff250
DW
11710 if (!idx)
11711 return CMD_WARNING;
11712
7b2ff250 11713 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11714 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11715
11716 if (argv_find(argv, argc, "dampening", &idx)) {
11717 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11718 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11719 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11720 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11721 }
11722
11723 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11724 char *maybecomm = NULL;
d0086e8e 11725
79bc257a
RW
11726 if (idx + 1 < argc) {
11727 if (argv[idx + 1]->type == VARIABLE_TKN)
11728 maybecomm = argv[idx + 1]->arg;
11729 else
11730 maybecomm = argv[idx + 1]->text;
11731 }
11732
cf4898bc
QY
11733 if (maybecomm && !strmatch(maybecomm, "json")
11734 && !strmatch(maybecomm, "exact-match"))
11735 community = maybecomm;
d0086e8e 11736
cf4898bc
QY
11737 if (argv_find(argv, argc, "exact-match", &idx))
11738 exact_match = 1;
d0086e8e 11739
96f3485c
MK
11740 if (!community)
11741 sh_type = bgp_show_type_community_all;
11742 }
11743
11744 if (!all) {
11745 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11746 if (community)
11747 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11748 exact_match, afi, safi,
11749 show_flags);
cf4898bc 11750 else
96f3485c
MK
11751 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11752 show_flags);
11753 } else {
11754 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11755 * AFI_IP6 */
11756
11757 if (uj)
11758 vty_out(vty, "{\n");
11759
11760 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11761 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11762 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11763 ? AFI_IP
11764 : AFI_IP6;
11765 FOREACH_SAFI (safi) {
96f3485c
MK
11766 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11767 continue;
11768
11769 if (uj) {
11770 if (first)
11771 first = false;
11772 else
11773 vty_out(vty, ",\n");
11774 vty_out(vty, "\"%s\":{\n",
11775 get_afi_safi_str(afi, safi,
11776 true));
11777 } else
11778 vty_out(vty,
11779 "\nFor address family: %s\n",
11780 get_afi_safi_str(afi, safi,
11781 false));
11782
11783 if (community)
11784 bgp_show_community(vty, bgp, community,
11785 exact_match, afi,
11786 safi, show_flags);
11787 else
11788 bgp_show(vty, bgp, afi, safi, sh_type,
11789 NULL, show_flags);
11790 if (uj)
11791 vty_out(vty, "}\n");
11792 }
11793 } else {
11794 /* show <ip> bgp all: for each AFI and SAFI*/
11795 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
11796 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11797 continue;
11798
11799 if (uj) {
11800 if (first)
11801 first = false;
11802 else
11803 vty_out(vty, ",\n");
d0086e8e 11804
96f3485c
MK
11805 vty_out(vty, "\"%s\":{\n",
11806 get_afi_safi_str(afi, safi,
11807 true));
11808 } else
11809 vty_out(vty,
11810 "\nFor address family: %s\n",
11811 get_afi_safi_str(afi, safi,
11812 false));
11813
11814 if (community)
11815 bgp_show_community(vty, bgp, community,
11816 exact_match, afi,
11817 safi, show_flags);
11818 else
11819 bgp_show(vty, bgp, afi, safi, sh_type,
11820 NULL, show_flags);
11821 if (uj)
11822 vty_out(vty, "}\n");
11823 }
11824 }
11825 if (uj)
11826 vty_out(vty, "}\n");
11827 }
11828 return CMD_SUCCESS;
a636c635 11829}
47fc97cc 11830
718e3744 11831DEFUN (show_ip_bgp_route,
11832 show_ip_bgp_route_cmd,
3efd0893 11833 "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>] [json]",
718e3744 11834 SHOW_STR
11835 IP_STR
11836 BGP_STR
a636c635 11837 BGP_INSTANCE_HELP_STR
4f280b15 11838 BGP_AFI_HELP_STR
4dd6177e 11839 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11840 "Network in the BGP routing table to display\n"
0c7b1b01 11841 "IPv4 prefix\n"
8c3deaae 11842 "Network in the BGP routing table to display\n"
0c7b1b01 11843 "IPv6 prefix\n"
4092b06c 11844 "Display only the bestpath\n"
b05a1c8b 11845 "Display only multipaths\n"
9973d184 11846 JSON_STR)
4092b06c 11847{
d62a17ae 11848 int prefix_check = 0;
ae19d7dd 11849
d62a17ae 11850 afi_t afi = AFI_IP6;
11851 safi_t safi = SAFI_UNICAST;
11852 char *prefix = NULL;
11853 struct bgp *bgp = NULL;
11854 enum bgp_path_type path_type;
9f049418 11855 bool uj = use_json(argc, argv);
b05a1c8b 11856
d62a17ae 11857 int idx = 0;
ae19d7dd 11858
d62a17ae 11859 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11860 &bgp, uj);
d62a17ae 11861 if (!idx)
11862 return CMD_WARNING;
c41247f5 11863
d62a17ae 11864 if (!bgp) {
11865 vty_out(vty,
11866 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11867 return CMD_WARNING;
11868 }
a636c635 11869
d62a17ae 11870 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11871 if (argv_find(argv, argc, "A.B.C.D", &idx)
11872 || argv_find(argv, argc, "X:X::X:X", &idx))
11873 prefix_check = 0;
11874 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11875 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11876 prefix_check = 1;
11877
11878 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11879 && afi != AFI_IP6) {
11880 vty_out(vty,
11881 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11882 return CMD_WARNING;
11883 }
11884 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11885 && afi != AFI_IP) {
11886 vty_out(vty,
11887 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11888 return CMD_WARNING;
11889 }
11890
11891 prefix = argv[idx]->arg;
11892
11893 /* [<bestpath|multipath>] */
11894 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11895 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11896 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11897 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11898 else
360660c6 11899 path_type = BGP_PATH_SHOW_ALL;
a636c635 11900
d62a17ae 11901 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11902 path_type, uj);
4092b06c
DS
11903}
11904
8c3deaae
QY
11905DEFUN (show_ip_bgp_regexp,
11906 show_ip_bgp_regexp_cmd,
3e5b31b3 11907 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11908 SHOW_STR
11909 IP_STR
11910 BGP_STR
b00b230a 11911 BGP_INSTANCE_HELP_STR
4f280b15 11912 BGP_AFI_HELP_STR
4dd6177e 11913 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11914 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11915 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11916 JSON_STR)
8c3deaae 11917{
d62a17ae 11918 afi_t afi = AFI_IP6;
11919 safi_t safi = SAFI_UNICAST;
11920 struct bgp *bgp = NULL;
3e5b31b3
DA
11921 bool uj = use_json(argc, argv);
11922 char *regstr = NULL;
8c3deaae 11923
d62a17ae 11924 int idx = 0;
11925 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11926 &bgp, false);
d62a17ae 11927 if (!idx)
11928 return CMD_WARNING;
8c3deaae 11929
d62a17ae 11930 // get index of regex
3e5b31b3
DA
11931 if (argv_find(argv, argc, "REGEX", &idx))
11932 regstr = argv[idx]->arg;
8c3deaae 11933
5f71d11c 11934 assert(regstr);
3e5b31b3
DA
11935 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11936 bgp_show_type_regexp, uj);
8c3deaae
QY
11937}
11938
ae248832 11939DEFPY (show_ip_bgp_instance_all,
a636c635 11940 show_ip_bgp_instance_all_cmd,
ae248832 11941 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11942 SHOW_STR
a636c635 11943 IP_STR
4092b06c 11944 BGP_STR
a636c635 11945 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11946 BGP_AFI_HELP_STR
4dd6177e 11947 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11948 JSON_STR
11949 "Increase table width for longer prefixes\n")
4092b06c 11950{
d62a17ae 11951 afi_t afi = AFI_IP;
11952 safi_t safi = SAFI_UNICAST;
11953 struct bgp *bgp = NULL;
d62a17ae 11954 int idx = 0;
96f3485c 11955 uint8_t show_flags = 0;
ae19d7dd 11956
96f3485c 11957 if (uj) {
d62a17ae 11958 argc--;
96f3485c
MK
11959 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11960 }
11961
11962 if (wide)
11963 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11964
9f049418
DS
11965 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11966 &bgp, uj);
11967 if (!idx)
11968 return CMD_WARNING;
11969
96f3485c 11970 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11971 return CMD_SUCCESS;
e3e29b32
LB
11972}
11973
a4d82a8a 11974static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11975 afi_t afi, safi_t safi, enum bgp_show_type type,
11976 bool use_json)
718e3744 11977{
d62a17ae 11978 regex_t *regex;
11979 int rc;
96f3485c
MK
11980 uint8_t show_flags = 0;
11981
11982 if (use_json)
11983 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11984
c3900853 11985 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11986 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11987 regstr);
11988 return CMD_WARNING_CONFIG_FAILED;
11989 }
11990
d62a17ae 11991 regex = bgp_regcomp(regstr);
11992 if (!regex) {
11993 vty_out(vty, "Can't compile regexp %s\n", regstr);
11994 return CMD_WARNING;
11995 }
a636c635 11996
96f3485c 11997 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11998 bgp_regex_free(regex);
11999 return rc;
e3e29b32
LB
12000}
12001
d62a17ae 12002static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12003 const char *prefix_list_str, afi_t afi,
12004 safi_t safi, enum bgp_show_type type)
e3e29b32 12005{
d62a17ae 12006 struct prefix_list *plist;
96f3485c 12007 uint8_t show_flags = 0;
718e3744 12008
d62a17ae 12009 plist = prefix_list_lookup(afi, prefix_list_str);
12010 if (plist == NULL) {
12011 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12012 prefix_list_str);
12013 return CMD_WARNING;
12014 }
718e3744 12015
96f3485c 12016 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
12017}
12018
d62a17ae 12019static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12020 const char *filter, afi_t afi, safi_t safi,
12021 enum bgp_show_type type)
4092b06c 12022{
d62a17ae 12023 struct as_list *as_list;
96f3485c 12024 uint8_t show_flags = 0;
718e3744 12025
d62a17ae 12026 as_list = as_list_lookup(filter);
12027 if (as_list == NULL) {
12028 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12029 filter);
12030 return CMD_WARNING;
12031 }
a636c635 12032
96f3485c 12033 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12034}
12035
d62a17ae 12036static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12037 const char *rmap_str, afi_t afi, safi_t safi,
12038 enum bgp_show_type type)
718e3744 12039{
d62a17ae 12040 struct route_map *rmap;
96f3485c 12041 uint8_t show_flags = 0;
bb46e94f 12042
d62a17ae 12043 rmap = route_map_lookup_by_name(rmap_str);
12044 if (!rmap) {
12045 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12046 return CMD_WARNING;
12047 }
12048
96f3485c 12049 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12050}
12051
7f323236
DW
12052static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12053 const char *comstr, int exact, afi_t afi,
96f3485c 12054 safi_t safi, uint8_t show_flags)
d62a17ae 12055{
12056 struct community *com;
d62a17ae 12057 int ret = 0;
12058
7f323236 12059 com = community_str2com(comstr);
d62a17ae 12060 if (!com) {
7f323236 12061 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12062 return CMD_WARNING;
12063 }
12064
12065 ret = bgp_show(vty, bgp, afi, safi,
12066 (exact ? bgp_show_type_community_exact
12067 : bgp_show_type_community),
96f3485c 12068 com, show_flags);
3c1f53de 12069 community_free(&com);
46c3ce83 12070
d62a17ae 12071 return ret;
718e3744 12072}
12073
d62a17ae 12074static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12075 const char *com, int exact, afi_t afi,
12076 safi_t safi)
50ef26d4 12077{
d62a17ae 12078 struct community_list *list;
96f3485c 12079 uint8_t show_flags = 0;
50ef26d4 12080
e237b0d2 12081 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12082 if (list == NULL) {
12083 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12084 return CMD_WARNING;
12085 }
718e3744 12086
d62a17ae 12087 return bgp_show(vty, bgp, afi, safi,
12088 (exact ? bgp_show_type_community_list_exact
12089 : bgp_show_type_community_list),
96f3485c 12090 list, show_flags);
50ef26d4 12091}
12092
d62a17ae 12093static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12094 const char *prefix, afi_t afi, safi_t safi,
12095 enum bgp_show_type type)
718e3744 12096{
d62a17ae 12097 int ret;
12098 struct prefix *p;
96f3485c 12099 uint8_t show_flags = 0;
47fc97cc 12100
d62a17ae 12101 p = prefix_new();
95cbbd2a 12102
d62a17ae 12103 ret = str2prefix(prefix, p);
12104 if (!ret) {
12105 vty_out(vty, "%% Malformed Prefix\n");
12106 return CMD_WARNING;
12107 }
47e9b292 12108
96f3485c 12109 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12110 prefix_free(&p);
d62a17ae 12111 return ret;
12112}
12113
d62a17ae 12114enum bgp_stats {
12115 BGP_STATS_MAXBITLEN = 0,
12116 BGP_STATS_RIB,
12117 BGP_STATS_PREFIXES,
12118 BGP_STATS_TOTPLEN,
12119 BGP_STATS_UNAGGREGATEABLE,
12120 BGP_STATS_MAX_AGGREGATEABLE,
12121 BGP_STATS_AGGREGATES,
12122 BGP_STATS_SPACE,
12123 BGP_STATS_ASPATH_COUNT,
12124 BGP_STATS_ASPATH_MAXHOPS,
12125 BGP_STATS_ASPATH_TOTHOPS,
12126 BGP_STATS_ASPATH_MAXSIZE,
12127 BGP_STATS_ASPATH_TOTSIZE,
12128 BGP_STATS_ASN_HIGHEST,
12129 BGP_STATS_MAX,
a636c635 12130};
2815e61f 12131
9ab0cf58 12132#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12133#define TABLE_STATS_IDX_JSON 1
12134
12135static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12136 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12137 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12138 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12139 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12140 "unaggregateablePrefixes"},
12141 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12142 "maximumAggregateablePrefixes"},
12143 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12144 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12145 [BGP_STATS_SPACE] = {"Address space advertised",
12146 "addressSpaceAdvertised"},
9ab0cf58
PG
12147 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12148 "advertisementsWithPaths"},
12149 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12150 "longestAsPath"},
12151 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12152 "largestAsPath"},
12153 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12154 "averageAsPathLengthHops"},
12155 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12156 "averageAsPathSizeBytes"},
12157 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12158 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12159};
2815e61f 12160
d62a17ae 12161struct bgp_table_stats {
12162 struct bgp_table *table;
12163 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12164 double total_space;
ff7924f6
PJ
12165};
12166
a636c635
DW
12167#if 0
12168#define TALLY_SIGFIG 100000
12169static unsigned long
12170ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12171{
a636c635
DW
12172 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12173 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12174 unsigned long ret = newtot / count;
07d0c4ed 12175
a636c635
DW
12176 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12177 return ret + 1;
12178 else
12179 return ret;
12180}
12181#endif
ff7924f6 12182
9bcb3eef 12183static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12184 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12185{
9bcb3eef 12186 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12187 struct bgp_path_info *pi;
b54892e0 12188 const struct prefix *rn_p;
d62a17ae 12189
9bcb3eef 12190 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12191 return;
d62a17ae 12192
9bcb3eef 12193 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12194 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12195 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12196
a636c635
DW
12197#if 0
12198 ts->counts[BGP_STATS_AVGPLEN]
12199 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12200 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12201 rn_p->prefixlen);
a636c635 12202#endif
d62a17ae 12203
9c14ec72 12204 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12205 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12206 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12207
9bcb3eef 12208 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12209 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12210 /* announced address space */
12211 if (space)
b54892e0 12212 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12213 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12214 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12215
9c14ec72 12216
9bcb3eef 12217 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12218 ts->counts[BGP_STATS_RIB]++;
12219
05864da7
DS
12220 if (CHECK_FLAG(pi->attr->flag,
12221 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12222 ts->counts[BGP_STATS_AGGREGATES]++;
12223
12224 /* as-path stats */
05864da7 12225 if (pi->attr->aspath) {
9c14ec72
RW
12226 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12227 unsigned int size = aspath_size(pi->attr->aspath);
12228 as_t highest = aspath_highest(pi->attr->aspath);
12229
12230 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12231
12232 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12233 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12234
12235 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12236 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12237
12238 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12239 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12240#if 0
07d0c4ed 12241 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12242 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12243 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12244 hops);
12245 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12246 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12247 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12248 size);
12249#endif
9c14ec72
RW
12250 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12251 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12252 }
12253 }
12254}
12255
12256static int bgp_table_stats_walker(struct thread *t)
12257{
9bcb3eef
DS
12258 struct bgp_dest *dest, *ndest;
12259 struct bgp_dest *top;
9c14ec72
RW
12260 struct bgp_table_stats *ts = THREAD_ARG(t);
12261 unsigned int space = 0;
12262
12263 if (!(top = bgp_table_top(ts->table)))
12264 return 0;
12265
12266 switch (ts->table->afi) {
12267 case AFI_IP:
12268 space = IPV4_MAX_BITLEN;
12269 break;
12270 case AFI_IP6:
12271 space = IPV6_MAX_BITLEN;
12272 break;
12273 default:
12274 return 0;
12275 }
12276
12277 ts->counts[BGP_STATS_MAXBITLEN] = space;
12278
9bcb3eef 12279 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12280 if (ts->table->safi == SAFI_MPLS_VPN
12281 || ts->table->safi == SAFI_ENCAP
12282 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12283 struct bgp_table *table;
12284
9bcb3eef 12285 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12286 if (!table)
12287 continue;
12288
12289 top = bgp_table_top(table);
9bcb3eef
DS
12290 for (ndest = bgp_table_top(table); ndest;
12291 ndest = bgp_route_next(ndest))
12292 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12293 } else {
9bcb3eef 12294 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12295 }
12296 }
9c14ec72 12297
d62a17ae 12298 return 0;
2815e61f 12299}
ff7924f6 12300
71f1613a
DA
12301static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12302 struct json_object *json_array)
12303{
12304 struct listnode *node, *nnode;
12305 struct bgp *bgp;
12306
12307 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12308 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12309}
12310
12311static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12312 safi_t safi, struct json_object *json_array)
2815e61f 12313{
d62a17ae 12314 struct bgp_table_stats ts;
12315 unsigned int i;
893cccd0
PG
12316 int ret = CMD_SUCCESS;
12317 char temp_buf[20];
6c9d22e2
PG
12318 struct json_object *json = NULL;
12319
12320 if (json_array)
12321 json = json_object_new_object();
019386c2 12322
d62a17ae 12323 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12324 char warning_msg[50];
12325
12326 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12327 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12328 safi);
6c9d22e2
PG
12329
12330 if (!json)
893cccd0
PG
12331 vty_out(vty, "%s\n", warning_msg);
12332 else
9ab0cf58 12333 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12334
893cccd0
PG
12335 ret = CMD_WARNING;
12336 goto end_table_stats;
d62a17ae 12337 }
019386c2 12338
893cccd0 12339 if (!json)
5290ceab
DA
12340 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12341 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12342 else
12343 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12344
d62a17ae 12345 /* labeled-unicast routes live in the unicast table */
12346 if (safi == SAFI_LABELED_UNICAST)
12347 safi = SAFI_UNICAST;
019386c2 12348
d62a17ae 12349 memset(&ts, 0, sizeof(ts));
12350 ts.table = bgp->rib[afi][safi];
12351 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12352
d62a17ae 12353 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12354 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12355 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12356 continue;
12357
12358 switch (i) {
a636c635
DW
12359#if 0
12360 case BGP_STATS_ASPATH_AVGHOPS:
12361 case BGP_STATS_ASPATH_AVGSIZE:
12362 case BGP_STATS_AVGPLEN:
12363 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12364 vty_out (vty, "%12.2f",
12365 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12366 break;
12367#endif
d62a17ae 12368 case BGP_STATS_ASPATH_TOTHOPS:
12369 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12370 if (!json) {
9ab0cf58
PG
12371 snprintf(
12372 temp_buf, sizeof(temp_buf), "%12.2f",
12373 ts.counts[i]
12374 ? (float)ts.counts[i]
12375 / (float)ts.counts
12376 [BGP_STATS_ASPATH_COUNT]
12377 : 0);
893cccd0 12378 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12379 table_stats_strs[i]
12380 [TABLE_STATS_IDX_VTY],
893cccd0 12381 temp_buf);
9ab0cf58
PG
12382 } else {
12383 json_object_double_add(
12384 json,
12385 table_stats_strs[i]
12386 [TABLE_STATS_IDX_JSON],
12387 ts.counts[i]
12388 ? (double)ts.counts[i]
12389 / (double)ts.counts
d62a17ae 12390 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12391 : 0);
12392 }
d62a17ae 12393 break;
12394 case BGP_STATS_TOTPLEN:
6c9d22e2 12395 if (!json) {
9ab0cf58
PG
12396 snprintf(
12397 temp_buf, sizeof(temp_buf), "%12.2f",
12398 ts.counts[i]
12399 ? (float)ts.counts[i]
12400 / (float)ts.counts
12401 [BGP_STATS_PREFIXES]
12402 : 0);
893cccd0 12403 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12404 table_stats_strs[i]
12405 [TABLE_STATS_IDX_VTY],
893cccd0 12406 temp_buf);
9ab0cf58
PG
12407 } else {
12408 json_object_double_add(
12409 json,
12410 table_stats_strs[i]
12411 [TABLE_STATS_IDX_JSON],
12412 ts.counts[i]
12413 ? (double)ts.counts[i]
12414 / (double)ts.counts
d62a17ae 12415 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12416 : 0);
12417 }
d62a17ae 12418 break;
12419 case BGP_STATS_SPACE:
6c9d22e2
PG
12420 if (!json) {
12421 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12422 ts.total_space);
893cccd0 12423 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12424 table_stats_strs[i]
12425 [TABLE_STATS_IDX_VTY],
893cccd0 12426 temp_buf);
9ab0cf58
PG
12427 } else {
12428 json_object_double_add(
12429 json,
12430 table_stats_strs[i]
12431 [TABLE_STATS_IDX_JSON],
12432 (double)ts.total_space);
12433 }
8d0ab76d 12434 if (afi == AFI_IP6) {
6c9d22e2
PG
12435 if (!json) {
12436 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12437 "%12g",
12438 ts.total_space
12439 * pow(2.0, -128 + 32));
6c9d22e2
PG
12440 vty_out(vty, "%30s: %s\n",
12441 "/32 equivalent %s\n",
12442 temp_buf);
9ab0cf58
PG
12443 } else {
12444 json_object_double_add(
12445 json, "/32equivalent",
12446 (double)(ts.total_space
12447 * pow(2.0,
12448 -128 + 32)));
12449 }
6c9d22e2
PG
12450 if (!json) {
12451 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12452 "%12g",
12453 ts.total_space
12454 * pow(2.0, -128 + 48));
6c9d22e2
PG
12455 vty_out(vty, "%30s: %s\n",
12456 "/48 equivalent %s\n",
12457 temp_buf);
9ab0cf58
PG
12458 } else {
12459 json_object_double_add(
12460 json, "/48equivalent",
12461 (double)(ts.total_space
12462 * pow(2.0,
12463 -128 + 48)));
12464 }
8d0ab76d 12465 } else {
6c9d22e2
PG
12466 if (!json) {
12467 snprintf(temp_buf, sizeof(temp_buf),
12468 "%12.2f",
9ab0cf58
PG
12469 ts.total_space * 100.
12470 * pow(2.0, -32));
6c9d22e2 12471 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12472 "% announced ", temp_buf);
12473 } else {
12474 json_object_double_add(
12475 json, "%announced",
12476 (double)(ts.total_space * 100.
12477 * pow(2.0, -32)));
12478 }
6c9d22e2
PG
12479 if (!json) {
12480 snprintf(temp_buf, sizeof(temp_buf),
12481 "%12.2f",
9ab0cf58
PG
12482 ts.total_space
12483 * pow(2.0, -32 + 8));
6c9d22e2
PG
12484 vty_out(vty, "%30s: %s\n",
12485 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12486 } else {
12487 json_object_double_add(
12488 json, "/8equivalent",
12489 (double)(ts.total_space
12490 * pow(2.0, -32 + 8)));
12491 }
6c9d22e2
PG
12492 if (!json) {
12493 snprintf(temp_buf, sizeof(temp_buf),
12494 "%12.2f",
9ab0cf58
PG
12495 ts.total_space
12496 * pow(2.0, -32 + 24));
6c9d22e2 12497 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12498 "/24 equivalent ", temp_buf);
12499 } else {
12500 json_object_double_add(
12501 json, "/24equivalent",
12502 (double)(ts.total_space
12503 * pow(2.0, -32 + 24)));
12504 }
8d0ab76d 12505 }
d62a17ae 12506 break;
12507 default:
6c9d22e2
PG
12508 if (!json) {
12509 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12510 ts.counts[i]);
893cccd0 12511 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12512 table_stats_strs[i]
12513 [TABLE_STATS_IDX_VTY],
12514 temp_buf);
12515 } else {
12516 json_object_int_add(
12517 json,
12518 table_stats_strs[i]
12519 [TABLE_STATS_IDX_JSON],
12520 ts.counts[i]);
12521 }
d62a17ae 12522 }
893cccd0
PG
12523 if (!json)
12524 vty_out(vty, "\n");
d62a17ae 12525 }
9ab0cf58 12526end_table_stats:
6c9d22e2
PG
12527 if (json)
12528 json_object_array_add(json_array, json);
893cccd0 12529 return ret;
d62a17ae 12530}
12531
71f1613a
DA
12532static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12533 safi_t safi, struct json_object *json_array)
12534{
12535 if (!bgp) {
12536 bgp_table_stats_all(vty, afi, safi, json_array);
12537 return CMD_SUCCESS;
12538 }
12539
12540 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12541}
12542
d62a17ae 12543enum bgp_pcounts {
12544 PCOUNT_ADJ_IN = 0,
12545 PCOUNT_DAMPED,
12546 PCOUNT_REMOVED,
12547 PCOUNT_HISTORY,
12548 PCOUNT_STALE,
12549 PCOUNT_VALID,
12550 PCOUNT_ALL,
12551 PCOUNT_COUNTED,
7e3d9632 12552 PCOUNT_BPATH_SELECTED,
d62a17ae 12553 PCOUNT_PFCNT, /* the figure we display to users */
12554 PCOUNT_MAX,
a636c635 12555};
718e3744 12556
2b64873d 12557static const char *const pcount_strs[] = {
9d303b37
DL
12558 [PCOUNT_ADJ_IN] = "Adj-in",
12559 [PCOUNT_DAMPED] = "Damped",
12560 [PCOUNT_REMOVED] = "Removed",
12561 [PCOUNT_HISTORY] = "History",
12562 [PCOUNT_STALE] = "Stale",
12563 [PCOUNT_VALID] = "Valid",
12564 [PCOUNT_ALL] = "All RIB",
12565 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12566 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12567 [PCOUNT_PFCNT] = "Useable",
12568 [PCOUNT_MAX] = NULL,
a636c635 12569};
718e3744 12570
d62a17ae 12571struct peer_pcounts {
12572 unsigned int count[PCOUNT_MAX];
12573 const struct peer *peer;
12574 const struct bgp_table *table;
54317cba 12575 safi_t safi;
a636c635 12576};
47fc97cc 12577
9bcb3eef 12578static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12579{
54317cba
JW
12580 const struct bgp_adj_in *ain;
12581 const struct bgp_path_info *pi;
d62a17ae 12582 const struct peer *peer = pc->peer;
12583
54317cba
JW
12584 for (ain = rn->adj_in; ain; ain = ain->next)
12585 if (ain->peer == peer)
12586 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12587
9bcb3eef 12588 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12589
54317cba
JW
12590 if (pi->peer != peer)
12591 continue;
d62a17ae 12592
54317cba 12593 pc->count[PCOUNT_ALL]++;
d62a17ae 12594
54317cba
JW
12595 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12596 pc->count[PCOUNT_DAMPED]++;
12597 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12598 pc->count[PCOUNT_HISTORY]++;
12599 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12600 pc->count[PCOUNT_REMOVED]++;
12601 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12602 pc->count[PCOUNT_STALE]++;
12603 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12604 pc->count[PCOUNT_VALID]++;
12605 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12606 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12607 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12608 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12609
12610 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12611 pc->count[PCOUNT_COUNTED]++;
12612 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12613 flog_err(
12614 EC_LIB_DEVELOPMENT,
12615 "Attempting to count but flags say it is unusable");
12616 } else {
40381db7 12617 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12618 flog_err(
12619 EC_LIB_DEVELOPMENT,
12620 "Not counted but flags say we should");
d62a17ae 12621 }
12622 }
54317cba
JW
12623}
12624
12625static int bgp_peer_count_walker(struct thread *t)
12626{
9bcb3eef 12627 struct bgp_dest *rn, *rm;
54317cba
JW
12628 const struct bgp_table *table;
12629 struct peer_pcounts *pc = THREAD_ARG(t);
12630
12631 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12632 || pc->safi == SAFI_EVPN) {
12633 /* Special handling for 2-level routing tables. */
12634 for (rn = bgp_table_top(pc->table); rn;
12635 rn = bgp_route_next(rn)) {
9bcb3eef 12636 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12637 if (table != NULL)
12638 for (rm = bgp_table_top(table); rm;
12639 rm = bgp_route_next(rm))
12640 bgp_peer_count_proc(rm, pc);
12641 }
12642 } else
12643 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12644 bgp_peer_count_proc(rn, pc);
12645
d62a17ae 12646 return 0;
718e3744 12647}
12648
d62a17ae 12649static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12650 safi_t safi, bool use_json)
856ca177 12651{
d62a17ae 12652 struct peer_pcounts pcounts = {.peer = peer};
12653 unsigned int i;
12654 json_object *json = NULL;
12655 json_object *json_loop = NULL;
856ca177 12656
d62a17ae 12657 if (use_json) {
12658 json = json_object_new_object();
12659 json_loop = json_object_new_object();
12660 }
718e3744 12661
d62a17ae 12662 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12663 || !peer->bgp->rib[afi][safi]) {
12664 if (use_json) {
12665 json_object_string_add(
12666 json, "warning",
12667 "No such neighbor or address family");
12668 vty_out(vty, "%s\n", json_object_to_json_string(json));
12669 json_object_free(json);
12670 } else
12671 vty_out(vty, "%% No such neighbor or address family\n");
12672
12673 return CMD_WARNING;
12674 }
2a71e9ce 12675
d62a17ae 12676 memset(&pcounts, 0, sizeof(pcounts));
12677 pcounts.peer = peer;
12678 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12679 pcounts.safi = safi;
d62a17ae 12680
12681 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12682 * stats for the thread-walk (i.e. ensure this can't be blamed on
12683 * on just vty_read()).
12684 */
d62a17ae 12685 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12686
12687 if (use_json) {
12688 json_object_string_add(json, "prefixCountsFor", peer->host);
12689 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12690 get_afi_safi_str(afi, safi, true));
d62a17ae 12691 json_object_int_add(json, "pfxCounter",
12692 peer->pcount[afi][safi]);
12693
12694 for (i = 0; i < PCOUNT_MAX; i++)
12695 json_object_int_add(json_loop, pcount_strs[i],
12696 pcounts.count[i]);
12697
12698 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12699
12700 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12701 json_object_string_add(json, "pfxctDriftFor",
12702 peer->host);
12703 json_object_string_add(
12704 json, "recommended",
12705 "Please report this bug, with the above command output");
12706 }
996c9314
LB
12707 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12708 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12709 json_object_free(json);
12710 } else {
12711
12712 if (peer->hostname
892fedb6 12713 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12714 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12715 peer->hostname, peer->host,
5cb5f4d0 12716 get_afi_safi_str(afi, safi, false));
d62a17ae 12717 } else {
12718 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12719 get_afi_safi_str(afi, safi, false));
d62a17ae 12720 }
12721
6cde4b45 12722 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12723 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12724
12725 for (i = 0; i < PCOUNT_MAX; i++)
12726 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12727 pcounts.count[i]);
12728
12729 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12730 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12731 vty_out(vty,
12732 "Please report this bug, with the above command output\n");
12733 }
12734 }
12735
12736 return CMD_SUCCESS;
718e3744 12737}
12738
a636c635
DW
12739DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12740 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12741 "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 12742 SHOW_STR
12743 IP_STR
12744 BGP_STR
8386ac43 12745 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12746 BGP_AFI_HELP_STR
12747 BGP_SAFI_HELP_STR
0b16f239
DS
12748 "Detailed information on TCP and BGP neighbor connections\n"
12749 "Neighbor to display information about\n"
12750 "Neighbor to display information about\n"
91d37724 12751 "Neighbor on BGP configured interface\n"
a636c635 12752 "Display detailed prefix count information\n"
9973d184 12753 JSON_STR)
0b16f239 12754{
d62a17ae 12755 afi_t afi = AFI_IP6;
12756 safi_t safi = SAFI_UNICAST;
12757 struct peer *peer;
12758 int idx = 0;
12759 struct bgp *bgp = NULL;
9f049418
DS
12760 bool uj = use_json(argc, argv);
12761
12762 if (uj)
12763 argc--;
856ca177 12764
d62a17ae 12765 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12766 &bgp, uj);
d62a17ae 12767 if (!idx)
12768 return CMD_WARNING;
0b16f239 12769
d62a17ae 12770 argv_find(argv, argc, "neighbors", &idx);
12771 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12772 if (!peer)
12773 return CMD_WARNING;
bb46e94f 12774
29c8d9da 12775 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12776}
0b16f239 12777
d6902373
PG
12778#ifdef KEEP_OLD_VPN_COMMANDS
12779DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12780 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12781 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12782 SHOW_STR
12783 IP_STR
12784 BGP_STR
d6902373 12785 BGP_VPNVX_HELP_STR
91d37724 12786 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12787 "Detailed information on TCP and BGP neighbor connections\n"
12788 "Neighbor to display information about\n"
12789 "Neighbor to display information about\n"
91d37724 12790 "Neighbor on BGP configured interface\n"
a636c635 12791 "Display detailed prefix count information\n"
9973d184 12792 JSON_STR)
a636c635 12793{
d62a17ae 12794 int idx_peer = 6;
12795 struct peer *peer;
9f049418 12796 bool uj = use_json(argc, argv);
a636c635 12797
d62a17ae 12798 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12799 if (!peer)
12800 return CMD_WARNING;
12801
12802 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12803}
12804
d6902373
PG
12805DEFUN (show_ip_bgp_vpn_all_route_prefix,
12806 show_ip_bgp_vpn_all_route_prefix_cmd,
12807 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12808 SHOW_STR
12809 IP_STR
12810 BGP_STR
d6902373 12811 BGP_VPNVX_HELP_STR
91d37724
QY
12812 "Display information about all VPNv4 NLRIs\n"
12813 "Network in the BGP routing table to display\n"
3a2d747c 12814 "Network in the BGP routing table to display\n"
9973d184 12815 JSON_STR)
91d37724 12816{
d62a17ae 12817 int idx = 0;
12818 char *network = NULL;
12819 struct bgp *bgp = bgp_get_default();
12820 if (!bgp) {
12821 vty_out(vty, "Can't find default instance\n");
12822 return CMD_WARNING;
12823 }
87e34b58 12824
d62a17ae 12825 if (argv_find(argv, argc, "A.B.C.D", &idx))
12826 network = argv[idx]->arg;
12827 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12828 network = argv[idx]->arg;
12829 else {
12830 vty_out(vty, "Unable to figure out Network\n");
12831 return CMD_WARNING;
12832 }
87e34b58 12833
d62a17ae 12834 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12835 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12836}
d6902373 12837#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12838
44c69747
LK
12839DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12840 show_bgp_l2vpn_evpn_route_prefix_cmd,
12841 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12842 SHOW_STR
4c63a661
PG
12843 BGP_STR
12844 L2VPN_HELP_STR
12845 EVPN_HELP_STR
44c69747
LK
12846 "Network in the BGP routing table to display\n"
12847 "Network in the BGP routing table to display\n"
4c63a661
PG
12848 "Network in the BGP routing table to display\n"
12849 "Network in the BGP routing table to display\n"
12850 JSON_STR)
12851{
d62a17ae 12852 int idx = 0;
12853 char *network = NULL;
44c69747 12854 int prefix_check = 0;
a636c635 12855
44c69747
LK
12856 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12857 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12858 network = argv[idx]->arg;
44c69747 12859 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12860 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12861 network = argv[idx]->arg;
44c69747
LK
12862 prefix_check = 1;
12863 } else {
d62a17ae 12864 vty_out(vty, "Unable to figure out Network\n");
12865 return CMD_WARNING;
12866 }
44c69747
LK
12867 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12868 prefix_check, BGP_PATH_SHOW_ALL,
12869 use_json(argc, argv));
d62a17ae 12870}
12871
2f9bc755
DS
12872static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12873 struct bgp_table *table, int *header1,
12874 int *header2, json_object *json,
12875 json_object *json_scode,
12876 json_object *json_ocode, bool wide)
12877{
12878 uint64_t version = table ? table->version : 0;
23d0a753 12879 char buf[BUFSIZ] = {0};
2f9bc755
DS
12880
12881 if (*header1) {
12882 if (json) {
12883 json_object_int_add(json, "bgpTableVersion", version);
12884 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12885 inet_ntop(AF_INET,
12886 &bgp->router_id, buf,
12887 sizeof(buf)));
2f9bc755
DS
12888 json_object_int_add(json, "defaultLocPrf",
12889 bgp->default_local_pref);
12890 json_object_int_add(json, "localAS", bgp->as);
12891 json_object_object_add(json, "bgpStatusCodes",
12892 json_scode);
12893 json_object_object_add(json, "bgpOriginCodes",
12894 json_ocode);
12895 } else {
12896 vty_out(vty,
23d0a753
DA
12897 "BGP table version is %" PRIu64
12898 ", local router ID is %pI4, vrf id ",
12899 version, &bgp->router_id);
2f9bc755
DS
12900 if (bgp->vrf_id == VRF_UNKNOWN)
12901 vty_out(vty, "%s", VRFID_NONE_STR);
12902 else
12903 vty_out(vty, "%u", bgp->vrf_id);
12904 vty_out(vty, "\n");
12905 vty_out(vty, "Default local pref %u, ",
12906 bgp->default_local_pref);
12907 vty_out(vty, "local AS %u\n", bgp->as);
12908 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12909 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12910 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12911 }
12912 *header1 = 0;
12913 }
12914 if (*header2) {
12915 if (!json)
12916 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12917 : BGP_SHOW_HEADER));
12918 *header2 = 0;
12919 }
12920}
12921
d62a17ae 12922static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12923 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12924 const char *rmap_name, json_object *json,
12925 uint8_t show_flags)
d62a17ae 12926{
12927 struct bgp_table *table;
12928 struct bgp_adj_in *ain;
12929 struct bgp_adj_out *adj;
74a630b6
NT
12930 unsigned long output_count = 0;
12931 unsigned long filtered_count = 0;
9bcb3eef 12932 struct bgp_dest *dest;
d62a17ae 12933 int header1 = 1;
12934 struct bgp *bgp;
12935 int header2 = 1;
12936 struct attr attr;
12937 int ret;
12938 struct update_subgroup *subgrp;
12939 json_object *json_scode = NULL;
12940 json_object *json_ocode = NULL;
12941 json_object *json_ar = NULL;
12942 struct peer_af *paf;
f99def61 12943 bool route_filtered;
96f3485c
MK
12944 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12945 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12946
12947 if (use_json) {
12948 json_scode = json_object_new_object();
12949 json_ocode = json_object_new_object();
12950 json_ar = json_object_new_object();
12951
12952 json_object_string_add(json_scode, "suppressed", "s");
12953 json_object_string_add(json_scode, "damped", "d");
12954 json_object_string_add(json_scode, "history", "h");
12955 json_object_string_add(json_scode, "valid", "*");
12956 json_object_string_add(json_scode, "best", ">");
12957 json_object_string_add(json_scode, "multipath", "=");
12958 json_object_string_add(json_scode, "internal", "i");
12959 json_object_string_add(json_scode, "ribFailure", "r");
12960 json_object_string_add(json_scode, "stale", "S");
12961 json_object_string_add(json_scode, "removed", "R");
12962
12963 json_object_string_add(json_ocode, "igp", "i");
12964 json_object_string_add(json_ocode, "egp", "e");
12965 json_object_string_add(json_ocode, "incomplete", "?");
12966 }
a636c635 12967
d62a17ae 12968 bgp = peer->bgp;
a636c635 12969
d62a17ae 12970 if (!bgp) {
12971 if (use_json) {
12972 json_object_string_add(json, "alert", "no BGP");
12973 vty_out(vty, "%s\n", json_object_to_json_string(json));
12974 json_object_free(json);
12975 } else
12976 vty_out(vty, "%% No bgp\n");
12977 return;
12978 }
a636c635 12979
c512a642
EDP
12980 /* labeled-unicast routes live in the unicast table */
12981 if (safi == SAFI_LABELED_UNICAST)
12982 table = bgp->rib[afi][SAFI_UNICAST];
12983 else
12984 table = bgp->rib[afi][safi];
d62a17ae 12985
12986 output_count = filtered_count = 0;
12987 subgrp = peer_subgroup(peer, afi, safi);
12988
6392aaa6 12989 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12990 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
12991 char buf[BUFSIZ] = {0};
12992
d62a17ae 12993 if (use_json) {
12994 json_object_int_add(json, "bgpTableVersion",
12995 table->version);
12996 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12997 inet_ntop(AF_INET,
12998 &bgp->router_id, buf,
12999 sizeof(buf)));
01eced22
AD
13000 json_object_int_add(json, "defaultLocPrf",
13001 bgp->default_local_pref);
13002 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13003 json_object_object_add(json, "bgpStatusCodes",
13004 json_scode);
13005 json_object_object_add(json, "bgpOriginCodes",
13006 json_ocode);
07d0c4ed
DA
13007 json_object_string_add(
13008 json, "bgpOriginatingDefaultNetwork",
13009 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13010 } else {
23d0a753
DA
13011 vty_out(vty,
13012 "BGP table version is %" PRIu64
13013 ", local router ID is %pI4, vrf id ",
13014 table->version, &bgp->router_id);
9df8b37c
PZ
13015 if (bgp->vrf_id == VRF_UNKNOWN)
13016 vty_out(vty, "%s", VRFID_NONE_STR);
13017 else
13018 vty_out(vty, "%u", bgp->vrf_id);
13019 vty_out(vty, "\n");
01eced22
AD
13020 vty_out(vty, "Default local pref %u, ",
13021 bgp->default_local_pref);
13022 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13023 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13024 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13025 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13026
07d0c4ed
DA
13027 vty_out(vty, "Originating default network %s\n\n",
13028 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13029 }
13030 header1 = 0;
13031 }
a636c635 13032
9bcb3eef 13033 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13034 if (type == bgp_show_adj_route_received
13035 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13036 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13037 if (ain->peer != peer)
ea47320b 13038 continue;
6392aaa6 13039
2f9bc755
DS
13040 show_adj_route_header(
13041 vty, bgp, table, &header1, &header2,
13042 json, json_scode, json_ocode, wide);
6392aaa6 13043
6f4f49b2 13044 attr = *ain->attr;
f99def61
AD
13045 route_filtered = false;
13046
13047 /* Filter prefix using distribute list,
13048 * filter list or prefix list
13049 */
b54892e0 13050 const struct prefix *rn_p =
9bcb3eef 13051 bgp_dest_get_prefix(dest);
b54892e0
DS
13052 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13053 safi))
13054 == FILTER_DENY)
f99def61
AD
13055 route_filtered = true;
13056
13057 /* Filter prefix using route-map */
b54892e0
DS
13058 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13059 safi, rmap_name, NULL,
13060 0, NULL);
6392aaa6 13061
13c8e163
AD
13062 if (type == bgp_show_adj_route_filtered &&
13063 !route_filtered && ret != RMAP_DENY) {
b755861b 13064 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13065 continue;
d62a17ae 13066 }
6392aaa6 13067
13c8e163
AD
13068 if (type == bgp_show_adj_route_received &&
13069 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13070 filtered_count++;
13071
b54892e0 13072 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13073 use_json, json_ar, wide);
b755861b 13074 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13075 output_count++;
d62a17ae 13076 }
6392aaa6 13077 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13078 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13079 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13080 if (paf->peer != peer || !adj->attr)
924c3f6a 13081 continue;
d62a17ae 13082
2f9bc755
DS
13083 show_adj_route_header(
13084 vty, bgp, table, &header1,
13085 &header2, json, json_scode,
13086 json_ocode, wide);
d62a17ae 13087
b54892e0 13088 const struct prefix *rn_p =
9bcb3eef 13089 bgp_dest_get_prefix(dest);
b54892e0 13090
6f4f49b2 13091 attr = *adj->attr;
b755861b 13092 ret = bgp_output_modifier(
b54892e0 13093 peer, rn_p, &attr, afi, safi,
b755861b 13094 rmap_name);
f46d8e1e 13095
b755861b 13096 if (ret != RMAP_DENY) {
b54892e0
DS
13097 route_vty_out_tmp(
13098 vty, rn_p, &attr, safi,
ae248832
MK
13099 use_json, json_ar,
13100 wide);
b755861b
PM
13101 output_count++;
13102 } else {
13103 filtered_count++;
a2addae8 13104 }
b755861b
PM
13105
13106 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13107 }
f20ce998
DS
13108 } else if (type == bgp_show_adj_route_bestpath) {
13109 struct bgp_path_info *pi;
13110
13111 show_adj_route_header(vty, bgp, table, &header1,
13112 &header2, json, json_scode,
13113 json_ocode, wide);
13114
13115 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13116 pi = pi->next) {
13117 if (pi->peer != peer)
13118 continue;
13119
13120 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13121 continue;
13122
13123 route_vty_out_tmp(vty,
13124 bgp_dest_get_prefix(dest),
13125 pi->attr, safi, use_json,
13126 json_ar, wide);
13127 output_count++;
13128 }
d62a17ae 13129 }
13130 }
d62a17ae 13131
d62a17ae 13132 if (use_json) {
6392aaa6
PM
13133 json_object_object_add(json, "advertisedRoutes", json_ar);
13134 json_object_int_add(json, "totalPrefixCounter", output_count);
13135 json_object_int_add(json, "filteredPrefixCounter",
13136 filtered_count);
13137
996c9314
LB
13138 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13139 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13140
13141 if (!output_count && !filtered_count) {
13142 json_object_free(json_scode);
13143 json_object_free(json_ocode);
13144 }
13145
d62a17ae 13146 json_object_free(json);
6392aaa6
PM
13147 } else if (output_count > 0) {
13148 if (filtered_count > 0)
13149 vty_out(vty,
13150 "\nTotal number of prefixes %ld (%ld filtered)\n",
13151 output_count, filtered_count);
13152 else
13153 vty_out(vty, "\nTotal number of prefixes %ld\n",
13154 output_count);
d62a17ae 13155 }
a636c635 13156}
2a71e9ce 13157
d62a17ae 13158static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13159 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13160 const char *rmap_name, uint8_t show_flags)
0b16f239 13161{
d62a17ae 13162 json_object *json = NULL;
96f3485c 13163 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13164
d62a17ae 13165 if (use_json)
13166 json = json_object_new_object();
0b16f239 13167
d62a17ae 13168 if (!peer || !peer->afc[afi][safi]) {
13169 if (use_json) {
13170 json_object_string_add(
13171 json, "warning",
13172 "No such neighbor or address family");
13173 vty_out(vty, "%s\n", json_object_to_json_string(json));
13174 json_object_free(json);
13175 } else
13176 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13177
d62a17ae 13178 return CMD_WARNING;
13179 }
13180
6392aaa6
PM
13181 if ((type == bgp_show_adj_route_received
13182 || type == bgp_show_adj_route_filtered)
d62a17ae 13183 && !CHECK_FLAG(peer->af_flags[afi][safi],
13184 PEER_FLAG_SOFT_RECONFIG)) {
13185 if (use_json) {
13186 json_object_string_add(
13187 json, "warning",
13188 "Inbound soft reconfiguration not enabled");
13189 vty_out(vty, "%s\n", json_object_to_json_string(json));
13190 json_object_free(json);
13191 } else
13192 vty_out(vty,
13193 "%% Inbound soft reconfiguration not enabled\n");
13194
13195 return CMD_WARNING;
13196 }
0b16f239 13197
96f3485c 13198 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13199
d62a17ae 13200 return CMD_SUCCESS;
a636c635 13201}
50ef26d4 13202
f20ce998
DS
13203DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13204 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13205 "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]",
13206 SHOW_STR
13207 IP_STR
13208 BGP_STR
13209 BGP_INSTANCE_HELP_STR
13210 BGP_AFI_HELP_STR
13211 BGP_SAFI_WITH_LABEL_HELP_STR
13212 "Detailed information on TCP and BGP neighbor connections\n"
13213 "Neighbor to display information about\n"
13214 "Neighbor to display information about\n"
13215 "Neighbor on BGP configured interface\n"
13216 "Display the routes selected by best path\n"
13217 JSON_STR
13218 "Increase table width for longer prefixes\n")
13219{
13220 afi_t afi = AFI_IP6;
13221 safi_t safi = SAFI_UNICAST;
13222 char *rmap_name = NULL;
13223 char *peerstr = NULL;
13224 struct bgp *bgp = NULL;
13225 struct peer *peer;
13226 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13227 int idx = 0;
96f3485c
MK
13228 uint8_t show_flags = 0;
13229
13230 if (uj)
13231 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13232
13233 if (wide)
13234 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13235
13236 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13237 &bgp, uj);
13238
13239 if (!idx)
13240 return CMD_WARNING;
13241
13242 argv_find(argv, argc, "neighbors", &idx);
13243 peerstr = argv[++idx]->arg;
13244
13245 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13246 if (!peer)
13247 return CMD_WARNING;
13248
96f3485c
MK
13249 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13250 show_flags);
f20ce998
DS
13251}
13252
ae248832 13253DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13254 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13255 "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 13256 SHOW_STR
13257 IP_STR
13258 BGP_STR
a636c635 13259 BGP_INSTANCE_HELP_STR
7395a2c9 13260 BGP_AFI_HELP_STR
4dd6177e 13261 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13262 "Display the entries for all address families\n"
718e3744 13263 "Detailed information on TCP and BGP neighbor connections\n"
13264 "Neighbor to display information about\n"
13265 "Neighbor to display information about\n"
91d37724 13266 "Neighbor on BGP configured interface\n"
a636c635 13267 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13268 "Display the received routes from neighbor\n"
13269 "Display the filtered routes received from neighbor\n"
a636c635
DW
13270 "Route-map to modify the attributes\n"
13271 "Name of the route map\n"
ae248832
MK
13272 JSON_STR
13273 "Increase table width for longer prefixes\n")
718e3744 13274{
d62a17ae 13275 afi_t afi = AFI_IP6;
13276 safi_t safi = SAFI_UNICAST;
13277 char *rmap_name = NULL;
13278 char *peerstr = NULL;
d62a17ae 13279 struct bgp *bgp = NULL;
13280 struct peer *peer;
6392aaa6 13281 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13282 int idx = 0;
96f3485c
MK
13283 bool first = true;
13284 uint8_t show_flags = 0;
6392aaa6 13285
96f3485c 13286 if (uj) {
d62a17ae 13287 argc--;
96f3485c
MK
13288 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13289 }
13290
13291 if (all) {
13292 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13293 if (argv_find(argv, argc, "ipv4", &idx))
13294 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13295
13296 if (argv_find(argv, argc, "ipv6", &idx))
13297 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13298 }
13299
13300 if (wide)
13301 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13302
9f049418
DS
13303 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13304 &bgp, uj);
13305 if (!idx)
13306 return CMD_WARNING;
13307
d62a17ae 13308 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13309 argv_find(argv, argc, "neighbors", &idx);
13310 peerstr = argv[++idx]->arg;
8c3deaae 13311
d62a17ae 13312 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13313 if (!peer)
13314 return CMD_WARNING;
856ca177 13315
d62a17ae 13316 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13317 type = bgp_show_adj_route_advertised;
13318 else if (argv_find(argv, argc, "received-routes", &idx))
13319 type = bgp_show_adj_route_received;
13320 else if (argv_find(argv, argc, "filtered-routes", &idx))
13321 type = bgp_show_adj_route_filtered;
13322
d62a17ae 13323 if (argv_find(argv, argc, "route-map", &idx))
13324 rmap_name = argv[++idx]->arg;
95cbbd2a 13325
96f3485c
MK
13326 if (!all)
13327 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13328 show_flags);
13329 if (uj)
13330 vty_out(vty, "{\n");
13331
13332 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13333 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13334 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13335 : AFI_IP6;
13336 FOREACH_SAFI (safi) {
96f3485c
MK
13337 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13338 continue;
13339
13340 if (uj) {
13341 if (first)
13342 first = false;
13343 else
13344 vty_out(vty, ",\n");
13345 vty_out(vty, "\"%s\":",
13346 get_afi_safi_str(afi, safi, true));
13347 } else
13348 vty_out(vty, "\nFor address family: %s\n",
13349 get_afi_safi_str(afi, safi, false));
13350
13351 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13352 show_flags);
13353 }
13354 } else {
13355 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13356 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13357 continue;
13358
13359 if (uj) {
13360 if (first)
13361 first = false;
13362 else
13363 vty_out(vty, ",\n");
13364 vty_out(vty, "\"%s\":",
13365 get_afi_safi_str(afi, safi, true));
13366 } else
13367 vty_out(vty, "\nFor address family: %s\n",
13368 get_afi_safi_str(afi, safi, false));
13369
13370 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13371 show_flags);
13372 }
13373 }
13374 if (uj)
13375 vty_out(vty, "}\n");
13376
13377 return CMD_SUCCESS;
95cbbd2a
ML
13378}
13379
718e3744 13380DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13381 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13382 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13383 SHOW_STR
13384 IP_STR
13385 BGP_STR
8c3deaae
QY
13386 "Address Family\n"
13387 "Address Family\n"
718e3744 13388 "Address Family modifier\n"
13389 "Detailed information on TCP and BGP neighbor connections\n"
13390 "Neighbor to display information about\n"
13391 "Neighbor to display information about\n"
91d37724 13392 "Neighbor on BGP configured interface\n"
718e3744 13393 "Display information received from a BGP neighbor\n"
856ca177 13394 "Display the prefixlist filter\n"
9973d184 13395 JSON_STR)
718e3744 13396{
d62a17ae 13397 afi_t afi = AFI_IP6;
13398 safi_t safi = SAFI_UNICAST;
13399 char *peerstr = NULL;
13400
13401 char name[BUFSIZ];
13402 union sockunion su;
13403 struct peer *peer;
13404 int count, ret;
13405
13406 int idx = 0;
13407
13408 /* show [ip] bgp */
13409 if (argv_find(argv, argc, "ip", &idx))
13410 afi = AFI_IP;
13411 /* [<ipv4|ipv6> [unicast]] */
13412 if (argv_find(argv, argc, "ipv4", &idx))
13413 afi = AFI_IP;
13414 if (argv_find(argv, argc, "ipv6", &idx))
13415 afi = AFI_IP6;
13416 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13417 argv_find(argv, argc, "neighbors", &idx);
13418 peerstr = argv[++idx]->arg;
13419
9f049418 13420 bool uj = use_json(argc, argv);
d62a17ae 13421
13422 ret = str2sockunion(peerstr, &su);
13423 if (ret < 0) {
13424 peer = peer_lookup_by_conf_if(NULL, peerstr);
13425 if (!peer) {
13426 if (uj)
13427 vty_out(vty, "{}\n");
13428 else
13429 vty_out(vty,
13430 "%% Malformed address or name: %s\n",
13431 peerstr);
13432 return CMD_WARNING;
13433 }
13434 } else {
13435 peer = peer_lookup(NULL, &su);
13436 if (!peer) {
13437 if (uj)
13438 vty_out(vty, "{}\n");
13439 else
13440 vty_out(vty, "No peer\n");
13441 return CMD_WARNING;
13442 }
13443 }
718e3744 13444
4ced1a2c 13445 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13446 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13447 if (count) {
13448 if (!uj)
13449 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13450 get_afi_safi_str(afi, safi, false));
d62a17ae 13451 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13452 } else {
13453 if (uj)
13454 vty_out(vty, "{}\n");
13455 else
13456 vty_out(vty, "No functional output\n");
13457 }
718e3744 13458
d62a17ae 13459 return CMD_SUCCESS;
13460}
13461
13462static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13463 afi_t afi, safi_t safi,
9f049418 13464 enum bgp_show_type type, bool use_json)
d62a17ae 13465{
96f3485c
MK
13466 uint8_t show_flags = 0;
13467
13468 if (use_json)
13469 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13470
d62a17ae 13471 if (!peer || !peer->afc[afi][safi]) {
13472 if (use_json) {
13473 json_object *json_no = NULL;
13474 json_no = json_object_new_object();
13475 json_object_string_add(
13476 json_no, "warning",
13477 "No such neighbor or address family");
13478 vty_out(vty, "%s\n",
13479 json_object_to_json_string(json_no));
13480 json_object_free(json_no);
13481 } else
13482 vty_out(vty, "%% No such neighbor or address family\n");
13483 return CMD_WARNING;
13484 }
47fc97cc 13485
7daf25a3
TA
13486 /* labeled-unicast routes live in the unicast table */
13487 if (safi == SAFI_LABELED_UNICAST)
13488 safi = SAFI_UNICAST;
13489
96f3485c 13490 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13491}
13492
dba3c1d3
PG
13493DEFUN (show_ip_bgp_flowspec_routes_detailed,
13494 show_ip_bgp_flowspec_routes_detailed_cmd,
13495 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13496 SHOW_STR
13497 IP_STR
13498 BGP_STR
13499 BGP_INSTANCE_HELP_STR
13500 BGP_AFI_HELP_STR
13501 "SAFI Flowspec\n"
13502 "Detailed information on flowspec entries\n"
13503 JSON_STR)
13504{
13505 afi_t afi = AFI_IP;
13506 safi_t safi = SAFI_UNICAST;
13507 struct bgp *bgp = NULL;
13508 int idx = 0;
9f049418 13509 bool uj = use_json(argc, argv);
96f3485c 13510 uint8_t show_flags = 0;
9f049418 13511
96f3485c 13512 if (uj) {
9f049418 13513 argc--;
96f3485c
MK
13514 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13515 }
dba3c1d3
PG
13516
13517 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13518 &bgp, uj);
dba3c1d3
PG
13519 if (!idx)
13520 return CMD_WARNING;
13521
96f3485c
MK
13522 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13523 show_flags);
dba3c1d3
PG
13524}
13525
718e3744 13526DEFUN (show_ip_bgp_neighbor_routes,
13527 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13528 "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 13529 SHOW_STR
13530 IP_STR
13531 BGP_STR
8386ac43 13532 BGP_INSTANCE_HELP_STR
4f280b15 13533 BGP_AFI_HELP_STR
4dd6177e 13534 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13535 "Detailed information on TCP and BGP neighbor connections\n"
13536 "Neighbor to display information about\n"
13537 "Neighbor to display information about\n"
91d37724 13538 "Neighbor on BGP configured interface\n"
2525cf39 13539 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13540 "Display the dampened routes received from neighbor\n"
13541 "Display routes learned from neighbor\n"
9973d184 13542 JSON_STR)
718e3744 13543{
d62a17ae 13544 char *peerstr = NULL;
13545 struct bgp *bgp = NULL;
13546 afi_t afi = AFI_IP6;
13547 safi_t safi = SAFI_UNICAST;
13548 struct peer *peer;
13549 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13550 int idx = 0;
9f049418
DS
13551 bool uj = use_json(argc, argv);
13552
13553 if (uj)
13554 argc--;
bb46e94f 13555
d62a17ae 13556 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13557 &bgp, uj);
d62a17ae 13558 if (!idx)
13559 return CMD_WARNING;
c493f2d8 13560
d62a17ae 13561 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13562 argv_find(argv, argc, "neighbors", &idx);
13563 peerstr = argv[++idx]->arg;
8c3deaae 13564
d62a17ae 13565 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13566 if (!peer)
d62a17ae 13567 return CMD_WARNING;
bb46e94f 13568
d62a17ae 13569 if (argv_find(argv, argc, "flap-statistics", &idx))
13570 sh_type = bgp_show_type_flap_neighbor;
13571 else if (argv_find(argv, argc, "dampened-routes", &idx))
13572 sh_type = bgp_show_type_damp_neighbor;
13573 else if (argv_find(argv, argc, "routes", &idx))
13574 sh_type = bgp_show_type_neighbor;
2525cf39 13575
d62a17ae 13576 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13577}
6b0655a2 13578
734b349e 13579struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13580
d62a17ae 13581struct bgp_distance {
13582 /* Distance value for the IP source prefix. */
d7c0a89a 13583 uint8_t distance;
718e3744 13584
d62a17ae 13585 /* Name of the access-list to be matched. */
13586 char *access_list;
718e3744 13587};
13588
4f280b15
LB
13589DEFUN (show_bgp_afi_vpn_rd_route,
13590 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13591 "show bgp "BGP_AFI_CMD_STR" vpn rd ASN:NN_OR_IP-ADDRESS:NN <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
13592 SHOW_STR
13593 BGP_STR
13594 BGP_AFI_HELP_STR
13595 "Address Family modifier\n"
13596 "Display information for a route distinguisher\n"
13597 "Route Distinguisher\n"
7395a2c9
DS
13598 "Network in the BGP routing table to display\n"
13599 "Network in the BGP routing table to display\n"
13600 JSON_STR)
4f280b15 13601{
d62a17ae 13602 int ret;
13603 struct prefix_rd prd;
13604 afi_t afi = AFI_MAX;
13605 int idx = 0;
4f280b15 13606
ff6566f3
DS
13607 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13608 vty_out(vty, "%% Malformed Address Family\n");
13609 return CMD_WARNING;
13610 }
13611
d62a17ae 13612 ret = str2prefix_rd(argv[5]->arg, &prd);
13613 if (!ret) {
13614 vty_out(vty, "%% Malformed Route Distinguisher\n");
13615 return CMD_WARNING;
13616 }
ff6566f3 13617
d62a17ae 13618 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13619 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13620}
13621
d62a17ae 13622static struct bgp_distance *bgp_distance_new(void)
718e3744 13623{
d62a17ae 13624 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13625}
13626
d62a17ae 13627static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13628{
d62a17ae 13629 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13630}
13631
37a87b8f
CS
13632int bgp_distance_set(uint8_t distance, const char *ip_str,
13633 const char *access_list_str, afi_t afi, safi_t safi,
13634 char *errmsg, size_t errmsg_len)
718e3744 13635{
d62a17ae 13636 int ret;
d62a17ae 13637 struct prefix p;
9bcb3eef 13638 struct bgp_dest *dest;
d62a17ae 13639 struct bgp_distance *bdistance;
718e3744 13640
d62a17ae 13641 ret = str2prefix(ip_str, &p);
13642 if (ret == 0) {
37a87b8f 13643 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13644 return CMD_WARNING_CONFIG_FAILED;
13645 }
718e3744 13646
d62a17ae 13647 /* Get BGP distance node. */
9bcb3eef
DS
13648 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13649 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13650 if (bdistance)
9bcb3eef 13651 bgp_dest_unlock_node(dest);
ca2e160d 13652 else {
d62a17ae 13653 bdistance = bgp_distance_new();
9bcb3eef 13654 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13655 }
718e3744 13656
d62a17ae 13657 /* Set distance value. */
13658 bdistance->distance = distance;
718e3744 13659
d62a17ae 13660 /* Reset access-list configuration. */
e1b36e13 13661 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13662 if (access_list_str)
13663 bdistance->access_list =
13664 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13665
d62a17ae 13666 return CMD_SUCCESS;
718e3744 13667}
13668
37a87b8f
CS
13669int bgp_distance_unset(uint8_t distance, const char *ip_str,
13670 const char *access_list_str, afi_t afi, safi_t safi,
13671 char *errmsg, size_t errmsg_len)
718e3744 13672{
d62a17ae 13673 int ret;
d62a17ae 13674 struct prefix p;
9bcb3eef 13675 struct bgp_dest *dest;
d62a17ae 13676 struct bgp_distance *bdistance;
718e3744 13677
d62a17ae 13678 ret = str2prefix(ip_str, &p);
13679 if (ret == 0) {
37a87b8f 13680 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13681 return CMD_WARNING_CONFIG_FAILED;
13682 }
718e3744 13683
9bcb3eef
DS
13684 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13685 if (!dest) {
37a87b8f 13686 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13687 return CMD_WARNING_CONFIG_FAILED;
13688 }
718e3744 13689
9bcb3eef 13690 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13691
d62a17ae 13692 if (bdistance->distance != distance) {
37a87b8f
CS
13693 snprintf(errmsg, errmsg_len,
13694 "Distance does not match configured\n");
d62a17ae 13695 return CMD_WARNING_CONFIG_FAILED;
13696 }
718e3744 13697
0a22ddfb 13698 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13699 bgp_distance_free(bdistance);
718e3744 13700
9bcb3eef
DS
13701 bgp_dest_set_bgp_path_info(dest, NULL);
13702 bgp_dest_unlock_node(dest);
13703 bgp_dest_unlock_node(dest);
718e3744 13704
d62a17ae 13705 return CMD_SUCCESS;
718e3744 13706}
13707
718e3744 13708/* Apply BGP information to distance method. */
b8685f9b 13709uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13710 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13711{
9bcb3eef 13712 struct bgp_dest *dest;
801bb996 13713 struct prefix q = {0};
d62a17ae 13714 struct peer *peer;
13715 struct bgp_distance *bdistance;
13716 struct access_list *alist;
13717 struct bgp_static *bgp_static;
13718
13719 if (!bgp)
13720 return 0;
13721
40381db7 13722 peer = pinfo->peer;
d62a17ae 13723
7b7d48e5
DS
13724 if (pinfo->attr->distance)
13725 return pinfo->attr->distance;
13726
801bb996
CS
13727 /* Check source address.
13728 * Note: for aggregate route, peer can have unspec af type.
13729 */
13730 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13731 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13732 return 0;
13733
9bcb3eef
DS
13734 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13735 if (dest) {
13736 bdistance = bgp_dest_get_bgp_distance_info(dest);
13737 bgp_dest_unlock_node(dest);
d62a17ae 13738
13739 if (bdistance->access_list) {
13740 alist = access_list_lookup(afi, bdistance->access_list);
13741 if (alist
13742 && access_list_apply(alist, p) == FILTER_PERMIT)
13743 return bdistance->distance;
13744 } else
13745 return bdistance->distance;
718e3744 13746 }
718e3744 13747
d62a17ae 13748 /* Backdoor check. */
9bcb3eef
DS
13749 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13750 if (dest) {
13751 bgp_static = bgp_dest_get_bgp_static_info(dest);
13752 bgp_dest_unlock_node(dest);
718e3744 13753
d62a17ae 13754 if (bgp_static->backdoor) {
13755 if (bgp->distance_local[afi][safi])
13756 return bgp->distance_local[afi][safi];
13757 else
13758 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13759 }
718e3744 13760 }
718e3744 13761
d62a17ae 13762 if (peer->sort == BGP_PEER_EBGP) {
13763 if (bgp->distance_ebgp[afi][safi])
13764 return bgp->distance_ebgp[afi][safi];
13765 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 13766 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 13767 if (bgp->distance_ibgp[afi][safi])
13768 return bgp->distance_ibgp[afi][safi];
13769 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
13770 } else {
13771 if (bgp->distance_local[afi][safi])
13772 return bgp->distance_local[afi][safi];
13773 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 13774 }
718e3744 13775}
13776
a612fb77
DA
13777/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13778 * we should tell ZEBRA update the routes for a specific
13779 * AFI/SAFI to reflect changes in RIB.
13780 */
37a87b8f
CS
13781void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13782 safi_t update_safi)
a612fb77
DA
13783{
13784 afi_t afi;
13785 safi_t safi;
13786
13787 FOREACH_AFI_SAFI (afi, safi) {
13788 if (!bgp_fibupd_safi(safi))
13789 continue;
13790
8b54bc30
DA
13791 if (afi != update_afi && safi != update_safi)
13792 continue;
13793
13794 if (BGP_DEBUG(zebra, ZEBRA))
13795 zlog_debug(
13796 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13797 __func__, afi, safi);
13798 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13799 }
13800}
13801
37a87b8f
CS
13802DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13803 "distance bgp (1-255) (1-255) (1-255)",
13804 "Define an administrative distance\n"
13805 "BGP distance\n"
13806 "Distance for routes external to the AS\n"
13807 "Distance for routes internal to the AS\n"
13808 "Distance for local routes\n")
718e3744 13809{
d62a17ae 13810 int idx_number = 2;
13811 int idx_number_2 = 3;
13812 int idx_number_3 = 4;
13813 afi_t afi;
13814 safi_t safi;
37a87b8f 13815 char xpath[XPATH_MAXLEN];
718e3744 13816
d62a17ae 13817 afi = bgp_node_afi(vty);
13818 safi = bgp_node_safi(vty);
718e3744 13819
37a87b8f
CS
13820 snprintf(
13821 xpath, sizeof(xpath),
13822 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13823 yang_afi_safi_value2identity(afi, safi),
13824 bgp_afi_safi_get_container_str(afi, safi));
13825 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13826 snprintf(
13827 xpath, sizeof(xpath),
13828 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13829 yang_afi_safi_value2identity(afi, safi),
13830 bgp_afi_safi_get_container_str(afi, safi));
13831 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13832 argv[idx_number_2]->arg);
13833 snprintf(
13834 xpath, sizeof(xpath),
13835 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13836 yang_afi_safi_value2identity(afi, safi),
13837 bgp_afi_safi_get_container_str(afi, safi));
13838
13839 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13840 argv[idx_number_3]->arg);
13841
13842 return nb_cli_apply_changes(vty, NULL);
13843}
13844
13845DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13846 "no distance bgp [(1-255) (1-255) (1-255)]",
13847 NO_STR
13848 "Define an administrative distance\n"
13849 "BGP distance\n"
13850 "Distance for routes external to the AS\n"
13851 "Distance for routes internal to the AS\n"
13852 "Distance for local routes\n")
13853{
13854 afi_t afi;
13855 safi_t safi;
13856 char xpath[XPATH_MAXLEN];
13857
13858 afi = bgp_node_afi(vty);
13859 safi = bgp_node_safi(vty);
13860
13861 snprintf(
13862 xpath, sizeof(xpath),
13863 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13864 yang_afi_safi_value2identity(afi, safi),
13865 bgp_afi_safi_get_container_str(afi, safi));
13866 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13867 snprintf(
13868 xpath, sizeof(xpath),
13869 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13870 yang_afi_safi_value2identity(afi, safi),
13871 bgp_afi_safi_get_container_str(afi, safi));
13872 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13873 snprintf(
13874 xpath, sizeof(xpath),
13875 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13876 yang_afi_safi_value2identity(afi, safi),
13877 bgp_afi_safi_get_container_str(afi, safi));
13878
13879 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13880
13881 return nb_cli_apply_changes(vty, NULL);
718e3744 13882}
13883
37a87b8f
CS
13884void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13885 struct lyd_node *dnode,
13886 bool show_defaults)
718e3744 13887{
37a87b8f
CS
13888 uint8_t distance_ebgp, distance_ibgp, distance_local;
13889
13890 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13891 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13892 distance_local = yang_dnode_get_uint8(dnode, "./local");
13893
13894 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13895 distance_local);
13896}
13897
8cc7152a
CS
13898DEFPY_YANG(bgp_distance_source,
13899 bgp_distance_source_cmd,
13900 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
13901 NO_STR
13902 "Define an administrative distance\n"
8cc7152a 13903 "Distance value\n"
e12affc1
SW
13904 "IPv4 source prefix\n"
13905 "IPv6 source prefix\n"
37a87b8f 13906 "Access list name\n")
718e3744 13907{
37a87b8f
CS
13908 afi_t afi;
13909 safi_t safi;
13910 char xpath[XPATH_MAXLEN];
13911
13912 afi = bgp_node_afi(vty);
13913 safi = bgp_node_safi(vty);
13914
8cc7152a
CS
13915 if (!no) {
13916 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
13917 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
13918 distance_str);
13919 if (acl)
13920 nb_cli_enqueue_change(vty,
13921 "./access-list-policy-export",
13922 NB_OP_CREATE, acl);
13923 else
13924 nb_cli_enqueue_change(vty,
13925 "./access-list-policy-export",
13926 NB_OP_DESTROY, NULL);
13927 } else {
13928 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
13929 }
37a87b8f
CS
13930
13931 snprintf(
13932 xpath, sizeof(xpath),
13933 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
13934 yang_afi_safi_value2identity(afi, safi),
8cc7152a 13935 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
13936
13937 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
13938}
13939
37a87b8f
CS
13940void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
13941 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
13942{
13943 vty_out(vty, " distance %d %s %s\n",
13944 yang_dnode_get_uint8(dnode, "./distance"),
13945 yang_dnode_get_string(dnode, "./prefix"),
13946 (yang_dnode_exists(dnode, "./access-list-policy-export"))
13947 ? yang_dnode_get_string(dnode,
13948 "./access-list-policy-export")
13949 : "");
13950}
13951
7c98d487
DA
13952DEFPY_YANG(
13953 bgp_dampening, bgp_dampening_cmd,
13954 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
13955 NO_STR
13956 "BGP Specific commands\n"
13957 "Enable route-flap dampening\n"
13958 "Half-life time for the penalty\n"
13959 "Value to start reusing a route\n"
13960 "Value to start suppressing a route\n"
13961 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
13962{
13963 afi_t afi;
13964 safi_t safi;
13965 char xpath[XPATH_MAXLEN];
718e3744 13966
37a87b8f
CS
13967 afi = bgp_node_afi(vty);
13968 safi = bgp_node_safi(vty);
13969
d9ce5113
CS
13970 if (!no) {
13971 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
13972 if (argc == 6) {
13973 nb_cli_enqueue_change(vty, "./reach-decay",
13974 NB_OP_MODIFY, halflife_str);
13975 nb_cli_enqueue_change(vty, "./reuse-above",
13976 NB_OP_MODIFY, reuse_str);
13977 nb_cli_enqueue_change(vty, "./suppress-above",
13978 NB_OP_MODIFY, suppress_str);
13979 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 13980 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
13981 } if (argc == 3) {
13982 nb_cli_enqueue_change(vty, "./reach-decay",
13983 NB_OP_MODIFY, halflife_str);
13984 }
13985 } else {
13986 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
13987 }
7ebe9748 13988
37a87b8f
CS
13989 snprintf(
13990 xpath, sizeof(xpath),
13991 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
13992 yang_afi_safi_value2identity(afi, safi),
13993 bgp_afi_safi_get_container_str(afi, safi));
13994
13995 return nb_cli_apply_changes(vty, xpath);
718e3744 13996}
13997
37a87b8f
CS
13998void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
13999 struct lyd_node *dnode,
14000 bool show_defaults)
718e3744 14001{
37a87b8f
CS
14002 if (!yang_dnode_get_bool(dnode, "./enable"))
14003 return;
14004
14005 int half = DEFAULT_HALF_LIFE * 60;
14006 int reuse = DEFAULT_REUSE;
14007 int suppress = DEFAULT_SUPPRESS;
14008 int max;
14009
14010 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14011 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14012 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14013 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14014
14015 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14016 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14017 vty_out(vty, " bgp dampening\n");
14018 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14019 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14020 vty_out(vty, " bgp dampening %u\n", half);
14021 else
14022 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14023 suppress, max);
718e3744 14024}
14025
718e3744 14026/* Display specified route of BGP table. */
d62a17ae 14027static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14028 const char *ip_str, afi_t afi, safi_t safi,
14029 struct prefix_rd *prd, int prefix_check)
14030{
14031 int ret;
14032 struct prefix match;
9bcb3eef
DS
14033 struct bgp_dest *dest;
14034 struct bgp_dest *rm;
40381db7
DS
14035 struct bgp_path_info *pi;
14036 struct bgp_path_info *pi_temp;
d62a17ae 14037 struct bgp *bgp;
14038 struct bgp_table *table;
14039
14040 /* BGP structure lookup. */
14041 if (view_name) {
14042 bgp = bgp_lookup_by_name(view_name);
14043 if (bgp == NULL) {
14044 vty_out(vty, "%% Can't find BGP instance %s\n",
14045 view_name);
14046 return CMD_WARNING;
14047 }
14048 } else {
14049 bgp = bgp_get_default();
14050 if (bgp == NULL) {
14051 vty_out(vty, "%% No BGP process is configured\n");
14052 return CMD_WARNING;
14053 }
718e3744 14054 }
718e3744 14055
d62a17ae 14056 /* Check IP address argument. */
14057 ret = str2prefix(ip_str, &match);
14058 if (!ret) {
14059 vty_out(vty, "%% address is malformed\n");
14060 return CMD_WARNING;
14061 }
718e3744 14062
d62a17ae 14063 match.family = afi2family(afi);
14064
14065 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14066 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14067 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14068 dest = bgp_route_next(dest)) {
14069 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14070
9bcb3eef 14071 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14072 continue;
9bcb3eef 14073 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14074 if (!table)
ea47320b
DL
14075 continue;
14076 if ((rm = bgp_node_match(table, &match)) == NULL)
14077 continue;
d62a17ae 14078
9bcb3eef 14079 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14080
ea47320b 14081 if (!prefix_check
b54892e0 14082 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14083 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14084 while (pi) {
14085 if (pi->extra && pi->extra->damp_info) {
14086 pi_temp = pi->next;
ea47320b 14087 bgp_damp_info_free(
40381db7 14088 pi->extra->damp_info,
a935f597 14089 1, afi, safi);
40381db7 14090 pi = pi_temp;
ea47320b 14091 } else
40381db7 14092 pi = pi->next;
d62a17ae 14093 }
ea47320b
DL
14094 }
14095
9bcb3eef 14096 bgp_dest_unlock_node(rm);
d62a17ae 14097 }
14098 } else {
9bcb3eef 14099 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14100 != NULL) {
9bcb3eef 14101 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14102
d62a17ae 14103 if (!prefix_check
9bcb3eef
DS
14104 || dest_p->prefixlen == match.prefixlen) {
14105 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14106 while (pi) {
14107 if (pi->extra && pi->extra->damp_info) {
14108 pi_temp = pi->next;
d62a17ae 14109 bgp_damp_info_free(
40381db7 14110 pi->extra->damp_info,
a935f597 14111 1, afi, safi);
40381db7 14112 pi = pi_temp;
d62a17ae 14113 } else
40381db7 14114 pi = pi->next;
d62a17ae 14115 }
14116 }
14117
9bcb3eef 14118 bgp_dest_unlock_node(dest);
d62a17ae 14119 }
14120 }
718e3744 14121
d62a17ae 14122 return CMD_SUCCESS;
718e3744 14123}
14124
14125DEFUN (clear_ip_bgp_dampening,
14126 clear_ip_bgp_dampening_cmd,
14127 "clear ip bgp dampening",
14128 CLEAR_STR
14129 IP_STR
14130 BGP_STR
14131 "Clear route flap dampening information\n")
14132{
a935f597 14133 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14134 return CMD_SUCCESS;
718e3744 14135}
14136
14137DEFUN (clear_ip_bgp_dampening_prefix,
14138 clear_ip_bgp_dampening_prefix_cmd,
14139 "clear ip bgp dampening A.B.C.D/M",
14140 CLEAR_STR
14141 IP_STR
14142 BGP_STR
14143 "Clear route flap dampening information\n"
0c7b1b01 14144 "IPv4 prefix\n")
718e3744 14145{
d62a17ae 14146 int idx_ipv4_prefixlen = 4;
14147 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14148 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14149}
14150
14151DEFUN (clear_ip_bgp_dampening_address,
14152 clear_ip_bgp_dampening_address_cmd,
14153 "clear ip bgp dampening A.B.C.D",
14154 CLEAR_STR
14155 IP_STR
14156 BGP_STR
14157 "Clear route flap dampening information\n"
14158 "Network to clear damping information\n")
14159{
d62a17ae 14160 int idx_ipv4 = 4;
14161 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14162 SAFI_UNICAST, NULL, 0);
718e3744 14163}
14164
14165DEFUN (clear_ip_bgp_dampening_address_mask,
14166 clear_ip_bgp_dampening_address_mask_cmd,
14167 "clear ip bgp dampening A.B.C.D A.B.C.D",
14168 CLEAR_STR
14169 IP_STR
14170 BGP_STR
14171 "Clear route flap dampening information\n"
14172 "Network to clear damping information\n"
14173 "Network mask\n")
14174{
d62a17ae 14175 int idx_ipv4 = 4;
14176 int idx_ipv4_2 = 5;
14177 int ret;
14178 char prefix_str[BUFSIZ];
718e3744 14179
d62a17ae 14180 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14181 prefix_str);
14182 if (!ret) {
14183 vty_out(vty, "%% Inconsistent address and mask\n");
14184 return CMD_WARNING;
14185 }
718e3744 14186
d62a17ae 14187 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14188 NULL, 0);
718e3744 14189}
6b0655a2 14190
e3b78da8 14191static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14192{
14193 struct vty *vty = arg;
e3b78da8 14194 struct peer *peer = bucket->data;
825d9834
DS
14195 char buf[SU_ADDRSTRLEN];
14196
14197 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14198 sockunion2str(&peer->su, buf, sizeof(buf)));
14199}
14200
2a0e69ae
DS
14201DEFUN (show_bgp_listeners,
14202 show_bgp_listeners_cmd,
14203 "show bgp listeners",
14204 SHOW_STR
14205 BGP_STR
14206 "Display Listen Sockets and who created them\n")
14207{
14208 bgp_dump_listener_info(vty);
14209
14210 return CMD_SUCCESS;
14211}
14212
825d9834
DS
14213DEFUN (show_bgp_peerhash,
14214 show_bgp_peerhash_cmd,
14215 "show bgp peerhash",
14216 SHOW_STR
14217 BGP_STR
14218 "Display information about the BGP peerhash\n")
14219{
14220 struct list *instances = bm->bgp;
14221 struct listnode *node;
14222 struct bgp *bgp;
14223
14224 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14225 vty_out(vty, "BGP: %s\n", bgp->name);
14226 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14227 vty);
14228 }
14229
14230 return CMD_SUCCESS;
14231}
14232
587ff0fd 14233/* also used for encap safi */
2b791107
DL
14234static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14235 afi_t afi, safi_t safi)
d62a17ae 14236{
9bcb3eef
DS
14237 struct bgp_dest *pdest;
14238 struct bgp_dest *dest;
d62a17ae 14239 struct bgp_table *table;
b54892e0
DS
14240 const struct prefix *p;
14241 const struct prefix_rd *prd;
d62a17ae 14242 struct bgp_static *bgp_static;
14243 mpls_label_t label;
d62a17ae 14244 char rdbuf[RD_ADDRSTRLEN];
14245
14246 /* Network configuration. */
9bcb3eef
DS
14247 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14248 pdest = bgp_route_next(pdest)) {
14249 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14250 if (!table)
ea47320b 14251 continue;
d62a17ae 14252
9bcb3eef
DS
14253 for (dest = bgp_table_top(table); dest;
14254 dest = bgp_route_next(dest)) {
14255 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14256 if (bgp_static == NULL)
ea47320b 14257 continue;
d62a17ae 14258
9bcb3eef
DS
14259 p = bgp_dest_get_prefix(dest);
14260 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14261 pdest);
d62a17ae 14262
ea47320b 14263 /* "network" configuration display. */
06b9f471 14264 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14265 label = decode_label(&bgp_static->label);
14266
8228a9a7 14267 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14268 if (safi == SAFI_MPLS_VPN)
14269 vty_out(vty, " label %u", label);
14270
14271 if (bgp_static->rmap.name)
14272 vty_out(vty, " route-map %s",
14273 bgp_static->rmap.name);
e2a86ad9
DS
14274
14275 if (bgp_static->backdoor)
14276 vty_out(vty, " backdoor");
14277
ea47320b
DL
14278 vty_out(vty, "\n");
14279 }
14280 }
d62a17ae 14281}
14282
2b791107
DL
14283static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14284 afi_t afi, safi_t safi)
d62a17ae 14285{
9bcb3eef
DS
14286 struct bgp_dest *pdest;
14287 struct bgp_dest *dest;
d62a17ae 14288 struct bgp_table *table;
b54892e0
DS
14289 const struct prefix *p;
14290 const struct prefix_rd *prd;
d62a17ae 14291 struct bgp_static *bgp_static;
ff44f570 14292 char buf[PREFIX_STRLEN * 2];
d62a17ae 14293 char buf2[SU_ADDRSTRLEN];
14294 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14295 char esi_buf[ESI_BYTES];
d62a17ae 14296
14297 /* Network configuration. */
9bcb3eef
DS
14298 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14299 pdest = bgp_route_next(pdest)) {
14300 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14301 if (!table)
ea47320b 14302 continue;
d62a17ae 14303
9bcb3eef
DS
14304 for (dest = bgp_table_top(table); dest;
14305 dest = bgp_route_next(dest)) {
14306 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14307 if (bgp_static == NULL)
ea47320b 14308 continue;
d62a17ae 14309
ea47320b 14310 char *macrouter = NULL;
d62a17ae 14311
ea47320b
DL
14312 if (bgp_static->router_mac)
14313 macrouter = prefix_mac2str(
14314 bgp_static->router_mac, NULL, 0);
14315 if (bgp_static->eth_s_id)
0a50c248
AK
14316 esi_to_str(bgp_static->eth_s_id,
14317 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14318 p = bgp_dest_get_prefix(dest);
14319 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14320
ea47320b 14321 /* "network" configuration display. */
06b9f471 14322 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14323 if (p->u.prefix_evpn.route_type == 5) {
14324 char local_buf[PREFIX_STRLEN];
3714a385 14325 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14326 struct prefix_evpn *)p)
14327 ? AF_INET
14328 : AF_INET6;
3714a385 14329 inet_ntop(family,
14330 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14331 local_buf, PREFIX_STRLEN);
772270f3
QY
14332 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14333 p->u.prefix_evpn.prefix_addr
14334 .ip_prefix_length);
197cb530
PG
14335 } else {
14336 prefix2str(p, buf, sizeof(buf));
14337 }
ea47320b 14338
a4d82a8a
PZ
14339 if (bgp_static->gatewayIp.family == AF_INET
14340 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14341 inet_ntop(bgp_static->gatewayIp.family,
14342 &bgp_static->gatewayIp.u.prefix, buf2,
14343 sizeof(buf2));
ea47320b 14344 vty_out(vty,
7bcc8dac 14345 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14346 buf, rdbuf,
14347 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14348 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14349 macrouter);
14350
0a22ddfb 14351 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14352 }
14353 }
3da6fcd5
PG
14354}
14355
718e3744 14356/* Configuration of static route announcement and aggregate
14357 information. */
2b791107
DL
14358void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14359 safi_t safi)
d62a17ae 14360{
9bcb3eef 14361 struct bgp_dest *dest;
b54892e0 14362 const struct prefix *p;
d62a17ae 14363 struct bgp_static *bgp_static;
14364 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14365
2b791107
DL
14366 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14367 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14368 return;
14369 }
d62a17ae 14370
2b791107
DL
14371 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14372 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14373 return;
14374 }
d62a17ae 14375
14376 /* Network configuration. */
9bcb3eef
DS
14377 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14378 dest = bgp_route_next(dest)) {
14379 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14380 if (bgp_static == NULL)
ea47320b 14381 continue;
d62a17ae 14382
9bcb3eef 14383 p = bgp_dest_get_prefix(dest);
d62a17ae 14384
8228a9a7 14385 vty_out(vty, " network %pFX", p);
d62a17ae 14386
ea47320b
DL
14387 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14388 vty_out(vty, " label-index %u",
14389 bgp_static->label_index);
d62a17ae 14390
ea47320b
DL
14391 if (bgp_static->rmap.name)
14392 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14393
14394 if (bgp_static->backdoor)
14395 vty_out(vty, " backdoor");
718e3744 14396
ea47320b
DL
14397 vty_out(vty, "\n");
14398 }
14399
d62a17ae 14400 /* Aggregate-address configuration. */
9bcb3eef
DS
14401 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14402 dest = bgp_route_next(dest)) {
14403 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14404 if (bgp_aggregate == NULL)
ea47320b 14405 continue;
d62a17ae 14406
9bcb3eef 14407 p = bgp_dest_get_prefix(dest);
d62a17ae 14408
8228a9a7 14409 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14410
ea47320b
DL
14411 if (bgp_aggregate->as_set)
14412 vty_out(vty, " as-set");
d62a17ae 14413
ea47320b
DL
14414 if (bgp_aggregate->summary_only)
14415 vty_out(vty, " summary-only");
718e3744 14416
20894f50
DA
14417 if (bgp_aggregate->rmap.name)
14418 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14419
229757f1
DA
14420 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14421 vty_out(vty, " origin %s",
14422 bgp_origin2str(bgp_aggregate->origin));
14423
6aabb15d
RZ
14424 if (bgp_aggregate->match_med)
14425 vty_out(vty, " matching-MED-only");
14426
365ab2e7
RZ
14427 if (bgp_aggregate->suppress_map_name)
14428 vty_out(vty, " suppress-map %s",
14429 bgp_aggregate->suppress_map_name);
14430
ea47320b
DL
14431 vty_out(vty, "\n");
14432 }
d62a17ae 14433}
734b349e 14434
2b791107 14435void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14436 safi_t safi)
d62a17ae 14437{
9bcb3eef 14438 struct bgp_dest *dest;
d62a17ae 14439 struct bgp_distance *bdistance;
14440
14441 /* Distance configuration. */
14442 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14443 && bgp->distance_local[afi][safi]
14444 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14445 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14446 || bgp->distance_local[afi][safi]
14447 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14448 vty_out(vty, " distance bgp %d %d %d\n",
14449 bgp->distance_ebgp[afi][safi],
14450 bgp->distance_ibgp[afi][safi],
14451 bgp->distance_local[afi][safi]);
14452 }
734b349e 14453
9bcb3eef
DS
14454 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14455 dest = bgp_route_next(dest)) {
14456 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14457 if (bdistance != NULL)
56ca3b5b 14458 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14459 bdistance->distance, dest,
d62a17ae 14460 bdistance->access_list ? bdistance->access_list
14461 : "");
ca2e160d 14462 }
718e3744 14463}
14464
14465/* Allocate routing table structure and install commands. */
d62a17ae 14466void bgp_route_init(void)
14467{
14468 afi_t afi;
14469 safi_t safi;
14470
14471 /* Init BGP distance table. */
05c7a1cc 14472 FOREACH_AFI_SAFI (afi, safi)
960035b2 14473 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14474
14475 /* IPv4 BGP commands. */
14476 install_element(BGP_NODE, &bgp_table_map_cmd);
14477 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14478 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14479
554b3b10 14480 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14481
14482 /* IPv4 unicast configuration. */
14483 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14484 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14485 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14486
554b3b10 14487 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14488
14489 /* IPv4 multicast configuration. */
14490 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14491 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14492 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14493 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14494
14495 /* IPv4 labeled-unicast configuration. */
fb985e0c 14496 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14497 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14498
d62a17ae 14499 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14500 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14501 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14502 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14503 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14504 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14505 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14506 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14507
14508 install_element(VIEW_NODE,
14509 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14510 install_element(VIEW_NODE,
14511 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14512 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14513 install_element(VIEW_NODE,
14514 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14515#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14516 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14517#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14518 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14519 install_element(VIEW_NODE,
44c69747 14520 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14521
d62a17ae 14522 /* BGP dampening clear commands */
14523 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14524 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14525
d62a17ae 14526 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14527 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14528
14529 /* prefix count */
14530 install_element(ENABLE_NODE,
14531 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14532#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14533 install_element(ENABLE_NODE,
14534 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14535#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14536
d62a17ae 14537 /* New config IPv6 BGP commands. */
14538 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14539 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14540 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14541
554b3b10 14542 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14543
14544 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14545
fb985e0c
DA
14546 /* IPv6 labeled unicast address family. */
14547 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14548 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14549
d62a17ae 14550 install_element(BGP_NODE, &bgp_distance_cmd);
14551 install_element(BGP_NODE, &no_bgp_distance_cmd);
14552 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14553 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14554 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14555 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14556 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14557 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14558 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14559 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14560 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14561 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14562 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14563 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14564 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14565
ef5f4b23 14566 /* BGP dampening */
d9ce5113
CS
14567 install_element(BGP_NODE, &bgp_dampening_cmd);
14568 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14569 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14570 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14571 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14572 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14573 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14574
14575 /* Large Communities */
14576 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14577 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14578
14579 /* show bgp ipv4 flowspec detailed */
14580 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14581
2a0e69ae 14582 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14583 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14584}
14585
14586void bgp_route_finish(void)
14587{
14588 afi_t afi;
14589 safi_t safi;
14590
05c7a1cc
QY
14591 FOREACH_AFI_SAFI (afi, safi) {
14592 bgp_table_unlock(bgp_distance_table[afi][safi]);
14593 bgp_distance_table[afi][safi] = NULL;
14594 }
228da428 14595}