]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
doc: Add rfc7313 (Enhanced Route Refresh Capability for BGP-4) to the list
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
6401252f 73#include "bgpd/bgp_trace.h"
718e3744 74
49e5a4a0 75#ifdef ENABLE_BGP_VNC
f8b6f499
LB
76#include "bgpd/rfapi/rfapi_backend.h"
77#include "bgpd/rfapi/vnc_import_bgp.h"
78#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 79#endif
aee875b5
PG
80#include "bgpd/bgp_encap_types.h"
81#include "bgpd/bgp_encap_tlv.h"
684a7227 82#include "bgpd/bgp_evpn.h"
0a50c248 83#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 84#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 85#include "bgpd/bgp_flowspec.h"
98a9dbc7 86#include "bgpd/bgp_flowspec_util.h"
45918cfb 87#include "bgpd/bgp_pbr.h"
37a87b8f
CS
88#include "northbound.h"
89#include "northbound_cli.h"
90#include "bgpd/bgp_nb.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
718e3744 96/* Extern from bgp_dump.c */
dde72586
SH
97extern const char *bgp_origin_str[];
98extern const char *bgp_origin_long_str[];
3742de8d 99
b7d08f5a 100/* PMSI strings. */
101#define PMSI_TNLTYPE_STR_NO_INFO "No info"
102#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
103static const struct message bgp_pmsi_tnltype_str[] = {
104 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
105 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
106 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
107 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
108 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
109 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
110 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
111 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 112 {0}
113};
b7d08f5a 114
9df8b37c
PZ
115#define VRFID_NONE_STR "-"
116
4a11bf2c 117DEFINE_HOOK(bgp_process,
9bcb3eef
DS
118 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
119 struct peer *peer, bool withdraw),
120 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c 121
4056a5f6
RZ
122/** Test if path is suppressed. */
123static bool bgp_path_suppressed(struct bgp_path_info *pi)
124{
125 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
126 return false;
127
128 return listcount(pi->extra->aggr_suppressors) > 0;
129}
4a11bf2c 130
9bcb3eef 131struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 132 safi_t safi, const struct prefix *p,
d62a17ae 133 struct prefix_rd *prd)
134{
9bcb3eef
DS
135 struct bgp_dest *dest;
136 struct bgp_dest *pdest = NULL;
d62a17ae 137
138 assert(table);
d62a17ae 139
140 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
141 || (safi == SAFI_EVPN)) {
9bcb3eef 142 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 143
9bcb3eef
DS
144 if (!bgp_dest_has_bgp_path_info_data(pdest))
145 bgp_dest_set_bgp_table_info(
146 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 147 else
9bcb3eef
DS
148 bgp_dest_unlock_node(pdest);
149 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 150 }
718e3744 151
9bcb3eef 152 dest = bgp_node_get(table, p);
718e3744 153
d62a17ae 154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN))
9bcb3eef 156 dest->pdest = pdest;
718e3744 157
9bcb3eef 158 return dest;
718e3744 159}
6b0655a2 160
9bcb3eef 161struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 162 safi_t safi, const struct prefix *p,
d62a17ae 163 struct prefix_rd *prd)
128ea8ab 164{
9bcb3eef
DS
165 struct bgp_dest *dest;
166 struct bgp_dest *pdest = NULL;
128ea8ab 167
d62a17ae 168 if (!table)
169 return NULL;
128ea8ab 170
d62a17ae 171 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
172 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
173 pdest = bgp_node_lookup(table, (struct prefix *)prd);
174 if (!pdest)
d62a17ae 175 return NULL;
128ea8ab 176
9bcb3eef
DS
177 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
178 bgp_dest_unlock_node(pdest);
d62a17ae 179 return NULL;
180 }
128ea8ab 181
9bcb3eef 182 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 183 }
128ea8ab 184
9bcb3eef 185 dest = bgp_node_lookup(table, p);
128ea8ab 186
9bcb3eef 187 return dest;
128ea8ab 188}
189
18ee8310
DS
190/* Allocate bgp_path_info_extra */
191static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 192{
4b7e6066
DS
193 struct bgp_path_info_extra *new;
194 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
195 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
196 new->label[0] = MPLS_INVALID_LABEL;
197 new->num_labels = 0;
3e3708cb
PG
198 new->bgp_fs_pbr = NULL;
199 new->bgp_fs_iprule = NULL;
d62a17ae 200 return new;
fb982c25
PJ
201}
202
a2e219fe 203void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 204{
4b7e6066 205 struct bgp_path_info_extra *e;
d62a17ae 206
c93a3b77
DS
207 if (!extra || !*extra)
208 return;
d62a17ae 209
c93a3b77
DS
210 e = *extra;
211 if (e->damp_info)
a935f597
DA
212 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
213 e->damp_info->safi);
d62a17ae 214
c93a3b77
DS
215 e->damp_info = NULL;
216 if (e->parent) {
40381db7 217 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 218
40381db7 219 if (bpi->net) {
0e70e6c8
DL
220 /* FIXME: since multiple e may have the same e->parent
221 * and e->parent->net is holding a refcount for each
222 * of them, we need to do some fudging here.
223 *
40381db7
DS
224 * WARNING: if bpi->net->lock drops to 0, bpi may be
225 * freed as well (because bpi->net was holding the
226 * last reference to bpi) => write after free!
0e70e6c8
DL
227 */
228 unsigned refcount;
229
40381db7 230 bpi = bgp_path_info_lock(bpi);
c10e14e9 231 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 232 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 233 if (!refcount)
40381db7
DS
234 bpi->net = NULL;
235 bgp_path_info_unlock(bpi);
0e70e6c8 236 }
18ee8310 237 bgp_path_info_unlock(e->parent);
c93a3b77 238 e->parent = NULL;
d62a17ae 239 }
c93a3b77
DS
240
241 if (e->bgp_orig)
242 bgp_unlock(e->bgp_orig);
c26edcda 243
ff3bf9a4
DS
244 if (e->aggr_suppressors)
245 list_delete(&e->aggr_suppressors);
246
26c03e43
AK
247 if (e->es_info)
248 bgp_evpn_path_es_info_free(e->es_info);
249
ce3c0614
PG
250 if ((*extra)->bgp_fs_iprule)
251 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 252 if ((*extra)->bgp_fs_pbr)
6a154c88 253 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 254 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
255}
256
18ee8310
DS
257/* Get bgp_path_info extra information for the given bgp_path_info, lazy
258 * allocated if required.
fb982c25 259 */
40381db7 260struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 261{
40381db7
DS
262 if (!pi->extra)
263 pi->extra = bgp_path_info_extra_new();
264 return pi->extra;
fb982c25
PJ
265}
266
718e3744 267/* Free bgp route information. */
9b6d8fcf 268static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 269{
05864da7 270 bgp_attr_unintern(&path->attr);
fb018d25 271
9b6d8fcf
DS
272 bgp_unlink_nexthop(path);
273 bgp_path_info_extra_free(&path->extra);
274 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
275 if (path->net)
276 bgp_addpath_free_info_data(&path->tx_addpath,
277 &path->net->tx_addpath);
718e3744 278
9b6d8fcf 279 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 280
9b6d8fcf 281 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 282}
283
9b6d8fcf 284struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 285{
9b6d8fcf
DS
286 path->lock++;
287 return path;
200df115 288}
289
9b6d8fcf 290struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 291{
9b6d8fcf
DS
292 assert(path && path->lock > 0);
293 path->lock--;
d62a17ae 294
9b6d8fcf 295 if (path->lock == 0) {
200df115 296#if 0
297 zlog_debug ("%s: unlocked and freeing", __func__);
298 zlog_backtrace (LOG_DEBUG);
299#endif
9b6d8fcf 300 bgp_path_info_free(path);
d62a17ae 301 return NULL;
302 }
200df115 303
304#if 0
9b6d8fcf 305 if (path->lock == 1)
200df115 306 {
307 zlog_debug ("%s: unlocked to 1", __func__);
308 zlog_backtrace (LOG_DEBUG);
309 }
310#endif
d62a17ae 311
9b6d8fcf 312 return path;
200df115 313}
314
f009ff26 315/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 316static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 317{
318 struct peer *peer;
319 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 320 bool set_flag = false;
f009ff26 321 struct bgp *bgp = NULL;
322 struct bgp_table *table = NULL;
323 afi_t afi = 0;
324 safi_t safi = 0;
f009ff26 325
326 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
327 * then the route selection is deferred
328 */
9bcb3eef 329 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 330 return 0;
331
9bcb3eef 332 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 333 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 334 zlog_debug(
56ca3b5b
DL
335 "Route %pBD is in workqueue and being processed, not deferred.",
336 dest);
b54892e0 337
5f9c1aa2 338 return 0;
339 }
340
9bcb3eef 341 table = bgp_dest_table(dest);
f009ff26 342 if (table) {
343 bgp = table->bgp;
344 afi = table->afi;
345 safi = table->safi;
346 }
347
9bcb3eef 348 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 349 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
350 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
351 continue;
352
353 /* Route selection is deferred if there is a stale path which
354 * which indicates peer is in restart mode
355 */
36235319
QY
356 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
357 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 358 set_flag = true;
f009ff26 359 } else {
360 /* If the peer is graceful restart capable and peer is
361 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
362 */
363 peer = old_pi->peer;
36235319
QY
364 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
365 && BGP_PEER_RESTARTING_MODE(peer)
366 && (old_pi
367 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 368 set_flag = true;
f009ff26 369 }
370 }
371 if (set_flag)
372 break;
373 }
374
375 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
376 * is active
377 */
2ba1fe69 378 if (set_flag && table) {
f009ff26 379 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
380 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
381 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 382 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 383 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
384 zlog_debug("DEFER route %pBD, dest %p", dest,
385 dest);
f009ff26 386 return 0;
387 }
388 }
389 return -1;
390}
391
9bcb3eef 392void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 393{
4b7e6066 394 struct bgp_path_info *top;
718e3744 395
9bcb3eef 396 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 397
6f94b685 398 pi->next = top;
40381db7 399 pi->prev = NULL;
d62a17ae 400 if (top)
40381db7 401 top->prev = pi;
9bcb3eef 402 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 403
40381db7 404 bgp_path_info_lock(pi);
9bcb3eef 405 bgp_dest_lock_node(dest);
40381db7 406 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 407 bgp_dest_set_defer_flag(dest, false);
718e3744 408}
409
d62a17ae 410/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 411 completion callback *only* */
9bcb3eef 412void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 413{
40381db7
DS
414 if (pi->next)
415 pi->next->prev = pi->prev;
416 if (pi->prev)
417 pi->prev->next = pi->next;
d62a17ae 418 else
9bcb3eef 419 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 420
40381db7
DS
421 bgp_path_info_mpath_dequeue(pi);
422 bgp_path_info_unlock(pi);
9bcb3eef 423 bgp_dest_unlock_node(dest);
718e3744 424}
425
9bcb3eef 426void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 427{
9bcb3eef 428 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 429 /* set of previous already took care of pcount */
40381db7 430 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 431}
432
18ee8310 433/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
434 called when a route is deleted and then quickly re-added before the
435 deletion has been processed */
9bcb3eef 436void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 437{
9bcb3eef 438 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 439 /* unset of previous already took care of pcount */
40381db7 440 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
441}
442
d62a17ae 443/* Adjust pcount as required */
9bcb3eef 444static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 445{
d62a17ae 446 struct bgp_table *table;
67174041 447
9bcb3eef 448 assert(dest && bgp_dest_table(dest));
40381db7 449 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 450
9bcb3eef 451 table = bgp_dest_table(dest);
67174041 452
40381db7 453 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 454 return;
455
40381db7
DS
456 if (!BGP_PATH_COUNTABLE(pi)
457 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 458
40381db7 459 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 460
461 /* slight hack, but more robust against errors. */
40381db7
DS
462 if (pi->peer->pcount[table->afi][table->safi])
463 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 464 else
450971aa 465 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 466 "Asked to decrement 0 prefix count for peer");
40381db7
DS
467 } else if (BGP_PATH_COUNTABLE(pi)
468 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
469 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
470 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 471 }
1a392d46
PJ
472}
473
40381db7
DS
474static int bgp_label_index_differs(struct bgp_path_info *pi1,
475 struct bgp_path_info *pi2)
28d58fd7 476{
40381db7 477 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 478}
1a392d46 479
18ee8310 480/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
481 * This is here primarily to keep prefix-count in check.
482 */
9bcb3eef 483void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 484 uint32_t flag)
1a392d46 485{
40381db7 486 SET_FLAG(pi->flags, flag);
d62a17ae 487
488 /* early bath if we know it's not a flag that changes countability state
489 */
490 if (!CHECK_FLAG(flag,
1defdda8 491 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 492 return;
493
9bcb3eef 494 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
495}
496
9bcb3eef 497void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 498 uint32_t flag)
1a392d46 499{
40381db7 500 UNSET_FLAG(pi->flags, flag);
d62a17ae 501
502 /* early bath if we know it's not a flag that changes countability state
503 */
504 if (!CHECK_FLAG(flag,
1defdda8 505 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 506 return;
507
9bcb3eef 508 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
509}
510
718e3744 511/* Get MED value. If MED value is missing and "bgp bestpath
512 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 513static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 514{
515 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
516 return attr->med;
517 else {
892fedb6 518 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 519 return BGP_MED_MAX;
520 else
521 return 0;
522 }
718e3744 523}
524
40381db7 525void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 526{
40381db7
DS
527 if (pi->addpath_rx_id)
528 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
529 pi->addpath_rx_id);
d62a17ae 530 else
40381db7 531 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 532}
9fbdd100 533
d62a17ae 534/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
535 */
18ee8310
DS
536static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
537 struct bgp_path_info *exist, int *paths_eq,
538 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
539 char *pfx_buf, afi_t afi, safi_t safi,
540 enum bgp_path_selection_reason *reason)
d62a17ae 541{
542 struct attr *newattr, *existattr;
543 bgp_peer_sort_t new_sort;
544 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
545 uint32_t new_pref;
546 uint32_t exist_pref;
547 uint32_t new_med;
548 uint32_t exist_med;
549 uint32_t new_weight;
550 uint32_t exist_weight;
d62a17ae 551 uint32_t newm, existm;
552 struct in_addr new_id;
553 struct in_addr exist_id;
554 int new_cluster;
555 int exist_cluster;
556 int internal_as_route;
557 int confed_as_route;
04d14c8b 558 int ret = 0;
d62a17ae 559 char new_buf[PATH_ADDPATH_STR_BUFFER];
560 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
561 uint32_t new_mm_seq;
562 uint32_t exist_mm_seq;
6d8c603a 563 int nh_cmp;
d071f237
AK
564 esi_t *exist_esi;
565 esi_t *new_esi;
566 bool same_esi;
567 bool old_proxy;
568 bool new_proxy;
33c6e933 569 bool new_origin, exist_origin;
d62a17ae 570
571 *paths_eq = 0;
572
573 /* 0. Null check. */
574 if (new == NULL) {
fdf81fa0 575 *reason = bgp_path_selection_none;
d62a17ae 576 if (debug)
577 zlog_debug("%s: new is NULL", pfx_buf);
578 return 0;
579 }
2ec1e66f 580
d62a17ae 581 if (debug)
18ee8310 582 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 583
d62a17ae 584 if (exist == NULL) {
fdf81fa0 585 *reason = bgp_path_selection_first;
d62a17ae 586 if (debug)
587 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
588 new_buf);
589 return 1;
590 }
2ec1e66f 591
d62a17ae 592 if (debug) {
18ee8310 593 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 594 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
595 pfx_buf, new_buf, new->flags, exist_buf,
596 exist->flags);
597 }
8ff56318 598
d62a17ae 599 newattr = new->attr;
600 existattr = exist->attr;
601
602 /* For EVPN routes, we cannot just go by local vs remote, we have to
603 * look at the MAC mobility sequence number, if present.
604 */
605 if (safi == SAFI_EVPN) {
606 /* This is an error condition described in RFC 7432 Section
607 * 15.2. The RFC
608 * states that in this scenario "the PE MUST alert the operator"
609 * but it
610 * does not state what other action to take. In order to provide
611 * some
612 * consistency in this scenario we are going to prefer the path
613 * with the
614 * sticky flag.
615 */
616 if (newattr->sticky != existattr->sticky) {
617 if (!debug) {
9bcb3eef
DS
618 prefix2str(
619 bgp_dest_get_prefix(new->net), pfx_buf,
620 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
621 bgp_path_info_path_with_addpath_rx_str(new,
622 new_buf);
623 bgp_path_info_path_with_addpath_rx_str(
624 exist, exist_buf);
d62a17ae 625 }
626
627 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 628 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
629 if (debug)
630 zlog_debug(
631 "%s: %s wins over %s due to sticky MAC flag",
632 pfx_buf, new_buf, exist_buf);
d62a17ae 633 return 1;
634 }
635
636 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 637 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
638 if (debug)
639 zlog_debug(
640 "%s: %s loses to %s due to sticky MAC flag",
641 pfx_buf, new_buf, exist_buf);
d62a17ae 642 return 0;
643 }
644 }
128ea8ab 645
d071f237
AK
646 new_esi = bgp_evpn_attr_get_esi(newattr);
647 exist_esi = bgp_evpn_attr_get_esi(existattr);
648 if (bgp_evpn_is_esi_valid(new_esi) &&
649 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
650 same_esi = true;
651 } else {
652 same_esi = false;
653 }
654
655 /* If both paths have the same non-zero ES and
656 * one path is local it wins.
657 * PS: Note the local path wins even if the remote
658 * has the higher MM seq. The local path's
659 * MM seq will be fixed up to match the highest
660 * rem seq, subsequently.
661 */
662 if (same_esi) {
663 char esi_buf[ESI_STR_LEN];
664
665 if (bgp_evpn_is_path_local(bgp, new)) {
666 *reason = bgp_path_selection_evpn_local_path;
667 if (debug)
668 zlog_debug(
669 "%s: %s wins over %s as ES %s is same and local",
670 pfx_buf, new_buf, exist_buf,
671 esi_to_str(new_esi, esi_buf,
672 sizeof(esi_buf)));
673 return 1;
674 }
675 if (bgp_evpn_is_path_local(bgp, exist)) {
676 *reason = bgp_path_selection_evpn_local_path;
677 if (debug)
678 zlog_debug(
679 "%s: %s loses to %s as ES %s is same and local",
680 pfx_buf, new_buf, exist_buf,
681 esi_to_str(new_esi, esi_buf,
682 sizeof(esi_buf)));
683 return 0;
684 }
685 }
686
d62a17ae 687 new_mm_seq = mac_mobility_seqnum(newattr);
688 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 689
d62a17ae 690 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 691 *reason = bgp_path_selection_evpn_seq;
d62a17ae 692 if (debug)
693 zlog_debug(
694 "%s: %s wins over %s due to MM seq %u > %u",
695 pfx_buf, new_buf, exist_buf, new_mm_seq,
696 exist_mm_seq);
697 return 1;
698 }
8ff56318 699
d62a17ae 700 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 701 *reason = bgp_path_selection_evpn_seq;
d62a17ae 702 if (debug)
703 zlog_debug(
704 "%s: %s loses to %s due to MM seq %u < %u",
705 pfx_buf, new_buf, exist_buf, new_mm_seq,
706 exist_mm_seq);
707 return 0;
708 }
6d8c603a 709
d071f237
AK
710 /* if the sequence numbers and ESI are the same and one path
711 * is non-proxy it wins (over proxy)
712 */
713 new_proxy = bgp_evpn_attr_is_proxy(newattr);
714 old_proxy = bgp_evpn_attr_is_proxy(existattr);
715 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
716 old_proxy != new_proxy) {
717 if (!new_proxy) {
718 *reason = bgp_path_selection_evpn_non_proxy;
719 if (debug)
720 zlog_debug(
721 "%s: %s wins over %s, same seq/es and non-proxy",
722 pfx_buf, new_buf, exist_buf);
723 return 1;
724 }
725
726 *reason = bgp_path_selection_evpn_non_proxy;
727 if (debug)
728 zlog_debug(
729 "%s: %s loses to %s, same seq/es and non-proxy",
730 pfx_buf, new_buf, exist_buf);
731 return 0;
732 }
733
6d8c603a
AK
734 /*
735 * if sequence numbers are the same path with the lowest IP
736 * wins
737 */
738 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
739 if (nh_cmp < 0) {
fdf81fa0 740 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
741 if (debug)
742 zlog_debug(
23d0a753 743 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 744 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 745 &new->attr->nexthop);
6d8c603a
AK
746 return 1;
747 }
748 if (nh_cmp > 0) {
fdf81fa0 749 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
750 if (debug)
751 zlog_debug(
23d0a753 752 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 753 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 754 &new->attr->nexthop);
6d8c603a
AK
755 return 0;
756 }
d62a17ae 757 }
9fbdd100 758
d62a17ae 759 /* 1. Weight check. */
d62a17ae 760 new_weight = newattr->weight;
761 exist_weight = existattr->weight;
8ff56318 762
d62a17ae 763 if (new_weight > exist_weight) {
fdf81fa0 764 *reason = bgp_path_selection_weight;
d62a17ae 765 if (debug)
766 zlog_debug("%s: %s wins over %s due to weight %d > %d",
767 pfx_buf, new_buf, exist_buf, new_weight,
768 exist_weight);
769 return 1;
770 }
718e3744 771
d62a17ae 772 if (new_weight < exist_weight) {
fdf81fa0 773 *reason = bgp_path_selection_weight;
d62a17ae 774 if (debug)
775 zlog_debug("%s: %s loses to %s due to weight %d < %d",
776 pfx_buf, new_buf, exist_buf, new_weight,
777 exist_weight);
778 return 0;
779 }
9fbdd100 780
d62a17ae 781 /* 2. Local preference check. */
782 new_pref = exist_pref = bgp->default_local_pref;
783
784 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
785 new_pref = newattr->local_pref;
786 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
787 exist_pref = existattr->local_pref;
788
789 if (new_pref > exist_pref) {
fdf81fa0 790 *reason = bgp_path_selection_local_pref;
d62a17ae 791 if (debug)
792 zlog_debug(
793 "%s: %s wins over %s due to localpref %d > %d",
794 pfx_buf, new_buf, exist_buf, new_pref,
795 exist_pref);
796 return 1;
797 }
718e3744 798
d62a17ae 799 if (new_pref < exist_pref) {
fdf81fa0 800 *reason = bgp_path_selection_local_pref;
d62a17ae 801 if (debug)
802 zlog_debug(
803 "%s: %s loses to %s due to localpref %d < %d",
804 pfx_buf, new_buf, exist_buf, new_pref,
805 exist_pref);
806 return 0;
807 }
9fbdd100 808
d62a17ae 809 /* 3. Local route check. We prefer:
810 * - BGP_ROUTE_STATIC
811 * - BGP_ROUTE_AGGREGATE
812 * - BGP_ROUTE_REDISTRIBUTE
813 */
33c6e933
DS
814 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
815 new->sub_type == BGP_ROUTE_IMPORTED);
816 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
817 exist->sub_type == BGP_ROUTE_IMPORTED);
818
819 if (new_origin && !exist_origin) {
fdf81fa0 820 *reason = bgp_path_selection_local_route;
d62a17ae 821 if (debug)
822 zlog_debug(
823 "%s: %s wins over %s due to preferred BGP_ROUTE type",
824 pfx_buf, new_buf, exist_buf);
825 return 1;
826 }
718e3744 827
33c6e933 828 if (!new_origin && exist_origin) {
fdf81fa0 829 *reason = bgp_path_selection_local_route;
d62a17ae 830 if (debug)
831 zlog_debug(
832 "%s: %s loses to %s due to preferred BGP_ROUTE type",
833 pfx_buf, new_buf, exist_buf);
834 return 0;
6811845b 835 }
718e3744 836
d62a17ae 837 /* 4. AS path length check. */
892fedb6 838 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 839 int exist_hops = aspath_count_hops(existattr->aspath);
840 int exist_confeds = aspath_count_confeds(existattr->aspath);
841
892fedb6 842 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 843 int aspath_hops;
844
845 aspath_hops = aspath_count_hops(newattr->aspath);
846 aspath_hops += aspath_count_confeds(newattr->aspath);
847
848 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 849 *reason = bgp_path_selection_confed_as_path;
d62a17ae 850 if (debug)
851 zlog_debug(
852 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
853 pfx_buf, new_buf, exist_buf,
854 aspath_hops,
855 (exist_hops + exist_confeds));
856 return 1;
857 }
858
859 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 860 *reason = bgp_path_selection_confed_as_path;
d62a17ae 861 if (debug)
862 zlog_debug(
863 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
864 pfx_buf, new_buf, exist_buf,
865 aspath_hops,
866 (exist_hops + exist_confeds));
867 return 0;
868 }
869 } else {
870 int newhops = aspath_count_hops(newattr->aspath);
871
872 if (newhops < exist_hops) {
fdf81fa0 873 *reason = bgp_path_selection_as_path;
d62a17ae 874 if (debug)
875 zlog_debug(
876 "%s: %s wins over %s due to aspath hopcount %d < %d",
877 pfx_buf, new_buf, exist_buf,
878 newhops, exist_hops);
879 return 1;
880 }
881
882 if (newhops > exist_hops) {
fdf81fa0 883 *reason = bgp_path_selection_as_path;
d62a17ae 884 if (debug)
885 zlog_debug(
886 "%s: %s loses to %s due to aspath hopcount %d > %d",
887 pfx_buf, new_buf, exist_buf,
888 newhops, exist_hops);
889 return 0;
890 }
891 }
892 }
9fbdd100 893
d62a17ae 894 /* 5. Origin check. */
895 if (newattr->origin < existattr->origin) {
fdf81fa0 896 *reason = bgp_path_selection_origin;
d62a17ae 897 if (debug)
898 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
899 pfx_buf, new_buf, exist_buf,
900 bgp_origin_long_str[newattr->origin],
901 bgp_origin_long_str[existattr->origin]);
902 return 1;
903 }
718e3744 904
d62a17ae 905 if (newattr->origin > existattr->origin) {
fdf81fa0 906 *reason = bgp_path_selection_origin;
d62a17ae 907 if (debug)
908 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
909 pfx_buf, new_buf, exist_buf,
910 bgp_origin_long_str[newattr->origin],
911 bgp_origin_long_str[existattr->origin]);
912 return 0;
913 }
718e3744 914
d62a17ae 915 /* 6. MED check. */
916 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
917 && aspath_count_hops(existattr->aspath) == 0);
918 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
919 && aspath_count_confeds(existattr->aspath) > 0
920 && aspath_count_hops(newattr->aspath) == 0
921 && aspath_count_hops(existattr->aspath) == 0);
922
892fedb6
DA
923 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
924 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 925 || aspath_cmp_left(newattr->aspath, existattr->aspath)
926 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
927 || internal_as_route) {
928 new_med = bgp_med_value(new->attr, bgp);
929 exist_med = bgp_med_value(exist->attr, bgp);
930
931 if (new_med < exist_med) {
fdf81fa0 932 *reason = bgp_path_selection_med;
d62a17ae 933 if (debug)
934 zlog_debug(
935 "%s: %s wins over %s due to MED %d < %d",
936 pfx_buf, new_buf, exist_buf, new_med,
937 exist_med);
938 return 1;
939 }
8ff56318 940
d62a17ae 941 if (new_med > exist_med) {
fdf81fa0 942 *reason = bgp_path_selection_med;
d62a17ae 943 if (debug)
944 zlog_debug(
945 "%s: %s loses to %s due to MED %d > %d",
946 pfx_buf, new_buf, exist_buf, new_med,
947 exist_med);
948 return 0;
949 }
950 }
9fbdd100 951
d62a17ae 952 /* 7. Peer type check. */
953 new_sort = new->peer->sort;
954 exist_sort = exist->peer->sort;
955
956 if (new_sort == BGP_PEER_EBGP
957 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 958 *reason = bgp_path_selection_peer;
d62a17ae 959 if (debug)
960 zlog_debug(
961 "%s: %s wins over %s due to eBGP peer > iBGP peer",
962 pfx_buf, new_buf, exist_buf);
963 return 1;
964 }
718e3744 965
d62a17ae 966 if (exist_sort == BGP_PEER_EBGP
967 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 968 *reason = bgp_path_selection_peer;
d62a17ae 969 if (debug)
970 zlog_debug(
971 "%s: %s loses to %s due to iBGP peer < eBGP peer",
972 pfx_buf, new_buf, exist_buf);
973 return 0;
974 }
8ff56318 975
d62a17ae 976 /* 8. IGP metric check. */
977 newm = existm = 0;
8ff56318 978
d62a17ae 979 if (new->extra)
980 newm = new->extra->igpmetric;
981 if (exist->extra)
982 existm = exist->extra->igpmetric;
9fbdd100 983
d62a17ae 984 if (newm < existm) {
985 if (debug)
986 zlog_debug(
987 "%s: %s wins over %s due to IGP metric %d < %d",
988 pfx_buf, new_buf, exist_buf, newm, existm);
989 ret = 1;
990 }
718e3744 991
d62a17ae 992 if (newm > existm) {
993 if (debug)
994 zlog_debug(
995 "%s: %s loses to %s due to IGP metric %d > %d",
996 pfx_buf, new_buf, exist_buf, newm, existm);
997 ret = 0;
5e242b0d 998 }
5e242b0d 999
d62a17ae 1000 /* 9. Same IGP metric. Compare the cluster list length as
1001 representative of IGP hops metric. Rewrite the metric value
1002 pair (newm, existm) with the cluster list length. Prefer the
1003 path with smaller cluster list length. */
1004 if (newm == existm) {
bf0d28dc
DS
1005 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1006 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1007 && (mpath_cfg == NULL
1008 || CHECK_FLAG(
1009 mpath_cfg->ibgp_flags,
1010 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1011 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1012 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1013
1014 if (newm < existm) {
1015 if (debug)
1016 zlog_debug(
1017 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1018 pfx_buf, new_buf, exist_buf,
1019 newm, existm);
1020 ret = 1;
1021 }
1022
1023 if (newm > existm) {
1024 if (debug)
1025 zlog_debug(
1026 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1027 pfx_buf, new_buf, exist_buf,
1028 newm, existm);
1029 ret = 0;
1030 }
1031 }
1032 }
31a4638f 1033
d62a17ae 1034 /* 10. confed-external vs. confed-internal */
1035 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1036 if (new_sort == BGP_PEER_CONFED
1037 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1038 *reason = bgp_path_selection_confed;
d62a17ae 1039 if (debug)
1040 zlog_debug(
1041 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1042 pfx_buf, new_buf, exist_buf);
1043 return 1;
1044 }
718e3744 1045
d62a17ae 1046 if (exist_sort == BGP_PEER_CONFED
1047 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1048 *reason = bgp_path_selection_confed;
d62a17ae 1049 if (debug)
1050 zlog_debug(
1051 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1052 pfx_buf, new_buf, exist_buf);
1053 return 0;
1054 }
1055 }
718e3744 1056
d62a17ae 1057 /* 11. Maximum path check. */
1058 if (newm == existm) {
1059 /* If one path has a label but the other does not, do not treat
1060 * them as equals for multipath
1061 */
a4d82a8a 1062 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1063 != (exist->extra
b57ba6d2 1064 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1065 if (debug)
1066 zlog_debug(
1067 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1068 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1069 } else if (CHECK_FLAG(bgp->flags,
1070 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1071
1072 /*
1073 * For the two paths, all comparison steps till IGP
1074 * metric
1075 * have succeeded - including AS_PATH hop count. Since
1076 * 'bgp
1077 * bestpath as-path multipath-relax' knob is on, we
1078 * don't need
1079 * an exact match of AS_PATH. Thus, mark the paths are
1080 * equal.
1081 * That will trigger both these paths to get into the
1082 * multipath
1083 * array.
1084 */
1085 *paths_eq = 1;
1086
1087 if (debug)
1088 zlog_debug(
1089 "%s: %s and %s are equal via multipath-relax",
1090 pfx_buf, new_buf, exist_buf);
1091 } else if (new->peer->sort == BGP_PEER_IBGP) {
1092 if (aspath_cmp(new->attr->aspath,
1093 exist->attr->aspath)) {
1094 *paths_eq = 1;
1095
1096 if (debug)
1097 zlog_debug(
1098 "%s: %s and %s are equal via matching aspaths",
1099 pfx_buf, new_buf, exist_buf);
1100 }
1101 } else if (new->peer->as == exist->peer->as) {
1102 *paths_eq = 1;
1103
1104 if (debug)
1105 zlog_debug(
1106 "%s: %s and %s are equal via same remote-as",
1107 pfx_buf, new_buf, exist_buf);
1108 }
1109 } else {
1110 /*
1111 * TODO: If unequal cost ibgp multipath is enabled we can
1112 * mark the paths as equal here instead of returning
1113 */
1114 if (debug) {
1115 if (ret == 1)
1116 zlog_debug(
1117 "%s: %s wins over %s after IGP metric comparison",
1118 pfx_buf, new_buf, exist_buf);
1119 else
1120 zlog_debug(
1121 "%s: %s loses to %s after IGP metric comparison",
1122 pfx_buf, new_buf, exist_buf);
1123 }
fdf81fa0 1124 *reason = bgp_path_selection_igp_metric;
d62a17ae 1125 return ret;
1126 }
718e3744 1127
d62a17ae 1128 /* 12. If both paths are external, prefer the path that was received
1129 first (the oldest one). This step minimizes route-flap, since a
1130 newer path won't displace an older one, even if it was the
1131 preferred route based on the additional decision criteria below. */
892fedb6 1132 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1133 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1134 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1135 *reason = bgp_path_selection_older;
d62a17ae 1136 if (debug)
1137 zlog_debug(
1138 "%s: %s wins over %s due to oldest external",
1139 pfx_buf, new_buf, exist_buf);
1140 return 1;
1141 }
9fbdd100 1142
1defdda8 1143 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1144 *reason = bgp_path_selection_older;
d62a17ae 1145 if (debug)
1146 zlog_debug(
1147 "%s: %s loses to %s due to oldest external",
1148 pfx_buf, new_buf, exist_buf);
1149 return 0;
1150 }
1151 }
718e3744 1152
d62a17ae 1153 /* 13. Router-ID comparision. */
1154 /* If one of the paths is "stale", the corresponding peer router-id will
1155 * be 0 and would always win over the other path. If originator id is
1156 * used for the comparision, it will decide which path is better.
1157 */
1158 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1159 new_id.s_addr = newattr->originator_id.s_addr;
1160 else
1161 new_id.s_addr = new->peer->remote_id.s_addr;
1162 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1163 exist_id.s_addr = existattr->originator_id.s_addr;
1164 else
1165 exist_id.s_addr = exist->peer->remote_id.s_addr;
1166
1167 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1168 *reason = bgp_path_selection_router_id;
d62a17ae 1169 if (debug)
1170 zlog_debug(
1171 "%s: %s wins over %s due to Router-ID comparison",
1172 pfx_buf, new_buf, exist_buf);
1173 return 1;
1174 }
718e3744 1175
d62a17ae 1176 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1177 *reason = bgp_path_selection_router_id;
d62a17ae 1178 if (debug)
1179 zlog_debug(
1180 "%s: %s loses to %s due to Router-ID comparison",
1181 pfx_buf, new_buf, exist_buf);
1182 return 0;
1183 }
9fbdd100 1184
d62a17ae 1185 /* 14. Cluster length comparision. */
1186 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1187 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1188
1189 if (new_cluster < exist_cluster) {
fdf81fa0 1190 *reason = bgp_path_selection_cluster_length;
d62a17ae 1191 if (debug)
1192 zlog_debug(
1193 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1194 pfx_buf, new_buf, exist_buf, new_cluster,
1195 exist_cluster);
1196 return 1;
1197 }
718e3744 1198
d62a17ae 1199 if (new_cluster > exist_cluster) {
fdf81fa0 1200 *reason = bgp_path_selection_cluster_length;
d62a17ae 1201 if (debug)
1202 zlog_debug(
1203 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1204 pfx_buf, new_buf, exist_buf, new_cluster,
1205 exist_cluster);
1206 return 0;
1207 }
9fbdd100 1208
d62a17ae 1209 /* 15. Neighbor address comparision. */
1210 /* Do this only if neither path is "stale" as stale paths do not have
1211 * valid peer information (as the connection may or may not be up).
1212 */
1defdda8 1213 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1214 *reason = bgp_path_selection_stale;
d62a17ae 1215 if (debug)
1216 zlog_debug(
1217 "%s: %s wins over %s due to latter path being STALE",
1218 pfx_buf, new_buf, exist_buf);
1219 return 1;
1220 }
0de5153c 1221
1defdda8 1222 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1223 *reason = bgp_path_selection_stale;
d62a17ae 1224 if (debug)
1225 zlog_debug(
1226 "%s: %s loses to %s due to former path being STALE",
1227 pfx_buf, new_buf, exist_buf);
1228 return 0;
1229 }
718e3744 1230
d62a17ae 1231 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1232 if (new->peer->su_remote == NULL) {
1233 *reason = bgp_path_selection_local_configured;
d62a17ae 1234 return 0;
fdf81fa0
DS
1235 }
1236 if (exist->peer->su_remote == NULL) {
1237 *reason = bgp_path_selection_local_configured;
d62a17ae 1238 return 1;
fdf81fa0 1239 }
9fbdd100 1240
d62a17ae 1241 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1242
1243 if (ret == 1) {
fdf81fa0 1244 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s loses to %s due to Neighor IP comparison",
1248 pfx_buf, new_buf, exist_buf);
1249 return 0;
1250 }
1251
1252 if (ret == -1) {
fdf81fa0 1253 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1254 if (debug)
1255 zlog_debug(
1256 "%s: %s wins over %s due to Neighor IP comparison",
1257 pfx_buf, new_buf, exist_buf);
1258 return 1;
1259 }
9fbdd100 1260
fdf81fa0 1261 *reason = bgp_path_selection_default;
d62a17ae 1262 if (debug)
1263 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1264 pfx_buf, new_buf, exist_buf);
718e3744 1265
d62a17ae 1266 return 1;
718e3744 1267}
1268
d071f237
AK
1269
1270int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1271 struct bgp_path_info *exist, int *paths_eq)
1272{
1273 enum bgp_path_selection_reason reason;
1274 char pfx_buf[PREFIX2STR_BUFFER];
1275
1276 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1277 AFI_L2VPN, SAFI_EVPN, &reason);
1278}
1279
65efcfce
LB
1280/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1281 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1282 * multipath is enabled
65efcfce 1283 * This version is compatible with */
18ee8310
DS
1284int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1285 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1286 afi_t afi, safi_t safi,
1287 enum bgp_path_selection_reason *reason)
d62a17ae 1288{
1289 int paths_eq;
1290 int ret;
18ee8310 1291 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1292 afi, safi, reason);
d62a17ae 1293
1294 if (paths_eq)
1295 ret = 0;
1296 else {
1297 if (ret == 1)
1298 ret = -1;
1299 else
1300 ret = 1;
1301 }
1302 return ret;
65efcfce
LB
1303}
1304
5a1ae2c2
DS
1305static enum filter_type bgp_input_filter(struct peer *peer,
1306 const struct prefix *p,
d62a17ae 1307 struct attr *attr, afi_t afi,
1308 safi_t safi)
718e3744 1309{
d62a17ae 1310 struct bgp_filter *filter;
6401252f 1311 enum filter_type ret = FILTER_PERMIT;
718e3744 1312
d62a17ae 1313 filter = &peer->filter[afi][safi];
718e3744 1314
d62a17ae 1315#define FILTER_EXIST_WARN(F, f, filter) \
1316 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1317 zlog_debug("%s: Could not find configured input %s-list %s!", \
1318 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1319
1320 if (DISTRIBUTE_IN_NAME(filter)) {
1321 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1322
6401252f
QY
1323 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1324 == FILTER_DENY) {
1325 ret = FILTER_DENY;
1326 goto done;
1327 }
d62a17ae 1328 }
1329
1330 if (PREFIX_LIST_IN_NAME(filter)) {
1331 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1332
6401252f
QY
1333 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1334 == PREFIX_DENY) {
1335 ret = FILTER_DENY;
1336 goto done;
1337 }
d62a17ae 1338 }
1339
1340 if (FILTER_LIST_IN_NAME(filter)) {
1341 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1342
1343 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1344 == AS_FILTER_DENY) {
1345 ret = FILTER_DENY;
1346 goto done;
1347 }
d62a17ae 1348 }
1349
6401252f 1350done:
c7bb4f00 1351 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1352 char pfxprint[PREFIX2STR_BUFFER];
1353
1354 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1355 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1356 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1357 }
1358
1359 return ret;
650f76c2 1360#undef FILTER_EXIST_WARN
718e3744 1361}
1362
b8685f9b
DS
1363static enum filter_type bgp_output_filter(struct peer *peer,
1364 const struct prefix *p,
d62a17ae 1365 struct attr *attr, afi_t afi,
1366 safi_t safi)
718e3744 1367{
d62a17ae 1368 struct bgp_filter *filter;
6401252f 1369 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1370
1371 filter = &peer->filter[afi][safi];
1372
1373#define FILTER_EXIST_WARN(F, f, filter) \
1374 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1375 zlog_debug("%s: Could not find configured output %s-list %s!", \
1376 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1377
d62a17ae 1378 if (DISTRIBUTE_OUT_NAME(filter)) {
1379 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1380
6401252f
QY
1381 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1382 == FILTER_DENY) {
1383 ret = FILTER_DENY;
1384 goto done;
1385 }
d62a17ae 1386 }
1387
1388 if (PREFIX_LIST_OUT_NAME(filter)) {
1389 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1390
d62a17ae 1391 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1392 == PREFIX_DENY) {
1393 ret = FILTER_DENY;
1394 goto done;
1395 }
d62a17ae 1396 }
718e3744 1397
d62a17ae 1398 if (FILTER_LIST_OUT_NAME(filter)) {
1399 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1400
d62a17ae 1401 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1402 == AS_FILTER_DENY) {
1403 ret = FILTER_DENY;
1404 goto done;
1405 }
1406 }
1407
c7bb4f00 1408 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1409 char pfxprint[PREFIX2STR_BUFFER];
1410
1411 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1412 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1413 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1414 }
718e3744 1415
6401252f
QY
1416done:
1417 return ret;
650f76c2 1418#undef FILTER_EXIST_WARN
718e3744 1419}
1420
1421/* If community attribute includes no_export then return 1. */
3dc339cd 1422static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1423{
1424 if (attr->community) {
1425 /* NO_ADVERTISE check. */
1426 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1427 return true;
d62a17ae 1428
1429 /* NO_EXPORT check. */
1430 if (peer->sort == BGP_PEER_EBGP
1431 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1432 return true;
d62a17ae 1433
1434 /* NO_EXPORT_SUBCONFED check. */
1435 if (peer->sort == BGP_PEER_EBGP
1436 || peer->sort == BGP_PEER_CONFED)
1437 if (community_include(attr->community,
1438 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1439 return true;
d62a17ae 1440 }
3dc339cd 1441 return false;
718e3744 1442}
1443
1444/* Route reflection loop check. */
3dc339cd 1445static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1446{
d62a17ae 1447 struct in_addr cluster_id;
779fee93 1448 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1449
779fee93 1450 if (cluster) {
d62a17ae 1451 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1452 cluster_id = peer->bgp->cluster_id;
1453 else
1454 cluster_id = peer->bgp->router_id;
1455
779fee93 1456 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1457 return true;
d62a17ae 1458 }
3dc339cd 1459 return false;
718e3744 1460}
6b0655a2 1461
5a1ae2c2 1462static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1463 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1464 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1465 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1466{
d62a17ae 1467 struct bgp_filter *filter;
82b692c0
LK
1468 struct bgp_path_info rmap_path = { 0 };
1469 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1470 route_map_result_t ret;
1471 struct route_map *rmap = NULL;
718e3744 1472
d62a17ae 1473 filter = &peer->filter[afi][safi];
718e3744 1474
d62a17ae 1475 /* Apply default weight value. */
1476 if (peer->weight[afi][safi])
1477 attr->weight = peer->weight[afi][safi];
718e3744 1478
d62a17ae 1479 if (rmap_name) {
1480 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1481
d62a17ae 1482 if (rmap == NULL)
1483 return RMAP_DENY;
1484 } else {
1485 if (ROUTE_MAP_IN_NAME(filter)) {
1486 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1487
d62a17ae 1488 if (rmap == NULL)
1489 return RMAP_DENY;
1490 }
1491 }
0b16f239 1492
d62a17ae 1493 /* Route map apply. */
1494 if (rmap) {
40381db7 1495 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1496 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1497 rmap_path.peer = peer;
1498 rmap_path.attr = attr;
82b692c0 1499 rmap_path.extra = &extra;
9bcb3eef 1500 rmap_path.net = dest;
196c6b09 1501
82b692c0
LK
1502 extra.num_labels = num_labels;
1503 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1504 memcpy(extra.label, label,
1505 num_labels * sizeof(mpls_label_t));
718e3744 1506
d62a17ae 1507 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1508
d62a17ae 1509 /* Apply BGP route map to the attribute. */
1782514f 1510 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1511
d62a17ae 1512 peer->rmap_type = 0;
0b16f239 1513
1f2263be 1514 if (ret == RMAP_DENYMATCH)
d62a17ae 1515 return RMAP_DENY;
0b16f239 1516 }
d62a17ae 1517 return RMAP_PERMIT;
0b16f239
DS
1518}
1519
5f040085 1520static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1521 struct attr *attr, afi_t afi, safi_t safi,
1522 const char *rmap_name)
0b16f239 1523{
40381db7 1524 struct bgp_path_info rmap_path;
d62a17ae 1525 route_map_result_t ret;
1526 struct route_map *rmap = NULL;
d7c0a89a 1527 uint8_t rmap_type;
0b16f239 1528
b787157a
DS
1529 /*
1530 * So if we get to this point and have no rmap_name
1531 * we want to just show the output as it currently
1532 * exists.
1533 */
1534 if (!rmap_name)
1535 return RMAP_PERMIT;
0b16f239 1536
d62a17ae 1537 /* Apply default weight value. */
1538 if (peer->weight[afi][safi])
1539 attr->weight = peer->weight[afi][safi];
0b16f239 1540
b787157a 1541 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1542
b787157a
DS
1543 /*
1544 * If we have a route map name and we do not find
1545 * the routemap that means we have an implicit
1546 * deny.
1547 */
1548 if (rmap == NULL)
1549 return RMAP_DENY;
0b16f239 1550
40381db7 1551 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1552 /* Route map apply. */
b787157a 1553 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1554 rmap_path.peer = peer;
1555 rmap_path.attr = attr;
0b16f239 1556
0f672529 1557 rmap_type = peer->rmap_type;
b787157a 1558 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1559
b787157a 1560 /* Apply BGP route map to the attribute. */
1782514f 1561 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1562
0f672529 1563 peer->rmap_type = rmap_type;
b787157a
DS
1564
1565 if (ret == RMAP_DENYMATCH)
1566 /*
1567 * caller has multiple error paths with bgp_attr_flush()
1568 */
1569 return RMAP_DENY;
ac41b2a2 1570
d62a17ae 1571 return RMAP_PERMIT;
718e3744 1572}
6b0655a2 1573
5000f21c 1574/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1575static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1576 struct peer *peer, struct attr *attr)
1577{
1578 if (peer->sort == BGP_PEER_EBGP
1579 && (peer_af_flag_check(peer, afi, safi,
1580 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1581 || peer_af_flag_check(peer, afi, safi,
1582 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1583 || peer_af_flag_check(peer, afi, safi,
1584 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1585 || peer_af_flag_check(peer, afi, safi,
1586 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1587 // Take action on the entire aspath
1588 if (peer_af_flag_check(peer, afi, safi,
1589 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1590 || peer_af_flag_check(peer, afi, safi,
1591 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1592 if (peer_af_flag_check(
1593 peer, afi, safi,
1594 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1595 attr->aspath = aspath_replace_private_asns(
bf26b80e 1596 attr->aspath, bgp->as, peer->as);
d62a17ae 1597
1598 // The entire aspath consists of private ASNs so create
1599 // an empty aspath
1600 else if (aspath_private_as_check(attr->aspath))
1601 attr->aspath = aspath_empty_get();
1602
1603 // There are some public and some private ASNs, remove
1604 // the private ASNs
1605 else
1606 attr->aspath = aspath_remove_private_asns(
bf26b80e 1607 attr->aspath, peer->as);
d62a17ae 1608 }
1609
1610 // 'all' was not specified so the entire aspath must be private
1611 // ASNs
1612 // for us to do anything
1613 else if (aspath_private_as_check(attr->aspath)) {
1614 if (peer_af_flag_check(
1615 peer, afi, safi,
1616 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1617 attr->aspath = aspath_replace_private_asns(
bf26b80e 1618 attr->aspath, bgp->as, peer->as);
d62a17ae 1619 else
1620 attr->aspath = aspath_empty_get();
1621 }
1622 }
5000f21c
DS
1623}
1624
c7122e14 1625/* If this is an EBGP peer with as-override */
d62a17ae 1626static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1627 struct peer *peer, struct attr *attr)
1628{
1629 if (peer->sort == BGP_PEER_EBGP
1630 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1631 if (aspath_single_asn_check(attr->aspath, peer->as))
1632 attr->aspath = aspath_replace_specific_asn(
1633 attr->aspath, peer->as, bgp->as);
1634 }
1635}
1636
7f323236
DW
1637void bgp_attr_add_gshut_community(struct attr *attr)
1638{
1639 struct community *old;
1640 struct community *new;
1641 struct community *merge;
1642 struct community *gshut;
1643
1644 old = attr->community;
1645 gshut = community_str2com("graceful-shutdown");
1646
990f4f91 1647 assert(gshut);
1648
7f323236
DW
1649 if (old) {
1650 merge = community_merge(community_dup(old), gshut);
1651
a4d82a8a 1652 if (old->refcnt == 0)
3c1f53de 1653 community_free(&old);
7f323236
DW
1654
1655 new = community_uniq_sort(merge);
3c1f53de 1656 community_free(&merge);
7f323236
DW
1657 } else {
1658 new = community_dup(gshut);
1659 }
1660
3c1f53de 1661 community_free(&gshut);
7f323236
DW
1662 attr->community = new;
1663 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1664
1665 /* When we add the graceful-shutdown community we must also
1666 * lower the local-preference */
1667 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1668 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1669}
1670
1671
e73c112e
MK
1672/* Notify BGP Conditional advertisement scanner process. */
1673void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1674{
1675 struct peer *temp_peer;
1676 struct peer *peer = SUBGRP_PEER(subgrp);
1677 struct listnode *temp_node, *temp_nnode = NULL;
1678 afi_t afi = SUBGRP_AFI(subgrp);
1679 safi_t safi = SUBGRP_SAFI(subgrp);
1680 struct bgp *bgp = SUBGRP_INST(subgrp);
1681 struct bgp_filter *filter = &peer->filter[afi][safi];
1682
1683 if (!ADVERTISE_MAP_NAME(filter))
1684 return;
1685
1686 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1687 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1688 continue;
1689
1690 if (peer != temp_peer)
1691 continue;
1692
1693 temp_peer->advmap_table_change = true;
1694 break;
1695 }
1696}
1697
1698
f2ee6d5c 1699void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1700{
960035b2 1701 if (family == AF_INET) {
975a328e
DA
1702 attr->nexthop.s_addr = INADDR_ANY;
1703 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1704 }
d62a17ae 1705 if (family == AF_INET6)
1706 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1707 if (family == AF_EVPN)
1708 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1709}
1710
9bcb3eef 1711bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1712 struct update_subgroup *subgrp,
7f7940e6
MK
1713 const struct prefix *p, struct attr *attr,
1714 bool skip_rmap_check)
d62a17ae 1715{
1716 struct bgp_filter *filter;
1717 struct peer *from;
1718 struct peer *peer;
1719 struct peer *onlypeer;
1720 struct bgp *bgp;
40381db7 1721 struct attr *piattr;
b68885f9 1722 route_map_result_t ret;
d62a17ae 1723 int transparent;
1724 int reflect;
1725 afi_t afi;
1726 safi_t safi;
1727 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1728 bool nh_reset = false;
1729 uint64_t cum_bw;
d62a17ae 1730
1731 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1732 return false;
d62a17ae 1733
1734 afi = SUBGRP_AFI(subgrp);
1735 safi = SUBGRP_SAFI(subgrp);
1736 peer = SUBGRP_PEER(subgrp);
1737 onlypeer = NULL;
1738 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1739 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1740
40381db7 1741 from = pi->peer;
d62a17ae 1742 filter = &peer->filter[afi][safi];
1743 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1744 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1745 : pi->attr;
3f9c7369 1746
49e5a4a0 1747#ifdef ENABLE_BGP_VNC
d62a17ae 1748 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1749 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1750 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1751
1752 /*
1753 * direct and direct_ext type routes originate internally even
1754 * though they can have peer pointers that reference other
1755 * systems
1756 */
8228a9a7
DS
1757 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1758 __func__, p);
d62a17ae 1759 samepeer_safe = 1;
1760 }
65efcfce
LB
1761#endif
1762
ddb5b488
PZ
1763 if (((afi == AFI_IP) || (afi == AFI_IP6))
1764 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1765 && (pi->type == ZEBRA_ROUTE_BGP)
1766 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1767
1768 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1769
1770 samepeer_safe = 1;
1771 }
1772
d62a17ae 1773 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1774 * pi is valid */
1775 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1776 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1777 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1778 return false;
d62a17ae 1779 }
adbac85e 1780
d62a17ae 1781 /* If this is not the bestpath then check to see if there is an enabled
1782 * addpath
1783 * feature that requires us to advertise it */
40381db7 1784 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1785 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1786 return false;
d62a17ae 1787 }
1788 }
06370dac 1789
d62a17ae 1790 /* Aggregate-address suppress check. */
4056a5f6
RZ
1791 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1792 return false;
3f9c7369 1793
13b7e7f0
DS
1794 /*
1795 * If we are doing VRF 2 VRF leaking via the import
1796 * statement, we want to prevent the route going
1797 * off box as that the RT and RD created are localy
1798 * significant and globaly useless.
1799 */
40381db7
DS
1800 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1801 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1802 return false;
13b7e7f0 1803
d62a17ae 1804 /* If it's labeled safi, make sure the route has a valid label. */
1805 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1806 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1807 if (!bgp_is_valid_label(&label)) {
1808 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1809 zlog_debug("u%" PRIu64 ":s%" PRIu64
1810 " %pFX is filtered - no label (%p)",
d62a17ae 1811 subgrp->update_group->id, subgrp->id,
8228a9a7 1812 p, &label);
3dc339cd 1813 return false;
d62a17ae 1814 }
1815 }
cd1964ff 1816
d62a17ae 1817 /* Do not send back route to sender. */
1818 if (onlypeer && from == onlypeer) {
3dc339cd 1819 return false;
d62a17ae 1820 }
3f9c7369 1821
d62a17ae 1822 /* Do not send the default route in the BGP table if the neighbor is
1823 * configured for default-originate */
1824 if (CHECK_FLAG(peer->af_flags[afi][safi],
1825 PEER_FLAG_DEFAULT_ORIGINATE)) {
1826 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1827 return false;
d62a17ae 1828 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1829 return false;
d62a17ae 1830 }
4125bb67 1831
d62a17ae 1832 /* Transparency check. */
1833 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1834 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1835 transparent = 1;
1836 else
1837 transparent = 0;
1838
1839 /* If community is not disabled check the no-export and local. */
40381db7 1840 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1841 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
84c320dc 1842 zlog_debug("%s: community filter check fail", __func__);
3dc339cd 1843 return false;
d62a17ae 1844 }
3f9c7369 1845
d62a17ae 1846 /* If the attribute has originator-id and it is same as remote
1847 peer's id. */
40381db7
DS
1848 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1849 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1850 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1851 zlog_debug(
8228a9a7
DS
1852 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1853 onlypeer->host, p);
3dc339cd 1854 return false;
d62a17ae 1855 }
3f9c7369 1856
d62a17ae 1857 /* ORF prefix-list filter check */
1858 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1859 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1860 || CHECK_FLAG(peer->af_cap[afi][safi],
1861 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1862 if (peer->orf_plist[afi][safi]) {
1863 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1864 == PREFIX_DENY) {
1865 if (bgp_debug_update(NULL, p,
1866 subgrp->update_group, 0))
1867 zlog_debug(
8228a9a7
DS
1868 "%s [Update:SEND] %pFX is filtered via ORF",
1869 peer->host, p);
3dc339cd 1870 return false;
d62a17ae 1871 }
1872 }
1873
1874 /* Output filter check. */
40381db7 1875 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1876 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1877 zlog_debug("%s [Update:SEND] %pFX is filtered",
1878 peer->host, p);
3dc339cd 1879 return false;
d62a17ae 1880 }
3f9c7369 1881
d62a17ae 1882 /* AS path loop check. */
2b31007c
RZ
1883 if (onlypeer && onlypeer->as_path_loop_detection
1884 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1885 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1886 zlog_debug(
3efd0893 1887 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1888 onlypeer->host, onlypeer->as);
3dc339cd 1889 return false;
d62a17ae 1890 }
3f9c7369 1891
d62a17ae 1892 /* If we're a CONFED we need to loop check the CONFED ID too */
1893 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1894 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1895 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1896 zlog_debug(
3efd0893 1897 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1898 peer->host, bgp->confed_id);
3dc339cd 1899 return false;
d62a17ae 1900 }
3f9c7369 1901 }
3f9c7369 1902
d62a17ae 1903 /* Route-Reflect check. */
1904 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1905 reflect = 1;
1906 else
1907 reflect = 0;
1908
1909 /* IBGP reflection check. */
1910 if (reflect && !samepeer_safe) {
1911 /* A route from a Client peer. */
1912 if (CHECK_FLAG(from->af_flags[afi][safi],
1913 PEER_FLAG_REFLECTOR_CLIENT)) {
1914 /* Reflect to all the Non-Client peers and also to the
1915 Client peers other than the originator. Originator
1916 check
1917 is already done. So there is noting to do. */
1918 /* no bgp client-to-client reflection check. */
892fedb6
DA
1919 if (CHECK_FLAG(bgp->flags,
1920 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1921 if (CHECK_FLAG(peer->af_flags[afi][safi],
1922 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1923 return false;
d62a17ae 1924 } else {
1925 /* A route from a Non-client peer. Reflect to all other
1926 clients. */
1927 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1928 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1929 return false;
d62a17ae 1930 }
1931 }
3f9c7369 1932
d62a17ae 1933 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1934 *attr = *piattr;
d62a17ae 1935
1936 /* If local-preference is not set. */
1937 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1938 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1939 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1940 attr->local_pref = bgp->default_local_pref;
3f9c7369 1941 }
3f9c7369 1942
d62a17ae 1943 /* If originator-id is not set and the route is to be reflected,
1944 set the originator id */
1945 if (reflect
1946 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1947 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1948 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1949 }
3f9c7369 1950
d62a17ae 1951 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1952 */
1953 if (peer->sort == BGP_PEER_EBGP
1954 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1955 if (from != bgp->peer_self && !transparent
1956 && !CHECK_FLAG(peer->af_flags[afi][safi],
1957 PEER_FLAG_MED_UNCHANGED))
1958 attr->flag &=
1959 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1960 }
3f9c7369 1961
d62a17ae 1962 /* Since the nexthop attribute can vary per peer, it is not explicitly
1963 * set
1964 * in announce check, only certain flags and length (or number of
1965 * nexthops
1966 * -- for IPv6/MP_REACH) are set here in order to guide the update
1967 * formation
1968 * code in setting the nexthop(s) on a per peer basis in
1969 * reformat_peer().
1970 * Typically, the source nexthop in the attribute is preserved but in
1971 * the
1972 * scenarios where we know it will always be overwritten, we reset the
1973 * nexthop to "0" in an attempt to achieve better Update packing. An
1974 * example of this is when a prefix from each of 2 IBGP peers needs to
1975 * be
1976 * announced to an EBGP peer (and they have the same attributes barring
1977 * their nexthop).
1978 */
1979 if (reflect)
1980 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1981
1982#define NEXTHOP_IS_V6 \
1983 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1984 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1985 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1986 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1987
1988 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1989 * if
1990 * the peer (group) is configured to receive link-local nexthop
1991 * unchanged
c728d027
DA
1992 * and it is available in the prefix OR we're not reflecting the route,
1993 * link-local nexthop address is valid and
d62a17ae 1994 * the peer (group) to whom we're going to announce is on a shared
1995 * network
1996 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1997 * By checking if nexthop LL address is valid we are sure that
1998 * we do not announce LL address as `::`.
d62a17ae 1999 */
2000 if (NEXTHOP_IS_V6) {
2001 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2002 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2003 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2004 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2005 || (!reflect
2006 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2007 && peer->shared_network
d62a17ae 2008 && (from == bgp->peer_self
2009 || peer->sort == BGP_PEER_EBGP))) {
2010 attr->mp_nexthop_len =
2011 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2012 }
3f9c7369 2013
d62a17ae 2014 /* Clear off link-local nexthop in source, whenever it is not
2015 * needed to
2016 * ensure more prefixes share the same attribute for
2017 * announcement.
2018 */
2019 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2020 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2021 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2022 }
3f9c7369 2023
d62a17ae 2024 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2025 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2026
2027 /* Route map & unsuppress-map apply. */
7f7940e6 2028 if (!skip_rmap_check
e73c112e 2029 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2030 struct bgp_path_info rmap_path = {0};
2031 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2032 struct attr dummy_attr = {0};
d62a17ae 2033
e34291b8 2034 /* Fill temp path_info */
9bcb3eef
DS
2035 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2036 pi, peer, attr);
16f7ce2b 2037
d62a17ae 2038 /* don't confuse inbound and outbound setting */
2039 RESET_FLAG(attr->rmap_change_flags);
2040
2041 /*
2042 * The route reflector is not allowed to modify the attributes
2043 * of the reflected IBGP routes unless explicitly allowed.
2044 */
2045 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2046 && !CHECK_FLAG(bgp->flags,
2047 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2048 dummy_attr = *attr;
40381db7 2049 rmap_path.attr = &dummy_attr;
d62a17ae 2050 }
3f9c7369 2051
d62a17ae 2052 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2053
4056a5f6 2054 if (bgp_path_suppressed(pi))
d62a17ae 2055 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2056 &rmap_path);
d62a17ae 2057 else
2058 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2059 &rmap_path);
d62a17ae 2060
2061 peer->rmap_type = 0;
2062
2063 if (ret == RMAP_DENYMATCH) {
778048bf 2064 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2065 zlog_debug(
2066 "%s [Update:SEND] %pFX is filtered by route-map",
2067 peer->host, p);
778048bf 2068
d62a17ae 2069 bgp_attr_flush(attr);
3dc339cd 2070 return false;
d62a17ae 2071 }
3f9c7369 2072 }
3f9c7369 2073
9dac9fc8
DA
2074 /* RFC 8212 to prevent route leaks.
2075 * This specification intends to improve this situation by requiring the
2076 * explicit configuration of both BGP Import and Export Policies for any
2077 * External BGP (EBGP) session such as customers, peers, or
2078 * confederation boundaries for all enabled address families. Through
2079 * codification of the aforementioned requirement, operators will
2080 * benefit from consistent behavior across different BGP
2081 * implementations.
2082 */
1d3fdccf 2083 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2084 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2085 return false;
9dac9fc8 2086
fb29348a
DA
2087 /* draft-ietf-idr-deprecate-as-set-confed-set
2088 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2089 * Eventually, This document (if approved) updates RFC 4271
2090 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2091 * and obsoletes RFC 6472.
2092 */
7f972cd8 2093 if (peer->bgp->reject_as_sets)
fb29348a 2094 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2095 return false;
fb29348a 2096
33d022bc
DA
2097 /* Codification of AS 0 Processing */
2098 if (aspath_check_as_zero(attr->aspath))
e2369003 2099 return false;
33d022bc 2100
637e5ba4 2101 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2102 if (peer->sort == BGP_PEER_IBGP
2103 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2104 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2105 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2106 } else {
2107 bgp_attr_add_gshut_community(attr);
2108 }
2109 }
2110
d62a17ae 2111 /* After route-map has been applied, we check to see if the nexthop to
2112 * be carried in the attribute (that is used for the announcement) can
2113 * be cleared off or not. We do this in all cases where we would be
2114 * setting the nexthop to "ourselves". For IPv6, we only need to
2115 * consider
2116 * the global nexthop here; the link-local nexthop would have been
2117 * cleared
2118 * already, and if not, it is required by the update formation code.
2119 * Also see earlier comments in this function.
2120 */
2121 /*
2122 * If route-map has performed some operation on the nexthop or the peer
2123 * configuration says to pass it unchanged, we cannot reset the nexthop
2124 * here, so only attempt to do it if these aren't true. Note that the
2125 * route-map handler itself might have cleared the nexthop, if for
2126 * example,
2127 * it is configured as 'peer-address'.
2128 */
2129 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2130 piattr->rmap_change_flags)
d62a17ae 2131 && !transparent
2132 && !CHECK_FLAG(peer->af_flags[afi][safi],
2133 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2134 /* We can reset the nexthop, if setting (or forcing) it to
2135 * 'self' */
2136 if (CHECK_FLAG(peer->af_flags[afi][safi],
2137 PEER_FLAG_NEXTHOP_SELF)
2138 || CHECK_FLAG(peer->af_flags[afi][safi],
2139 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2140 if (!reflect
2141 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2142 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2143 subgroup_announce_reset_nhop(
2144 (peer_cap_enhe(peer, afi, safi)
2145 ? AF_INET6
2146 : p->family),
2147 attr);
7b651a32 2148 nh_reset = true;
2149 }
d62a17ae 2150 } else if (peer->sort == BGP_PEER_EBGP) {
2151 /* Can also reset the nexthop if announcing to EBGP, but
2152 * only if
2153 * no peer in the subgroup is on a shared subnet.
2154 * Note: 3rd party nexthop currently implemented for
2155 * IPv4 only.
2156 */
737af885
BS
2157 if ((p->family == AF_INET) &&
2158 (!bgp_subgrp_multiaccess_check_v4(
2159 piattr->nexthop,
7b651a32 2160 subgrp, from))) {
d62a17ae 2161 subgroup_announce_reset_nhop(
2162 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2163 ? AF_INET6
2164 : p->family),
737af885 2165 attr);
7b651a32 2166 nh_reset = true;
2167 }
737af885
BS
2168
2169 if ((p->family == AF_INET6) &&
2170 (!bgp_subgrp_multiaccess_check_v6(
2171 piattr->mp_nexthop_global,
7b651a32 2172 subgrp, from))) {
737af885
BS
2173 subgroup_announce_reset_nhop(
2174 (peer_cap_enhe(peer, afi, safi)
2175 ? AF_INET6
2176 : p->family),
2177 attr);
7b651a32 2178 nh_reset = true;
2179 }
737af885
BS
2180
2181
2182
40381db7 2183 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2184 /*
2185 * This flag is used for leaked vpn-vrf routes
2186 */
2187 int family = p->family;
2188
2189 if (peer_cap_enhe(peer, afi, safi))
2190 family = AF_INET6;
2191
2192 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2193 zlog_debug(
1defdda8 2194 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2195 __func__, family2str(family));
2196 subgroup_announce_reset_nhop(family, attr);
7b651a32 2197 nh_reset = true;
d62a17ae 2198 }
63696f1d 2199 }
960035b2 2200
63696f1d 2201 /* If IPv6/MP and nexthop does not have any override and happens
2202 * to
2203 * be a link-local address, reset it so that we don't pass along
2204 * the
2205 * source's link-local IPv6 address to recipients who may not be
2206 * on
2207 * the same interface.
2208 */
2209 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2210 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2211 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2212 nh_reset = true;
2213 }
d62a17ae 2214 }
3f9c7369 2215
7b651a32 2216 /*
2217 * When the next hop is set to ourselves, if all multipaths have
2218 * link-bandwidth announce the cumulative bandwidth as that makes
2219 * the most sense. However, don't modify if the link-bandwidth has
2220 * been explicitly set by user policy.
2221 */
2222 if (nh_reset &&
f7e1c681 2223 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2224 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2225 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2226 attr->ecommunity = ecommunity_replace_linkbw(
2227 bgp->as, attr->ecommunity, cum_bw);
2228
3dc339cd 2229 return true;
3f9c7369
DS
2230}
2231
f009ff26 2232static int bgp_route_select_timer_expire(struct thread *thread)
2233{
2234 struct afi_safi_info *info;
2235 afi_t afi;
2236 safi_t safi;
2237 struct bgp *bgp;
2238
2239 info = THREAD_ARG(thread);
2240 afi = info->afi;
2241 safi = info->safi;
2242 bgp = info->bgp;
2243
2244 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2245 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2246 safi);
f009ff26 2247
2248 bgp->gr_info[afi][safi].t_route_select = NULL;
2249
2250 XFREE(MTYPE_TMP, info);
2251
2252 /* Best path selection */
2253 return bgp_best_path_select_defer(bgp, afi, safi);
2254}
2255
9bcb3eef 2256void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2257 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2258 struct bgp_path_info_pair *result, afi_t afi,
2259 safi_t safi)
2260{
2261 struct bgp_path_info *new_select;
2262 struct bgp_path_info *old_select;
40381db7
DS
2263 struct bgp_path_info *pi;
2264 struct bgp_path_info *pi1;
2265 struct bgp_path_info *pi2;
2266 struct bgp_path_info *nextpi = NULL;
d62a17ae 2267 int paths_eq, do_mpath, debug;
2268 struct list mp_list;
2269 char pfx_buf[PREFIX2STR_BUFFER];
2270 char path_buf[PATH_ADDPATH_STR_BUFFER];
2271
2272 bgp_mp_list_init(&mp_list);
2273 do_mpath =
2274 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2275
9bcb3eef 2276 debug = bgp_debug_bestpath(dest);
d62a17ae 2277
2278 if (debug)
9bcb3eef 2279 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2280
9bcb3eef 2281 dest->reason = bgp_path_selection_none;
d62a17ae 2282 /* bgp deterministic-med */
2283 new_select = NULL;
892fedb6 2284 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2285
1defdda8 2286 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2287 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2288 pi1 = pi1->next)
9bcb3eef 2289 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2290 BGP_PATH_DMED_SELECTED);
d62a17ae 2291
9bcb3eef 2292 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2293 pi1 = pi1->next) {
40381db7 2294 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2295 continue;
40381db7 2296 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2297 continue;
ea8b2282 2298 if (pi1->peer != bgp->peer_self)
40381db7 2299 if (pi1->peer->status != Established)
d62a17ae 2300 continue;
2301
40381db7
DS
2302 new_select = pi1;
2303 if (pi1->next) {
2304 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2305 if (CHECK_FLAG(pi2->flags,
1defdda8 2306 BGP_PATH_DMED_CHECK))
d62a17ae 2307 continue;
40381db7 2308 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2309 continue;
ea8b2282 2310 if (pi2->peer != bgp->peer_self
d62a17ae 2311 && !CHECK_FLAG(
ea8b2282
DS
2312 pi2->peer->sflags,
2313 PEER_STATUS_NSF_WAIT))
40381db7 2314 if (pi2->peer->status
d62a17ae 2315 != Established)
2316 continue;
2317
121e245d
DS
2318 if (!aspath_cmp_left(pi1->attr->aspath,
2319 pi2->attr->aspath)
2320 && !aspath_cmp_left_confed(
40381db7 2321 pi1->attr->aspath,
121e245d
DS
2322 pi2->attr->aspath))
2323 continue;
d62a17ae 2324
121e245d
DS
2325 if (bgp_path_info_cmp(
2326 bgp, pi2, new_select,
2327 &paths_eq, mpath_cfg, debug,
fdf81fa0 2328 pfx_buf, afi, safi,
9bcb3eef 2329 &dest->reason)) {
121e245d 2330 bgp_path_info_unset_flag(
9bcb3eef 2331 dest, new_select,
121e245d
DS
2332 BGP_PATH_DMED_SELECTED);
2333 new_select = pi2;
d62a17ae 2334 }
121e245d
DS
2335
2336 bgp_path_info_set_flag(
9bcb3eef 2337 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2338 }
2339 }
9bcb3eef 2340 bgp_path_info_set_flag(dest, new_select,
18ee8310 2341 BGP_PATH_DMED_CHECK);
9bcb3eef 2342 bgp_path_info_set_flag(dest, new_select,
18ee8310 2343 BGP_PATH_DMED_SELECTED);
d62a17ae 2344
2345 if (debug) {
18ee8310
DS
2346 bgp_path_info_path_with_addpath_rx_str(
2347 new_select, path_buf);
8228a9a7
DS
2348 zlog_debug(
2349 "%pBD: %s is the bestpath from AS %u",
2350 dest, path_buf,
2351 aspath_get_first_as(
2352 new_select->attr->aspath));
d62a17ae 2353 }
2354 }
2355 }
96450faf 2356
d62a17ae 2357 /* Check old selected route and new selected route. */
2358 old_select = NULL;
2359 new_select = NULL;
9bcb3eef 2360 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2361 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2362 enum bgp_path_selection_reason reason;
2363
40381db7
DS
2364 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2365 old_select = pi;
d62a17ae 2366
40381db7 2367 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2368 /* reap REMOVED routes, if needs be
2369 * selected route must stay for a while longer though
2370 */
40381db7
DS
2371 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2372 && (pi != old_select))
9bcb3eef 2373 bgp_path_info_reap(dest, pi);
d62a17ae 2374
ddb5b488 2375 if (debug)
40381db7
DS
2376 zlog_debug("%s: pi %p in holddown", __func__,
2377 pi);
ddb5b488 2378
d62a17ae 2379 continue;
2380 }
96450faf 2381
40381db7
DS
2382 if (pi->peer && pi->peer != bgp->peer_self
2383 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2384 if (pi->peer->status != Established) {
ddb5b488
PZ
2385
2386 if (debug)
2387 zlog_debug(
40381db7
DS
2388 "%s: pi %p non self peer %s not estab state",
2389 __func__, pi, pi->peer->host);
ddb5b488 2390
d62a17ae 2391 continue;
ddb5b488 2392 }
9fbdd100 2393
892fedb6 2394 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2395 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2396 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2397 if (debug)
40381db7 2398 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2399 continue;
2400 }
9fbdd100 2401
9bcb3eef 2402 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2403
9bcb3eef 2404 reason = dest->reason;
40381db7 2405 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2406 debug, pfx_buf, afi, safi,
2407 &dest->reason)) {
19ea4cec
DS
2408 if (new_select == NULL &&
2409 reason != bgp_path_selection_none)
9bcb3eef 2410 dest->reason = reason;
40381db7 2411 new_select = pi;
d62a17ae 2412 }
2413 }
718e3744 2414
d62a17ae 2415 /* Now that we know which path is the bestpath see if any of the other
2416 * paths
2417 * qualify as multipaths
2418 */
2419 if (debug) {
2420 if (new_select)
18ee8310
DS
2421 bgp_path_info_path_with_addpath_rx_str(new_select,
2422 path_buf);
d62a17ae 2423 else
772270f3 2424 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2425 zlog_debug(
8228a9a7
DS
2426 "%pBD: After path selection, newbest is %s oldbest was %s",
2427 dest, path_buf,
d62a17ae 2428 old_select ? old_select->peer->host : "NONE");
96450faf 2429 }
9fbdd100 2430
d62a17ae 2431 if (do_mpath && new_select) {
9bcb3eef 2432 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2433 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2434
2435 if (debug)
18ee8310 2436 bgp_path_info_path_with_addpath_rx_str(
40381db7 2437 pi, path_buf);
d62a17ae 2438
40381db7 2439 if (pi == new_select) {
d62a17ae 2440 if (debug)
2441 zlog_debug(
8228a9a7
DS
2442 "%pBD: %s is the bestpath, add to the multipath list",
2443 dest, path_buf);
40381db7 2444 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2445 continue;
2446 }
2447
40381db7 2448 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2449 continue;
2450
40381db7
DS
2451 if (pi->peer && pi->peer != bgp->peer_self
2452 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2453 PEER_STATUS_NSF_WAIT))
40381db7 2454 if (pi->peer->status != Established)
d62a17ae 2455 continue;
2456
40381db7 2457 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2458 if (debug)
2459 zlog_debug(
8228a9a7
DS
2460 "%pBD: %s has the same nexthop as the bestpath, skip it",
2461 dest, path_buf);
d62a17ae 2462 continue;
2463 }
2464
40381db7 2465 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2466 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2467 &dest->reason);
d62a17ae 2468
2469 if (paths_eq) {
2470 if (debug)
2471 zlog_debug(
8228a9a7
DS
2472 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2473 dest, path_buf);
40381db7 2474 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2475 }
2476 }
2477 }
fee0f4c6 2478
9bcb3eef 2479 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2480 mpath_cfg);
2481 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2482 bgp_mp_list_clear(&mp_list);
96450faf 2483
9bcb3eef 2484 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2485
d62a17ae 2486 result->old = old_select;
2487 result->new = new_select;
96450faf 2488
d62a17ae 2489 return;
fee0f4c6 2490}
2491
3f9c7369
DS
2492/*
2493 * A new route/change in bestpath of an existing route. Evaluate the path
2494 * for advertisement to the subgroup.
2495 */
3dc339cd
DA
2496void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2497 struct bgp_path_info *selected,
9bcb3eef 2498 struct bgp_dest *dest,
3dc339cd 2499 uint32_t addpath_tx_id)
d62a17ae 2500{
b54892e0 2501 const struct prefix *p;
d62a17ae 2502 struct peer *onlypeer;
2503 struct attr attr;
2504 afi_t afi;
2505 safi_t safi;
a77e2f4b
S
2506 struct bgp *bgp;
2507 bool advertise;
adbac85e 2508
9bcb3eef 2509 p = bgp_dest_get_prefix(dest);
d62a17ae 2510 afi = SUBGRP_AFI(subgrp);
2511 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2512 bgp = SUBGRP_INST(subgrp);
d62a17ae 2513 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2514 : NULL);
2515
2dbe669b
DA
2516 if (BGP_DEBUG(update, UPDATE_OUT))
2517 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2518
d62a17ae 2519 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2520 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2521 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2522 return;
d62a17ae 2523
2524 memset(&attr, 0, sizeof(struct attr));
2525 /* It's initialized in bgp_announce_check() */
2526
a77e2f4b
S
2527 /* Announcement to the subgroup. If the route is filtered withdraw it.
2528 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2529 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2530 * route
d62a17ae 2531 */
a77e2f4b
S
2532 advertise = bgp_check_advertise(bgp, dest);
2533
d62a17ae 2534 if (selected) {
7f7940e6 2535 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2536 false)) {
2537 /* Route is selected, if the route is already installed
2538 * in FIB, then it is advertised
2539 */
2540 if (advertise)
2541 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2542 selected);
2543 } else
9bcb3eef 2544 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2545 addpath_tx_id);
d62a17ae 2546 }
2547
2548 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2549 else {
9bcb3eef 2550 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2551 }
200df115 2552}
fee0f4c6 2553
3064bf43 2554/*
e1072051 2555 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2556 * This is called at the end of route processing.
3064bf43 2557 */
9bcb3eef 2558void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2559{
40381db7 2560 struct bgp_path_info *pi;
3064bf43 2561
9bcb3eef 2562 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2563 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2564 continue;
40381db7
DS
2565 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2566 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2567 }
3064bf43 2568}
2569
2570/*
2571 * Has the route changed from the RIB's perspective? This is invoked only
2572 * if the route selection returns the same best route as earlier - to
2573 * determine if we need to update zebra or not.
2574 */
9bcb3eef 2575bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2576{
4b7e6066 2577 struct bgp_path_info *mpinfo;
d62a17ae 2578
2bb9eff4
DS
2579 /* If this is multipath, check all selected paths for any nexthop
2580 * change or attribute change. Some attribute changes (e.g., community)
2581 * aren't of relevance to the RIB, but we'll update zebra to ensure
2582 * we handle the case of BGP nexthop change. This is the behavior
2583 * when the best path has an attribute change anyway.
d62a17ae 2584 */
1defdda8 2585 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2586 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2587 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2588 return true;
d62a17ae 2589
2bb9eff4
DS
2590 /*
2591 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2592 */
18ee8310
DS
2593 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2594 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2595 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2596 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2597 return true;
d62a17ae 2598 }
3064bf43 2599
d62a17ae 2600 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2601 return false;
3064bf43 2602}
2603
d62a17ae 2604struct bgp_process_queue {
2605 struct bgp *bgp;
9bcb3eef 2606 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2607#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2608 unsigned int flags;
2609 unsigned int queued;
200df115 2610};
2611
3b0c17e1 2612static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2613 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2614 struct bgp_path_info *new_select,
2615 struct bgp_path_info *old_select)
2616{
9bcb3eef 2617 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2618
2619 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2620 return;
2621
2622 if (advertise_type5_routes(bgp, afi) && new_select
2623 && is_route_injectable_into_evpn(new_select)) {
2624
2625 /* apply the route-map */
2626 if (bgp->adv_cmd_rmap[afi][safi].map) {
2627 route_map_result_t ret;
2628 struct bgp_path_info rmap_path;
2629 struct bgp_path_info_extra rmap_path_extra;
2630 struct attr dummy_attr;
2631
2632 dummy_attr = *new_select->attr;
2633
2634 /* Fill temp path_info */
9bcb3eef 2635 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2636 new_select, new_select->peer,
2637 &dummy_attr);
2638
2639 RESET_FLAG(dummy_attr.rmap_change_flags);
2640
2641 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2642 p, &rmap_path);
3b0c17e1 2643
2644 if (ret == RMAP_DENYMATCH) {
2645 bgp_attr_flush(&dummy_attr);
2646 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2647 safi);
2648 } else
2649 bgp_evpn_advertise_type5_route(
2650 bgp, p, &dummy_attr, afi, safi);
2651 } else {
2652 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2653 afi, safi);
2654 }
2655 } else if (advertise_type5_routes(bgp, afi) && old_select
2656 && is_route_injectable_into_evpn(old_select))
2657 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2658}
2659
3103e8d2
DS
2660/*
2661 * old_select = The old best path
2662 * new_select = the new best path
2663 *
2664 * if (!old_select && new_select)
2665 * We are sending new information on.
2666 *
2667 * if (old_select && new_select) {
2668 * if (new_select != old_select)
2669 * We have a new best path send a change
2670 * else
2671 * We've received a update with new attributes that needs
2672 * to be passed on.
2673 * }
2674 *
2675 * if (old_select && !new_select)
2676 * We have no eligible route that we can announce or the rn
2677 * is being removed.
2678 */
9bcb3eef 2679static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2680 afi_t afi, safi_t safi)
d62a17ae 2681{
4b7e6066
DS
2682 struct bgp_path_info *new_select;
2683 struct bgp_path_info *old_select;
2684 struct bgp_path_info_pair old_and_new;
ddb5b488 2685 int debug = 0;
d62a17ae 2686
892fedb6 2687 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2688 if (dest)
2689 debug = bgp_debug_bestpath(dest);
b54892e0 2690 if (debug)
f4c713ae 2691 zlog_debug(
56ca3b5b 2692 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2693 __func__, dest);
f4c713ae
LB
2694 return;
2695 }
d62a17ae 2696 /* Is it end of initial update? (after startup) */
9bcb3eef 2697 if (!dest) {
d62a17ae 2698 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2699 sizeof(bgp->update_delay_zebra_resume_time));
2700
2701 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2702 FOREACH_AFI_SAFI (afi, safi) {
2703 if (bgp_fibupd_safi(safi))
2704 bgp_zebra_announce_table(bgp, afi, safi);
2705 }
d62a17ae 2706 bgp->main_peers_update_hold = 0;
2707
2708 bgp_start_routeadv(bgp);
aac24838 2709 return;
d62a17ae 2710 }
cb1faec9 2711
9bcb3eef 2712 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2713
9bcb3eef 2714 debug = bgp_debug_bestpath(dest);
b54892e0 2715 if (debug)
56ca3b5b 2716 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2717 afi2str(afi), safi2str(safi));
ddb5b488 2718
f009ff26 2719 /* The best path calculation for the route is deferred if
2720 * BGP_NODE_SELECT_DEFER is set
2721 */
9bcb3eef 2722 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2723 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2724 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2725 return;
2726 }
2727
d62a17ae 2728 /* Best path selection. */
9bcb3eef 2729 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2730 afi, safi);
2731 old_select = old_and_new.old;
2732 new_select = old_and_new.new;
2733
2734 /* Do we need to allocate or free labels?
2735 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2736 * necessary to do this upon changes to best path. Exceptions:
2737 * - label index has changed -> recalculate resulting label
2738 * - path_info sub_type changed -> switch to/from implicit-null
2739 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2740 */
318cac96 2741 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2742 if (new_select) {
2743 if (!old_select
2744 || bgp_label_index_differs(new_select, old_select)
57592a53 2745 || new_select->sub_type != old_select->sub_type
9bcb3eef 2746 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2747 /* Enforced penultimate hop popping:
2748 * implicit-null for local routes, aggregate
2749 * and redistributed routes
2750 */
d62a17ae 2751 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2752 || new_select->sub_type
2753 == BGP_ROUTE_AGGREGATE
2754 || new_select->sub_type
2755 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2756 if (CHECK_FLAG(
9bcb3eef 2757 dest->flags,
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) {
96f3485c
MK
11742 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11743 continue;
11744
11745 if (uj) {
11746 if (first)
11747 first = false;
11748 else
11749 vty_out(vty, ",\n");
11750 vty_out(vty, "\"%s\":{\n",
11751 get_afi_safi_str(afi, safi,
11752 true));
11753 } else
11754 vty_out(vty,
11755 "\nFor address family: %s\n",
11756 get_afi_safi_str(afi, safi,
11757 false));
11758
11759 if (community)
11760 bgp_show_community(vty, bgp, community,
11761 exact_match, afi,
11762 safi, show_flags);
11763 else
11764 bgp_show(vty, bgp, afi, safi, sh_type,
11765 NULL, show_flags);
11766 if (uj)
11767 vty_out(vty, "}\n");
11768 }
11769 } else {
11770 /* show <ip> bgp all: for each AFI and SAFI*/
11771 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
11772 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11773 continue;
11774
11775 if (uj) {
11776 if (first)
11777 first = false;
11778 else
11779 vty_out(vty, ",\n");
d0086e8e 11780
96f3485c
MK
11781 vty_out(vty, "\"%s\":{\n",
11782 get_afi_safi_str(afi, safi,
11783 true));
11784 } else
11785 vty_out(vty,
11786 "\nFor address family: %s\n",
11787 get_afi_safi_str(afi, safi,
11788 false));
11789
11790 if (community)
11791 bgp_show_community(vty, bgp, community,
11792 exact_match, afi,
11793 safi, show_flags);
11794 else
11795 bgp_show(vty, bgp, afi, safi, sh_type,
11796 NULL, show_flags);
11797 if (uj)
11798 vty_out(vty, "}\n");
11799 }
11800 }
11801 if (uj)
11802 vty_out(vty, "}\n");
11803 }
11804 return CMD_SUCCESS;
a636c635 11805}
47fc97cc 11806
718e3744 11807DEFUN (show_ip_bgp_route,
11808 show_ip_bgp_route_cmd,
3efd0893 11809 "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 11810 SHOW_STR
11811 IP_STR
11812 BGP_STR
a636c635 11813 BGP_INSTANCE_HELP_STR
4f280b15 11814 BGP_AFI_HELP_STR
4dd6177e 11815 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11816 "Network in the BGP routing table to display\n"
0c7b1b01 11817 "IPv4 prefix\n"
8c3deaae 11818 "Network in the BGP routing table to display\n"
0c7b1b01 11819 "IPv6 prefix\n"
4092b06c 11820 "Display only the bestpath\n"
b05a1c8b 11821 "Display only multipaths\n"
9973d184 11822 JSON_STR)
4092b06c 11823{
d62a17ae 11824 int prefix_check = 0;
ae19d7dd 11825
d62a17ae 11826 afi_t afi = AFI_IP6;
11827 safi_t safi = SAFI_UNICAST;
11828 char *prefix = NULL;
11829 struct bgp *bgp = NULL;
11830 enum bgp_path_type path_type;
9f049418 11831 bool uj = use_json(argc, argv);
b05a1c8b 11832
d62a17ae 11833 int idx = 0;
ae19d7dd 11834
d62a17ae 11835 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11836 &bgp, uj);
d62a17ae 11837 if (!idx)
11838 return CMD_WARNING;
c41247f5 11839
d62a17ae 11840 if (!bgp) {
11841 vty_out(vty,
11842 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11843 return CMD_WARNING;
11844 }
a636c635 11845
d62a17ae 11846 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11847 if (argv_find(argv, argc, "A.B.C.D", &idx)
11848 || argv_find(argv, argc, "X:X::X:X", &idx))
11849 prefix_check = 0;
11850 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11851 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11852 prefix_check = 1;
11853
11854 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11855 && afi != AFI_IP6) {
11856 vty_out(vty,
11857 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11858 return CMD_WARNING;
11859 }
11860 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11861 && afi != AFI_IP) {
11862 vty_out(vty,
11863 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11864 return CMD_WARNING;
11865 }
11866
11867 prefix = argv[idx]->arg;
11868
11869 /* [<bestpath|multipath>] */
11870 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11871 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11872 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11873 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11874 else
360660c6 11875 path_type = BGP_PATH_SHOW_ALL;
a636c635 11876
d62a17ae 11877 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11878 path_type, uj);
4092b06c
DS
11879}
11880
8c3deaae
QY
11881DEFUN (show_ip_bgp_regexp,
11882 show_ip_bgp_regexp_cmd,
3e5b31b3 11883 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11884 SHOW_STR
11885 IP_STR
11886 BGP_STR
b00b230a 11887 BGP_INSTANCE_HELP_STR
4f280b15 11888 BGP_AFI_HELP_STR
4dd6177e 11889 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11890 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11891 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11892 JSON_STR)
8c3deaae 11893{
d62a17ae 11894 afi_t afi = AFI_IP6;
11895 safi_t safi = SAFI_UNICAST;
11896 struct bgp *bgp = NULL;
3e5b31b3
DA
11897 bool uj = use_json(argc, argv);
11898 char *regstr = NULL;
8c3deaae 11899
d62a17ae 11900 int idx = 0;
11901 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11902 &bgp, false);
d62a17ae 11903 if (!idx)
11904 return CMD_WARNING;
8c3deaae 11905
d62a17ae 11906 // get index of regex
3e5b31b3
DA
11907 if (argv_find(argv, argc, "REGEX", &idx))
11908 regstr = argv[idx]->arg;
8c3deaae 11909
5f71d11c 11910 assert(regstr);
3e5b31b3
DA
11911 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11912 bgp_show_type_regexp, uj);
8c3deaae
QY
11913}
11914
ae248832 11915DEFPY (show_ip_bgp_instance_all,
a636c635 11916 show_ip_bgp_instance_all_cmd,
ae248832 11917 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11918 SHOW_STR
a636c635 11919 IP_STR
4092b06c 11920 BGP_STR
a636c635 11921 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11922 BGP_AFI_HELP_STR
4dd6177e 11923 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11924 JSON_STR
11925 "Increase table width for longer prefixes\n")
4092b06c 11926{
d62a17ae 11927 afi_t afi = AFI_IP;
11928 safi_t safi = SAFI_UNICAST;
11929 struct bgp *bgp = NULL;
d62a17ae 11930 int idx = 0;
96f3485c 11931 uint8_t show_flags = 0;
ae19d7dd 11932
96f3485c 11933 if (uj) {
d62a17ae 11934 argc--;
96f3485c
MK
11935 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11936 }
11937
11938 if (wide)
11939 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11940
9f049418
DS
11941 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11942 &bgp, uj);
11943 if (!idx)
11944 return CMD_WARNING;
11945
96f3485c 11946 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11947 return CMD_SUCCESS;
e3e29b32
LB
11948}
11949
a4d82a8a 11950static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11951 afi_t afi, safi_t safi, enum bgp_show_type type,
11952 bool use_json)
718e3744 11953{
d62a17ae 11954 regex_t *regex;
11955 int rc;
96f3485c
MK
11956 uint8_t show_flags = 0;
11957
11958 if (use_json)
11959 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11960
c3900853 11961 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11962 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11963 regstr);
11964 return CMD_WARNING_CONFIG_FAILED;
11965 }
11966
d62a17ae 11967 regex = bgp_regcomp(regstr);
11968 if (!regex) {
11969 vty_out(vty, "Can't compile regexp %s\n", regstr);
11970 return CMD_WARNING;
11971 }
a636c635 11972
96f3485c 11973 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11974 bgp_regex_free(regex);
11975 return rc;
e3e29b32
LB
11976}
11977
d62a17ae 11978static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11979 const char *prefix_list_str, afi_t afi,
11980 safi_t safi, enum bgp_show_type type)
e3e29b32 11981{
d62a17ae 11982 struct prefix_list *plist;
96f3485c 11983 uint8_t show_flags = 0;
718e3744 11984
d62a17ae 11985 plist = prefix_list_lookup(afi, prefix_list_str);
11986 if (plist == NULL) {
11987 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11988 prefix_list_str);
11989 return CMD_WARNING;
11990 }
718e3744 11991
96f3485c 11992 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
11993}
11994
d62a17ae 11995static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11996 const char *filter, afi_t afi, safi_t safi,
11997 enum bgp_show_type type)
4092b06c 11998{
d62a17ae 11999 struct as_list *as_list;
96f3485c 12000 uint8_t show_flags = 0;
718e3744 12001
d62a17ae 12002 as_list = as_list_lookup(filter);
12003 if (as_list == NULL) {
12004 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12005 filter);
12006 return CMD_WARNING;
12007 }
a636c635 12008
96f3485c 12009 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12010}
12011
d62a17ae 12012static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12013 const char *rmap_str, afi_t afi, safi_t safi,
12014 enum bgp_show_type type)
718e3744 12015{
d62a17ae 12016 struct route_map *rmap;
96f3485c 12017 uint8_t show_flags = 0;
bb46e94f 12018
d62a17ae 12019 rmap = route_map_lookup_by_name(rmap_str);
12020 if (!rmap) {
12021 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12022 return CMD_WARNING;
12023 }
12024
96f3485c 12025 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12026}
12027
7f323236
DW
12028static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12029 const char *comstr, int exact, afi_t afi,
96f3485c 12030 safi_t safi, uint8_t show_flags)
d62a17ae 12031{
12032 struct community *com;
d62a17ae 12033 int ret = 0;
12034
7f323236 12035 com = community_str2com(comstr);
d62a17ae 12036 if (!com) {
7f323236 12037 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12038 return CMD_WARNING;
12039 }
12040
12041 ret = bgp_show(vty, bgp, afi, safi,
12042 (exact ? bgp_show_type_community_exact
12043 : bgp_show_type_community),
96f3485c 12044 com, show_flags);
3c1f53de 12045 community_free(&com);
46c3ce83 12046
d62a17ae 12047 return ret;
718e3744 12048}
12049
d62a17ae 12050static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12051 const char *com, int exact, afi_t afi,
12052 safi_t safi)
50ef26d4 12053{
d62a17ae 12054 struct community_list *list;
96f3485c 12055 uint8_t show_flags = 0;
50ef26d4 12056
e237b0d2 12057 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12058 if (list == NULL) {
12059 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12060 return CMD_WARNING;
12061 }
718e3744 12062
d62a17ae 12063 return bgp_show(vty, bgp, afi, safi,
12064 (exact ? bgp_show_type_community_list_exact
12065 : bgp_show_type_community_list),
96f3485c 12066 list, show_flags);
50ef26d4 12067}
12068
d62a17ae 12069static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12070 const char *prefix, afi_t afi, safi_t safi,
12071 enum bgp_show_type type)
718e3744 12072{
d62a17ae 12073 int ret;
12074 struct prefix *p;
96f3485c 12075 uint8_t show_flags = 0;
47fc97cc 12076
d62a17ae 12077 p = prefix_new();
95cbbd2a 12078
d62a17ae 12079 ret = str2prefix(prefix, p);
12080 if (!ret) {
12081 vty_out(vty, "%% Malformed Prefix\n");
12082 return CMD_WARNING;
12083 }
47e9b292 12084
96f3485c 12085 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12086 prefix_free(&p);
d62a17ae 12087 return ret;
12088}
12089
d62a17ae 12090enum bgp_stats {
12091 BGP_STATS_MAXBITLEN = 0,
12092 BGP_STATS_RIB,
12093 BGP_STATS_PREFIXES,
12094 BGP_STATS_TOTPLEN,
12095 BGP_STATS_UNAGGREGATEABLE,
12096 BGP_STATS_MAX_AGGREGATEABLE,
12097 BGP_STATS_AGGREGATES,
12098 BGP_STATS_SPACE,
12099 BGP_STATS_ASPATH_COUNT,
12100 BGP_STATS_ASPATH_MAXHOPS,
12101 BGP_STATS_ASPATH_TOTHOPS,
12102 BGP_STATS_ASPATH_MAXSIZE,
12103 BGP_STATS_ASPATH_TOTSIZE,
12104 BGP_STATS_ASN_HIGHEST,
12105 BGP_STATS_MAX,
a636c635 12106};
2815e61f 12107
9ab0cf58 12108#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12109#define TABLE_STATS_IDX_JSON 1
12110
12111static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12112 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12113 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12114 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12115 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12116 "unaggregateablePrefixes"},
12117 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12118 "maximumAggregateablePrefixes"},
12119 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12120 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12121 [BGP_STATS_SPACE] = {"Address space advertised",
12122 "addressSpaceAdvertised"},
9ab0cf58
PG
12123 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12124 "advertisementsWithPaths"},
12125 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12126 "longestAsPath"},
12127 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12128 "largestAsPath"},
12129 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12130 "averageAsPathLengthHops"},
12131 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12132 "averageAsPathSizeBytes"},
12133 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12134 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12135};
2815e61f 12136
d62a17ae 12137struct bgp_table_stats {
12138 struct bgp_table *table;
12139 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12140 double total_space;
ff7924f6
PJ
12141};
12142
a636c635
DW
12143#if 0
12144#define TALLY_SIGFIG 100000
12145static unsigned long
12146ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12147{
a636c635
DW
12148 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12149 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12150 unsigned long ret = newtot / count;
07d0c4ed 12151
a636c635
DW
12152 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12153 return ret + 1;
12154 else
12155 return ret;
12156}
12157#endif
ff7924f6 12158
9bcb3eef 12159static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12160 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12161{
9bcb3eef 12162 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12163 struct bgp_path_info *pi;
b54892e0 12164 const struct prefix *rn_p;
d62a17ae 12165
9bcb3eef 12166 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12167 return;
d62a17ae 12168
9bcb3eef 12169 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12170 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12171 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12172
a636c635
DW
12173#if 0
12174 ts->counts[BGP_STATS_AVGPLEN]
12175 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12176 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12177 rn_p->prefixlen);
a636c635 12178#endif
d62a17ae 12179
9c14ec72 12180 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12181 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12182 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12183
9bcb3eef 12184 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12185 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12186 /* announced address space */
12187 if (space)
b54892e0 12188 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12189 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12190 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12191
9c14ec72 12192
9bcb3eef 12193 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12194 ts->counts[BGP_STATS_RIB]++;
12195
05864da7
DS
12196 if (CHECK_FLAG(pi->attr->flag,
12197 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12198 ts->counts[BGP_STATS_AGGREGATES]++;
12199
12200 /* as-path stats */
05864da7 12201 if (pi->attr->aspath) {
9c14ec72
RW
12202 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12203 unsigned int size = aspath_size(pi->attr->aspath);
12204 as_t highest = aspath_highest(pi->attr->aspath);
12205
12206 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12207
12208 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12209 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12210
12211 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12212 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12213
12214 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12215 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12216#if 0
07d0c4ed 12217 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12218 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12219 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12220 hops);
12221 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12222 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12223 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12224 size);
12225#endif
9c14ec72
RW
12226 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12227 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12228 }
12229 }
12230}
12231
12232static int bgp_table_stats_walker(struct thread *t)
12233{
9bcb3eef
DS
12234 struct bgp_dest *dest, *ndest;
12235 struct bgp_dest *top;
9c14ec72
RW
12236 struct bgp_table_stats *ts = THREAD_ARG(t);
12237 unsigned int space = 0;
12238
12239 if (!(top = bgp_table_top(ts->table)))
12240 return 0;
12241
12242 switch (ts->table->afi) {
12243 case AFI_IP:
12244 space = IPV4_MAX_BITLEN;
12245 break;
12246 case AFI_IP6:
12247 space = IPV6_MAX_BITLEN;
12248 break;
12249 default:
12250 return 0;
12251 }
12252
12253 ts->counts[BGP_STATS_MAXBITLEN] = space;
12254
9bcb3eef 12255 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12256 if (ts->table->safi == SAFI_MPLS_VPN
12257 || ts->table->safi == SAFI_ENCAP
12258 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12259 struct bgp_table *table;
12260
9bcb3eef 12261 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12262 if (!table)
12263 continue;
12264
12265 top = bgp_table_top(table);
9bcb3eef
DS
12266 for (ndest = bgp_table_top(table); ndest;
12267 ndest = bgp_route_next(ndest))
12268 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12269 } else {
9bcb3eef 12270 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12271 }
12272 }
9c14ec72 12273
d62a17ae 12274 return 0;
2815e61f 12275}
ff7924f6 12276
71f1613a
DA
12277static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12278 struct json_object *json_array)
12279{
12280 struct listnode *node, *nnode;
12281 struct bgp *bgp;
12282
12283 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12284 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12285}
12286
12287static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12288 safi_t safi, struct json_object *json_array)
2815e61f 12289{
d62a17ae 12290 struct bgp_table_stats ts;
12291 unsigned int i;
893cccd0
PG
12292 int ret = CMD_SUCCESS;
12293 char temp_buf[20];
6c9d22e2
PG
12294 struct json_object *json = NULL;
12295
12296 if (json_array)
12297 json = json_object_new_object();
019386c2 12298
d62a17ae 12299 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12300 char warning_msg[50];
12301
12302 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12303 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12304 safi);
6c9d22e2
PG
12305
12306 if (!json)
893cccd0
PG
12307 vty_out(vty, "%s\n", warning_msg);
12308 else
9ab0cf58 12309 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12310
893cccd0
PG
12311 ret = CMD_WARNING;
12312 goto end_table_stats;
d62a17ae 12313 }
019386c2 12314
893cccd0 12315 if (!json)
5290ceab
DA
12316 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12317 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12318 else
12319 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12320
d62a17ae 12321 /* labeled-unicast routes live in the unicast table */
12322 if (safi == SAFI_LABELED_UNICAST)
12323 safi = SAFI_UNICAST;
019386c2 12324
d62a17ae 12325 memset(&ts, 0, sizeof(ts));
12326 ts.table = bgp->rib[afi][safi];
12327 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12328
d62a17ae 12329 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12330 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12331 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12332 continue;
12333
12334 switch (i) {
a636c635
DW
12335#if 0
12336 case BGP_STATS_ASPATH_AVGHOPS:
12337 case BGP_STATS_ASPATH_AVGSIZE:
12338 case BGP_STATS_AVGPLEN:
12339 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12340 vty_out (vty, "%12.2f",
12341 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12342 break;
12343#endif
d62a17ae 12344 case BGP_STATS_ASPATH_TOTHOPS:
12345 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12346 if (!json) {
9ab0cf58
PG
12347 snprintf(
12348 temp_buf, sizeof(temp_buf), "%12.2f",
12349 ts.counts[i]
12350 ? (float)ts.counts[i]
12351 / (float)ts.counts
12352 [BGP_STATS_ASPATH_COUNT]
12353 : 0);
893cccd0 12354 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12355 table_stats_strs[i]
12356 [TABLE_STATS_IDX_VTY],
893cccd0 12357 temp_buf);
9ab0cf58
PG
12358 } else {
12359 json_object_double_add(
12360 json,
12361 table_stats_strs[i]
12362 [TABLE_STATS_IDX_JSON],
12363 ts.counts[i]
12364 ? (double)ts.counts[i]
12365 / (double)ts.counts
d62a17ae 12366 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12367 : 0);
12368 }
d62a17ae 12369 break;
12370 case BGP_STATS_TOTPLEN:
6c9d22e2 12371 if (!json) {
9ab0cf58
PG
12372 snprintf(
12373 temp_buf, sizeof(temp_buf), "%12.2f",
12374 ts.counts[i]
12375 ? (float)ts.counts[i]
12376 / (float)ts.counts
12377 [BGP_STATS_PREFIXES]
12378 : 0);
893cccd0 12379 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12380 table_stats_strs[i]
12381 [TABLE_STATS_IDX_VTY],
893cccd0 12382 temp_buf);
9ab0cf58
PG
12383 } else {
12384 json_object_double_add(
12385 json,
12386 table_stats_strs[i]
12387 [TABLE_STATS_IDX_JSON],
12388 ts.counts[i]
12389 ? (double)ts.counts[i]
12390 / (double)ts.counts
d62a17ae 12391 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12392 : 0);
12393 }
d62a17ae 12394 break;
12395 case BGP_STATS_SPACE:
6c9d22e2
PG
12396 if (!json) {
12397 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12398 ts.total_space);
893cccd0 12399 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12400 table_stats_strs[i]
12401 [TABLE_STATS_IDX_VTY],
893cccd0 12402 temp_buf);
9ab0cf58
PG
12403 } else {
12404 json_object_double_add(
12405 json,
12406 table_stats_strs[i]
12407 [TABLE_STATS_IDX_JSON],
12408 (double)ts.total_space);
12409 }
8d0ab76d 12410 if (afi == AFI_IP6) {
6c9d22e2
PG
12411 if (!json) {
12412 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12413 "%12g",
12414 ts.total_space
12415 * pow(2.0, -128 + 32));
6c9d22e2
PG
12416 vty_out(vty, "%30s: %s\n",
12417 "/32 equivalent %s\n",
12418 temp_buf);
9ab0cf58
PG
12419 } else {
12420 json_object_double_add(
12421 json, "/32equivalent",
12422 (double)(ts.total_space
12423 * pow(2.0,
12424 -128 + 32)));
12425 }
6c9d22e2
PG
12426 if (!json) {
12427 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12428 "%12g",
12429 ts.total_space
12430 * pow(2.0, -128 + 48));
6c9d22e2
PG
12431 vty_out(vty, "%30s: %s\n",
12432 "/48 equivalent %s\n",
12433 temp_buf);
9ab0cf58
PG
12434 } else {
12435 json_object_double_add(
12436 json, "/48equivalent",
12437 (double)(ts.total_space
12438 * pow(2.0,
12439 -128 + 48)));
12440 }
8d0ab76d 12441 } else {
6c9d22e2
PG
12442 if (!json) {
12443 snprintf(temp_buf, sizeof(temp_buf),
12444 "%12.2f",
9ab0cf58
PG
12445 ts.total_space * 100.
12446 * pow(2.0, -32));
6c9d22e2 12447 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12448 "% announced ", temp_buf);
12449 } else {
12450 json_object_double_add(
12451 json, "%announced",
12452 (double)(ts.total_space * 100.
12453 * pow(2.0, -32)));
12454 }
6c9d22e2
PG
12455 if (!json) {
12456 snprintf(temp_buf, sizeof(temp_buf),
12457 "%12.2f",
9ab0cf58
PG
12458 ts.total_space
12459 * pow(2.0, -32 + 8));
6c9d22e2
PG
12460 vty_out(vty, "%30s: %s\n",
12461 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12462 } else {
12463 json_object_double_add(
12464 json, "/8equivalent",
12465 (double)(ts.total_space
12466 * pow(2.0, -32 + 8)));
12467 }
6c9d22e2
PG
12468 if (!json) {
12469 snprintf(temp_buf, sizeof(temp_buf),
12470 "%12.2f",
9ab0cf58
PG
12471 ts.total_space
12472 * pow(2.0, -32 + 24));
6c9d22e2 12473 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12474 "/24 equivalent ", temp_buf);
12475 } else {
12476 json_object_double_add(
12477 json, "/24equivalent",
12478 (double)(ts.total_space
12479 * pow(2.0, -32 + 24)));
12480 }
8d0ab76d 12481 }
d62a17ae 12482 break;
12483 default:
6c9d22e2
PG
12484 if (!json) {
12485 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12486 ts.counts[i]);
893cccd0 12487 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12488 table_stats_strs[i]
12489 [TABLE_STATS_IDX_VTY],
12490 temp_buf);
12491 } else {
12492 json_object_int_add(
12493 json,
12494 table_stats_strs[i]
12495 [TABLE_STATS_IDX_JSON],
12496 ts.counts[i]);
12497 }
d62a17ae 12498 }
893cccd0
PG
12499 if (!json)
12500 vty_out(vty, "\n");
d62a17ae 12501 }
9ab0cf58 12502end_table_stats:
6c9d22e2
PG
12503 if (json)
12504 json_object_array_add(json_array, json);
893cccd0 12505 return ret;
d62a17ae 12506}
12507
71f1613a
DA
12508static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12509 safi_t safi, struct json_object *json_array)
12510{
12511 if (!bgp) {
12512 bgp_table_stats_all(vty, afi, safi, json_array);
12513 return CMD_SUCCESS;
12514 }
12515
12516 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12517}
12518
d62a17ae 12519enum bgp_pcounts {
12520 PCOUNT_ADJ_IN = 0,
12521 PCOUNT_DAMPED,
12522 PCOUNT_REMOVED,
12523 PCOUNT_HISTORY,
12524 PCOUNT_STALE,
12525 PCOUNT_VALID,
12526 PCOUNT_ALL,
12527 PCOUNT_COUNTED,
7e3d9632 12528 PCOUNT_BPATH_SELECTED,
d62a17ae 12529 PCOUNT_PFCNT, /* the figure we display to users */
12530 PCOUNT_MAX,
a636c635 12531};
718e3744 12532
2b64873d 12533static const char *const pcount_strs[] = {
9d303b37
DL
12534 [PCOUNT_ADJ_IN] = "Adj-in",
12535 [PCOUNT_DAMPED] = "Damped",
12536 [PCOUNT_REMOVED] = "Removed",
12537 [PCOUNT_HISTORY] = "History",
12538 [PCOUNT_STALE] = "Stale",
12539 [PCOUNT_VALID] = "Valid",
12540 [PCOUNT_ALL] = "All RIB",
12541 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12542 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12543 [PCOUNT_PFCNT] = "Useable",
12544 [PCOUNT_MAX] = NULL,
a636c635 12545};
718e3744 12546
d62a17ae 12547struct peer_pcounts {
12548 unsigned int count[PCOUNT_MAX];
12549 const struct peer *peer;
12550 const struct bgp_table *table;
54317cba 12551 safi_t safi;
a636c635 12552};
47fc97cc 12553
9bcb3eef 12554static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12555{
54317cba
JW
12556 const struct bgp_adj_in *ain;
12557 const struct bgp_path_info *pi;
d62a17ae 12558 const struct peer *peer = pc->peer;
12559
54317cba
JW
12560 for (ain = rn->adj_in; ain; ain = ain->next)
12561 if (ain->peer == peer)
12562 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12563
9bcb3eef 12564 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12565
54317cba
JW
12566 if (pi->peer != peer)
12567 continue;
d62a17ae 12568
54317cba 12569 pc->count[PCOUNT_ALL]++;
d62a17ae 12570
54317cba
JW
12571 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12572 pc->count[PCOUNT_DAMPED]++;
12573 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12574 pc->count[PCOUNT_HISTORY]++;
12575 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12576 pc->count[PCOUNT_REMOVED]++;
12577 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12578 pc->count[PCOUNT_STALE]++;
12579 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12580 pc->count[PCOUNT_VALID]++;
12581 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12582 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12583 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12584 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12585
12586 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12587 pc->count[PCOUNT_COUNTED]++;
12588 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12589 flog_err(
12590 EC_LIB_DEVELOPMENT,
12591 "Attempting to count but flags say it is unusable");
12592 } else {
40381db7 12593 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12594 flog_err(
12595 EC_LIB_DEVELOPMENT,
12596 "Not counted but flags say we should");
d62a17ae 12597 }
12598 }
54317cba
JW
12599}
12600
12601static int bgp_peer_count_walker(struct thread *t)
12602{
9bcb3eef 12603 struct bgp_dest *rn, *rm;
54317cba
JW
12604 const struct bgp_table *table;
12605 struct peer_pcounts *pc = THREAD_ARG(t);
12606
12607 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12608 || pc->safi == SAFI_EVPN) {
12609 /* Special handling for 2-level routing tables. */
12610 for (rn = bgp_table_top(pc->table); rn;
12611 rn = bgp_route_next(rn)) {
9bcb3eef 12612 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12613 if (table != NULL)
12614 for (rm = bgp_table_top(table); rm;
12615 rm = bgp_route_next(rm))
12616 bgp_peer_count_proc(rm, pc);
12617 }
12618 } else
12619 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12620 bgp_peer_count_proc(rn, pc);
12621
d62a17ae 12622 return 0;
718e3744 12623}
12624
d62a17ae 12625static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12626 safi_t safi, bool use_json)
856ca177 12627{
d62a17ae 12628 struct peer_pcounts pcounts = {.peer = peer};
12629 unsigned int i;
12630 json_object *json = NULL;
12631 json_object *json_loop = NULL;
856ca177 12632
d62a17ae 12633 if (use_json) {
12634 json = json_object_new_object();
12635 json_loop = json_object_new_object();
12636 }
718e3744 12637
d62a17ae 12638 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12639 || !peer->bgp->rib[afi][safi]) {
12640 if (use_json) {
12641 json_object_string_add(
12642 json, "warning",
12643 "No such neighbor or address family");
12644 vty_out(vty, "%s\n", json_object_to_json_string(json));
12645 json_object_free(json);
12646 } else
12647 vty_out(vty, "%% No such neighbor or address family\n");
12648
12649 return CMD_WARNING;
12650 }
2a71e9ce 12651
d62a17ae 12652 memset(&pcounts, 0, sizeof(pcounts));
12653 pcounts.peer = peer;
12654 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12655 pcounts.safi = safi;
d62a17ae 12656
12657 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12658 * stats for the thread-walk (i.e. ensure this can't be blamed on
12659 * on just vty_read()).
12660 */
d62a17ae 12661 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12662
12663 if (use_json) {
12664 json_object_string_add(json, "prefixCountsFor", peer->host);
12665 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12666 get_afi_safi_str(afi, safi, true));
d62a17ae 12667 json_object_int_add(json, "pfxCounter",
12668 peer->pcount[afi][safi]);
12669
12670 for (i = 0; i < PCOUNT_MAX; i++)
12671 json_object_int_add(json_loop, pcount_strs[i],
12672 pcounts.count[i]);
12673
12674 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12675
12676 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12677 json_object_string_add(json, "pfxctDriftFor",
12678 peer->host);
12679 json_object_string_add(
12680 json, "recommended",
12681 "Please report this bug, with the above command output");
12682 }
996c9314
LB
12683 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12684 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12685 json_object_free(json);
12686 } else {
12687
12688 if (peer->hostname
892fedb6 12689 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12690 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12691 peer->hostname, peer->host,
5cb5f4d0 12692 get_afi_safi_str(afi, safi, false));
d62a17ae 12693 } else {
12694 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12695 get_afi_safi_str(afi, safi, false));
d62a17ae 12696 }
12697
6cde4b45 12698 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12699 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12700
12701 for (i = 0; i < PCOUNT_MAX; i++)
12702 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12703 pcounts.count[i]);
12704
12705 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12706 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12707 vty_out(vty,
12708 "Please report this bug, with the above command output\n");
12709 }
12710 }
12711
12712 return CMD_SUCCESS;
718e3744 12713}
12714
a636c635
DW
12715DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12716 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12717 "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 12718 SHOW_STR
12719 IP_STR
12720 BGP_STR
8386ac43 12721 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12722 BGP_AFI_HELP_STR
12723 BGP_SAFI_HELP_STR
0b16f239
DS
12724 "Detailed information on TCP and BGP neighbor connections\n"
12725 "Neighbor to display information about\n"
12726 "Neighbor to display information about\n"
91d37724 12727 "Neighbor on BGP configured interface\n"
a636c635 12728 "Display detailed prefix count information\n"
9973d184 12729 JSON_STR)
0b16f239 12730{
d62a17ae 12731 afi_t afi = AFI_IP6;
12732 safi_t safi = SAFI_UNICAST;
12733 struct peer *peer;
12734 int idx = 0;
12735 struct bgp *bgp = NULL;
9f049418
DS
12736 bool uj = use_json(argc, argv);
12737
12738 if (uj)
12739 argc--;
856ca177 12740
d62a17ae 12741 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12742 &bgp, uj);
d62a17ae 12743 if (!idx)
12744 return CMD_WARNING;
0b16f239 12745
d62a17ae 12746 argv_find(argv, argc, "neighbors", &idx);
12747 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12748 if (!peer)
12749 return CMD_WARNING;
bb46e94f 12750
29c8d9da 12751 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12752}
0b16f239 12753
d6902373
PG
12754#ifdef KEEP_OLD_VPN_COMMANDS
12755DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12756 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12757 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12758 SHOW_STR
12759 IP_STR
12760 BGP_STR
d6902373 12761 BGP_VPNVX_HELP_STR
91d37724 12762 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12763 "Detailed information on TCP and BGP neighbor connections\n"
12764 "Neighbor to display information about\n"
12765 "Neighbor to display information about\n"
91d37724 12766 "Neighbor on BGP configured interface\n"
a636c635 12767 "Display detailed prefix count information\n"
9973d184 12768 JSON_STR)
a636c635 12769{
d62a17ae 12770 int idx_peer = 6;
12771 struct peer *peer;
9f049418 12772 bool uj = use_json(argc, argv);
a636c635 12773
d62a17ae 12774 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12775 if (!peer)
12776 return CMD_WARNING;
12777
12778 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12779}
12780
d6902373
PG
12781DEFUN (show_ip_bgp_vpn_all_route_prefix,
12782 show_ip_bgp_vpn_all_route_prefix_cmd,
12783 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12784 SHOW_STR
12785 IP_STR
12786 BGP_STR
d6902373 12787 BGP_VPNVX_HELP_STR
91d37724
QY
12788 "Display information about all VPNv4 NLRIs\n"
12789 "Network in the BGP routing table to display\n"
3a2d747c 12790 "Network in the BGP routing table to display\n"
9973d184 12791 JSON_STR)
91d37724 12792{
d62a17ae 12793 int idx = 0;
12794 char *network = NULL;
12795 struct bgp *bgp = bgp_get_default();
12796 if (!bgp) {
12797 vty_out(vty, "Can't find default instance\n");
12798 return CMD_WARNING;
12799 }
87e34b58 12800
d62a17ae 12801 if (argv_find(argv, argc, "A.B.C.D", &idx))
12802 network = argv[idx]->arg;
12803 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12804 network = argv[idx]->arg;
12805 else {
12806 vty_out(vty, "Unable to figure out Network\n");
12807 return CMD_WARNING;
12808 }
87e34b58 12809
d62a17ae 12810 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12811 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12812}
d6902373 12813#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12814
44c69747
LK
12815DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12816 show_bgp_l2vpn_evpn_route_prefix_cmd,
12817 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12818 SHOW_STR
4c63a661
PG
12819 BGP_STR
12820 L2VPN_HELP_STR
12821 EVPN_HELP_STR
44c69747
LK
12822 "Network in the BGP routing table to display\n"
12823 "Network in the BGP routing table to display\n"
4c63a661
PG
12824 "Network in the BGP routing table to display\n"
12825 "Network in the BGP routing table to display\n"
12826 JSON_STR)
12827{
d62a17ae 12828 int idx = 0;
12829 char *network = NULL;
44c69747 12830 int prefix_check = 0;
a636c635 12831
44c69747
LK
12832 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12833 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12834 network = argv[idx]->arg;
44c69747 12835 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12836 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12837 network = argv[idx]->arg;
44c69747
LK
12838 prefix_check = 1;
12839 } else {
d62a17ae 12840 vty_out(vty, "Unable to figure out Network\n");
12841 return CMD_WARNING;
12842 }
44c69747
LK
12843 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12844 prefix_check, BGP_PATH_SHOW_ALL,
12845 use_json(argc, argv));
d62a17ae 12846}
12847
2f9bc755
DS
12848static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12849 struct bgp_table *table, int *header1,
12850 int *header2, json_object *json,
12851 json_object *json_scode,
12852 json_object *json_ocode, bool wide)
12853{
12854 uint64_t version = table ? table->version : 0;
23d0a753 12855 char buf[BUFSIZ] = {0};
2f9bc755
DS
12856
12857 if (*header1) {
12858 if (json) {
12859 json_object_int_add(json, "bgpTableVersion", version);
12860 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12861 inet_ntop(AF_INET,
12862 &bgp->router_id, buf,
12863 sizeof(buf)));
2f9bc755
DS
12864 json_object_int_add(json, "defaultLocPrf",
12865 bgp->default_local_pref);
12866 json_object_int_add(json, "localAS", bgp->as);
12867 json_object_object_add(json, "bgpStatusCodes",
12868 json_scode);
12869 json_object_object_add(json, "bgpOriginCodes",
12870 json_ocode);
12871 } else {
12872 vty_out(vty,
23d0a753
DA
12873 "BGP table version is %" PRIu64
12874 ", local router ID is %pI4, vrf id ",
12875 version, &bgp->router_id);
2f9bc755
DS
12876 if (bgp->vrf_id == VRF_UNKNOWN)
12877 vty_out(vty, "%s", VRFID_NONE_STR);
12878 else
12879 vty_out(vty, "%u", bgp->vrf_id);
12880 vty_out(vty, "\n");
12881 vty_out(vty, "Default local pref %u, ",
12882 bgp->default_local_pref);
12883 vty_out(vty, "local AS %u\n", bgp->as);
12884 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12885 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12886 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12887 }
12888 *header1 = 0;
12889 }
12890 if (*header2) {
12891 if (!json)
12892 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12893 : BGP_SHOW_HEADER));
12894 *header2 = 0;
12895 }
12896}
12897
d62a17ae 12898static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12899 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12900 const char *rmap_name, json_object *json,
12901 uint8_t show_flags)
d62a17ae 12902{
12903 struct bgp_table *table;
12904 struct bgp_adj_in *ain;
12905 struct bgp_adj_out *adj;
74a630b6
NT
12906 unsigned long output_count = 0;
12907 unsigned long filtered_count = 0;
9bcb3eef 12908 struct bgp_dest *dest;
d62a17ae 12909 int header1 = 1;
12910 struct bgp *bgp;
12911 int header2 = 1;
12912 struct attr attr;
12913 int ret;
12914 struct update_subgroup *subgrp;
12915 json_object *json_scode = NULL;
12916 json_object *json_ocode = NULL;
12917 json_object *json_ar = NULL;
12918 struct peer_af *paf;
f99def61 12919 bool route_filtered;
96f3485c
MK
12920 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12921 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12922
12923 if (use_json) {
12924 json_scode = json_object_new_object();
12925 json_ocode = json_object_new_object();
12926 json_ar = json_object_new_object();
12927
12928 json_object_string_add(json_scode, "suppressed", "s");
12929 json_object_string_add(json_scode, "damped", "d");
12930 json_object_string_add(json_scode, "history", "h");
12931 json_object_string_add(json_scode, "valid", "*");
12932 json_object_string_add(json_scode, "best", ">");
12933 json_object_string_add(json_scode, "multipath", "=");
12934 json_object_string_add(json_scode, "internal", "i");
12935 json_object_string_add(json_scode, "ribFailure", "r");
12936 json_object_string_add(json_scode, "stale", "S");
12937 json_object_string_add(json_scode, "removed", "R");
12938
12939 json_object_string_add(json_ocode, "igp", "i");
12940 json_object_string_add(json_ocode, "egp", "e");
12941 json_object_string_add(json_ocode, "incomplete", "?");
12942 }
a636c635 12943
d62a17ae 12944 bgp = peer->bgp;
a636c635 12945
d62a17ae 12946 if (!bgp) {
12947 if (use_json) {
12948 json_object_string_add(json, "alert", "no BGP");
12949 vty_out(vty, "%s\n", json_object_to_json_string(json));
12950 json_object_free(json);
12951 } else
12952 vty_out(vty, "%% No bgp\n");
12953 return;
12954 }
a636c635 12955
c512a642
EDP
12956 /* labeled-unicast routes live in the unicast table */
12957 if (safi == SAFI_LABELED_UNICAST)
12958 table = bgp->rib[afi][SAFI_UNICAST];
12959 else
12960 table = bgp->rib[afi][safi];
d62a17ae 12961
12962 output_count = filtered_count = 0;
12963 subgrp = peer_subgroup(peer, afi, safi);
12964
6392aaa6 12965 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12966 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
12967 char buf[BUFSIZ] = {0};
12968
d62a17ae 12969 if (use_json) {
12970 json_object_int_add(json, "bgpTableVersion",
12971 table->version);
12972 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12973 inet_ntop(AF_INET,
12974 &bgp->router_id, buf,
12975 sizeof(buf)));
01eced22
AD
12976 json_object_int_add(json, "defaultLocPrf",
12977 bgp->default_local_pref);
12978 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12979 json_object_object_add(json, "bgpStatusCodes",
12980 json_scode);
12981 json_object_object_add(json, "bgpOriginCodes",
12982 json_ocode);
07d0c4ed
DA
12983 json_object_string_add(
12984 json, "bgpOriginatingDefaultNetwork",
12985 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12986 } else {
23d0a753
DA
12987 vty_out(vty,
12988 "BGP table version is %" PRIu64
12989 ", local router ID is %pI4, vrf id ",
12990 table->version, &bgp->router_id);
9df8b37c
PZ
12991 if (bgp->vrf_id == VRF_UNKNOWN)
12992 vty_out(vty, "%s", VRFID_NONE_STR);
12993 else
12994 vty_out(vty, "%u", bgp->vrf_id);
12995 vty_out(vty, "\n");
01eced22
AD
12996 vty_out(vty, "Default local pref %u, ",
12997 bgp->default_local_pref);
12998 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12999 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13000 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13001 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13002
07d0c4ed
DA
13003 vty_out(vty, "Originating default network %s\n\n",
13004 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13005 }
13006 header1 = 0;
13007 }
a636c635 13008
9bcb3eef 13009 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13010 if (type == bgp_show_adj_route_received
13011 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13012 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13013 if (ain->peer != peer)
ea47320b 13014 continue;
6392aaa6 13015
2f9bc755
DS
13016 show_adj_route_header(
13017 vty, bgp, table, &header1, &header2,
13018 json, json_scode, json_ocode, wide);
6392aaa6 13019
6f4f49b2 13020 attr = *ain->attr;
f99def61
AD
13021 route_filtered = false;
13022
13023 /* Filter prefix using distribute list,
13024 * filter list or prefix list
13025 */
b54892e0 13026 const struct prefix *rn_p =
9bcb3eef 13027 bgp_dest_get_prefix(dest);
b54892e0
DS
13028 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13029 safi))
13030 == FILTER_DENY)
f99def61
AD
13031 route_filtered = true;
13032
13033 /* Filter prefix using route-map */
b54892e0
DS
13034 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13035 safi, rmap_name, NULL,
13036 0, NULL);
6392aaa6 13037
13c8e163
AD
13038 if (type == bgp_show_adj_route_filtered &&
13039 !route_filtered && ret != RMAP_DENY) {
b755861b 13040 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13041 continue;
d62a17ae 13042 }
6392aaa6 13043
13c8e163
AD
13044 if (type == bgp_show_adj_route_received &&
13045 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13046 filtered_count++;
13047
b54892e0 13048 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13049 use_json, json_ar, wide);
b755861b 13050 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13051 output_count++;
d62a17ae 13052 }
6392aaa6 13053 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13054 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13055 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13056 if (paf->peer != peer || !adj->attr)
924c3f6a 13057 continue;
d62a17ae 13058
2f9bc755
DS
13059 show_adj_route_header(
13060 vty, bgp, table, &header1,
13061 &header2, json, json_scode,
13062 json_ocode, wide);
d62a17ae 13063
b54892e0 13064 const struct prefix *rn_p =
9bcb3eef 13065 bgp_dest_get_prefix(dest);
b54892e0 13066
6f4f49b2 13067 attr = *adj->attr;
b755861b 13068 ret = bgp_output_modifier(
b54892e0 13069 peer, rn_p, &attr, afi, safi,
b755861b 13070 rmap_name);
f46d8e1e 13071
b755861b 13072 if (ret != RMAP_DENY) {
b54892e0
DS
13073 route_vty_out_tmp(
13074 vty, rn_p, &attr, safi,
ae248832
MK
13075 use_json, json_ar,
13076 wide);
b755861b
PM
13077 output_count++;
13078 } else {
13079 filtered_count++;
a2addae8 13080 }
b755861b
PM
13081
13082 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13083 }
f20ce998
DS
13084 } else if (type == bgp_show_adj_route_bestpath) {
13085 struct bgp_path_info *pi;
13086
13087 show_adj_route_header(vty, bgp, table, &header1,
13088 &header2, json, json_scode,
13089 json_ocode, wide);
13090
13091 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13092 pi = pi->next) {
13093 if (pi->peer != peer)
13094 continue;
13095
13096 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13097 continue;
13098
13099 route_vty_out_tmp(vty,
13100 bgp_dest_get_prefix(dest),
13101 pi->attr, safi, use_json,
13102 json_ar, wide);
13103 output_count++;
13104 }
d62a17ae 13105 }
13106 }
d62a17ae 13107
d62a17ae 13108 if (use_json) {
6392aaa6
PM
13109 json_object_object_add(json, "advertisedRoutes", json_ar);
13110 json_object_int_add(json, "totalPrefixCounter", output_count);
13111 json_object_int_add(json, "filteredPrefixCounter",
13112 filtered_count);
13113
996c9314
LB
13114 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13115 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13116
13117 if (!output_count && !filtered_count) {
13118 json_object_free(json_scode);
13119 json_object_free(json_ocode);
13120 }
13121
d62a17ae 13122 json_object_free(json);
6392aaa6
PM
13123 } else if (output_count > 0) {
13124 if (filtered_count > 0)
13125 vty_out(vty,
13126 "\nTotal number of prefixes %ld (%ld filtered)\n",
13127 output_count, filtered_count);
13128 else
13129 vty_out(vty, "\nTotal number of prefixes %ld\n",
13130 output_count);
d62a17ae 13131 }
a636c635 13132}
2a71e9ce 13133
d62a17ae 13134static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13135 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13136 const char *rmap_name, uint8_t show_flags)
0b16f239 13137{
d62a17ae 13138 json_object *json = NULL;
96f3485c 13139 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13140
d62a17ae 13141 if (use_json)
13142 json = json_object_new_object();
0b16f239 13143
d62a17ae 13144 if (!peer || !peer->afc[afi][safi]) {
13145 if (use_json) {
13146 json_object_string_add(
13147 json, "warning",
13148 "No such neighbor or address family");
13149 vty_out(vty, "%s\n", json_object_to_json_string(json));
13150 json_object_free(json);
13151 } else
13152 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13153
d62a17ae 13154 return CMD_WARNING;
13155 }
13156
6392aaa6
PM
13157 if ((type == bgp_show_adj_route_received
13158 || type == bgp_show_adj_route_filtered)
d62a17ae 13159 && !CHECK_FLAG(peer->af_flags[afi][safi],
13160 PEER_FLAG_SOFT_RECONFIG)) {
13161 if (use_json) {
13162 json_object_string_add(
13163 json, "warning",
13164 "Inbound soft reconfiguration not enabled");
13165 vty_out(vty, "%s\n", json_object_to_json_string(json));
13166 json_object_free(json);
13167 } else
13168 vty_out(vty,
13169 "%% Inbound soft reconfiguration not enabled\n");
13170
13171 return CMD_WARNING;
13172 }
0b16f239 13173
96f3485c 13174 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13175
d62a17ae 13176 return CMD_SUCCESS;
a636c635 13177}
50ef26d4 13178
f20ce998
DS
13179DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13180 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13181 "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]",
13182 SHOW_STR
13183 IP_STR
13184 BGP_STR
13185 BGP_INSTANCE_HELP_STR
13186 BGP_AFI_HELP_STR
13187 BGP_SAFI_WITH_LABEL_HELP_STR
13188 "Detailed information on TCP and BGP neighbor connections\n"
13189 "Neighbor to display information about\n"
13190 "Neighbor to display information about\n"
13191 "Neighbor on BGP configured interface\n"
13192 "Display the routes selected by best path\n"
13193 JSON_STR
13194 "Increase table width for longer prefixes\n")
13195{
13196 afi_t afi = AFI_IP6;
13197 safi_t safi = SAFI_UNICAST;
13198 char *rmap_name = NULL;
13199 char *peerstr = NULL;
13200 struct bgp *bgp = NULL;
13201 struct peer *peer;
13202 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13203 int idx = 0;
96f3485c
MK
13204 uint8_t show_flags = 0;
13205
13206 if (uj)
13207 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13208
13209 if (wide)
13210 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13211
13212 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13213 &bgp, uj);
13214
13215 if (!idx)
13216 return CMD_WARNING;
13217
13218 argv_find(argv, argc, "neighbors", &idx);
13219 peerstr = argv[++idx]->arg;
13220
13221 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13222 if (!peer)
13223 return CMD_WARNING;
13224
96f3485c
MK
13225 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13226 show_flags);
f20ce998
DS
13227}
13228
ae248832 13229DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13230 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13231 "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 13232 SHOW_STR
13233 IP_STR
13234 BGP_STR
a636c635 13235 BGP_INSTANCE_HELP_STR
7395a2c9 13236 BGP_AFI_HELP_STR
4dd6177e 13237 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13238 "Display the entries for all address families\n"
718e3744 13239 "Detailed information on TCP and BGP neighbor connections\n"
13240 "Neighbor to display information about\n"
13241 "Neighbor to display information about\n"
91d37724 13242 "Neighbor on BGP configured interface\n"
a636c635 13243 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13244 "Display the received routes from neighbor\n"
13245 "Display the filtered routes received from neighbor\n"
a636c635
DW
13246 "Route-map to modify the attributes\n"
13247 "Name of the route map\n"
ae248832
MK
13248 JSON_STR
13249 "Increase table width for longer prefixes\n")
718e3744 13250{
d62a17ae 13251 afi_t afi = AFI_IP6;
13252 safi_t safi = SAFI_UNICAST;
13253 char *rmap_name = NULL;
13254 char *peerstr = NULL;
d62a17ae 13255 struct bgp *bgp = NULL;
13256 struct peer *peer;
6392aaa6 13257 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13258 int idx = 0;
96f3485c
MK
13259 bool first = true;
13260 uint8_t show_flags = 0;
6392aaa6 13261
96f3485c 13262 if (uj) {
d62a17ae 13263 argc--;
96f3485c
MK
13264 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13265 }
13266
13267 if (all) {
13268 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13269 if (argv_find(argv, argc, "ipv4", &idx))
13270 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13271
13272 if (argv_find(argv, argc, "ipv6", &idx))
13273 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13274 }
13275
13276 if (wide)
13277 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13278
9f049418
DS
13279 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13280 &bgp, uj);
13281 if (!idx)
13282 return CMD_WARNING;
13283
d62a17ae 13284 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13285 argv_find(argv, argc, "neighbors", &idx);
13286 peerstr = argv[++idx]->arg;
8c3deaae 13287
d62a17ae 13288 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13289 if (!peer)
13290 return CMD_WARNING;
856ca177 13291
d62a17ae 13292 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13293 type = bgp_show_adj_route_advertised;
13294 else if (argv_find(argv, argc, "received-routes", &idx))
13295 type = bgp_show_adj_route_received;
13296 else if (argv_find(argv, argc, "filtered-routes", &idx))
13297 type = bgp_show_adj_route_filtered;
13298
d62a17ae 13299 if (argv_find(argv, argc, "route-map", &idx))
13300 rmap_name = argv[++idx]->arg;
95cbbd2a 13301
96f3485c
MK
13302 if (!all)
13303 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13304 show_flags);
13305 if (uj)
13306 vty_out(vty, "{\n");
13307
13308 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13309 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13310 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13311 : AFI_IP6;
13312 FOREACH_SAFI (safi) {
96f3485c
MK
13313 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13314 continue;
13315
13316 if (uj) {
13317 if (first)
13318 first = false;
13319 else
13320 vty_out(vty, ",\n");
13321 vty_out(vty, "\"%s\":",
13322 get_afi_safi_str(afi, safi, true));
13323 } else
13324 vty_out(vty, "\nFor address family: %s\n",
13325 get_afi_safi_str(afi, safi, false));
13326
13327 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13328 show_flags);
13329 }
13330 } else {
13331 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13332 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13333 continue;
13334
13335 if (uj) {
13336 if (first)
13337 first = false;
13338 else
13339 vty_out(vty, ",\n");
13340 vty_out(vty, "\"%s\":",
13341 get_afi_safi_str(afi, safi, true));
13342 } else
13343 vty_out(vty, "\nFor address family: %s\n",
13344 get_afi_safi_str(afi, safi, false));
13345
13346 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13347 show_flags);
13348 }
13349 }
13350 if (uj)
13351 vty_out(vty, "}\n");
13352
13353 return CMD_SUCCESS;
95cbbd2a
ML
13354}
13355
718e3744 13356DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13357 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13358 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13359 SHOW_STR
13360 IP_STR
13361 BGP_STR
8c3deaae
QY
13362 "Address Family\n"
13363 "Address Family\n"
718e3744 13364 "Address Family modifier\n"
13365 "Detailed information on TCP and BGP neighbor connections\n"
13366 "Neighbor to display information about\n"
13367 "Neighbor to display information about\n"
91d37724 13368 "Neighbor on BGP configured interface\n"
718e3744 13369 "Display information received from a BGP neighbor\n"
856ca177 13370 "Display the prefixlist filter\n"
9973d184 13371 JSON_STR)
718e3744 13372{
d62a17ae 13373 afi_t afi = AFI_IP6;
13374 safi_t safi = SAFI_UNICAST;
13375 char *peerstr = NULL;
13376
13377 char name[BUFSIZ];
13378 union sockunion su;
13379 struct peer *peer;
13380 int count, ret;
13381
13382 int idx = 0;
13383
13384 /* show [ip] bgp */
13385 if (argv_find(argv, argc, "ip", &idx))
13386 afi = AFI_IP;
13387 /* [<ipv4|ipv6> [unicast]] */
13388 if (argv_find(argv, argc, "ipv4", &idx))
13389 afi = AFI_IP;
13390 if (argv_find(argv, argc, "ipv6", &idx))
13391 afi = AFI_IP6;
13392 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13393 argv_find(argv, argc, "neighbors", &idx);
13394 peerstr = argv[++idx]->arg;
13395
9f049418 13396 bool uj = use_json(argc, argv);
d62a17ae 13397
13398 ret = str2sockunion(peerstr, &su);
13399 if (ret < 0) {
13400 peer = peer_lookup_by_conf_if(NULL, peerstr);
13401 if (!peer) {
13402 if (uj)
13403 vty_out(vty, "{}\n");
13404 else
13405 vty_out(vty,
13406 "%% Malformed address or name: %s\n",
13407 peerstr);
13408 return CMD_WARNING;
13409 }
13410 } else {
13411 peer = peer_lookup(NULL, &su);
13412 if (!peer) {
13413 if (uj)
13414 vty_out(vty, "{}\n");
13415 else
13416 vty_out(vty, "No peer\n");
13417 return CMD_WARNING;
13418 }
13419 }
718e3744 13420
4ced1a2c 13421 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13422 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13423 if (count) {
13424 if (!uj)
13425 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13426 get_afi_safi_str(afi, safi, false));
d62a17ae 13427 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13428 } else {
13429 if (uj)
13430 vty_out(vty, "{}\n");
13431 else
13432 vty_out(vty, "No functional output\n");
13433 }
718e3744 13434
d62a17ae 13435 return CMD_SUCCESS;
13436}
13437
13438static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13439 afi_t afi, safi_t safi,
9f049418 13440 enum bgp_show_type type, bool use_json)
d62a17ae 13441{
96f3485c
MK
13442 uint8_t show_flags = 0;
13443
13444 if (use_json)
13445 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13446
d62a17ae 13447 if (!peer || !peer->afc[afi][safi]) {
13448 if (use_json) {
13449 json_object *json_no = NULL;
13450 json_no = json_object_new_object();
13451 json_object_string_add(
13452 json_no, "warning",
13453 "No such neighbor or address family");
13454 vty_out(vty, "%s\n",
13455 json_object_to_json_string(json_no));
13456 json_object_free(json_no);
13457 } else
13458 vty_out(vty, "%% No such neighbor or address family\n");
13459 return CMD_WARNING;
13460 }
47fc97cc 13461
7daf25a3
TA
13462 /* labeled-unicast routes live in the unicast table */
13463 if (safi == SAFI_LABELED_UNICAST)
13464 safi = SAFI_UNICAST;
13465
96f3485c 13466 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13467}
13468
dba3c1d3
PG
13469DEFUN (show_ip_bgp_flowspec_routes_detailed,
13470 show_ip_bgp_flowspec_routes_detailed_cmd,
13471 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13472 SHOW_STR
13473 IP_STR
13474 BGP_STR
13475 BGP_INSTANCE_HELP_STR
13476 BGP_AFI_HELP_STR
13477 "SAFI Flowspec\n"
13478 "Detailed information on flowspec entries\n"
13479 JSON_STR)
13480{
13481 afi_t afi = AFI_IP;
13482 safi_t safi = SAFI_UNICAST;
13483 struct bgp *bgp = NULL;
13484 int idx = 0;
9f049418 13485 bool uj = use_json(argc, argv);
96f3485c 13486 uint8_t show_flags = 0;
9f049418 13487
96f3485c 13488 if (uj) {
9f049418 13489 argc--;
96f3485c
MK
13490 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13491 }
dba3c1d3
PG
13492
13493 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13494 &bgp, uj);
dba3c1d3
PG
13495 if (!idx)
13496 return CMD_WARNING;
13497
96f3485c
MK
13498 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13499 show_flags);
dba3c1d3
PG
13500}
13501
718e3744 13502DEFUN (show_ip_bgp_neighbor_routes,
13503 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13504 "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 13505 SHOW_STR
13506 IP_STR
13507 BGP_STR
8386ac43 13508 BGP_INSTANCE_HELP_STR
4f280b15 13509 BGP_AFI_HELP_STR
4dd6177e 13510 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13511 "Detailed information on TCP and BGP neighbor connections\n"
13512 "Neighbor to display information about\n"
13513 "Neighbor to display information about\n"
91d37724 13514 "Neighbor on BGP configured interface\n"
2525cf39 13515 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13516 "Display the dampened routes received from neighbor\n"
13517 "Display routes learned from neighbor\n"
9973d184 13518 JSON_STR)
718e3744 13519{
d62a17ae 13520 char *peerstr = NULL;
13521 struct bgp *bgp = NULL;
13522 afi_t afi = AFI_IP6;
13523 safi_t safi = SAFI_UNICAST;
13524 struct peer *peer;
13525 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13526 int idx = 0;
9f049418
DS
13527 bool uj = use_json(argc, argv);
13528
13529 if (uj)
13530 argc--;
bb46e94f 13531
d62a17ae 13532 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13533 &bgp, uj);
d62a17ae 13534 if (!idx)
13535 return CMD_WARNING;
c493f2d8 13536
d62a17ae 13537 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13538 argv_find(argv, argc, "neighbors", &idx);
13539 peerstr = argv[++idx]->arg;
8c3deaae 13540
d62a17ae 13541 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13542 if (!peer)
d62a17ae 13543 return CMD_WARNING;
bb46e94f 13544
d62a17ae 13545 if (argv_find(argv, argc, "flap-statistics", &idx))
13546 sh_type = bgp_show_type_flap_neighbor;
13547 else if (argv_find(argv, argc, "dampened-routes", &idx))
13548 sh_type = bgp_show_type_damp_neighbor;
13549 else if (argv_find(argv, argc, "routes", &idx))
13550 sh_type = bgp_show_type_neighbor;
2525cf39 13551
d62a17ae 13552 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13553}
6b0655a2 13554
734b349e 13555struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13556
d62a17ae 13557struct bgp_distance {
13558 /* Distance value for the IP source prefix. */
d7c0a89a 13559 uint8_t distance;
718e3744 13560
d62a17ae 13561 /* Name of the access-list to be matched. */
13562 char *access_list;
718e3744 13563};
13564
4f280b15
LB
13565DEFUN (show_bgp_afi_vpn_rd_route,
13566 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13567 "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
13568 SHOW_STR
13569 BGP_STR
13570 BGP_AFI_HELP_STR
13571 "Address Family modifier\n"
13572 "Display information for a route distinguisher\n"
13573 "Route Distinguisher\n"
7395a2c9
DS
13574 "Network in the BGP routing table to display\n"
13575 "Network in the BGP routing table to display\n"
13576 JSON_STR)
4f280b15 13577{
d62a17ae 13578 int ret;
13579 struct prefix_rd prd;
13580 afi_t afi = AFI_MAX;
13581 int idx = 0;
4f280b15 13582
ff6566f3
DS
13583 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13584 vty_out(vty, "%% Malformed Address Family\n");
13585 return CMD_WARNING;
13586 }
13587
d62a17ae 13588 ret = str2prefix_rd(argv[5]->arg, &prd);
13589 if (!ret) {
13590 vty_out(vty, "%% Malformed Route Distinguisher\n");
13591 return CMD_WARNING;
13592 }
ff6566f3 13593
d62a17ae 13594 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13595 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13596}
13597
d62a17ae 13598static struct bgp_distance *bgp_distance_new(void)
718e3744 13599{
d62a17ae 13600 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13601}
13602
d62a17ae 13603static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13604{
d62a17ae 13605 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13606}
13607
37a87b8f
CS
13608int bgp_distance_set(uint8_t distance, const char *ip_str,
13609 const char *access_list_str, afi_t afi, safi_t safi,
13610 char *errmsg, size_t errmsg_len)
718e3744 13611{
d62a17ae 13612 int ret;
d62a17ae 13613 struct prefix p;
9bcb3eef 13614 struct bgp_dest *dest;
d62a17ae 13615 struct bgp_distance *bdistance;
718e3744 13616
d62a17ae 13617 ret = str2prefix(ip_str, &p);
13618 if (ret == 0) {
37a87b8f 13619 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13620 return CMD_WARNING_CONFIG_FAILED;
13621 }
718e3744 13622
d62a17ae 13623 /* Get BGP distance node. */
9bcb3eef
DS
13624 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13625 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13626 if (bdistance)
9bcb3eef 13627 bgp_dest_unlock_node(dest);
ca2e160d 13628 else {
d62a17ae 13629 bdistance = bgp_distance_new();
9bcb3eef 13630 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13631 }
718e3744 13632
d62a17ae 13633 /* Set distance value. */
13634 bdistance->distance = distance;
718e3744 13635
d62a17ae 13636 /* Reset access-list configuration. */
e1b36e13 13637 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13638 if (access_list_str)
13639 bdistance->access_list =
13640 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13641
d62a17ae 13642 return CMD_SUCCESS;
718e3744 13643}
13644
37a87b8f
CS
13645int bgp_distance_unset(uint8_t distance, const char *ip_str,
13646 const char *access_list_str, afi_t afi, safi_t safi,
13647 char *errmsg, size_t errmsg_len)
718e3744 13648{
d62a17ae 13649 int ret;
d62a17ae 13650 struct prefix p;
9bcb3eef 13651 struct bgp_dest *dest;
d62a17ae 13652 struct bgp_distance *bdistance;
718e3744 13653
d62a17ae 13654 ret = str2prefix(ip_str, &p);
13655 if (ret == 0) {
37a87b8f 13656 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13657 return CMD_WARNING_CONFIG_FAILED;
13658 }
718e3744 13659
9bcb3eef
DS
13660 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13661 if (!dest) {
37a87b8f 13662 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13663 return CMD_WARNING_CONFIG_FAILED;
13664 }
718e3744 13665
9bcb3eef 13666 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13667
d62a17ae 13668 if (bdistance->distance != distance) {
37a87b8f
CS
13669 snprintf(errmsg, errmsg_len,
13670 "Distance does not match configured\n");
d62a17ae 13671 return CMD_WARNING_CONFIG_FAILED;
13672 }
718e3744 13673
0a22ddfb 13674 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13675 bgp_distance_free(bdistance);
718e3744 13676
9bcb3eef
DS
13677 bgp_dest_set_bgp_path_info(dest, NULL);
13678 bgp_dest_unlock_node(dest);
13679 bgp_dest_unlock_node(dest);
718e3744 13680
d62a17ae 13681 return CMD_SUCCESS;
718e3744 13682}
13683
718e3744 13684/* Apply BGP information to distance method. */
b8685f9b 13685uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13686 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13687{
9bcb3eef 13688 struct bgp_dest *dest;
801bb996 13689 struct prefix q = {0};
d62a17ae 13690 struct peer *peer;
13691 struct bgp_distance *bdistance;
13692 struct access_list *alist;
13693 struct bgp_static *bgp_static;
13694
13695 if (!bgp)
13696 return 0;
13697
40381db7 13698 peer = pinfo->peer;
d62a17ae 13699
7b7d48e5
DS
13700 if (pinfo->attr->distance)
13701 return pinfo->attr->distance;
13702
801bb996
CS
13703 /* Check source address.
13704 * Note: for aggregate route, peer can have unspec af type.
13705 */
13706 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13707 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13708 return 0;
13709
9bcb3eef
DS
13710 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13711 if (dest) {
13712 bdistance = bgp_dest_get_bgp_distance_info(dest);
13713 bgp_dest_unlock_node(dest);
d62a17ae 13714
13715 if (bdistance->access_list) {
13716 alist = access_list_lookup(afi, bdistance->access_list);
13717 if (alist
13718 && access_list_apply(alist, p) == FILTER_PERMIT)
13719 return bdistance->distance;
13720 } else
13721 return bdistance->distance;
718e3744 13722 }
718e3744 13723
d62a17ae 13724 /* Backdoor check. */
9bcb3eef
DS
13725 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13726 if (dest) {
13727 bgp_static = bgp_dest_get_bgp_static_info(dest);
13728 bgp_dest_unlock_node(dest);
718e3744 13729
d62a17ae 13730 if (bgp_static->backdoor) {
13731 if (bgp->distance_local[afi][safi])
13732 return bgp->distance_local[afi][safi];
13733 else
13734 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13735 }
718e3744 13736 }
718e3744 13737
d62a17ae 13738 if (peer->sort == BGP_PEER_EBGP) {
13739 if (bgp->distance_ebgp[afi][safi])
13740 return bgp->distance_ebgp[afi][safi];
13741 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 13742 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 13743 if (bgp->distance_ibgp[afi][safi])
13744 return bgp->distance_ibgp[afi][safi];
13745 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
13746 } else {
13747 if (bgp->distance_local[afi][safi])
13748 return bgp->distance_local[afi][safi];
13749 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 13750 }
718e3744 13751}
13752
a612fb77
DA
13753/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13754 * we should tell ZEBRA update the routes for a specific
13755 * AFI/SAFI to reflect changes in RIB.
13756 */
37a87b8f
CS
13757void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13758 safi_t update_safi)
a612fb77
DA
13759{
13760 afi_t afi;
13761 safi_t safi;
13762
13763 FOREACH_AFI_SAFI (afi, safi) {
13764 if (!bgp_fibupd_safi(safi))
13765 continue;
13766
8b54bc30
DA
13767 if (afi != update_afi && safi != update_safi)
13768 continue;
13769
13770 if (BGP_DEBUG(zebra, ZEBRA))
13771 zlog_debug(
13772 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13773 __func__, afi, safi);
13774 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13775 }
13776}
13777
37a87b8f
CS
13778DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13779 "distance bgp (1-255) (1-255) (1-255)",
13780 "Define an administrative distance\n"
13781 "BGP distance\n"
13782 "Distance for routes external to the AS\n"
13783 "Distance for routes internal to the AS\n"
13784 "Distance for local routes\n")
718e3744 13785{
d62a17ae 13786 int idx_number = 2;
13787 int idx_number_2 = 3;
13788 int idx_number_3 = 4;
13789 afi_t afi;
13790 safi_t safi;
37a87b8f 13791 char xpath[XPATH_MAXLEN];
718e3744 13792
d62a17ae 13793 afi = bgp_node_afi(vty);
13794 safi = bgp_node_safi(vty);
718e3744 13795
37a87b8f
CS
13796 snprintf(
13797 xpath, sizeof(xpath),
13798 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13799 yang_afi_safi_value2identity(afi, safi),
13800 bgp_afi_safi_get_container_str(afi, safi));
13801 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13802 snprintf(
13803 xpath, sizeof(xpath),
13804 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13805 yang_afi_safi_value2identity(afi, safi),
13806 bgp_afi_safi_get_container_str(afi, safi));
13807 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13808 argv[idx_number_2]->arg);
13809 snprintf(
13810 xpath, sizeof(xpath),
13811 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13812 yang_afi_safi_value2identity(afi, safi),
13813 bgp_afi_safi_get_container_str(afi, safi));
13814
13815 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13816 argv[idx_number_3]->arg);
13817
13818 return nb_cli_apply_changes(vty, NULL);
13819}
13820
13821DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13822 "no distance bgp [(1-255) (1-255) (1-255)]",
13823 NO_STR
13824 "Define an administrative distance\n"
13825 "BGP distance\n"
13826 "Distance for routes external to the AS\n"
13827 "Distance for routes internal to the AS\n"
13828 "Distance for local routes\n")
13829{
13830 afi_t afi;
13831 safi_t safi;
13832 char xpath[XPATH_MAXLEN];
13833
13834 afi = bgp_node_afi(vty);
13835 safi = bgp_node_safi(vty);
13836
13837 snprintf(
13838 xpath, sizeof(xpath),
13839 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13840 yang_afi_safi_value2identity(afi, safi),
13841 bgp_afi_safi_get_container_str(afi, safi));
13842 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13843 snprintf(
13844 xpath, sizeof(xpath),
13845 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13846 yang_afi_safi_value2identity(afi, safi),
13847 bgp_afi_safi_get_container_str(afi, safi));
13848 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13849 snprintf(
13850 xpath, sizeof(xpath),
13851 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13852 yang_afi_safi_value2identity(afi, safi),
13853 bgp_afi_safi_get_container_str(afi, safi));
13854
13855 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13856
13857 return nb_cli_apply_changes(vty, NULL);
718e3744 13858}
13859
37a87b8f
CS
13860void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13861 struct lyd_node *dnode,
13862 bool show_defaults)
718e3744 13863{
37a87b8f
CS
13864 uint8_t distance_ebgp, distance_ibgp, distance_local;
13865
13866 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13867 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13868 distance_local = yang_dnode_get_uint8(dnode, "./local");
13869
13870 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13871 distance_local);
13872}
13873
8cc7152a
CS
13874DEFPY_YANG(bgp_distance_source,
13875 bgp_distance_source_cmd,
13876 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
13877 NO_STR
13878 "Define an administrative distance\n"
8cc7152a 13879 "Distance value\n"
e12affc1
SW
13880 "IPv4 source prefix\n"
13881 "IPv6 source prefix\n"
37a87b8f 13882 "Access list name\n")
718e3744 13883{
37a87b8f
CS
13884 afi_t afi;
13885 safi_t safi;
13886 char xpath[XPATH_MAXLEN];
13887
13888 afi = bgp_node_afi(vty);
13889 safi = bgp_node_safi(vty);
13890
8cc7152a
CS
13891 if (!no) {
13892 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
13893 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
13894 distance_str);
13895 if (acl)
13896 nb_cli_enqueue_change(vty,
13897 "./access-list-policy-export",
13898 NB_OP_CREATE, acl);
13899 else
13900 nb_cli_enqueue_change(vty,
13901 "./access-list-policy-export",
13902 NB_OP_DESTROY, NULL);
13903 } else {
13904 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
13905 }
37a87b8f
CS
13906
13907 snprintf(
13908 xpath, sizeof(xpath),
13909 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
13910 yang_afi_safi_value2identity(afi, safi),
8cc7152a 13911 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
13912
13913 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
13914}
13915
37a87b8f
CS
13916void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
13917 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
13918{
13919 vty_out(vty, " distance %d %s %s\n",
13920 yang_dnode_get_uint8(dnode, "./distance"),
13921 yang_dnode_get_string(dnode, "./prefix"),
13922 (yang_dnode_exists(dnode, "./access-list-policy-export"))
13923 ? yang_dnode_get_string(dnode,
13924 "./access-list-policy-export")
13925 : "");
13926}
13927
7c98d487
DA
13928DEFPY_YANG(
13929 bgp_dampening, bgp_dampening_cmd,
13930 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
13931 NO_STR
13932 "BGP Specific commands\n"
13933 "Enable route-flap dampening\n"
13934 "Half-life time for the penalty\n"
13935 "Value to start reusing a route\n"
13936 "Value to start suppressing a route\n"
13937 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
13938{
13939 afi_t afi;
13940 safi_t safi;
13941 char xpath[XPATH_MAXLEN];
718e3744 13942
37a87b8f
CS
13943 afi = bgp_node_afi(vty);
13944 safi = bgp_node_safi(vty);
13945
d9ce5113
CS
13946 if (!no) {
13947 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
13948 if (argc == 6) {
13949 nb_cli_enqueue_change(vty, "./reach-decay",
13950 NB_OP_MODIFY, halflife_str);
13951 nb_cli_enqueue_change(vty, "./reuse-above",
13952 NB_OP_MODIFY, reuse_str);
13953 nb_cli_enqueue_change(vty, "./suppress-above",
13954 NB_OP_MODIFY, suppress_str);
13955 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 13956 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
13957 } if (argc == 3) {
13958 nb_cli_enqueue_change(vty, "./reach-decay",
13959 NB_OP_MODIFY, halflife_str);
13960 }
13961 } else {
13962 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
13963 }
7ebe9748 13964
37a87b8f
CS
13965 snprintf(
13966 xpath, sizeof(xpath),
13967 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
13968 yang_afi_safi_value2identity(afi, safi),
13969 bgp_afi_safi_get_container_str(afi, safi));
13970
13971 return nb_cli_apply_changes(vty, xpath);
718e3744 13972}
13973
37a87b8f
CS
13974void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
13975 struct lyd_node *dnode,
13976 bool show_defaults)
718e3744 13977{
37a87b8f
CS
13978 if (!yang_dnode_get_bool(dnode, "./enable"))
13979 return;
13980
13981 int half = DEFAULT_HALF_LIFE * 60;
13982 int reuse = DEFAULT_REUSE;
13983 int suppress = DEFAULT_SUPPRESS;
13984 int max;
13985
13986 half = yang_dnode_get_uint8(dnode, "../reach-decay");
13987 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
13988 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
13989 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
13990
13991 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13992 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13993 vty_out(vty, " bgp dampening\n");
13994 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13995 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13996 vty_out(vty, " bgp dampening %u\n", half);
13997 else
13998 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
13999 suppress, max);
718e3744 14000}
14001
718e3744 14002/* Display specified route of BGP table. */
d62a17ae 14003static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14004 const char *ip_str, afi_t afi, safi_t safi,
14005 struct prefix_rd *prd, int prefix_check)
14006{
14007 int ret;
14008 struct prefix match;
9bcb3eef
DS
14009 struct bgp_dest *dest;
14010 struct bgp_dest *rm;
40381db7
DS
14011 struct bgp_path_info *pi;
14012 struct bgp_path_info *pi_temp;
d62a17ae 14013 struct bgp *bgp;
14014 struct bgp_table *table;
14015
14016 /* BGP structure lookup. */
14017 if (view_name) {
14018 bgp = bgp_lookup_by_name(view_name);
14019 if (bgp == NULL) {
14020 vty_out(vty, "%% Can't find BGP instance %s\n",
14021 view_name);
14022 return CMD_WARNING;
14023 }
14024 } else {
14025 bgp = bgp_get_default();
14026 if (bgp == NULL) {
14027 vty_out(vty, "%% No BGP process is configured\n");
14028 return CMD_WARNING;
14029 }
718e3744 14030 }
718e3744 14031
d62a17ae 14032 /* Check IP address argument. */
14033 ret = str2prefix(ip_str, &match);
14034 if (!ret) {
14035 vty_out(vty, "%% address is malformed\n");
14036 return CMD_WARNING;
14037 }
718e3744 14038
d62a17ae 14039 match.family = afi2family(afi);
14040
14041 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14042 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14043 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14044 dest = bgp_route_next(dest)) {
14045 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14046
9bcb3eef 14047 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14048 continue;
9bcb3eef 14049 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14050 if (!table)
ea47320b
DL
14051 continue;
14052 if ((rm = bgp_node_match(table, &match)) == NULL)
14053 continue;
d62a17ae 14054
9bcb3eef 14055 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14056
ea47320b 14057 if (!prefix_check
b54892e0 14058 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14059 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14060 while (pi) {
14061 if (pi->extra && pi->extra->damp_info) {
14062 pi_temp = pi->next;
ea47320b 14063 bgp_damp_info_free(
40381db7 14064 pi->extra->damp_info,
a935f597 14065 1, afi, safi);
40381db7 14066 pi = pi_temp;
ea47320b 14067 } else
40381db7 14068 pi = pi->next;
d62a17ae 14069 }
ea47320b
DL
14070 }
14071
9bcb3eef 14072 bgp_dest_unlock_node(rm);
d62a17ae 14073 }
14074 } else {
9bcb3eef 14075 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14076 != NULL) {
9bcb3eef 14077 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14078
d62a17ae 14079 if (!prefix_check
9bcb3eef
DS
14080 || dest_p->prefixlen == match.prefixlen) {
14081 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14082 while (pi) {
14083 if (pi->extra && pi->extra->damp_info) {
14084 pi_temp = pi->next;
d62a17ae 14085 bgp_damp_info_free(
40381db7 14086 pi->extra->damp_info,
a935f597 14087 1, afi, safi);
40381db7 14088 pi = pi_temp;
d62a17ae 14089 } else
40381db7 14090 pi = pi->next;
d62a17ae 14091 }
14092 }
14093
9bcb3eef 14094 bgp_dest_unlock_node(dest);
d62a17ae 14095 }
14096 }
718e3744 14097
d62a17ae 14098 return CMD_SUCCESS;
718e3744 14099}
14100
14101DEFUN (clear_ip_bgp_dampening,
14102 clear_ip_bgp_dampening_cmd,
14103 "clear ip bgp dampening",
14104 CLEAR_STR
14105 IP_STR
14106 BGP_STR
14107 "Clear route flap dampening information\n")
14108{
a935f597 14109 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14110 return CMD_SUCCESS;
718e3744 14111}
14112
14113DEFUN (clear_ip_bgp_dampening_prefix,
14114 clear_ip_bgp_dampening_prefix_cmd,
14115 "clear ip bgp dampening A.B.C.D/M",
14116 CLEAR_STR
14117 IP_STR
14118 BGP_STR
14119 "Clear route flap dampening information\n"
0c7b1b01 14120 "IPv4 prefix\n")
718e3744 14121{
d62a17ae 14122 int idx_ipv4_prefixlen = 4;
14123 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14124 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14125}
14126
14127DEFUN (clear_ip_bgp_dampening_address,
14128 clear_ip_bgp_dampening_address_cmd,
14129 "clear ip bgp dampening A.B.C.D",
14130 CLEAR_STR
14131 IP_STR
14132 BGP_STR
14133 "Clear route flap dampening information\n"
14134 "Network to clear damping information\n")
14135{
d62a17ae 14136 int idx_ipv4 = 4;
14137 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14138 SAFI_UNICAST, NULL, 0);
718e3744 14139}
14140
14141DEFUN (clear_ip_bgp_dampening_address_mask,
14142 clear_ip_bgp_dampening_address_mask_cmd,
14143 "clear ip bgp dampening A.B.C.D A.B.C.D",
14144 CLEAR_STR
14145 IP_STR
14146 BGP_STR
14147 "Clear route flap dampening information\n"
14148 "Network to clear damping information\n"
14149 "Network mask\n")
14150{
d62a17ae 14151 int idx_ipv4 = 4;
14152 int idx_ipv4_2 = 5;
14153 int ret;
14154 char prefix_str[BUFSIZ];
718e3744 14155
d62a17ae 14156 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14157 prefix_str);
14158 if (!ret) {
14159 vty_out(vty, "%% Inconsistent address and mask\n");
14160 return CMD_WARNING;
14161 }
718e3744 14162
d62a17ae 14163 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14164 NULL, 0);
718e3744 14165}
6b0655a2 14166
e3b78da8 14167static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14168{
14169 struct vty *vty = arg;
e3b78da8 14170 struct peer *peer = bucket->data;
825d9834
DS
14171 char buf[SU_ADDRSTRLEN];
14172
14173 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14174 sockunion2str(&peer->su, buf, sizeof(buf)));
14175}
14176
2a0e69ae
DS
14177DEFUN (show_bgp_listeners,
14178 show_bgp_listeners_cmd,
14179 "show bgp listeners",
14180 SHOW_STR
14181 BGP_STR
14182 "Display Listen Sockets and who created them\n")
14183{
14184 bgp_dump_listener_info(vty);
14185
14186 return CMD_SUCCESS;
14187}
14188
825d9834
DS
14189DEFUN (show_bgp_peerhash,
14190 show_bgp_peerhash_cmd,
14191 "show bgp peerhash",
14192 SHOW_STR
14193 BGP_STR
14194 "Display information about the BGP peerhash\n")
14195{
14196 struct list *instances = bm->bgp;
14197 struct listnode *node;
14198 struct bgp *bgp;
14199
14200 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14201 vty_out(vty, "BGP: %s\n", bgp->name);
14202 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14203 vty);
14204 }
14205
14206 return CMD_SUCCESS;
14207}
14208
587ff0fd 14209/* also used for encap safi */
2b791107
DL
14210static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14211 afi_t afi, safi_t safi)
d62a17ae 14212{
9bcb3eef
DS
14213 struct bgp_dest *pdest;
14214 struct bgp_dest *dest;
d62a17ae 14215 struct bgp_table *table;
b54892e0
DS
14216 const struct prefix *p;
14217 const struct prefix_rd *prd;
d62a17ae 14218 struct bgp_static *bgp_static;
14219 mpls_label_t label;
d62a17ae 14220 char rdbuf[RD_ADDRSTRLEN];
14221
14222 /* Network configuration. */
9bcb3eef
DS
14223 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14224 pdest = bgp_route_next(pdest)) {
14225 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14226 if (!table)
ea47320b 14227 continue;
d62a17ae 14228
9bcb3eef
DS
14229 for (dest = bgp_table_top(table); dest;
14230 dest = bgp_route_next(dest)) {
14231 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14232 if (bgp_static == NULL)
ea47320b 14233 continue;
d62a17ae 14234
9bcb3eef
DS
14235 p = bgp_dest_get_prefix(dest);
14236 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14237 pdest);
d62a17ae 14238
ea47320b 14239 /* "network" configuration display. */
06b9f471 14240 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14241 label = decode_label(&bgp_static->label);
14242
8228a9a7 14243 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14244 if (safi == SAFI_MPLS_VPN)
14245 vty_out(vty, " label %u", label);
14246
14247 if (bgp_static->rmap.name)
14248 vty_out(vty, " route-map %s",
14249 bgp_static->rmap.name);
e2a86ad9
DS
14250
14251 if (bgp_static->backdoor)
14252 vty_out(vty, " backdoor");
14253
ea47320b
DL
14254 vty_out(vty, "\n");
14255 }
14256 }
d62a17ae 14257}
14258
2b791107
DL
14259static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14260 afi_t afi, safi_t safi)
d62a17ae 14261{
9bcb3eef
DS
14262 struct bgp_dest *pdest;
14263 struct bgp_dest *dest;
d62a17ae 14264 struct bgp_table *table;
b54892e0
DS
14265 const struct prefix *p;
14266 const struct prefix_rd *prd;
d62a17ae 14267 struct bgp_static *bgp_static;
ff44f570 14268 char buf[PREFIX_STRLEN * 2];
d62a17ae 14269 char buf2[SU_ADDRSTRLEN];
14270 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14271 char esi_buf[ESI_BYTES];
d62a17ae 14272
14273 /* Network configuration. */
9bcb3eef
DS
14274 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14275 pdest = bgp_route_next(pdest)) {
14276 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14277 if (!table)
ea47320b 14278 continue;
d62a17ae 14279
9bcb3eef
DS
14280 for (dest = bgp_table_top(table); dest;
14281 dest = bgp_route_next(dest)) {
14282 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14283 if (bgp_static == NULL)
ea47320b 14284 continue;
d62a17ae 14285
ea47320b 14286 char *macrouter = NULL;
d62a17ae 14287
ea47320b
DL
14288 if (bgp_static->router_mac)
14289 macrouter = prefix_mac2str(
14290 bgp_static->router_mac, NULL, 0);
14291 if (bgp_static->eth_s_id)
0a50c248
AK
14292 esi_to_str(bgp_static->eth_s_id,
14293 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14294 p = bgp_dest_get_prefix(dest);
14295 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14296
ea47320b 14297 /* "network" configuration display. */
06b9f471 14298 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14299 if (p->u.prefix_evpn.route_type == 5) {
14300 char local_buf[PREFIX_STRLEN];
3714a385 14301 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14302 struct prefix_evpn *)p)
14303 ? AF_INET
14304 : AF_INET6;
3714a385 14305 inet_ntop(family,
14306 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14307 local_buf, PREFIX_STRLEN);
772270f3
QY
14308 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14309 p->u.prefix_evpn.prefix_addr
14310 .ip_prefix_length);
197cb530
PG
14311 } else {
14312 prefix2str(p, buf, sizeof(buf));
14313 }
ea47320b 14314
a4d82a8a
PZ
14315 if (bgp_static->gatewayIp.family == AF_INET
14316 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14317 inet_ntop(bgp_static->gatewayIp.family,
14318 &bgp_static->gatewayIp.u.prefix, buf2,
14319 sizeof(buf2));
ea47320b 14320 vty_out(vty,
7bcc8dac 14321 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14322 buf, rdbuf,
14323 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14324 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14325 macrouter);
14326
0a22ddfb 14327 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14328 }
14329 }
3da6fcd5
PG
14330}
14331
718e3744 14332/* Configuration of static route announcement and aggregate
14333 information. */
2b791107
DL
14334void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14335 safi_t safi)
d62a17ae 14336{
9bcb3eef 14337 struct bgp_dest *dest;
b54892e0 14338 const struct prefix *p;
d62a17ae 14339 struct bgp_static *bgp_static;
14340 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14341
2b791107
DL
14342 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14343 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14344 return;
14345 }
d62a17ae 14346
2b791107
DL
14347 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14348 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14349 return;
14350 }
d62a17ae 14351
14352 /* Network configuration. */
9bcb3eef
DS
14353 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14354 dest = bgp_route_next(dest)) {
14355 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14356 if (bgp_static == NULL)
ea47320b 14357 continue;
d62a17ae 14358
9bcb3eef 14359 p = bgp_dest_get_prefix(dest);
d62a17ae 14360
8228a9a7 14361 vty_out(vty, " network %pFX", p);
d62a17ae 14362
ea47320b
DL
14363 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14364 vty_out(vty, " label-index %u",
14365 bgp_static->label_index);
d62a17ae 14366
ea47320b
DL
14367 if (bgp_static->rmap.name)
14368 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14369
14370 if (bgp_static->backdoor)
14371 vty_out(vty, " backdoor");
718e3744 14372
ea47320b
DL
14373 vty_out(vty, "\n");
14374 }
14375
d62a17ae 14376 /* Aggregate-address configuration. */
9bcb3eef
DS
14377 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14378 dest = bgp_route_next(dest)) {
14379 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14380 if (bgp_aggregate == NULL)
ea47320b 14381 continue;
d62a17ae 14382
9bcb3eef 14383 p = bgp_dest_get_prefix(dest);
d62a17ae 14384
8228a9a7 14385 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14386
ea47320b
DL
14387 if (bgp_aggregate->as_set)
14388 vty_out(vty, " as-set");
d62a17ae 14389
ea47320b
DL
14390 if (bgp_aggregate->summary_only)
14391 vty_out(vty, " summary-only");
718e3744 14392
20894f50
DA
14393 if (bgp_aggregate->rmap.name)
14394 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14395
229757f1
DA
14396 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14397 vty_out(vty, " origin %s",
14398 bgp_origin2str(bgp_aggregate->origin));
14399
6aabb15d
RZ
14400 if (bgp_aggregate->match_med)
14401 vty_out(vty, " matching-MED-only");
14402
365ab2e7
RZ
14403 if (bgp_aggregate->suppress_map_name)
14404 vty_out(vty, " suppress-map %s",
14405 bgp_aggregate->suppress_map_name);
14406
ea47320b
DL
14407 vty_out(vty, "\n");
14408 }
d62a17ae 14409}
734b349e 14410
2b791107 14411void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14412 safi_t safi)
d62a17ae 14413{
9bcb3eef 14414 struct bgp_dest *dest;
d62a17ae 14415 struct bgp_distance *bdistance;
14416
14417 /* Distance configuration. */
14418 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14419 && bgp->distance_local[afi][safi]
14420 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14421 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14422 || bgp->distance_local[afi][safi]
14423 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14424 vty_out(vty, " distance bgp %d %d %d\n",
14425 bgp->distance_ebgp[afi][safi],
14426 bgp->distance_ibgp[afi][safi],
14427 bgp->distance_local[afi][safi]);
14428 }
734b349e 14429
9bcb3eef
DS
14430 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14431 dest = bgp_route_next(dest)) {
14432 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14433 if (bdistance != NULL)
56ca3b5b 14434 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14435 bdistance->distance, dest,
d62a17ae 14436 bdistance->access_list ? bdistance->access_list
14437 : "");
ca2e160d 14438 }
718e3744 14439}
14440
14441/* Allocate routing table structure and install commands. */
d62a17ae 14442void bgp_route_init(void)
14443{
14444 afi_t afi;
14445 safi_t safi;
14446
14447 /* Init BGP distance table. */
05c7a1cc 14448 FOREACH_AFI_SAFI (afi, safi)
960035b2 14449 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14450
14451 /* IPv4 BGP commands. */
14452 install_element(BGP_NODE, &bgp_table_map_cmd);
14453 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14454 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14455
554b3b10 14456 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14457
14458 /* IPv4 unicast configuration. */
14459 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14460 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14461 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14462
554b3b10 14463 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14464
14465 /* IPv4 multicast configuration. */
14466 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14467 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14468 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14469 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14470
14471 /* IPv4 labeled-unicast configuration. */
fb985e0c 14472 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14473 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14474
d62a17ae 14475 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14476 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14477 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14478 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14479 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14480 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14481 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14482 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14483
14484 install_element(VIEW_NODE,
14485 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14486 install_element(VIEW_NODE,
14487 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14488 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14489 install_element(VIEW_NODE,
14490 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14491#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14492 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14493#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14494 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14495 install_element(VIEW_NODE,
44c69747 14496 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14497
d62a17ae 14498 /* BGP dampening clear commands */
14499 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14500 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14501
d62a17ae 14502 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14503 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14504
14505 /* prefix count */
14506 install_element(ENABLE_NODE,
14507 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14508#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14509 install_element(ENABLE_NODE,
14510 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14511#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14512
d62a17ae 14513 /* New config IPv6 BGP commands. */
14514 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14515 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14516 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14517
554b3b10 14518 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14519
14520 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14521
fb985e0c
DA
14522 /* IPv6 labeled unicast address family. */
14523 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14524 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14525
d62a17ae 14526 install_element(BGP_NODE, &bgp_distance_cmd);
14527 install_element(BGP_NODE, &no_bgp_distance_cmd);
14528 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14529 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14530 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14531 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14532 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14533 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14534 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14535 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14536 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14537 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14538 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14539 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14540 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14541
ef5f4b23 14542 /* BGP dampening */
d9ce5113
CS
14543 install_element(BGP_NODE, &bgp_dampening_cmd);
14544 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14545 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14546 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14547 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14548 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14549 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14550
14551 /* Large Communities */
14552 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14553 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14554
14555 /* show bgp ipv4 flowspec detailed */
14556 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14557
2a0e69ae 14558 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14559 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14560}
14561
14562void bgp_route_finish(void)
14563{
14564 afi_t afi;
14565 safi_t safi;
14566
05c7a1cc
QY
14567 FOREACH_AFI_SAFI (afi, safi) {
14568 bgp_table_unlock(bgp_distance_table[afi][safi]);
14569 bgp_distance_table[afi][safi] = NULL;
14570 }
228da428 14571}