]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Somewhat optimize string returns
[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[];
36235319 99const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
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,
d62a17ae 2758 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2759 bgp_unregister_for_label(dest);
70e98a7f 2760 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2761 &dest->local_label);
2762 bgp_set_valid_label(&dest->local_label);
d62a17ae 2763 } else
9bcb3eef
DS
2764 bgp_register_for_label(dest,
2765 new_select);
d62a17ae 2766 }
9bcb3eef 2767 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2768 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2769 bgp_unregister_for_label(dest);
318cac96 2770 }
9bcb3eef
DS
2771 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2772 bgp_unregister_for_label(dest);
d62a17ae 2773 }
cd1964ff 2774
b54892e0 2775 if (debug)
ddb5b488 2776 zlog_debug(
56ca3b5b 2777 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2778 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2779 old_select, new_select);
ddb5b488 2780
d62a17ae 2781 /* If best route remains the same and this is not due to user-initiated
2782 * clear, see exactly what needs to be done.
2783 */
d62a17ae 2784 if (old_select && old_select == new_select
9bcb3eef 2785 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2786 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2787 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2788 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2789#ifdef ENABLE_BGP_VNC
d62a17ae 2790 vnc_import_bgp_add_route(bgp, p, old_select);
2791 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2792#endif
bb744275 2793 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2794 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2795
2796 if (new_select->type == ZEBRA_ROUTE_BGP
2797 && (new_select->sub_type == BGP_ROUTE_NORMAL
2798 || new_select->sub_type
2799 == BGP_ROUTE_IMPORTED))
2800
9bcb3eef 2801 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2802 bgp, afi, safi);
2803 }
d62a17ae 2804 }
d62a17ae 2805
2806 /* If there is a change of interest to peers, reannounce the
2807 * route. */
1defdda8 2808 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2809 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2810 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2811 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2812
2813 /* unicast routes must also be annouced to
2814 * labeled-unicast update-groups */
2815 if (safi == SAFI_UNICAST)
2816 group_announce_route(bgp, afi,
9bcb3eef 2817 SAFI_LABELED_UNICAST, dest,
d62a17ae 2818 new_select);
2819
1defdda8 2820 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2821 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2822 }
fee0f4c6 2823
3b0c17e1 2824 /* advertise/withdraw type-5 routes */
2825 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2826 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2827 bgp_process_evpn_route_injection(
9bcb3eef 2828 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2829
b1875e65 2830 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2831 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2832 bgp_zebra_clear_route_change_flags(dest);
2833 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2834 return;
d62a17ae 2835 }
8ad7271d 2836
d62a17ae 2837 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2838 */
9bcb3eef 2839 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2840
2841 /* bestpath has changed; bump version */
2842 if (old_select || new_select) {
9bcb3eef 2843 bgp_bump_version(dest);
d62a17ae 2844
2845 if (!bgp->t_rmap_def_originate_eval) {
2846 bgp_lock(bgp);
2847 thread_add_timer(
2848 bm->master,
2849 update_group_refresh_default_originate_route_map,
2850 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2851 &bgp->t_rmap_def_originate_eval);
2852 }
2853 }
3f9c7369 2854
d62a17ae 2855 if (old_select)
9bcb3eef 2856 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2857 if (new_select) {
ddb5b488
PZ
2858 if (debug)
2859 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2860 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2861 bgp_path_info_unset_flag(dest, new_select,
2862 BGP_PATH_ATTR_CHANGED);
1defdda8 2863 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2864 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2865 }
338b3424 2866
49e5a4a0 2867#ifdef ENABLE_BGP_VNC
d62a17ae 2868 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2869 if (old_select != new_select) {
2870 if (old_select) {
2871 vnc_import_bgp_exterior_del_route(bgp, p,
2872 old_select);
2873 vnc_import_bgp_del_route(bgp, p, old_select);
2874 }
2875 if (new_select) {
2876 vnc_import_bgp_exterior_add_route(bgp, p,
2877 new_select);
2878 vnc_import_bgp_add_route(bgp, p, new_select);
2879 }
2880 }
2881 }
65efcfce
LB
2882#endif
2883
9bcb3eef 2884 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2885
2886 /* unicast routes must also be annouced to labeled-unicast update-groups
2887 */
2888 if (safi == SAFI_UNICAST)
9bcb3eef 2889 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2890 new_select);
2891
2892 /* FIB update. */
2893 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2894 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2895 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2896 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2897 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2898 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2899
2900 /* if this is an evpn imported type-5 prefix,
2901 * we need to withdraw the route first to clear
2902 * the nh neigh and the RMAC entry.
2903 */
2904 if (old_select &&
2905 is_route_parent_evpn(old_select))
2906 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2907
9bcb3eef 2908 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2909 } else {
d62a17ae 2910 /* Withdraw the route from the kernel. */
2911 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2912 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2913 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2914 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2915
568e10ca 2916 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2917 }
718e3744 2918 }
3064bf43 2919
9bcb3eef 2920 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2921 old_select);
5424b7ba 2922
d62a17ae 2923 /* Clear any route change flags. */
9bcb3eef 2924 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2925
18ee8310 2926 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2927 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2928 bgp_path_info_reap(dest, old_select);
d62a17ae 2929
9bcb3eef 2930 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2931 return;
718e3744 2932}
2933
f009ff26 2934/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2935int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2936{
9bcb3eef 2937 struct bgp_dest *dest;
f009ff26 2938 int cnt = 0;
2939 struct afi_safi_info *thread_info;
f009ff26 2940
56c226e7
DS
2941 if (bgp->gr_info[afi][safi].t_route_select) {
2942 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2943
2944 thread_info = THREAD_ARG(t);
2945 XFREE(MTYPE_TMP, thread_info);
f009ff26 2946 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2947 }
f009ff26 2948
2949 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2950 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2951 get_afi_safi_str(afi, safi, false),
26742171 2952 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2953 }
2954
2955 /* Process the route list */
6338d242
DS
2956 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2957 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2958 dest = bgp_route_next(dest)) {
2959 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2960 continue;
2961
2962 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2963 bgp->gr_info[afi][safi].gr_deferred--;
2964 bgp_process_main_one(bgp, dest, afi, safi);
2965 cnt++;
2966 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2967 bgp_dest_unlock_node(dest);
2968 break;
f009ff26 2969 }
f009ff26 2970 }
2971
9e3b51a7 2972 /* Send EOR message when all routes are processed */
6338d242 2973 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2974 bgp_send_delayed_eor(bgp);
8c48b3b6 2975 /* Send route processing complete message to RIB */
2976 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2977 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2978 return 0;
9e3b51a7 2979 }
f009ff26 2980
2981 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2982
2983 thread_info->afi = afi;
2984 thread_info->safi = safi;
2985 thread_info->bgp = bgp;
2986
2987 /* If there are more routes to be processed, start the
2988 * selection timer
2989 */
2990 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2991 BGP_ROUTE_SELECT_DELAY,
2992 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2993 return 0;
2994}
2995
aac24838 2996static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2997{
aac24838
JB
2998 struct bgp_process_queue *pqnode = data;
2999 struct bgp *bgp = pqnode->bgp;
d62a17ae 3000 struct bgp_table *table;
9bcb3eef 3001 struct bgp_dest *dest;
aac24838
JB
3002
3003 /* eoiu marker */
3004 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3005 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3006 /* should always have dedicated wq call */
3007 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3008 return WQ_SUCCESS;
3009 }
3010
ac021f40 3011 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3012 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3013 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3014 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3015 table = bgp_dest_table(dest);
3016 /* note, new DESTs may be added as part of processing */
3017 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3018
9bcb3eef 3019 bgp_dest_unlock_node(dest);
d62a17ae 3020 bgp_table_unlock(table);
3021 }
aac24838
JB
3022
3023 return WQ_SUCCESS;
3024}
3025
3026static void bgp_processq_del(struct work_queue *wq, void *data)
3027{
3028 struct bgp_process_queue *pqnode = data;
3029
3030 bgp_unlock(pqnode->bgp);
3031
3032 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3033}
3034
b6c386bb 3035void bgp_process_queue_init(struct bgp *bgp)
200df115 3036{
b6c386bb
DS
3037 if (!bgp->process_queue) {
3038 char name[BUFSIZ];
3039
3040 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3041 bgp->process_queue = work_queue_new(bm->master, name);
3042 }
3043
3044 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3045 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3046 bgp->process_queue->spec.max_retries = 0;
3047 bgp->process_queue->spec.hold = 50;
d62a17ae 3048 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3049 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3050}
3051
cfe8d15a 3052static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3053{
3054 struct bgp_process_queue *pqnode;
3055
a4d82a8a
PZ
3056 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3057 sizeof(struct bgp_process_queue));
aac24838
JB
3058
3059 /* unlocked in bgp_processq_del */
3060 pqnode->bgp = bgp_lock(bgp);
3061 STAILQ_INIT(&pqnode->pqueue);
3062
aac24838
JB
3063 return pqnode;
3064}
3065
9bcb3eef 3066void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3067{
aac24838 3068#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3069 struct work_queue *wq = bgp->process_queue;
d62a17ae 3070 struct bgp_process_queue *pqnode;
cfe8d15a 3071 int pqnode_reuse = 0;
495f0b13 3072
d62a17ae 3073 /* already scheduled for processing? */
9bcb3eef 3074 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3075 return;
2e02b9b2 3076
f009ff26 3077 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3078 * the workqueue
3079 */
9bcb3eef 3080 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3081 if (BGP_DEBUG(update, UPDATE_OUT))
3082 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3083 dest);
f009ff26 3084 return;
3085 }
3086
aac24838 3087 if (wq == NULL)
d62a17ae 3088 return;
3089
aac24838 3090 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3091 limit only if is from the same BGP view and it's not an EOIU marker
3092 */
aac24838
JB
3093 if (work_queue_item_count(wq)) {
3094 struct work_queue_item *item = work_queue_last_item(wq);
3095 pqnode = item->data;
228da428 3096
a4d82a8a
PZ
3097 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3098 || pqnode->bgp != bgp
3099 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3100 pqnode = bgp_processq_alloc(bgp);
3101 else
3102 pqnode_reuse = 1;
aac24838 3103 } else
cfe8d15a 3104 pqnode = bgp_processq_alloc(bgp);
aac24838 3105 /* all unlocked in bgp_process_wq */
9bcb3eef 3106 bgp_table_lock(bgp_dest_table(dest));
aac24838 3107
9bcb3eef
DS
3108 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3109 bgp_dest_lock_node(dest);
aac24838 3110
60466a63 3111 /* can't be enqueued twice */
9bcb3eef
DS
3112 assert(STAILQ_NEXT(dest, pq) == NULL);
3113 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3114 pqnode->queued++;
3115
cfe8d15a
LB
3116 if (!pqnode_reuse)
3117 work_queue_add(wq, pqnode);
3118
d62a17ae 3119 return;
fee0f4c6 3120}
0a486e5f 3121
d62a17ae 3122void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3123{
d62a17ae 3124 struct bgp_process_queue *pqnode;
cb1faec9 3125
b6c386bb 3126 if (bgp->process_queue == NULL)
d62a17ae 3127 return;
2e02b9b2 3128
cfe8d15a 3129 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3130
aac24838 3131 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3132 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3133}
3134
d62a17ae 3135static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3136{
d62a17ae 3137 struct peer *peer;
0a486e5f 3138
d62a17ae 3139 peer = THREAD_ARG(thread);
3140 peer->t_pmax_restart = NULL;
0a486e5f 3141
d62a17ae 3142 if (bgp_debug_neighbor_events(peer))
3143 zlog_debug(
3144 "%s Maximum-prefix restart timer expired, restore peering",
3145 peer->host);
0a486e5f 3146
a9bafa95 3147 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3148 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3149
d62a17ae 3150 return 0;
0a486e5f 3151}
3152
9cbd06e0
DA
3153static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3154 safi_t safi)
3155{
3156 uint32_t count = 0;
f41b0459 3157 bool filtered = false;
9cbd06e0
DA
3158 struct bgp_dest *dest;
3159 struct bgp_adj_in *ain;
40bb2ccf 3160 struct attr attr = {};
9cbd06e0
DA
3161 struct bgp_table *table = peer->bgp->rib[afi][safi];
3162
3163 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3164 for (ain = dest->adj_in; ain; ain = ain->next) {
3165 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3166
3167 attr = *ain->attr;
9cbd06e0
DA
3168
3169 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3170 == FILTER_DENY)
f41b0459
DA
3171 filtered = true;
3172
3173 if (bgp_input_modifier(
3174 peer, rn_p, &attr, afi, safi,
3175 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3176 NULL, 0, NULL)
3177 == RMAP_DENY)
3178 filtered = true;
3179
3180 if (filtered)
9cbd06e0 3181 count++;
f41b0459
DA
3182
3183 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3184 }
3185 }
3186
3187 return count;
3188}
3189
3dc339cd
DA
3190bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3191 int always)
718e3744 3192{
d62a17ae 3193 iana_afi_t pkt_afi;
5c525538 3194 iana_safi_t pkt_safi;
9cbd06e0
DA
3195 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3196 PEER_FLAG_MAX_PREFIX_FORCE))
3197 ? bgp_filtered_routes_count(peer, afi, safi)
3198 + peer->pcount[afi][safi]
3199 : peer->pcount[afi][safi];
9cabb64b 3200
d62a17ae 3201 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3202 return false;
e0701b79 3203
9cbd06e0 3204 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3205 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3206 PEER_STATUS_PREFIX_LIMIT)
3207 && !always)
3dc339cd 3208 return false;
e0701b79 3209
d62a17ae 3210 zlog_info(
6cde4b45 3211 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3212 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3213 peer->pmax[afi][safi]);
d62a17ae 3214 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3215
3216 if (CHECK_FLAG(peer->af_flags[afi][safi],
3217 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3218 return false;
d62a17ae 3219
3220 /* Convert AFI, SAFI to values for packet. */
3221 pkt_afi = afi_int2iana(afi);
3222 pkt_safi = safi_int2iana(safi);
3223 {
d7c0a89a 3224 uint8_t ndata[7];
d62a17ae 3225
3226 ndata[0] = (pkt_afi >> 8);
3227 ndata[1] = pkt_afi;
3228 ndata[2] = pkt_safi;
3229 ndata[3] = (peer->pmax[afi][safi] >> 24);
3230 ndata[4] = (peer->pmax[afi][safi] >> 16);
3231 ndata[5] = (peer->pmax[afi][safi] >> 8);
3232 ndata[6] = (peer->pmax[afi][safi]);
3233
3234 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3235 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3236 BGP_NOTIFY_CEASE_MAX_PREFIX,
3237 ndata, 7);
3238 }
3239
3240 /* Dynamic peers will just close their connection. */
3241 if (peer_dynamic_neighbor(peer))
3dc339cd 3242 return true;
d62a17ae 3243
3244 /* restart timer start */
3245 if (peer->pmax_restart[afi][safi]) {
3246 peer->v_pmax_restart =
3247 peer->pmax_restart[afi][safi] * 60;
3248
3249 if (bgp_debug_neighbor_events(peer))
3250 zlog_debug(
3251 "%s Maximum-prefix restart timer started for %d secs",
3252 peer->host, peer->v_pmax_restart);
3253
3254 BGP_TIMER_ON(peer->t_pmax_restart,
3255 bgp_maximum_prefix_restart_timer,
3256 peer->v_pmax_restart);
3257 }
3258
3dc339cd 3259 return true;
d62a17ae 3260 } else
3261 UNSET_FLAG(peer->af_sflags[afi][safi],
3262 PEER_STATUS_PREFIX_LIMIT);
3263
b1823b69
DS
3264 if (pcount
3265 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3266 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3267 PEER_STATUS_PREFIX_THRESHOLD)
3268 && !always)
3dc339cd 3269 return false;
d62a17ae 3270
3271 zlog_info(
6cde4b45 3272 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3273 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3274 peer->pmax[afi][safi]);
d62a17ae 3275 SET_FLAG(peer->af_sflags[afi][safi],
3276 PEER_STATUS_PREFIX_THRESHOLD);
3277 } else
3278 UNSET_FLAG(peer->af_sflags[afi][safi],
3279 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3280 return false;
718e3744 3281}
3282
b40d939b 3283/* Unconditionally remove the route from the RIB, without taking
3284 * damping into consideration (eg, because the session went down)
3285 */
9bcb3eef 3286void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3287 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3288{
f009ff26 3289
3290 struct bgp *bgp = NULL;
3291 bool delete_route = false;
3292
9bcb3eef
DS
3293 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3294 safi);
d62a17ae 3295
f009ff26 3296 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3297 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3298
f009ff26 3299 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3300 * flag
3301 */
3302 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3303 delete_route = true;
9bcb3eef 3304 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3305 delete_route = true;
f009ff26 3306 if (delete_route) {
9bcb3eef
DS
3307 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3308 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3309 bgp = pi->peer->bgp;
26742171 3310 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3311 }
3312 }
3313 }
4a11bf2c 3314
9bcb3eef
DS
3315 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3316 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3317}
3318
9bcb3eef 3319static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3320 struct peer *peer, afi_t afi, safi_t safi,
3321 struct prefix_rd *prd)
3322{
9bcb3eef 3323 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3324
d62a17ae 3325 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3326 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3327 */
3328 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3329 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3330 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3331 == BGP_DAMP_SUPPRESSED) {
b54892e0 3332 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3333 safi);
3334 return;
3335 }
3336
49e5a4a0 3337#ifdef ENABLE_BGP_VNC
d62a17ae 3338 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3339 struct bgp_dest *pdest = NULL;
d62a17ae 3340 struct bgp_table *table = NULL;
3341
9bcb3eef
DS
3342 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3343 (struct prefix *)prd);
3344 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3345 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3346
3347 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3348 peer->bgp, prd, table, p, pi);
d62a17ae 3349 }
9bcb3eef 3350 bgp_dest_unlock_node(pdest);
d62a17ae 3351 }
3352 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3353 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3354
b54892e0
DS
3355 vnc_import_bgp_del_route(peer->bgp, p, pi);
3356 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3357 }
65efcfce 3358 }
d62a17ae 3359#endif
128ea8ab 3360
d62a17ae 3361 /* If this is an EVPN route, process for un-import. */
3362 if (safi == SAFI_EVPN)
b54892e0 3363 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3364
9bcb3eef 3365 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3366}
3367
4b7e6066
DS
3368struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3369 struct peer *peer, struct attr *attr,
9bcb3eef 3370 struct bgp_dest *dest)
fb018d25 3371{
4b7e6066 3372 struct bgp_path_info *new;
fb018d25 3373
d62a17ae 3374 /* Make new BGP info. */
4b7e6066 3375 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3376 new->type = type;
3377 new->instance = instance;
3378 new->sub_type = sub_type;
3379 new->peer = peer;
3380 new->attr = attr;
3381 new->uptime = bgp_clock();
9bcb3eef 3382 new->net = dest;
d62a17ae 3383 return new;
fb018d25
DS
3384}
3385
d62a17ae 3386static void overlay_index_update(struct attr *attr,
d62a17ae 3387 union gw_addr *gw_ip)
684a7227 3388{
d62a17ae 3389 if (!attr)
3390 return;
d62a17ae 3391 if (gw_ip == NULL) {
6c924775
DS
3392 struct bgp_route_evpn eo;
3393
3394 memset(&eo, 0, sizeof(eo));
3395 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3396 } else {
6c924775
DS
3397 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3398
3399 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3400 }
684a7227
PG
3401}
3402
40381db7 3403static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3404 union gw_addr *gw_ip)
3405{
6c924775
DS
3406 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3407 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3408 union {
0a50c248 3409 esi_t esi;
11ebf4ed
DS
3410 union gw_addr ip;
3411 } temp;
d62a17ae 3412
3413 if (afi != AFI_L2VPN)
3414 return true;
11ebf4ed 3415
6c924775 3416 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3417
3418 if (gw_ip == NULL) {
3419 memset(&temp, 0, sizeof(temp));
40381db7 3420 path_gw_ip_remote = &temp.ip;
11ebf4ed 3421 } else
40381db7 3422 path_gw_ip_remote = gw_ip;
11ebf4ed 3423
6c924775 3424 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3425}
3426
c265ee22 3427/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3428bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3429 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3430 struct bgp_dest *dest)
d62a17ae 3431{
2dbe3fa9 3432 bool ret = false;
b099a5c8
DA
3433 bool is_bgp_static_route =
3434 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3435 : false;
d62a17ae 3436
e8442016
DS
3437 /*
3438 * Only validated for unicast and multicast currently.
3439 * Also valid for EVPN where the nexthop is an IP address.
3440 * If we are a bgp static route being checked then there is
3441 * no need to check to see if the nexthop is martian as
3442 * that it should be ok.
3443 */
3444 if (is_bgp_static_route ||
3445 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3446 return false;
d62a17ae 3447
3448 /* If NEXT_HOP is present, validate it. */
3449 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3450 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3451 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3452 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3453 return true;
d62a17ae 3454 }
c265ee22 3455
d62a17ae 3456 /* If MP_NEXTHOP is present, validate it. */
3457 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3458 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3459 * it is not an IPv6 link-local address.
0355b41d
DA
3460 *
3461 * If we receive an UPDATE with nexthop length set to 32 bytes
3462 * we shouldn't discard an UPDATE if it's set to (::).
3463 * The link-local (2st) is validated along the code path later.
d62a17ae 3464 */
3465 if (attr->mp_nexthop_len) {
3466 switch (attr->mp_nexthop_len) {
3467 case BGP_ATTR_NHLEN_IPV4:
3468 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3469 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3470 || IPV4_CLASS_DE(
3471 ntohl(attr->mp_nexthop_global_in.s_addr))
3472 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3473 dest));
d62a17ae 3474 break;
3475
3476 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3477 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3478 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3479 &attr->mp_nexthop_global)
d62a17ae 3480 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3481 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3482 &attr->mp_nexthop_global)
3483 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3484 dest));
d62a17ae 3485 break;
0355b41d
DA
3486 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3487 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3488 || IN6_IS_ADDR_MULTICAST(
3489 &attr->mp_nexthop_global)
3490 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3491 dest));
0355b41d 3492 break;
d62a17ae 3493
3494 default:
3dc339cd 3495 ret = true;
d62a17ae 3496 break;
3497 }
3498 }
c265ee22 3499
d62a17ae 3500 return ret;
3501}
3502
5a1ae2c2 3503int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3504 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3505 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3506 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3507 struct bgp_route_evpn *evpn)
d62a17ae 3508{
3509 int ret;
3510 int aspath_loop_count = 0;
9bcb3eef 3511 struct bgp_dest *dest;
d62a17ae 3512 struct bgp *bgp;
3513 struct attr new_attr;
3514 struct attr *attr_new;
40381db7 3515 struct bgp_path_info *pi;
4b7e6066
DS
3516 struct bgp_path_info *new;
3517 struct bgp_path_info_extra *extra;
d62a17ae 3518 const char *reason;
3519 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3520 int connected = 0;
3521 int do_loop_check = 1;
3522 int has_valid_label = 0;
7c312383 3523 afi_t nh_afi;
949b0f24 3524 uint8_t pi_type = 0;
3525 uint8_t pi_sub_type = 0;
3526
c7bb4f00 3527 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3528 char pfxprint[PREFIX2STR_BUFFER];
3529
3530 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3531 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3532 afi, safi, attr);
6401252f
QY
3533 }
3534
49e5a4a0 3535#ifdef ENABLE_BGP_VNC
d62a17ae 3536 int vnc_implicit_withdraw = 0;
65efcfce 3537#endif
d62a17ae 3538 int same_attr = 0;
718e3744 3539
d62a17ae 3540 memset(&new_attr, 0, sizeof(struct attr));
3541 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3542 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3543
d62a17ae 3544 bgp = peer->bgp;
9bcb3eef 3545 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3546 /* TODO: Check to see if we can get rid of "is_valid_label" */
3547 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3548 has_valid_label = (num_labels > 0) ? 1 : 0;
3549 else
3550 has_valid_label = bgp_is_valid_label(label);
718e3744 3551
28f66de2
MS
3552 if (has_valid_label)
3553 assert(label != NULL);
3554
a77e2f4b
S
3555 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3556 * condition :
3557 * Suppress fib is enabled
3558 * BGP_OPT_NO_FIB is not enabled
3559 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3560 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3561 */
3562 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3563 (sub_type == BGP_ROUTE_NORMAL) &&
3564 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3565 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3566 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3567
d62a17ae 3568 /* When peer's soft reconfiguration enabled. Record input packet in
3569 Adj-RIBs-In. */
3570 if (!soft_reconfig
3571 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3572 && peer != bgp->peer_self)
9bcb3eef 3573 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3574
3575 /* Check previously received route. */
9bcb3eef 3576 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3577 if (pi->peer == peer && pi->type == type
3578 && pi->sub_type == sub_type
3579 && pi->addpath_rx_id == addpath_id)
d62a17ae 3580 break;
3581
3582 /* AS path local-as loop check. */
3583 if (peer->change_local_as) {
c4368918
DW
3584 if (peer->allowas_in[afi][safi])
3585 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3586 else if (!CHECK_FLAG(peer->flags,
3587 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3588 aspath_loop_count = 1;
3589
3590 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3591 > aspath_loop_count) {
b4d46cc9 3592 peer->stat_pfx_aspath_loop++;
9bcb3eef 3593 reason = "as-path contains our own AS A;";
d62a17ae 3594 goto filtered;
3595 }
718e3744 3596 }
718e3744 3597
d62a17ae 3598 /* If the peer is configured for "allowas-in origin" and the last ASN in
3599 * the
3600 * as-path is our ASN then we do not need to call aspath_loop_check
3601 */
3602 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3603 if (aspath_get_last_as(attr->aspath) == bgp->as)
3604 do_loop_check = 0;
3605
3606 /* AS path loop check. */
3607 if (do_loop_check) {
3608 if (aspath_loop_check(attr->aspath, bgp->as)
3609 > peer->allowas_in[afi][safi]
3610 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3611 && aspath_loop_check(attr->aspath, bgp->confed_id)
3612 > peer->allowas_in[afi][safi])) {
b4d46cc9 3613 peer->stat_pfx_aspath_loop++;
d62a17ae 3614 reason = "as-path contains our own AS;";
3615 goto filtered;
3616 }
3617 }
aac9ef6c 3618
d62a17ae 3619 /* Route reflector originator ID check. */
3620 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3621 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3622 peer->stat_pfx_originator_loop++;
d62a17ae 3623 reason = "originator is us;";
3624 goto filtered;
3625 }
718e3744 3626
d62a17ae 3627 /* Route reflector cluster ID check. */
3628 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3629 peer->stat_pfx_cluster_loop++;
d62a17ae 3630 reason = "reflected from the same cluster;";
3631 goto filtered;
3632 }
718e3744 3633
d62a17ae 3634 /* Apply incoming filter. */
3635 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3636 peer->stat_pfx_filter++;
d62a17ae 3637 reason = "filter;";
3638 goto filtered;
3639 }
718e3744 3640
a8b72dc6
DA
3641 /* RFC 8212 to prevent route leaks.
3642 * This specification intends to improve this situation by requiring the
3643 * explicit configuration of both BGP Import and Export Policies for any
3644 * External BGP (EBGP) session such as customers, peers, or
3645 * confederation boundaries for all enabled address families. Through
3646 * codification of the aforementioned requirement, operators will
3647 * benefit from consistent behavior across different BGP
3648 * implementations.
3649 */
1d3fdccf 3650 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3651 if (!bgp_inbound_policy_exists(peer,
3652 &peer->filter[afi][safi])) {
3653 reason = "inbound policy missing";
3654 goto filtered;
3655 }
3656
fb29348a
DA
3657 /* draft-ietf-idr-deprecate-as-set-confed-set
3658 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3659 * Eventually, This document (if approved) updates RFC 4271
3660 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3661 * and obsoletes RFC 6472.
3662 */
7f972cd8 3663 if (peer->bgp->reject_as_sets)
fb29348a
DA
3664 if (aspath_check_as_sets(attr->aspath)) {
3665 reason =
3666 "as-path contains AS_SET or AS_CONFED_SET type;";
3667 goto filtered;
3668 }
3669
6f4f49b2 3670 new_attr = *attr;
d62a17ae 3671
3672 /* Apply incoming route-map.
3673 * NB: new_attr may now contain newly allocated values from route-map
3674 * "set"
3675 * commands, so we need bgp_attr_flush in the error paths, until we
3676 * intern
3677 * the attr (which takes over the memory references) */
9bcb3eef
DS
3678 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3679 num_labels, dest)
3680 == RMAP_DENY) {
b4d46cc9 3681 peer->stat_pfx_filter++;
d62a17ae 3682 reason = "route-map;";
3683 bgp_attr_flush(&new_attr);
3684 goto filtered;
3685 }
718e3744 3686
05864da7 3687 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3688 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3689 /* remove from RIB previous entry */
3690 bgp_zebra_withdraw(p, pi, bgp, safi);
3691 }
3692
7f323236
DW
3693 if (peer->sort == BGP_PEER_EBGP) {
3694
a4d82a8a
PZ
3695 /* If we receive the graceful-shutdown community from an eBGP
3696 * peer we must lower local-preference */
3697 if (new_attr.community
3698 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3699 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3700 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3701
a4d82a8a
PZ
3702 /* If graceful-shutdown is configured then add the GSHUT
3703 * community to all paths received from eBGP peers */
637e5ba4 3704 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3705 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3706 }
3707
949b0f24 3708 if (pi) {
3709 pi_type = pi->type;
3710 pi_sub_type = pi->sub_type;
3711 }
3712
d62a17ae 3713 /* next hop check. */
a4d82a8a 3714 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3715 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3716 &new_attr, dest)) {
b4d46cc9 3717 peer->stat_pfx_nh_invalid++;
d62a17ae 3718 reason = "martian or self next-hop;";
3719 bgp_attr_flush(&new_attr);
3720 goto filtered;
3721 }
718e3744 3722
5c14a191 3723 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3724 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3725 reason = "self mac;";
3726 goto filtered;
3727 }
3728
1e9be514
QY
3729 /* Update Overlay Index */
3730 if (afi == AFI_L2VPN) {
3731 overlay_index_update(&new_attr,
3732 evpn == NULL ? NULL : &evpn->gw_ip);
3733 }
3734
d62a17ae 3735 attr_new = bgp_attr_intern(&new_attr);
3736
9cbd06e0
DA
3737 /* If maximum prefix count is configured and current prefix
3738 * count exeed it.
3739 */
3740 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3741 return -1;
3742
d62a17ae 3743 /* If the update is implicit withdraw. */
40381db7
DS
3744 if (pi) {
3745 pi->uptime = bgp_clock();
3746 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3747
9bcb3eef 3748 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3749
d62a17ae 3750 /* Same attribute comes in. */
40381db7
DS
3751 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3752 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3753 && (!has_valid_label
40381db7 3754 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3755 num_labels * sizeof(mpls_label_t))
d62a17ae 3756 == 0)
3757 && (overlay_index_equal(
0a50c248 3758 afi, pi,
d62a17ae 3759 evpn == NULL ? NULL : &evpn->gw_ip))) {
3760 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3761 BGP_CONFIG_DAMPENING)
3762 && peer->sort == BGP_PEER_EBGP
40381db7 3763 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3764 if (bgp_debug_update(peer, p, NULL, 1)) {
3765 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3766 afi, safi, prd, p, label,
3767 num_labels, addpath_id ? 1 : 0,
3768 addpath_id, pfx_buf,
3769 sizeof(pfx_buf));
d62a17ae 3770 zlog_debug("%s rcvd %s", peer->host,
3771 pfx_buf);
3772 }
3773
9bcb3eef 3774 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3775 != BGP_DAMP_SUPPRESSED) {
40381db7 3776 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3777 safi);
9bcb3eef 3778 bgp_process(bgp, dest, afi, safi);
d62a17ae 3779 }
3780 } else /* Duplicate - odd */
3781 {
3782 if (bgp_debug_update(peer, p, NULL, 1)) {
3783 if (!peer->rcvd_attr_printed) {
3784 zlog_debug(
3785 "%s rcvd UPDATE w/ attr: %s",
3786 peer->host,
3787 peer->rcvd_attr_str);
3788 peer->rcvd_attr_printed = 1;
3789 }
3790
3791 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3792 afi, safi, prd, p, label,
3793 num_labels, addpath_id ? 1 : 0,
3794 addpath_id, pfx_buf,
3795 sizeof(pfx_buf));
d62a17ae 3796 zlog_debug(
3797 "%s rcvd %s...duplicate ignored",
3798 peer->host, pfx_buf);
3799 }
3800
3801 /* graceful restart STALE flag unset. */
40381db7 3802 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3803 bgp_path_info_unset_flag(
9bcb3eef
DS
3804 dest, pi, BGP_PATH_STALE);
3805 bgp_dest_set_defer_flag(dest, false);
3806 bgp_process(bgp, dest, afi, safi);
d62a17ae 3807 }
3808 }
3809
9bcb3eef 3810 bgp_dest_unlock_node(dest);
d62a17ae 3811 bgp_attr_unintern(&attr_new);
3812
3813 return 0;
3814 }
718e3744 3815
d62a17ae 3816 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3817 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3818 if (bgp_debug_update(peer, p, NULL, 1)) {
3819 bgp_debug_rdpfxpath2str(
a4d82a8a 3820 afi, safi, prd, p, label, num_labels,
d62a17ae 3821 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3822 sizeof(pfx_buf));
3823 zlog_debug(
3824 "%s rcvd %s, flapped quicker than processing",
3825 peer->host, pfx_buf);
3826 }
3827
9bcb3eef 3828 bgp_path_info_restore(dest, pi);
d62a17ae 3829 }
718e3744 3830
d62a17ae 3831 /* Received Logging. */
3832 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3833 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3834 num_labels, addpath_id ? 1 : 0,
3835 addpath_id, pfx_buf,
3836 sizeof(pfx_buf));
d62a17ae 3837 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3838 }
718e3744 3839
d62a17ae 3840 /* graceful restart STALE flag unset. */
f009ff26 3841 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3842 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3843 bgp_dest_set_defer_flag(dest, false);
f009ff26 3844 }
d62a17ae 3845
3846 /* The attribute is changed. */
9bcb3eef 3847 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3848
3849 /* implicit withdraw, decrement aggregate and pcount here.
3850 * only if update is accepted, they'll increment below.
3851 */
40381db7 3852 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3853
3854 /* Update bgp route dampening information. */
3855 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3856 && peer->sort == BGP_PEER_EBGP) {
3857 /* This is implicit withdraw so we should update
3858 dampening
3859 information. */
40381db7 3860 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3861 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3862 }
49e5a4a0 3863#ifdef ENABLE_BGP_VNC
d62a17ae 3864 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3865 struct bgp_dest *pdest = NULL;
d62a17ae 3866 struct bgp_table *table = NULL;
3867
9bcb3eef
DS
3868 pdest = bgp_node_get(bgp->rib[afi][safi],
3869 (struct prefix *)prd);
3870 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3871 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3872
3873 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3874 bgp, prd, table, p, pi);
d62a17ae 3875 }
9bcb3eef 3876 bgp_dest_unlock_node(pdest);
d62a17ae 3877 }
3878 if ((afi == AFI_IP || afi == AFI_IP6)
3879 && (safi == SAFI_UNICAST)) {
40381db7 3880 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3881 /*
3882 * Implicit withdraw case.
3883 */
3884 ++vnc_implicit_withdraw;
40381db7
DS
3885 vnc_import_bgp_del_route(bgp, p, pi);
3886 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3887 }
3888 }
65efcfce 3889#endif
128ea8ab 3890
d62a17ae 3891 /* Special handling for EVPN update of an existing route. If the
3892 * extended community attribute has changed, we need to
3893 * un-import
3894 * the route using its existing extended community. It will be
3895 * subsequently processed for import with the new extended
3896 * community.
3897 */
6f8c9c11
PR
3898 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3899 && !same_attr) {
40381db7 3900 if ((pi->attr->flag
d62a17ae 3901 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3902 && (attr_new->flag
3903 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3904 int cmp;
3905
40381db7 3906 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3907 attr_new->ecommunity);
3908 if (!cmp) {
3909 if (bgp_debug_update(peer, p, NULL, 1))
3910 zlog_debug(
3911 "Change in EXT-COMM, existing %s new %s",
3912 ecommunity_str(
40381db7 3913 pi->attr->ecommunity),
d62a17ae 3914 ecommunity_str(
3915 attr_new->ecommunity));
6f8c9c11
PR
3916 if (safi == SAFI_EVPN)
3917 bgp_evpn_unimport_route(
3918 bgp, afi, safi, p, pi);
3919 else /* SAFI_MPLS_VPN */
3920 vpn_leak_to_vrf_withdraw(bgp,
3921 pi);
d62a17ae 3922 }
3923 }
3924 }
718e3744 3925
d62a17ae 3926 /* Update to new attribute. */
40381db7
DS
3927 bgp_attr_unintern(&pi->attr);
3928 pi->attr = attr_new;
d62a17ae 3929
3930 /* Update MPLS label */
3931 if (has_valid_label) {
40381db7 3932 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3933 if (extra->label != label) {
3934 memcpy(&extra->label, label,
dbd587da 3935 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3936 extra->num_labels = num_labels;
3937 }
b57ba6d2
MK
3938 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3939 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3940 }
718e3744 3941
e496b420
HS
3942 /* Update SRv6 SID */
3943 if (attr->srv6_l3vpn) {
3944 extra = bgp_path_info_extra_get(pi);
3945 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3946 sid_copy(&extra->sid[0],
3947 &attr->srv6_l3vpn->sid);
3948 extra->num_sids = 1;
3949 }
3950 } else if (attr->srv6_vpn) {
3951 extra = bgp_path_info_extra_get(pi);
3952 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3953 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3954 extra->num_sids = 1;
3955 }
3956 }
3957
49e5a4a0 3958#ifdef ENABLE_BGP_VNC
d62a17ae 3959 if ((afi == AFI_IP || afi == AFI_IP6)
3960 && (safi == SAFI_UNICAST)) {
3961 if (vnc_implicit_withdraw) {
3962 /*
3963 * Add back the route with its new attributes
3964 * (e.g., nexthop).
3965 * The route is still selected, until the route
3966 * selection
3967 * queued by bgp_process actually runs. We have
3968 * to make this
3969 * update to the VNC side immediately to avoid
3970 * racing against
3971 * configuration changes (e.g., route-map
3972 * changes) which
3973 * trigger re-importation of the entire RIB.
3974 */
40381db7
DS
3975 vnc_import_bgp_add_route(bgp, p, pi);
3976 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3977 }
3978 }
65efcfce
LB
3979#endif
3980
d62a17ae 3981 /* Update bgp route dampening information. */
3982 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3983 && peer->sort == BGP_PEER_EBGP) {
3984 /* Now we do normal update dampening. */
9bcb3eef 3985 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3986 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3987 bgp_dest_unlock_node(dest);
d62a17ae 3988 return 0;
3989 }
3990 }
128ea8ab 3991
d62a17ae 3992 /* Nexthop reachability check - for unicast and
3993 * labeled-unicast.. */
7c312383
AD
3994 if (((afi == AFI_IP || afi == AFI_IP6)
3995 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3996 || (safi == SAFI_EVPN &&
3997 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3998 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3999 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4000 && !CHECK_FLAG(peer->flags,
4001 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4002 && !CHECK_FLAG(bgp->flags,
4003 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4004 connected = 1;
4005 else
4006 connected = 0;
4007
960035b2
PZ
4008 struct bgp *bgp_nexthop = bgp;
4009
40381db7
DS
4010 if (pi->extra && pi->extra->bgp_orig)
4011 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4012
7c312383
AD
4013 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4014
4015 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4016 pi, NULL, connected)
a4d82a8a 4017 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4018 bgp_path_info_set_flag(dest, pi,
4019 BGP_PATH_VALID);
d62a17ae 4020 else {
4021 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4022 zlog_debug("%s(%pI4): NH unresolved",
4023 __func__,
4024 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4025 }
9bcb3eef 4026 bgp_path_info_unset_flag(dest, pi,
18ee8310 4027 BGP_PATH_VALID);
d62a17ae 4028 }
4029 } else
9bcb3eef 4030 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4031
49e5a4a0 4032#ifdef ENABLE_BGP_VNC
d62a17ae 4033 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4034 struct bgp_dest *pdest = NULL;
d62a17ae 4035 struct bgp_table *table = NULL;
4036
9bcb3eef
DS
4037 pdest = bgp_node_get(bgp->rib[afi][safi],
4038 (struct prefix *)prd);
4039 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4040 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4041
4042 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4043 bgp, prd, table, p, pi);
d62a17ae 4044 }
9bcb3eef 4045 bgp_dest_unlock_node(pdest);
d62a17ae 4046 }
4047#endif
718e3744 4048
d62a17ae 4049 /* If this is an EVPN route and some attribute has changed,
4050 * process
4051 * route for import. If the extended community has changed, we
4052 * would
4053 * have done the un-import earlier and the import would result
4054 * in the
4055 * route getting injected into appropriate L2 VNIs. If it is
4056 * just
4057 * some other attribute change, the import will result in
4058 * updating
4059 * the attributes for the route in the VNI(s).
4060 */
7c312383
AD
4061 if (safi == SAFI_EVPN && !same_attr &&
4062 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4063 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4064
4065 /* Process change. */
40381db7 4066 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4067
9bcb3eef
DS
4068 bgp_process(bgp, dest, afi, safi);
4069 bgp_dest_unlock_node(dest);
558d1fec 4070
ddb5b488
PZ
4071 if (SAFI_UNICAST == safi
4072 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4073 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4074
40381db7 4075 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4076 }
4077 if ((SAFI_MPLS_VPN == safi)
4078 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4079
40381db7 4080 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4081 }
4082
49e5a4a0 4083#ifdef ENABLE_BGP_VNC
d62a17ae 4084 if (SAFI_MPLS_VPN == safi) {
4085 mpls_label_t label_decoded = decode_label(label);
28070ee3 4086
d62a17ae 4087 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4088 type, sub_type, &label_decoded);
4089 }
4090 if (SAFI_ENCAP == safi) {
4091 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4092 type, sub_type, NULL);
4093 }
28070ee3
PZ
4094#endif
4095
d62a17ae 4096 return 0;
4097 } // End of implicit withdraw
718e3744 4098
d62a17ae 4099 /* Received Logging. */
4100 if (bgp_debug_update(peer, p, NULL, 1)) {
4101 if (!peer->rcvd_attr_printed) {
4102 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4103 peer->rcvd_attr_str);
4104 peer->rcvd_attr_printed = 1;
4105 }
718e3744 4106
a4d82a8a 4107 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4108 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4109 sizeof(pfx_buf));
4110 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4111 }
718e3744 4112
d62a17ae 4113 /* Make new BGP info. */
9bcb3eef 4114 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4115
d62a17ae 4116 /* Update MPLS label */
4117 if (has_valid_label) {
18ee8310 4118 extra = bgp_path_info_extra_get(new);
8ba71050 4119 if (extra->label != label) {
dbd587da
QY
4120 memcpy(&extra->label, label,
4121 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4122 extra->num_labels = num_labels;
4123 }
b57ba6d2
MK
4124 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4125 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4126 }
718e3744 4127
e496b420
HS
4128 /* Update SRv6 SID */
4129 if (safi == SAFI_MPLS_VPN) {
4130 extra = bgp_path_info_extra_get(new);
4131 if (attr->srv6_l3vpn) {
4132 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4133 extra->num_sids = 1;
4134 } else if (attr->srv6_vpn) {
4135 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4136 extra->num_sids = 1;
4137 }
4138 }
4139
d62a17ae 4140 /* Update Overlay Index */
4141 if (afi == AFI_L2VPN) {
4142 overlay_index_update(new->attr,
d62a17ae 4143 evpn == NULL ? NULL : &evpn->gw_ip);
4144 }
4145 /* Nexthop reachability check. */
7c312383
AD
4146 if (((afi == AFI_IP || afi == AFI_IP6)
4147 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4148 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4149 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4150 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4151 && !CHECK_FLAG(peer->flags,
4152 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4153 && !CHECK_FLAG(bgp->flags,
4154 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4155 connected = 1;
4156 else
4157 connected = 0;
4158
7c312383
AD
4159 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4160
4161 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4162 connected)
a4d82a8a 4163 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4164 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4165 else {
4166 if (BGP_DEBUG(nht, NHT)) {
4167 char buf1[INET6_ADDRSTRLEN];
4168 inet_ntop(AF_INET,
4169 (const void *)&attr_new->nexthop,
4170 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4171 zlog_debug("%s(%s): NH unresolved", __func__,
4172 buf1);
d62a17ae 4173 }
9bcb3eef 4174 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4175 }
4176 } else
9bcb3eef 4177 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4178
d62a17ae 4179 /* Addpath ID */
4180 new->addpath_rx_id = addpath_id;
4181
4182 /* Increment prefix */
4183 bgp_aggregate_increment(bgp, p, new, afi, safi);
4184
4185 /* Register new BGP information. */
9bcb3eef 4186 bgp_path_info_add(dest, new);
d62a17ae 4187
4188 /* route_node_get lock */
9bcb3eef 4189 bgp_dest_unlock_node(dest);
558d1fec 4190
49e5a4a0 4191#ifdef ENABLE_BGP_VNC
d62a17ae 4192 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4193 struct bgp_dest *pdest = NULL;
d62a17ae 4194 struct bgp_table *table = NULL;
4195
9bcb3eef
DS
4196 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4197 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4198 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4199
4200 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4201 bgp, prd, table, p, new);
4202 }
9bcb3eef 4203 bgp_dest_unlock_node(pdest);
d62a17ae 4204 }
65efcfce
LB
4205#endif
4206
d62a17ae 4207 /* If this is an EVPN route, process for import. */
7c312383 4208 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4209 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4210
9bcb3eef 4211 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4212
d62a17ae 4213 /* Process change. */
9bcb3eef 4214 bgp_process(bgp, dest, afi, safi);
718e3744 4215
ddb5b488
PZ
4216 if (SAFI_UNICAST == safi
4217 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4218 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4219 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4220 }
4221 if ((SAFI_MPLS_VPN == safi)
4222 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4223
4224 vpn_leak_to_vrf_update(bgp, new);
4225 }
49e5a4a0 4226#ifdef ENABLE_BGP_VNC
d62a17ae 4227 if (SAFI_MPLS_VPN == safi) {
4228 mpls_label_t label_decoded = decode_label(label);
28070ee3 4229
d62a17ae 4230 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4231 sub_type, &label_decoded);
4232 }
4233 if (SAFI_ENCAP == safi) {
4234 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4235 sub_type, NULL);
4236 }
28070ee3
PZ
4237#endif
4238
d62a17ae 4239 return 0;
718e3744 4240
d62a17ae 4241/* This BGP update is filtered. Log the reason then update BGP
4242 entry. */
4243filtered:
9bcb3eef 4244 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4245
d62a17ae 4246 if (bgp_debug_update(peer, p, NULL, 1)) {
4247 if (!peer->rcvd_attr_printed) {
4248 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4249 peer->rcvd_attr_str);
4250 peer->rcvd_attr_printed = 1;
4251 }
718e3744 4252
a4d82a8a 4253 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4254 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4255 sizeof(pfx_buf));
4256 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4257 peer->host, pfx_buf, reason);
4258 }
128ea8ab 4259
40381db7 4260 if (pi) {
d62a17ae 4261 /* If this is an EVPN route, un-import it as it is now filtered.
4262 */
4263 if (safi == SAFI_EVPN)
40381db7 4264 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4265
ddb5b488
PZ
4266 if (SAFI_UNICAST == safi
4267 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4268 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4269
40381db7 4270 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4271 }
4272 if ((SAFI_MPLS_VPN == safi)
4273 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4274
40381db7 4275 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4276 }
4277
9bcb3eef 4278 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4279 }
4280
9bcb3eef 4281 bgp_dest_unlock_node(dest);
558d1fec 4282
49e5a4a0 4283#ifdef ENABLE_BGP_VNC
d62a17ae 4284 /*
4285 * Filtered update is treated as an implicit withdrawal (see
4286 * bgp_rib_remove()
4287 * a few lines above)
4288 */
4289 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4290 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4291 0);
4292 }
97736e32
PZ
4293#endif
4294
d62a17ae 4295 return 0;
718e3744 4296}
4297
26a3ffd6 4298int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4299 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4300 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4301 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4302{
d62a17ae 4303 struct bgp *bgp;
4304 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4305 struct bgp_dest *dest;
40381db7 4306 struct bgp_path_info *pi;
718e3744 4307
49e5a4a0 4308#ifdef ENABLE_BGP_VNC
d62a17ae 4309 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4310 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4311 0);
4312 }
28070ee3
PZ
4313#endif
4314
d62a17ae 4315 bgp = peer->bgp;
4316
4317 /* Lookup node. */
9bcb3eef 4318 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4319
4320 /* If peer is soft reconfiguration enabled. Record input packet for
4321 * further calculation.
4322 *
4323 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4324 * routes that are filtered. This tanks out Quagga RS pretty badly due
4325 * to
4326 * the iteration over all RS clients.
4327 * Since we need to remove the entry from adj_in anyway, do that first
4328 * and
4329 * if there was no entry, we don't need to do anything more.
4330 */
4331 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4332 && peer != bgp->peer_self)
9bcb3eef 4333 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4334 peer->stat_pfx_dup_withdraw++;
4335
d62a17ae 4336 if (bgp_debug_update(peer, p, NULL, 1)) {
4337 bgp_debug_rdpfxpath2str(
a4d82a8a 4338 afi, safi, prd, p, label, num_labels,
d62a17ae 4339 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4340 sizeof(pfx_buf));
4341 zlog_debug(
4342 "%s withdrawing route %s not in adj-in",
4343 peer->host, pfx_buf);
4344 }
9bcb3eef 4345 bgp_dest_unlock_node(dest);
d62a17ae 4346 return 0;
4347 }
cd808e74 4348
d62a17ae 4349 /* Lookup withdrawn route. */
9bcb3eef 4350 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4351 if (pi->peer == peer && pi->type == type
4352 && pi->sub_type == sub_type
4353 && pi->addpath_rx_id == addpath_id)
d62a17ae 4354 break;
4355
4356 /* Logging. */
4357 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4358 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4359 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4360 sizeof(pfx_buf));
4361 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4362 pfx_buf);
4363 }
718e3744 4364
d62a17ae 4365 /* Withdraw specified route from routing table. */
40381db7 4366 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4367 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4368 if (SAFI_UNICAST == safi
4369 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4370 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4371 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4372 }
4373 if ((SAFI_MPLS_VPN == safi)
4374 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4375
40381db7 4376 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4377 }
4378 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4379 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4380 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4381 sizeof(pfx_buf));
4382 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4383 }
718e3744 4384
d62a17ae 4385 /* Unlock bgp_node_get() lock. */
9bcb3eef 4386 bgp_dest_unlock_node(dest);
d62a17ae 4387
4388 return 0;
718e3744 4389}
6b0655a2 4390
d62a17ae 4391void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4392 int withdraw)
718e3744 4393{
d62a17ae 4394 struct update_subgroup *subgrp;
4395 subgrp = peer_subgroup(peer, afi, safi);
4396 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4397}
6182d65b 4398
718e3744 4399
3f9c7369
DS
4400/*
4401 * bgp_stop_announce_route_timer
4402 */
d62a17ae 4403void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4404{
d62a17ae 4405 if (!paf->t_announce_route)
4406 return;
4407
50478845 4408 thread_cancel(&paf->t_announce_route);
718e3744 4409}
6b0655a2 4410
3f9c7369
DS
4411/*
4412 * bgp_announce_route_timer_expired
4413 *
4414 * Callback that is invoked when the route announcement timer for a
4415 * peer_af expires.
4416 */
d62a17ae 4417static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4418{
d62a17ae 4419 struct peer_af *paf;
4420 struct peer *peer;
558d1fec 4421
d62a17ae 4422 paf = THREAD_ARG(t);
4423 peer = paf->peer;
718e3744 4424
d62a17ae 4425 if (peer->status != Established)
4426 return 0;
3f9c7369 4427
d62a17ae 4428 if (!peer->afc_nego[paf->afi][paf->safi])
4429 return 0;
3f9c7369 4430
d62a17ae 4431 peer_af_announce_route(paf, 1);
c5aec50b
MK
4432
4433 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4434 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4435
d62a17ae 4436 return 0;
718e3744 4437}
4438
3f9c7369
DS
4439/*
4440 * bgp_announce_route
4441 *
4442 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4443 */
d62a17ae 4444void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4445{
4446 struct peer_af *paf;
4447 struct update_subgroup *subgrp;
4448
4449 paf = peer_af_find(peer, afi, safi);
4450 if (!paf)
4451 return;
4452 subgrp = PAF_SUBGRP(paf);
4453
4454 /*
4455 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4456 * or a refresh has already been triggered.
4457 */
4458 if (!subgrp || paf->t_announce_route)
4459 return;
4460
4461 /*
4462 * Start a timer to stagger/delay the announce. This serves
4463 * two purposes - announcement can potentially be combined for
4464 * multiple peers and the announcement doesn't happen in the
4465 * vty context.
4466 */
4467 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4468 (subgrp->peer_count == 1)
4469 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4470 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4471 &paf->t_announce_route);
3f9c7369
DS
4472}
4473
4474/*
4475 * Announce routes from all AF tables to a peer.
4476 *
4477 * This should ONLY be called when there is a need to refresh the
4478 * routes to the peer based on a policy change for this peer alone
4479 * or a route refresh request received from the peer.
4480 * The operation will result in splitting the peer from its existing
4481 * subgroups and putting it in new subgroups.
4482 */
d62a17ae 4483void bgp_announce_route_all(struct peer *peer)
718e3744 4484{
d62a17ae 4485 afi_t afi;
4486 safi_t safi;
4487
05c7a1cc
QY
4488 FOREACH_AFI_SAFI (afi, safi)
4489 bgp_announce_route(peer, afi, safi);
718e3744 4490}
6b0655a2 4491
d62a17ae 4492static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4493 struct bgp_table *table,
4494 struct prefix_rd *prd)
718e3744 4495{
d62a17ae 4496 int ret;
9bcb3eef 4497 struct bgp_dest *dest;
d62a17ae 4498 struct bgp_adj_in *ain;
718e3744 4499
d62a17ae 4500 if (!table)
4501 table = peer->bgp->rib[afi][safi];
718e3744 4502
9bcb3eef
DS
4503 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4504 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4505 if (ain->peer != peer)
4506 continue;
8692c506 4507
d7d15889 4508 struct bgp_path_info *pi;
d7c0a89a 4509 uint32_t num_labels = 0;
b57ba6d2 4510 mpls_label_t *label_pnt = NULL;
8cb687c2 4511 struct bgp_route_evpn evpn;
b57ba6d2 4512
9bcb3eef 4513 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4514 pi = pi->next)
4515 if (pi->peer == peer)
4516 break;
4517
40381db7
DS
4518 if (pi && pi->extra)
4519 num_labels = pi->extra->num_labels;
b57ba6d2 4520 if (num_labels)
40381db7 4521 label_pnt = &pi->extra->label[0];
8cb687c2 4522 if (pi)
6c924775
DS
4523 memcpy(&evpn,
4524 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4525 sizeof(evpn));
4526 else
4527 memset(&evpn, 0, sizeof(evpn));
8692c506 4528
9bcb3eef
DS
4529 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4530 ain->addpath_rx_id, ain->attr, afi,
4531 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4532 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4533 num_labels, 1, &evpn);
ea47320b
DL
4534
4535 if (ret < 0) {
9bcb3eef 4536 bgp_dest_unlock_node(dest);
ea47320b 4537 return;
d62a17ae 4538 }
4539 }
718e3744 4540}
4541
d62a17ae 4542void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4543{
9bcb3eef 4544 struct bgp_dest *dest;
d62a17ae 4545 struct bgp_table *table;
718e3744 4546
d62a17ae 4547 if (peer->status != Established)
4548 return;
718e3744 4549
d62a17ae 4550 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4551 && (safi != SAFI_EVPN))
4552 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4553 else
9bcb3eef
DS
4554 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4555 dest = bgp_route_next(dest)) {
4556 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4557
b54892e0
DS
4558 if (table == NULL)
4559 continue;
8692c506 4560
9bcb3eef 4561 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4562 struct prefix_rd prd;
4563
4564 prd.family = AF_UNSPEC;
4565 prd.prefixlen = 64;
4566 memcpy(&prd.val, p->u.val, 8);
4567
4568 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4569 }
718e3744 4570}
6b0655a2 4571
228da428 4572
d62a17ae 4573struct bgp_clear_node_queue {
9bcb3eef 4574 struct bgp_dest *dest;
228da428
CC
4575};
4576
d62a17ae 4577static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4578{
d62a17ae 4579 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4580 struct bgp_dest *dest = cnq->dest;
d62a17ae 4581 struct peer *peer = wq->spec.data;
40381db7 4582 struct bgp_path_info *pi;
3103e8d2 4583 struct bgp *bgp;
9bcb3eef
DS
4584 afi_t afi = bgp_dest_table(dest)->afi;
4585 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4586
9bcb3eef 4587 assert(dest && peer);
3103e8d2 4588 bgp = peer->bgp;
d62a17ae 4589
4590 /* It is possible that we have multiple paths for a prefix from a peer
4591 * if that peer is using AddPath.
4592 */
9bcb3eef 4593 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4594 if (pi->peer != peer)
ea47320b
DL
4595 continue;
4596
4597 /* graceful restart STALE flag set. */
4598 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4599 && peer->nsf[afi][safi]
40381db7
DS
4600 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4601 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4602 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4603 else {
4604 /* If this is an EVPN route, process for
4605 * un-import. */
4606 if (safi == SAFI_EVPN)
9bcb3eef
DS
4607 bgp_evpn_unimport_route(
4608 bgp, afi, safi,
4609 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4610 /* Handle withdraw for VRF route-leaking and L3VPN */
4611 if (SAFI_UNICAST == safi
4612 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4613 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4614 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4615 bgp, pi);
960035b2 4616 }
3103e8d2 4617 if (SAFI_MPLS_VPN == safi &&
960035b2 4618 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4619 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4620 }
3103e8d2 4621
9bcb3eef 4622 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4623 }
ea47320b 4624 }
d62a17ae 4625 return WQ_SUCCESS;
200df115 4626}
4627
d62a17ae 4628static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4629{
d62a17ae 4630 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4631 struct bgp_dest *dest = cnq->dest;
4632 struct bgp_table *table = bgp_dest_table(dest);
228da428 4633
9bcb3eef 4634 bgp_dest_unlock_node(dest);
d62a17ae 4635 bgp_table_unlock(table);
4636 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4637}
4638
d62a17ae 4639static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4640{
d62a17ae 4641 struct peer *peer = wq->spec.data;
64e580a7 4642
d62a17ae 4643 /* Tickle FSM to start moving again */
4644 BGP_EVENT_ADD(peer, Clearing_Completed);
4645
4646 peer_unlock(peer); /* bgp_clear_route */
200df115 4647}
718e3744 4648
d62a17ae 4649static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4650{
d62a17ae 4651 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4652
4653 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4654#undef CLEAR_QUEUE_NAME_LEN
4655
0ce1ca80 4656 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4657 peer->clear_node_queue->spec.hold = 10;
4658 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4659 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4660 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4661 peer->clear_node_queue->spec.max_retries = 0;
4662
4663 /* we only 'lock' this peer reference when the queue is actually active
4664 */
4665 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4666}
4667
d62a17ae 4668static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4669 struct bgp_table *table)
65ca75e0 4670{
9bcb3eef 4671 struct bgp_dest *dest;
b6c386bb 4672 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4673
d62a17ae 4674 if (!table)
4675 table = peer->bgp->rib[afi][safi];
dc83d712 4676
d62a17ae 4677 /* If still no table => afi/safi isn't configured at all or smth. */
4678 if (!table)
4679 return;
dc83d712 4680
9bcb3eef 4681 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4682 struct bgp_path_info *pi, *next;
d62a17ae 4683 struct bgp_adj_in *ain;
4684 struct bgp_adj_in *ain_next;
4685
4686 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4687 * queued for every clearing peer, regardless of whether it is
4688 * relevant to the peer at hand.
4689 *
4690 * Overview: There are 3 different indices which need to be
4691 * scrubbed, potentially, when a peer is removed:
4692 *
4693 * 1 peer's routes visible via the RIB (ie accepted routes)
4694 * 2 peer's routes visible by the (optional) peer's adj-in index
4695 * 3 other routes visible by the peer's adj-out index
4696 *
4697 * 3 there is no hurry in scrubbing, once the struct peer is
4698 * removed from bgp->peer, we could just GC such deleted peer's
4699 * adj-outs at our leisure.
4700 *
4701 * 1 and 2 must be 'scrubbed' in some way, at least made
4702 * invisible via RIB index before peer session is allowed to be
4703 * brought back up. So one needs to know when such a 'search' is
4704 * complete.
4705 *
4706 * Ideally:
4707 *
4708 * - there'd be a single global queue or a single RIB walker
4709 * - rather than tracking which route_nodes still need to be
4710 * examined on a peer basis, we'd track which peers still
4711 * aren't cleared
4712 *
4713 * Given that our per-peer prefix-counts now should be reliable,
4714 * this may actually be achievable. It doesn't seem to be a huge
4715 * problem at this time,
4716 *
4717 * It is possible that we have multiple paths for a prefix from
4718 * a peer
4719 * if that peer is using AddPath.
4720 */
9bcb3eef 4721 ain = dest->adj_in;
d62a17ae 4722 while (ain) {
4723 ain_next = ain->next;
4724
4725 if (ain->peer == peer) {
9bcb3eef
DS
4726 bgp_adj_in_remove(dest, ain);
4727 bgp_dest_unlock_node(dest);
d62a17ae 4728 }
4729
4730 ain = ain_next;
4731 }
4732
9bcb3eef 4733 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4734 next = pi->next;
4735 if (pi->peer != peer)
d62a17ae 4736 continue;
4737
4738 if (force)
9bcb3eef 4739 bgp_path_info_reap(dest, pi);
d62a17ae 4740 else {
4741 struct bgp_clear_node_queue *cnq;
4742
4743 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4744 bgp_table_lock(bgp_dest_table(dest));
4745 bgp_dest_lock_node(dest);
d62a17ae 4746 cnq = XCALLOC(
4747 MTYPE_BGP_CLEAR_NODE_QUEUE,
4748 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4749 cnq->dest = dest;
d62a17ae 4750 work_queue_add(peer->clear_node_queue, cnq);
4751 break;
4752 }
4753 }
4754 }
4755 return;
4756}
4757
4758void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4759{
9bcb3eef 4760 struct bgp_dest *dest;
d62a17ae 4761 struct bgp_table *table;
4762
4763 if (peer->clear_node_queue == NULL)
4764 bgp_clear_node_queue_init(peer);
4765
4766 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4767 * Idle until it receives a Clearing_Completed event. This protects
4768 * against peers which flap faster than we can we clear, which could
4769 * lead to:
4770 *
4771 * a) race with routes from the new session being installed before
4772 * clear_route_node visits the node (to delete the route of that
4773 * peer)
4774 * b) resource exhaustion, clear_route_node likely leads to an entry
4775 * on the process_main queue. Fast-flapping could cause that queue
4776 * to grow and grow.
4777 */
4778
4779 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4780 * the unlock will happen upon work-queue completion; other wise, the
4781 * unlock happens at the end of this function.
4782 */
4783 if (!peer->clear_node_queue->thread)
4784 peer_lock(peer);
4785
4786 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4787 bgp_clear_route_table(peer, afi, safi, NULL);
4788 else
9bcb3eef
DS
4789 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4790 dest = bgp_route_next(dest)) {
4791 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4792 if (!table)
4793 continue;
4794
4795 bgp_clear_route_table(peer, afi, safi, table);
4796 }
d62a17ae 4797
4798 /* unlock if no nodes got added to the clear-node-queue. */
4799 if (!peer->clear_node_queue->thread)
4800 peer_unlock(peer);
718e3744 4801}
d62a17ae 4802
4803void bgp_clear_route_all(struct peer *peer)
718e3744 4804{
d62a17ae 4805 afi_t afi;
4806 safi_t safi;
718e3744 4807
05c7a1cc
QY
4808 FOREACH_AFI_SAFI (afi, safi)
4809 bgp_clear_route(peer, afi, safi);
65efcfce 4810
49e5a4a0 4811#ifdef ENABLE_BGP_VNC
d62a17ae 4812 rfapiProcessPeerDown(peer);
65efcfce 4813#endif
718e3744 4814}
4815
d62a17ae 4816void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4817{
d62a17ae 4818 struct bgp_table *table;
9bcb3eef 4819 struct bgp_dest *dest;
d62a17ae 4820 struct bgp_adj_in *ain;
4821 struct bgp_adj_in *ain_next;
718e3744 4822
d62a17ae 4823 table = peer->bgp->rib[afi][safi];
718e3744 4824
d62a17ae 4825 /* It is possible that we have multiple paths for a prefix from a peer
4826 * if that peer is using AddPath.
4827 */
9bcb3eef
DS
4828 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4829 ain = dest->adj_in;
43143c8f 4830
d62a17ae 4831 while (ain) {
4832 ain_next = ain->next;
43143c8f 4833
d62a17ae 4834 if (ain->peer == peer) {
9bcb3eef
DS
4835 bgp_adj_in_remove(dest, ain);
4836 bgp_dest_unlock_node(dest);
d62a17ae 4837 }
43143c8f 4838
d62a17ae 4839 ain = ain_next;
4840 }
4841 }
718e3744 4842}
93406d87 4843
d62a17ae 4844void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4845{
9bcb3eef 4846 struct bgp_dest *dest;
40381db7 4847 struct bgp_path_info *pi;
d62a17ae 4848 struct bgp_table *table;
4849
4850 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4851 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4852 dest = bgp_route_next(dest)) {
4853 struct bgp_dest *rm;
d62a17ae 4854
4855 /* look for neighbor in tables */
9bcb3eef 4856 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4857 if (!table)
ea47320b
DL
4858 continue;
4859
4860 for (rm = bgp_table_top(table); rm;
4861 rm = bgp_route_next(rm))
9bcb3eef 4862 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4863 pi = pi->next) {
40381db7 4864 if (pi->peer != peer)
ea47320b 4865 continue;
40381db7 4866 if (!CHECK_FLAG(pi->flags,
1defdda8 4867 BGP_PATH_STALE))
ea47320b
DL
4868 break;
4869
40381db7 4870 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4871 break;
4872 }
d62a17ae 4873 }
4874 } else {
9bcb3eef
DS
4875 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4876 dest = bgp_route_next(dest))
4877 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4878 pi = pi->next) {
40381db7 4879 if (pi->peer != peer)
ea47320b 4880 continue;
40381db7 4881 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4882 break;
9bcb3eef 4883 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4884 break;
4885 }
d62a17ae 4886 }
93406d87 4887}
6b0655a2 4888
3dc339cd 4889bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4890{
e0df4c04 4891 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4892 return true;
e0df4c04 4893
9dac9fc8
DA
4894 if (peer->sort == BGP_PEER_EBGP
4895 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4896 || FILTER_LIST_OUT_NAME(filter)
4897 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4898 return true;
4899 return false;
9dac9fc8
DA
4900}
4901
3dc339cd 4902bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4903{
e0df4c04 4904 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4905 return true;
e0df4c04 4906
9dac9fc8
DA
4907 if (peer->sort == BGP_PEER_EBGP
4908 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4909 || FILTER_LIST_IN_NAME(filter)
4910 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4911 return true;
4912 return false;
9dac9fc8
DA
4913}
4914
568e10ca 4915static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4916 safi_t safi)
bb86c601 4917{
9bcb3eef 4918 struct bgp_dest *dest;
40381db7 4919 struct bgp_path_info *pi;
4b7e6066 4920 struct bgp_path_info *next;
bb86c601 4921
9bcb3eef
DS
4922 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4923 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4924 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4925
40381db7 4926 next = pi->next;
1b7bb747
CS
4927
4928 /* Unimport EVPN routes from VRFs */
4929 if (safi == SAFI_EVPN)
4930 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4931 SAFI_EVPN, p, pi);
1b7bb747 4932
40381db7
DS
4933 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4934 && pi->type == ZEBRA_ROUTE_BGP
4935 && (pi->sub_type == BGP_ROUTE_NORMAL
4936 || pi->sub_type == BGP_ROUTE_AGGREGATE
4937 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4938
d62a17ae 4939 if (bgp_fibupd_safi(safi))
b54892e0 4940 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4941 }
9514b37d 4942
9bcb3eef 4943 bgp_path_info_reap(dest, pi);
d62a17ae 4944 }
bb86c601
LB
4945}
4946
718e3744 4947/* Delete all kernel routes. */
d62a17ae 4948void bgp_cleanup_routes(struct bgp *bgp)
4949{
4950 afi_t afi;
9bcb3eef 4951 struct bgp_dest *dest;
67009e22 4952 struct bgp_table *table;
d62a17ae 4953
4954 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4955 if (afi == AFI_L2VPN)
4956 continue;
568e10ca 4957 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4958 SAFI_UNICAST);
d62a17ae 4959 /*
4960 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4961 */
4962 if (afi != AFI_L2VPN) {
4963 safi_t safi;
4964 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4965 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4966 dest = bgp_route_next(dest)) {
4967 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4968 if (table != NULL) {
4969 bgp_cleanup_table(bgp, table, safi);
4970 bgp_table_finish(&table);
9bcb3eef
DS
4971 bgp_dest_set_bgp_table_info(dest, NULL);
4972 bgp_dest_unlock_node(dest);
d62a17ae 4973 }
4974 }
4975 safi = SAFI_ENCAP;
9bcb3eef
DS
4976 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4977 dest = bgp_route_next(dest)) {
4978 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4979 if (table != NULL) {
4980 bgp_cleanup_table(bgp, table, safi);
4981 bgp_table_finish(&table);
9bcb3eef
DS
4982 bgp_dest_set_bgp_table_info(dest, NULL);
4983 bgp_dest_unlock_node(dest);
d62a17ae 4984 }
4985 }
4986 }
4987 }
9bcb3eef
DS
4988 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4989 dest = bgp_route_next(dest)) {
4990 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4991 if (table != NULL) {
4992 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4993 bgp_table_finish(&table);
9bcb3eef
DS
4994 bgp_dest_set_bgp_table_info(dest, NULL);
4995 bgp_dest_unlock_node(dest);
d62a17ae 4996 }
bb86c601 4997 }
718e3744 4998}
4999
d62a17ae 5000void bgp_reset(void)
718e3744 5001{
d62a17ae 5002 vty_reset();
5003 bgp_zclient_reset();
5004 access_list_reset();
5005 prefix_list_reset();
718e3744 5006}
6b0655a2 5007
d62a17ae 5008static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5009{
d62a17ae 5010 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5011 && CHECK_FLAG(peer->af_cap[afi][safi],
5012 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5013}
5014
718e3744 5015/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5016 value. */
d62a17ae 5017int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5018 struct bgp_nlri *packet)
5019{
d7c0a89a
QY
5020 uint8_t *pnt;
5021 uint8_t *lim;
d62a17ae 5022 struct prefix p;
5023 int psize;
5024 int ret;
5025 afi_t afi;
5026 safi_t safi;
5027 int addpath_encoded;
d7c0a89a 5028 uint32_t addpath_id;
d62a17ae 5029
d62a17ae 5030 pnt = packet->nlri;
5031 lim = pnt + packet->length;
5032 afi = packet->afi;
5033 safi = packet->safi;
5034 addpath_id = 0;
5035 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5036
5037 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5038 syntactic validity. If the field is syntactically incorrect,
5039 then the Error Subcode is set to Invalid Network Field. */
5040 for (; pnt < lim; pnt += psize) {
5041 /* Clear prefix structure. */
5042 memset(&p, 0, sizeof(struct prefix));
5043
5044 if (addpath_encoded) {
5045
5046 /* When packet overflow occurs return immediately. */
761ed665 5047 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5048 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5049
a3a850a1 5050 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5051 addpath_id = ntohl(addpath_id);
d62a17ae 5052 pnt += BGP_ADDPATH_ID_LEN;
5053 }
718e3744 5054
d62a17ae 5055 /* Fetch prefix length. */
5056 p.prefixlen = *pnt++;
5057 /* afi/safi validity already verified by caller,
5058 * bgp_update_receive */
5059 p.family = afi2family(afi);
5060
5061 /* Prefix length check. */
5062 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5063 flog_err(
e50f7cfd 5064 EC_BGP_UPDATE_RCV,
14454c9f 5065 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5066 peer->host, p.prefixlen, packet->afi);
513386b5 5067 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5068 }
6b0655a2 5069
d62a17ae 5070 /* Packet size overflow check. */
5071 psize = PSIZE(p.prefixlen);
5072
5073 /* When packet overflow occur return immediately. */
5074 if (pnt + psize > lim) {
af4c2728 5075 flog_err(
e50f7cfd 5076 EC_BGP_UPDATE_RCV,
d62a17ae 5077 "%s [Error] Update packet error (prefix length %d overflows packet)",
5078 peer->host, p.prefixlen);
513386b5 5079 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5080 }
5081
5082 /* Defensive coding, double-check the psize fits in a struct
5083 * prefix */
5084 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5085 flog_err(
e50f7cfd 5086 EC_BGP_UPDATE_RCV,
d62a17ae 5087 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5088 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5089 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5090 }
5091
5092 /* Fetch prefix from NLRI packet. */
a85297a7 5093 memcpy(p.u.val, pnt, psize);
d62a17ae 5094
5095 /* Check address. */
5096 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5097 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5098 /* From RFC4271 Section 6.3:
5099 *
5100 * If a prefix in the NLRI field is semantically
5101 * incorrect
5102 * (e.g., an unexpected multicast IP address),
5103 * an error SHOULD
5104 * be logged locally, and the prefix SHOULD be
5105 * ignored.
a4d82a8a 5106 */
af4c2728 5107 flog_err(
e50f7cfd 5108 EC_BGP_UPDATE_RCV,
23d0a753
DA
5109 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5110 peer->host, &p.u.prefix4);
d62a17ae 5111 continue;
5112 }
5113 }
5114
5115 /* Check address. */
5116 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5117 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5118 char buf[BUFSIZ];
5119
af4c2728 5120 flog_err(
e50f7cfd 5121 EC_BGP_UPDATE_RCV,
d62a17ae 5122 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5123 peer->host,
5124 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5125 BUFSIZ));
5126
5127 continue;
5128 }
5129 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5130 char buf[BUFSIZ];
5131
af4c2728 5132 flog_err(
e50f7cfd 5133 EC_BGP_UPDATE_RCV,
d62a17ae 5134 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5135 peer->host,
5136 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5137 BUFSIZ));
5138
5139 continue;
5140 }
5141 }
5142
5143 /* Normal process. */
5144 if (attr)
5145 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5146 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5147 NULL, NULL, 0, 0, NULL);
d62a17ae 5148 else
5149 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5150 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5151 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5152 NULL);
d62a17ae 5153
513386b5
DA
5154 /* Do not send BGP notification twice when maximum-prefix count
5155 * overflow. */
5156 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5157 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5158
5159 /* Address family configuration mismatch. */
d62a17ae 5160 if (ret < 0)
513386b5 5161 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5162 }
5163
5164 /* Packet length consistency check. */
5165 if (pnt != lim) {
af4c2728 5166 flog_err(
e50f7cfd 5167 EC_BGP_UPDATE_RCV,
d62a17ae 5168 "%s [Error] Update packet error (prefix length mismatch with total length)",
5169 peer->host);
513386b5 5170 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5171 }
6b0655a2 5172
513386b5 5173 return BGP_NLRI_PARSE_OK;
718e3744 5174}
5175
d62a17ae 5176static struct bgp_static *bgp_static_new(void)
718e3744 5177{
d62a17ae 5178 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5179}
5180
d62a17ae 5181static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5182{
0a22ddfb 5183 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5184 route_map_counter_decrement(bgp_static->rmap.map);
5185
0a22ddfb 5186 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5187 XFREE(MTYPE_BGP_STATIC, bgp_static);
5188}
5189
5f040085 5190void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5191 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5192{
9bcb3eef 5193 struct bgp_dest *dest;
40381db7 5194 struct bgp_path_info *pi;
4b7e6066 5195 struct bgp_path_info *new;
40381db7 5196 struct bgp_path_info rmap_path;
d62a17ae 5197 struct attr attr;
5198 struct attr *attr_new;
b68885f9 5199 route_map_result_t ret;
49e5a4a0 5200#ifdef ENABLE_BGP_VNC
d62a17ae 5201 int vnc_implicit_withdraw = 0;
65efcfce 5202#endif
fee0f4c6 5203
d62a17ae 5204 assert(bgp_static);
dd8103a9 5205
9bcb3eef 5206 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5207
d62a17ae 5208 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5209
d62a17ae 5210 attr.nexthop = bgp_static->igpnexthop;
5211 attr.med = bgp_static->igpmetric;
5212 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5213
d62a17ae 5214 if (bgp_static->atomic)
5215 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5216
d62a17ae 5217 /* Store label index, if required. */
5218 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5219 attr.label_index = bgp_static->label_index;
5220 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5221 }
718e3744 5222
d62a17ae 5223 /* Apply route-map. */
5224 if (bgp_static->rmap.name) {
5225 struct attr attr_tmp = attr;
80ced710 5226
40381db7
DS
5227 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5228 rmap_path.peer = bgp->peer_self;
5229 rmap_path.attr = &attr_tmp;
fee0f4c6 5230
d62a17ae 5231 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5232
1782514f 5233 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5234
d62a17ae 5235 bgp->peer_self->rmap_type = 0;
718e3744 5236
d62a17ae 5237 if (ret == RMAP_DENYMATCH) {
5238 /* Free uninterned attribute. */
5239 bgp_attr_flush(&attr_tmp);
718e3744 5240
d62a17ae 5241 /* Unintern original. */
5242 aspath_unintern(&attr.aspath);
5243 bgp_static_withdraw(bgp, p, afi, safi);
5244 return;
5245 }
7f323236 5246
637e5ba4 5247 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5248 bgp_attr_add_gshut_community(&attr_tmp);
5249
d62a17ae 5250 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5251 } else {
5252
637e5ba4 5253 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5254 bgp_attr_add_gshut_community(&attr);
5255
d62a17ae 5256 attr_new = bgp_attr_intern(&attr);
7f323236 5257 }
718e3744 5258
9bcb3eef 5259 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5260 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5261 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5262 break;
5263
40381db7
DS
5264 if (pi) {
5265 if (attrhash_cmp(pi->attr, attr_new)
5266 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5267 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5268 bgp_dest_unlock_node(dest);
d62a17ae 5269 bgp_attr_unintern(&attr_new);
5270 aspath_unintern(&attr.aspath);
5271 return;
5272 } else {
5273 /* The attribute is changed. */
9bcb3eef 5274 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5275
5276 /* Rewrite BGP route information. */
40381db7 5277 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5278 bgp_path_info_restore(dest, pi);
d62a17ae 5279 else
40381db7 5280 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5281#ifdef ENABLE_BGP_VNC
d62a17ae 5282 if ((afi == AFI_IP || afi == AFI_IP6)
5283 && (safi == SAFI_UNICAST)) {
40381db7 5284 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5285 /*
5286 * Implicit withdraw case.
40381db7 5287 * We have to do this before pi is
d62a17ae 5288 * changed
5289 */
5290 ++vnc_implicit_withdraw;
40381db7 5291 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5292 vnc_import_bgp_exterior_del_route(
40381db7 5293 bgp, p, pi);
d62a17ae 5294 }
5295 }
65efcfce 5296#endif
40381db7
DS
5297 bgp_attr_unintern(&pi->attr);
5298 pi->attr = attr_new;
5299 pi->uptime = bgp_clock();
49e5a4a0 5300#ifdef ENABLE_BGP_VNC
d62a17ae 5301 if ((afi == AFI_IP || afi == AFI_IP6)
5302 && (safi == SAFI_UNICAST)) {
5303 if (vnc_implicit_withdraw) {
40381db7 5304 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5305 vnc_import_bgp_exterior_add_route(
40381db7 5306 bgp, p, pi);
d62a17ae 5307 }
5308 }
65efcfce 5309#endif
718e3744 5310
d62a17ae 5311 /* Nexthop reachability check. */
892fedb6 5312 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5313 && (safi == SAFI_UNICAST
5314 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5315
5316 struct bgp *bgp_nexthop = bgp;
5317
40381db7
DS
5318 if (pi->extra && pi->extra->bgp_orig)
5319 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5320
5321 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5322 afi, pi, NULL, 0))
9bcb3eef 5323 bgp_path_info_set_flag(dest, pi,
18ee8310 5324 BGP_PATH_VALID);
d62a17ae 5325 else {
5326 if (BGP_DEBUG(nht, NHT)) {
5327 char buf1[INET6_ADDRSTRLEN];
5328 inet_ntop(p->family,
5329 &p->u.prefix, buf1,
5330 INET6_ADDRSTRLEN);
5331 zlog_debug(
5332 "%s(%s): Route not in table, not advertising",
15569c58 5333 __func__, buf1);
d62a17ae 5334 }
18ee8310 5335 bgp_path_info_unset_flag(
9bcb3eef 5336 dest, pi, BGP_PATH_VALID);
d62a17ae 5337 }
5338 } else {
5339 /* Delete the NHT structure if any, if we're
5340 * toggling between
5341 * enabling/disabling import check. We
5342 * deregister the route
5343 * from NHT to avoid overloading NHT and the
5344 * process interaction
5345 */
40381db7 5346 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5347 bgp_path_info_set_flag(dest, pi,
5348 BGP_PATH_VALID);
d62a17ae 5349 }
5350 /* Process change. */
40381db7 5351 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5352 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5353
5354 if (SAFI_UNICAST == safi
5355 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5356 || bgp->inst_type
5357 == BGP_INSTANCE_TYPE_DEFAULT)) {
5358 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5359 pi);
ddb5b488
PZ
5360 }
5361
9bcb3eef 5362 bgp_dest_unlock_node(dest);
d62a17ae 5363 aspath_unintern(&attr.aspath);
5364 return;
5365 }
718e3744 5366 }
718e3744 5367
d62a17ae 5368 /* Make new BGP info. */
5369 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5370 attr_new, dest);
d62a17ae 5371 /* Nexthop reachability check. */
892fedb6 5372 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5373 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5374 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5375 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5376 else {
5377 if (BGP_DEBUG(nht, NHT)) {
5378 char buf1[INET6_ADDRSTRLEN];
5379 inet_ntop(p->family, &p->u.prefix, buf1,
5380 INET6_ADDRSTRLEN);
5381 zlog_debug(
5382 "%s(%s): Route not in table, not advertising",
15569c58 5383 __func__, buf1);
d62a17ae 5384 }
9bcb3eef 5385 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5386 }
5387 } else {
5388 /* Delete the NHT structure if any, if we're toggling between
5389 * enabling/disabling import check. We deregister the route
5390 * from NHT to avoid overloading NHT and the process interaction
5391 */
5392 bgp_unlink_nexthop(new);
5393
9bcb3eef 5394 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5395 }
078430f6 5396
d62a17ae 5397 /* Aggregate address increment. */
5398 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5399
d62a17ae 5400 /* Register new BGP information. */
9bcb3eef 5401 bgp_path_info_add(dest, new);
718e3744 5402
d62a17ae 5403 /* route_node_get lock */
9bcb3eef 5404 bgp_dest_unlock_node(dest);
d62a17ae 5405
5406 /* Process change. */
9bcb3eef 5407 bgp_process(bgp, dest, afi, safi);
d62a17ae 5408
ddb5b488
PZ
5409 if (SAFI_UNICAST == safi
5410 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5411 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5412 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5413 }
5414
d62a17ae 5415 /* Unintern original. */
5416 aspath_unintern(&attr.aspath);
718e3744 5417}
5418
5f040085 5419void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5420 safi_t safi)
718e3744 5421{
9bcb3eef 5422 struct bgp_dest *dest;
40381db7 5423 struct bgp_path_info *pi;
718e3744 5424
9bcb3eef 5425 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5426
d62a17ae 5427 /* Check selected route and self inserted route. */
9bcb3eef 5428 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5429 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5430 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5431 break;
5432
5433 /* Withdraw static BGP route from routing table. */
40381db7 5434 if (pi) {
ddb5b488
PZ
5435 if (SAFI_UNICAST == safi
5436 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5437 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5438 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5439 }
40381db7
DS
5440 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5441 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5442 bgp_path_info_delete(dest, pi);
5443 bgp_process(bgp, dest, afi, safi);
d62a17ae 5444 }
718e3744 5445
d62a17ae 5446 /* Unlock bgp_node_lookup. */
9bcb3eef 5447 bgp_dest_unlock_node(dest);
718e3744 5448}
5449
137446f9
LB
5450/*
5451 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5452 */
5f040085 5453static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5454 afi_t afi, safi_t safi,
5455 struct prefix_rd *prd)
718e3744 5456{
9bcb3eef 5457 struct bgp_dest *dest;
40381db7 5458 struct bgp_path_info *pi;
718e3744 5459
9bcb3eef 5460 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5461
d62a17ae 5462 /* Check selected route and self inserted route. */
9bcb3eef 5463 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5464 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5465 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5466 break;
718e3744 5467
d62a17ae 5468 /* Withdraw static BGP route from routing table. */
40381db7 5469 if (pi) {
49e5a4a0 5470#ifdef ENABLE_BGP_VNC
d62a17ae 5471 rfapiProcessWithdraw(
40381db7 5472 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5473 1); /* Kill, since it is an administrative change */
65efcfce 5474#endif
ddb5b488
PZ
5475 if (SAFI_MPLS_VPN == safi
5476 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5477 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5478 }
40381db7 5479 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5480 bgp_path_info_delete(dest, pi);
5481 bgp_process(bgp, dest, afi, safi);
d62a17ae 5482 }
718e3744 5483
d62a17ae 5484 /* Unlock bgp_node_lookup. */
9bcb3eef 5485 bgp_dest_unlock_node(dest);
718e3744 5486}
5487
5f040085 5488static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5489 struct bgp_static *bgp_static, afi_t afi,
5490 safi_t safi)
137446f9 5491{
9bcb3eef 5492 struct bgp_dest *dest;
4b7e6066 5493 struct bgp_path_info *new;
d62a17ae 5494 struct attr *attr_new;
5495 struct attr attr = {0};
40381db7 5496 struct bgp_path_info *pi;
49e5a4a0 5497#ifdef ENABLE_BGP_VNC
d62a17ae 5498 mpls_label_t label = 0;
65efcfce 5499#endif
d7c0a89a 5500 uint32_t num_labels = 0;
d62a17ae 5501 union gw_addr add;
137446f9 5502
d62a17ae 5503 assert(bgp_static);
137446f9 5504
b57ba6d2
MK
5505 if (bgp_static->label != MPLS_INVALID_LABEL)
5506 num_labels = 1;
9bcb3eef
DS
5507 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5508 &bgp_static->prd);
137446f9 5509
d62a17ae 5510 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5511
d62a17ae 5512 attr.nexthop = bgp_static->igpnexthop;
5513 attr.med = bgp_static->igpmetric;
5514 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5515
d62a17ae 5516 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5517 || (safi == SAFI_ENCAP)) {
5518 if (afi == AFI_IP) {
5519 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5520 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5521 }
5522 }
5523 if (afi == AFI_L2VPN) {
5524 if (bgp_static->gatewayIp.family == AF_INET)
5525 add.ipv4.s_addr =
5526 bgp_static->gatewayIp.u.prefix4.s_addr;
5527 else if (bgp_static->gatewayIp.family == AF_INET6)
5528 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5529 sizeof(struct in6_addr));
0a50c248 5530 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5531 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5532 struct bgp_encap_type_vxlan bet;
5533 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5534 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5535 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5536 }
5537 if (bgp_static->router_mac) {
5538 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5539 }
5540 }
5541 /* Apply route-map. */
5542 if (bgp_static->rmap.name) {
5543 struct attr attr_tmp = attr;
40381db7 5544 struct bgp_path_info rmap_path;
b68885f9 5545 route_map_result_t ret;
137446f9 5546
40381db7
DS
5547 rmap_path.peer = bgp->peer_self;
5548 rmap_path.attr = &attr_tmp;
137446f9 5549
d62a17ae 5550 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5551
1782514f 5552 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5553
d62a17ae 5554 bgp->peer_self->rmap_type = 0;
137446f9 5555
d62a17ae 5556 if (ret == RMAP_DENYMATCH) {
5557 /* Free uninterned attribute. */
5558 bgp_attr_flush(&attr_tmp);
137446f9 5559
d62a17ae 5560 /* Unintern original. */
5561 aspath_unintern(&attr.aspath);
5562 bgp_static_withdraw_safi(bgp, p, afi, safi,
5563 &bgp_static->prd);
5564 return;
5565 }
137446f9 5566
d62a17ae 5567 attr_new = bgp_attr_intern(&attr_tmp);
5568 } else {
5569 attr_new = bgp_attr_intern(&attr);
5570 }
137446f9 5571
9bcb3eef 5572 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5573 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5574 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5575 break;
5576
40381db7 5577 if (pi) {
d62a17ae 5578 memset(&add, 0, sizeof(union gw_addr));
40381db7 5579 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5580 && overlay_index_equal(afi, pi, &add)
40381db7 5581 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5582 bgp_dest_unlock_node(dest);
d62a17ae 5583 bgp_attr_unintern(&attr_new);
5584 aspath_unintern(&attr.aspath);
5585 return;
5586 } else {
5587 /* The attribute is changed. */
9bcb3eef 5588 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5589
5590 /* Rewrite BGP route information. */
40381db7 5591 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5592 bgp_path_info_restore(dest, pi);
d62a17ae 5593 else
40381db7
DS
5594 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5595 bgp_attr_unintern(&pi->attr);
5596 pi->attr = attr_new;
5597 pi->uptime = bgp_clock();
49e5a4a0 5598#ifdef ENABLE_BGP_VNC
40381db7
DS
5599 if (pi->extra)
5600 label = decode_label(&pi->extra->label[0]);
65efcfce 5601#endif
137446f9 5602
d62a17ae 5603 /* Process change. */
40381db7 5604 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5605 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5606
5607 if (SAFI_MPLS_VPN == safi
5608 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5609 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5610 }
49e5a4a0 5611#ifdef ENABLE_BGP_VNC
40381db7
DS
5612 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5613 pi->attr, afi, safi, pi->type,
5614 pi->sub_type, &label);
65efcfce 5615#endif
9bcb3eef 5616 bgp_dest_unlock_node(dest);
d62a17ae 5617 aspath_unintern(&attr.aspath);
5618 return;
5619 }
5620 }
137446f9
LB
5621
5622
d62a17ae 5623 /* Make new BGP info. */
5624 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5625 attr_new, dest);
1defdda8 5626 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5627 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5628 if (num_labels) {
5629 new->extra->label[0] = bgp_static->label;
5630 new->extra->num_labels = num_labels;
5631 }
49e5a4a0 5632#ifdef ENABLE_BGP_VNC
d62a17ae 5633 label = decode_label(&bgp_static->label);
65efcfce 5634#endif
137446f9 5635
d62a17ae 5636 /* Aggregate address increment. */
5637 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5638
d62a17ae 5639 /* Register new BGP information. */
9bcb3eef 5640 bgp_path_info_add(dest, new);
d62a17ae 5641 /* route_node_get lock */
9bcb3eef 5642 bgp_dest_unlock_node(dest);
137446f9 5643
d62a17ae 5644 /* Process change. */
9bcb3eef 5645 bgp_process(bgp, dest, afi, safi);
137446f9 5646
ddb5b488
PZ
5647 if (SAFI_MPLS_VPN == safi
5648 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5649 vpn_leak_to_vrf_update(bgp, new);
5650 }
49e5a4a0 5651#ifdef ENABLE_BGP_VNC
d62a17ae 5652 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5653 safi, new->type, new->sub_type, &label);
65efcfce
LB
5654#endif
5655
d62a17ae 5656 /* Unintern original. */
5657 aspath_unintern(&attr.aspath);
137446f9
LB
5658}
5659
718e3744 5660/* Configure static BGP network. When user don't run zebra, static
5661 route should be installed as valid. */
37a87b8f
CS
5662int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5663 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5664 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5665{
d62a17ae 5666 struct prefix p;
5667 struct bgp_static *bgp_static;
9bcb3eef 5668 struct bgp_dest *dest;
d7c0a89a 5669 uint8_t need_update = 0;
d62a17ae 5670
37a87b8f 5671 prefix_copy(&p, pfx);
d62a17ae 5672 apply_mask(&p);
718e3744 5673
e2a86ad9 5674 if (negate) {
718e3744 5675
e2a86ad9 5676 /* Set BGP static route configuration. */
9bcb3eef 5677 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5678
9bcb3eef 5679 if (!dest) {
37a87b8f
CS
5680 snprintf(errmsg, errmsg_len,
5681 "Can't find static route specified\n");
5682 return -1;
d62a17ae 5683 }
5684
9bcb3eef 5685 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5686
e2a86ad9
DS
5687 if ((label_index != BGP_INVALID_LABEL_INDEX)
5688 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5689 snprintf(errmsg, errmsg_len,
5690 "label-index doesn't match static route\n");
5691 return -1;
d62a17ae 5692 }
d62a17ae 5693
e2a86ad9
DS
5694 if ((rmap && bgp_static->rmap.name)
5695 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5696 snprintf(errmsg, errmsg_len,
5697 "route-map name doesn't match static route\n");
5698 return -1;
d62a17ae 5699 }
718e3744 5700
e2a86ad9
DS
5701 /* Update BGP RIB. */
5702 if (!bgp_static->backdoor)
5703 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5704
e2a86ad9
DS
5705 /* Clear configuration. */
5706 bgp_static_free(bgp_static);
9bcb3eef
DS
5707 bgp_dest_set_bgp_static_info(dest, NULL);
5708 bgp_dest_unlock_node(dest);
5709 bgp_dest_unlock_node(dest);
e2a86ad9 5710 } else {
718e3744 5711
e2a86ad9 5712 /* Set BGP static route configuration. */
9bcb3eef
DS
5713 dest = bgp_node_get(bgp->route[afi][safi], &p);
5714 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5715 if (bgp_static) {
e2a86ad9 5716 /* Configuration change. */
e2a86ad9
DS
5717 /* Label index cannot be changed. */
5718 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5719 snprintf(errmsg, errmsg_len,
5720 "cannot change label-index\n");
5721 return -1;
e2a86ad9 5722 }
d62a17ae 5723
e2a86ad9 5724 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5725 if (bgp_static->valid
5726 && bgp_static->backdoor != backdoor)
e2a86ad9 5727 need_update = 1;
718e3744 5728
e2a86ad9 5729 bgp_static->backdoor = backdoor;
718e3744 5730
e2a86ad9 5731 if (rmap) {
0a22ddfb
QY
5732 XFREE(MTYPE_ROUTE_MAP_NAME,
5733 bgp_static->rmap.name);
b4897fa5 5734 route_map_counter_decrement(
5735 bgp_static->rmap.map);
e2a86ad9
DS
5736 bgp_static->rmap.name =
5737 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5738 bgp_static->rmap.map =
5739 route_map_lookup_by_name(rmap);
b4897fa5 5740 route_map_counter_increment(
5741 bgp_static->rmap.map);
e2a86ad9 5742 } else {
0a22ddfb
QY
5743 XFREE(MTYPE_ROUTE_MAP_NAME,
5744 bgp_static->rmap.name);
b4897fa5 5745 route_map_counter_decrement(
5746 bgp_static->rmap.map);
e2a86ad9
DS
5747 bgp_static->rmap.map = NULL;
5748 bgp_static->valid = 0;
5749 }
9bcb3eef 5750 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5751 } else {
5752 /* New configuration. */
5753 bgp_static = bgp_static_new();
5754 bgp_static->backdoor = backdoor;
5755 bgp_static->valid = 0;
5756 bgp_static->igpmetric = 0;
975a328e 5757 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5758 bgp_static->label_index = label_index;
718e3744 5759
e2a86ad9 5760 if (rmap) {
0a22ddfb
QY
5761 XFREE(MTYPE_ROUTE_MAP_NAME,
5762 bgp_static->rmap.name);
b4897fa5 5763 route_map_counter_decrement(
5764 bgp_static->rmap.map);
e2a86ad9
DS
5765 bgp_static->rmap.name =
5766 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5767 bgp_static->rmap.map =
5768 route_map_lookup_by_name(rmap);
b4897fa5 5769 route_map_counter_increment(
5770 bgp_static->rmap.map);
e2a86ad9 5771 }
9bcb3eef 5772 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5773 }
d62a17ae 5774
e2a86ad9
DS
5775 bgp_static->valid = 1;
5776 if (need_update)
5777 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5778
e2a86ad9
DS
5779 if (!bgp_static->backdoor)
5780 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5781 }
d62a17ae 5782
37a87b8f 5783 return 0;
d62a17ae 5784}
5785
5786void bgp_static_add(struct bgp *bgp)
5787{
5788 afi_t afi;
5789 safi_t safi;
9bcb3eef
DS
5790 struct bgp_dest *dest;
5791 struct bgp_dest *rm;
d62a17ae 5792 struct bgp_table *table;
5793 struct bgp_static *bgp_static;
5794
05c7a1cc 5795 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5796 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5797 dest = bgp_route_next(dest)) {
5798 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5799 continue;
ea47320b 5800
05c7a1cc
QY
5801 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5802 || (safi == SAFI_EVPN)) {
9bcb3eef 5803 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5804
5805 for (rm = bgp_table_top(table); rm;
5806 rm = bgp_route_next(rm)) {
a78beeb5 5807 bgp_static =
9bcb3eef 5808 bgp_dest_get_bgp_static_info(
5a8ba9fc 5809 rm);
9bcb3eef
DS
5810 bgp_static_update_safi(
5811 bgp, bgp_dest_get_prefix(rm),
5812 bgp_static, afi, safi);
d62a17ae 5813 }
05c7a1cc 5814 } else {
5a8ba9fc 5815 bgp_static_update(
9bcb3eef
DS
5816 bgp, bgp_dest_get_prefix(dest),
5817 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5818 safi);
ea47320b 5819 }
05c7a1cc 5820 }
6aeb9e78
DS
5821}
5822
718e3744 5823/* Called from bgp_delete(). Delete all static routes from the BGP
5824 instance. */
d62a17ae 5825void bgp_static_delete(struct bgp *bgp)
5826{
5827 afi_t afi;
5828 safi_t safi;
9bcb3eef
DS
5829 struct bgp_dest *dest;
5830 struct bgp_dest *rm;
d62a17ae 5831 struct bgp_table *table;
5832 struct bgp_static *bgp_static;
5833
05c7a1cc 5834 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5835 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5836 dest = bgp_route_next(dest)) {
5837 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5838 continue;
ea47320b 5839
05c7a1cc
QY
5840 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5841 || (safi == SAFI_EVPN)) {
9bcb3eef 5842 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5843
5844 for (rm = bgp_table_top(table); rm;
5845 rm = bgp_route_next(rm)) {
a78beeb5 5846 bgp_static =
9bcb3eef 5847 bgp_dest_get_bgp_static_info(
5a8ba9fc 5848 rm);
c7d14ba6
PG
5849 if (!bgp_static)
5850 continue;
5851
05c7a1cc 5852 bgp_static_withdraw_safi(
9bcb3eef 5853 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5854 AFI_IP, safi,
5855 (struct prefix_rd *)
9bcb3eef
DS
5856 bgp_dest_get_prefix(
5857 dest));
ea47320b 5858 bgp_static_free(bgp_static);
811c6797 5859 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5860 NULL);
811c6797 5861 bgp_dest_unlock_node(rm);
d62a17ae 5862 }
05c7a1cc 5863 } else {
9bcb3eef 5864 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5865 bgp_static_withdraw(bgp,
9bcb3eef 5866 bgp_dest_get_prefix(dest),
b54892e0 5867 afi, safi);
05c7a1cc 5868 bgp_static_free(bgp_static);
9bcb3eef
DS
5869 bgp_dest_set_bgp_static_info(dest, NULL);
5870 bgp_dest_unlock_node(dest);
ea47320b 5871 }
05c7a1cc 5872 }
d62a17ae 5873}
5874
5875void bgp_static_redo_import_check(struct bgp *bgp)
5876{
5877 afi_t afi;
5878 safi_t safi;
9bcb3eef
DS
5879 struct bgp_dest *dest;
5880 struct bgp_dest *rm;
d62a17ae 5881 struct bgp_table *table;
5882 struct bgp_static *bgp_static;
5883
5884 /* Use this flag to force reprocessing of the route */
892fedb6 5885 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5886 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5887 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5888 dest = bgp_route_next(dest)) {
5889 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5890 continue;
ea47320b 5891
05c7a1cc
QY
5892 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5893 || (safi == SAFI_EVPN)) {
9bcb3eef 5894 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5895
5896 for (rm = bgp_table_top(table); rm;
5897 rm = bgp_route_next(rm)) {
a78beeb5 5898 bgp_static =
9bcb3eef 5899 bgp_dest_get_bgp_static_info(
5a8ba9fc 5900 rm);
9bcb3eef
DS
5901 bgp_static_update_safi(
5902 bgp, bgp_dest_get_prefix(rm),
5903 bgp_static, afi, safi);
d62a17ae 5904 }
05c7a1cc 5905 } else {
9bcb3eef
DS
5906 bgp_static = bgp_dest_get_bgp_static_info(dest);
5907 bgp_static_update(bgp,
5908 bgp_dest_get_prefix(dest),
5909 bgp_static, afi, safi);
ea47320b 5910 }
05c7a1cc
QY
5911 }
5912 }
892fedb6 5913 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5914}
5915
5916static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5917 safi_t safi)
5918{
5919 struct bgp_table *table;
9bcb3eef 5920 struct bgp_dest *dest;
40381db7 5921 struct bgp_path_info *pi;
d62a17ae 5922
dfb6fd1d
NT
5923 /* Do not install the aggregate route if BGP is in the
5924 * process of termination.
5925 */
892fedb6
DA
5926 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5927 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5928 return;
5929
d62a17ae 5930 table = bgp->rib[afi][safi];
9bcb3eef
DS
5931 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5932 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5933 if (pi->peer == bgp->peer_self
5934 && ((pi->type == ZEBRA_ROUTE_BGP
5935 && pi->sub_type == BGP_ROUTE_STATIC)
5936 || (pi->type != ZEBRA_ROUTE_BGP
5937 && pi->sub_type
d62a17ae 5938 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5939 bgp_aggregate_decrement(
5940 bgp, bgp_dest_get_prefix(dest), pi, afi,
5941 safi);
40381db7 5942 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5943 bgp_path_info_delete(dest, pi);
5944 bgp_process(bgp, dest, afi, safi);
d62a17ae 5945 }
5946 }
5947 }
ad4cbda1 5948}
5949
5950/*
5951 * Purge all networks and redistributed routes from routing table.
5952 * Invoked upon the instance going down.
5953 */
d62a17ae 5954void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5955{
d62a17ae 5956 afi_t afi;
5957 safi_t safi;
ad4cbda1 5958
05c7a1cc
QY
5959 FOREACH_AFI_SAFI (afi, safi)
5960 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5961}
5962
137446f9
LB
5963/*
5964 * gpz 110624
5965 * Currently this is used to set static routes for VPN and ENCAP.
5966 * I think it can probably be factored with bgp_static_set.
5967 */
d62a17ae 5968int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5969 const char *ip_str, const char *rd_str,
5970 const char *label_str, const char *rmap_str,
5971 int evpn_type, const char *esi, const char *gwip,
5972 const char *ethtag, const char *routermac)
5973{
5974 VTY_DECLVAR_CONTEXT(bgp, bgp);
5975 int ret;
5976 struct prefix p;
5977 struct prefix_rd prd;
9bcb3eef
DS
5978 struct bgp_dest *pdest;
5979 struct bgp_dest *dest;
d62a17ae 5980 struct bgp_table *table;
5981 struct bgp_static *bgp_static;
5982 mpls_label_t label = MPLS_INVALID_LABEL;
5983 struct prefix gw_ip;
5984
5985 /* validate ip prefix */
5986 ret = str2prefix(ip_str, &p);
5987 if (!ret) {
5988 vty_out(vty, "%% Malformed prefix\n");
5989 return CMD_WARNING_CONFIG_FAILED;
5990 }
5991 apply_mask(&p);
5992 if ((afi == AFI_L2VPN)
5993 && (bgp_build_evpn_prefix(evpn_type,
5994 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5995 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5996 return CMD_WARNING_CONFIG_FAILED;
5997 }
718e3744 5998
d62a17ae 5999 ret = str2prefix_rd(rd_str, &prd);
6000 if (!ret) {
6001 vty_out(vty, "%% Malformed rd\n");
6002 return CMD_WARNING_CONFIG_FAILED;
6003 }
718e3744 6004
d62a17ae 6005 if (label_str) {
6006 unsigned long label_val;
6007 label_val = strtoul(label_str, NULL, 10);
6008 encode_label(label_val, &label);
6009 }
9bedbb1e 6010
d62a17ae 6011 if (safi == SAFI_EVPN) {
6012 if (esi && str2esi(esi, NULL) == 0) {
6013 vty_out(vty, "%% Malformed ESI\n");
6014 return CMD_WARNING_CONFIG_FAILED;
6015 }
6016 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6017 vty_out(vty, "%% Malformed Router MAC\n");
6018 return CMD_WARNING_CONFIG_FAILED;
6019 }
6020 if (gwip) {
6021 memset(&gw_ip, 0, sizeof(struct prefix));
6022 ret = str2prefix(gwip, &gw_ip);
6023 if (!ret) {
6024 vty_out(vty, "%% Malformed GatewayIp\n");
6025 return CMD_WARNING_CONFIG_FAILED;
6026 }
6027 if ((gw_ip.family == AF_INET
3714a385 6028 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6029 (struct prefix_evpn *)&p))
6030 || (gw_ip.family == AF_INET6
3714a385 6031 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6032 (struct prefix_evpn *)&p))) {
6033 vty_out(vty,
6034 "%% GatewayIp family differs with IP prefix\n");
6035 return CMD_WARNING_CONFIG_FAILED;
6036 }
6037 }
6038 }
9bcb3eef
DS
6039 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6040 if (!bgp_dest_has_bgp_path_info_data(pdest))
6041 bgp_dest_set_bgp_table_info(pdest,
67009e22 6042 bgp_table_init(bgp, afi, safi));
9bcb3eef 6043 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6044
9bcb3eef 6045 dest = bgp_node_get(table, &p);
d62a17ae 6046
9bcb3eef 6047 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6048 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6049 bgp_dest_unlock_node(dest);
d62a17ae 6050 } else {
6051 /* New configuration. */
6052 bgp_static = bgp_static_new();
6053 bgp_static->backdoor = 0;
6054 bgp_static->valid = 0;
6055 bgp_static->igpmetric = 0;
975a328e 6056 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6057 bgp_static->label = label;
6058 bgp_static->prd = prd;
6059
6060 if (rmap_str) {
0a22ddfb 6061 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6062 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6063 bgp_static->rmap.name =
6064 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6065 bgp_static->rmap.map =
6066 route_map_lookup_by_name(rmap_str);
b4897fa5 6067 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6068 }
718e3744 6069
d62a17ae 6070 if (safi == SAFI_EVPN) {
6071 if (esi) {
6072 bgp_static->eth_s_id =
6073 XCALLOC(MTYPE_ATTR,
0a50c248 6074 sizeof(esi_t));
d62a17ae 6075 str2esi(esi, bgp_static->eth_s_id);
6076 }
6077 if (routermac) {
6078 bgp_static->router_mac =
28328ea9 6079 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6080 (void)prefix_str2mac(routermac,
6081 bgp_static->router_mac);
d62a17ae 6082 }
6083 if (gwip)
6084 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6085 }
9bcb3eef 6086 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6087
d62a17ae 6088 bgp_static->valid = 1;
6089 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6090 }
718e3744 6091
d62a17ae 6092 return CMD_SUCCESS;
718e3744 6093}
6094
6095/* Configure static BGP network. */
d62a17ae 6096int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6097 const char *ip_str, const char *rd_str,
6098 const char *label_str, int evpn_type, const char *esi,
6099 const char *gwip, const char *ethtag)
6100{
6101 VTY_DECLVAR_CONTEXT(bgp, bgp);
6102 int ret;
6103 struct prefix p;
6104 struct prefix_rd prd;
9bcb3eef
DS
6105 struct bgp_dest *pdest;
6106 struct bgp_dest *dest;
d62a17ae 6107 struct bgp_table *table;
6108 struct bgp_static *bgp_static;
6109 mpls_label_t label = MPLS_INVALID_LABEL;
6110
6111 /* Convert IP prefix string to struct prefix. */
6112 ret = str2prefix(ip_str, &p);
6113 if (!ret) {
6114 vty_out(vty, "%% Malformed prefix\n");
6115 return CMD_WARNING_CONFIG_FAILED;
6116 }
6117 apply_mask(&p);
6118 if ((afi == AFI_L2VPN)
6119 && (bgp_build_evpn_prefix(evpn_type,
6120 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6121 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6122 return CMD_WARNING_CONFIG_FAILED;
6123 }
6124 ret = str2prefix_rd(rd_str, &prd);
6125 if (!ret) {
6126 vty_out(vty, "%% Malformed rd\n");
6127 return CMD_WARNING_CONFIG_FAILED;
6128 }
718e3744 6129
d62a17ae 6130 if (label_str) {
6131 unsigned long label_val;
6132 label_val = strtoul(label_str, NULL, 10);
6133 encode_label(label_val, &label);
6134 }
718e3744 6135
9bcb3eef
DS
6136 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6137 if (!bgp_dest_has_bgp_path_info_data(pdest))
6138 bgp_dest_set_bgp_table_info(pdest,
67009e22 6139 bgp_table_init(bgp, afi, safi));
d62a17ae 6140 else
9bcb3eef
DS
6141 bgp_dest_unlock_node(pdest);
6142 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6143
9bcb3eef 6144 dest = bgp_node_lookup(table, &p);
6b0655a2 6145
9bcb3eef 6146 if (dest) {
d62a17ae 6147 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6148
9bcb3eef 6149 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6150 bgp_static_free(bgp_static);
9bcb3eef
DS
6151 bgp_dest_set_bgp_static_info(dest, NULL);
6152 bgp_dest_unlock_node(dest);
6153 bgp_dest_unlock_node(dest);
d62a17ae 6154 } else
6155 vty_out(vty, "%% Can't find the route\n");
6156
6157 return CMD_SUCCESS;
6158}
6159
6160static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6161 const char *rmap_name)
6162{
6163 VTY_DECLVAR_CONTEXT(bgp, bgp);
6164 struct bgp_rmap *rmap;
6165
6166 rmap = &bgp->table_map[afi][safi];
6167 if (rmap_name) {
0a22ddfb 6168 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6169 route_map_counter_decrement(rmap->map);
d62a17ae 6170 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6171 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6172 route_map_counter_increment(rmap->map);
d62a17ae 6173 } else {
0a22ddfb 6174 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6175 route_map_counter_decrement(rmap->map);
d62a17ae 6176 rmap->map = NULL;
6177 }
73ac8160 6178
d62a17ae 6179 if (bgp_fibupd_safi(safi))
6180 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6181
d62a17ae 6182 return CMD_SUCCESS;
73ac8160
DS
6183}
6184
d62a17ae 6185static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6186 const char *rmap_name)
73ac8160 6187{
d62a17ae 6188 VTY_DECLVAR_CONTEXT(bgp, bgp);
6189 struct bgp_rmap *rmap;
73ac8160 6190
d62a17ae 6191 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6192 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6193 route_map_counter_decrement(rmap->map);
d62a17ae 6194 rmap->map = NULL;
73ac8160 6195
d62a17ae 6196 if (bgp_fibupd_safi(safi))
6197 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6198
d62a17ae 6199 return CMD_SUCCESS;
73ac8160
DS
6200}
6201
2b791107 6202void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6203 safi_t safi)
73ac8160 6204{
d62a17ae 6205 if (bgp->table_map[afi][safi].name) {
d62a17ae 6206 vty_out(vty, " table-map %s\n",
6207 bgp->table_map[afi][safi].name);
6208 }
73ac8160
DS
6209}
6210
73ac8160
DS
6211DEFUN (bgp_table_map,
6212 bgp_table_map_cmd,
6213 "table-map WORD",
6214 "BGP table to RIB route download filter\n"
6215 "Name of the route map\n")
6216{
d62a17ae 6217 int idx_word = 1;
6218 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6219 argv[idx_word]->arg);
73ac8160
DS
6220}
6221DEFUN (no_bgp_table_map,
6222 no_bgp_table_map_cmd,
6223 "no table-map WORD",
3a2d747c 6224 NO_STR
73ac8160
DS
6225 "BGP table to RIB route download filter\n"
6226 "Name of the route map\n")
6227{
d62a17ae 6228 int idx_word = 2;
6229 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6230 argv[idx_word]->arg);
73ac8160
DS
6231}
6232
37a87b8f
CS
6233DEFPY_YANG (bgp_network, bgp_network_cmd,
6234 "[no] network \
6235 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6236 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6237 backdoor$backdoor}]",
6238 NO_STR
6239 "Specify a network to announce via BGP\n"
6240 "IPv4 prefix\n"
6241 "Network number\n"
6242 "Network mask\n"
6243 "Network mask\n"
6244 "Route-map to modify the attributes\n"
6245 "Name of the route map\n"
6246 "Label index to associate with the prefix\n"
6247 "Label index value\n"
6248 "Specify a BGP backdoor route\n")
6249{
6250 char addr_prefix_str[PREFIX_STRLEN];
6251 char base_xpath[XPATH_MAXLEN];
6252 afi_t afi;
6253 safi_t safi;
e2a86ad9
DS
6254
6255 if (address_str) {
6256 int ret;
718e3744 6257
e2a86ad9
DS
6258 ret = netmask_str2prefix_str(address_str, netmask_str,
6259 addr_prefix_str);
6260 if (!ret) {
6261 vty_out(vty, "%% Inconsistent address and mask\n");
6262 return CMD_WARNING_CONFIG_FAILED;
6263 }
d62a17ae 6264 }
718e3744 6265
37a87b8f
CS
6266 afi = bgp_node_afi(vty);
6267 safi = bgp_node_safi(vty);
6268
6269 if (no) {
6270 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6271 } else {
6272 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6273
6274 if (map_name)
6275 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6276 NB_OP_CREATE, map_name);
6277 else
6278 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6279 NB_OP_DESTROY, NULL);
6280
6281 if (label_index_str)
6282 nb_cli_enqueue_change(vty, "./label-index",
6283 NB_OP_MODIFY, label_index_str);
6284
6285 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6286 backdoor ? "true" : "false");
6287 }
6288
6289 snprintf(
6290 base_xpath, sizeof(base_xpath),
6291 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6292 yang_afi_safi_value2identity(afi, safi),
6293 bgp_afi_safi_get_container_str(afi, safi),
6294 address_str ? addr_prefix_str : prefix_str);
6295
6296 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6297}
6298
37a87b8f
CS
6299DEFPY_YANG (ipv6_bgp_network,
6300 ipv6_bgp_network_cmd,
6301 "[no] network X:X::X:X/M$prefix \
6302 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6303 NO_STR
6304 "Specify a network to announce via BGP\n"
6305 "IPv6 prefix\n"
6306 "Route-map to modify the attributes\n"
6307 "Name of the route map\n"
6308 "Label index to associate with the prefix\n"
6309 "Label index value\n")
6310{
6311 char base_xpath[XPATH_MAXLEN];
6312 afi_t afi;
6313 safi_t safi;
6314
6315 afi = bgp_node_afi(vty);
6316 safi = bgp_node_safi(vty);
6317
6318 if (no) {
6319 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6320 } else {
6321 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6322
6323 if (map_name)
6324 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6325 NB_OP_MODIFY, map_name);
6326 else
6327 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6328 NB_OP_DESTROY, NULL);
6329
6330 if (label_index_str)
6331 nb_cli_enqueue_change(vty, "./label-index",
6332 NB_OP_MODIFY, label_index_str);
6333 }
6334
6335 snprintf(
6336 base_xpath, sizeof(base_xpath),
6337 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6338 yang_afi_safi_value2identity(afi, safi),
6339 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6340
6341 return nb_cli_apply_changes(vty, base_xpath);
6342}
6343
6344void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6345 struct lyd_node *dnode,
6346 bool show_defaults)
718e3744 6347{
37a87b8f
CS
6348 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6349
6350 if (yang_dnode_exists(dnode, "./label-index"))
6351 vty_out(vty, " label-index %s",
6352 yang_dnode_get_string(dnode, "./label-index"));
6353
6354 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6355 vty_out(vty, " route-map %s",
6356 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6357
6358 if (yang_dnode_get_bool(dnode, "./backdoor"))
6359 vty_out(vty, " backdoor");
6360
6361 vty_out(vty, "\n");
1b6d5c7e
VV
6362}
6363
d62a17ae 6364static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6365{
d62a17ae 6366 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6367}
6368
d62a17ae 6369static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6370{
365ab2e7
RZ
6371 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6372 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6373 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6374 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6375 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6376}
718e3744 6377
365ab2e7
RZ
6378/**
6379 * Helper function to avoid repeated code: prepare variables for a
6380 * `route_map_apply` call.
6381 *
6382 * \returns `true` on route map match, otherwise `false`.
6383 */
6384static bool aggr_suppress_map_test(struct bgp *bgp,
6385 struct bgp_aggregate *aggregate,
6386 struct bgp_path_info *pi)
6387{
6388 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6389 route_map_result_t rmr = RMAP_DENYMATCH;
6390 struct bgp_path_info rmap_path = {};
6391 struct attr attr = {};
6392
6393 /* No route map entries created, just don't match. */
6394 if (aggregate->suppress_map == NULL)
6395 return false;
6396
6397 /* Call route map matching and return result. */
6398 attr.aspath = aspath_empty();
6399 rmap_path.peer = bgp->peer_self;
6400 rmap_path.attr = &attr;
6401
6402 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6403 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6404 bgp->peer_self->rmap_type = 0;
6405
6406 bgp_attr_flush(&attr);
6407
6408 return rmr == RMAP_PERMITMATCH;
6409}
6410
4056a5f6
RZ
6411/** Test whether the aggregation has suppressed this path or not. */
6412static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6413 struct bgp_path_info *pi)
6414{
6415 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6416 return false;
6417
6418 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6419}
6420
6421/**
6422 * Suppress this path and keep the reference.
6423 *
6424 * \returns `true` if needs processing otherwise `false`.
6425 */
6426static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6427 struct bgp_path_info *pi)
6428{
6429 struct bgp_path_info_extra *pie;
6430
6431 /* Path is already suppressed by this aggregation. */
6432 if (aggr_suppress_exists(aggregate, pi))
6433 return false;
6434
6435 pie = bgp_path_info_extra_get(pi);
6436
6437 /* This is the first suppression, allocate memory and list it. */
6438 if (pie->aggr_suppressors == NULL)
6439 pie->aggr_suppressors = list_new();
6440
6441 listnode_add(pie->aggr_suppressors, aggregate);
6442
6443 /* Only mark for processing if suppressed. */
6444 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6445 if (BGP_DEBUG(update, UPDATE_OUT))
6446 zlog_debug("aggregate-address suppressing: %pFX",
6447 bgp_dest_get_prefix(pi->net));
6448
4056a5f6
RZ
6449 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6450 return true;
6451 }
6452
6453 return false;
6454}
6455
6456/**
6457 * Unsuppress this path and remove the reference.
6458 *
6459 * \returns `true` if needs processing otherwise `false`.
6460 */
6461static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6462 struct bgp_path_info *pi)
6463{
6464 /* Path wasn't suppressed. */
6465 if (!aggr_suppress_exists(aggregate, pi))
6466 return false;
6467
6468 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6469
6470 /* Unsuppress and free extra memory if last item. */
6471 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6472 if (BGP_DEBUG(update, UPDATE_OUT))
6473 zlog_debug("aggregate-address unsuppressing: %pFX",
6474 bgp_dest_get_prefix(pi->net));
6475
4056a5f6
RZ
6476 list_delete(&pi->extra->aggr_suppressors);
6477 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6478 return true;
6479 }
6480
6481 return false;
6482}
6483
3dc339cd
DA
6484static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6485 struct aspath *aspath,
6486 struct community *comm,
6487 struct ecommunity *ecomm,
6488 struct lcommunity *lcomm)
eaaf8adb
DS
6489{
6490 static struct aspath *ae = NULL;
6491
6492 if (!ae)
6493 ae = aspath_empty();
6494
40381db7 6495 if (!pi)
3dc339cd 6496 return false;
eaaf8adb 6497
40381db7 6498 if (origin != pi->attr->origin)
3dc339cd 6499 return false;
eaaf8adb 6500
40381db7 6501 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6502 return false;
29f7d023 6503
40381db7 6504 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6505 return false;
eaaf8adb 6506
3da2cc32 6507 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6508 return false;
eaaf8adb 6509
dd18c5a9 6510 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6511 return false;
dd18c5a9 6512
40381db7 6513 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6514 return false;
7ce8a8e0 6515
3dc339cd 6516 return true;
eaaf8adb
DS
6517}
6518
5f040085
DS
6519static void bgp_aggregate_install(
6520 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6521 uint8_t origin, struct aspath *aspath, struct community *community,
6522 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6523 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6524{
9bcb3eef 6525 struct bgp_dest *dest;
c701010e 6526 struct bgp_table *table;
6f94b685 6527 struct bgp_path_info *pi, *orig, *new;
20894f50 6528 struct attr *attr;
c701010e
DS
6529
6530 table = bgp->rib[afi][safi];
6531
9bcb3eef 6532 dest = bgp_node_get(table, p);
eaaf8adb 6533
9bcb3eef 6534 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6535 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6536 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6537 break;
6538
6aabb15d
RZ
6539 /*
6540 * If we have paths with different MEDs, then don't install
6541 * (or uninstall) the aggregate route.
6542 */
6543 if (aggregate->match_med && aggregate->med_mismatched)
6544 goto uninstall_aggregate_route;
6545
c701010e 6546 if (aggregate->count > 0) {
eaaf8adb
DS
6547 /*
6548 * If the aggregate information has not changed
6549 * no need to re-install it again.
6550 */
6f94b685 6551 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6552 ecommunity, lcommunity)) {
9bcb3eef 6553 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6554
6555 if (aspath)
6556 aspath_free(aspath);
6557 if (community)
3c1f53de 6558 community_free(&community);
3da2cc32
DS
6559 if (ecommunity)
6560 ecommunity_free(&ecommunity);
dd18c5a9
DS
6561 if (lcommunity)
6562 lcommunity_free(&lcommunity);
eaaf8adb
DS
6563
6564 return;
6565 }
6566
6567 /*
6568 * Mark the old as unusable
6569 */
40381db7 6570 if (pi)
9bcb3eef 6571 bgp_path_info_delete(dest, pi);
eaaf8adb 6572
20894f50
DA
6573 attr = bgp_attr_aggregate_intern(
6574 bgp, origin, aspath, community, ecommunity, lcommunity,
6575 aggregate, atomic_aggregate, p);
6576
6577 if (!attr) {
6578 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6579 return;
6580 }
6581
3da2cc32 6582 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6583 bgp->peer_self, attr, dest);
20894f50 6584
1defdda8 6585 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6586
9bcb3eef
DS
6587 bgp_path_info_add(dest, new);
6588 bgp_process(bgp, dest, afi, safi);
c701010e 6589 } else {
6aabb15d 6590 uninstall_aggregate_route:
6f94b685 6591 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6592 if (pi->peer == bgp->peer_self
6593 && pi->type == ZEBRA_ROUTE_BGP
6594 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6595 break;
6596
6597 /* Withdraw static BGP route from routing table. */
40381db7 6598 if (pi) {
9bcb3eef
DS
6599 bgp_path_info_delete(dest, pi);
6600 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6601 }
6602 }
6603
9bcb3eef 6604 bgp_dest_unlock_node(dest);
c701010e
DS
6605}
6606
6aabb15d
RZ
6607/**
6608 * Check if the current path has different MED than other known paths.
6609 *
6610 * \returns `true` if the MED matched the others else `false`.
6611 */
6612static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6613 struct bgp *bgp, struct bgp_path_info *pi)
6614{
6615 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6616
6617 /* This is the first route being analyzed. */
6618 if (!aggregate->med_initialized) {
6619 aggregate->med_initialized = true;
6620 aggregate->med_mismatched = false;
6621 aggregate->med_matched_value = cur_med;
6622 } else {
6623 /* Check if routes with different MED showed up. */
6624 if (cur_med != aggregate->med_matched_value)
6625 aggregate->med_mismatched = true;
6626 }
6627
6628 return !aggregate->med_mismatched;
6629}
6630
6631/**
6632 * Initializes and tests all routes in the aggregate address path for MED
6633 * values.
6634 *
6635 * \returns `true` if all MEDs are the same otherwise `false`.
6636 */
6637static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6638 struct bgp *bgp, const struct prefix *p,
6639 afi_t afi, safi_t safi)
6640{
6641 struct bgp_table *table = bgp->rib[afi][safi];
6642 const struct prefix *dest_p;
6643 struct bgp_dest *dest, *top;
6644 struct bgp_path_info *pi;
6645 bool med_matched = true;
6646
6647 aggregate->med_initialized = false;
6648
6649 top = bgp_node_get(table, p);
6650 for (dest = bgp_node_get(table, p); dest;
6651 dest = bgp_route_next_until(dest, top)) {
6652 dest_p = bgp_dest_get_prefix(dest);
6653 if (dest_p->prefixlen <= p->prefixlen)
6654 continue;
6655
6656 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6657 if (BGP_PATH_HOLDDOWN(pi))
6658 continue;
6659 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6660 continue;
6661 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6662 med_matched = false;
6663 break;
6664 }
6665 }
6666 if (!med_matched)
6667 break;
6668 }
6669 bgp_dest_unlock_node(top);
6670
6671 return med_matched;
6672}
6673
6674/**
6675 * Toggles the route suppression status for this aggregate address
6676 * configuration.
6677 */
4056a5f6
RZ
6678void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6679 struct bgp *bgp, const struct prefix *p,
6680 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6681{
6682 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6683 const struct prefix *dest_p;
6684 struct bgp_dest *dest, *top;
6685 struct bgp_path_info *pi;
6686 bool toggle_suppression;
6687
6688 /* We've found a different MED we must revert any suppressed routes. */
6689 top = bgp_node_get(table, p);
6690 for (dest = bgp_node_get(table, p); dest;
6691 dest = bgp_route_next_until(dest, top)) {
6692 dest_p = bgp_dest_get_prefix(dest);
6693 if (dest_p->prefixlen <= p->prefixlen)
6694 continue;
6695
6696 toggle_suppression = false;
6697 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6698 if (BGP_PATH_HOLDDOWN(pi))
6699 continue;
6700 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6701 continue;
6702
6aabb15d
RZ
6703 /* We are toggling suppression back. */
6704 if (suppress) {
6aabb15d 6705 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6706 if (aggr_suppress_path(aggregate, pi))
6707 toggle_suppression = true;
6aabb15d
RZ
6708 continue;
6709 }
6710
6aabb15d 6711 /* Install route if there is no more suppression. */
4056a5f6 6712 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6713 toggle_suppression = true;
6aabb15d
RZ
6714 }
6715
6716 if (toggle_suppression)
6717 bgp_process(bgp, dest, afi, safi);
6718 }
6719 bgp_dest_unlock_node(top);
6720}
6721
6722/**
6723 * Aggregate address MED matching incremental test: this function is called
6724 * when the initial aggregation occurred and we are only testing a single
6725 * new path.
6726 *
6727 * In addition to testing and setting the MED validity it also installs back
6728 * suppressed routes (if summary is configured).
6729 *
6730 * Must not be called in `bgp_aggregate_route`.
6731 */
6732static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6733 struct bgp *bgp, const struct prefix *p,
6734 afi_t afi, safi_t safi,
6735 struct bgp_path_info *pi, bool is_adding)
6736{
6737 /* MED matching disabled. */
6738 if (!aggregate->match_med)
6739 return;
6740
6741 /* Aggregation with different MED, nothing to do. */
6742 if (aggregate->med_mismatched)
6743 return;
6744
6745 /*
6746 * Test the current entry:
6747 *
6748 * is_adding == true: if the new entry doesn't match then we must
6749 * install all suppressed routes.
6750 *
6751 * is_adding == false: if the entry being removed was the last
6752 * unmatching entry then we can suppress all routes.
6753 */
6754 if (!is_adding) {
6755 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6756 && aggregate->summary_only)
6757 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6758 safi, true);
6759 } else
6760 bgp_aggregate_med_match(aggregate, bgp, pi);
6761
6762 /* No mismatches, just quit. */
6763 if (!aggregate->med_mismatched)
6764 return;
6765
6766 /* Route summarization is disabled. */
6767 if (!aggregate->summary_only)
6768 return;
6769
6770 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6771}
6772
b5d58c32 6773/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6774void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6775 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6776{
6777 struct bgp_table *table;
9bcb3eef
DS
6778 struct bgp_dest *top;
6779 struct bgp_dest *dest;
d7c0a89a 6780 uint8_t origin;
d62a17ae 6781 struct aspath *aspath = NULL;
d62a17ae 6782 struct community *community = NULL;
3da2cc32 6783 struct ecommunity *ecommunity = NULL;
dd18c5a9 6784 struct lcommunity *lcommunity = NULL;
40381db7 6785 struct bgp_path_info *pi;
d62a17ae 6786 unsigned long match = 0;
d7c0a89a 6787 uint8_t atomic_aggregate = 0;
d62a17ae 6788
9f822fa2
S
6789 /* If the bgp instance is being deleted or self peer is deleted
6790 * then do not create aggregate route
6791 */
892fedb6
DA
6792 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6793 || (bgp->peer_self == NULL))
9f822fa2
S
6794 return;
6795
6aabb15d
RZ
6796 /* Initialize and test routes for MED difference. */
6797 if (aggregate->match_med)
6798 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6799
4056a5f6
RZ
6800 /*
6801 * Reset aggregate count: we might've been called from route map
6802 * update so in that case we must retest all more specific routes.
6803 *
6804 * \see `bgp_route_map_process_update`.
6805 */
6806 aggregate->count = 0;
6807 aggregate->incomplete_origin_count = 0;
6808 aggregate->incomplete_origin_count = 0;
6809 aggregate->egp_origin_count = 0;
6810
d62a17ae 6811 /* ORIGIN attribute: If at least one route among routes that are
6812 aggregated has ORIGIN with the value INCOMPLETE, then the
6813 aggregated route must have the ORIGIN attribute with the value
6814 INCOMPLETE. Otherwise, if at least one route among routes that
6815 are aggregated has ORIGIN with the value EGP, then the aggregated
6816 route must have the origin attribute with the value EGP. In all
6817 other case the value of the ORIGIN attribute of the aggregated
6818 route is INTERNAL. */
6819 origin = BGP_ORIGIN_IGP;
718e3744 6820
d62a17ae 6821 table = bgp->rib[afi][safi];
718e3744 6822
d62a17ae 6823 top = bgp_node_get(table, p);
9bcb3eef
DS
6824 for (dest = bgp_node_get(table, p); dest;
6825 dest = bgp_route_next_until(dest, top)) {
6826 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6827
9bcb3eef 6828 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6829 continue;
d62a17ae 6830
a77e2f4b
S
6831 /* If suppress fib is enabled and route not installed
6832 * in FIB, skip the route
6833 */
6834 if (!bgp_check_advertise(bgp, dest))
6835 continue;
6836
c2ff8b3e 6837 match = 0;
d62a17ae 6838
9bcb3eef 6839 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6840 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6841 continue;
718e3744 6842
40381db7 6843 if (pi->attr->flag
c2ff8b3e
DS
6844 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6845 atomic_aggregate = 1;
d62a17ae 6846
40381db7 6847 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6848 continue;
d62a17ae 6849
f273fef1
DS
6850 /*
6851 * summary-only aggregate route suppress
6852 * aggregated route announcements.
6aabb15d
RZ
6853 *
6854 * MED matching:
6855 * Don't create summaries if MED didn't match
6856 * otherwise neither the specific routes and the
6857 * aggregation will be announced.
f273fef1 6858 */
6aabb15d
RZ
6859 if (aggregate->summary_only
6860 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6861 if (aggr_suppress_path(aggregate, pi))
6862 match++;
d62a17ae 6863 }
c2ff8b3e 6864
365ab2e7
RZ
6865 /*
6866 * Suppress more specific routes that match the route
6867 * map results.
6868 *
6869 * MED matching:
6870 * Don't suppress routes if MED matching is enabled and
6871 * it mismatched otherwise we might end up with no
6872 * routes for this path.
6873 */
6874 if (aggregate->suppress_map_name
6875 && AGGREGATE_MED_VALID(aggregate)
6876 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
6877 if (aggr_suppress_path(aggregate, pi))
6878 match++;
d62a17ae 6879 }
c2ff8b3e
DS
6880
6881 aggregate->count++;
6882
f273fef1
DS
6883 /*
6884 * If at least one route among routes that are
6885 * aggregated has ORIGIN with the value INCOMPLETE,
6886 * then the aggregated route MUST have the ORIGIN
6887 * attribute with the value INCOMPLETE. Otherwise, if
6888 * at least one route among routes that are aggregated
6889 * has ORIGIN with the value EGP, then the aggregated
6890 * route MUST have the ORIGIN attribute with the value
6891 * EGP.
6892 */
fc968841
NT
6893 switch (pi->attr->origin) {
6894 case BGP_ORIGIN_INCOMPLETE:
6895 aggregate->incomplete_origin_count++;
6896 break;
6897 case BGP_ORIGIN_EGP:
6898 aggregate->egp_origin_count++;
6899 break;
6900 default:
6901 /*Do nothing.
6902 */
6903 break;
6904 }
c2ff8b3e
DS
6905
6906 if (!aggregate->as_set)
6907 continue;
6908
f273fef1
DS
6909 /*
6910 * as-set aggregate route generate origin, as path,
6911 * and community aggregation.
6912 */
fc968841
NT
6913 /* Compute aggregate route's as-path.
6914 */
ef51a7d8 6915 bgp_compute_aggregate_aspath_hash(aggregate,
6916 pi->attr->aspath);
c2ff8b3e 6917
fc968841
NT
6918 /* Compute aggregate route's community.
6919 */
6920 if (pi->attr->community)
21fec674 6921 bgp_compute_aggregate_community_hash(
fc968841
NT
6922 aggregate,
6923 pi->attr->community);
dd18c5a9 6924
fc968841
NT
6925 /* Compute aggregate route's extended community.
6926 */
6927 if (pi->attr->ecommunity)
4edd83f9 6928 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6929 aggregate,
6930 pi->attr->ecommunity);
6931
6932 /* Compute aggregate route's large community.
6933 */
6934 if (pi->attr->lcommunity)
f1eb1f05 6935 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6936 aggregate,
6937 pi->attr->lcommunity);
d62a17ae 6938 }
c2ff8b3e 6939 if (match)
9bcb3eef 6940 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6941 }
21fec674 6942 if (aggregate->as_set) {
ef51a7d8 6943 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6944 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6945 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6946 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6947 }
6948
f1eb1f05 6949
9bcb3eef 6950 bgp_dest_unlock_node(top);
718e3744 6951
718e3744 6952
fc968841
NT
6953 if (aggregate->incomplete_origin_count > 0)
6954 origin = BGP_ORIGIN_INCOMPLETE;
6955 else if (aggregate->egp_origin_count > 0)
6956 origin = BGP_ORIGIN_EGP;
d62a17ae 6957
229757f1
DA
6958 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6959 origin = aggregate->origin;
6960
fc968841
NT
6961 if (aggregate->as_set) {
6962 if (aggregate->aspath)
6963 /* Retrieve aggregate route's as-path.
6964 */
6965 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6966
fc968841
NT
6967 if (aggregate->community)
6968 /* Retrieve aggregate route's community.
6969 */
6970 community = community_dup(aggregate->community);
3da2cc32 6971
fc968841
NT
6972 if (aggregate->ecommunity)
6973 /* Retrieve aggregate route's ecommunity.
6974 */
6975 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6976
fc968841
NT
6977 if (aggregate->lcommunity)
6978 /* Retrieve aggregate route's lcommunity.
6979 */
6980 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6981 }
718e3744 6982
c701010e 6983 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6984 ecommunity, lcommunity, atomic_aggregate,
6985 aggregate);
718e3744 6986}
6987
5f040085
DS
6988void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6989 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6990{
6991 struct bgp_table *table;
9bcb3eef
DS
6992 struct bgp_dest *top;
6993 struct bgp_dest *dest;
40381db7 6994 struct bgp_path_info *pi;
3b7db173
DS
6995 unsigned long match;
6996
6997 table = bgp->rib[afi][safi];
6998
6999 /* If routes exists below this node, generate aggregate routes. */
7000 top = bgp_node_get(table, p);
9bcb3eef
DS
7001 for (dest = bgp_node_get(table, p); dest;
7002 dest = bgp_route_next_until(dest, top)) {
7003 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7004
9bcb3eef 7005 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7006 continue;
7007 match = 0;
7008
9bcb3eef 7009 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7010 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7011 continue;
7012
40381db7 7013 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7014 continue;
7015
6aabb15d
RZ
7016 if (aggregate->summary_only && pi->extra
7017 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7018 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7019 match++;
3b7db173 7020 }
3b7db173 7021
365ab2e7
RZ
7022 if (aggregate->suppress_map_name
7023 && AGGREGATE_MED_VALID(aggregate)
7024 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7025 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7026 match++;
3b7db173 7027 }
365ab2e7 7028
3b7db173 7029 aggregate->count--;
fc968841
NT
7030
7031 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7032 aggregate->incomplete_origin_count--;
7033 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7034 aggregate->egp_origin_count--;
7035
7036 if (aggregate->as_set) {
7037 /* Remove as-path from aggregate.
7038 */
ef51a7d8 7039 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7040 aggregate,
7041 pi->attr->aspath);
7042
7043 if (pi->attr->community)
7044 /* Remove community from aggregate.
7045 */
21fec674 7046 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7047 aggregate,
7048 pi->attr->community);
7049
7050 if (pi->attr->ecommunity)
7051 /* Remove ecommunity from aggregate.
7052 */
4edd83f9 7053 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7054 aggregate,
7055 pi->attr->ecommunity);
7056
7057 if (pi->attr->lcommunity)
7058 /* Remove lcommunity from aggregate.
7059 */
f1eb1f05 7060 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7061 aggregate,
7062 pi->attr->lcommunity);
7063 }
3b7db173
DS
7064 }
7065
7066 /* If this node was suppressed, process the change. */
7067 if (match)
9bcb3eef 7068 bgp_process(bgp, dest, afi, safi);
3b7db173 7069 }
f1eb1f05 7070 if (aggregate->as_set) {
ef51a7d8 7071 aspath_free(aggregate->aspath);
7072 aggregate->aspath = NULL;
21fec674 7073 if (aggregate->community)
7074 community_free(&aggregate->community);
4edd83f9 7075 if (aggregate->ecommunity)
7076 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7077 if (aggregate->lcommunity)
7078 lcommunity_free(&aggregate->lcommunity);
7079 }
7080
9bcb3eef 7081 bgp_dest_unlock_node(top);
3b7db173 7082}
718e3744 7083
5f040085
DS
7084static void bgp_add_route_to_aggregate(struct bgp *bgp,
7085 const struct prefix *aggr_p,
fc968841
NT
7086 struct bgp_path_info *pinew, afi_t afi,
7087 safi_t safi,
7088 struct bgp_aggregate *aggregate)
7089{
7090 uint8_t origin;
7091 struct aspath *aspath = NULL;
7092 uint8_t atomic_aggregate = 0;
7093 struct community *community = NULL;
7094 struct ecommunity *ecommunity = NULL;
7095 struct lcommunity *lcommunity = NULL;
7096
7097 /* ORIGIN attribute: If at least one route among routes that are
7098 * aggregated has ORIGIN with the value INCOMPLETE, then the
7099 * aggregated route must have the ORIGIN attribute with the value
7100 * INCOMPLETE. Otherwise, if at least one route among routes that
7101 * are aggregated has ORIGIN with the value EGP, then the aggregated
7102 * route must have the origin attribute with the value EGP. In all
7103 * other case the value of the ORIGIN attribute of the aggregated
7104 * route is INTERNAL.
7105 */
7106 origin = BGP_ORIGIN_IGP;
7107
7108 aggregate->count++;
7109
6aabb15d
RZ
7110 /*
7111 * This must be called before `summary` check to avoid
7112 * "suppressing" twice.
7113 */
7114 if (aggregate->match_med)
7115 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7116 pinew, true);
7117
7118 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7119 aggr_suppress_path(aggregate, pinew);
fc968841 7120
365ab2e7
RZ
7121 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7122 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7123 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7124
7125 switch (pinew->attr->origin) {
7126 case BGP_ORIGIN_INCOMPLETE:
7127 aggregate->incomplete_origin_count++;
7128 break;
7129 case BGP_ORIGIN_EGP:
7130 aggregate->egp_origin_count++;
7131 break;
7132 default:
7133 /* Do nothing.
7134 */
7135 break;
7136 }
7137
7138 if (aggregate->incomplete_origin_count > 0)
7139 origin = BGP_ORIGIN_INCOMPLETE;
7140 else if (aggregate->egp_origin_count > 0)
7141 origin = BGP_ORIGIN_EGP;
7142
229757f1
DA
7143 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7144 origin = aggregate->origin;
7145
fc968841
NT
7146 if (aggregate->as_set) {
7147 /* Compute aggregate route's as-path.
7148 */
7149 bgp_compute_aggregate_aspath(aggregate,
7150 pinew->attr->aspath);
7151
7152 /* Compute aggregate route's community.
7153 */
7154 if (pinew->attr->community)
7155 bgp_compute_aggregate_community(
7156 aggregate,
7157 pinew->attr->community);
7158
7159 /* Compute aggregate route's extended community.
7160 */
7161 if (pinew->attr->ecommunity)
7162 bgp_compute_aggregate_ecommunity(
7163 aggregate,
7164 pinew->attr->ecommunity);
7165
7166 /* Compute aggregate route's large community.
7167 */
7168 if (pinew->attr->lcommunity)
7169 bgp_compute_aggregate_lcommunity(
7170 aggregate,
7171 pinew->attr->lcommunity);
7172
7173 /* Retrieve aggregate route's as-path.
7174 */
7175 if (aggregate->aspath)
7176 aspath = aspath_dup(aggregate->aspath);
7177
7178 /* Retrieve aggregate route's community.
7179 */
7180 if (aggregate->community)
7181 community = community_dup(aggregate->community);
7182
7183 /* Retrieve aggregate route's ecommunity.
7184 */
7185 if (aggregate->ecommunity)
7186 ecommunity = ecommunity_dup(aggregate->ecommunity);
7187
7188 /* Retrieve aggregate route's lcommunity.
7189 */
7190 if (aggregate->lcommunity)
7191 lcommunity = lcommunity_dup(aggregate->lcommunity);
7192 }
7193
7194 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7195 aspath, community, ecommunity,
7196 lcommunity, atomic_aggregate, aggregate);
7197}
7198
7199static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7200 safi_t safi,
7201 struct bgp_path_info *pi,
7202 struct bgp_aggregate *aggregate,
5f040085 7203 const struct prefix *aggr_p)
fc968841
NT
7204{
7205 uint8_t origin;
7206 struct aspath *aspath = NULL;
7207 uint8_t atomic_aggregate = 0;
7208 struct community *community = NULL;
7209 struct ecommunity *ecommunity = NULL;
7210 struct lcommunity *lcommunity = NULL;
7211 unsigned long match = 0;
7212
7213 if (BGP_PATH_HOLDDOWN(pi))
7214 return;
7215
7216 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7217 return;
7218
4056a5f6
RZ
7219 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7220 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7221 match++;
fc968841 7222
365ab2e7 7223 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7224 && aggr_suppress_map_test(bgp, aggregate, pi))
7225 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7226 match++;
fc968841 7227
6aabb15d 7228 /*
365ab2e7 7229 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7230 * "unsuppressing" twice.
7231 */
7232 if (aggregate->match_med)
7233 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7234 true);
7235
fc968841
NT
7236 if (aggregate->count > 0)
7237 aggregate->count--;
7238
7239 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7240 aggregate->incomplete_origin_count--;
7241 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7242 aggregate->egp_origin_count--;
7243
7244 if (aggregate->as_set) {
7245 /* Remove as-path from aggregate.
7246 */
7247 bgp_remove_aspath_from_aggregate(aggregate,
7248 pi->attr->aspath);
7249
7250 if (pi->attr->community)
7251 /* Remove community from aggregate.
7252 */
7253 bgp_remove_community_from_aggregate(
7254 aggregate,
7255 pi->attr->community);
7256
7257 if (pi->attr->ecommunity)
7258 /* Remove ecommunity from aggregate.
7259 */
7260 bgp_remove_ecommunity_from_aggregate(
7261 aggregate,
7262 pi->attr->ecommunity);
7263
7264 if (pi->attr->lcommunity)
7265 /* Remove lcommunity from aggregate.
7266 */
7267 bgp_remove_lcommunity_from_aggregate(
7268 aggregate,
7269 pi->attr->lcommunity);
7270 }
7271
7272 /* If this node was suppressed, process the change. */
7273 if (match)
7274 bgp_process(bgp, pi->net, afi, safi);
7275
7276 origin = BGP_ORIGIN_IGP;
7277 if (aggregate->incomplete_origin_count > 0)
7278 origin = BGP_ORIGIN_INCOMPLETE;
7279 else if (aggregate->egp_origin_count > 0)
7280 origin = BGP_ORIGIN_EGP;
7281
229757f1
DA
7282 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7283 origin = aggregate->origin;
7284
fc968841
NT
7285 if (aggregate->as_set) {
7286 /* Retrieve aggregate route's as-path.
7287 */
7288 if (aggregate->aspath)
7289 aspath = aspath_dup(aggregate->aspath);
7290
7291 /* Retrieve aggregate route's community.
7292 */
7293 if (aggregate->community)
7294 community = community_dup(aggregate->community);
7295
7296 /* Retrieve aggregate route's ecommunity.
7297 */
7298 if (aggregate->ecommunity)
7299 ecommunity = ecommunity_dup(aggregate->ecommunity);
7300
7301 /* Retrieve aggregate route's lcommunity.
7302 */
7303 if (aggregate->lcommunity)
7304 lcommunity = lcommunity_dup(aggregate->lcommunity);
7305 }
7306
7307 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7308 aspath, community, ecommunity,
7309 lcommunity, atomic_aggregate, aggregate);
7310}
7311
5a1ae2c2 7312void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7313 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7314{
9bcb3eef
DS
7315 struct bgp_dest *child;
7316 struct bgp_dest *dest;
d62a17ae 7317 struct bgp_aggregate *aggregate;
7318 struct bgp_table *table;
718e3744 7319
d62a17ae 7320 table = bgp->aggregate[afi][safi];
f018db83 7321
d62a17ae 7322 /* No aggregates configured. */
7323 if (bgp_table_top_nolock(table) == NULL)
7324 return;
f018db83 7325
d62a17ae 7326 if (p->prefixlen == 0)
7327 return;
718e3744 7328
40381db7 7329 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7330 return;
718e3744 7331
a77e2f4b
S
7332 /* If suppress fib is enabled and route not installed
7333 * in FIB, do not update the aggregate route
7334 */
7335 if (!bgp_check_advertise(bgp, pi->net))
7336 return;
7337
d62a17ae 7338 child = bgp_node_get(table, p);
718e3744 7339
d62a17ae 7340 /* Aggregate address configuration check. */
9bcb3eef
DS
7341 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7342 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7343
9bcb3eef
DS
7344 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7345 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7346 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7347 aggregate);
d62a17ae 7348 }
b1e62edd 7349 }
9bcb3eef 7350 bgp_dest_unlock_node(child);
718e3744 7351}
7352
5a1ae2c2 7353void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7354 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7355{
9bcb3eef
DS
7356 struct bgp_dest *child;
7357 struct bgp_dest *dest;
d62a17ae 7358 struct bgp_aggregate *aggregate;
7359 struct bgp_table *table;
718e3744 7360
d62a17ae 7361 table = bgp->aggregate[afi][safi];
718e3744 7362
d62a17ae 7363 /* No aggregates configured. */
7364 if (bgp_table_top_nolock(table) == NULL)
7365 return;
718e3744 7366
d62a17ae 7367 if (p->prefixlen == 0)
7368 return;
718e3744 7369
d62a17ae 7370 child = bgp_node_get(table, p);
718e3744 7371
d62a17ae 7372 /* Aggregate address configuration check. */
9bcb3eef
DS
7373 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7374 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7375
9bcb3eef
DS
7376 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7377 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7378 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7379 aggregate, dest_p);
d62a17ae 7380 }
b1e62edd 7381 }
9bcb3eef 7382 bgp_dest_unlock_node(child);
d62a17ae 7383}
718e3744 7384
718e3744 7385/* Aggregate route attribute. */
7386#define AGGREGATE_SUMMARY_ONLY 1
7387#define AGGREGATE_AS_SET 1
fb29348a 7388#define AGGREGATE_AS_UNSET 0
718e3744 7389
229757f1
DA
7390static const char *bgp_origin2str(uint8_t origin)
7391{
7392 switch (origin) {
7393 case BGP_ORIGIN_IGP:
7394 return "igp";
7395 case BGP_ORIGIN_EGP:
7396 return "egp";
7397 case BGP_ORIGIN_INCOMPLETE:
7398 return "incomplete";
7399 }
7400 return "n/a";
7401}
7402
37a87b8f
CS
7403int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7404 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7405{
9bcb3eef 7406 struct bgp_dest *dest;
d62a17ae 7407 struct bgp_aggregate *aggregate;
718e3744 7408
37a87b8f 7409 apply_mask(prefix);
d62a17ae 7410 /* Old configuration check. */
37a87b8f 7411 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7412 if (!dest) {
37a87b8f
CS
7413 snprintf(errmsg, errmsg_len,
7414 "There is no aggregate-address configuration.\n");
7415 return -1;
d62a17ae 7416 }
f6269b4f 7417
9bcb3eef 7418 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7419 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7420 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7421 0, aggregate);
d62a17ae 7422
7423 /* Unlock aggregate address configuration. */
9bcb3eef 7424 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7425
7426 if (aggregate->community)
7427 community_free(&aggregate->community);
7428
7429 if (aggregate->community_hash) {
7430 /* Delete all communities in the hash.
7431 */
7432 hash_clean(aggregate->community_hash,
7433 bgp_aggr_community_remove);
7434 /* Free up the community_hash.
7435 */
7436 hash_free(aggregate->community_hash);
7437 }
7438
7439 if (aggregate->ecommunity)
7440 ecommunity_free(&aggregate->ecommunity);
7441
7442 if (aggregate->ecommunity_hash) {
7443 /* Delete all ecommunities in the hash.
7444 */
7445 hash_clean(aggregate->ecommunity_hash,
7446 bgp_aggr_ecommunity_remove);
7447 /* Free up the ecommunity_hash.
7448 */
7449 hash_free(aggregate->ecommunity_hash);
7450 }
7451
7452 if (aggregate->lcommunity)
7453 lcommunity_free(&aggregate->lcommunity);
7454
7455 if (aggregate->lcommunity_hash) {
7456 /* Delete all lcommunities in the hash.
7457 */
7458 hash_clean(aggregate->lcommunity_hash,
7459 bgp_aggr_lcommunity_remove);
7460 /* Free up the lcommunity_hash.
7461 */
7462 hash_free(aggregate->lcommunity_hash);
7463 }
7464
7465 if (aggregate->aspath)
7466 aspath_free(aggregate->aspath);
7467
7468 if (aggregate->aspath_hash) {
7469 /* Delete all as-paths in the hash.
7470 */
7471 hash_clean(aggregate->aspath_hash,
7472 bgp_aggr_aspath_remove);
7473 /* Free up the aspath_hash.
7474 */
7475 hash_free(aggregate->aspath_hash);
7476 }
7477
d62a17ae 7478 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7479 bgp_dest_unlock_node(dest);
7480 bgp_dest_unlock_node(dest);
d62a17ae 7481
37a87b8f 7482 return 0;
d62a17ae 7483}
7484
37a87b8f
CS
7485int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7486 safi_t safi, const char *rmap, uint8_t summary_only,
7487 uint8_t as_set, uint8_t origin, bool match_med,
7488 const char *suppress_map,
7489 char *errmsg, size_t errmsg_len)
d62a17ae 7490{
d62a17ae 7491 int ret;
9bcb3eef 7492 struct bgp_dest *dest;
d62a17ae 7493 struct bgp_aggregate *aggregate;
fb29348a 7494 uint8_t as_set_new = as_set;
37a87b8f 7495 char buf[PREFIX2STR_BUFFER];
d62a17ae 7496
365ab2e7 7497 if (suppress_map && summary_only) {
37a87b8f 7498 snprintf(errmsg, errmsg_len,
365ab2e7 7499 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7500 return -1;
365ab2e7
RZ
7501 }
7502
37a87b8f 7503 apply_mask(prefix);
d62a17ae 7504
37a87b8f
CS
7505 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7506 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7507 snprintf(
7508 errmsg, errmsg_len,
7509 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7510 prefix2str(prefix, buf, PREFIX_STRLEN));
7511 return -1;
3624ac81
DS
7512 }
7513
d62a17ae 7514 /* Old configuration check. */
37a87b8f 7515 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7516 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7517
20894f50 7518 if (aggregate) {
37a87b8f
CS
7519 snprintf(errmsg, errmsg_len,
7520 "There is already same aggregate network.\n");
d62a17ae 7521 /* try to remove the old entry */
37a87b8f
CS
7522 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7523 errmsg_len);
d62a17ae 7524 if (ret) {
37a87b8f
CS
7525 snprintf(errmsg, errmsg_len,
7526 "Error deleting aggregate.\n");
9bcb3eef 7527 bgp_dest_unlock_node(dest);
37a87b8f 7528 return -1;
d62a17ae 7529 }
7530 }
718e3744 7531
d62a17ae 7532 /* Make aggregate address structure. */
7533 aggregate = bgp_aggregate_new();
7534 aggregate->summary_only = summary_only;
6aabb15d 7535 aggregate->match_med = match_med;
fb29348a
DA
7536
7537 /* Network operators MUST NOT locally generate any new
7538 * announcements containing AS_SET or AS_CONFED_SET. If they have
7539 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7540 * SHOULD withdraw those routes and re-announce routes for the
7541 * aggregate or component prefixes (i.e., the more-specific routes
7542 * subsumed by the previously aggregated route) without AS_SET
7543 * or AS_CONFED_SET in the updates.
7544 */
7f972cd8 7545 if (bgp->reject_as_sets) {
fb29348a
DA
7546 if (as_set == AGGREGATE_AS_SET) {
7547 as_set_new = AGGREGATE_AS_UNSET;
7548 zlog_warn(
63efca0e 7549 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7550 __func__);
37a87b8f
CS
7551 snprintf(
7552 errmsg, errmsg_len,
fb29348a
DA
7553 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7554 }
7555 }
7556
7557 aggregate->as_set = as_set_new;
d62a17ae 7558 aggregate->safi = safi;
229757f1
DA
7559 /* Override ORIGIN attribute if defined.
7560 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7561 * to IGP which is not what rfc4271 says.
7562 * This enables the same behavior, optionally.
7563 */
7564 aggregate->origin = origin;
20894f50
DA
7565
7566 if (rmap) {
7567 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7568 route_map_counter_decrement(aggregate->rmap.map);
7569 aggregate->rmap.name =
7570 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7571 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7572 route_map_counter_increment(aggregate->rmap.map);
7573 }
365ab2e7
RZ
7574
7575 if (suppress_map) {
7576 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7577 route_map_counter_decrement(aggregate->suppress_map);
7578
7579 aggregate->suppress_map_name =
7580 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7581 aggregate->suppress_map =
7582 route_map_lookup_by_name(aggregate->suppress_map_name);
7583 route_map_counter_increment(aggregate->suppress_map);
7584 }
7585
9bcb3eef 7586 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7587
d62a17ae 7588 /* Aggregate address insert into BGP routing table. */
37a87b8f 7589 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7590
37a87b8f 7591 return 0;
718e3744 7592}
7593
37a87b8f
CS
7594DEFPY_YANG(
7595 aggregate_addressv4, aggregate_addressv4_cmd,
7596 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7597 "as-set$as_set_s"
7598 "|summary-only$summary_only"
7599 "|route-map WORD$rmap_name"
7600 "|origin <egp|igp|incomplete>$origin_s"
7601 "|matching-MED-only$match_med"
90e21f35 7602 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7603 "}",
7604 NO_STR
7605 "Configure BGP aggregate entries\n"
7606 "Aggregate prefix\n"
7607 "Aggregate address\n"
7608 "Aggregate mask\n"
7609 "Generate AS set path information\n"
7610 "Filter more specific routes from updates\n"
7611 "Apply route map to aggregate network\n"
7612 "Route map name\n"
7613 "BGP origin code\n"
7614 "Remote EGP\n"
7615 "Local IGP\n"
7616 "Unknown heritage\n"
7617 "Only aggregate routes with matching MED\n"
90e21f35
CS
7618 "Suppress the selected more specific routes\n"
7619 "Route map with the route selectors\n")
37a87b8f
CS
7620{
7621 char base_xpath[XPATH_MAXLEN];
554b3b10 7622 safi_t safi = bgp_node_safi(vty);
554b3b10 7623 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7624
554b3b10
RZ
7625 if (addr_str) {
7626 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7627 == 0) {
7628 vty_out(vty, "%% Inconsistent address and mask\n");
7629 return CMD_WARNING_CONFIG_FAILED;
7630 }
37a87b8f
CS
7631 } else {
7632 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7633 }
7634
37a87b8f
CS
7635 if (!no && origin_s)
7636 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7637
7638 if (!no && as_set_s)
7639 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7640 else
7641 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7642
7643 if (!no && summary_only)
7644 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7645 "true");
7646 else
7647 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7648 "false");
7649
fa423774
CS
7650 if (!no && match_med)
7651 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7652 else
7653 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7654 "false");
7655
37a87b8f
CS
7656 if (rmap_name)
7657 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7658 rmap_name);
7659 else
7660 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7661 NB_OP_DESTROY, NULL);
7662
90e21f35
CS
7663 if (suppress_map)
7664 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7665 suppress_map);
7666 else
7667 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7668 NULL);
7669
37a87b8f
CS
7670 snprintf(
7671 base_xpath, sizeof(base_xpath),
7672 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7673 yang_afi_safi_value2identity(AFI_IP, safi),
7674 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7675
554b3b10 7676 if (no)
37a87b8f
CS
7677 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7678 else
7679 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7680
7681 return nb_cli_apply_changes(vty, base_xpath);
7682}
7683
7684DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7685 "[no] aggregate-address X:X::X:X/M$prefix {"
7686 "as-set$as_set_s"
7687 "|summary-only$summary_only"
7688 "|route-map WORD$rmap_name"
7689 "|origin <egp|igp|incomplete>$origin_s"
7690 "|matching-MED-only$match_med"
90e21f35 7691 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7692 "}",
7693 NO_STR
7694 "Configure BGP aggregate entries\n"
7695 "Aggregate prefix\n"
7696 "Generate AS set path information\n"
7697 "Filter more specific routes from updates\n"
7698 "Apply route map to aggregate network\n"
7699 "Route map name\n"
7700 "BGP origin code\n"
7701 "Remote EGP\n"
7702 "Local IGP\n"
7703 "Unknown heritage\n"
7704 "Only aggregate routes with matching MED\n"
7705 "Suppress the selected more specific routes\n"
90e21f35 7706 "Route map with the route selectors\n")
37a87b8f
CS
7707{
7708 char base_xpath[XPATH_MAXLEN];
7709 safi_t safi = bgp_node_safi(vty);
7710
7711 if (!no && origin_s)
7712 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7713
7714 if (!no && as_set_s)
7715 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7716 else
7717 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7718
7719 if (!no && summary_only)
7720 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7721 "true");
7722 else
7723 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7724 "false");
7725
fa423774
CS
7726 if (!no && match_med)
7727 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7728 else
7729 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7730 "false");
7731
37a87b8f
CS
7732 if (rmap_name)
7733 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7734 rmap_name);
7735
90e21f35
CS
7736 if (suppress_map)
7737 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7738 suppress_map);
7739 else
7740 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7741 NULL);
7742
37a87b8f
CS
7743 snprintf(
7744 base_xpath, sizeof(base_xpath),
7745 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7746 yang_afi_safi_value2identity(AFI_IP6, safi),
7747 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7748
554b3b10 7749 if (no)
37a87b8f
CS
7750 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7751 else
7752 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7753
37a87b8f
CS
7754 return nb_cli_apply_changes(vty, base_xpath);
7755}
7756
7757void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7758 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7759{
7760 uint8_t origin;
7761
7762 vty_out(vty, " aggregate-address %s",
7763 yang_dnode_get_string(dnode, "./prefix"));
7764
7765 if (yang_dnode_get_bool(dnode, "./as-set"))
7766 vty_out(vty, " as-set");
7767
7768 if (yang_dnode_get_bool(dnode, "./summary-only"))
7769 vty_out(vty, " summary-only");
7770
7771 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7772 vty_out(vty, " route-map %s",
7773 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7774
7775 origin = yang_dnode_get_enum(dnode, "./origin");
7776 if (origin != BGP_ORIGIN_UNSPECIFIED)
7777 vty_out(vty, " origin %s", bgp_origin2str(origin));
7778
fa423774
CS
7779 if (yang_dnode_get_bool(dnode, "./match-med"))
7780 vty_out(vty, " matching-MED-only");
7781
37a87b8f 7782 vty_out(vty, "\n");
718e3744 7783}
7784
718e3744 7785/* Redistribute route treatment. */
d62a17ae 7786void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7787 const union g_addr *nexthop, ifindex_t ifindex,
7788 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7789 uint8_t type, unsigned short instance,
7790 route_tag_t tag)
d62a17ae 7791{
4b7e6066 7792 struct bgp_path_info *new;
40381db7
DS
7793 struct bgp_path_info *bpi;
7794 struct bgp_path_info rmap_path;
9bcb3eef 7795 struct bgp_dest *bn;
d62a17ae 7796 struct attr attr;
7797 struct attr *new_attr;
7798 afi_t afi;
b68885f9 7799 route_map_result_t ret;
d62a17ae 7800 struct bgp_redist *red;
7801
7802 /* Make default attribute. */
7803 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7804 /*
7805 * This must not be NULL to satisfy Coverity SA
7806 */
7807 assert(attr.aspath);
9de1f7ff 7808
a4d82a8a 7809 switch (nhtype) {
9de1f7ff
DS
7810 case NEXTHOP_TYPE_IFINDEX:
7811 break;
7812 case NEXTHOP_TYPE_IPV4:
7813 case NEXTHOP_TYPE_IPV4_IFINDEX:
7814 attr.nexthop = nexthop->ipv4;
7815 break;
7816 case NEXTHOP_TYPE_IPV6:
7817 case NEXTHOP_TYPE_IPV6_IFINDEX:
7818 attr.mp_nexthop_global = nexthop->ipv6;
7819 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7820 break;
7821 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7822 switch (p->family) {
7823 case AF_INET:
9de1f7ff 7824 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7825 break;
7826 case AF_INET6:
9de1f7ff
DS
7827 memset(&attr.mp_nexthop_global, 0,
7828 sizeof(attr.mp_nexthop_global));
74489921 7829 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7830 break;
74489921 7831 }
9de1f7ff 7832 break;
d62a17ae 7833 }
74489921 7834 attr.nh_ifindex = ifindex;
f04a80a5 7835
d62a17ae 7836 attr.med = metric;
7837 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7838 attr.tag = tag;
718e3744 7839
d62a17ae 7840 afi = family2afi(p->family);
6aeb9e78 7841
d62a17ae 7842 red = bgp_redist_lookup(bgp, afi, type, instance);
7843 if (red) {
7844 struct attr attr_new;
718e3744 7845
d62a17ae 7846 /* Copy attribute for modification. */
6f4f49b2 7847 attr_new = attr;
718e3744 7848
d62a17ae 7849 if (red->redist_metric_flag)
7850 attr_new.med = red->redist_metric;
718e3744 7851
d62a17ae 7852 /* Apply route-map. */
7853 if (red->rmap.name) {
40381db7
DS
7854 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7855 rmap_path.peer = bgp->peer_self;
7856 rmap_path.attr = &attr_new;
718e3744 7857
d62a17ae 7858 SET_FLAG(bgp->peer_self->rmap_type,
7859 PEER_RMAP_TYPE_REDISTRIBUTE);
7860
1782514f 7861 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 7862
7863 bgp->peer_self->rmap_type = 0;
7864
7865 if (ret == RMAP_DENYMATCH) {
7866 /* Free uninterned attribute. */
7867 bgp_attr_flush(&attr_new);
7868
7869 /* Unintern original. */
7870 aspath_unintern(&attr.aspath);
7871 bgp_redistribute_delete(bgp, p, type, instance);
7872 return;
7873 }
7874 }
7875
637e5ba4 7876 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
7877 bgp_attr_add_gshut_community(&attr_new);
7878
d62a17ae 7879 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7880 SAFI_UNICAST, p, NULL);
7881
7882 new_attr = bgp_attr_intern(&attr_new);
7883
9bcb3eef 7884 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7885 if (bpi->peer == bgp->peer_self
7886 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7887 break;
7888
40381db7 7889 if (bpi) {
d62a17ae 7890 /* Ensure the (source route) type is updated. */
40381db7
DS
7891 bpi->type = type;
7892 if (attrhash_cmp(bpi->attr, new_attr)
7893 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7894 bgp_attr_unintern(&new_attr);
7895 aspath_unintern(&attr.aspath);
9bcb3eef 7896 bgp_dest_unlock_node(bn);
d62a17ae 7897 return;
7898 } else {
7899 /* The attribute is changed. */
40381db7 7900 bgp_path_info_set_flag(bn, bpi,
18ee8310 7901 BGP_PATH_ATTR_CHANGED);
d62a17ae 7902
7903 /* Rewrite BGP route information. */
40381db7
DS
7904 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7905 bgp_path_info_restore(bn, bpi);
d62a17ae 7906 else
40381db7
DS
7907 bgp_aggregate_decrement(
7908 bgp, p, bpi, afi, SAFI_UNICAST);
7909 bgp_attr_unintern(&bpi->attr);
7910 bpi->attr = new_attr;
7911 bpi->uptime = bgp_clock();
d62a17ae 7912
7913 /* Process change. */
40381db7 7914 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7915 SAFI_UNICAST);
7916 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7917 bgp_dest_unlock_node(bn);
d62a17ae 7918 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7919
7920 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7921 || (bgp->inst_type
7922 == BGP_INSTANCE_TYPE_DEFAULT)) {
7923
7924 vpn_leak_from_vrf_update(
40381db7 7925 bgp_get_default(), bgp, bpi);
ddb5b488 7926 }
d62a17ae 7927 return;
7928 }
7929 }
7930
7931 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7932 bgp->peer_self, new_attr, bn);
1defdda8 7933 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7934
7935 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7936 bgp_path_info_add(bn, new);
9bcb3eef 7937 bgp_dest_unlock_node(bn);
d62a17ae 7938 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7939
7940 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7941 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7942
7943 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7944 }
d62a17ae 7945 }
7946
7947 /* Unintern original. */
7948 aspath_unintern(&attr.aspath);
718e3744 7949}
7950
d7c0a89a
QY
7951void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7952 unsigned short instance)
718e3744 7953{
d62a17ae 7954 afi_t afi;
9bcb3eef 7955 struct bgp_dest *dest;
40381db7 7956 struct bgp_path_info *pi;
d62a17ae 7957 struct bgp_redist *red;
718e3744 7958
d62a17ae 7959 afi = family2afi(p->family);
718e3744 7960
d62a17ae 7961 red = bgp_redist_lookup(bgp, afi, type, instance);
7962 if (red) {
9bcb3eef
DS
7963 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7964 SAFI_UNICAST, p, NULL);
d62a17ae 7965
9bcb3eef 7966 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7967 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7968 break;
7969
40381db7 7970 if (pi) {
ddb5b488
PZ
7971 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7972 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7973
7974 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7975 bgp, pi);
ddb5b488 7976 }
40381db7 7977 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7978 bgp_path_info_delete(dest, pi);
7979 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7980 }
9bcb3eef 7981 bgp_dest_unlock_node(dest);
d62a17ae 7982 }
7983}
7984
7985/* Withdraw specified route type's route. */
7986void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7987 unsigned short instance)
d62a17ae 7988{
9bcb3eef 7989 struct bgp_dest *dest;
40381db7 7990 struct bgp_path_info *pi;
d62a17ae 7991 struct bgp_table *table;
7992
7993 table = bgp->rib[afi][SAFI_UNICAST];
7994
9bcb3eef
DS
7995 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7996 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7997 if (pi->peer == bgp->peer_self && pi->type == type
7998 && pi->instance == instance)
d62a17ae 7999 break;
8000
40381db7 8001 if (pi) {
ddb5b488
PZ
8002 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8003 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8004
8005 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8006 bgp, pi);
ddb5b488 8007 }
9bcb3eef 8008 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8009 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8010 bgp_path_info_delete(dest, pi);
8011 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8012 }
718e3744 8013 }
718e3744 8014}
6b0655a2 8015
718e3744 8016/* Static function to display route. */
bd494ec5 8017static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8018 json_object *json, bool wide)
718e3744 8019{
be054588 8020 int len = 0;
d62a17ae 8021 char buf[BUFSIZ];
50e05855 8022 char buf2[BUFSIZ];
718e3744 8023
d62a17ae 8024 if (p->family == AF_INET) {
c6462ff4 8025 if (!json) {
8228a9a7 8026 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8027 } else {
8028 json_object_string_add(json, "prefix",
8029 inet_ntop(p->family,
8030 &p->u.prefix, buf,
8031 BUFSIZ));
8032 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8033 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8034 json_object_string_add(json, "network", buf2);
c6462ff4 8035 }
d62a17ae 8036 } else if (p->family == AF_ETHERNET) {
8228a9a7 8037 len = vty_out(vty, "%pFX", p);
b03b8898 8038 } else if (p->family == AF_EVPN) {
57f7feb6 8039 if (!json)
2dbe669b 8040 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8041 else
60466a63 8042 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8043 } else if (p->family == AF_FLOWSPEC) {
8044 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8045 json ?
8046 NLRI_STRING_FORMAT_JSON_SIMPLE :
8047 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8048 } else {
c6462ff4 8049 if (!json)
8228a9a7 8050 len = vty_out(vty, "%pFX", p);
50e05855
AD
8051 else {
8052 json_object_string_add(json, "prefix",
8053 inet_ntop(p->family,
8054 &p->u.prefix, buf,
8055 BUFSIZ));
8056 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8057 prefix2str(p, buf2, PREFIX_STRLEN);
8058 json_object_string_add(json, "network", buf2);
8059 }
9c92b5f7 8060 }
d62a17ae 8061
9c92b5f7 8062 if (!json) {
ae248832 8063 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8064 if (len < 1)
8065 vty_out(vty, "\n%*s", 20, " ");
8066 else
8067 vty_out(vty, "%*s", len, " ");
8068 }
718e3744 8069}
8070
d62a17ae 8071enum bgp_display_type {
8072 normal_list,
718e3744 8073};
8074
bbb46eb5
DA
8075static const char *
8076bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8077{
8078 switch (reason) {
8079 case bgp_path_selection_none:
8080 return "Nothing to Select";
8081 case bgp_path_selection_first:
8082 return "First path received";
8083 case bgp_path_selection_evpn_sticky_mac:
8084 return "EVPN Sticky Mac";
8085 case bgp_path_selection_evpn_seq:
8086 return "EVPN sequence number";
8087 case bgp_path_selection_evpn_lower_ip:
8088 return "EVPN lower IP";
8089 case bgp_path_selection_evpn_local_path:
8090 return "EVPN local ES path";
8091 case bgp_path_selection_evpn_non_proxy:
8092 return "EVPN non proxy";
8093 case bgp_path_selection_weight:
8094 return "Weight";
8095 case bgp_path_selection_local_pref:
8096 return "Local Pref";
8097 case bgp_path_selection_local_route:
8098 return "Local Route";
8099 case bgp_path_selection_confed_as_path:
8100 return "Confederation based AS Path";
8101 case bgp_path_selection_as_path:
8102 return "AS Path";
8103 case bgp_path_selection_origin:
8104 return "Origin";
8105 case bgp_path_selection_med:
8106 return "MED";
8107 case bgp_path_selection_peer:
8108 return "Peer Type";
8109 case bgp_path_selection_confed:
8110 return "Confed Peer Type";
8111 case bgp_path_selection_igp_metric:
8112 return "IGP Metric";
8113 case bgp_path_selection_older:
8114 return "Older Path";
8115 case bgp_path_selection_router_id:
8116 return "Router ID";
8117 case bgp_path_selection_cluster_length:
8118 return "Cluser length";
8119 case bgp_path_selection_stale:
8120 return "Path Staleness";
8121 case bgp_path_selection_local_configured:
8122 return "Locally configured route";
8123 case bgp_path_selection_neighbor_ip:
8124 return "Neighbor IP";
8125 case bgp_path_selection_default:
8126 return "Nothing left to compare";
8127 }
8128 return "Invalid (internal error)";
8129}
8130
18ee8310 8131/* Print the short form route status for a bgp_path_info */
4b7e6066 8132static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8133 struct bgp_path_info *path,
d62a17ae 8134 json_object *json_path)
718e3744 8135{
d62a17ae 8136 if (json_path) {
b05a1c8b 8137
d62a17ae 8138 /* Route status display. */
9b6d8fcf 8139 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8140 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8141
9b6d8fcf 8142 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8143 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8144
4056a5f6 8145 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8146 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8147
9b6d8fcf
DS
8148 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8149 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8150 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8151
d62a17ae 8152 /* Selected */
9b6d8fcf 8153 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8154 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8155
9b6d8fcf 8156 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8157 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8158
bbb46eb5 8159 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8160 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8161 json_object_string_add(json_path, "selectionReason",
8162 bgp_path_selection_reason2str(
8163 path->net->reason));
8164 }
b05a1c8b 8165
9b6d8fcf 8166 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8167 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8168
d62a17ae 8169 /* Internal route. */
9b6d8fcf
DS
8170 if ((path->peer->as)
8171 && (path->peer->as == path->peer->local_as))
d62a17ae 8172 json_object_string_add(json_path, "pathFrom",
8173 "internal");
8174 else
8175 json_object_string_add(json_path, "pathFrom",
8176 "external");
b05a1c8b 8177
d62a17ae 8178 return;
8179 }
b05a1c8b 8180
d62a17ae 8181 /* Route status display. */
9b6d8fcf 8182 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8183 vty_out(vty, "R");
9b6d8fcf 8184 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8185 vty_out(vty, "S");
4056a5f6 8186 else if (bgp_path_suppressed(path))
d62a17ae 8187 vty_out(vty, "s");
9b6d8fcf
DS
8188 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8189 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8190 vty_out(vty, "*");
8191 else
8192 vty_out(vty, " ");
8193
8194 /* Selected */
9b6d8fcf 8195 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8196 vty_out(vty, "h");
9b6d8fcf 8197 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8198 vty_out(vty, "d");
9b6d8fcf 8199 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8200 vty_out(vty, ">");
9b6d8fcf 8201 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8202 vty_out(vty, "=");
8203 else
8204 vty_out(vty, " ");
718e3744 8205
d62a17ae 8206 /* Internal route. */
9b6d8fcf
DS
8207 if (path->peer && (path->peer->as)
8208 && (path->peer->as == path->peer->local_as))
d62a17ae 8209 vty_out(vty, "i");
8210 else
8211 vty_out(vty, " ");
b40d939b 8212}
8213
2ba93fd6
DA
8214static char *bgp_nexthop_hostname(struct peer *peer,
8215 struct bgp_nexthop_cache *bnc)
25b5da8d 8216{
892fedb6 8217 if (peer->hostname
aef999a2 8218 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8219 return peer->hostname;
8220 return NULL;
8221}
8222
b40d939b 8223/* called from terminal list command */
bd494ec5 8224void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8225 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8226 json_object *json_paths, bool wide)
d62a17ae 8227{
aef999a2 8228 int len;
515c2602 8229 struct attr *attr = path->attr;
d62a17ae 8230 json_object *json_path = NULL;
8231 json_object *json_nexthops = NULL;
8232 json_object *json_nexthop_global = NULL;
8233 json_object *json_nexthop_ll = NULL;
6f214dd3 8234 json_object *json_ext_community = NULL;
9df8b37c 8235 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8236 bool nexthop_self =
9b6d8fcf 8237 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8238 bool nexthop_othervrf = false;
43089216 8239 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8240 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8241 char *nexthop_hostname =
8242 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8243 char esi_buf[ESI_STR_LEN];
d62a17ae 8244
8245 if (json_paths)
8246 json_path = json_object_new_object();
8247
8248 /* short status lead text */
9b6d8fcf 8249 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8250
8251 if (!json_paths) {
8252 /* print prefix and mask */
8253 if (!display)
ae248832 8254 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8255 else
ae248832 8256 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8257 } else {
ae248832 8258 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8259 }
47fc97cc 8260
9df8b37c
PZ
8261 /*
8262 * If vrf id of nexthop is different from that of prefix,
8263 * set up printable string to append
8264 */
9b6d8fcf 8265 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8266 const char *self = "";
8267
8268 if (nexthop_self)
8269 self = "<";
8270
8271 nexthop_othervrf = true;
9b6d8fcf 8272 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8273
9b6d8fcf 8274 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8275 snprintf(vrf_id_str, sizeof(vrf_id_str),
8276 "@%s%s", VRFID_NONE_STR, self);
8277 else
8278 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8279 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8280
9b6d8fcf
DS
8281 if (path->extra->bgp_orig->inst_type
8282 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8283
9b6d8fcf 8284 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8285 } else {
8286 const char *self = "";
8287
8288 if (nexthop_self)
8289 self = "<";
8290
8291 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8292 }
8293
445c2480
DS
8294 /*
8295 * For ENCAP and EVPN routes, nexthop address family is not
8296 * neccessarily the same as the prefix address family.
8297 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8298 * EVPN routes are also exchanged with a MP nexthop. Currently,
8299 * this
8300 * is only IPv4, the value will be present in either
8301 * attr->nexthop or
8302 * attr->mp_nexthop_global_in
8303 */
8304 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8305 char buf[BUFSIZ];
8306 char nexthop[128];
8307 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8308
8309 switch (af) {
8310 case AF_INET:
772270f3
QY
8311 snprintf(nexthop, sizeof(nexthop), "%s",
8312 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8313 BUFSIZ));
445c2480
DS
8314 break;
8315 case AF_INET6:
772270f3
QY
8316 snprintf(nexthop, sizeof(nexthop), "%s",
8317 inet_ntop(af, &attr->mp_nexthop_global, buf,
8318 BUFSIZ));
445c2480
DS
8319 break;
8320 default:
772270f3 8321 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8322 break;
d62a17ae 8323 }
d62a17ae 8324
445c2480
DS
8325 if (json_paths) {
8326 json_nexthop_global = json_object_new_object();
8327
515c2602
DA
8328 json_object_string_add(json_nexthop_global, "ip",
8329 nexthop);
8330
939a97f4 8331 if (path->peer->hostname)
515c2602
DA
8332 json_object_string_add(json_nexthop_global,
8333 "hostname",
939a97f4 8334 path->peer->hostname);
515c2602
DA
8335
8336 json_object_string_add(json_nexthop_global, "afi",
8337 (af == AF_INET) ? "ipv4"
8338 : "ipv6");
445c2480
DS
8339 json_object_boolean_true_add(json_nexthop_global,
8340 "used");
aef999a2
DA
8341 } else {
8342 if (nexthop_hostname)
8343 len = vty_out(vty, "%s(%s)%s", nexthop,
8344 nexthop_hostname, vrf_id_str);
8345 else
8346 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8347
ae248832 8348 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8349 if (len < 1)
8350 vty_out(vty, "\n%*s", 36, " ");
8351 else
8352 vty_out(vty, "%*s", len, " ");
8353 }
445c2480
DS
8354 } else if (safi == SAFI_EVPN) {
8355 if (json_paths) {
23d0a753
DA
8356 char buf[BUFSIZ] = {0};
8357
445c2480
DS
8358 json_nexthop_global = json_object_new_object();
8359
515c2602 8360 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8361 inet_ntop(AF_INET,
8362 &attr->nexthop, buf,
8363 sizeof(buf)));
515c2602 8364
939a97f4 8365 if (path->peer->hostname)
515c2602
DA
8366 json_object_string_add(json_nexthop_global,
8367 "hostname",
939a97f4 8368 path->peer->hostname);
515c2602 8369
a4d82a8a
PZ
8370 json_object_string_add(json_nexthop_global, "afi",
8371 "ipv4");
445c2480
DS
8372 json_object_boolean_true_add(json_nexthop_global,
8373 "used");
aef999a2
DA
8374 } else {
8375 if (nexthop_hostname)
8376 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8377 nexthop_hostname, vrf_id_str);
8378 else
8379 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8380 vrf_id_str);
8381
ae248832 8382 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8383 if (len < 1)
8384 vty_out(vty, "\n%*s", 36, " ");
8385 else
8386 vty_out(vty, "%*s", len, " ");
8387 }
d33fc23b 8388 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8389 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8390 if (json_paths) {
23d0a753
DA
8391 char buf[BUFSIZ] = {0};
8392
026b914a 8393 json_nexthop_global = json_object_new_object();
515c2602 8394
026b914a
PG
8395 json_object_string_add(json_nexthop_global,
8396 "afi", "ipv4");
515c2602
DA
8397 json_object_string_add(
8398 json_nexthop_global, "ip",
23d0a753
DA
8399 inet_ntop(AF_INET, &attr->nexthop, buf,
8400 sizeof(buf)));
515c2602 8401
939a97f4 8402 if (path->peer->hostname)
515c2602
DA
8403 json_object_string_add(
8404 json_nexthop_global, "hostname",
939a97f4 8405 path->peer->hostname);
515c2602 8406
50e05855
AD
8407 json_object_boolean_true_add(
8408 json_nexthop_global,
026b914a
PG
8409 "used");
8410 } else {
aef999a2
DA
8411 if (nexthop_hostname)
8412 len = vty_out(vty, "%pI4(%s)%s",
8413 &attr->nexthop,
8414 nexthop_hostname,
8415 vrf_id_str);
8416 else
8417 len = vty_out(vty, "%pI4%s",
8418 &attr->nexthop,
8419 vrf_id_str);
8420
ae248832 8421 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8422 if (len < 1)
8423 vty_out(vty, "\n%*s", 36, " ");
8424 else
8425 vty_out(vty, "%*s", len, " ");
026b914a
PG
8426 }
8427 }
d33fc23b 8428 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8429 if (json_paths) {
23d0a753
DA
8430 char buf[BUFSIZ] = {0};
8431
445c2480 8432 json_nexthop_global = json_object_new_object();
d62a17ae 8433
515c2602 8434 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8435 inet_ntop(AF_INET,
8436 &attr->nexthop, buf,
8437 sizeof(buf)));
515c2602 8438
939a97f4 8439 if (path->peer->hostname)
515c2602
DA
8440 json_object_string_add(json_nexthop_global,
8441 "hostname",
939a97f4 8442 path->peer->hostname);
445c2480 8443
a4d82a8a
PZ
8444 json_object_string_add(json_nexthop_global, "afi",
8445 "ipv4");
445c2480
DS
8446 json_object_boolean_true_add(json_nexthop_global,
8447 "used");
8448 } else {
aef999a2
DA
8449 if (nexthop_hostname)
8450 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8451 nexthop_hostname, vrf_id_str);
8452 else
8453 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8454 vrf_id_str);
9df8b37c 8455
ae248832 8456 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8457 if (len < 1)
8458 vty_out(vty, "\n%*s", 36, " ");
8459 else
8460 vty_out(vty, "%*s", len, " ");
d62a17ae 8461 }
445c2480 8462 }
b05a1c8b 8463
445c2480 8464 /* IPv6 Next Hop */
a4d82a8a 8465 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8466 char buf[BUFSIZ];
d62a17ae 8467
445c2480
DS
8468 if (json_paths) {
8469 json_nexthop_global = json_object_new_object();
a4d82a8a 8470 json_object_string_add(
515c2602
DA
8471 json_nexthop_global, "ip",
8472 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8473 buf, BUFSIZ));
8474
939a97f4 8475 if (path->peer->hostname)
515c2602
DA
8476 json_object_string_add(json_nexthop_global,
8477 "hostname",
939a97f4 8478 path->peer->hostname);
515c2602 8479
a4d82a8a
PZ
8480 json_object_string_add(json_nexthop_global, "afi",
8481 "ipv6");
8482 json_object_string_add(json_nexthop_global, "scope",
8483 "global");
445c2480
DS
8484
8485 /* We display both LL & GL if both have been
8486 * received */
0606039c
DA
8487 if ((attr->mp_nexthop_len
8488 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8489 || (path->peer->conf_if)) {
a4d82a8a 8490 json_nexthop_ll = json_object_new_object();
d62a17ae 8491 json_object_string_add(
515c2602
DA
8492 json_nexthop_ll, "ip",
8493 inet_ntop(AF_INET6,
8494 &attr->mp_nexthop_local, buf,
8495 BUFSIZ));
8496
939a97f4 8497 if (path->peer->hostname)
515c2602
DA
8498 json_object_string_add(
8499 json_nexthop_ll, "hostname",
939a97f4 8500 path->peer->hostname);
515c2602 8501
a4d82a8a
PZ
8502 json_object_string_add(json_nexthop_ll, "afi",
8503 "ipv6");
8504 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8505 "link-local");
d62a17ae 8506
a4d82a8a
PZ
8507 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8508 &attr->mp_nexthop_local)
445c2480
DS
8509 != 0)
8510 && !attr->mp_nexthop_prefer_global)
d62a17ae 8511 json_object_boolean_true_add(
a4d82a8a 8512 json_nexthop_ll, "used");
445c2480
DS
8513 else
8514 json_object_boolean_true_add(
a4d82a8a 8515 json_nexthop_global, "used");
445c2480
DS
8516 } else
8517 json_object_boolean_true_add(
8518 json_nexthop_global, "used");
8519 } else {
8520 /* Display LL if LL/Global both in table unless
8521 * prefer-global is set */
0606039c
DA
8522 if (((attr->mp_nexthop_len
8523 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8524 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8525 || (path->peer->conf_if)) {
8526 if (path->peer->conf_if) {
a4d82a8a 8527 len = vty_out(vty, "%s",
9b6d8fcf 8528 path->peer->conf_if);
ae248832
MK
8529 /* len of IPv6 addr + max len of def
8530 * ifname */
8531 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8532
8533 if (len < 1)
a4d82a8a 8534 vty_out(vty, "\n%*s", 36, " ");
445c2480 8535 else
a4d82a8a 8536 vty_out(vty, "%*s", len, " ");
d62a17ae 8537 } else {
aef999a2
DA
8538 if (nexthop_hostname)
8539 len = vty_out(
8540 vty, "%pI6(%s)%s",
8541 &attr->mp_nexthop_local,
8542 nexthop_hostname,
8543 vrf_id_str);
8544 else
8545 len = vty_out(
8546 vty, "%pI6%s",
8547 &attr->mp_nexthop_local,
8548 vrf_id_str);
8549
ae248832 8550 len = wide ? (41 - len) : (16 - len);
d62a17ae 8551
8552 if (len < 1)
a4d82a8a 8553 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8554 else
a4d82a8a 8555 vty_out(vty, "%*s", len, " ");
d62a17ae 8556 }
445c2480 8557 } else {
aef999a2
DA
8558 if (nexthop_hostname)
8559 len = vty_out(vty, "%pI6(%s)%s",
8560 &attr->mp_nexthop_global,
8561 nexthop_hostname,
8562 vrf_id_str);
8563 else
8564 len = vty_out(vty, "%pI6%s",
8565 &attr->mp_nexthop_global,
8566 vrf_id_str);
8567
ae248832 8568 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8569
8570 if (len < 1)
8571 vty_out(vty, "\n%*s", 36, " ");
8572 else
8573 vty_out(vty, "%*s", len, " ");
d62a17ae 8574 }
8575 }
445c2480 8576 }
718e3744 8577
445c2480
DS
8578 /* MED/Metric */
8579 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8580 if (json_paths)
50e05855 8581 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8582 else if (wide)
8583 vty_out(vty, "%7u", attr->med);
0fbac0b4 8584 else
445c2480 8585 vty_out(vty, "%10u", attr->med);
ae248832
MK
8586 else if (!json_paths) {
8587 if (wide)
8588 vty_out(vty, "%*s", 7, " ");
8589 else
8590 vty_out(vty, "%*s", 10, " ");
8591 }
d62a17ae 8592
445c2480
DS
8593 /* Local Pref */
8594 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8595 if (json_paths)
50e05855 8596 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8597 attr->local_pref);
8598 else
445c2480
DS
8599 vty_out(vty, "%7u", attr->local_pref);
8600 else if (!json_paths)
8601 vty_out(vty, " ");
d62a17ae 8602
445c2480
DS
8603 if (json_paths)
8604 json_object_int_add(json_path, "weight", attr->weight);
8605 else
8606 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8607
445c2480
DS
8608 if (json_paths) {
8609 char buf[BUFSIZ];
a4d82a8a
PZ
8610 json_object_string_add(
8611 json_path, "peerId",
9b6d8fcf 8612 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8613 }
b05a1c8b 8614
445c2480
DS
8615 /* Print aspath */
8616 if (attr->aspath) {
0fbac0b4 8617 if (json_paths)
50e05855 8618 json_object_string_add(json_path, "path",
0fbac0b4
DA
8619 attr->aspath->str);
8620 else
445c2480 8621 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8622 }
f1aa5d8a 8623
445c2480
DS
8624 /* Print origin */
8625 if (json_paths)
a4d82a8a
PZ
8626 json_object_string_add(json_path, "origin",
8627 bgp_origin_long_str[attr->origin]);
445c2480
DS
8628 else
8629 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8630
9df8b37c 8631 if (json_paths) {
d071f237 8632 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8633 json_object_string_add(json_path, "esi",
8634 esi_to_str(&attr->esi,
8635 esi_buf, sizeof(esi_buf)));
8636 }
6f214dd3
CS
8637 if (safi == SAFI_EVPN &&
8638 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8639 json_ext_community = json_object_new_object();
8640 json_object_string_add(json_ext_community,
8641 "string",
8642 attr->ecommunity->str);
8643 json_object_object_add(json_path,
8644 "extendedCommunity",
8645 json_ext_community);
8646 }
8647
9df8b37c
PZ
8648 if (nexthop_self)
8649 json_object_boolean_true_add(json_path,
8650 "announceNexthopSelf");
8651 if (nexthop_othervrf) {
8652 json_object_string_add(json_path, "nhVrfName",
8653 nexthop_vrfname);
8654
8655 json_object_int_add(json_path, "nhVrfId",
8656 ((nexthop_vrfid == VRF_UNKNOWN)
8657 ? -1
8658 : (int)nexthop_vrfid));
8659 }
8660 }
8661
d62a17ae 8662 if (json_paths) {
8663 if (json_nexthop_global || json_nexthop_ll) {
8664 json_nexthops = json_object_new_array();
f1aa5d8a 8665
d62a17ae 8666 if (json_nexthop_global)
8667 json_object_array_add(json_nexthops,
8668 json_nexthop_global);
f1aa5d8a 8669
d62a17ae 8670 if (json_nexthop_ll)
8671 json_object_array_add(json_nexthops,
8672 json_nexthop_ll);
f1aa5d8a 8673
d62a17ae 8674 json_object_object_add(json_path, "nexthops",
8675 json_nexthops);
8676 }
8677
8678 json_object_array_add(json_paths, json_path);
8679 } else {
8680 vty_out(vty, "\n");
6f214dd3 8681
b5e140c8 8682 if (safi == SAFI_EVPN) {
229587fb
AK
8683 struct bgp_path_es_info *path_es_info = NULL;
8684
8685 if (path->extra)
8686 path_es_info = path->extra->es_info;
8687
d071f237 8688 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8689 /* XXX - add these params to the json out */
b5e140c8 8690 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8691 vty_out(vty, "ESI:%s",
8692 esi_to_str(&attr->esi, esi_buf,
8693 sizeof(esi_buf)));
8694 if (path_es_info && path_es_info->es)
8695 vty_out(vty, " VNI: %u",
8696 path_es_info->vni);
8697 vty_out(vty, "\n");
b5e140c8
AK
8698 }
8699 if (attr->flag &
8700 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8701 vty_out(vty, "%*s", 20, " ");
8702 vty_out(vty, "%s\n", attr->ecommunity->str);
8703 }
6f214dd3
CS
8704 }
8705
49e5a4a0 8706#ifdef ENABLE_BGP_VNC
d62a17ae 8707 /* prints an additional line, indented, with VNC info, if
8708 * present */
8709 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8710 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8711#endif
d62a17ae 8712 }
8713}
718e3744 8714
8715/* called from terminal list command */
5f040085
DS
8716void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8717 struct attr *attr, safi_t safi, bool use_json,
ae248832 8718 json_object *json_ar, bool wide)
d62a17ae 8719{
8720 json_object *json_status = NULL;
8721 json_object *json_net = NULL;
aef999a2 8722 int len;
d62a17ae 8723 char buff[BUFSIZ];
dc387b0f 8724
d62a17ae 8725 /* Route status display. */
8726 if (use_json) {
8727 json_status = json_object_new_object();
8728 json_net = json_object_new_object();
8729 } else {
8730 vty_out(vty, "*");
8731 vty_out(vty, ">");
8732 vty_out(vty, " ");
8733 }
718e3744 8734
d62a17ae 8735 /* print prefix and mask */
50e05855 8736 if (use_json) {
dc387b0f
LK
8737 if (safi == SAFI_EVPN)
8738 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8739 else if (p->family == AF_INET || p->family == AF_INET6) {
8740 json_object_string_add(
8741 json_net, "addrPrefix",
8742 inet_ntop(p->family, &p->u.prefix, buff,
8743 BUFSIZ));
8744 json_object_int_add(json_net, "prefixLen",
8745 p->prefixlen);
8746 prefix2str(p, buff, PREFIX_STRLEN);
8747 json_object_string_add(json_net, "network", buff);
8748 }
50e05855 8749 } else
ae248832 8750 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8751
8752 /* Print attribute */
8753 if (attr) {
8754 if (use_json) {
23d0a753
DA
8755 char buf[BUFSIZ] = {0};
8756
d62a17ae 8757 if (p->family == AF_INET
8758 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8759 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8760 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8761 json_object_string_add(
8762 json_net, "nextHop",
23d0a753
DA
8763 inet_ntop(
8764 AF_INET,
8765 &attr->mp_nexthop_global_in,
8766 buf, sizeof(buf)));
d62a17ae 8767 else
8768 json_object_string_add(
8769 json_net, "nextHop",
23d0a753
DA
8770 inet_ntop(AF_INET,
8771 &attr->nexthop, buf,
8772 sizeof(buf)));
d62a17ae 8773 } else if (p->family == AF_INET6
8774 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8775 char buf[BUFSIZ];
8776
8777 json_object_string_add(
aa0a10fc 8778 json_net, "nextHopGlobal",
d62a17ae 8779 inet_ntop(AF_INET6,
8780 &attr->mp_nexthop_global, buf,
8781 BUFSIZ));
23d0a753
DA
8782 } else if (p->family == AF_EVPN
8783 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8784 char buf[BUFSIZ] = {0};
8785
8786 json_object_string_add(
8787 json_net, "nextHop",
8788 inet_ntop(AF_INET,
8789 &attr->mp_nexthop_global_in,
8790 buf, sizeof(buf)));
8791 }
d62a17ae 8792
8793 if (attr->flag
8794 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8795 json_object_int_add(json_net, "metric",
8796 attr->med);
8797
0fbac0b4 8798 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8799 json_object_int_add(json_net, "locPrf",
0fbac0b4 8800 attr->local_pref);
d62a17ae 8801
8802 json_object_int_add(json_net, "weight", attr->weight);
8803
8804 /* Print aspath */
0fbac0b4 8805 if (attr->aspath)
50e05855 8806 json_object_string_add(json_net, "path",
0fbac0b4 8807 attr->aspath->str);
d62a17ae 8808
8809 /* Print origin */
8810 json_object_string_add(json_net, "bgpOriginCode",
8811 bgp_origin_str[attr->origin]);
8812 } else {
8813 if (p->family == AF_INET
8814 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8815 || safi == SAFI_EVPN
8816 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8817 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8818 || safi == SAFI_EVPN)
23d0a753
DA
8819 vty_out(vty, "%-16pI4",
8820 &attr->mp_nexthop_global_in);
ae248832 8821 else if (wide)
23d0a753 8822 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8823 else
23d0a753 8824 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8825 } else if (p->family == AF_INET6
8826 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8827 char buf[BUFSIZ];
8828
8829 len = vty_out(
8830 vty, "%s",
8831 inet_ntop(AF_INET6,
8832 &attr->mp_nexthop_global, buf,
8833 BUFSIZ));
ae248832 8834 len = wide ? (41 - len) : (16 - len);
d62a17ae 8835 if (len < 1)
8836 vty_out(vty, "\n%*s", 36, " ");
8837 else
8838 vty_out(vty, "%*s", len, " ");
8839 }
8840 if (attr->flag
8841 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8842 if (wide)
8843 vty_out(vty, "%7u", attr->med);
8844 else
8845 vty_out(vty, "%10u", attr->med);
8846 else if (wide)
8847 vty_out(vty, " ");
d62a17ae 8848 else
8849 vty_out(vty, " ");
718e3744 8850
d62a17ae 8851 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8852 vty_out(vty, "%7u", attr->local_pref);
8853 else
8854 vty_out(vty, " ");
8855
8856 vty_out(vty, "%7u ", attr->weight);
8857
8858 /* Print aspath */
8859 if (attr->aspath)
8860 aspath_print_vty(vty, "%s", attr->aspath, " ");
8861
8862 /* Print origin */
8863 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8864 }
8865 }
8866 if (use_json) {
8867 json_object_boolean_true_add(json_status, "*");
8868 json_object_boolean_true_add(json_status, ">");
8869 json_object_object_add(json_net, "appliedStatusSymbols",
8870 json_status);
1608ff77 8871
dc387b0f
LK
8872 prefix2str(p, buff, PREFIX_STRLEN);
8873 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8874 } else
8875 vty_out(vty, "\n");
8876}
8877
bd494ec5 8878void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8879 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8880 json_object *json)
8881{
8882 json_object *json_out = NULL;
8883 struct attr *attr;
8884 mpls_label_t label = MPLS_INVALID_LABEL;
8885
9b6d8fcf 8886 if (!path->extra)
d62a17ae 8887 return;
8888
8889 if (json)
8890 json_out = json_object_new_object();
8891
8892 /* short status lead text */
9b6d8fcf 8893 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8894
8895 /* print prefix and mask */
8896 if (json == NULL) {
8897 if (!display)
ae248832 8898 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8899 else
8900 vty_out(vty, "%*s", 17, " ");
8901 }
8902
8903 /* Print attribute */
9b6d8fcf 8904 attr = path->attr;
05864da7
DS
8905 if (((p->family == AF_INET)
8906 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8907 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8908 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
8909 char buf[BUFSIZ] = {0};
8910
05864da7
DS
8911 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8912 || safi == SAFI_EVPN) {
8913 if (json)
8914 json_object_string_add(
8915 json_out, "mpNexthopGlobalIn",
23d0a753
DA
8916 inet_ntop(AF_INET,
8917 &attr->mp_nexthop_global_in,
8918 buf, sizeof(buf)));
05864da7 8919 else
23d0a753
DA
8920 vty_out(vty, "%-16pI4",
8921 &attr->mp_nexthop_global_in);
05864da7
DS
8922 } else {
8923 if (json)
8924 json_object_string_add(
8925 json_out, "nexthop",
23d0a753
DA
8926 inet_ntop(AF_INET, &attr->nexthop, buf,
8927 sizeof(buf)));
05864da7 8928 else
23d0a753 8929 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
8930 }
8931 } else if (((p->family == AF_INET6)
8932 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8933 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8934 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8935 char buf_a[512];
8936
8937 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8938 if (json)
8939 json_object_string_add(
8940 json_out, "mpNexthopGlobalIn",
8941 inet_ntop(AF_INET6,
8942 &attr->mp_nexthop_global,
8943 buf_a, sizeof(buf_a)));
8944 else
8945 vty_out(vty, "%s",
8946 inet_ntop(AF_INET6,
8947 &attr->mp_nexthop_global,
8948 buf_a, sizeof(buf_a)));
8949 } else if (attr->mp_nexthop_len
8950 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8951 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8952 &attr->mp_nexthop_global,
8953 &attr->mp_nexthop_local);
8954 if (json)
8955 json_object_string_add(json_out,
8956 "mpNexthopGlobalLocal",
8957 buf_a);
8958 else
8959 vty_out(vty, "%s", buf_a);
d62a17ae 8960 }
8961 }
8962
9b6d8fcf 8963 label = decode_label(&path->extra->label[0]);
d62a17ae 8964
8965 if (bgp_is_valid_label(&label)) {
8966 if (json) {
8967 json_object_int_add(json_out, "notag", label);
8968 json_object_array_add(json, json_out);
8969 } else {
8970 vty_out(vty, "notag/%d", label);
8971 vty_out(vty, "\n");
8972 }
8973 }
8974}
718e3744 8975
bd494ec5 8976void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8977 struct bgp_path_info *path, int display,
d62a17ae 8978 json_object *json_paths)
718e3744 8979{
d62a17ae 8980 struct attr *attr;
14f51eba 8981 char buf[BUFSIZ] = {0};
d62a17ae 8982 json_object *json_path = NULL;
14f51eba
LK
8983 json_object *json_nexthop = NULL;
8984 json_object *json_overlay = NULL;
856ca177 8985
9b6d8fcf 8986 if (!path->extra)
d62a17ae 8987 return;
718e3744 8988
14f51eba
LK
8989 if (json_paths) {
8990 json_path = json_object_new_object();
8991 json_overlay = json_object_new_object();
8992 json_nexthop = json_object_new_object();
8993 }
8994
d62a17ae 8995 /* short status lead text */
9b6d8fcf 8996 route_vty_short_status_out(vty, path, json_path);
856ca177 8997
d62a17ae 8998 /* print prefix and mask */
8999 if (!display)
ae248832 9000 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9001 else
9002 vty_out(vty, "%*s", 17, " ");
9003
9004 /* Print attribute */
9b6d8fcf 9005 attr = path->attr;
05864da7
DS
9006 char buf1[BUFSIZ];
9007 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9008
05864da7
DS
9009 switch (af) {
9010 case AF_INET:
9011 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9012 if (!json_path) {
9013 vty_out(vty, "%-16s", buf);
9014 } else {
9015 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9016
05864da7 9017 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9018
05864da7
DS
9019 json_object_object_add(json_path, "nexthop",
9020 json_nexthop);
9021 }
9022 break;
9023 case AF_INET6:
9024 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9025 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9026 if (!json_path) {
9027 vty_out(vty, "%s(%s)", buf, buf1);
9028 } else {
9029 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9030
05864da7
DS
9031 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9032 buf1);
14f51eba 9033
05864da7 9034 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9035
05864da7
DS
9036 json_object_object_add(json_path, "nexthop",
9037 json_nexthop);
9038 }
9039 break;
9040 default:
9041 if (!json_path) {
9042 vty_out(vty, "?");
9043 } else {
9044 json_object_string_add(json_nexthop, "Error",
9045 "Unsupported address-family");
d62a17ae 9046 }
05864da7 9047 }
988258b4 9048
6c924775
DS
9049 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9050
9051 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9052 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9053 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9054 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9055
05864da7
DS
9056 if (!json_path)
9057 vty_out(vty, "/%s", buf);
9058 else
9059 json_object_string_add(json_overlay, "gw", buf);
9060
9061 if (attr->ecommunity) {
9062 char *mac = NULL;
9063 struct ecommunity_val *routermac = ecommunity_lookup(
9064 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9065 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9066
9067 if (routermac)
9068 mac = ecom_mac2str((char *)routermac->val);
9069 if (mac) {
9070 if (!json_path) {
c4efd0f4 9071 vty_out(vty, "/%s", mac);
05864da7
DS
9072 } else {
9073 json_object_string_add(json_overlay, "rmac",
9074 mac);
988258b4 9075 }
05864da7 9076 XFREE(MTYPE_TMP, mac);
988258b4 9077 }
05864da7 9078 }
718e3744 9079
05864da7
DS
9080 if (!json_path) {
9081 vty_out(vty, "\n");
9082 } else {
9083 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9084
05864da7 9085 json_object_array_add(json_paths, json_path);
14f51eba 9086 }
d62a17ae 9087}
718e3744 9088
d62a17ae 9089/* dampening route */
5f040085
DS
9090static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9091 struct bgp_path_info *path, int display,
9092 afi_t afi, safi_t safi, bool use_json,
9093 json_object *json)
d62a17ae 9094{
9095 struct attr *attr;
9096 int len;
9097 char timebuf[BGP_UPTIME_LEN];
9098
9099 /* short status lead text */
9b6d8fcf 9100 route_vty_short_status_out(vty, path, json);
d62a17ae 9101
9102 /* print prefix and mask */
9103 if (!use_json) {
9104 if (!display)
ae248832 9105 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9106 else
9107 vty_out(vty, "%*s", 17, " ");
9108 }
9109
9b6d8fcf 9110 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9111 len = 17 - len;
9112 if (len < 1) {
9113 if (!use_json)
9114 vty_out(vty, "\n%*s", 34, " ");
9115 } else {
9116 if (use_json)
9117 json_object_int_add(json, "peerHost", len);
9118 else
9119 vty_out(vty, "%*s", len, " ");
9120 }
9121
9122 if (use_json)
a935f597
DA
9123 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9124 safi, use_json, json);
d62a17ae 9125 else
9b6d8fcf
DS
9126 vty_out(vty, "%s ",
9127 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9128 BGP_UPTIME_LEN, afi, safi,
9129 use_json, json));
d62a17ae 9130
9131 /* Print attribute */
9b6d8fcf 9132 attr = path->attr;
d62a17ae 9133
05864da7
DS
9134 /* Print aspath */
9135 if (attr->aspath) {
d62a17ae 9136 if (use_json)
05864da7
DS
9137 json_object_string_add(json, "asPath",
9138 attr->aspath->str);
d62a17ae 9139 else
05864da7 9140 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9141 }
05864da7
DS
9142
9143 /* Print origin */
9144 if (use_json)
9145 json_object_string_add(json, "origin",
9146 bgp_origin_str[attr->origin]);
9147 else
9148 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9149
d62a17ae 9150 if (!use_json)
9151 vty_out(vty, "\n");
9152}
718e3744 9153
d62a17ae 9154/* flap route */
5f040085
DS
9155static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9156 struct bgp_path_info *path, int display,
9157 afi_t afi, safi_t safi, bool use_json,
9158 json_object *json)
784d3a42 9159{
d62a17ae 9160 struct attr *attr;
9161 struct bgp_damp_info *bdi;
9162 char timebuf[BGP_UPTIME_LEN];
9163 int len;
784d3a42 9164
9b6d8fcf 9165 if (!path->extra)
d62a17ae 9166 return;
784d3a42 9167
9b6d8fcf 9168 bdi = path->extra->damp_info;
784d3a42 9169
d62a17ae 9170 /* short status lead text */
9b6d8fcf 9171 route_vty_short_status_out(vty, path, json);
784d3a42 9172
d62a17ae 9173 /* print prefix and mask */
9174 if (!use_json) {
9175 if (!display)
ae248832 9176 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9177 else
9178 vty_out(vty, "%*s", 17, " ");
9179 }
784d3a42 9180
9b6d8fcf 9181 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9182 len = 16 - len;
9183 if (len < 1) {
9184 if (!use_json)
9185 vty_out(vty, "\n%*s", 33, " ");
9186 } else {
9187 if (use_json)
9188 json_object_int_add(json, "peerHost", len);
9189 else
9190 vty_out(vty, "%*s", len, " ");
9191 }
784d3a42 9192
d62a17ae 9193 len = vty_out(vty, "%d", bdi->flap);
9194 len = 5 - len;
9195 if (len < 1) {
9196 if (!use_json)
9197 vty_out(vty, " ");
9198 } else {
9199 if (use_json)
9200 json_object_int_add(json, "bdiFlap", len);
9201 else
9202 vty_out(vty, "%*s", len, " ");
9203 }
9204
9205 if (use_json)
9206 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9207 json);
9208 else
996c9314
LB
9209 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9210 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9211
9b6d8fcf
DS
9212 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9213 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9214 if (use_json)
9b6d8fcf 9215 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9216 BGP_UPTIME_LEN, afi, safi,
9217 use_json, json);
d62a17ae 9218 else
9219 vty_out(vty, "%s ",
9b6d8fcf 9220 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9221 BGP_UPTIME_LEN, afi,
9222 safi, use_json, json));
d62a17ae 9223 } else {
9224 if (!use_json)
9225 vty_out(vty, "%*s ", 8, " ");
9226 }
9227
9228 /* Print attribute */
9b6d8fcf 9229 attr = path->attr;
d62a17ae 9230
05864da7
DS
9231 /* Print aspath */
9232 if (attr->aspath) {
d62a17ae 9233 if (use_json)
05864da7
DS
9234 json_object_string_add(json, "asPath",
9235 attr->aspath->str);
d62a17ae 9236 else
05864da7 9237 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9238 }
05864da7
DS
9239
9240 /* Print origin */
9241 if (use_json)
9242 json_object_string_add(json, "origin",
9243 bgp_origin_str[attr->origin]);
9244 else
9245 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9246
d62a17ae 9247 if (!use_json)
9248 vty_out(vty, "\n");
9249}
9250
9251static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9252 int *first, const char *header,
9253 json_object *json_adv_to)
9254{
9255 char buf1[INET6_ADDRSTRLEN];
9256 json_object *json_peer = NULL;
9257
9258 if (json_adv_to) {
9259 /* 'advertised-to' is a dictionary of peers we have advertised
9260 * this
9261 * prefix too. The key is the peer's IP or swpX, the value is
9262 * the
9263 * hostname if we know it and "" if not.
9264 */
9265 json_peer = json_object_new_object();
9266
9267 if (peer->hostname)
9268 json_object_string_add(json_peer, "hostname",
9269 peer->hostname);
9270
9271 if (peer->conf_if)
9272 json_object_object_add(json_adv_to, peer->conf_if,
9273 json_peer);
9274 else
9275 json_object_object_add(
9276 json_adv_to,
9277 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9278 json_peer);
9279 } else {
9280 if (*first) {
9281 vty_out(vty, "%s", header);
9282 *first = 0;
9283 }
9284
9285 if (peer->hostname
892fedb6 9286 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9287 if (peer->conf_if)
9288 vty_out(vty, " %s(%s)", peer->hostname,
9289 peer->conf_if);
9290 else
9291 vty_out(vty, " %s(%s)", peer->hostname,
9292 sockunion2str(&peer->su, buf1,
9293 SU_ADDRSTRLEN));
9294 } else {
9295 if (peer->conf_if)
9296 vty_out(vty, " %s", peer->conf_if);
9297 else
9298 vty_out(vty, " %s",
9299 sockunion2str(&peer->su, buf1,
9300 SU_ADDRSTRLEN));
9301 }
9302 }
784d3a42
PG
9303}
9304
dcc68b5e
MS
9305static void route_vty_out_tx_ids(struct vty *vty,
9306 struct bgp_addpath_info_data *d)
9307{
9308 int i;
9309
9310 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9311 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9312 d->addpath_tx_id[i],
9313 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9314 }
9315}
9316
5e4d4c8a 9317static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9318 struct bgp_path_info *pi,
9319 struct attr *attr,
9320 json_object *json_path)
5e4d4c8a
AK
9321{
9322 char esi_buf[ESI_STR_LEN];
9323 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9324 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9325 ATTR_ES_PEER_ROUTER);
9326 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9327 ATTR_ES_PEER_ACTIVE);
9328 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9329 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9330 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9331 if (json_path) {
9332 json_object *json_es_info = NULL;
9333
9334 json_object_string_add(
9335 json_path, "esi",
9336 esi_buf);
9337 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9338 json_es_info = json_object_new_object();
9339 if (es_local)
9340 json_object_boolean_true_add(
9341 json_es_info, "localEs");
9342 if (peer_active)
9343 json_object_boolean_true_add(
9344 json_es_info, "peerActive");
9345 if (peer_proxy)
9346 json_object_boolean_true_add(
9347 json_es_info, "peerProxy");
9348 if (peer_router)
9349 json_object_boolean_true_add(
9350 json_es_info, "peerRouter");
9351 if (attr->mm_sync_seqnum)
9352 json_object_int_add(
9353 json_es_info, "peerSeq",
9354 attr->mm_sync_seqnum);
9355 json_object_object_add(
9356 json_path, "es_info",
9357 json_es_info);
9358 }
9359 } else {
9360 if (bgp_evpn_attr_is_sync(attr))
9361 vty_out(vty,
9362 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9363 esi_buf,
9364 es_local ? "local-es":"",
9365 peer_proxy ? "proxy " : "",
9366 peer_active ? "active ":"",
9367 peer_router ? "router ":"",
9368 attr->mm_sync_seqnum);
9369 else
9370 vty_out(vty, " ESI %s %s\n",
9371 esi_buf,
9372 es_local ? "local-es":"");
9373 }
9374}
9375
9376void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9377 struct bgp_dest *bn, struct bgp_path_info *path,
9378 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9379{
9380 char buf[INET6_ADDRSTRLEN];
9381 char buf1[BUFSIZ];
515c2602 9382 struct attr *attr = path->attr;
d62a17ae 9383 int sockunion_vty_out(struct vty *, union sockunion *);
9384 time_t tbuf;
9385 json_object *json_bestpath = NULL;
9386 json_object *json_cluster_list = NULL;
9387 json_object *json_cluster_list_list = NULL;
9388 json_object *json_ext_community = NULL;
9389 json_object *json_last_update = NULL;
7fd077aa 9390 json_object *json_pmsi = NULL;
d62a17ae 9391 json_object *json_nexthop_global = NULL;
9392 json_object *json_nexthop_ll = NULL;
9393 json_object *json_nexthops = NULL;
9394 json_object *json_path = NULL;
9395 json_object *json_peer = NULL;
9396 json_object *json_string = NULL;
9397 json_object *json_adv_to = NULL;
9398 int first = 0;
9399 struct listnode *node, *nnode;
9400 struct peer *peer;
9401 int addpath_capable;
9402 int has_adj;
9403 unsigned int first_as;
1defdda8 9404 bool nexthop_self =
9b6d8fcf 9405 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9406 int i;
2ba93fd6
DA
9407 char *nexthop_hostname =
9408 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9409
9410 if (json_paths) {
9411 json_path = json_object_new_object();
9412 json_peer = json_object_new_object();
9413 json_nexthop_global = json_object_new_object();
9414 }
9415
44c69747 9416 if (path->extra) {
b57ba6d2 9417 char tag_buf[30];
d62a17ae 9418
d62a17ae 9419 tag_buf[0] = '\0';
9b6d8fcf
DS
9420 if (path->extra && path->extra->num_labels) {
9421 bgp_evpn_label2str(path->extra->label,
9422 path->extra->num_labels, tag_buf,
a4d82a8a 9423 sizeof(tag_buf));
d62a17ae 9424 }
d7325ee7 9425 if (safi == SAFI_EVPN) {
44c69747 9426 if (!json_paths) {
2dbe669b
DA
9427 vty_out(vty, " Route %pFX",
9428 (struct prefix_evpn *)
9429 bgp_dest_get_prefix(bn));
44c69747
LK
9430 if (tag_buf[0] != '\0')
9431 vty_out(vty, " VNI %s", tag_buf);
9432 vty_out(vty, "\n");
9433 } else {
9434 if (tag_buf[0])
9435 json_object_string_add(json_path, "VNI",
9436 tag_buf);
9437 }
d7325ee7
DD
9438 }
9439
44c69747 9440 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9441 struct bgp_path_info *parent_ri;
9bcb3eef 9442 struct bgp_dest *dest, *pdest;
d62a17ae 9443
9b6d8fcf 9444 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9445 dest = parent_ri->net;
9446 if (dest && dest->pdest) {
9447 pdest = dest->pdest;
9448 prefix_rd2str(
9449 (struct prefix_rd *)bgp_dest_get_prefix(
9450 pdest),
9451 buf1, sizeof(buf1));
d7325ee7 9452 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9453 vty_out(vty,
9454 " Imported from %s:%pFX, VNI %s\n",
9455 buf1,
9456 (struct prefix_evpn *)
9457 bgp_dest_get_prefix(
9458 dest),
9459 tag_buf);
d7325ee7 9460 } else
2dbe669b
DA
9461 vty_out(vty,
9462 " Imported from %s:%pFX\n",
9463 buf1,
9464 (struct prefix_evpn *)
9465 bgp_dest_get_prefix(
9466 dest));
d62a17ae 9467 }
9468 }
9469 }
d62a17ae 9470
05864da7
DS
9471 /* Line1 display AS-path, Aggregator */
9472 if (attr->aspath) {
9473 if (json_paths) {
9474 if (!attr->aspath->json)
9475 aspath_str_update(attr->aspath, true);
9476 json_object_lock(attr->aspath->json);
9477 json_object_object_add(json_path, "aspath",
9478 attr->aspath->json);
9479 } else {
9480 if (attr->aspath->segments)
9481 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9482 else
05864da7 9483 vty_out(vty, " Local");
d62a17ae 9484 }
05864da7 9485 }
d62a17ae 9486
05864da7
DS
9487 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9488 if (json_paths)
9489 json_object_boolean_true_add(json_path, "removed");
9490 else
9491 vty_out(vty, ", (removed)");
9492 }
d62a17ae 9493
05864da7
DS
9494 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9495 if (json_paths)
9496 json_object_boolean_true_add(json_path, "stale");
9497 else
9498 vty_out(vty, ", (stale)");
9499 }
d62a17ae 9500
05864da7
DS
9501 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9502 if (json_paths) {
23d0a753
DA
9503 char buf[BUFSIZ] = {0};
9504
05864da7
DS
9505 json_object_int_add(json_path, "aggregatorAs",
9506 attr->aggregator_as);
23d0a753
DA
9507 json_object_string_add(json_path, "aggregatorId",
9508 inet_ntop(AF_INET,
9509 &attr->aggregator_addr,
9510 buf, sizeof(buf)));
87c82131
DA
9511 if (attr->aggregator_as == BGP_AS_ZERO)
9512 json_object_boolean_true_add(
9513 json_path, "aggregatorAsMalformed");
9514 else
9515 json_object_boolean_false_add(
9516 json_path, "aggregatorAsMalformed");
05864da7 9517 } else {
87c82131
DA
9518 if (attr->aggregator_as == BGP_AS_ZERO)
9519 vty_out(vty,
23d0a753 9520 ", (aggregated by %u(malformed) %pI4)",
87c82131 9521 attr->aggregator_as,
23d0a753 9522 &attr->aggregator_addr);
87c82131 9523 else
23d0a753 9524 vty_out(vty, ", (aggregated by %u %pI4)",
87c82131 9525 attr->aggregator_as,
23d0a753 9526 &attr->aggregator_addr);
d62a17ae 9527 }
05864da7 9528 }
d62a17ae 9529
05864da7
DS
9530 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9531 PEER_FLAG_REFLECTOR_CLIENT)) {
9532 if (json_paths)
9533 json_object_boolean_true_add(json_path,
9534 "rxedFromRrClient");
9535 else
9536 vty_out(vty, ", (Received from a RR-client)");
9537 }
d62a17ae 9538
05864da7
DS
9539 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9540 PEER_FLAG_RSERVER_CLIENT)) {
9541 if (json_paths)
9542 json_object_boolean_true_add(json_path,
9543 "rxedFromRsClient");
9544 else
9545 vty_out(vty, ", (Received from a RS-client)");
9546 }
d62a17ae 9547
05864da7
DS
9548 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9549 if (json_paths)
9550 json_object_boolean_true_add(json_path,
9551 "dampeningHistoryEntry");
9552 else
9553 vty_out(vty, ", (history entry)");
9554 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9555 if (json_paths)
9556 json_object_boolean_true_add(json_path,
9557 "dampeningSuppressed");
9558 else
9559 vty_out(vty, ", (suppressed due to dampening)");
9560 }
d62a17ae 9561
05864da7
DS
9562 if (!json_paths)
9563 vty_out(vty, "\n");
d62a17ae 9564
05864da7
DS
9565 /* Line2 display Next-hop, Neighbor, Router-id */
9566 /* Display the nexthop */
9bcb3eef 9567 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9568
9569 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9570 || bn_p->family == AF_EVPN)
05864da7
DS
9571 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9572 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9573 char buf[BUFSIZ] = {0};
9574
05864da7
DS
9575 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9576 || safi == SAFI_EVPN) {
515c2602 9577 if (json_paths) {
d62a17ae 9578 json_object_string_add(
515c2602 9579 json_nexthop_global, "ip",
23d0a753
DA
9580 inet_ntop(AF_INET,
9581 &attr->mp_nexthop_global_in,
9582 buf, sizeof(buf)));
515c2602 9583
939a97f4 9584 if (path->peer->hostname)
515c2602
DA
9585 json_object_string_add(
9586 json_nexthop_global, "hostname",
939a97f4 9587 path->peer->hostname);
aef999a2
DA
9588 } else {
9589 if (nexthop_hostname)
9590 vty_out(vty, " %pI4(%s)",
9591 &attr->mp_nexthop_global_in,
9592 nexthop_hostname);
9593 else
9594 vty_out(vty, " %pI4",
9595 &attr->mp_nexthop_global_in);
9596 }
d62a17ae 9597 } else {
515c2602 9598 if (json_paths) {
05864da7 9599 json_object_string_add(
515c2602 9600 json_nexthop_global, "ip",
23d0a753
DA
9601 inet_ntop(AF_INET, &attr->nexthop, buf,
9602 sizeof(buf)));
515c2602 9603
939a97f4 9604 if (path->peer->hostname)
515c2602
DA
9605 json_object_string_add(
9606 json_nexthop_global, "hostname",
939a97f4 9607 path->peer->hostname);
aef999a2
DA
9608 } else {
9609 if (nexthop_hostname)
9610 vty_out(vty, " %pI4(%s)",
9611 &attr->nexthop,
9612 nexthop_hostname);
9613 else
9614 vty_out(vty, " %pI4",
9615 &attr->nexthop);
9616 }
d62a17ae 9617 }
9618
05864da7
DS
9619 if (json_paths)
9620 json_object_string_add(json_nexthop_global, "afi",
9621 "ipv4");
9622 } else {
9623 if (json_paths) {
9624 json_object_string_add(
515c2602
DA
9625 json_nexthop_global, "ip",
9626 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9627 buf, INET6_ADDRSTRLEN));
9628
939a97f4 9629 if (path->peer->hostname)
515c2602
DA
9630 json_object_string_add(json_nexthop_global,
9631 "hostname",
939a97f4 9632 path->peer->hostname);
515c2602 9633
05864da7
DS
9634 json_object_string_add(json_nexthop_global, "afi",
9635 "ipv6");
9636 json_object_string_add(json_nexthop_global, "scope",
9637 "global");
9638 } else {
aef999a2
DA
9639 if (nexthop_hostname)
9640 vty_out(vty, " %pI6(%s)",
9641 &attr->mp_nexthop_global,
9642 nexthop_hostname);
9643 else
9644 vty_out(vty, " %pI6",
9645 &attr->mp_nexthop_global);
d62a17ae 9646 }
05864da7 9647 }
d62a17ae 9648
05864da7
DS
9649 /* Display the IGP cost or 'inaccessible' */
9650 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9651 if (json_paths)
9652 json_object_boolean_false_add(json_nexthop_global,
9653 "accessible");
9654 else
9655 vty_out(vty, " (inaccessible)");
9656 } else {
9657 if (path->extra && path->extra->igpmetric) {
d62a17ae 9658 if (json_paths)
05864da7
DS
9659 json_object_int_add(json_nexthop_global,
9660 "metric",
9661 path->extra->igpmetric);
d62a17ae 9662 else
05864da7
DS
9663 vty_out(vty, " (metric %u)",
9664 path->extra->igpmetric);
d62a17ae 9665 }
9666
05864da7 9667 /* IGP cost is 0, display this only for json */
d62a17ae 9668 else {
d62a17ae 9669 if (json_paths)
05864da7
DS
9670 json_object_int_add(json_nexthop_global,
9671 "metric", 0);
d62a17ae 9672 }
d62a17ae 9673
05864da7
DS
9674 if (json_paths)
9675 json_object_boolean_true_add(json_nexthop_global,
9676 "accessible");
9677 }
d62a17ae 9678
05864da7
DS
9679 /* Display peer "from" output */
9680 /* This path was originated locally */
9681 if (path->peer == bgp->peer_self) {
d62a17ae 9682
05864da7 9683 if (safi == SAFI_EVPN
b54892e0 9684 || (bn_p->family == AF_INET
05864da7 9685 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9686 if (json_paths)
05864da7
DS
9687 json_object_string_add(json_peer, "peerId",
9688 "0.0.0.0");
d62a17ae 9689 else
05864da7
DS
9690 vty_out(vty, " from 0.0.0.0 ");
9691 } else {
d62a17ae 9692 if (json_paths)
05864da7
DS
9693 json_object_string_add(json_peer, "peerId",
9694 "::");
d62a17ae 9695 else
05864da7 9696 vty_out(vty, " from :: ");
d62a17ae 9697 }
d62a17ae 9698
23d0a753
DA
9699 if (json_paths) {
9700 char buf[BUFSIZ] = {0};
9701
05864da7 9702 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9703 inet_ntop(AF_INET,
9704 &bgp->router_id, buf,
9705 sizeof(buf)));
9706 } else {
9707 vty_out(vty, "(%pI4)", &bgp->router_id);
9708 }
05864da7 9709 }
d62a17ae 9710
05864da7
DS
9711 /* We RXed this path from one of our peers */
9712 else {
9713
9714 if (json_paths) {
9715 json_object_string_add(json_peer, "peerId",
9716 sockunion2str(&path->peer->su,
9717 buf,
9718 SU_ADDRSTRLEN));
9719 json_object_string_add(json_peer, "routerId",
9720 inet_ntop(AF_INET,
9721 &path->peer->remote_id,
9722 buf1, sizeof(buf1)));
9723
9724 if (path->peer->hostname)
9725 json_object_string_add(json_peer, "hostname",
9726 path->peer->hostname);
9727
9728 if (path->peer->domainname)
9729 json_object_string_add(json_peer, "domainname",
9730 path->peer->domainname);
9731
9732 if (path->peer->conf_if)
9733 json_object_string_add(json_peer, "interface",
9734 path->peer->conf_if);
9735 } else {
9736 if (path->peer->conf_if) {
9737 if (path->peer->hostname
892fedb6
DA
9738 && CHECK_FLAG(path->peer->bgp->flags,
9739 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9740 vty_out(vty, " from %s(%s)",
9741 path->peer->hostname,
9742 path->peer->conf_if);
d62a17ae 9743 else
05864da7 9744 vty_out(vty, " from %s",
9b6d8fcf 9745 path->peer->conf_if);
d62a17ae 9746 } else {
05864da7 9747 if (path->peer->hostname
892fedb6
DA
9748 && CHECK_FLAG(path->peer->bgp->flags,
9749 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9750 vty_out(vty, " from %s(%s)",
9751 path->peer->hostname,
9752 path->peer->host);
d62a17ae 9753 else
05864da7
DS
9754 vty_out(vty, " from %s",
9755 sockunion2str(&path->peer->su,
9756 buf,
9757 SU_ADDRSTRLEN));
d62a17ae 9758 }
d62a17ae 9759
05864da7 9760 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9761 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9762 else
9763 vty_out(vty, " (%s)",
9764 inet_ntop(AF_INET,
9765 &path->peer->remote_id, buf1,
9766 sizeof(buf1)));
d62a17ae 9767 }
05864da7 9768 }
9df8b37c 9769
05864da7
DS
9770 /*
9771 * Note when vrfid of nexthop is different from that of prefix
9772 */
9773 if (path->extra && path->extra->bgp_orig) {
9774 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9775
05864da7
DS
9776 if (json_paths) {
9777 const char *vn;
9df8b37c 9778
05864da7
DS
9779 if (path->extra->bgp_orig->inst_type
9780 == BGP_INSTANCE_TYPE_DEFAULT)
9781 vn = VRF_DEFAULT_NAME;
9782 else
9783 vn = path->extra->bgp_orig->name;
9df8b37c 9784
05864da7 9785 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9786
05864da7
DS
9787 if (nexthop_vrfid == VRF_UNKNOWN) {
9788 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9789 } else {
05864da7
DS
9790 json_object_int_add(json_path, "nhVrfId",
9791 (int)nexthop_vrfid);
9df8b37c 9792 }
05864da7
DS
9793 } else {
9794 if (nexthop_vrfid == VRF_UNKNOWN)
9795 vty_out(vty, " vrf ?");
137147c6
DS
9796 else {
9797 struct vrf *vrf;
9798
9799 vrf = vrf_lookup_by_id(nexthop_vrfid);
9800 vty_out(vty, " vrf %s(%u)",
9801 VRF_LOGNAME(vrf), nexthop_vrfid);
9802 }
9df8b37c 9803 }
05864da7 9804 }
9df8b37c 9805
05864da7
DS
9806 if (nexthop_self) {
9807 if (json_paths) {
9808 json_object_boolean_true_add(json_path,
9809 "announceNexthopSelf");
9810 } else {
9811 vty_out(vty, " announce-nh-self");
9df8b37c 9812 }
05864da7 9813 }
9df8b37c 9814
05864da7
DS
9815 if (!json_paths)
9816 vty_out(vty, "\n");
d62a17ae 9817
05864da7
DS
9818 /* display the link-local nexthop */
9819 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9820 if (json_paths) {
9821 json_nexthop_ll = json_object_new_object();
9822 json_object_string_add(
515c2602
DA
9823 json_nexthop_ll, "ip",
9824 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9825 buf, INET6_ADDRSTRLEN));
9826
939a97f4 9827 if (path->peer->hostname)
515c2602
DA
9828 json_object_string_add(json_nexthop_ll,
9829 "hostname",
939a97f4 9830 path->peer->hostname);
515c2602 9831
05864da7
DS
9832 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9833 json_object_string_add(json_nexthop_ll, "scope",
9834 "link-local");
d62a17ae 9835
05864da7
DS
9836 json_object_boolean_true_add(json_nexthop_ll,
9837 "accessible");
d62a17ae 9838
05864da7 9839 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9840 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9841 "used");
9842 else
9843 json_object_boolean_true_add(
9844 json_nexthop_global, "used");
9845 } else {
9846 vty_out(vty, " (%s) %s\n",
9847 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9848 buf, INET6_ADDRSTRLEN),
9849 attr->mp_nexthop_prefer_global
9850 ? "(prefer-global)"
9851 : "(used)");
d62a17ae 9852 }
05864da7
DS
9853 }
9854 /* If we do not have a link-local nexthop then we must flag the
9855 global as "used" */
9856 else {
9857 if (json_paths)
9858 json_object_boolean_true_add(json_nexthop_global,
9859 "used");
9860 }
d62a17ae 9861
b5e140c8 9862 if (safi == SAFI_EVPN &&
5e4d4c8a 9863 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9864 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
9865 }
9866
05864da7
DS
9867 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9868 * Int/Ext/Local, Atomic, best */
9869 if (json_paths)
9870 json_object_string_add(json_path, "origin",
9871 bgp_origin_long_str[attr->origin]);
9872 else
9873 vty_out(vty, " Origin %s",
9874 bgp_origin_long_str[attr->origin]);
9df8b37c 9875
05864da7 9876 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9877 if (json_paths)
05864da7 9878 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9879 else
05864da7
DS
9880 vty_out(vty, ", metric %u", attr->med);
9881 }
9df8b37c 9882
05864da7
DS
9883 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9884 if (json_paths)
0fbac0b4 9885 json_object_int_add(json_path, "locPrf",
05864da7
DS
9886 attr->local_pref);
9887 else
9888 vty_out(vty, ", localpref %u", attr->local_pref);
9889 }
9df8b37c 9890
05864da7
DS
9891 if (attr->weight != 0) {
9892 if (json_paths)
9893 json_object_int_add(json_path, "weight", attr->weight);
9894 else
9895 vty_out(vty, ", weight %u", attr->weight);
9896 }
9df8b37c 9897
05864da7
DS
9898 if (attr->tag != 0) {
9899 if (json_paths)
9900 json_object_int_add(json_path, "tag", attr->tag);
9901 else
9902 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9903 }
9df8b37c 9904
05864da7
DS
9905 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9906 if (json_paths)
9907 json_object_boolean_false_add(json_path, "valid");
9908 else
9909 vty_out(vty, ", invalid");
9910 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9911 if (json_paths)
9912 json_object_boolean_true_add(json_path, "valid");
9913 else
9914 vty_out(vty, ", valid");
9915 }
9df8b37c 9916
05864da7
DS
9917 if (path->peer != bgp->peer_self) {
9918 if (path->peer->as == path->peer->local_as) {
9919 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9920 if (json_paths)
9921 json_object_string_add(
9922 json_peer, "type",
9923 "confed-internal");
d62a17ae 9924 else
05864da7 9925 vty_out(vty, ", confed-internal");
d62a17ae 9926 } else {
05864da7
DS
9927 if (json_paths)
9928 json_object_string_add(
9929 json_peer, "type", "internal");
9930 else
9931 vty_out(vty, ", internal");
9df8b37c 9932 }
05864da7
DS
9933 } else {
9934 if (bgp_confederation_peers_check(bgp,
9935 path->peer->as)) {
9936 if (json_paths)
9937 json_object_string_add(
9938 json_peer, "type",
9939 "confed-external");
d62a17ae 9940 else
05864da7 9941 vty_out(vty, ", confed-external");
d62a17ae 9942 } else {
05864da7
DS
9943 if (json_paths)
9944 json_object_string_add(
9945 json_peer, "type", "external");
9946 else
9947 vty_out(vty, ", external");
d62a17ae 9948 }
9949 }
05864da7
DS
9950 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9951 if (json_paths) {
9952 json_object_boolean_true_add(json_path, "aggregated");
9953 json_object_boolean_true_add(json_path, "local");
9954 } else {
9955 vty_out(vty, ", aggregated, local");
9956 }
9957 } else if (path->type != ZEBRA_ROUTE_BGP) {
9958 if (json_paths)
9959 json_object_boolean_true_add(json_path, "sourced");
9960 else
9961 vty_out(vty, ", sourced");
9962 } else {
9963 if (json_paths) {
9964 json_object_boolean_true_add(json_path, "sourced");
9965 json_object_boolean_true_add(json_path, "local");
9966 } else {
9967 vty_out(vty, ", sourced, local");
d62a17ae 9968 }
05864da7 9969 }
718e3744 9970
05864da7 9971 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9972 if (json_paths)
05864da7
DS
9973 json_object_boolean_true_add(json_path,
9974 "atomicAggregate");
d62a17ae 9975 else
05864da7
DS
9976 vty_out(vty, ", atomic-aggregate");
9977 }
d62a17ae 9978
05864da7
DS
9979 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9980 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9981 && bgp_path_info_mpath_count(path))) {
9982 if (json_paths)
9983 json_object_boolean_true_add(json_path, "multipath");
9984 else
9985 vty_out(vty, ", multipath");
9986 }
50e05855 9987
05864da7
DS
9988 // Mark the bestpath(s)
9989 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9990 first_as = aspath_get_first_as(attr->aspath);
718e3744 9991
05864da7
DS
9992 if (json_paths) {
9993 if (!json_bestpath)
9994 json_bestpath = json_object_new_object();
9995 json_object_int_add(json_bestpath, "bestpathFromAs",
9996 first_as);
9997 } else {
9998 if (first_as)
9999 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10000 else
05864da7 10001 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10002 }
05864da7 10003 }
718e3744 10004
05864da7
DS
10005 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10006 if (json_paths) {
10007 if (!json_bestpath)
10008 json_bestpath = json_object_new_object();
10009 json_object_boolean_true_add(json_bestpath, "overall");
10010 json_object_string_add(
10011 json_bestpath, "selectionReason",
10012 bgp_path_selection_reason2str(bn->reason));
10013 } else {
10014 vty_out(vty, ", best");
10015 vty_out(vty, " (%s)",
10016 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10017 }
05864da7 10018 }
718e3744 10019
05864da7
DS
10020 if (json_bestpath)
10021 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10022
05864da7
DS
10023 if (!json_paths)
10024 vty_out(vty, "\n");
10025
10026 /* Line 4 display Community */
10027 if (attr->community) {
10028 if (json_paths) {
10029 if (!attr->community->json)
10030 community_str(attr->community, true);
10031 json_object_lock(attr->community->json);
10032 json_object_object_add(json_path, "community",
10033 attr->community->json);
10034 } else {
10035 vty_out(vty, " Community: %s\n",
10036 attr->community->str);
d62a17ae 10037 }
05864da7 10038 }
718e3744 10039
05864da7
DS
10040 /* Line 5 display Extended-community */
10041 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10042 if (json_paths) {
10043 json_ext_community = json_object_new_object();
10044 json_object_string_add(json_ext_community, "string",
10045 attr->ecommunity->str);
10046 json_object_object_add(json_path, "extendedCommunity",
10047 json_ext_community);
d62a17ae 10048 } else {
05864da7
DS
10049 vty_out(vty, " Extended Community: %s\n",
10050 attr->ecommunity->str);
d62a17ae 10051 }
05864da7 10052 }
718e3744 10053
05864da7
DS
10054 /* Line 6 display Large community */
10055 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10056 if (json_paths) {
10057 if (!attr->lcommunity->json)
10058 lcommunity_str(attr->lcommunity, true);
10059 json_object_lock(attr->lcommunity->json);
10060 json_object_object_add(json_path, "largeCommunity",
10061 attr->lcommunity->json);
10062 } else {
10063 vty_out(vty, " Large Community: %s\n",
10064 attr->lcommunity->str);
d62a17ae 10065 }
05864da7 10066 }
718e3744 10067
05864da7
DS
10068 /* Line 7 display Originator, Cluster-id */
10069 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10070 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10071 char buf[BUFSIZ] = {0};
10072
05864da7 10073 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10074 if (json_paths)
05864da7
DS
10075 json_object_string_add(
10076 json_path, "originatorId",
23d0a753
DA
10077 inet_ntop(AF_INET, &attr->originator_id,
10078 buf, sizeof(buf)));
d62a17ae 10079 else
23d0a753
DA
10080 vty_out(vty, " Originator: %pI4",
10081 &attr->originator_id);
d62a17ae 10082 }
856ca177 10083
05864da7 10084 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10085 struct cluster_list *cluster =
10086 bgp_attr_get_cluster(attr);
05864da7 10087 int i;
d62a17ae 10088
10089 if (json_paths) {
05864da7
DS
10090 json_cluster_list = json_object_new_object();
10091 json_cluster_list_list =
10092 json_object_new_array();
10093
779fee93 10094 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10095 json_string = json_object_new_string(
779fee93
DS
10096 inet_ntop(AF_INET,
10097 &cluster->list[i],
10098 buf, sizeof(buf)));
05864da7
DS
10099 json_object_array_add(
10100 json_cluster_list_list,
10101 json_string);
10102 }
718e3744 10103
05864da7
DS
10104 /*
10105 * struct cluster_list does not have
10106 * "str" variable like aspath and community
10107 * do. Add this someday if someone asks
10108 * for it.
10109 * json_object_string_add(json_cluster_list,
779fee93 10110 * "string", cluster->str);
05864da7
DS
10111 */
10112 json_object_object_add(json_cluster_list,
10113 "list",
10114 json_cluster_list_list);
10115 json_object_object_add(json_path, "clusterList",
10116 json_cluster_list);
0dc8ee70 10117 } else {
05864da7
DS
10118 vty_out(vty, ", Cluster list: ");
10119
779fee93 10120 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10121 vty_out(vty, "%pI4 ",
779fee93 10122 &cluster->list[i]);
05864da7 10123 }
0dc8ee70 10124 }
d62a17ae 10125 }
718e3744 10126
d62a17ae 10127 if (!json_paths)
10128 vty_out(vty, "\n");
05864da7 10129 }
d62a17ae 10130
05864da7 10131 if (path->extra && path->extra->damp_info)
a935f597 10132 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10133
05864da7
DS
10134 /* Remote Label */
10135 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10136 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10137 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10138
05864da7
DS
10139 if (json_paths)
10140 json_object_int_add(json_path, "remoteLabel", label);
10141 else
10142 vty_out(vty, " Remote label: %d\n", label);
10143 }
d62a17ae 10144
e496b420
HS
10145 /* Remote SID */
10146 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10147 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10148 if (json_paths)
10149 json_object_string_add(json_path, "remoteSid", buf);
10150 else
10151 vty_out(vty, " Remote SID: %s\n", buf);
10152 }
10153
05864da7
DS
10154 /* Label Index */
10155 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10156 if (json_paths)
10157 json_object_int_add(json_path, "labelIndex",
10158 attr->label_index);
10159 else
10160 vty_out(vty, " Label Index: %d\n",
10161 attr->label_index);
10162 }
d62a17ae 10163
05864da7
DS
10164 /* Line 8 display Addpath IDs */
10165 if (path->addpath_rx_id
10166 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10167 if (json_paths) {
10168 json_object_int_add(json_path, "addpathRxId",
10169 path->addpath_rx_id);
d62a17ae 10170
05864da7
DS
10171 /* Keep backwards compatibility with the old API
10172 * by putting TX All's ID in the old field
10173 */
10174 json_object_int_add(
10175 json_path, "addpathTxId",
10176 path->tx_addpath
10177 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10178
05864da7
DS
10179 /* ... but create a specific field for each
10180 * strategy
10181 */
10182 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10183 json_object_int_add(
10184 json_path,
10185 bgp_addpath_names(i)->id_json_name,
10186 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10187 }
05864da7
DS
10188 } else {
10189 vty_out(vty, " AddPath ID: RX %u, ",
10190 path->addpath_rx_id);
d62a17ae 10191
05864da7 10192 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10193 }
05864da7 10194 }
520d5d76 10195
05864da7
DS
10196 /* If we used addpath to TX a non-bestpath we need to display
10197 * "Advertised to" on a path-by-path basis
10198 */
10199 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10200 first = 1;
dcc68b5e 10201
05864da7
DS
10202 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10203 addpath_capable =
10204 bgp_addpath_encode_tx(peer, afi, safi);
10205 has_adj = bgp_adj_out_lookup(
10206 peer, path->net,
10207 bgp_addpath_id_for_peer(peer, afi, safi,
10208 &path->tx_addpath));
10209
10210 if ((addpath_capable && has_adj)
10211 || (!addpath_capable && has_adj
10212 && CHECK_FLAG(path->flags,
10213 BGP_PATH_SELECTED))) {
10214 if (json_path && !json_adv_to)
10215 json_adv_to = json_object_new_object();
dcc68b5e 10216
05864da7
DS
10217 route_vty_out_advertised_to(
10218 vty, peer, &first,
10219 " Advertised to:", json_adv_to);
d62a17ae 10220 }
10221 }
718e3744 10222
05864da7
DS
10223 if (json_path) {
10224 if (json_adv_to) {
10225 json_object_object_add(
10226 json_path, "advertisedTo", json_adv_to);
d62a17ae 10227 }
05864da7
DS
10228 } else {
10229 if (!first) {
10230 vty_out(vty, "\n");
d62a17ae 10231 }
10232 }
05864da7 10233 }
b05a1c8b 10234
05864da7
DS
10235 /* Line 9 display Uptime */
10236 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10237 if (json_paths) {
10238 json_last_update = json_object_new_object();
10239 json_object_int_add(json_last_update, "epoch", tbuf);
10240 json_object_string_add(json_last_update, "string",
10241 ctime(&tbuf));
10242 json_object_object_add(json_path, "lastUpdate",
10243 json_last_update);
10244 } else
10245 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10246
05864da7
DS
10247 /* Line 10 display PMSI tunnel attribute, if present */
10248 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10249 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10250 bgp_attr_get_pmsi_tnl_type(attr),
10251 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10252
05864da7
DS
10253 if (json_paths) {
10254 json_pmsi = json_object_new_object();
10255 json_object_string_add(json_pmsi, "tunnelType", str);
10256 json_object_int_add(json_pmsi, "label",
10257 label2vni(&attr->label));
10258 json_object_object_add(json_path, "pmsi", json_pmsi);
10259 } else
10260 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10261 str, label2vni(&attr->label));
d62a17ae 10262 }
f1aa5d8a 10263
d62a17ae 10264 /* We've constructed the json object for this path, add it to the json
10265 * array of paths
10266 */
10267 if (json_paths) {
10268 if (json_nexthop_global || json_nexthop_ll) {
10269 json_nexthops = json_object_new_array();
f1aa5d8a 10270
d62a17ae 10271 if (json_nexthop_global)
10272 json_object_array_add(json_nexthops,
10273 json_nexthop_global);
f1aa5d8a 10274
d62a17ae 10275 if (json_nexthop_ll)
10276 json_object_array_add(json_nexthops,
10277 json_nexthop_ll);
f1aa5d8a 10278
d62a17ae 10279 json_object_object_add(json_path, "nexthops",
10280 json_nexthops);
10281 }
10282
10283 json_object_object_add(json_path, "peer", json_peer);
10284 json_object_array_add(json_paths, json_path);
05864da7 10285 }
b366b518
BB
10286}
10287
96ade3ed 10288#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10289#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10290#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10291
d62a17ae 10292static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10293 const char *prefix_list_str, afi_t afi,
10294 safi_t safi, enum bgp_show_type type);
10295static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10296 const char *filter, afi_t afi, safi_t safi,
10297 enum bgp_show_type type);
10298static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10299 const char *rmap_str, afi_t afi, safi_t safi,
10300 enum bgp_show_type type);
10301static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10302 const char *com, int exact, afi_t afi,
10303 safi_t safi);
10304static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10305 const char *prefix, afi_t afi, safi_t safi,
10306 enum bgp_show_type type);
a4d82a8a 10307static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10308 afi_t afi, safi_t safi, enum bgp_show_type type,
10309 bool use_json);
7f323236
DW
10310static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10311 const char *comstr, int exact, afi_t afi,
96f3485c 10312 safi_t safi, uint8_t show_flags);
d62a17ae 10313
1ae44dfc
LB
10314
10315static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10316 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10317 void *output_arg, char *rd, int is_last,
10318 unsigned long *output_cum, unsigned long *total_cum,
10319 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10320{
40381db7 10321 struct bgp_path_info *pi;
9bcb3eef 10322 struct bgp_dest *dest;
d62a17ae 10323 int header = 1;
10324 int display;
1ae44dfc
LB
10325 unsigned long output_count = 0;
10326 unsigned long total_count = 0;
d62a17ae 10327 struct prefix *p;
d62a17ae 10328 json_object *json_paths = NULL;
10329 int first = 1;
96f3485c
MK
10330 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10331 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10332 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10333
1ae44dfc
LB
10334 if (output_cum && *output_cum != 0)
10335 header = 0;
10336
9386b588 10337 if (use_json && !*json_header_depth) {
96f3485c
MK
10338 if (all)
10339 *json_header_depth = 1;
10340 else {
10341 vty_out(vty, "{\n");
10342 *json_header_depth = 2;
10343 }
10344
d62a17ae 10345 vty_out(vty,
23d0a753
DA
10346 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10347 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10348 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10349 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10350 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10351 ? VRF_DEFAULT_NAME
10352 : bgp->name,
10353 table->version, &bgp->router_id,
01eced22 10354 bgp->default_local_pref, bgp->as);
9386b588 10355 if (rd) {
445c2480 10356 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10357 ++*json_header_depth;
10358 }
d62a17ae 10359 }
718e3744 10360
445c2480
DS
10361 if (use_json && rd) {
10362 vty_out(vty, " \"%s\" : { ", rd);
10363 }
10364
d62a17ae 10365 /* Start processing of routes. */
9bcb3eef
DS
10366 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10367 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10368
9bcb3eef 10369 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10370 if (pi == NULL)
98ce9a06 10371 continue;
d62a17ae 10372
98ce9a06 10373 display = 0;
98ce9a06
DS
10374 if (use_json)
10375 json_paths = json_object_new_array();
10376 else
10377 json_paths = NULL;
d62a17ae 10378
6f94b685 10379 for (; pi; pi = pi->next) {
98ce9a06
DS
10380 total_count++;
10381 if (type == bgp_show_type_flap_statistics
10382 || type == bgp_show_type_flap_neighbor
10383 || type == bgp_show_type_dampend_paths
10384 || type == bgp_show_type_damp_neighbor) {
40381db7 10385 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10386 continue;
10387 }
10388 if (type == bgp_show_type_regexp) {
10389 regex_t *regex = output_arg;
d62a17ae 10390
40381db7 10391 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10392 == REG_NOMATCH)
10393 continue;
10394 }
10395 if (type == bgp_show_type_prefix_list) {
10396 struct prefix_list *plist = output_arg;
d62a17ae 10397
9bcb3eef 10398 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10399 != PREFIX_PERMIT)
10400 continue;
10401 }
10402 if (type == bgp_show_type_filter_list) {
10403 struct as_list *as_list = output_arg;
d62a17ae 10404
40381db7 10405 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10406 != AS_FILTER_PERMIT)
10407 continue;
10408 }
10409 if (type == bgp_show_type_route_map) {
10410 struct route_map *rmap = output_arg;
9b6d8fcf 10411 struct bgp_path_info path;
98ce9a06 10412 struct attr dummy_attr;
b68885f9 10413 route_map_result_t ret;
d62a17ae 10414
6f4f49b2 10415 dummy_attr = *pi->attr;
d62a17ae 10416
40381db7 10417 path.peer = pi->peer;
9b6d8fcf 10418 path.attr = &dummy_attr;
d62a17ae 10419
1782514f 10420 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10421 if (ret == RMAP_DENYMATCH)
10422 continue;
10423 }
10424 if (type == bgp_show_type_neighbor
10425 || type == bgp_show_type_flap_neighbor
10426 || type == bgp_show_type_damp_neighbor) {
10427 union sockunion *su = output_arg;
10428
40381db7
DS
10429 if (pi->peer == NULL
10430 || pi->peer->su_remote == NULL
10431 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10432 continue;
10433 }
10434 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10435 uint32_t destination;
d62a17ae 10436
9bcb3eef 10437 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10438 if (IN_CLASSC(destination)
9bcb3eef 10439 && dest_p->prefixlen == 24)
98ce9a06
DS
10440 continue;
10441 if (IN_CLASSB(destination)
9bcb3eef 10442 && dest_p->prefixlen == 16)
98ce9a06
DS
10443 continue;
10444 if (IN_CLASSA(destination)
9bcb3eef 10445 && dest_p->prefixlen == 8)
98ce9a06
DS
10446 continue;
10447 }
10448 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10449 p = output_arg;
9bcb3eef 10450 if (!prefix_match(p, dest_p))
98ce9a06
DS
10451 continue;
10452 }
10453 if (type == bgp_show_type_community_all) {
40381db7 10454 if (!pi->attr->community)
98ce9a06
DS
10455 continue;
10456 }
10457 if (type == bgp_show_type_community) {
10458 struct community *com = output_arg;
d62a17ae 10459
40381db7
DS
10460 if (!pi->attr->community
10461 || !community_match(pi->attr->community,
98ce9a06
DS
10462 com))
10463 continue;
10464 }
10465 if (type == bgp_show_type_community_exact) {
10466 struct community *com = output_arg;
d62a17ae 10467
40381db7
DS
10468 if (!pi->attr->community
10469 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10470 continue;
10471 }
10472 if (type == bgp_show_type_community_list) {
10473 struct community_list *list = output_arg;
d62a17ae 10474
40381db7 10475 if (!community_list_match(pi->attr->community,
a4d82a8a 10476 list))
98ce9a06
DS
10477 continue;
10478 }
a4d82a8a 10479 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10480 struct community_list *list = output_arg;
d62a17ae 10481
98ce9a06 10482 if (!community_list_exact_match(
40381db7 10483 pi->attr->community, list))
98ce9a06
DS
10484 continue;
10485 }
10486 if (type == bgp_show_type_lcommunity) {
10487 struct lcommunity *lcom = output_arg;
d62a17ae 10488
40381db7
DS
10489 if (!pi->attr->lcommunity
10490 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10491 lcom))
10492 continue;
10493 }
36a206db 10494
10495 if (type == bgp_show_type_lcommunity_exact) {
10496 struct lcommunity *lcom = output_arg;
10497
10498 if (!pi->attr->lcommunity
10499 || !lcommunity_cmp(pi->attr->lcommunity,
10500 lcom))
10501 continue;
10502 }
98ce9a06
DS
10503 if (type == bgp_show_type_lcommunity_list) {
10504 struct community_list *list = output_arg;
d62a17ae 10505
40381db7 10506 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10507 list))
98ce9a06
DS
10508 continue;
10509 }
36a206db 10510 if (type
10511 == bgp_show_type_lcommunity_list_exact) {
10512 struct community_list *list = output_arg;
10513
10514 if (!lcommunity_list_exact_match(
10515 pi->attr->lcommunity, list))
10516 continue;
10517 }
98ce9a06 10518 if (type == bgp_show_type_lcommunity_all) {
40381db7 10519 if (!pi->attr->lcommunity)
98ce9a06
DS
10520 continue;
10521 }
10522 if (type == bgp_show_type_dampend_paths
10523 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10524 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10525 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10526 continue;
10527 }
10528
10529 if (!use_json && header) {
23d0a753
DA
10530 vty_out(vty,
10531 "BGP table version is %" PRIu64
10532 ", local router ID is %pI4, vrf id ",
10533 table->version, &bgp->router_id);
9df8b37c
PZ
10534 if (bgp->vrf_id == VRF_UNKNOWN)
10535 vty_out(vty, "%s", VRFID_NONE_STR);
10536 else
10537 vty_out(vty, "%u", bgp->vrf_id);
10538 vty_out(vty, "\n");
01eced22
AD
10539 vty_out(vty, "Default local pref %u, ",
10540 bgp->default_local_pref);
10541 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10542 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10543 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10544 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10545 if (type == bgp_show_type_dampend_paths
10546 || type == bgp_show_type_damp_neighbor)
98ce9a06 10547 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10548 else if (type == bgp_show_type_flap_statistics
10549 || type == bgp_show_type_flap_neighbor)
98ce9a06 10550 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10551 else
ae248832
MK
10552 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10553 : BGP_SHOW_HEADER));
98ce9a06 10554 header = 0;
d62a17ae 10555 }
98ce9a06
DS
10556 if (rd != NULL && !display && !output_count) {
10557 if (!use_json)
10558 vty_out(vty,
10559 "Route Distinguisher: %s\n",
10560 rd);
d62a17ae 10561 }
98ce9a06
DS
10562 if (type == bgp_show_type_dampend_paths
10563 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10564 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10565 AFI_IP, safi, use_json,
10566 json_paths);
98ce9a06
DS
10567 else if (type == bgp_show_type_flap_statistics
10568 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10569 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10570 AFI_IP, safi, use_json,
10571 json_paths);
98ce9a06 10572 else
9bcb3eef 10573 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10574 json_paths, wide);
98ce9a06 10575 display++;
d62a17ae 10576 }
10577
98ce9a06
DS
10578 if (display) {
10579 output_count++;
10580 if (!use_json)
10581 continue;
10582
625d2931 10583 /* encode prefix */
9bcb3eef 10584 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10585 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10586
1840384b 10587
b54892e0
DS
10588 bgp_fs_nlri_get_string(
10589 (unsigned char *)
9bcb3eef
DS
10590 dest_p->u.prefix_flowspec.ptr,
10591 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10592 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10593 family2afi(dest_p->u
10594 .prefix_flowspec.family));
625d2931 10595 if (first)
b54892e0 10596 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10597 dest_p->u.prefix_flowspec
b54892e0 10598 .prefixlen);
625d2931 10599 else
b54892e0 10600 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10601 dest_p->u.prefix_flowspec
b54892e0 10602 .prefixlen);
625d2931 10603 } else {
625d2931 10604 if (first)
1b78780b 10605 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10606 else
1b78780b 10607 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10608 }
98ce9a06 10609 vty_out(vty, "%s",
f4ec52f7
DA
10610 json_object_to_json_string_ext(
10611 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10612 json_object_free(json_paths);
449feb8e 10613 json_paths = NULL;
98ce9a06 10614 first = 0;
1f83ed02
DS
10615 } else
10616 json_object_free(json_paths);
98ce9a06
DS
10617 }
10618
1ae44dfc
LB
10619 if (output_cum) {
10620 output_count += *output_cum;
10621 *output_cum = output_count;
10622 }
10623 if (total_cum) {
10624 total_count += *total_cum;
10625 *total_cum = total_count;
10626 }
d62a17ae 10627 if (use_json) {
9386b588 10628 if (rd) {
a4d82a8a 10629 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10630 }
10631 if (is_last) {
a4d82a8a
PZ
10632 unsigned long i;
10633 for (i = 0; i < *json_header_depth; ++i)
10634 vty_out(vty, " } ");
96f3485c
MK
10635 if (!all)
10636 vty_out(vty, "\n");
9386b588 10637 }
d62a17ae 10638 } else {
1ae44dfc
LB
10639 if (is_last) {
10640 /* No route is displayed */
10641 if (output_count == 0) {
10642 if (type == bgp_show_type_normal)
10643 vty_out(vty,
10644 "No BGP prefixes displayed, %ld exist\n",
10645 total_count);
10646 } else
d62a17ae 10647 vty_out(vty,
1ae44dfc
LB
10648 "\nDisplayed %ld routes and %ld total paths\n",
10649 output_count, total_count);
10650 }
d62a17ae 10651 }
718e3744 10652
d62a17ae 10653 return CMD_SUCCESS;
718e3744 10654}
10655
1ae44dfc
LB
10656int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10657 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10658 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10659{
9bcb3eef 10660 struct bgp_dest *dest, *next;
1ae44dfc
LB
10661 unsigned long output_cum = 0;
10662 unsigned long total_cum = 0;
9386b588 10663 unsigned long json_header_depth = 0;
67009e22 10664 struct bgp_table *itable;
0136788c 10665 bool show_msg;
96f3485c 10666 uint8_t show_flags = 0;
0136788c
LB
10667
10668 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10669
96f3485c
MK
10670 if (use_json)
10671 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10672
9bcb3eef
DS
10673 for (dest = bgp_table_top(table); dest; dest = next) {
10674 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10675
9bcb3eef
DS
10676 next = bgp_route_next(dest);
10677 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10678 continue;
67009e22 10679
9bcb3eef 10680 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10681 if (itable != NULL) {
1ae44dfc 10682 struct prefix_rd prd;
06b9f471 10683 char rd[RD_ADDRSTRLEN];
1ae44dfc 10684
9bcb3eef 10685 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10686 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10687 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10688 rd, next == NULL, &output_cum,
10689 &total_cum, &json_header_depth,
10690 show_flags);
0136788c
LB
10691 if (next == NULL)
10692 show_msg = false;
1ae44dfc
LB
10693 }
10694 }
0136788c
LB
10695 if (show_msg) {
10696 if (output_cum == 0)
10697 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10698 total_cum);
10699 else
10700 vty_out(vty,
10701 "\nDisplayed %ld routes and %ld total paths\n",
10702 output_cum, total_cum);
10703 }
1ae44dfc
LB
10704 return CMD_SUCCESS;
10705}
d62a17ae 10706static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10707 enum bgp_show_type type, void *output_arg,
10708 uint8_t show_flags)
fee0f4c6 10709{
d62a17ae 10710 struct bgp_table *table;
9386b588 10711 unsigned long json_header_depth = 0;
96f3485c 10712 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10713
d62a17ae 10714 if (bgp == NULL) {
10715 bgp = bgp_get_default();
10716 }
fee0f4c6 10717
d62a17ae 10718 if (bgp == NULL) {
10719 if (!use_json)
10720 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10721 else
10722 vty_out(vty, "{}\n");
d62a17ae 10723 return CMD_WARNING;
10724 }
4dd6177e 10725
1ae44dfc 10726 table = bgp->rib[afi][safi];
d62a17ae 10727 /* use MPLS and ENCAP specific shows until they are merged */
10728 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10729 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10730 output_arg, use_json);
d62a17ae 10731 }
dba3c1d3
PG
10732
10733 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10734 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10735 output_arg, use_json,
10736 1, NULL, NULL);
10737 }
d62a17ae 10738 /* labeled-unicast routes live in the unicast table */
10739 else if (safi == SAFI_LABELED_UNICAST)
10740 safi = SAFI_UNICAST;
fee0f4c6 10741
96f3485c
MK
10742 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10743 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10744}
10745
d62a17ae 10746static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10747 safi_t safi, uint8_t show_flags)
f186de26 10748{
d62a17ae 10749 struct listnode *node, *nnode;
10750 struct bgp *bgp;
10751 int is_first = 1;
9f049418 10752 bool route_output = false;
96f3485c 10753 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10754
d62a17ae 10755 if (use_json)
10756 vty_out(vty, "{\n");
9f689658 10757
d62a17ae 10758 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10759 route_output = true;
d62a17ae 10760 if (use_json) {
10761 if (!is_first)
10762 vty_out(vty, ",\n");
10763 else
10764 is_first = 0;
10765
10766 vty_out(vty, "\"%s\":",
10767 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10768 ? VRF_DEFAULT_NAME
d62a17ae 10769 : bgp->name);
10770 } else {
10771 vty_out(vty, "\nInstance %s:\n",
10772 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10773 ? VRF_DEFAULT_NAME
d62a17ae 10774 : bgp->name);
10775 }
10776 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10777 show_flags);
d62a17ae 10778 }
9f689658 10779
d62a17ae 10780 if (use_json)
10781 vty_out(vty, "}\n");
9f049418
DS
10782 else if (!route_output)
10783 vty_out(vty, "%% BGP instance not found\n");
f186de26 10784}
10785
718e3744 10786/* Header of detailed BGP route information */
d62a17ae 10787void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10788 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10789 afi_t afi, safi_t safi, json_object *json)
10790{
40381db7 10791 struct bgp_path_info *pi;
b54892e0 10792 const struct prefix *p;
d62a17ae 10793 struct peer *peer;
10794 struct listnode *node, *nnode;
06b9f471 10795 char buf1[RD_ADDRSTRLEN];
0291c246 10796 char prefix_str[BUFSIZ];
d62a17ae 10797 int count = 0;
10798 int best = 0;
10799 int suppress = 0;
c5f1e1b2
C
10800 int accept_own = 0;
10801 int route_filter_translated_v4 = 0;
10802 int route_filter_v4 = 0;
10803 int route_filter_translated_v6 = 0;
10804 int route_filter_v6 = 0;
10805 int llgr_stale = 0;
10806 int no_llgr = 0;
10807 int accept_own_nexthop = 0;
10808 int blackhole = 0;
d62a17ae 10809 int no_export = 0;
10810 int no_advertise = 0;
10811 int local_as = 0;
c5f1e1b2 10812 int no_peer = 0;
d62a17ae 10813 int first = 1;
10814 int has_valid_label = 0;
10815 mpls_label_t label = 0;
10816 json_object *json_adv_to = NULL;
9bedbb1e 10817
9bcb3eef
DS
10818 p = bgp_dest_get_prefix(dest);
10819 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10820
10821 if (has_valid_label)
9bcb3eef 10822 label = label_pton(&dest->local_label);
d62a17ae 10823
44c69747 10824 if (safi == SAFI_EVPN) {
d62a17ae 10825
44c69747 10826 if (!json) {
2dbe669b 10827 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10828 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10829 : "",
2dbe669b 10830 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10831 } else {
10832 json_object_string_add(json, "rd",
10833 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10834 "");
10835 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10836 }
10837 } else {
10838 if (!json) {
8228a9a7 10839 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 10840 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
10841 ? prefix_rd2str(prd, buf1,
10842 sizeof(buf1))
10843 : ""),
10844 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 10845
44c69747
LK
10846 } else
10847 json_object_string_add(json, "prefix",
10848 prefix2str(p, prefix_str, sizeof(prefix_str)));
10849 }
10850
10851 if (has_valid_label) {
10852 if (json)
10853 json_object_int_add(json, "localLabel", label);
10854 else
d62a17ae 10855 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10856 }
10857
10858 if (!json)
d62a17ae 10859 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10860 vty_out(vty, "not allocated\n");
718e3744 10861
9bcb3eef 10862 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10863 count++;
40381db7 10864 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10865 best = count;
4056a5f6 10866 if (bgp_path_suppressed(pi))
d62a17ae 10867 suppress = 1;
cee9c031 10868
40381db7 10869 if (pi->attr->community == NULL)
cee9c031
QY
10870 continue;
10871
10872 no_advertise += community_include(
40381db7
DS
10873 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10874 no_export += community_include(pi->attr->community,
cee9c031 10875 COMMUNITY_NO_EXPORT);
40381db7 10876 local_as += community_include(pi->attr->community,
cee9c031 10877 COMMUNITY_LOCAL_AS);
40381db7 10878 accept_own += community_include(pi->attr->community,
cee9c031
QY
10879 COMMUNITY_ACCEPT_OWN);
10880 route_filter_translated_v4 += community_include(
40381db7 10881 pi->attr->community,
cee9c031
QY
10882 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10883 route_filter_translated_v6 += community_include(
40381db7 10884 pi->attr->community,
cee9c031
QY
10885 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10886 route_filter_v4 += community_include(
40381db7 10887 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10888 route_filter_v6 += community_include(
40381db7
DS
10889 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10890 llgr_stale += community_include(pi->attr->community,
cee9c031 10891 COMMUNITY_LLGR_STALE);
40381db7 10892 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10893 COMMUNITY_NO_LLGR);
10894 accept_own_nexthop +=
40381db7 10895 community_include(pi->attr->community,
cee9c031 10896 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10897 blackhole += community_include(pi->attr->community,
cee9c031 10898 COMMUNITY_BLACKHOLE);
40381db7 10899 no_peer += community_include(pi->attr->community,
cee9c031 10900 COMMUNITY_NO_PEER);
d62a17ae 10901 }
718e3744 10902 }
718e3744 10903
d62a17ae 10904 if (!json) {
10905 vty_out(vty, "Paths: (%d available", count);
10906 if (best) {
10907 vty_out(vty, ", best #%d", best);
b84060bb
PG
10908 if (safi == SAFI_UNICAST) {
10909 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10910 vty_out(vty, ", table %s",
10911 VRF_DEFAULT_NAME);
10912 else
10913 vty_out(vty, ", vrf %s",
10914 bgp->name);
10915 }
d62a17ae 10916 } else
10917 vty_out(vty, ", no best path");
10918
c5f1e1b2
C
10919 if (accept_own)
10920 vty_out(vty,
10921 ", accept own local route exported and imported in different VRF");
10922 else if (route_filter_translated_v4)
10923 vty_out(vty,
10924 ", mark translated RTs for VPNv4 route filtering");
10925 else if (route_filter_v4)
10926 vty_out(vty,
10927 ", attach RT as-is for VPNv4 route filtering");
10928 else if (route_filter_translated_v6)
10929 vty_out(vty,
10930 ", mark translated RTs for VPNv6 route filtering");
10931 else if (route_filter_v6)
10932 vty_out(vty,
10933 ", attach RT as-is for VPNv6 route filtering");
10934 else if (llgr_stale)
10935 vty_out(vty,
10936 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10937 else if (no_llgr)
10938 vty_out(vty,
10939 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10940 else if (accept_own_nexthop)
10941 vty_out(vty,
10942 ", accept local nexthop");
10943 else if (blackhole)
10944 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10945 else if (no_export)
10946 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10947 else if (no_advertise)
10948 vty_out(vty, ", not advertised to any peer");
d62a17ae 10949 else if (local_as)
10950 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10951 else if (no_peer)
10952 vty_out(vty,
10953 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10954
10955 if (suppress)
10956 vty_out(vty,
10957 ", Advertisements suppressed by an aggregate.");
10958 vty_out(vty, ")\n");
10959 }
718e3744 10960
d62a17ae 10961 /* If we are not using addpath then we can display Advertised to and
10962 * that will
10963 * show what peers we advertised the bestpath to. If we are using
10964 * addpath
10965 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10966 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10967 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10968 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10969 if (json && !json_adv_to)
10970 json_adv_to = json_object_new_object();
10971
10972 route_vty_out_advertised_to(
10973 vty, peer, &first,
10974 " Advertised to non peer-group peers:\n ",
10975 json_adv_to);
10976 }
10977 }
10978
10979 if (json) {
10980 if (json_adv_to) {
10981 json_object_object_add(json, "advertisedTo",
10982 json_adv_to);
10983 }
10984 } else {
10985 if (first)
10986 vty_out(vty, " Not advertised to any peer");
10987 vty_out(vty, "\n");
10988 }
10989 }
718e3744 10990}
10991
44c69747 10992static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10993 struct bgp_dest *bgp_node, struct vty *vty,
10994 struct bgp *bgp, afi_t afi, safi_t safi,
10995 json_object *json, enum bgp_path_type pathtype,
10996 int *display)
44c69747
LK
10997{
10998 struct bgp_path_info *pi;
10999 int header = 1;
11000 char rdbuf[RD_ADDRSTRLEN];
11001 json_object *json_header = NULL;
11002 json_object *json_paths = NULL;
11003
9bcb3eef 11004 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
11005
11006 if (json && !json_paths) {
11007 /* Instantiate json_paths only if path is valid */
11008 json_paths = json_object_new_array();
11009 if (pfx_rd) {
11010 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11011 json_header = json_object_new_object();
11012 } else
11013 json_header = json;
11014 }
11015
11016 if (header) {
11017 route_vty_out_detail_header(
11018 vty, bgp, bgp_node, pfx_rd,
11019 AFI_IP, safi, json_header);
11020 header = 0;
11021 }
11022 (*display)++;
11023
11024 if (pathtype == BGP_PATH_SHOW_ALL
11025 || (pathtype == BGP_PATH_SHOW_BESTPATH
11026 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11027 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11028 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11029 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11030 route_vty_out_detail(vty, bgp, bgp_node,
11031 pi, AFI_IP, safi,
11032 json_paths);
11033 }
11034
11035 if (json && json_paths) {
11036 json_object_object_add(json_header, "paths", json_paths);
11037
11038 if (pfx_rd)
11039 json_object_object_add(json, rdbuf, json_header);
11040 }
11041}
11042
718e3744 11043/* Display specified route of BGP table. */
d62a17ae 11044static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11045 struct bgp_table *rib, const char *ip_str,
11046 afi_t afi, safi_t safi,
11047 struct prefix_rd *prd, int prefix_check,
9f049418 11048 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11049{
11050 int ret;
d62a17ae 11051 int display = 0;
11052 struct prefix match;
9bcb3eef
DS
11053 struct bgp_dest *dest;
11054 struct bgp_dest *rm;
d62a17ae 11055 struct bgp_table *table;
11056 json_object *json = NULL;
11057 json_object *json_paths = NULL;
11058
11059 /* Check IP address argument. */
11060 ret = str2prefix(ip_str, &match);
11061 if (!ret) {
11062 vty_out(vty, "address is malformed\n");
11063 return CMD_WARNING;
11064 }
718e3744 11065
d62a17ae 11066 match.family = afi2family(afi);
b05a1c8b 11067
44c69747 11068 if (use_json)
d62a17ae 11069 json = json_object_new_object();
718e3744 11070
44c69747 11071 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11072 for (dest = bgp_table_top(rib); dest;
11073 dest = bgp_route_next(dest)) {
11074 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11075
9bcb3eef 11076 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11077 continue;
9bcb3eef 11078 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11079 if (!table)
ea47320b 11080 continue;
d62a17ae 11081
ea47320b
DL
11082 if ((rm = bgp_node_match(table, &match)) == NULL)
11083 continue;
d62a17ae 11084
9bcb3eef 11085 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11086 if (prefix_check
b54892e0 11087 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11088 bgp_dest_unlock_node(rm);
ea47320b
DL
11089 continue;
11090 }
d62a17ae 11091
9bcb3eef 11092 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11093 bgp, afi, safi, json, pathtype,
11094 &display);
44c69747 11095
9bcb3eef 11096 bgp_dest_unlock_node(rm);
44c69747
LK
11097 }
11098 } else if (safi == SAFI_EVPN) {
9bcb3eef 11099 struct bgp_dest *longest_pfx;
cded3b72 11100 bool is_exact_pfxlen_match = false;
44c69747 11101
9bcb3eef
DS
11102 for (dest = bgp_table_top(rib); dest;
11103 dest = bgp_route_next(dest)) {
11104 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11105
9bcb3eef 11106 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11107 continue;
9bcb3eef 11108 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11109 if (!table)
11110 continue;
11111
11112 longest_pfx = NULL;
cded3b72 11113 is_exact_pfxlen_match = false;
44c69747
LK
11114 /*
11115 * Search through all the prefixes for a match. The
11116 * pfx's are enumerated in ascending order of pfxlens.
11117 * So, the last pfx match is the longest match. Set
11118 * is_exact_pfxlen_match when we get exact pfxlen match
11119 */
11120 for (rm = bgp_table_top(table); rm;
11121 rm = bgp_route_next(rm)) {
b54892e0 11122 const struct prefix *rm_p =
9bcb3eef 11123 bgp_dest_get_prefix(rm);
44c69747
LK
11124 /*
11125 * Get prefixlen of the ip-prefix within type5
11126 * evpn route
11127 */
b54892e0
DS
11128 if (evpn_type5_prefix_match(rm_p, &match)
11129 && rm->info) {
44c69747
LK
11130 longest_pfx = rm;
11131 int type5_pfxlen =
b54892e0
DS
11132 bgp_evpn_get_type5_prefixlen(
11133 rm_p);
44c69747 11134 if (type5_pfxlen == match.prefixlen) {
cded3b72 11135 is_exact_pfxlen_match = true;
9bcb3eef 11136 bgp_dest_unlock_node(rm);
44c69747
LK
11137 break;
11138 }
d62a17ae 11139 }
11140 }
ea47320b 11141
44c69747
LK
11142 if (!longest_pfx)
11143 continue;
11144
11145 if (prefix_check && !is_exact_pfxlen_match)
11146 continue;
11147
11148 rm = longest_pfx;
9bcb3eef 11149 bgp_dest_lock_node(rm);
44c69747 11150
9bcb3eef 11151 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11152 bgp, afi, safi, json, pathtype,
11153 &display);
44c69747 11154
9bcb3eef 11155 bgp_dest_unlock_node(rm);
d62a17ae 11156 }
98a9dbc7 11157 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11158 if (use_json)
11159 json_paths = json_object_new_array();
11160
63a0b7a9
PG
11161 display = bgp_flowspec_display_match_per_ip(afi, rib,
11162 &match, prefix_check,
11163 vty,
11164 use_json,
11165 json_paths);
44c69747
LK
11166 if (use_json && display)
11167 json_object_object_add(json, "paths", json_paths);
d62a17ae 11168 } else {
9bcb3eef
DS
11169 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11170 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11171 if (!prefix_check
9bcb3eef
DS
11172 || dest_p->prefixlen == match.prefixlen) {
11173 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11174 safi, json, pathtype,
11175 &display);
d62a17ae 11176 }
11177
9bcb3eef 11178 bgp_dest_unlock_node(dest);
d62a17ae 11179 }
11180 }
e5eee9af 11181
d62a17ae 11182 if (use_json) {
996c9314 11183 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11184 json, JSON_C_TO_STRING_PRETTY |
11185 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11186 json_object_free(json);
11187 } else {
11188 if (!display) {
11189 vty_out(vty, "%% Network not in table\n");
11190 return CMD_WARNING;
11191 }
11192 }
b05a1c8b 11193
d62a17ae 11194 return CMD_SUCCESS;
718e3744 11195}
11196
fee0f4c6 11197/* Display specified route of Main RIB */
d62a17ae 11198static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11199 afi_t afi, safi_t safi, struct prefix_rd *prd,
11200 int prefix_check, enum bgp_path_type pathtype,
9f049418 11201 bool use_json)
d62a17ae 11202{
9b86009a 11203 if (!bgp) {
d62a17ae 11204 bgp = bgp_get_default();
9b86009a
RW
11205 if (!bgp) {
11206 if (!use_json)
11207 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11208 else
11209 vty_out(vty, "{}\n");
9b86009a
RW
11210 return CMD_WARNING;
11211 }
11212 }
d62a17ae 11213
11214 /* labeled-unicast routes live in the unicast table */
11215 if (safi == SAFI_LABELED_UNICAST)
11216 safi = SAFI_UNICAST;
11217
11218 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11219 afi, safi, prd, prefix_check, pathtype,
11220 use_json);
11221}
11222
11223static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11224 struct cmd_token **argv, bool exact, afi_t afi,
11225 safi_t safi, bool uj)
d62a17ae 11226{
11227 struct lcommunity *lcom;
11228 struct buffer *b;
11229 int i;
11230 char *str;
11231 int first = 0;
96f3485c 11232 uint8_t show_flags = 0;
4f28b2b5 11233 int ret;
96f3485c
MK
11234
11235 if (uj)
11236 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11237
11238 b = buffer_new(1024);
11239 for (i = 0; i < argc; i++) {
11240 if (first)
11241 buffer_putc(b, ' ');
11242 else {
11243 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11244 first = 1;
11245 buffer_putstr(b, argv[i]->arg);
11246 }
11247 }
11248 }
11249 buffer_putc(b, '\0');
57d187bc 11250
d62a17ae 11251 str = buffer_getstr(b);
11252 buffer_free(b);
57d187bc 11253
d62a17ae 11254 lcom = lcommunity_str2com(str);
11255 XFREE(MTYPE_TMP, str);
11256 if (!lcom) {
11257 vty_out(vty, "%% Large-community malformed\n");
11258 return CMD_WARNING;
11259 }
57d187bc 11260
4f28b2b5 11261 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11262 (exact ? bgp_show_type_lcommunity_exact
ae248832 11263 : bgp_show_type_lcommunity),
96f3485c 11264 lcom, show_flags);
4f28b2b5
DS
11265
11266 lcommunity_free(&lcom);
11267 return ret;
57d187bc
JS
11268}
11269
d62a17ae 11270static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11271 const char *lcom, bool exact, afi_t afi,
11272 safi_t safi, bool uj)
57d187bc 11273{
d62a17ae 11274 struct community_list *list;
96f3485c
MK
11275 uint8_t show_flags = 0;
11276
11277 if (uj)
11278 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11279
57d187bc 11280
e237b0d2 11281 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11282 LARGE_COMMUNITY_LIST_MASTER);
11283 if (list == NULL) {
11284 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11285 lcom);
11286 return CMD_WARNING;
11287 }
57d187bc 11288
36a206db 11289 return bgp_show(vty, bgp, afi, safi,
11290 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11291 : bgp_show_type_lcommunity_list),
96f3485c 11292 list, show_flags);
fee0f4c6 11293}
11294
52951b63
DS
11295DEFUN (show_ip_bgp_large_community_list,
11296 show_ip_bgp_large_community_list_cmd,
36a206db 11297 "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
11298 SHOW_STR
11299 IP_STR
11300 BGP_STR
11301 BGP_INSTANCE_HELP_STR
9bedbb1e 11302 BGP_AFI_HELP_STR
4dd6177e 11303 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11304 "Display routes matching the large-community-list\n"
11305 "large-community-list number\n"
11306 "large-community-list name\n"
36a206db 11307 "Exact match of the large-communities\n"
52951b63
DS
11308 JSON_STR)
11309{
d62a17ae 11310 afi_t afi = AFI_IP6;
11311 safi_t safi = SAFI_UNICAST;
11312 int idx = 0;
36a206db 11313 bool exact_match = 0;
4d678463 11314 struct bgp *bgp = NULL;
9f049418 11315 bool uj = use_json(argc, argv);
d62a17ae 11316
4d678463
KA
11317 if (uj)
11318 argc--;
11319
11320 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11321 &bgp, uj);
11322 if (!idx)
11323 return CMD_WARNING;
d62a17ae 11324
11325 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11326
11327 const char *clist_number_or_name = argv[++idx]->arg;
11328
11329 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11330 exact_match = 1;
11331
11332 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11333 exact_match, afi, safi, uj);
52951b63
DS
11334}
11335DEFUN (show_ip_bgp_large_community,
11336 show_ip_bgp_large_community_cmd,
36a206db 11337 "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
11338 SHOW_STR
11339 IP_STR
11340 BGP_STR
11341 BGP_INSTANCE_HELP_STR
9bedbb1e 11342 BGP_AFI_HELP_STR
4dd6177e 11343 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11344 "Display routes matching the large-communities\n"
11345 "List of large-community numbers\n"
36a206db 11346 "Exact match of the large-communities\n"
52951b63
DS
11347 JSON_STR)
11348{
d62a17ae 11349 afi_t afi = AFI_IP6;
11350 safi_t safi = SAFI_UNICAST;
11351 int idx = 0;
36a206db 11352 bool exact_match = 0;
4d678463 11353 struct bgp *bgp = NULL;
9f049418 11354 bool uj = use_json(argc, argv);
96f3485c 11355 uint8_t show_flags = 0;
d62a17ae 11356
96f3485c
MK
11357 if (uj) {
11358 argc--;
11359 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11360 }
4d678463 11361
96f3485c
MK
11362 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11363 &bgp, uj);
11364 if (!idx)
11365 return CMD_WARNING;
d62a17ae 11366
36a206db 11367 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11368 if (argv_find(argv, argc, "exact-match", &idx))
11369 exact_match = 1;
11370 return bgp_show_lcommunity(vty, bgp, argc, argv,
11371 exact_match, afi, safi, uj);
11372 } else
d62a17ae 11373 return bgp_show(vty, bgp, afi, safi,
96f3485c 11374 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11375}
11376
71f1613a
DA
11377static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11378 safi_t safi, struct json_object *json_array);
d62a17ae 11379static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11380 safi_t safi, struct json_object *json);
e01ca200 11381
7b2ff250 11382
9ab0cf58
PG
11383DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11384 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11385 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11386 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11387{
11388 bool uj = use_json(argc, argv);
11389 struct bgp *bgp = NULL;
ec76a1d1
DA
11390 safi_t safi = SAFI_UNICAST;
11391 afi_t afi = AFI_IP6;
4265b261 11392 int idx = 0;
6c9d22e2
PG
11393 struct json_object *json_all = NULL;
11394 struct json_object *json_afi_safi = NULL;
4265b261
PG
11395
11396 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11397 &bgp, false);
71f1613a 11398 if (!idx)
4265b261 11399 return CMD_WARNING;
6c9d22e2 11400
4265b261 11401 if (uj)
6c9d22e2 11402 json_all = json_object_new_object();
4265b261 11403
9ab0cf58
PG
11404 FOREACH_AFI_SAFI (afi, safi) {
11405 /*
11406 * So limit output to those afi/safi pairs that
11407 * actually have something interesting in them
11408 */
11409 if (strmatch(get_afi_safi_str(afi, safi, true),
11410 "Unknown")) {
11411 continue;
11412 }
11413 if (uj) {
11414 json_afi_safi = json_object_new_array();
11415 json_object_object_add(
11416 json_all,
11417 get_afi_safi_str(afi, safi, true),
11418 json_afi_safi);
11419 } else {
11420 json_afi_safi = NULL;
6c9d22e2 11421 }
9ab0cf58
PG
11422
11423 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11424 }
6c9d22e2
PG
11425
11426 if (uj) {
9ab0cf58
PG
11427 vty_out(vty, "%s",
11428 json_object_to_json_string_ext(
11429 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11430 json_object_free(json_all);
4265b261 11431 }
6c9d22e2 11432
4265b261
PG
11433 return CMD_SUCCESS;
11434}
11435
7b2ff250 11436/* BGP route print out function without JSON */
14718643
PG
11437DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11438 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11439 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11440 SHOW_STR
11441 IP_STR
11442 BGP_STR
11443 BGP_INSTANCE_HELP_STR
11444 L2VPN_HELP_STR
11445 EVPN_HELP_STR
11446 "BGP RIB advertisement statistics\n"
11447 JSON_STR)
11448{
ec76a1d1
DA
11449 afi_t afi = AFI_IP6;
11450 safi_t safi = SAFI_UNICAST;
14718643
PG
11451 struct bgp *bgp = NULL;
11452 int idx = 0, ret;
11453 bool uj = use_json(argc, argv);
11454 struct json_object *json_afi_safi = NULL, *json = NULL;
11455
11456 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11457 &bgp, false);
11458 if (!idx)
11459 return CMD_WARNING;
11460
11461 if (uj)
11462 json_afi_safi = json_object_new_array();
11463 else
11464 json_afi_safi = NULL;
11465
11466 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11467
11468 if (uj) {
11469 json = json_object_new_object();
11470 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11471 json_afi_safi);
11472 vty_out(vty, "%s", json_object_to_json_string_ext(
11473 json, JSON_C_TO_STRING_PRETTY));
11474 json_object_free(json);
11475 }
11476 return ret;
11477}
11478
893cccd0 11479/* BGP route print out function without JSON */
9ab0cf58
PG
11480DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11481 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11482 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11483 "]]\
893cccd0 11484 statistics [json]",
9ab0cf58
PG
11485 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11486 BGP_SAFI_WITH_LABEL_HELP_STR
11487 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11488{
ec76a1d1
DA
11489 afi_t afi = AFI_IP6;
11490 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11491 struct bgp *bgp = NULL;
11492 int idx = 0, ret;
11493 bool uj = use_json(argc, argv);
6c9d22e2 11494 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11495
11496 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11497 &bgp, false);
11498 if (!idx)
11499 return CMD_WARNING;
6c9d22e2 11500
893cccd0 11501 if (uj)
6c9d22e2
PG
11502 json_afi_safi = json_object_new_array();
11503 else
11504 json_afi_safi = NULL;
11505
11506 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11507
11508 if (uj) {
11509 json = json_object_new_object();
11510 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11511 json_afi_safi);
9ab0cf58
PG
11512 vty_out(vty, "%s",
11513 json_object_to_json_string_ext(
11514 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11515 json_object_free(json);
11516 }
11517 return ret;
893cccd0 11518}
7b2ff250
DW
11519
11520/* BGP route print out function without JSON */
96f3485c 11521DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11522 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11523 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11524 "]]\
96f3485c 11525 <[all$all] dampening <parameters>\
7b2ff250
DW
11526 |route-map WORD\
11527 |prefix-list WORD\
11528 |filter-list WORD\
7b2ff250
DW
11529 |community-list <(1-500)|WORD> [exact-match]\
11530 |A.B.C.D/M longer-prefixes\
11531 |X:X::X:X/M longer-prefixes\
893cccd0 11532 >",
9ab0cf58
PG
11533 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11534 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11535 "Display the entries for all address families\n"
9ab0cf58
PG
11536 "Display detailed information about dampening\n"
11537 "Display detail of configured dampening parameters\n"
11538 "Display routes matching the route-map\n"
11539 "A route-map to match on\n"
11540 "Display routes conforming to the prefix-list\n"
11541 "Prefix-list name\n"
11542 "Display routes conforming to the filter-list\n"
11543 "Regular expression access list name\n"
11544 "Display routes matching the community-list\n"
11545 "community-list number\n"
11546 "community-list name\n"
11547 "Exact match of the communities\n"
11548 "IPv4 prefix\n"
11549 "Display route and more specific routes\n"
11550 "IPv6 prefix\n"
11551 "Display route and more specific routes\n")
718e3744 11552{
d62a17ae 11553 afi_t afi = AFI_IP6;
11554 safi_t safi = SAFI_UNICAST;
11555 int exact_match = 0;
d62a17ae 11556 struct bgp *bgp = NULL;
11557 int idx = 0;
96f3485c
MK
11558 uint8_t show_flags = 0;
11559
11560 /* [<ipv4|ipv6> [all]] */
11561 if (all) {
11562 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11563 if (argv_find(argv, argc, "ipv4", &idx))
11564 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11565
11566 if (argv_find(argv, argc, "ipv6", &idx))
11567 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11568 }
d62a17ae 11569
11570 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11571 &bgp, false);
d62a17ae 11572 if (!idx)
11573 return CMD_WARNING;
11574
d62a17ae 11575 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11576 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11577 return bgp_show_dampening_parameters(vty, afi, safi,
11578 show_flags);
d62a17ae 11579 }
c016b6c7 11580
d62a17ae 11581 if (argv_find(argv, argc, "prefix-list", &idx))
11582 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11583 safi, bgp_show_type_prefix_list);
11584
11585 if (argv_find(argv, argc, "filter-list", &idx))
11586 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11587 safi, bgp_show_type_filter_list);
11588
d62a17ae 11589 if (argv_find(argv, argc, "route-map", &idx))
11590 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11591 safi, bgp_show_type_route_map);
11592
d62a17ae 11593 if (argv_find(argv, argc, "community-list", &idx)) {
11594 const char *clist_number_or_name = argv[++idx]->arg;
11595 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11596 exact_match = 1;
11597 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11598 exact_match, afi, safi);
11599 }
11600 /* prefix-longer */
11601 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11602 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11603 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11604 safi,
11605 bgp_show_type_prefix_longer);
11606
7b2ff250
DW
11607 return CMD_WARNING;
11608}
11609
11610/* BGP route print out function with JSON */
ae248832 11611DEFPY (show_ip_bgp_json,
7b2ff250
DW
11612 show_ip_bgp_json_cmd,
11613 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11614 [all$all]\
cf4898bc
QY
11615 [cidr-only\
11616 |dampening <flap-statistics|dampened-paths>\
11617 |community [AA:NN|local-AS|no-advertise|no-export\
11618 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11619 |accept-own|accept-own-nexthop|route-filter-v6\
11620 |route-filter-v4|route-filter-translated-v6\
11621 |route-filter-translated-v4] [exact-match]\
ae248832 11622 ] [json$uj | wide$wide]",
7b2ff250
DW
11623 SHOW_STR
11624 IP_STR
11625 BGP_STR
11626 BGP_INSTANCE_HELP_STR
11627 BGP_AFI_HELP_STR
11628 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11629 "Display the entries for all address families\n"
7b2ff250
DW
11630 "Display only routes with non-natural netmasks\n"
11631 "Display detailed information about dampening\n"
11632 "Display flap statistics of routes\n"
11633 "Display paths suppressed due to dampening\n"
11634 "Display routes matching the communities\n"
d0086e8e
AD
11635 COMMUNITY_AANN_STR
11636 "Do not send outside local AS (well-known community)\n"
11637 "Do not advertise to any peer (well-known community)\n"
11638 "Do not export to next AS (well-known community)\n"
11639 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11640 "Do not export to any peer (well-known community)\n"
11641 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11642 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11643 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11644 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11645 "Should accept VPN route with local nexthop (well-known community)\n"
11646 "RT VPNv6 route filtering (well-known community)\n"
11647 "RT VPNv4 route filtering (well-known community)\n"
11648 "RT translated VPNv6 route filtering (well-known community)\n"
11649 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11650 "Exact match of the communities\n"
ae248832
MK
11651 JSON_STR
11652 "Increase table width for longer prefixes\n")
7b2ff250
DW
11653{
11654 afi_t afi = AFI_IP6;
11655 safi_t safi = SAFI_UNICAST;
11656 enum bgp_show_type sh_type = bgp_show_type_normal;
11657 struct bgp *bgp = NULL;
11658 int idx = 0;
d0086e8e 11659 int exact_match = 0;
96f3485c
MK
11660 char *community = NULL;
11661 bool first = true;
11662 uint8_t show_flags = 0;
9f049418 11663
96f3485c
MK
11664
11665 if (uj) {
9f049418 11666 argc--;
96f3485c
MK
11667 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11668 }
11669
11670 /* [<ipv4|ipv6> [all]] */
11671 if (all) {
11672 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11673
11674 if (argv_find(argv, argc, "ipv4", &idx))
11675 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11676
11677 if (argv_find(argv, argc, "ipv6", &idx))
11678 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11679 }
11680
11681 if (wide)
11682 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11683
11684 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11685 &bgp, uj);
7b2ff250
DW
11686 if (!idx)
11687 return CMD_WARNING;
11688
7b2ff250 11689 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11690 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11691
11692 if (argv_find(argv, argc, "dampening", &idx)) {
11693 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11694 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11695 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11696 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11697 }
11698
11699 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11700 char *maybecomm = NULL;
d0086e8e 11701
79bc257a
RW
11702 if (idx + 1 < argc) {
11703 if (argv[idx + 1]->type == VARIABLE_TKN)
11704 maybecomm = argv[idx + 1]->arg;
11705 else
11706 maybecomm = argv[idx + 1]->text;
11707 }
11708
cf4898bc
QY
11709 if (maybecomm && !strmatch(maybecomm, "json")
11710 && !strmatch(maybecomm, "exact-match"))
11711 community = maybecomm;
d0086e8e 11712
cf4898bc
QY
11713 if (argv_find(argv, argc, "exact-match", &idx))
11714 exact_match = 1;
d0086e8e 11715
96f3485c
MK
11716 if (!community)
11717 sh_type = bgp_show_type_community_all;
11718 }
11719
11720 if (!all) {
11721 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11722 if (community)
11723 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11724 exact_match, afi, safi,
11725 show_flags);
cf4898bc 11726 else
96f3485c
MK
11727 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11728 show_flags);
11729 } else {
11730 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11731 * AFI_IP6 */
11732
11733 if (uj)
11734 vty_out(vty, "{\n");
11735
11736 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11737 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11738 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11739 ? AFI_IP
11740 : AFI_IP6;
11741 FOREACH_SAFI (safi) {
11742 if (strmatch(get_afi_safi_str(afi, safi, true),
11743 "Unknown"))
11744 continue;
11745
11746 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11747 continue;
11748
11749 if (uj) {
11750 if (first)
11751 first = false;
11752 else
11753 vty_out(vty, ",\n");
11754 vty_out(vty, "\"%s\":{\n",
11755 get_afi_safi_str(afi, safi,
11756 true));
11757 } else
11758 vty_out(vty,
11759 "\nFor address family: %s\n",
11760 get_afi_safi_str(afi, safi,
11761 false));
11762
11763 if (community)
11764 bgp_show_community(vty, bgp, community,
11765 exact_match, afi,
11766 safi, show_flags);
11767 else
11768 bgp_show(vty, bgp, afi, safi, sh_type,
11769 NULL, show_flags);
11770 if (uj)
11771 vty_out(vty, "}\n");
11772 }
11773 } else {
11774 /* show <ip> bgp all: for each AFI and SAFI*/
11775 FOREACH_AFI_SAFI (afi, safi) {
11776 if (strmatch(get_afi_safi_str(afi, safi, true),
11777 "Unknown"))
11778 continue;
11779
11780 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11781 continue;
11782
11783 if (uj) {
11784 if (first)
11785 first = false;
11786 else
11787 vty_out(vty, ",\n");
d0086e8e 11788
96f3485c
MK
11789 vty_out(vty, "\"%s\":{\n",
11790 get_afi_safi_str(afi, safi,
11791 true));
11792 } else
11793 vty_out(vty,
11794 "\nFor address family: %s\n",
11795 get_afi_safi_str(afi, safi,
11796 false));
11797
11798 if (community)
11799 bgp_show_community(vty, bgp, community,
11800 exact_match, afi,
11801 safi, show_flags);
11802 else
11803 bgp_show(vty, bgp, afi, safi, sh_type,
11804 NULL, show_flags);
11805 if (uj)
11806 vty_out(vty, "}\n");
11807 }
11808 }
11809 if (uj)
11810 vty_out(vty, "}\n");
11811 }
11812 return CMD_SUCCESS;
a636c635 11813}
47fc97cc 11814
718e3744 11815DEFUN (show_ip_bgp_route,
11816 show_ip_bgp_route_cmd,
3efd0893 11817 "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 11818 SHOW_STR
11819 IP_STR
11820 BGP_STR
a636c635 11821 BGP_INSTANCE_HELP_STR
4f280b15 11822 BGP_AFI_HELP_STR
4dd6177e 11823 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11824 "Network in the BGP routing table to display\n"
0c7b1b01 11825 "IPv4 prefix\n"
8c3deaae 11826 "Network in the BGP routing table to display\n"
0c7b1b01 11827 "IPv6 prefix\n"
4092b06c 11828 "Display only the bestpath\n"
b05a1c8b 11829 "Display only multipaths\n"
9973d184 11830 JSON_STR)
4092b06c 11831{
d62a17ae 11832 int prefix_check = 0;
ae19d7dd 11833
d62a17ae 11834 afi_t afi = AFI_IP6;
11835 safi_t safi = SAFI_UNICAST;
11836 char *prefix = NULL;
11837 struct bgp *bgp = NULL;
11838 enum bgp_path_type path_type;
9f049418 11839 bool uj = use_json(argc, argv);
b05a1c8b 11840
d62a17ae 11841 int idx = 0;
ae19d7dd 11842
d62a17ae 11843 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11844 &bgp, uj);
d62a17ae 11845 if (!idx)
11846 return CMD_WARNING;
c41247f5 11847
d62a17ae 11848 if (!bgp) {
11849 vty_out(vty,
11850 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11851 return CMD_WARNING;
11852 }
a636c635 11853
d62a17ae 11854 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11855 if (argv_find(argv, argc, "A.B.C.D", &idx)
11856 || argv_find(argv, argc, "X:X::X:X", &idx))
11857 prefix_check = 0;
11858 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11859 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11860 prefix_check = 1;
11861
11862 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11863 && afi != AFI_IP6) {
11864 vty_out(vty,
11865 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11866 return CMD_WARNING;
11867 }
11868 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11869 && afi != AFI_IP) {
11870 vty_out(vty,
11871 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11872 return CMD_WARNING;
11873 }
11874
11875 prefix = argv[idx]->arg;
11876
11877 /* [<bestpath|multipath>] */
11878 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11879 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11880 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11881 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11882 else
360660c6 11883 path_type = BGP_PATH_SHOW_ALL;
a636c635 11884
d62a17ae 11885 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11886 path_type, uj);
4092b06c
DS
11887}
11888
8c3deaae
QY
11889DEFUN (show_ip_bgp_regexp,
11890 show_ip_bgp_regexp_cmd,
3e5b31b3 11891 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11892 SHOW_STR
11893 IP_STR
11894 BGP_STR
b00b230a 11895 BGP_INSTANCE_HELP_STR
4f280b15 11896 BGP_AFI_HELP_STR
4dd6177e 11897 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11898 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11899 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11900 JSON_STR)
8c3deaae 11901{
d62a17ae 11902 afi_t afi = AFI_IP6;
11903 safi_t safi = SAFI_UNICAST;
11904 struct bgp *bgp = NULL;
3e5b31b3
DA
11905 bool uj = use_json(argc, argv);
11906 char *regstr = NULL;
8c3deaae 11907
d62a17ae 11908 int idx = 0;
11909 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11910 &bgp, false);
d62a17ae 11911 if (!idx)
11912 return CMD_WARNING;
8c3deaae 11913
d62a17ae 11914 // get index of regex
3e5b31b3
DA
11915 if (argv_find(argv, argc, "REGEX", &idx))
11916 regstr = argv[idx]->arg;
8c3deaae 11917
5f71d11c 11918 assert(regstr);
3e5b31b3
DA
11919 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11920 bgp_show_type_regexp, uj);
8c3deaae
QY
11921}
11922
ae248832 11923DEFPY (show_ip_bgp_instance_all,
a636c635 11924 show_ip_bgp_instance_all_cmd,
ae248832 11925 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11926 SHOW_STR
a636c635 11927 IP_STR
4092b06c 11928 BGP_STR
a636c635 11929 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11930 BGP_AFI_HELP_STR
4dd6177e 11931 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11932 JSON_STR
11933 "Increase table width for longer prefixes\n")
4092b06c 11934{
d62a17ae 11935 afi_t afi = AFI_IP;
11936 safi_t safi = SAFI_UNICAST;
11937 struct bgp *bgp = NULL;
d62a17ae 11938 int idx = 0;
96f3485c 11939 uint8_t show_flags = 0;
ae19d7dd 11940
96f3485c 11941 if (uj) {
d62a17ae 11942 argc--;
96f3485c
MK
11943 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11944 }
11945
11946 if (wide)
11947 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11948
9f049418
DS
11949 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11950 &bgp, uj);
11951 if (!idx)
11952 return CMD_WARNING;
11953
96f3485c 11954 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11955 return CMD_SUCCESS;
e3e29b32
LB
11956}
11957
a4d82a8a 11958static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11959 afi_t afi, safi_t safi, enum bgp_show_type type,
11960 bool use_json)
718e3744 11961{
d62a17ae 11962 regex_t *regex;
11963 int rc;
96f3485c
MK
11964 uint8_t show_flags = 0;
11965
11966 if (use_json)
11967 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11968
c3900853 11969 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11970 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11971 regstr);
11972 return CMD_WARNING_CONFIG_FAILED;
11973 }
11974
d62a17ae 11975 regex = bgp_regcomp(regstr);
11976 if (!regex) {
11977 vty_out(vty, "Can't compile regexp %s\n", regstr);
11978 return CMD_WARNING;
11979 }
a636c635 11980
96f3485c 11981 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11982 bgp_regex_free(regex);
11983 return rc;
e3e29b32
LB
11984}
11985
d62a17ae 11986static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11987 const char *prefix_list_str, afi_t afi,
11988 safi_t safi, enum bgp_show_type type)
e3e29b32 11989{
d62a17ae 11990 struct prefix_list *plist;
96f3485c 11991 uint8_t show_flags = 0;
718e3744 11992
d62a17ae 11993 plist = prefix_list_lookup(afi, prefix_list_str);
11994 if (plist == NULL) {
11995 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11996 prefix_list_str);
11997 return CMD_WARNING;
11998 }
718e3744 11999
96f3485c 12000 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
12001}
12002
d62a17ae 12003static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12004 const char *filter, afi_t afi, safi_t safi,
12005 enum bgp_show_type type)
4092b06c 12006{
d62a17ae 12007 struct as_list *as_list;
96f3485c 12008 uint8_t show_flags = 0;
718e3744 12009
d62a17ae 12010 as_list = as_list_lookup(filter);
12011 if (as_list == NULL) {
12012 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12013 filter);
12014 return CMD_WARNING;
12015 }
a636c635 12016
96f3485c 12017 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12018}
12019
d62a17ae 12020static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12021 const char *rmap_str, afi_t afi, safi_t safi,
12022 enum bgp_show_type type)
718e3744 12023{
d62a17ae 12024 struct route_map *rmap;
96f3485c 12025 uint8_t show_flags = 0;
bb46e94f 12026
d62a17ae 12027 rmap = route_map_lookup_by_name(rmap_str);
12028 if (!rmap) {
12029 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12030 return CMD_WARNING;
12031 }
12032
96f3485c 12033 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12034}
12035
7f323236
DW
12036static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12037 const char *comstr, int exact, afi_t afi,
96f3485c 12038 safi_t safi, uint8_t show_flags)
d62a17ae 12039{
12040 struct community *com;
d62a17ae 12041 int ret = 0;
12042
7f323236 12043 com = community_str2com(comstr);
d62a17ae 12044 if (!com) {
7f323236 12045 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12046 return CMD_WARNING;
12047 }
12048
12049 ret = bgp_show(vty, bgp, afi, safi,
12050 (exact ? bgp_show_type_community_exact
12051 : bgp_show_type_community),
96f3485c 12052 com, show_flags);
3c1f53de 12053 community_free(&com);
46c3ce83 12054
d62a17ae 12055 return ret;
718e3744 12056}
12057
d62a17ae 12058static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12059 const char *com, int exact, afi_t afi,
12060 safi_t safi)
50ef26d4 12061{
d62a17ae 12062 struct community_list *list;
96f3485c 12063 uint8_t show_flags = 0;
50ef26d4 12064
e237b0d2 12065 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12066 if (list == NULL) {
12067 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12068 return CMD_WARNING;
12069 }
718e3744 12070
d62a17ae 12071 return bgp_show(vty, bgp, afi, safi,
12072 (exact ? bgp_show_type_community_list_exact
12073 : bgp_show_type_community_list),
96f3485c 12074 list, show_flags);
50ef26d4 12075}
12076
d62a17ae 12077static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12078 const char *prefix, afi_t afi, safi_t safi,
12079 enum bgp_show_type type)
718e3744 12080{
d62a17ae 12081 int ret;
12082 struct prefix *p;
96f3485c 12083 uint8_t show_flags = 0;
47fc97cc 12084
d62a17ae 12085 p = prefix_new();
95cbbd2a 12086
d62a17ae 12087 ret = str2prefix(prefix, p);
12088 if (!ret) {
12089 vty_out(vty, "%% Malformed Prefix\n");
12090 return CMD_WARNING;
12091 }
47e9b292 12092
96f3485c 12093 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12094 prefix_free(&p);
d62a17ae 12095 return ret;
12096}
12097
d62a17ae 12098enum bgp_stats {
12099 BGP_STATS_MAXBITLEN = 0,
12100 BGP_STATS_RIB,
12101 BGP_STATS_PREFIXES,
12102 BGP_STATS_TOTPLEN,
12103 BGP_STATS_UNAGGREGATEABLE,
12104 BGP_STATS_MAX_AGGREGATEABLE,
12105 BGP_STATS_AGGREGATES,
12106 BGP_STATS_SPACE,
12107 BGP_STATS_ASPATH_COUNT,
12108 BGP_STATS_ASPATH_MAXHOPS,
12109 BGP_STATS_ASPATH_TOTHOPS,
12110 BGP_STATS_ASPATH_MAXSIZE,
12111 BGP_STATS_ASPATH_TOTSIZE,
12112 BGP_STATS_ASN_HIGHEST,
12113 BGP_STATS_MAX,
a636c635 12114};
2815e61f 12115
9ab0cf58 12116#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12117#define TABLE_STATS_IDX_JSON 1
12118
12119static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12120 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12121 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12122 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12123 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12124 "unaggregateablePrefixes"},
12125 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12126 "maximumAggregateablePrefixes"},
12127 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12128 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12129 [BGP_STATS_SPACE] = {"Address space advertised",
12130 "addressSpaceAdvertised"},
9ab0cf58
PG
12131 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12132 "advertisementsWithPaths"},
12133 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12134 "longestAsPath"},
12135 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12136 "largestAsPath"},
12137 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12138 "averageAsPathLengthHops"},
12139 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12140 "averageAsPathSizeBytes"},
12141 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12142 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12143};
2815e61f 12144
d62a17ae 12145struct bgp_table_stats {
12146 struct bgp_table *table;
12147 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12148 double total_space;
ff7924f6
PJ
12149};
12150
a636c635
DW
12151#if 0
12152#define TALLY_SIGFIG 100000
12153static unsigned long
12154ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12155{
a636c635
DW
12156 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12157 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12158 unsigned long ret = newtot / count;
07d0c4ed 12159
a636c635
DW
12160 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12161 return ret + 1;
12162 else
12163 return ret;
12164}
12165#endif
ff7924f6 12166
9bcb3eef 12167static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12168 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12169{
9bcb3eef 12170 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12171 struct bgp_path_info *pi;
b54892e0 12172 const struct prefix *rn_p;
d62a17ae 12173
9bcb3eef 12174 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12175 return;
d62a17ae 12176
9bcb3eef 12177 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12178 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12179 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12180
a636c635
DW
12181#if 0
12182 ts->counts[BGP_STATS_AVGPLEN]
12183 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12184 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12185 rn_p->prefixlen);
a636c635 12186#endif
d62a17ae 12187
9c14ec72 12188 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12189 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12190 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12191
9bcb3eef 12192 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12193 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12194 /* announced address space */
12195 if (space)
b54892e0 12196 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12197 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12198 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12199
9c14ec72 12200
9bcb3eef 12201 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12202 ts->counts[BGP_STATS_RIB]++;
12203
05864da7
DS
12204 if (CHECK_FLAG(pi->attr->flag,
12205 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12206 ts->counts[BGP_STATS_AGGREGATES]++;
12207
12208 /* as-path stats */
05864da7 12209 if (pi->attr->aspath) {
9c14ec72
RW
12210 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12211 unsigned int size = aspath_size(pi->attr->aspath);
12212 as_t highest = aspath_highest(pi->attr->aspath);
12213
12214 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12215
12216 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12217 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12218
12219 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12220 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12221
12222 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12223 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12224#if 0
07d0c4ed 12225 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12226 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12227 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12228 hops);
12229 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12230 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12231 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12232 size);
12233#endif
9c14ec72
RW
12234 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12235 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12236 }
12237 }
12238}
12239
12240static int bgp_table_stats_walker(struct thread *t)
12241{
9bcb3eef
DS
12242 struct bgp_dest *dest, *ndest;
12243 struct bgp_dest *top;
9c14ec72
RW
12244 struct bgp_table_stats *ts = THREAD_ARG(t);
12245 unsigned int space = 0;
12246
12247 if (!(top = bgp_table_top(ts->table)))
12248 return 0;
12249
12250 switch (ts->table->afi) {
12251 case AFI_IP:
12252 space = IPV4_MAX_BITLEN;
12253 break;
12254 case AFI_IP6:
12255 space = IPV6_MAX_BITLEN;
12256 break;
12257 default:
12258 return 0;
12259 }
12260
12261 ts->counts[BGP_STATS_MAXBITLEN] = space;
12262
9bcb3eef 12263 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12264 if (ts->table->safi == SAFI_MPLS_VPN
12265 || ts->table->safi == SAFI_ENCAP
12266 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12267 struct bgp_table *table;
12268
9bcb3eef 12269 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12270 if (!table)
12271 continue;
12272
12273 top = bgp_table_top(table);
9bcb3eef
DS
12274 for (ndest = bgp_table_top(table); ndest;
12275 ndest = bgp_route_next(ndest))
12276 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12277 } else {
9bcb3eef 12278 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12279 }
12280 }
9c14ec72 12281
d62a17ae 12282 return 0;
2815e61f 12283}
ff7924f6 12284
71f1613a
DA
12285static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12286 struct json_object *json_array)
12287{
12288 struct listnode *node, *nnode;
12289 struct bgp *bgp;
12290
12291 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12292 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12293}
12294
12295static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12296 safi_t safi, struct json_object *json_array)
2815e61f 12297{
d62a17ae 12298 struct bgp_table_stats ts;
12299 unsigned int i;
893cccd0
PG
12300 int ret = CMD_SUCCESS;
12301 char temp_buf[20];
6c9d22e2
PG
12302 struct json_object *json = NULL;
12303
12304 if (json_array)
12305 json = json_object_new_object();
019386c2 12306
d62a17ae 12307 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12308 char warning_msg[50];
12309
12310 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12311 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12312 safi);
6c9d22e2
PG
12313
12314 if (!json)
893cccd0
PG
12315 vty_out(vty, "%s\n", warning_msg);
12316 else
9ab0cf58 12317 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12318
893cccd0
PG
12319 ret = CMD_WARNING;
12320 goto end_table_stats;
d62a17ae 12321 }
019386c2 12322
893cccd0 12323 if (!json)
5290ceab
DA
12324 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12325 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12326 else
12327 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12328
d62a17ae 12329 /* labeled-unicast routes live in the unicast table */
12330 if (safi == SAFI_LABELED_UNICAST)
12331 safi = SAFI_UNICAST;
019386c2 12332
d62a17ae 12333 memset(&ts, 0, sizeof(ts));
12334 ts.table = bgp->rib[afi][safi];
12335 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12336
d62a17ae 12337 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12338 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12339 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12340 continue;
12341
12342 switch (i) {
a636c635
DW
12343#if 0
12344 case BGP_STATS_ASPATH_AVGHOPS:
12345 case BGP_STATS_ASPATH_AVGSIZE:
12346 case BGP_STATS_AVGPLEN:
12347 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12348 vty_out (vty, "%12.2f",
12349 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12350 break;
12351#endif
d62a17ae 12352 case BGP_STATS_ASPATH_TOTHOPS:
12353 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12354 if (!json) {
9ab0cf58
PG
12355 snprintf(
12356 temp_buf, sizeof(temp_buf), "%12.2f",
12357 ts.counts[i]
12358 ? (float)ts.counts[i]
12359 / (float)ts.counts
12360 [BGP_STATS_ASPATH_COUNT]
12361 : 0);
893cccd0 12362 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12363 table_stats_strs[i]
12364 [TABLE_STATS_IDX_VTY],
893cccd0 12365 temp_buf);
9ab0cf58
PG
12366 } else {
12367 json_object_double_add(
12368 json,
12369 table_stats_strs[i]
12370 [TABLE_STATS_IDX_JSON],
12371 ts.counts[i]
12372 ? (double)ts.counts[i]
12373 / (double)ts.counts
d62a17ae 12374 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12375 : 0);
12376 }
d62a17ae 12377 break;
12378 case BGP_STATS_TOTPLEN:
6c9d22e2 12379 if (!json) {
9ab0cf58
PG
12380 snprintf(
12381 temp_buf, sizeof(temp_buf), "%12.2f",
12382 ts.counts[i]
12383 ? (float)ts.counts[i]
12384 / (float)ts.counts
12385 [BGP_STATS_PREFIXES]
12386 : 0);
893cccd0 12387 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12388 table_stats_strs[i]
12389 [TABLE_STATS_IDX_VTY],
893cccd0 12390 temp_buf);
9ab0cf58
PG
12391 } else {
12392 json_object_double_add(
12393 json,
12394 table_stats_strs[i]
12395 [TABLE_STATS_IDX_JSON],
12396 ts.counts[i]
12397 ? (double)ts.counts[i]
12398 / (double)ts.counts
d62a17ae 12399 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12400 : 0);
12401 }
d62a17ae 12402 break;
12403 case BGP_STATS_SPACE:
6c9d22e2
PG
12404 if (!json) {
12405 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12406 ts.total_space);
893cccd0 12407 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12408 table_stats_strs[i]
12409 [TABLE_STATS_IDX_VTY],
893cccd0 12410 temp_buf);
9ab0cf58
PG
12411 } else {
12412 json_object_double_add(
12413 json,
12414 table_stats_strs[i]
12415 [TABLE_STATS_IDX_JSON],
12416 (double)ts.total_space);
12417 }
8d0ab76d 12418 if (afi == AFI_IP6) {
6c9d22e2
PG
12419 if (!json) {
12420 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12421 "%12g",
12422 ts.total_space
12423 * pow(2.0, -128 + 32));
6c9d22e2
PG
12424 vty_out(vty, "%30s: %s\n",
12425 "/32 equivalent %s\n",
12426 temp_buf);
9ab0cf58
PG
12427 } else {
12428 json_object_double_add(
12429 json, "/32equivalent",
12430 (double)(ts.total_space
12431 * pow(2.0,
12432 -128 + 32)));
12433 }
6c9d22e2
PG
12434 if (!json) {
12435 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12436 "%12g",
12437 ts.total_space
12438 * pow(2.0, -128 + 48));
6c9d22e2
PG
12439 vty_out(vty, "%30s: %s\n",
12440 "/48 equivalent %s\n",
12441 temp_buf);
9ab0cf58
PG
12442 } else {
12443 json_object_double_add(
12444 json, "/48equivalent",
12445 (double)(ts.total_space
12446 * pow(2.0,
12447 -128 + 48)));
12448 }
8d0ab76d 12449 } else {
6c9d22e2
PG
12450 if (!json) {
12451 snprintf(temp_buf, sizeof(temp_buf),
12452 "%12.2f",
9ab0cf58
PG
12453 ts.total_space * 100.
12454 * pow(2.0, -32));
6c9d22e2 12455 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12456 "% announced ", temp_buf);
12457 } else {
12458 json_object_double_add(
12459 json, "%announced",
12460 (double)(ts.total_space * 100.
12461 * pow(2.0, -32)));
12462 }
6c9d22e2
PG
12463 if (!json) {
12464 snprintf(temp_buf, sizeof(temp_buf),
12465 "%12.2f",
9ab0cf58
PG
12466 ts.total_space
12467 * pow(2.0, -32 + 8));
6c9d22e2
PG
12468 vty_out(vty, "%30s: %s\n",
12469 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12470 } else {
12471 json_object_double_add(
12472 json, "/8equivalent",
12473 (double)(ts.total_space
12474 * pow(2.0, -32 + 8)));
12475 }
6c9d22e2
PG
12476 if (!json) {
12477 snprintf(temp_buf, sizeof(temp_buf),
12478 "%12.2f",
9ab0cf58
PG
12479 ts.total_space
12480 * pow(2.0, -32 + 24));
6c9d22e2 12481 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12482 "/24 equivalent ", temp_buf);
12483 } else {
12484 json_object_double_add(
12485 json, "/24equivalent",
12486 (double)(ts.total_space
12487 * pow(2.0, -32 + 24)));
12488 }
8d0ab76d 12489 }
d62a17ae 12490 break;
12491 default:
6c9d22e2
PG
12492 if (!json) {
12493 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12494 ts.counts[i]);
893cccd0 12495 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12496 table_stats_strs[i]
12497 [TABLE_STATS_IDX_VTY],
12498 temp_buf);
12499 } else {
12500 json_object_int_add(
12501 json,
12502 table_stats_strs[i]
12503 [TABLE_STATS_IDX_JSON],
12504 ts.counts[i]);
12505 }
d62a17ae 12506 }
893cccd0
PG
12507 if (!json)
12508 vty_out(vty, "\n");
d62a17ae 12509 }
9ab0cf58 12510end_table_stats:
6c9d22e2
PG
12511 if (json)
12512 json_object_array_add(json_array, json);
893cccd0 12513 return ret;
d62a17ae 12514}
12515
71f1613a
DA
12516static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12517 safi_t safi, struct json_object *json_array)
12518{
12519 if (!bgp) {
12520 bgp_table_stats_all(vty, afi, safi, json_array);
12521 return CMD_SUCCESS;
12522 }
12523
12524 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12525}
12526
d62a17ae 12527enum bgp_pcounts {
12528 PCOUNT_ADJ_IN = 0,
12529 PCOUNT_DAMPED,
12530 PCOUNT_REMOVED,
12531 PCOUNT_HISTORY,
12532 PCOUNT_STALE,
12533 PCOUNT_VALID,
12534 PCOUNT_ALL,
12535 PCOUNT_COUNTED,
7e3d9632 12536 PCOUNT_BPATH_SELECTED,
d62a17ae 12537 PCOUNT_PFCNT, /* the figure we display to users */
12538 PCOUNT_MAX,
a636c635 12539};
718e3744 12540
2b64873d 12541static const char *const pcount_strs[] = {
9d303b37
DL
12542 [PCOUNT_ADJ_IN] = "Adj-in",
12543 [PCOUNT_DAMPED] = "Damped",
12544 [PCOUNT_REMOVED] = "Removed",
12545 [PCOUNT_HISTORY] = "History",
12546 [PCOUNT_STALE] = "Stale",
12547 [PCOUNT_VALID] = "Valid",
12548 [PCOUNT_ALL] = "All RIB",
12549 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12550 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12551 [PCOUNT_PFCNT] = "Useable",
12552 [PCOUNT_MAX] = NULL,
a636c635 12553};
718e3744 12554
d62a17ae 12555struct peer_pcounts {
12556 unsigned int count[PCOUNT_MAX];
12557 const struct peer *peer;
12558 const struct bgp_table *table;
54317cba 12559 safi_t safi;
a636c635 12560};
47fc97cc 12561
9bcb3eef 12562static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12563{
54317cba
JW
12564 const struct bgp_adj_in *ain;
12565 const struct bgp_path_info *pi;
d62a17ae 12566 const struct peer *peer = pc->peer;
12567
54317cba
JW
12568 for (ain = rn->adj_in; ain; ain = ain->next)
12569 if (ain->peer == peer)
12570 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12571
9bcb3eef 12572 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12573
54317cba
JW
12574 if (pi->peer != peer)
12575 continue;
d62a17ae 12576
54317cba 12577 pc->count[PCOUNT_ALL]++;
d62a17ae 12578
54317cba
JW
12579 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12580 pc->count[PCOUNT_DAMPED]++;
12581 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12582 pc->count[PCOUNT_HISTORY]++;
12583 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12584 pc->count[PCOUNT_REMOVED]++;
12585 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12586 pc->count[PCOUNT_STALE]++;
12587 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12588 pc->count[PCOUNT_VALID]++;
12589 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12590 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12591 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12592 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12593
12594 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12595 pc->count[PCOUNT_COUNTED]++;
12596 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12597 flog_err(
12598 EC_LIB_DEVELOPMENT,
12599 "Attempting to count but flags say it is unusable");
12600 } else {
40381db7 12601 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12602 flog_err(
12603 EC_LIB_DEVELOPMENT,
12604 "Not counted but flags say we should");
d62a17ae 12605 }
12606 }
54317cba
JW
12607}
12608
12609static int bgp_peer_count_walker(struct thread *t)
12610{
9bcb3eef 12611 struct bgp_dest *rn, *rm;
54317cba
JW
12612 const struct bgp_table *table;
12613 struct peer_pcounts *pc = THREAD_ARG(t);
12614
12615 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12616 || pc->safi == SAFI_EVPN) {
12617 /* Special handling for 2-level routing tables. */
12618 for (rn = bgp_table_top(pc->table); rn;
12619 rn = bgp_route_next(rn)) {
9bcb3eef 12620 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12621 if (table != NULL)
12622 for (rm = bgp_table_top(table); rm;
12623 rm = bgp_route_next(rm))
12624 bgp_peer_count_proc(rm, pc);
12625 }
12626 } else
12627 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12628 bgp_peer_count_proc(rn, pc);
12629
d62a17ae 12630 return 0;
718e3744 12631}
12632
d62a17ae 12633static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12634 safi_t safi, bool use_json)
856ca177 12635{
d62a17ae 12636 struct peer_pcounts pcounts = {.peer = peer};
12637 unsigned int i;
12638 json_object *json = NULL;
12639 json_object *json_loop = NULL;
856ca177 12640
d62a17ae 12641 if (use_json) {
12642 json = json_object_new_object();
12643 json_loop = json_object_new_object();
12644 }
718e3744 12645
d62a17ae 12646 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12647 || !peer->bgp->rib[afi][safi]) {
12648 if (use_json) {
12649 json_object_string_add(
12650 json, "warning",
12651 "No such neighbor or address family");
12652 vty_out(vty, "%s\n", json_object_to_json_string(json));
12653 json_object_free(json);
12654 } else
12655 vty_out(vty, "%% No such neighbor or address family\n");
12656
12657 return CMD_WARNING;
12658 }
2a71e9ce 12659
d62a17ae 12660 memset(&pcounts, 0, sizeof(pcounts));
12661 pcounts.peer = peer;
12662 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12663 pcounts.safi = safi;
d62a17ae 12664
12665 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12666 * stats for the thread-walk (i.e. ensure this can't be blamed on
12667 * on just vty_read()).
12668 */
d62a17ae 12669 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12670
12671 if (use_json) {
12672 json_object_string_add(json, "prefixCountsFor", peer->host);
12673 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12674 get_afi_safi_str(afi, safi, true));
d62a17ae 12675 json_object_int_add(json, "pfxCounter",
12676 peer->pcount[afi][safi]);
12677
12678 for (i = 0; i < PCOUNT_MAX; i++)
12679 json_object_int_add(json_loop, pcount_strs[i],
12680 pcounts.count[i]);
12681
12682 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12683
12684 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12685 json_object_string_add(json, "pfxctDriftFor",
12686 peer->host);
12687 json_object_string_add(
12688 json, "recommended",
12689 "Please report this bug, with the above command output");
12690 }
996c9314
LB
12691 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12692 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12693 json_object_free(json);
12694 } else {
12695
12696 if (peer->hostname
892fedb6 12697 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12698 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12699 peer->hostname, peer->host,
5cb5f4d0 12700 get_afi_safi_str(afi, safi, false));
d62a17ae 12701 } else {
12702 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12703 get_afi_safi_str(afi, safi, false));
d62a17ae 12704 }
12705
6cde4b45 12706 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12707 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12708
12709 for (i = 0; i < PCOUNT_MAX; i++)
12710 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12711 pcounts.count[i]);
12712
12713 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12714 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12715 vty_out(vty,
12716 "Please report this bug, with the above command output\n");
12717 }
12718 }
12719
12720 return CMD_SUCCESS;
718e3744 12721}
12722
a636c635
DW
12723DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12724 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12725 "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 12726 SHOW_STR
12727 IP_STR
12728 BGP_STR
8386ac43 12729 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12730 BGP_AFI_HELP_STR
12731 BGP_SAFI_HELP_STR
0b16f239
DS
12732 "Detailed information on TCP and BGP neighbor connections\n"
12733 "Neighbor to display information about\n"
12734 "Neighbor to display information about\n"
91d37724 12735 "Neighbor on BGP configured interface\n"
a636c635 12736 "Display detailed prefix count information\n"
9973d184 12737 JSON_STR)
0b16f239 12738{
d62a17ae 12739 afi_t afi = AFI_IP6;
12740 safi_t safi = SAFI_UNICAST;
12741 struct peer *peer;
12742 int idx = 0;
12743 struct bgp *bgp = NULL;
9f049418
DS
12744 bool uj = use_json(argc, argv);
12745
12746 if (uj)
12747 argc--;
856ca177 12748
d62a17ae 12749 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12750 &bgp, uj);
d62a17ae 12751 if (!idx)
12752 return CMD_WARNING;
0b16f239 12753
d62a17ae 12754 argv_find(argv, argc, "neighbors", &idx);
12755 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12756 if (!peer)
12757 return CMD_WARNING;
bb46e94f 12758
29c8d9da 12759 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12760}
0b16f239 12761
d6902373
PG
12762#ifdef KEEP_OLD_VPN_COMMANDS
12763DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12764 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12765 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12766 SHOW_STR
12767 IP_STR
12768 BGP_STR
d6902373 12769 BGP_VPNVX_HELP_STR
91d37724 12770 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12771 "Detailed information on TCP and BGP neighbor connections\n"
12772 "Neighbor to display information about\n"
12773 "Neighbor to display information about\n"
91d37724 12774 "Neighbor on BGP configured interface\n"
a636c635 12775 "Display detailed prefix count information\n"
9973d184 12776 JSON_STR)
a636c635 12777{
d62a17ae 12778 int idx_peer = 6;
12779 struct peer *peer;
9f049418 12780 bool uj = use_json(argc, argv);
a636c635 12781
d62a17ae 12782 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12783 if (!peer)
12784 return CMD_WARNING;
12785
12786 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12787}
12788
d6902373
PG
12789DEFUN (show_ip_bgp_vpn_all_route_prefix,
12790 show_ip_bgp_vpn_all_route_prefix_cmd,
12791 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12792 SHOW_STR
12793 IP_STR
12794 BGP_STR
d6902373 12795 BGP_VPNVX_HELP_STR
91d37724
QY
12796 "Display information about all VPNv4 NLRIs\n"
12797 "Network in the BGP routing table to display\n"
3a2d747c 12798 "Network in the BGP routing table to display\n"
9973d184 12799 JSON_STR)
91d37724 12800{
d62a17ae 12801 int idx = 0;
12802 char *network = NULL;
12803 struct bgp *bgp = bgp_get_default();
12804 if (!bgp) {
12805 vty_out(vty, "Can't find default instance\n");
12806 return CMD_WARNING;
12807 }
87e34b58 12808
d62a17ae 12809 if (argv_find(argv, argc, "A.B.C.D", &idx))
12810 network = argv[idx]->arg;
12811 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12812 network = argv[idx]->arg;
12813 else {
12814 vty_out(vty, "Unable to figure out Network\n");
12815 return CMD_WARNING;
12816 }
87e34b58 12817
d62a17ae 12818 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12819 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12820}
d6902373 12821#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12822
44c69747
LK
12823DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12824 show_bgp_l2vpn_evpn_route_prefix_cmd,
12825 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12826 SHOW_STR
4c63a661
PG
12827 BGP_STR
12828 L2VPN_HELP_STR
12829 EVPN_HELP_STR
44c69747
LK
12830 "Network in the BGP routing table to display\n"
12831 "Network in the BGP routing table to display\n"
4c63a661
PG
12832 "Network in the BGP routing table to display\n"
12833 "Network in the BGP routing table to display\n"
12834 JSON_STR)
12835{
d62a17ae 12836 int idx = 0;
12837 char *network = NULL;
44c69747 12838 int prefix_check = 0;
a636c635 12839
44c69747
LK
12840 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12841 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12842 network = argv[idx]->arg;
44c69747 12843 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12844 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12845 network = argv[idx]->arg;
44c69747
LK
12846 prefix_check = 1;
12847 } else {
d62a17ae 12848 vty_out(vty, "Unable to figure out Network\n");
12849 return CMD_WARNING;
12850 }
44c69747
LK
12851 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12852 prefix_check, BGP_PATH_SHOW_ALL,
12853 use_json(argc, argv));
d62a17ae 12854}
12855
2f9bc755
DS
12856static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12857 struct bgp_table *table, int *header1,
12858 int *header2, json_object *json,
12859 json_object *json_scode,
12860 json_object *json_ocode, bool wide)
12861{
12862 uint64_t version = table ? table->version : 0;
23d0a753 12863 char buf[BUFSIZ] = {0};
2f9bc755
DS
12864
12865 if (*header1) {
12866 if (json) {
12867 json_object_int_add(json, "bgpTableVersion", version);
12868 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12869 inet_ntop(AF_INET,
12870 &bgp->router_id, buf,
12871 sizeof(buf)));
2f9bc755
DS
12872 json_object_int_add(json, "defaultLocPrf",
12873 bgp->default_local_pref);
12874 json_object_int_add(json, "localAS", bgp->as);
12875 json_object_object_add(json, "bgpStatusCodes",
12876 json_scode);
12877 json_object_object_add(json, "bgpOriginCodes",
12878 json_ocode);
12879 } else {
12880 vty_out(vty,
23d0a753
DA
12881 "BGP table version is %" PRIu64
12882 ", local router ID is %pI4, vrf id ",
12883 version, &bgp->router_id);
2f9bc755
DS
12884 if (bgp->vrf_id == VRF_UNKNOWN)
12885 vty_out(vty, "%s", VRFID_NONE_STR);
12886 else
12887 vty_out(vty, "%u", bgp->vrf_id);
12888 vty_out(vty, "\n");
12889 vty_out(vty, "Default local pref %u, ",
12890 bgp->default_local_pref);
12891 vty_out(vty, "local AS %u\n", bgp->as);
12892 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12893 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12894 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12895 }
12896 *header1 = 0;
12897 }
12898 if (*header2) {
12899 if (!json)
12900 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12901 : BGP_SHOW_HEADER));
12902 *header2 = 0;
12903 }
12904}
12905
d62a17ae 12906static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12907 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12908 const char *rmap_name, json_object *json,
12909 uint8_t show_flags)
d62a17ae 12910{
12911 struct bgp_table *table;
12912 struct bgp_adj_in *ain;
12913 struct bgp_adj_out *adj;
74a630b6
NT
12914 unsigned long output_count = 0;
12915 unsigned long filtered_count = 0;
9bcb3eef 12916 struct bgp_dest *dest;
d62a17ae 12917 int header1 = 1;
12918 struct bgp *bgp;
12919 int header2 = 1;
12920 struct attr attr;
12921 int ret;
12922 struct update_subgroup *subgrp;
12923 json_object *json_scode = NULL;
12924 json_object *json_ocode = NULL;
12925 json_object *json_ar = NULL;
12926 struct peer_af *paf;
f99def61 12927 bool route_filtered;
96f3485c
MK
12928 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12929 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12930
12931 if (use_json) {
12932 json_scode = json_object_new_object();
12933 json_ocode = json_object_new_object();
12934 json_ar = json_object_new_object();
12935
12936 json_object_string_add(json_scode, "suppressed", "s");
12937 json_object_string_add(json_scode, "damped", "d");
12938 json_object_string_add(json_scode, "history", "h");
12939 json_object_string_add(json_scode, "valid", "*");
12940 json_object_string_add(json_scode, "best", ">");
12941 json_object_string_add(json_scode, "multipath", "=");
12942 json_object_string_add(json_scode, "internal", "i");
12943 json_object_string_add(json_scode, "ribFailure", "r");
12944 json_object_string_add(json_scode, "stale", "S");
12945 json_object_string_add(json_scode, "removed", "R");
12946
12947 json_object_string_add(json_ocode, "igp", "i");
12948 json_object_string_add(json_ocode, "egp", "e");
12949 json_object_string_add(json_ocode, "incomplete", "?");
12950 }
a636c635 12951
d62a17ae 12952 bgp = peer->bgp;
a636c635 12953
d62a17ae 12954 if (!bgp) {
12955 if (use_json) {
12956 json_object_string_add(json, "alert", "no BGP");
12957 vty_out(vty, "%s\n", json_object_to_json_string(json));
12958 json_object_free(json);
12959 } else
12960 vty_out(vty, "%% No bgp\n");
12961 return;
12962 }
a636c635 12963
c512a642
EDP
12964 /* labeled-unicast routes live in the unicast table */
12965 if (safi == SAFI_LABELED_UNICAST)
12966 table = bgp->rib[afi][SAFI_UNICAST];
12967 else
12968 table = bgp->rib[afi][safi];
d62a17ae 12969
12970 output_count = filtered_count = 0;
12971 subgrp = peer_subgroup(peer, afi, safi);
12972
6392aaa6 12973 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12974 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
12975 char buf[BUFSIZ] = {0};
12976
d62a17ae 12977 if (use_json) {
12978 json_object_int_add(json, "bgpTableVersion",
12979 table->version);
12980 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12981 inet_ntop(AF_INET,
12982 &bgp->router_id, buf,
12983 sizeof(buf)));
01eced22
AD
12984 json_object_int_add(json, "defaultLocPrf",
12985 bgp->default_local_pref);
12986 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12987 json_object_object_add(json, "bgpStatusCodes",
12988 json_scode);
12989 json_object_object_add(json, "bgpOriginCodes",
12990 json_ocode);
07d0c4ed
DA
12991 json_object_string_add(
12992 json, "bgpOriginatingDefaultNetwork",
12993 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12994 } else {
23d0a753
DA
12995 vty_out(vty,
12996 "BGP table version is %" PRIu64
12997 ", local router ID is %pI4, vrf id ",
12998 table->version, &bgp->router_id);
9df8b37c
PZ
12999 if (bgp->vrf_id == VRF_UNKNOWN)
13000 vty_out(vty, "%s", VRFID_NONE_STR);
13001 else
13002 vty_out(vty, "%u", bgp->vrf_id);
13003 vty_out(vty, "\n");
01eced22
AD
13004 vty_out(vty, "Default local pref %u, ",
13005 bgp->default_local_pref);
13006 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13007 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13008 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13009 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13010
07d0c4ed
DA
13011 vty_out(vty, "Originating default network %s\n\n",
13012 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13013 }
13014 header1 = 0;
13015 }
a636c635 13016
9bcb3eef 13017 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13018 if (type == bgp_show_adj_route_received
13019 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13020 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13021 if (ain->peer != peer)
ea47320b 13022 continue;
6392aaa6 13023
2f9bc755
DS
13024 show_adj_route_header(
13025 vty, bgp, table, &header1, &header2,
13026 json, json_scode, json_ocode, wide);
6392aaa6 13027
6f4f49b2 13028 attr = *ain->attr;
f99def61
AD
13029 route_filtered = false;
13030
13031 /* Filter prefix using distribute list,
13032 * filter list or prefix list
13033 */
b54892e0 13034 const struct prefix *rn_p =
9bcb3eef 13035 bgp_dest_get_prefix(dest);
b54892e0
DS
13036 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13037 safi))
13038 == FILTER_DENY)
f99def61
AD
13039 route_filtered = true;
13040
13041 /* Filter prefix using route-map */
b54892e0
DS
13042 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13043 safi, rmap_name, NULL,
13044 0, NULL);
6392aaa6 13045
13c8e163
AD
13046 if (type == bgp_show_adj_route_filtered &&
13047 !route_filtered && ret != RMAP_DENY) {
b755861b 13048 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13049 continue;
d62a17ae 13050 }
6392aaa6 13051
13c8e163
AD
13052 if (type == bgp_show_adj_route_received &&
13053 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13054 filtered_count++;
13055
b54892e0 13056 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13057 use_json, json_ar, wide);
b755861b 13058 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13059 output_count++;
d62a17ae 13060 }
6392aaa6 13061 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13062 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13063 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13064 if (paf->peer != peer || !adj->attr)
924c3f6a 13065 continue;
d62a17ae 13066
2f9bc755
DS
13067 show_adj_route_header(
13068 vty, bgp, table, &header1,
13069 &header2, json, json_scode,
13070 json_ocode, wide);
d62a17ae 13071
b54892e0 13072 const struct prefix *rn_p =
9bcb3eef 13073 bgp_dest_get_prefix(dest);
b54892e0 13074
6f4f49b2 13075 attr = *adj->attr;
b755861b 13076 ret = bgp_output_modifier(
b54892e0 13077 peer, rn_p, &attr, afi, safi,
b755861b 13078 rmap_name);
f46d8e1e 13079
b755861b 13080 if (ret != RMAP_DENY) {
b54892e0
DS
13081 route_vty_out_tmp(
13082 vty, rn_p, &attr, safi,
ae248832
MK
13083 use_json, json_ar,
13084 wide);
b755861b
PM
13085 output_count++;
13086 } else {
13087 filtered_count++;
a2addae8 13088 }
b755861b
PM
13089
13090 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13091 }
f20ce998
DS
13092 } else if (type == bgp_show_adj_route_bestpath) {
13093 struct bgp_path_info *pi;
13094
13095 show_adj_route_header(vty, bgp, table, &header1,
13096 &header2, json, json_scode,
13097 json_ocode, wide);
13098
13099 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13100 pi = pi->next) {
13101 if (pi->peer != peer)
13102 continue;
13103
13104 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13105 continue;
13106
13107 route_vty_out_tmp(vty,
13108 bgp_dest_get_prefix(dest),
13109 pi->attr, safi, use_json,
13110 json_ar, wide);
13111 output_count++;
13112 }
d62a17ae 13113 }
13114 }
d62a17ae 13115
d62a17ae 13116 if (use_json) {
6392aaa6
PM
13117 json_object_object_add(json, "advertisedRoutes", json_ar);
13118 json_object_int_add(json, "totalPrefixCounter", output_count);
13119 json_object_int_add(json, "filteredPrefixCounter",
13120 filtered_count);
13121
996c9314
LB
13122 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13123 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13124
13125 if (!output_count && !filtered_count) {
13126 json_object_free(json_scode);
13127 json_object_free(json_ocode);
13128 }
13129
d62a17ae 13130 json_object_free(json);
6392aaa6
PM
13131 } else if (output_count > 0) {
13132 if (filtered_count > 0)
13133 vty_out(vty,
13134 "\nTotal number of prefixes %ld (%ld filtered)\n",
13135 output_count, filtered_count);
13136 else
13137 vty_out(vty, "\nTotal number of prefixes %ld\n",
13138 output_count);
d62a17ae 13139 }
a636c635 13140}
2a71e9ce 13141
d62a17ae 13142static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13143 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13144 const char *rmap_name, uint8_t show_flags)
0b16f239 13145{
d62a17ae 13146 json_object *json = NULL;
96f3485c 13147 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13148
d62a17ae 13149 if (use_json)
13150 json = json_object_new_object();
0b16f239 13151
d62a17ae 13152 if (!peer || !peer->afc[afi][safi]) {
13153 if (use_json) {
13154 json_object_string_add(
13155 json, "warning",
13156 "No such neighbor or address family");
13157 vty_out(vty, "%s\n", json_object_to_json_string(json));
13158 json_object_free(json);
13159 } else
13160 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13161
d62a17ae 13162 return CMD_WARNING;
13163 }
13164
6392aaa6
PM
13165 if ((type == bgp_show_adj_route_received
13166 || type == bgp_show_adj_route_filtered)
d62a17ae 13167 && !CHECK_FLAG(peer->af_flags[afi][safi],
13168 PEER_FLAG_SOFT_RECONFIG)) {
13169 if (use_json) {
13170 json_object_string_add(
13171 json, "warning",
13172 "Inbound soft reconfiguration not enabled");
13173 vty_out(vty, "%s\n", json_object_to_json_string(json));
13174 json_object_free(json);
13175 } else
13176 vty_out(vty,
13177 "%% Inbound soft reconfiguration not enabled\n");
13178
13179 return CMD_WARNING;
13180 }
0b16f239 13181
96f3485c 13182 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13183
d62a17ae 13184 return CMD_SUCCESS;
a636c635 13185}
50ef26d4 13186
f20ce998
DS
13187DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13188 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13189 "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]",
13190 SHOW_STR
13191 IP_STR
13192 BGP_STR
13193 BGP_INSTANCE_HELP_STR
13194 BGP_AFI_HELP_STR
13195 BGP_SAFI_WITH_LABEL_HELP_STR
13196 "Detailed information on TCP and BGP neighbor connections\n"
13197 "Neighbor to display information about\n"
13198 "Neighbor to display information about\n"
13199 "Neighbor on BGP configured interface\n"
13200 "Display the routes selected by best path\n"
13201 JSON_STR
13202 "Increase table width for longer prefixes\n")
13203{
13204 afi_t afi = AFI_IP6;
13205 safi_t safi = SAFI_UNICAST;
13206 char *rmap_name = NULL;
13207 char *peerstr = NULL;
13208 struct bgp *bgp = NULL;
13209 struct peer *peer;
13210 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13211 int idx = 0;
96f3485c
MK
13212 uint8_t show_flags = 0;
13213
13214 if (uj)
13215 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13216
13217 if (wide)
13218 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13219
13220 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13221 &bgp, uj);
13222
13223 if (!idx)
13224 return CMD_WARNING;
13225
13226 argv_find(argv, argc, "neighbors", &idx);
13227 peerstr = argv[++idx]->arg;
13228
13229 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13230 if (!peer)
13231 return CMD_WARNING;
13232
96f3485c
MK
13233 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13234 show_flags);
f20ce998
DS
13235}
13236
ae248832 13237DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13238 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13239 "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 13240 SHOW_STR
13241 IP_STR
13242 BGP_STR
a636c635 13243 BGP_INSTANCE_HELP_STR
7395a2c9 13244 BGP_AFI_HELP_STR
4dd6177e 13245 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13246 "Display the entries for all address families\n"
718e3744 13247 "Detailed information on TCP and BGP neighbor connections\n"
13248 "Neighbor to display information about\n"
13249 "Neighbor to display information about\n"
91d37724 13250 "Neighbor on BGP configured interface\n"
a636c635 13251 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13252 "Display the received routes from neighbor\n"
13253 "Display the filtered routes received from neighbor\n"
a636c635
DW
13254 "Route-map to modify the attributes\n"
13255 "Name of the route map\n"
ae248832
MK
13256 JSON_STR
13257 "Increase table width for longer prefixes\n")
718e3744 13258{
d62a17ae 13259 afi_t afi = AFI_IP6;
13260 safi_t safi = SAFI_UNICAST;
13261 char *rmap_name = NULL;
13262 char *peerstr = NULL;
d62a17ae 13263 struct bgp *bgp = NULL;
13264 struct peer *peer;
6392aaa6 13265 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13266 int idx = 0;
96f3485c
MK
13267 bool first = true;
13268 uint8_t show_flags = 0;
6392aaa6 13269
96f3485c 13270 if (uj) {
d62a17ae 13271 argc--;
96f3485c
MK
13272 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13273 }
13274
13275 if (all) {
13276 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13277 if (argv_find(argv, argc, "ipv4", &idx))
13278 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13279
13280 if (argv_find(argv, argc, "ipv6", &idx))
13281 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13282 }
13283
13284 if (wide)
13285 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13286
9f049418
DS
13287 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13288 &bgp, uj);
13289 if (!idx)
13290 return CMD_WARNING;
13291
d62a17ae 13292 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13293 argv_find(argv, argc, "neighbors", &idx);
13294 peerstr = argv[++idx]->arg;
8c3deaae 13295
d62a17ae 13296 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13297 if (!peer)
13298 return CMD_WARNING;
856ca177 13299
d62a17ae 13300 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13301 type = bgp_show_adj_route_advertised;
13302 else if (argv_find(argv, argc, "received-routes", &idx))
13303 type = bgp_show_adj_route_received;
13304 else if (argv_find(argv, argc, "filtered-routes", &idx))
13305 type = bgp_show_adj_route_filtered;
13306
d62a17ae 13307 if (argv_find(argv, argc, "route-map", &idx))
13308 rmap_name = argv[++idx]->arg;
95cbbd2a 13309
96f3485c
MK
13310 if (!all)
13311 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13312 show_flags);
13313 if (uj)
13314 vty_out(vty, "{\n");
13315
13316 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13317 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13318 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13319 : AFI_IP6;
13320 FOREACH_SAFI (safi) {
13321 if (strmatch(get_afi_safi_str(afi, safi, true),
13322 "Unknown"))
13323 continue;
13324
13325 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13326 continue;
13327
13328 if (uj) {
13329 if (first)
13330 first = false;
13331 else
13332 vty_out(vty, ",\n");
13333 vty_out(vty, "\"%s\":",
13334 get_afi_safi_str(afi, safi, true));
13335 } else
13336 vty_out(vty, "\nFor address family: %s\n",
13337 get_afi_safi_str(afi, safi, false));
13338
13339 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13340 show_flags);
13341 }
13342 } else {
13343 FOREACH_AFI_SAFI (afi, safi) {
13344 if (strmatch(get_afi_safi_str(afi, safi, true),
13345 "Unknown"))
13346 continue;
13347
13348 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13349 continue;
13350
13351 if (uj) {
13352 if (first)
13353 first = false;
13354 else
13355 vty_out(vty, ",\n");
13356 vty_out(vty, "\"%s\":",
13357 get_afi_safi_str(afi, safi, true));
13358 } else
13359 vty_out(vty, "\nFor address family: %s\n",
13360 get_afi_safi_str(afi, safi, false));
13361
13362 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13363 show_flags);
13364 }
13365 }
13366 if (uj)
13367 vty_out(vty, "}\n");
13368
13369 return CMD_SUCCESS;
95cbbd2a
ML
13370}
13371
718e3744 13372DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13373 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13374 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13375 SHOW_STR
13376 IP_STR
13377 BGP_STR
8c3deaae
QY
13378 "Address Family\n"
13379 "Address Family\n"
718e3744 13380 "Address Family modifier\n"
13381 "Detailed information on TCP and BGP neighbor connections\n"
13382 "Neighbor to display information about\n"
13383 "Neighbor to display information about\n"
91d37724 13384 "Neighbor on BGP configured interface\n"
718e3744 13385 "Display information received from a BGP neighbor\n"
856ca177 13386 "Display the prefixlist filter\n"
9973d184 13387 JSON_STR)
718e3744 13388{
d62a17ae 13389 afi_t afi = AFI_IP6;
13390 safi_t safi = SAFI_UNICAST;
13391 char *peerstr = NULL;
13392
13393 char name[BUFSIZ];
13394 union sockunion su;
13395 struct peer *peer;
13396 int count, ret;
13397
13398 int idx = 0;
13399
13400 /* show [ip] bgp */
13401 if (argv_find(argv, argc, "ip", &idx))
13402 afi = AFI_IP;
13403 /* [<ipv4|ipv6> [unicast]] */
13404 if (argv_find(argv, argc, "ipv4", &idx))
13405 afi = AFI_IP;
13406 if (argv_find(argv, argc, "ipv6", &idx))
13407 afi = AFI_IP6;
13408 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13409 argv_find(argv, argc, "neighbors", &idx);
13410 peerstr = argv[++idx]->arg;
13411
9f049418 13412 bool uj = use_json(argc, argv);
d62a17ae 13413
13414 ret = str2sockunion(peerstr, &su);
13415 if (ret < 0) {
13416 peer = peer_lookup_by_conf_if(NULL, peerstr);
13417 if (!peer) {
13418 if (uj)
13419 vty_out(vty, "{}\n");
13420 else
13421 vty_out(vty,
13422 "%% Malformed address or name: %s\n",
13423 peerstr);
13424 return CMD_WARNING;
13425 }
13426 } else {
13427 peer = peer_lookup(NULL, &su);
13428 if (!peer) {
13429 if (uj)
13430 vty_out(vty, "{}\n");
13431 else
13432 vty_out(vty, "No peer\n");
13433 return CMD_WARNING;
13434 }
13435 }
718e3744 13436
4ced1a2c 13437 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13438 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13439 if (count) {
13440 if (!uj)
13441 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13442 get_afi_safi_str(afi, safi, false));
d62a17ae 13443 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13444 } else {
13445 if (uj)
13446 vty_out(vty, "{}\n");
13447 else
13448 vty_out(vty, "No functional output\n");
13449 }
718e3744 13450
d62a17ae 13451 return CMD_SUCCESS;
13452}
13453
13454static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13455 afi_t afi, safi_t safi,
9f049418 13456 enum bgp_show_type type, bool use_json)
d62a17ae 13457{
96f3485c
MK
13458 uint8_t show_flags = 0;
13459
13460 if (use_json)
13461 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13462
d62a17ae 13463 if (!peer || !peer->afc[afi][safi]) {
13464 if (use_json) {
13465 json_object *json_no = NULL;
13466 json_no = json_object_new_object();
13467 json_object_string_add(
13468 json_no, "warning",
13469 "No such neighbor or address family");
13470 vty_out(vty, "%s\n",
13471 json_object_to_json_string(json_no));
13472 json_object_free(json_no);
13473 } else
13474 vty_out(vty, "%% No such neighbor or address family\n");
13475 return CMD_WARNING;
13476 }
47fc97cc 13477
7daf25a3
TA
13478 /* labeled-unicast routes live in the unicast table */
13479 if (safi == SAFI_LABELED_UNICAST)
13480 safi = SAFI_UNICAST;
13481
96f3485c 13482 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13483}
13484
dba3c1d3
PG
13485DEFUN (show_ip_bgp_flowspec_routes_detailed,
13486 show_ip_bgp_flowspec_routes_detailed_cmd,
13487 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13488 SHOW_STR
13489 IP_STR
13490 BGP_STR
13491 BGP_INSTANCE_HELP_STR
13492 BGP_AFI_HELP_STR
13493 "SAFI Flowspec\n"
13494 "Detailed information on flowspec entries\n"
13495 JSON_STR)
13496{
13497 afi_t afi = AFI_IP;
13498 safi_t safi = SAFI_UNICAST;
13499 struct bgp *bgp = NULL;
13500 int idx = 0;
9f049418 13501 bool uj = use_json(argc, argv);
96f3485c 13502 uint8_t show_flags = 0;
9f049418 13503
96f3485c 13504 if (uj) {
9f049418 13505 argc--;
96f3485c
MK
13506 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13507 }
dba3c1d3
PG
13508
13509 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13510 &bgp, uj);
dba3c1d3
PG
13511 if (!idx)
13512 return CMD_WARNING;
13513
96f3485c
MK
13514 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13515 show_flags);
dba3c1d3
PG
13516}
13517
718e3744 13518DEFUN (show_ip_bgp_neighbor_routes,
13519 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13520 "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 13521 SHOW_STR
13522 IP_STR
13523 BGP_STR
8386ac43 13524 BGP_INSTANCE_HELP_STR
4f280b15 13525 BGP_AFI_HELP_STR
4dd6177e 13526 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13527 "Detailed information on TCP and BGP neighbor connections\n"
13528 "Neighbor to display information about\n"
13529 "Neighbor to display information about\n"
91d37724 13530 "Neighbor on BGP configured interface\n"
2525cf39 13531 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13532 "Display the dampened routes received from neighbor\n"
13533 "Display routes learned from neighbor\n"
9973d184 13534 JSON_STR)
718e3744 13535{
d62a17ae 13536 char *peerstr = NULL;
13537 struct bgp *bgp = NULL;
13538 afi_t afi = AFI_IP6;
13539 safi_t safi = SAFI_UNICAST;
13540 struct peer *peer;
13541 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13542 int idx = 0;
9f049418
DS
13543 bool uj = use_json(argc, argv);
13544
13545 if (uj)
13546 argc--;
bb46e94f 13547
d62a17ae 13548 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13549 &bgp, uj);
d62a17ae 13550 if (!idx)
13551 return CMD_WARNING;
c493f2d8 13552
d62a17ae 13553 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13554 argv_find(argv, argc, "neighbors", &idx);
13555 peerstr = argv[++idx]->arg;
8c3deaae 13556
d62a17ae 13557 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13558 if (!peer)
d62a17ae 13559 return CMD_WARNING;
bb46e94f 13560
d62a17ae 13561 if (argv_find(argv, argc, "flap-statistics", &idx))
13562 sh_type = bgp_show_type_flap_neighbor;
13563 else if (argv_find(argv, argc, "dampened-routes", &idx))
13564 sh_type = bgp_show_type_damp_neighbor;
13565 else if (argv_find(argv, argc, "routes", &idx))
13566 sh_type = bgp_show_type_neighbor;
2525cf39 13567
d62a17ae 13568 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13569}
6b0655a2 13570
734b349e 13571struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13572
d62a17ae 13573struct bgp_distance {
13574 /* Distance value for the IP source prefix. */
d7c0a89a 13575 uint8_t distance;
718e3744 13576
d62a17ae 13577 /* Name of the access-list to be matched. */
13578 char *access_list;
718e3744 13579};
13580
4f280b15
LB
13581DEFUN (show_bgp_afi_vpn_rd_route,
13582 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13583 "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
13584 SHOW_STR
13585 BGP_STR
13586 BGP_AFI_HELP_STR
13587 "Address Family modifier\n"
13588 "Display information for a route distinguisher\n"
13589 "Route Distinguisher\n"
7395a2c9
DS
13590 "Network in the BGP routing table to display\n"
13591 "Network in the BGP routing table to display\n"
13592 JSON_STR)
4f280b15 13593{
d62a17ae 13594 int ret;
13595 struct prefix_rd prd;
13596 afi_t afi = AFI_MAX;
13597 int idx = 0;
4f280b15 13598
ff6566f3
DS
13599 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13600 vty_out(vty, "%% Malformed Address Family\n");
13601 return CMD_WARNING;
13602 }
13603
d62a17ae 13604 ret = str2prefix_rd(argv[5]->arg, &prd);
13605 if (!ret) {
13606 vty_out(vty, "%% Malformed Route Distinguisher\n");
13607 return CMD_WARNING;
13608 }
ff6566f3 13609
d62a17ae 13610 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13611 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13612}
13613
d62a17ae 13614static struct bgp_distance *bgp_distance_new(void)
718e3744 13615{
d62a17ae 13616 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13617}
13618
d62a17ae 13619static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13620{
d62a17ae 13621 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13622}
13623
37a87b8f
CS
13624int bgp_distance_set(uint8_t distance, const char *ip_str,
13625 const char *access_list_str, afi_t afi, safi_t safi,
13626 char *errmsg, size_t errmsg_len)
718e3744 13627{
d62a17ae 13628 int ret;
d62a17ae 13629 struct prefix p;
9bcb3eef 13630 struct bgp_dest *dest;
d62a17ae 13631 struct bgp_distance *bdistance;
718e3744 13632
d62a17ae 13633 ret = str2prefix(ip_str, &p);
13634 if (ret == 0) {
37a87b8f 13635 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13636 return CMD_WARNING_CONFIG_FAILED;
13637 }
718e3744 13638
d62a17ae 13639 /* Get BGP distance node. */
9bcb3eef
DS
13640 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13641 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13642 if (bdistance)
9bcb3eef 13643 bgp_dest_unlock_node(dest);
ca2e160d 13644 else {
d62a17ae 13645 bdistance = bgp_distance_new();
9bcb3eef 13646 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13647 }
718e3744 13648
d62a17ae 13649 /* Set distance value. */
13650 bdistance->distance = distance;
718e3744 13651
d62a17ae 13652 /* Reset access-list configuration. */
e1b36e13 13653 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13654 if (access_list_str)
13655 bdistance->access_list =
13656 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13657
d62a17ae 13658 return CMD_SUCCESS;
718e3744 13659}
13660
37a87b8f
CS
13661int bgp_distance_unset(uint8_t distance, const char *ip_str,
13662 const char *access_list_str, afi_t afi, safi_t safi,
13663 char *errmsg, size_t errmsg_len)
718e3744 13664{
d62a17ae 13665 int ret;
d62a17ae 13666 struct prefix p;
9bcb3eef 13667 struct bgp_dest *dest;
d62a17ae 13668 struct bgp_distance *bdistance;
718e3744 13669
d62a17ae 13670 ret = str2prefix(ip_str, &p);
13671 if (ret == 0) {
37a87b8f 13672 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13673 return CMD_WARNING_CONFIG_FAILED;
13674 }
718e3744 13675
9bcb3eef
DS
13676 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13677 if (!dest) {
37a87b8f 13678 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13679 return CMD_WARNING_CONFIG_FAILED;
13680 }
718e3744 13681
9bcb3eef 13682 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13683
d62a17ae 13684 if (bdistance->distance != distance) {
37a87b8f
CS
13685 snprintf(errmsg, errmsg_len,
13686 "Distance does not match configured\n");
d62a17ae 13687 return CMD_WARNING_CONFIG_FAILED;
13688 }
718e3744 13689
0a22ddfb 13690 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13691 bgp_distance_free(bdistance);
718e3744 13692
9bcb3eef
DS
13693 bgp_dest_set_bgp_path_info(dest, NULL);
13694 bgp_dest_unlock_node(dest);
13695 bgp_dest_unlock_node(dest);
718e3744 13696
d62a17ae 13697 return CMD_SUCCESS;
718e3744 13698}
13699
718e3744 13700/* Apply BGP information to distance method. */
b8685f9b 13701uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13702 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13703{
9bcb3eef 13704 struct bgp_dest *dest;
801bb996 13705 struct prefix q = {0};
d62a17ae 13706 struct peer *peer;
13707 struct bgp_distance *bdistance;
13708 struct access_list *alist;
13709 struct bgp_static *bgp_static;
13710
13711 if (!bgp)
13712 return 0;
13713
40381db7 13714 peer = pinfo->peer;
d62a17ae 13715
7b7d48e5
DS
13716 if (pinfo->attr->distance)
13717 return pinfo->attr->distance;
13718
801bb996
CS
13719 /* Check source address.
13720 * Note: for aggregate route, peer can have unspec af type.
13721 */
13722 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13723 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13724 return 0;
13725
9bcb3eef
DS
13726 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13727 if (dest) {
13728 bdistance = bgp_dest_get_bgp_distance_info(dest);
13729 bgp_dest_unlock_node(dest);
d62a17ae 13730
13731 if (bdistance->access_list) {
13732 alist = access_list_lookup(afi, bdistance->access_list);
13733 if (alist
13734 && access_list_apply(alist, p) == FILTER_PERMIT)
13735 return bdistance->distance;
13736 } else
13737 return bdistance->distance;
718e3744 13738 }
718e3744 13739
d62a17ae 13740 /* Backdoor check. */
9bcb3eef
DS
13741 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13742 if (dest) {
13743 bgp_static = bgp_dest_get_bgp_static_info(dest);
13744 bgp_dest_unlock_node(dest);
718e3744 13745
d62a17ae 13746 if (bgp_static->backdoor) {
13747 if (bgp->distance_local[afi][safi])
13748 return bgp->distance_local[afi][safi];
13749 else
13750 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13751 }
718e3744 13752 }
718e3744 13753
d62a17ae 13754 if (peer->sort == BGP_PEER_EBGP) {
13755 if (bgp->distance_ebgp[afi][safi])
13756 return bgp->distance_ebgp[afi][safi];
13757 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 13758 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 13759 if (bgp->distance_ibgp[afi][safi])
13760 return bgp->distance_ibgp[afi][safi];
13761 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
13762 } else {
13763 if (bgp->distance_local[afi][safi])
13764 return bgp->distance_local[afi][safi];
13765 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 13766 }
718e3744 13767}
13768
a612fb77
DA
13769/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13770 * we should tell ZEBRA update the routes for a specific
13771 * AFI/SAFI to reflect changes in RIB.
13772 */
37a87b8f
CS
13773void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13774 safi_t update_safi)
a612fb77
DA
13775{
13776 afi_t afi;
13777 safi_t safi;
13778
13779 FOREACH_AFI_SAFI (afi, safi) {
13780 if (!bgp_fibupd_safi(safi))
13781 continue;
13782
8b54bc30
DA
13783 if (afi != update_afi && safi != update_safi)
13784 continue;
13785
13786 if (BGP_DEBUG(zebra, ZEBRA))
13787 zlog_debug(
13788 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13789 __func__, afi, safi);
13790 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13791 }
13792}
13793
37a87b8f
CS
13794DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13795 "distance bgp (1-255) (1-255) (1-255)",
13796 "Define an administrative distance\n"
13797 "BGP distance\n"
13798 "Distance for routes external to the AS\n"
13799 "Distance for routes internal to the AS\n"
13800 "Distance for local routes\n")
718e3744 13801{
d62a17ae 13802 int idx_number = 2;
13803 int idx_number_2 = 3;
13804 int idx_number_3 = 4;
13805 afi_t afi;
13806 safi_t safi;
37a87b8f 13807 char xpath[XPATH_MAXLEN];
718e3744 13808
d62a17ae 13809 afi = bgp_node_afi(vty);
13810 safi = bgp_node_safi(vty);
718e3744 13811
37a87b8f
CS
13812 snprintf(
13813 xpath, sizeof(xpath),
13814 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13815 yang_afi_safi_value2identity(afi, safi),
13816 bgp_afi_safi_get_container_str(afi, safi));
13817 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13818 snprintf(
13819 xpath, sizeof(xpath),
13820 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13821 yang_afi_safi_value2identity(afi, safi),
13822 bgp_afi_safi_get_container_str(afi, safi));
13823 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13824 argv[idx_number_2]->arg);
13825 snprintf(
13826 xpath, sizeof(xpath),
13827 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13828 yang_afi_safi_value2identity(afi, safi),
13829 bgp_afi_safi_get_container_str(afi, safi));
13830
13831 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13832 argv[idx_number_3]->arg);
13833
13834 return nb_cli_apply_changes(vty, NULL);
13835}
13836
13837DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13838 "no distance bgp [(1-255) (1-255) (1-255)]",
13839 NO_STR
13840 "Define an administrative distance\n"
13841 "BGP distance\n"
13842 "Distance for routes external to the AS\n"
13843 "Distance for routes internal to the AS\n"
13844 "Distance for local routes\n")
13845{
13846 afi_t afi;
13847 safi_t safi;
13848 char xpath[XPATH_MAXLEN];
13849
13850 afi = bgp_node_afi(vty);
13851 safi = bgp_node_safi(vty);
13852
13853 snprintf(
13854 xpath, sizeof(xpath),
13855 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13856 yang_afi_safi_value2identity(afi, safi),
13857 bgp_afi_safi_get_container_str(afi, safi));
13858 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13859 snprintf(
13860 xpath, sizeof(xpath),
13861 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13862 yang_afi_safi_value2identity(afi, safi),
13863 bgp_afi_safi_get_container_str(afi, safi));
13864 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13865 snprintf(
13866 xpath, sizeof(xpath),
13867 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13868 yang_afi_safi_value2identity(afi, safi),
13869 bgp_afi_safi_get_container_str(afi, safi));
13870
13871 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13872
13873 return nb_cli_apply_changes(vty, NULL);
718e3744 13874}
13875
37a87b8f
CS
13876void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13877 struct lyd_node *dnode,
13878 bool show_defaults)
718e3744 13879{
37a87b8f
CS
13880 uint8_t distance_ebgp, distance_ibgp, distance_local;
13881
13882 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13883 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13884 distance_local = yang_dnode_get_uint8(dnode, "./local");
13885
13886 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13887 distance_local);
13888}
13889
8cc7152a
CS
13890DEFPY_YANG(bgp_distance_source,
13891 bgp_distance_source_cmd,
13892 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
13893 NO_STR
13894 "Define an administrative distance\n"
8cc7152a 13895 "Distance value\n"
e12affc1
SW
13896 "IPv4 source prefix\n"
13897 "IPv6 source prefix\n"
37a87b8f 13898 "Access list name\n")
718e3744 13899{
37a87b8f
CS
13900 afi_t afi;
13901 safi_t safi;
13902 char xpath[XPATH_MAXLEN];
13903
13904 afi = bgp_node_afi(vty);
13905 safi = bgp_node_safi(vty);
13906
8cc7152a
CS
13907 if (!no) {
13908 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
13909 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
13910 distance_str);
13911 if (acl)
13912 nb_cli_enqueue_change(vty,
13913 "./access-list-policy-export",
13914 NB_OP_CREATE, acl);
13915 else
13916 nb_cli_enqueue_change(vty,
13917 "./access-list-policy-export",
13918 NB_OP_DESTROY, NULL);
13919 } else {
13920 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
13921 }
37a87b8f
CS
13922
13923 snprintf(
13924 xpath, sizeof(xpath),
13925 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
13926 yang_afi_safi_value2identity(afi, safi),
8cc7152a 13927 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
13928
13929 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
13930}
13931
37a87b8f
CS
13932void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
13933 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
13934{
13935 vty_out(vty, " distance %d %s %s\n",
13936 yang_dnode_get_uint8(dnode, "./distance"),
13937 yang_dnode_get_string(dnode, "./prefix"),
13938 (yang_dnode_exists(dnode, "./access-list-policy-export"))
13939 ? yang_dnode_get_string(dnode,
13940 "./access-list-policy-export")
13941 : "");
13942}
13943
7c98d487
DA
13944DEFPY_YANG(
13945 bgp_dampening, bgp_dampening_cmd,
13946 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
13947 NO_STR
13948 "BGP Specific commands\n"
13949 "Enable route-flap dampening\n"
13950 "Half-life time for the penalty\n"
13951 "Value to start reusing a route\n"
13952 "Value to start suppressing a route\n"
13953 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
13954{
13955 afi_t afi;
13956 safi_t safi;
13957 char xpath[XPATH_MAXLEN];
718e3744 13958
37a87b8f
CS
13959 afi = bgp_node_afi(vty);
13960 safi = bgp_node_safi(vty);
13961
d9ce5113
CS
13962 if (!no) {
13963 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
13964 if (argc == 6) {
13965 nb_cli_enqueue_change(vty, "./reach-decay",
13966 NB_OP_MODIFY, halflife_str);
13967 nb_cli_enqueue_change(vty, "./reuse-above",
13968 NB_OP_MODIFY, reuse_str);
13969 nb_cli_enqueue_change(vty, "./suppress-above",
13970 NB_OP_MODIFY, suppress_str);
13971 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 13972 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
13973 } if (argc == 3) {
13974 nb_cli_enqueue_change(vty, "./reach-decay",
13975 NB_OP_MODIFY, halflife_str);
13976 }
13977 } else {
13978 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
13979 }
7ebe9748 13980
37a87b8f
CS
13981 snprintf(
13982 xpath, sizeof(xpath),
13983 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
13984 yang_afi_safi_value2identity(afi, safi),
13985 bgp_afi_safi_get_container_str(afi, safi));
13986
13987 return nb_cli_apply_changes(vty, xpath);
718e3744 13988}
13989
37a87b8f
CS
13990void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
13991 struct lyd_node *dnode,
13992 bool show_defaults)
718e3744 13993{
37a87b8f
CS
13994 if (!yang_dnode_get_bool(dnode, "./enable"))
13995 return;
13996
13997 int half = DEFAULT_HALF_LIFE * 60;
13998 int reuse = DEFAULT_REUSE;
13999 int suppress = DEFAULT_SUPPRESS;
14000 int max;
14001
14002 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14003 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14004 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14005 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14006
14007 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14008 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14009 vty_out(vty, " bgp dampening\n");
14010 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14011 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14012 vty_out(vty, " bgp dampening %u\n", half);
14013 else
14014 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14015 suppress, max);
718e3744 14016}
14017
718e3744 14018/* Display specified route of BGP table. */
d62a17ae 14019static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14020 const char *ip_str, afi_t afi, safi_t safi,
14021 struct prefix_rd *prd, int prefix_check)
14022{
14023 int ret;
14024 struct prefix match;
9bcb3eef
DS
14025 struct bgp_dest *dest;
14026 struct bgp_dest *rm;
40381db7
DS
14027 struct bgp_path_info *pi;
14028 struct bgp_path_info *pi_temp;
d62a17ae 14029 struct bgp *bgp;
14030 struct bgp_table *table;
14031
14032 /* BGP structure lookup. */
14033 if (view_name) {
14034 bgp = bgp_lookup_by_name(view_name);
14035 if (bgp == NULL) {
14036 vty_out(vty, "%% Can't find BGP instance %s\n",
14037 view_name);
14038 return CMD_WARNING;
14039 }
14040 } else {
14041 bgp = bgp_get_default();
14042 if (bgp == NULL) {
14043 vty_out(vty, "%% No BGP process is configured\n");
14044 return CMD_WARNING;
14045 }
718e3744 14046 }
718e3744 14047
d62a17ae 14048 /* Check IP address argument. */
14049 ret = str2prefix(ip_str, &match);
14050 if (!ret) {
14051 vty_out(vty, "%% address is malformed\n");
14052 return CMD_WARNING;
14053 }
718e3744 14054
d62a17ae 14055 match.family = afi2family(afi);
14056
14057 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14058 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14059 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14060 dest = bgp_route_next(dest)) {
14061 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14062
9bcb3eef 14063 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14064 continue;
9bcb3eef 14065 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14066 if (!table)
ea47320b
DL
14067 continue;
14068 if ((rm = bgp_node_match(table, &match)) == NULL)
14069 continue;
d62a17ae 14070
9bcb3eef 14071 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14072
ea47320b 14073 if (!prefix_check
b54892e0 14074 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14075 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14076 while (pi) {
14077 if (pi->extra && pi->extra->damp_info) {
14078 pi_temp = pi->next;
ea47320b 14079 bgp_damp_info_free(
40381db7 14080 pi->extra->damp_info,
a935f597 14081 1, afi, safi);
40381db7 14082 pi = pi_temp;
ea47320b 14083 } else
40381db7 14084 pi = pi->next;
d62a17ae 14085 }
ea47320b
DL
14086 }
14087
9bcb3eef 14088 bgp_dest_unlock_node(rm);
d62a17ae 14089 }
14090 } else {
9bcb3eef 14091 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14092 != NULL) {
9bcb3eef 14093 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14094
d62a17ae 14095 if (!prefix_check
9bcb3eef
DS
14096 || dest_p->prefixlen == match.prefixlen) {
14097 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14098 while (pi) {
14099 if (pi->extra && pi->extra->damp_info) {
14100 pi_temp = pi->next;
d62a17ae 14101 bgp_damp_info_free(
40381db7 14102 pi->extra->damp_info,
a935f597 14103 1, afi, safi);
40381db7 14104 pi = pi_temp;
d62a17ae 14105 } else
40381db7 14106 pi = pi->next;
d62a17ae 14107 }
14108 }
14109
9bcb3eef 14110 bgp_dest_unlock_node(dest);
d62a17ae 14111 }
14112 }
718e3744 14113
d62a17ae 14114 return CMD_SUCCESS;
718e3744 14115}
14116
14117DEFUN (clear_ip_bgp_dampening,
14118 clear_ip_bgp_dampening_cmd,
14119 "clear ip bgp dampening",
14120 CLEAR_STR
14121 IP_STR
14122 BGP_STR
14123 "Clear route flap dampening information\n")
14124{
a935f597 14125 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14126 return CMD_SUCCESS;
718e3744 14127}
14128
14129DEFUN (clear_ip_bgp_dampening_prefix,
14130 clear_ip_bgp_dampening_prefix_cmd,
14131 "clear ip bgp dampening A.B.C.D/M",
14132 CLEAR_STR
14133 IP_STR
14134 BGP_STR
14135 "Clear route flap dampening information\n"
0c7b1b01 14136 "IPv4 prefix\n")
718e3744 14137{
d62a17ae 14138 int idx_ipv4_prefixlen = 4;
14139 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14140 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14141}
14142
14143DEFUN (clear_ip_bgp_dampening_address,
14144 clear_ip_bgp_dampening_address_cmd,
14145 "clear ip bgp dampening A.B.C.D",
14146 CLEAR_STR
14147 IP_STR
14148 BGP_STR
14149 "Clear route flap dampening information\n"
14150 "Network to clear damping information\n")
14151{
d62a17ae 14152 int idx_ipv4 = 4;
14153 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14154 SAFI_UNICAST, NULL, 0);
718e3744 14155}
14156
14157DEFUN (clear_ip_bgp_dampening_address_mask,
14158 clear_ip_bgp_dampening_address_mask_cmd,
14159 "clear ip bgp dampening A.B.C.D A.B.C.D",
14160 CLEAR_STR
14161 IP_STR
14162 BGP_STR
14163 "Clear route flap dampening information\n"
14164 "Network to clear damping information\n"
14165 "Network mask\n")
14166{
d62a17ae 14167 int idx_ipv4 = 4;
14168 int idx_ipv4_2 = 5;
14169 int ret;
14170 char prefix_str[BUFSIZ];
718e3744 14171
d62a17ae 14172 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14173 prefix_str);
14174 if (!ret) {
14175 vty_out(vty, "%% Inconsistent address and mask\n");
14176 return CMD_WARNING;
14177 }
718e3744 14178
d62a17ae 14179 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14180 NULL, 0);
718e3744 14181}
6b0655a2 14182
e3b78da8 14183static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14184{
14185 struct vty *vty = arg;
e3b78da8 14186 struct peer *peer = bucket->data;
825d9834
DS
14187 char buf[SU_ADDRSTRLEN];
14188
14189 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14190 sockunion2str(&peer->su, buf, sizeof(buf)));
14191}
14192
2a0e69ae
DS
14193DEFUN (show_bgp_listeners,
14194 show_bgp_listeners_cmd,
14195 "show bgp listeners",
14196 SHOW_STR
14197 BGP_STR
14198 "Display Listen Sockets and who created them\n")
14199{
14200 bgp_dump_listener_info(vty);
14201
14202 return CMD_SUCCESS;
14203}
14204
825d9834
DS
14205DEFUN (show_bgp_peerhash,
14206 show_bgp_peerhash_cmd,
14207 "show bgp peerhash",
14208 SHOW_STR
14209 BGP_STR
14210 "Display information about the BGP peerhash\n")
14211{
14212 struct list *instances = bm->bgp;
14213 struct listnode *node;
14214 struct bgp *bgp;
14215
14216 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14217 vty_out(vty, "BGP: %s\n", bgp->name);
14218 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14219 vty);
14220 }
14221
14222 return CMD_SUCCESS;
14223}
14224
587ff0fd 14225/* also used for encap safi */
2b791107
DL
14226static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14227 afi_t afi, safi_t safi)
d62a17ae 14228{
9bcb3eef
DS
14229 struct bgp_dest *pdest;
14230 struct bgp_dest *dest;
d62a17ae 14231 struct bgp_table *table;
b54892e0
DS
14232 const struct prefix *p;
14233 const struct prefix_rd *prd;
d62a17ae 14234 struct bgp_static *bgp_static;
14235 mpls_label_t label;
d62a17ae 14236 char rdbuf[RD_ADDRSTRLEN];
14237
14238 /* Network configuration. */
9bcb3eef
DS
14239 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14240 pdest = bgp_route_next(pdest)) {
14241 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14242 if (!table)
ea47320b 14243 continue;
d62a17ae 14244
9bcb3eef
DS
14245 for (dest = bgp_table_top(table); dest;
14246 dest = bgp_route_next(dest)) {
14247 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14248 if (bgp_static == NULL)
ea47320b 14249 continue;
d62a17ae 14250
9bcb3eef
DS
14251 p = bgp_dest_get_prefix(dest);
14252 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14253 pdest);
d62a17ae 14254
ea47320b 14255 /* "network" configuration display. */
06b9f471 14256 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14257 label = decode_label(&bgp_static->label);
14258
8228a9a7 14259 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14260 if (safi == SAFI_MPLS_VPN)
14261 vty_out(vty, " label %u", label);
14262
14263 if (bgp_static->rmap.name)
14264 vty_out(vty, " route-map %s",
14265 bgp_static->rmap.name);
e2a86ad9
DS
14266
14267 if (bgp_static->backdoor)
14268 vty_out(vty, " backdoor");
14269
ea47320b
DL
14270 vty_out(vty, "\n");
14271 }
14272 }
d62a17ae 14273}
14274
2b791107
DL
14275static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14276 afi_t afi, safi_t safi)
d62a17ae 14277{
9bcb3eef
DS
14278 struct bgp_dest *pdest;
14279 struct bgp_dest *dest;
d62a17ae 14280 struct bgp_table *table;
b54892e0
DS
14281 const struct prefix *p;
14282 const struct prefix_rd *prd;
d62a17ae 14283 struct bgp_static *bgp_static;
ff44f570 14284 char buf[PREFIX_STRLEN * 2];
d62a17ae 14285 char buf2[SU_ADDRSTRLEN];
14286 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14287 char esi_buf[ESI_BYTES];
d62a17ae 14288
14289 /* Network configuration. */
9bcb3eef
DS
14290 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14291 pdest = bgp_route_next(pdest)) {
14292 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14293 if (!table)
ea47320b 14294 continue;
d62a17ae 14295
9bcb3eef
DS
14296 for (dest = bgp_table_top(table); dest;
14297 dest = bgp_route_next(dest)) {
14298 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14299 if (bgp_static == NULL)
ea47320b 14300 continue;
d62a17ae 14301
ea47320b 14302 char *macrouter = NULL;
d62a17ae 14303
ea47320b
DL
14304 if (bgp_static->router_mac)
14305 macrouter = prefix_mac2str(
14306 bgp_static->router_mac, NULL, 0);
14307 if (bgp_static->eth_s_id)
0a50c248
AK
14308 esi_to_str(bgp_static->eth_s_id,
14309 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14310 p = bgp_dest_get_prefix(dest);
14311 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14312
ea47320b 14313 /* "network" configuration display. */
06b9f471 14314 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14315 if (p->u.prefix_evpn.route_type == 5) {
14316 char local_buf[PREFIX_STRLEN];
3714a385 14317 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14318 struct prefix_evpn *)p)
14319 ? AF_INET
14320 : AF_INET6;
3714a385 14321 inet_ntop(family,
14322 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14323 local_buf, PREFIX_STRLEN);
772270f3
QY
14324 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14325 p->u.prefix_evpn.prefix_addr
14326 .ip_prefix_length);
197cb530
PG
14327 } else {
14328 prefix2str(p, buf, sizeof(buf));
14329 }
ea47320b 14330
a4d82a8a
PZ
14331 if (bgp_static->gatewayIp.family == AF_INET
14332 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14333 inet_ntop(bgp_static->gatewayIp.family,
14334 &bgp_static->gatewayIp.u.prefix, buf2,
14335 sizeof(buf2));
ea47320b 14336 vty_out(vty,
7bcc8dac 14337 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14338 buf, rdbuf,
14339 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14340 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14341 macrouter);
14342
0a22ddfb 14343 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14344 }
14345 }
3da6fcd5
PG
14346}
14347
718e3744 14348/* Configuration of static route announcement and aggregate
14349 information. */
2b791107
DL
14350void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14351 safi_t safi)
d62a17ae 14352{
9bcb3eef 14353 struct bgp_dest *dest;
b54892e0 14354 const struct prefix *p;
d62a17ae 14355 struct bgp_static *bgp_static;
14356 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14357
2b791107
DL
14358 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14359 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14360 return;
14361 }
d62a17ae 14362
2b791107
DL
14363 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14364 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14365 return;
14366 }
d62a17ae 14367
14368 /* Network configuration. */
9bcb3eef
DS
14369 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14370 dest = bgp_route_next(dest)) {
14371 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14372 if (bgp_static == NULL)
ea47320b 14373 continue;
d62a17ae 14374
9bcb3eef 14375 p = bgp_dest_get_prefix(dest);
d62a17ae 14376
8228a9a7 14377 vty_out(vty, " network %pFX", p);
d62a17ae 14378
ea47320b
DL
14379 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14380 vty_out(vty, " label-index %u",
14381 bgp_static->label_index);
d62a17ae 14382
ea47320b
DL
14383 if (bgp_static->rmap.name)
14384 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14385
14386 if (bgp_static->backdoor)
14387 vty_out(vty, " backdoor");
718e3744 14388
ea47320b
DL
14389 vty_out(vty, "\n");
14390 }
14391
d62a17ae 14392 /* Aggregate-address configuration. */
9bcb3eef
DS
14393 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14394 dest = bgp_route_next(dest)) {
14395 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14396 if (bgp_aggregate == NULL)
ea47320b 14397 continue;
d62a17ae 14398
9bcb3eef 14399 p = bgp_dest_get_prefix(dest);
d62a17ae 14400
8228a9a7 14401 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14402
ea47320b
DL
14403 if (bgp_aggregate->as_set)
14404 vty_out(vty, " as-set");
d62a17ae 14405
ea47320b
DL
14406 if (bgp_aggregate->summary_only)
14407 vty_out(vty, " summary-only");
718e3744 14408
20894f50
DA
14409 if (bgp_aggregate->rmap.name)
14410 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14411
229757f1
DA
14412 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14413 vty_out(vty, " origin %s",
14414 bgp_origin2str(bgp_aggregate->origin));
14415
6aabb15d
RZ
14416 if (bgp_aggregate->match_med)
14417 vty_out(vty, " matching-MED-only");
14418
365ab2e7
RZ
14419 if (bgp_aggregate->suppress_map_name)
14420 vty_out(vty, " suppress-map %s",
14421 bgp_aggregate->suppress_map_name);
14422
ea47320b
DL
14423 vty_out(vty, "\n");
14424 }
d62a17ae 14425}
734b349e 14426
2b791107 14427void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14428 safi_t safi)
d62a17ae 14429{
9bcb3eef 14430 struct bgp_dest *dest;
d62a17ae 14431 struct bgp_distance *bdistance;
14432
14433 /* Distance configuration. */
14434 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14435 && bgp->distance_local[afi][safi]
14436 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14437 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14438 || bgp->distance_local[afi][safi]
14439 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14440 vty_out(vty, " distance bgp %d %d %d\n",
14441 bgp->distance_ebgp[afi][safi],
14442 bgp->distance_ibgp[afi][safi],
14443 bgp->distance_local[afi][safi]);
14444 }
734b349e 14445
9bcb3eef
DS
14446 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14447 dest = bgp_route_next(dest)) {
14448 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14449 if (bdistance != NULL)
56ca3b5b 14450 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14451 bdistance->distance, dest,
d62a17ae 14452 bdistance->access_list ? bdistance->access_list
14453 : "");
ca2e160d 14454 }
718e3744 14455}
14456
14457/* Allocate routing table structure and install commands. */
d62a17ae 14458void bgp_route_init(void)
14459{
14460 afi_t afi;
14461 safi_t safi;
14462
14463 /* Init BGP distance table. */
05c7a1cc 14464 FOREACH_AFI_SAFI (afi, safi)
960035b2 14465 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14466
14467 /* IPv4 BGP commands. */
14468 install_element(BGP_NODE, &bgp_table_map_cmd);
14469 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14470 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14471
554b3b10 14472 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14473
14474 /* IPv4 unicast configuration. */
14475 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14476 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14477 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14478
554b3b10 14479 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14480
14481 /* IPv4 multicast configuration. */
14482 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14483 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14484 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14485 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14486
14487 /* IPv4 labeled-unicast configuration. */
fb985e0c 14488 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14489 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14490
d62a17ae 14491 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14492 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14493 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14494 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14495 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14496 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14497 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14498 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14499
14500 install_element(VIEW_NODE,
14501 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14502 install_element(VIEW_NODE,
14503 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14504 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14505 install_element(VIEW_NODE,
14506 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14507#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14508 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14509#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14510 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14511 install_element(VIEW_NODE,
44c69747 14512 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14513
d62a17ae 14514 /* BGP dampening clear commands */
14515 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14516 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14517
d62a17ae 14518 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14519 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14520
14521 /* prefix count */
14522 install_element(ENABLE_NODE,
14523 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14524#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14525 install_element(ENABLE_NODE,
14526 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14527#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14528
d62a17ae 14529 /* New config IPv6 BGP commands. */
14530 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14531 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14532 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14533
554b3b10 14534 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14535
14536 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14537
fb985e0c
DA
14538 /* IPv6 labeled unicast address family. */
14539 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14540 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14541
d62a17ae 14542 install_element(BGP_NODE, &bgp_distance_cmd);
14543 install_element(BGP_NODE, &no_bgp_distance_cmd);
14544 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14545 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14546 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14547 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14548 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14549 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14550 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14551 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14552 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14553 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14554 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14555 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14556 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14557
ef5f4b23 14558 /* BGP dampening */
d9ce5113
CS
14559 install_element(BGP_NODE, &bgp_dampening_cmd);
14560 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14561 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14562 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14563 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14564 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14565 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14566
14567 /* Large Communities */
14568 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14569 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14570
14571 /* show bgp ipv4 flowspec detailed */
14572 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14573
2a0e69ae 14574 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14575 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14576}
14577
14578void bgp_route_finish(void)
14579{
14580 afi_t afi;
14581 safi_t safi;
14582
05c7a1cc
QY
14583 FOREACH_AFI_SAFI (afi, safi) {
14584 bgp_table_unlock(bgp_distance_table[afi][safi]);
14585 bgp_distance_table[afi][safi] = NULL;
14586 }
228da428 14587}