]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: Allow NULL to be passed in for ecommunity_free
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
6401252f 73#include "bgpd/bgp_trace.h"
718e3744 74
49e5a4a0 75#ifdef ENABLE_BGP_VNC
f8b6f499
LB
76#include "bgpd/rfapi/rfapi_backend.h"
77#include "bgpd/rfapi/vnc_import_bgp.h"
78#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 79#endif
aee875b5
PG
80#include "bgpd/bgp_encap_types.h"
81#include "bgpd/bgp_encap_tlv.h"
684a7227 82#include "bgpd/bgp_evpn.h"
0a50c248 83#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 84#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 85#include "bgpd/bgp_flowspec.h"
98a9dbc7 86#include "bgpd/bgp_flowspec_util.h"
45918cfb 87#include "bgpd/bgp_pbr.h"
37a87b8f
CS
88#include "northbound.h"
89#include "northbound_cli.h"
90#include "bgpd/bgp_nb.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
718e3744 96/* Extern from bgp_dump.c */
dde72586
SH
97extern const char *bgp_origin_str[];
98extern const char *bgp_origin_long_str[];
36235319 99const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 100/* PMSI strings. */
101#define PMSI_TNLTYPE_STR_NO_INFO "No info"
102#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
103static const struct message bgp_pmsi_tnltype_str[] = {
104 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
105 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
106 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
107 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
108 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
109 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
110 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
111 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 112 {0}
113};
b7d08f5a 114
9df8b37c
PZ
115#define VRFID_NONE_STR "-"
116
4a11bf2c 117DEFINE_HOOK(bgp_process,
9bcb3eef
DS
118 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
119 struct peer *peer, bool withdraw),
120 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c 121
4056a5f6
RZ
122/** Test if path is suppressed. */
123static bool bgp_path_suppressed(struct bgp_path_info *pi)
124{
125 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
126 return false;
127
128 return listcount(pi->extra->aggr_suppressors) > 0;
129}
4a11bf2c 130
9bcb3eef 131struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 132 safi_t safi, const struct prefix *p,
d62a17ae 133 struct prefix_rd *prd)
134{
9bcb3eef
DS
135 struct bgp_dest *dest;
136 struct bgp_dest *pdest = NULL;
d62a17ae 137
138 assert(table);
d62a17ae 139
140 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
141 || (safi == SAFI_EVPN)) {
9bcb3eef 142 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 143
9bcb3eef
DS
144 if (!bgp_dest_has_bgp_path_info_data(pdest))
145 bgp_dest_set_bgp_table_info(
146 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 147 else
9bcb3eef
DS
148 bgp_dest_unlock_node(pdest);
149 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 150 }
718e3744 151
9bcb3eef 152 dest = bgp_node_get(table, p);
718e3744 153
d62a17ae 154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN))
9bcb3eef 156 dest->pdest = pdest;
718e3744 157
9bcb3eef 158 return dest;
718e3744 159}
6b0655a2 160
9bcb3eef 161struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 162 safi_t safi, const struct prefix *p,
d62a17ae 163 struct prefix_rd *prd)
128ea8ab 164{
9bcb3eef
DS
165 struct bgp_dest *dest;
166 struct bgp_dest *pdest = NULL;
128ea8ab 167
d62a17ae 168 if (!table)
169 return NULL;
128ea8ab 170
d62a17ae 171 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
172 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
173 pdest = bgp_node_lookup(table, (struct prefix *)prd);
174 if (!pdest)
d62a17ae 175 return NULL;
128ea8ab 176
9bcb3eef
DS
177 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
178 bgp_dest_unlock_node(pdest);
d62a17ae 179 return NULL;
180 }
128ea8ab 181
9bcb3eef 182 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 183 }
128ea8ab 184
9bcb3eef 185 dest = bgp_node_lookup(table, p);
128ea8ab 186
9bcb3eef 187 return dest;
128ea8ab 188}
189
18ee8310
DS
190/* Allocate bgp_path_info_extra */
191static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 192{
4b7e6066
DS
193 struct bgp_path_info_extra *new;
194 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
195 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
196 new->label[0] = MPLS_INVALID_LABEL;
197 new->num_labels = 0;
3e3708cb
PG
198 new->bgp_fs_pbr = NULL;
199 new->bgp_fs_iprule = NULL;
d62a17ae 200 return new;
fb982c25
PJ
201}
202
a2e219fe 203void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 204{
4b7e6066 205 struct bgp_path_info_extra *e;
d62a17ae 206
c93a3b77
DS
207 if (!extra || !*extra)
208 return;
d62a17ae 209
c93a3b77
DS
210 e = *extra;
211 if (e->damp_info)
a935f597
DA
212 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
213 e->damp_info->safi);
d62a17ae 214
c93a3b77
DS
215 e->damp_info = NULL;
216 if (e->parent) {
40381db7 217 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 218
40381db7 219 if (bpi->net) {
0e70e6c8
DL
220 /* FIXME: since multiple e may have the same e->parent
221 * and e->parent->net is holding a refcount for each
222 * of them, we need to do some fudging here.
223 *
40381db7
DS
224 * WARNING: if bpi->net->lock drops to 0, bpi may be
225 * freed as well (because bpi->net was holding the
226 * last reference to bpi) => write after free!
0e70e6c8
DL
227 */
228 unsigned refcount;
229
40381db7 230 bpi = bgp_path_info_lock(bpi);
c10e14e9 231 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 232 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 233 if (!refcount)
40381db7
DS
234 bpi->net = NULL;
235 bgp_path_info_unlock(bpi);
0e70e6c8 236 }
18ee8310 237 bgp_path_info_unlock(e->parent);
c93a3b77 238 e->parent = NULL;
d62a17ae 239 }
c93a3b77
DS
240
241 if (e->bgp_orig)
242 bgp_unlock(e->bgp_orig);
c26edcda 243
ce3c0614
PG
244 if ((*extra)->bgp_fs_iprule)
245 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 246 if ((*extra)->bgp_fs_pbr)
6a154c88 247 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 248 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
249}
250
18ee8310
DS
251/* Get bgp_path_info extra information for the given bgp_path_info, lazy
252 * allocated if required.
fb982c25 253 */
40381db7 254struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 255{
40381db7
DS
256 if (!pi->extra)
257 pi->extra = bgp_path_info_extra_new();
258 return pi->extra;
fb982c25
PJ
259}
260
718e3744 261/* Free bgp route information. */
9b6d8fcf 262static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 263{
05864da7 264 bgp_attr_unintern(&path->attr);
fb018d25 265
9b6d8fcf
DS
266 bgp_unlink_nexthop(path);
267 bgp_path_info_extra_free(&path->extra);
268 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
269 if (path->net)
270 bgp_addpath_free_info_data(&path->tx_addpath,
271 &path->net->tx_addpath);
718e3744 272
9b6d8fcf 273 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 274
9b6d8fcf 275 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 276}
277
9b6d8fcf 278struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 279{
9b6d8fcf
DS
280 path->lock++;
281 return path;
200df115 282}
283
9b6d8fcf 284struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 285{
9b6d8fcf
DS
286 assert(path && path->lock > 0);
287 path->lock--;
d62a17ae 288
9b6d8fcf 289 if (path->lock == 0) {
200df115 290#if 0
291 zlog_debug ("%s: unlocked and freeing", __func__);
292 zlog_backtrace (LOG_DEBUG);
293#endif
9b6d8fcf 294 bgp_path_info_free(path);
d62a17ae 295 return NULL;
296 }
200df115 297
298#if 0
9b6d8fcf 299 if (path->lock == 1)
200df115 300 {
301 zlog_debug ("%s: unlocked to 1", __func__);
302 zlog_backtrace (LOG_DEBUG);
303 }
304#endif
d62a17ae 305
9b6d8fcf 306 return path;
200df115 307}
308
f009ff26 309/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 310static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 311{
312 struct peer *peer;
313 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 314 bool set_flag = false;
f009ff26 315 struct bgp *bgp = NULL;
316 struct bgp_table *table = NULL;
317 afi_t afi = 0;
318 safi_t safi = 0;
f009ff26 319
320 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
321 * then the route selection is deferred
322 */
9bcb3eef 323 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 324 return 0;
325
9bcb3eef 326 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 327 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 328 zlog_debug(
56ca3b5b
DL
329 "Route %pBD is in workqueue and being processed, not deferred.",
330 dest);
b54892e0 331
5f9c1aa2 332 return 0;
333 }
334
9bcb3eef 335 table = bgp_dest_table(dest);
f009ff26 336 if (table) {
337 bgp = table->bgp;
338 afi = table->afi;
339 safi = table->safi;
340 }
341
9bcb3eef 342 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 343 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
344 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
345 continue;
346
347 /* Route selection is deferred if there is a stale path which
348 * which indicates peer is in restart mode
349 */
36235319
QY
350 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
351 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 352 set_flag = true;
f009ff26 353 } else {
354 /* If the peer is graceful restart capable and peer is
355 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
356 */
357 peer = old_pi->peer;
36235319
QY
358 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
359 && BGP_PEER_RESTARTING_MODE(peer)
360 && (old_pi
361 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 362 set_flag = true;
f009ff26 363 }
364 }
365 if (set_flag)
366 break;
367 }
368
369 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
370 * is active
371 */
2ba1fe69 372 if (set_flag && table) {
f009ff26 373 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
374 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
375 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 376 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 377 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
378 zlog_debug("DEFER route %pBD, dest %p", dest,
379 dest);
f009ff26 380 return 0;
381 }
382 }
383 return -1;
384}
385
9bcb3eef 386void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 387{
4b7e6066 388 struct bgp_path_info *top;
718e3744 389
9bcb3eef 390 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 391
6f94b685 392 pi->next = top;
40381db7 393 pi->prev = NULL;
d62a17ae 394 if (top)
40381db7 395 top->prev = pi;
9bcb3eef 396 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 397
40381db7 398 bgp_path_info_lock(pi);
9bcb3eef 399 bgp_dest_lock_node(dest);
40381db7 400 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 401 bgp_dest_set_defer_flag(dest, false);
718e3744 402}
403
d62a17ae 404/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 405 completion callback *only* */
9bcb3eef 406void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 407{
40381db7
DS
408 if (pi->next)
409 pi->next->prev = pi->prev;
410 if (pi->prev)
411 pi->prev->next = pi->next;
d62a17ae 412 else
9bcb3eef 413 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 414
40381db7
DS
415 bgp_path_info_mpath_dequeue(pi);
416 bgp_path_info_unlock(pi);
9bcb3eef 417 bgp_dest_unlock_node(dest);
718e3744 418}
419
9bcb3eef 420void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 421{
9bcb3eef 422 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 423 /* set of previous already took care of pcount */
40381db7 424 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 425}
426
18ee8310 427/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
428 called when a route is deleted and then quickly re-added before the
429 deletion has been processed */
9bcb3eef 430void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 431{
9bcb3eef 432 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 433 /* unset of previous already took care of pcount */
40381db7 434 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
435}
436
d62a17ae 437/* Adjust pcount as required */
9bcb3eef 438static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 439{
d62a17ae 440 struct bgp_table *table;
67174041 441
9bcb3eef 442 assert(dest && bgp_dest_table(dest));
40381db7 443 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 444
9bcb3eef 445 table = bgp_dest_table(dest);
67174041 446
40381db7 447 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 448 return;
449
40381db7
DS
450 if (!BGP_PATH_COUNTABLE(pi)
451 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 452
40381db7 453 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 454
455 /* slight hack, but more robust against errors. */
40381db7
DS
456 if (pi->peer->pcount[table->afi][table->safi])
457 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 458 else
450971aa 459 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 460 "Asked to decrement 0 prefix count for peer");
40381db7
DS
461 } else if (BGP_PATH_COUNTABLE(pi)
462 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
463 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
464 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 465 }
1a392d46
PJ
466}
467
40381db7
DS
468static int bgp_label_index_differs(struct bgp_path_info *pi1,
469 struct bgp_path_info *pi2)
28d58fd7 470{
40381db7 471 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 472}
1a392d46 473
18ee8310 474/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
475 * This is here primarily to keep prefix-count in check.
476 */
9bcb3eef 477void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 478 uint32_t flag)
1a392d46 479{
40381db7 480 SET_FLAG(pi->flags, flag);
d62a17ae 481
482 /* early bath if we know it's not a flag that changes countability state
483 */
484 if (!CHECK_FLAG(flag,
1defdda8 485 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 486 return;
487
9bcb3eef 488 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
489}
490
9bcb3eef 491void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 492 uint32_t flag)
1a392d46 493{
40381db7 494 UNSET_FLAG(pi->flags, flag);
d62a17ae 495
496 /* early bath if we know it's not a flag that changes countability state
497 */
498 if (!CHECK_FLAG(flag,
1defdda8 499 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 500 return;
501
9bcb3eef 502 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
503}
504
718e3744 505/* Get MED value. If MED value is missing and "bgp bestpath
506 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 507static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 508{
509 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
510 return attr->med;
511 else {
892fedb6 512 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 513 return BGP_MED_MAX;
514 else
515 return 0;
516 }
718e3744 517}
518
40381db7 519void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 520{
40381db7
DS
521 if (pi->addpath_rx_id)
522 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
523 pi->addpath_rx_id);
d62a17ae 524 else
40381db7 525 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 526}
9fbdd100 527
d62a17ae 528/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
529 */
18ee8310
DS
530static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
531 struct bgp_path_info *exist, int *paths_eq,
532 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
533 char *pfx_buf, afi_t afi, safi_t safi,
534 enum bgp_path_selection_reason *reason)
d62a17ae 535{
536 struct attr *newattr, *existattr;
537 bgp_peer_sort_t new_sort;
538 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
539 uint32_t new_pref;
540 uint32_t exist_pref;
541 uint32_t new_med;
542 uint32_t exist_med;
543 uint32_t new_weight;
544 uint32_t exist_weight;
d62a17ae 545 uint32_t newm, existm;
546 struct in_addr new_id;
547 struct in_addr exist_id;
548 int new_cluster;
549 int exist_cluster;
550 int internal_as_route;
551 int confed_as_route;
04d14c8b 552 int ret = 0;
d62a17ae 553 char new_buf[PATH_ADDPATH_STR_BUFFER];
554 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
555 uint32_t new_mm_seq;
556 uint32_t exist_mm_seq;
6d8c603a 557 int nh_cmp;
d071f237
AK
558 esi_t *exist_esi;
559 esi_t *new_esi;
560 bool same_esi;
561 bool old_proxy;
562 bool new_proxy;
33c6e933 563 bool new_origin, exist_origin;
d62a17ae 564
565 *paths_eq = 0;
566
567 /* 0. Null check. */
568 if (new == NULL) {
fdf81fa0 569 *reason = bgp_path_selection_none;
d62a17ae 570 if (debug)
571 zlog_debug("%s: new is NULL", pfx_buf);
572 return 0;
573 }
2ec1e66f 574
d62a17ae 575 if (debug)
18ee8310 576 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 577
d62a17ae 578 if (exist == NULL) {
fdf81fa0 579 *reason = bgp_path_selection_first;
d62a17ae 580 if (debug)
581 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
582 new_buf);
583 return 1;
584 }
2ec1e66f 585
d62a17ae 586 if (debug) {
18ee8310 587 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 588 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
589 pfx_buf, new_buf, new->flags, exist_buf,
590 exist->flags);
591 }
8ff56318 592
d62a17ae 593 newattr = new->attr;
594 existattr = exist->attr;
595
596 /* For EVPN routes, we cannot just go by local vs remote, we have to
597 * look at the MAC mobility sequence number, if present.
598 */
599 if (safi == SAFI_EVPN) {
600 /* This is an error condition described in RFC 7432 Section
601 * 15.2. The RFC
602 * states that in this scenario "the PE MUST alert the operator"
603 * but it
604 * does not state what other action to take. In order to provide
605 * some
606 * consistency in this scenario we are going to prefer the path
607 * with the
608 * sticky flag.
609 */
610 if (newattr->sticky != existattr->sticky) {
611 if (!debug) {
9bcb3eef
DS
612 prefix2str(
613 bgp_dest_get_prefix(new->net), pfx_buf,
614 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
615 bgp_path_info_path_with_addpath_rx_str(new,
616 new_buf);
617 bgp_path_info_path_with_addpath_rx_str(
618 exist, exist_buf);
d62a17ae 619 }
620
621 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 622 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
623 if (debug)
624 zlog_debug(
625 "%s: %s wins over %s due to sticky MAC flag",
626 pfx_buf, new_buf, exist_buf);
d62a17ae 627 return 1;
628 }
629
630 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 631 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
632 if (debug)
633 zlog_debug(
634 "%s: %s loses to %s due to sticky MAC flag",
635 pfx_buf, new_buf, exist_buf);
d62a17ae 636 return 0;
637 }
638 }
128ea8ab 639
d071f237
AK
640 new_esi = bgp_evpn_attr_get_esi(newattr);
641 exist_esi = bgp_evpn_attr_get_esi(existattr);
642 if (bgp_evpn_is_esi_valid(new_esi) &&
643 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
644 same_esi = true;
645 } else {
646 same_esi = false;
647 }
648
649 /* If both paths have the same non-zero ES and
650 * one path is local it wins.
651 * PS: Note the local path wins even if the remote
652 * has the higher MM seq. The local path's
653 * MM seq will be fixed up to match the highest
654 * rem seq, subsequently.
655 */
656 if (same_esi) {
657 char esi_buf[ESI_STR_LEN];
658
659 if (bgp_evpn_is_path_local(bgp, new)) {
660 *reason = bgp_path_selection_evpn_local_path;
661 if (debug)
662 zlog_debug(
663 "%s: %s wins over %s as ES %s is same and local",
664 pfx_buf, new_buf, exist_buf,
665 esi_to_str(new_esi, esi_buf,
666 sizeof(esi_buf)));
667 return 1;
668 }
669 if (bgp_evpn_is_path_local(bgp, exist)) {
670 *reason = bgp_path_selection_evpn_local_path;
671 if (debug)
672 zlog_debug(
673 "%s: %s loses to %s as ES %s is same and local",
674 pfx_buf, new_buf, exist_buf,
675 esi_to_str(new_esi, esi_buf,
676 sizeof(esi_buf)));
677 return 0;
678 }
679 }
680
d62a17ae 681 new_mm_seq = mac_mobility_seqnum(newattr);
682 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 683
d62a17ae 684 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 685 *reason = bgp_path_selection_evpn_seq;
d62a17ae 686 if (debug)
687 zlog_debug(
688 "%s: %s wins over %s due to MM seq %u > %u",
689 pfx_buf, new_buf, exist_buf, new_mm_seq,
690 exist_mm_seq);
691 return 1;
692 }
8ff56318 693
d62a17ae 694 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 695 *reason = bgp_path_selection_evpn_seq;
d62a17ae 696 if (debug)
697 zlog_debug(
698 "%s: %s loses to %s due to MM seq %u < %u",
699 pfx_buf, new_buf, exist_buf, new_mm_seq,
700 exist_mm_seq);
701 return 0;
702 }
6d8c603a 703
d071f237
AK
704 /* if the sequence numbers and ESI are the same and one path
705 * is non-proxy it wins (over proxy)
706 */
707 new_proxy = bgp_evpn_attr_is_proxy(newattr);
708 old_proxy = bgp_evpn_attr_is_proxy(existattr);
709 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
710 old_proxy != new_proxy) {
711 if (!new_proxy) {
712 *reason = bgp_path_selection_evpn_non_proxy;
713 if (debug)
714 zlog_debug(
715 "%s: %s wins over %s, same seq/es and non-proxy",
716 pfx_buf, new_buf, exist_buf);
717 return 1;
718 }
719
720 *reason = bgp_path_selection_evpn_non_proxy;
721 if (debug)
722 zlog_debug(
723 "%s: %s loses to %s, same seq/es and non-proxy",
724 pfx_buf, new_buf, exist_buf);
725 return 0;
726 }
727
6d8c603a
AK
728 /*
729 * if sequence numbers are the same path with the lowest IP
730 * wins
731 */
732 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
733 if (nh_cmp < 0) {
fdf81fa0 734 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
735 if (debug)
736 zlog_debug(
23d0a753 737 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 738 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 739 &new->attr->nexthop);
6d8c603a
AK
740 return 1;
741 }
742 if (nh_cmp > 0) {
fdf81fa0 743 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
744 if (debug)
745 zlog_debug(
23d0a753 746 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 747 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 748 &new->attr->nexthop);
6d8c603a
AK
749 return 0;
750 }
d62a17ae 751 }
9fbdd100 752
d62a17ae 753 /* 1. Weight check. */
d62a17ae 754 new_weight = newattr->weight;
755 exist_weight = existattr->weight;
8ff56318 756
d62a17ae 757 if (new_weight > exist_weight) {
fdf81fa0 758 *reason = bgp_path_selection_weight;
d62a17ae 759 if (debug)
760 zlog_debug("%s: %s wins over %s due to weight %d > %d",
761 pfx_buf, new_buf, exist_buf, new_weight,
762 exist_weight);
763 return 1;
764 }
718e3744 765
d62a17ae 766 if (new_weight < exist_weight) {
fdf81fa0 767 *reason = bgp_path_selection_weight;
d62a17ae 768 if (debug)
769 zlog_debug("%s: %s loses to %s due to weight %d < %d",
770 pfx_buf, new_buf, exist_buf, new_weight,
771 exist_weight);
772 return 0;
773 }
9fbdd100 774
d62a17ae 775 /* 2. Local preference check. */
776 new_pref = exist_pref = bgp->default_local_pref;
777
778 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
779 new_pref = newattr->local_pref;
780 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
781 exist_pref = existattr->local_pref;
782
783 if (new_pref > exist_pref) {
fdf81fa0 784 *reason = bgp_path_selection_local_pref;
d62a17ae 785 if (debug)
786 zlog_debug(
787 "%s: %s wins over %s due to localpref %d > %d",
788 pfx_buf, new_buf, exist_buf, new_pref,
789 exist_pref);
790 return 1;
791 }
718e3744 792
d62a17ae 793 if (new_pref < exist_pref) {
fdf81fa0 794 *reason = bgp_path_selection_local_pref;
d62a17ae 795 if (debug)
796 zlog_debug(
797 "%s: %s loses to %s due to localpref %d < %d",
798 pfx_buf, new_buf, exist_buf, new_pref,
799 exist_pref);
800 return 0;
801 }
9fbdd100 802
d62a17ae 803 /* 3. Local route check. We prefer:
804 * - BGP_ROUTE_STATIC
805 * - BGP_ROUTE_AGGREGATE
806 * - BGP_ROUTE_REDISTRIBUTE
807 */
33c6e933
DS
808 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
809 new->sub_type == BGP_ROUTE_IMPORTED);
810 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
811 exist->sub_type == BGP_ROUTE_IMPORTED);
812
813 if (new_origin && !exist_origin) {
fdf81fa0 814 *reason = bgp_path_selection_local_route;
d62a17ae 815 if (debug)
816 zlog_debug(
817 "%s: %s wins over %s due to preferred BGP_ROUTE type",
818 pfx_buf, new_buf, exist_buf);
819 return 1;
820 }
718e3744 821
33c6e933 822 if (!new_origin && exist_origin) {
fdf81fa0 823 *reason = bgp_path_selection_local_route;
d62a17ae 824 if (debug)
825 zlog_debug(
826 "%s: %s loses to %s due to preferred BGP_ROUTE type",
827 pfx_buf, new_buf, exist_buf);
828 return 0;
6811845b 829 }
718e3744 830
d62a17ae 831 /* 4. AS path length check. */
892fedb6 832 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 833 int exist_hops = aspath_count_hops(existattr->aspath);
834 int exist_confeds = aspath_count_confeds(existattr->aspath);
835
892fedb6 836 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 837 int aspath_hops;
838
839 aspath_hops = aspath_count_hops(newattr->aspath);
840 aspath_hops += aspath_count_confeds(newattr->aspath);
841
842 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 843 *reason = bgp_path_selection_confed_as_path;
d62a17ae 844 if (debug)
845 zlog_debug(
846 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
847 pfx_buf, new_buf, exist_buf,
848 aspath_hops,
849 (exist_hops + exist_confeds));
850 return 1;
851 }
852
853 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 854 *reason = bgp_path_selection_confed_as_path;
d62a17ae 855 if (debug)
856 zlog_debug(
857 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
858 pfx_buf, new_buf, exist_buf,
859 aspath_hops,
860 (exist_hops + exist_confeds));
861 return 0;
862 }
863 } else {
864 int newhops = aspath_count_hops(newattr->aspath);
865
866 if (newhops < exist_hops) {
fdf81fa0 867 *reason = bgp_path_selection_as_path;
d62a17ae 868 if (debug)
869 zlog_debug(
870 "%s: %s wins over %s due to aspath hopcount %d < %d",
871 pfx_buf, new_buf, exist_buf,
872 newhops, exist_hops);
873 return 1;
874 }
875
876 if (newhops > exist_hops) {
fdf81fa0 877 *reason = bgp_path_selection_as_path;
d62a17ae 878 if (debug)
879 zlog_debug(
880 "%s: %s loses to %s due to aspath hopcount %d > %d",
881 pfx_buf, new_buf, exist_buf,
882 newhops, exist_hops);
883 return 0;
884 }
885 }
886 }
9fbdd100 887
d62a17ae 888 /* 5. Origin check. */
889 if (newattr->origin < existattr->origin) {
fdf81fa0 890 *reason = bgp_path_selection_origin;
d62a17ae 891 if (debug)
892 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
893 pfx_buf, new_buf, exist_buf,
894 bgp_origin_long_str[newattr->origin],
895 bgp_origin_long_str[existattr->origin]);
896 return 1;
897 }
718e3744 898
d62a17ae 899 if (newattr->origin > existattr->origin) {
fdf81fa0 900 *reason = bgp_path_selection_origin;
d62a17ae 901 if (debug)
902 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
903 pfx_buf, new_buf, exist_buf,
904 bgp_origin_long_str[newattr->origin],
905 bgp_origin_long_str[existattr->origin]);
906 return 0;
907 }
718e3744 908
d62a17ae 909 /* 6. MED check. */
910 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
911 && aspath_count_hops(existattr->aspath) == 0);
912 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
913 && aspath_count_confeds(existattr->aspath) > 0
914 && aspath_count_hops(newattr->aspath) == 0
915 && aspath_count_hops(existattr->aspath) == 0);
916
892fedb6
DA
917 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
918 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 919 || aspath_cmp_left(newattr->aspath, existattr->aspath)
920 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
921 || internal_as_route) {
922 new_med = bgp_med_value(new->attr, bgp);
923 exist_med = bgp_med_value(exist->attr, bgp);
924
925 if (new_med < exist_med) {
fdf81fa0 926 *reason = bgp_path_selection_med;
d62a17ae 927 if (debug)
928 zlog_debug(
929 "%s: %s wins over %s due to MED %d < %d",
930 pfx_buf, new_buf, exist_buf, new_med,
931 exist_med);
932 return 1;
933 }
8ff56318 934
d62a17ae 935 if (new_med > exist_med) {
fdf81fa0 936 *reason = bgp_path_selection_med;
d62a17ae 937 if (debug)
938 zlog_debug(
939 "%s: %s loses to %s due to MED %d > %d",
940 pfx_buf, new_buf, exist_buf, new_med,
941 exist_med);
942 return 0;
943 }
944 }
9fbdd100 945
d62a17ae 946 /* 7. Peer type check. */
947 new_sort = new->peer->sort;
948 exist_sort = exist->peer->sort;
949
950 if (new_sort == BGP_PEER_EBGP
951 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 952 *reason = bgp_path_selection_peer;
d62a17ae 953 if (debug)
954 zlog_debug(
955 "%s: %s wins over %s due to eBGP peer > iBGP peer",
956 pfx_buf, new_buf, exist_buf);
957 return 1;
958 }
718e3744 959
d62a17ae 960 if (exist_sort == BGP_PEER_EBGP
961 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 962 *reason = bgp_path_selection_peer;
d62a17ae 963 if (debug)
964 zlog_debug(
965 "%s: %s loses to %s due to iBGP peer < eBGP peer",
966 pfx_buf, new_buf, exist_buf);
967 return 0;
968 }
8ff56318 969
d62a17ae 970 /* 8. IGP metric check. */
971 newm = existm = 0;
8ff56318 972
d62a17ae 973 if (new->extra)
974 newm = new->extra->igpmetric;
975 if (exist->extra)
976 existm = exist->extra->igpmetric;
9fbdd100 977
d62a17ae 978 if (newm < existm) {
979 if (debug)
980 zlog_debug(
981 "%s: %s wins over %s due to IGP metric %d < %d",
982 pfx_buf, new_buf, exist_buf, newm, existm);
983 ret = 1;
984 }
718e3744 985
d62a17ae 986 if (newm > existm) {
987 if (debug)
988 zlog_debug(
989 "%s: %s loses to %s due to IGP metric %d > %d",
990 pfx_buf, new_buf, exist_buf, newm, existm);
991 ret = 0;
5e242b0d 992 }
5e242b0d 993
d62a17ae 994 /* 9. Same IGP metric. Compare the cluster list length as
995 representative of IGP hops metric. Rewrite the metric value
996 pair (newm, existm) with the cluster list length. Prefer the
997 path with smaller cluster list length. */
998 if (newm == existm) {
bf0d28dc
DS
999 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1000 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1001 && (mpath_cfg == NULL
1002 || CHECK_FLAG(
1003 mpath_cfg->ibgp_flags,
1004 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1005 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1006 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1007
1008 if (newm < existm) {
1009 if (debug)
1010 zlog_debug(
1011 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1012 pfx_buf, new_buf, exist_buf,
1013 newm, existm);
1014 ret = 1;
1015 }
1016
1017 if (newm > existm) {
1018 if (debug)
1019 zlog_debug(
1020 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1021 pfx_buf, new_buf, exist_buf,
1022 newm, existm);
1023 ret = 0;
1024 }
1025 }
1026 }
31a4638f 1027
d62a17ae 1028 /* 10. confed-external vs. confed-internal */
1029 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1030 if (new_sort == BGP_PEER_CONFED
1031 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1032 *reason = bgp_path_selection_confed;
d62a17ae 1033 if (debug)
1034 zlog_debug(
1035 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1036 pfx_buf, new_buf, exist_buf);
1037 return 1;
1038 }
718e3744 1039
d62a17ae 1040 if (exist_sort == BGP_PEER_CONFED
1041 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1042 *reason = bgp_path_selection_confed;
d62a17ae 1043 if (debug)
1044 zlog_debug(
1045 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1046 pfx_buf, new_buf, exist_buf);
1047 return 0;
1048 }
1049 }
718e3744 1050
d62a17ae 1051 /* 11. Maximum path check. */
1052 if (newm == existm) {
1053 /* If one path has a label but the other does not, do not treat
1054 * them as equals for multipath
1055 */
a4d82a8a 1056 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1057 != (exist->extra
b57ba6d2 1058 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1059 if (debug)
1060 zlog_debug(
1061 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1062 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1063 } else if (CHECK_FLAG(bgp->flags,
1064 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1065
1066 /*
1067 * For the two paths, all comparison steps till IGP
1068 * metric
1069 * have succeeded - including AS_PATH hop count. Since
1070 * 'bgp
1071 * bestpath as-path multipath-relax' knob is on, we
1072 * don't need
1073 * an exact match of AS_PATH. Thus, mark the paths are
1074 * equal.
1075 * That will trigger both these paths to get into the
1076 * multipath
1077 * array.
1078 */
1079 *paths_eq = 1;
1080
1081 if (debug)
1082 zlog_debug(
1083 "%s: %s and %s are equal via multipath-relax",
1084 pfx_buf, new_buf, exist_buf);
1085 } else if (new->peer->sort == BGP_PEER_IBGP) {
1086 if (aspath_cmp(new->attr->aspath,
1087 exist->attr->aspath)) {
1088 *paths_eq = 1;
1089
1090 if (debug)
1091 zlog_debug(
1092 "%s: %s and %s are equal via matching aspaths",
1093 pfx_buf, new_buf, exist_buf);
1094 }
1095 } else if (new->peer->as == exist->peer->as) {
1096 *paths_eq = 1;
1097
1098 if (debug)
1099 zlog_debug(
1100 "%s: %s and %s are equal via same remote-as",
1101 pfx_buf, new_buf, exist_buf);
1102 }
1103 } else {
1104 /*
1105 * TODO: If unequal cost ibgp multipath is enabled we can
1106 * mark the paths as equal here instead of returning
1107 */
1108 if (debug) {
1109 if (ret == 1)
1110 zlog_debug(
1111 "%s: %s wins over %s after IGP metric comparison",
1112 pfx_buf, new_buf, exist_buf);
1113 else
1114 zlog_debug(
1115 "%s: %s loses to %s after IGP metric comparison",
1116 pfx_buf, new_buf, exist_buf);
1117 }
fdf81fa0 1118 *reason = bgp_path_selection_igp_metric;
d62a17ae 1119 return ret;
1120 }
718e3744 1121
d62a17ae 1122 /* 12. If both paths are external, prefer the path that was received
1123 first (the oldest one). This step minimizes route-flap, since a
1124 newer path won't displace an older one, even if it was the
1125 preferred route based on the additional decision criteria below. */
892fedb6 1126 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1127 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1128 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1129 *reason = bgp_path_selection_older;
d62a17ae 1130 if (debug)
1131 zlog_debug(
1132 "%s: %s wins over %s due to oldest external",
1133 pfx_buf, new_buf, exist_buf);
1134 return 1;
1135 }
9fbdd100 1136
1defdda8 1137 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1138 *reason = bgp_path_selection_older;
d62a17ae 1139 if (debug)
1140 zlog_debug(
1141 "%s: %s loses to %s due to oldest external",
1142 pfx_buf, new_buf, exist_buf);
1143 return 0;
1144 }
1145 }
718e3744 1146
d62a17ae 1147 /* 13. Router-ID comparision. */
1148 /* If one of the paths is "stale", the corresponding peer router-id will
1149 * be 0 and would always win over the other path. If originator id is
1150 * used for the comparision, it will decide which path is better.
1151 */
1152 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1153 new_id.s_addr = newattr->originator_id.s_addr;
1154 else
1155 new_id.s_addr = new->peer->remote_id.s_addr;
1156 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1157 exist_id.s_addr = existattr->originator_id.s_addr;
1158 else
1159 exist_id.s_addr = exist->peer->remote_id.s_addr;
1160
1161 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1162 *reason = bgp_path_selection_router_id;
d62a17ae 1163 if (debug)
1164 zlog_debug(
1165 "%s: %s wins over %s due to Router-ID comparison",
1166 pfx_buf, new_buf, exist_buf);
1167 return 1;
1168 }
718e3744 1169
d62a17ae 1170 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1171 *reason = bgp_path_selection_router_id;
d62a17ae 1172 if (debug)
1173 zlog_debug(
1174 "%s: %s loses to %s due to Router-ID comparison",
1175 pfx_buf, new_buf, exist_buf);
1176 return 0;
1177 }
9fbdd100 1178
d62a17ae 1179 /* 14. Cluster length comparision. */
1180 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1181 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1182
1183 if (new_cluster < exist_cluster) {
fdf81fa0 1184 *reason = bgp_path_selection_cluster_length;
d62a17ae 1185 if (debug)
1186 zlog_debug(
1187 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1188 pfx_buf, new_buf, exist_buf, new_cluster,
1189 exist_cluster);
1190 return 1;
1191 }
718e3744 1192
d62a17ae 1193 if (new_cluster > exist_cluster) {
fdf81fa0 1194 *reason = bgp_path_selection_cluster_length;
d62a17ae 1195 if (debug)
1196 zlog_debug(
1197 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1198 pfx_buf, new_buf, exist_buf, new_cluster,
1199 exist_cluster);
1200 return 0;
1201 }
9fbdd100 1202
d62a17ae 1203 /* 15. Neighbor address comparision. */
1204 /* Do this only if neither path is "stale" as stale paths do not have
1205 * valid peer information (as the connection may or may not be up).
1206 */
1defdda8 1207 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1208 *reason = bgp_path_selection_stale;
d62a17ae 1209 if (debug)
1210 zlog_debug(
1211 "%s: %s wins over %s due to latter path being STALE",
1212 pfx_buf, new_buf, exist_buf);
1213 return 1;
1214 }
0de5153c 1215
1defdda8 1216 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1217 *reason = bgp_path_selection_stale;
d62a17ae 1218 if (debug)
1219 zlog_debug(
1220 "%s: %s loses to %s due to former path being STALE",
1221 pfx_buf, new_buf, exist_buf);
1222 return 0;
1223 }
718e3744 1224
d62a17ae 1225 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1226 if (new->peer->su_remote == NULL) {
1227 *reason = bgp_path_selection_local_configured;
d62a17ae 1228 return 0;
fdf81fa0
DS
1229 }
1230 if (exist->peer->su_remote == NULL) {
1231 *reason = bgp_path_selection_local_configured;
d62a17ae 1232 return 1;
fdf81fa0 1233 }
9fbdd100 1234
d62a17ae 1235 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1236
1237 if (ret == 1) {
fdf81fa0 1238 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1239 if (debug)
1240 zlog_debug(
1241 "%s: %s loses to %s due to Neighor IP comparison",
1242 pfx_buf, new_buf, exist_buf);
1243 return 0;
1244 }
1245
1246 if (ret == -1) {
fdf81fa0 1247 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1248 if (debug)
1249 zlog_debug(
1250 "%s: %s wins over %s due to Neighor IP comparison",
1251 pfx_buf, new_buf, exist_buf);
1252 return 1;
1253 }
9fbdd100 1254
fdf81fa0 1255 *reason = bgp_path_selection_default;
d62a17ae 1256 if (debug)
1257 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1258 pfx_buf, new_buf, exist_buf);
718e3744 1259
d62a17ae 1260 return 1;
718e3744 1261}
1262
d071f237
AK
1263
1264int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1265 struct bgp_path_info *exist, int *paths_eq)
1266{
1267 enum bgp_path_selection_reason reason;
1268 char pfx_buf[PREFIX2STR_BUFFER];
1269
1270 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1271 AFI_L2VPN, SAFI_EVPN, &reason);
1272}
1273
65efcfce
LB
1274/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1275 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1276 * multipath is enabled
65efcfce 1277 * This version is compatible with */
18ee8310
DS
1278int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1279 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1280 afi_t afi, safi_t safi,
1281 enum bgp_path_selection_reason *reason)
d62a17ae 1282{
1283 int paths_eq;
1284 int ret;
18ee8310 1285 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1286 afi, safi, reason);
d62a17ae 1287
1288 if (paths_eq)
1289 ret = 0;
1290 else {
1291 if (ret == 1)
1292 ret = -1;
1293 else
1294 ret = 1;
1295 }
1296 return ret;
65efcfce
LB
1297}
1298
5a1ae2c2
DS
1299static enum filter_type bgp_input_filter(struct peer *peer,
1300 const struct prefix *p,
d62a17ae 1301 struct attr *attr, afi_t afi,
1302 safi_t safi)
718e3744 1303{
d62a17ae 1304 struct bgp_filter *filter;
6401252f 1305 enum filter_type ret = FILTER_PERMIT;
718e3744 1306
d62a17ae 1307 filter = &peer->filter[afi][safi];
718e3744 1308
d62a17ae 1309#define FILTER_EXIST_WARN(F, f, filter) \
1310 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1311 zlog_debug("%s: Could not find configured input %s-list %s!", \
1312 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1313
1314 if (DISTRIBUTE_IN_NAME(filter)) {
1315 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1316
6401252f
QY
1317 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1318 == FILTER_DENY) {
1319 ret = FILTER_DENY;
1320 goto done;
1321 }
d62a17ae 1322 }
1323
1324 if (PREFIX_LIST_IN_NAME(filter)) {
1325 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1326
6401252f
QY
1327 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1328 == PREFIX_DENY) {
1329 ret = FILTER_DENY;
1330 goto done;
1331 }
d62a17ae 1332 }
1333
1334 if (FILTER_LIST_IN_NAME(filter)) {
1335 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1336
1337 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1338 == AS_FILTER_DENY) {
1339 ret = FILTER_DENY;
1340 goto done;
1341 }
d62a17ae 1342 }
1343
6401252f 1344done:
c7bb4f00 1345 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1346 char pfxprint[PREFIX2STR_BUFFER];
1347
1348 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1349 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1350 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1351 }
1352
1353 return ret;
650f76c2 1354#undef FILTER_EXIST_WARN
718e3744 1355}
1356
b8685f9b
DS
1357static enum filter_type bgp_output_filter(struct peer *peer,
1358 const struct prefix *p,
d62a17ae 1359 struct attr *attr, afi_t afi,
1360 safi_t safi)
718e3744 1361{
d62a17ae 1362 struct bgp_filter *filter;
6401252f 1363 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1364
1365 filter = &peer->filter[afi][safi];
1366
1367#define FILTER_EXIST_WARN(F, f, filter) \
1368 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1369 zlog_debug("%s: Could not find configured output %s-list %s!", \
1370 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1371
d62a17ae 1372 if (DISTRIBUTE_OUT_NAME(filter)) {
1373 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1374
6401252f
QY
1375 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1376 == FILTER_DENY) {
1377 ret = FILTER_DENY;
1378 goto done;
1379 }
d62a17ae 1380 }
1381
1382 if (PREFIX_LIST_OUT_NAME(filter)) {
1383 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1384
d62a17ae 1385 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1386 == PREFIX_DENY) {
1387 ret = FILTER_DENY;
1388 goto done;
1389 }
d62a17ae 1390 }
718e3744 1391
d62a17ae 1392 if (FILTER_LIST_OUT_NAME(filter)) {
1393 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1394
d62a17ae 1395 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1396 == AS_FILTER_DENY) {
1397 ret = FILTER_DENY;
1398 goto done;
1399 }
1400 }
1401
c7bb4f00 1402 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1403 char pfxprint[PREFIX2STR_BUFFER];
1404
1405 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1406 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1407 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1408 }
718e3744 1409
6401252f
QY
1410done:
1411 return ret;
650f76c2 1412#undef FILTER_EXIST_WARN
718e3744 1413}
1414
1415/* If community attribute includes no_export then return 1. */
3dc339cd 1416static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1417{
1418 if (attr->community) {
1419 /* NO_ADVERTISE check. */
1420 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1421 return true;
d62a17ae 1422
1423 /* NO_EXPORT check. */
1424 if (peer->sort == BGP_PEER_EBGP
1425 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1426 return true;
d62a17ae 1427
1428 /* NO_EXPORT_SUBCONFED check. */
1429 if (peer->sort == BGP_PEER_EBGP
1430 || peer->sort == BGP_PEER_CONFED)
1431 if (community_include(attr->community,
1432 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1433 return true;
d62a17ae 1434 }
3dc339cd 1435 return false;
718e3744 1436}
1437
1438/* Route reflection loop check. */
3dc339cd 1439static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1440{
d62a17ae 1441 struct in_addr cluster_id;
718e3744 1442
d62a17ae 1443 if (attr->cluster) {
1444 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1445 cluster_id = peer->bgp->cluster_id;
1446 else
1447 cluster_id = peer->bgp->router_id;
1448
1449 if (cluster_loop_check(attr->cluster, cluster_id))
3dc339cd 1450 return true;
d62a17ae 1451 }
3dc339cd 1452 return false;
718e3744 1453}
6b0655a2 1454
5a1ae2c2 1455static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1456 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1457 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1458 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1459{
d62a17ae 1460 struct bgp_filter *filter;
82b692c0
LK
1461 struct bgp_path_info rmap_path = { 0 };
1462 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1463 route_map_result_t ret;
1464 struct route_map *rmap = NULL;
718e3744 1465
d62a17ae 1466 filter = &peer->filter[afi][safi];
718e3744 1467
d62a17ae 1468 /* Apply default weight value. */
1469 if (peer->weight[afi][safi])
1470 attr->weight = peer->weight[afi][safi];
718e3744 1471
d62a17ae 1472 if (rmap_name) {
1473 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1474
d62a17ae 1475 if (rmap == NULL)
1476 return RMAP_DENY;
1477 } else {
1478 if (ROUTE_MAP_IN_NAME(filter)) {
1479 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1480
d62a17ae 1481 if (rmap == NULL)
1482 return RMAP_DENY;
1483 }
1484 }
0b16f239 1485
d62a17ae 1486 /* Route map apply. */
1487 if (rmap) {
40381db7 1488 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1489 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1490 rmap_path.peer = peer;
1491 rmap_path.attr = attr;
82b692c0 1492 rmap_path.extra = &extra;
9bcb3eef 1493 rmap_path.net = dest;
196c6b09 1494
82b692c0
LK
1495 extra.num_labels = num_labels;
1496 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1497 memcpy(extra.label, label,
1498 num_labels * sizeof(mpls_label_t));
718e3744 1499
d62a17ae 1500 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1501
d62a17ae 1502 /* Apply BGP route map to the attribute. */
40381db7 1503 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1504
d62a17ae 1505 peer->rmap_type = 0;
0b16f239 1506
1f2263be 1507 if (ret == RMAP_DENYMATCH)
d62a17ae 1508 return RMAP_DENY;
0b16f239 1509 }
d62a17ae 1510 return RMAP_PERMIT;
0b16f239
DS
1511}
1512
5f040085 1513static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1514 struct attr *attr, afi_t afi, safi_t safi,
1515 const char *rmap_name)
0b16f239 1516{
40381db7 1517 struct bgp_path_info rmap_path;
d62a17ae 1518 route_map_result_t ret;
1519 struct route_map *rmap = NULL;
d7c0a89a 1520 uint8_t rmap_type;
0b16f239 1521
b787157a
DS
1522 /*
1523 * So if we get to this point and have no rmap_name
1524 * we want to just show the output as it currently
1525 * exists.
1526 */
1527 if (!rmap_name)
1528 return RMAP_PERMIT;
0b16f239 1529
d62a17ae 1530 /* Apply default weight value. */
1531 if (peer->weight[afi][safi])
1532 attr->weight = peer->weight[afi][safi];
0b16f239 1533
b787157a 1534 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1535
b787157a
DS
1536 /*
1537 * If we have a route map name and we do not find
1538 * the routemap that means we have an implicit
1539 * deny.
1540 */
1541 if (rmap == NULL)
1542 return RMAP_DENY;
0b16f239 1543
40381db7 1544 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1545 /* Route map apply. */
b787157a 1546 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1547 rmap_path.peer = peer;
1548 rmap_path.attr = attr;
0b16f239 1549
0f672529 1550 rmap_type = peer->rmap_type;
b787157a 1551 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1552
b787157a 1553 /* Apply BGP route map to the attribute. */
40381db7 1554 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1555
0f672529 1556 peer->rmap_type = rmap_type;
b787157a
DS
1557
1558 if (ret == RMAP_DENYMATCH)
1559 /*
1560 * caller has multiple error paths with bgp_attr_flush()
1561 */
1562 return RMAP_DENY;
ac41b2a2 1563
d62a17ae 1564 return RMAP_PERMIT;
718e3744 1565}
6b0655a2 1566
5000f21c 1567/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1568static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1569 struct peer *peer, struct attr *attr)
1570{
1571 if (peer->sort == BGP_PEER_EBGP
1572 && (peer_af_flag_check(peer, afi, safi,
1573 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1574 || peer_af_flag_check(peer, afi, safi,
1575 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1576 || peer_af_flag_check(peer, afi, safi,
1577 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1578 || peer_af_flag_check(peer, afi, safi,
1579 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1580 // Take action on the entire aspath
1581 if (peer_af_flag_check(peer, afi, safi,
1582 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1583 || peer_af_flag_check(peer, afi, safi,
1584 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1585 if (peer_af_flag_check(
1586 peer, afi, safi,
1587 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1588 attr->aspath = aspath_replace_private_asns(
bf26b80e 1589 attr->aspath, bgp->as, peer->as);
d62a17ae 1590
1591 // The entire aspath consists of private ASNs so create
1592 // an empty aspath
1593 else if (aspath_private_as_check(attr->aspath))
1594 attr->aspath = aspath_empty_get();
1595
1596 // There are some public and some private ASNs, remove
1597 // the private ASNs
1598 else
1599 attr->aspath = aspath_remove_private_asns(
bf26b80e 1600 attr->aspath, peer->as);
d62a17ae 1601 }
1602
1603 // 'all' was not specified so the entire aspath must be private
1604 // ASNs
1605 // for us to do anything
1606 else if (aspath_private_as_check(attr->aspath)) {
1607 if (peer_af_flag_check(
1608 peer, afi, safi,
1609 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1610 attr->aspath = aspath_replace_private_asns(
bf26b80e 1611 attr->aspath, bgp->as, peer->as);
d62a17ae 1612 else
1613 attr->aspath = aspath_empty_get();
1614 }
1615 }
5000f21c
DS
1616}
1617
c7122e14 1618/* If this is an EBGP peer with as-override */
d62a17ae 1619static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1620 struct peer *peer, struct attr *attr)
1621{
1622 if (peer->sort == BGP_PEER_EBGP
1623 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1624 if (aspath_single_asn_check(attr->aspath, peer->as))
1625 attr->aspath = aspath_replace_specific_asn(
1626 attr->aspath, peer->as, bgp->as);
1627 }
1628}
1629
7f323236
DW
1630void bgp_attr_add_gshut_community(struct attr *attr)
1631{
1632 struct community *old;
1633 struct community *new;
1634 struct community *merge;
1635 struct community *gshut;
1636
1637 old = attr->community;
1638 gshut = community_str2com("graceful-shutdown");
1639
990f4f91 1640 assert(gshut);
1641
7f323236
DW
1642 if (old) {
1643 merge = community_merge(community_dup(old), gshut);
1644
a4d82a8a 1645 if (old->refcnt == 0)
3c1f53de 1646 community_free(&old);
7f323236
DW
1647
1648 new = community_uniq_sort(merge);
3c1f53de 1649 community_free(&merge);
7f323236
DW
1650 } else {
1651 new = community_dup(gshut);
1652 }
1653
3c1f53de 1654 community_free(&gshut);
7f323236
DW
1655 attr->community = new;
1656 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1657
1658 /* When we add the graceful-shutdown community we must also
1659 * lower the local-preference */
1660 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1661 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1662}
1663
1664
e73c112e
MK
1665/* Notify BGP Conditional advertisement scanner process. */
1666void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1667{
1668 struct peer *temp_peer;
1669 struct peer *peer = SUBGRP_PEER(subgrp);
1670 struct listnode *temp_node, *temp_nnode = NULL;
1671 afi_t afi = SUBGRP_AFI(subgrp);
1672 safi_t safi = SUBGRP_SAFI(subgrp);
1673 struct bgp *bgp = SUBGRP_INST(subgrp);
1674 struct bgp_filter *filter = &peer->filter[afi][safi];
1675
1676 if (!ADVERTISE_MAP_NAME(filter))
1677 return;
1678
1679 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1680 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1681 continue;
1682
1683 if (peer != temp_peer)
1684 continue;
1685
1686 temp_peer->advmap_table_change = true;
1687 break;
1688 }
1689}
1690
1691
f2ee6d5c 1692void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1693{
960035b2 1694 if (family == AF_INET) {
975a328e
DA
1695 attr->nexthop.s_addr = INADDR_ANY;
1696 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1697 }
d62a17ae 1698 if (family == AF_INET6)
1699 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1700 if (family == AF_EVPN)
1701 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1702}
1703
9bcb3eef 1704bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1705 struct update_subgroup *subgrp,
7f7940e6
MK
1706 const struct prefix *p, struct attr *attr,
1707 bool skip_rmap_check)
d62a17ae 1708{
1709 struct bgp_filter *filter;
1710 struct peer *from;
1711 struct peer *peer;
1712 struct peer *onlypeer;
1713 struct bgp *bgp;
40381db7 1714 struct attr *piattr;
b68885f9 1715 route_map_result_t ret;
d62a17ae 1716 int transparent;
1717 int reflect;
1718 afi_t afi;
1719 safi_t safi;
1720 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1721 bool nh_reset = false;
1722 uint64_t cum_bw;
d62a17ae 1723
1724 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1725 return false;
d62a17ae 1726
1727 afi = SUBGRP_AFI(subgrp);
1728 safi = SUBGRP_SAFI(subgrp);
1729 peer = SUBGRP_PEER(subgrp);
1730 onlypeer = NULL;
1731 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1732 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1733
40381db7 1734 from = pi->peer;
d62a17ae 1735 filter = &peer->filter[afi][safi];
1736 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1737 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1738 : pi->attr;
3f9c7369 1739
49e5a4a0 1740#ifdef ENABLE_BGP_VNC
d62a17ae 1741 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1742 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1743 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1744
1745 /*
1746 * direct and direct_ext type routes originate internally even
1747 * though they can have peer pointers that reference other
1748 * systems
1749 */
8228a9a7
DS
1750 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1751 __func__, p);
d62a17ae 1752 samepeer_safe = 1;
1753 }
65efcfce
LB
1754#endif
1755
ddb5b488
PZ
1756 if (((afi == AFI_IP) || (afi == AFI_IP6))
1757 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1758 && (pi->type == ZEBRA_ROUTE_BGP)
1759 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1760
1761 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1762
1763 samepeer_safe = 1;
1764 }
1765
d62a17ae 1766 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1767 * pi is valid */
1768 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1769 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1770 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1771 return false;
d62a17ae 1772 }
adbac85e 1773
d62a17ae 1774 /* If this is not the bestpath then check to see if there is an enabled
1775 * addpath
1776 * feature that requires us to advertise it */
40381db7 1777 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1778 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1779 return false;
d62a17ae 1780 }
1781 }
06370dac 1782
d62a17ae 1783 /* Aggregate-address suppress check. */
4056a5f6
RZ
1784 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1785 return false;
3f9c7369 1786
13b7e7f0
DS
1787 /*
1788 * If we are doing VRF 2 VRF leaking via the import
1789 * statement, we want to prevent the route going
1790 * off box as that the RT and RD created are localy
1791 * significant and globaly useless.
1792 */
40381db7
DS
1793 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1794 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1795 return false;
13b7e7f0 1796
d62a17ae 1797 /* If it's labeled safi, make sure the route has a valid label. */
1798 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1799 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1800 if (!bgp_is_valid_label(&label)) {
1801 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1802 zlog_debug("u%" PRIu64 ":s%" PRIu64
1803 " %pFX is filtered - no label (%p)",
d62a17ae 1804 subgrp->update_group->id, subgrp->id,
8228a9a7 1805 p, &label);
3dc339cd 1806 return false;
d62a17ae 1807 }
1808 }
cd1964ff 1809
d62a17ae 1810 /* Do not send back route to sender. */
1811 if (onlypeer && from == onlypeer) {
3dc339cd 1812 return false;
d62a17ae 1813 }
3f9c7369 1814
d62a17ae 1815 /* Do not send the default route in the BGP table if the neighbor is
1816 * configured for default-originate */
1817 if (CHECK_FLAG(peer->af_flags[afi][safi],
1818 PEER_FLAG_DEFAULT_ORIGINATE)) {
1819 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1820 return false;
d62a17ae 1821 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1822 return false;
d62a17ae 1823 }
4125bb67 1824
d62a17ae 1825 /* Transparency check. */
1826 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1827 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1828 transparent = 1;
1829 else
1830 transparent = 0;
1831
1832 /* If community is not disabled check the no-export and local. */
40381db7 1833 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1834 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1835 zlog_debug(
1836 "subgrpannouncecheck: community filter check fail");
3dc339cd 1837 return false;
d62a17ae 1838 }
3f9c7369 1839
d62a17ae 1840 /* If the attribute has originator-id and it is same as remote
1841 peer's id. */
40381db7
DS
1842 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1843 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1844 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1845 zlog_debug(
8228a9a7
DS
1846 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1847 onlypeer->host, p);
3dc339cd 1848 return false;
d62a17ae 1849 }
3f9c7369 1850
d62a17ae 1851 /* ORF prefix-list filter check */
1852 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1853 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1854 || CHECK_FLAG(peer->af_cap[afi][safi],
1855 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1856 if (peer->orf_plist[afi][safi]) {
1857 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1858 == PREFIX_DENY) {
1859 if (bgp_debug_update(NULL, p,
1860 subgrp->update_group, 0))
1861 zlog_debug(
8228a9a7
DS
1862 "%s [Update:SEND] %pFX is filtered via ORF",
1863 peer->host, p);
3dc339cd 1864 return false;
d62a17ae 1865 }
1866 }
1867
1868 /* Output filter check. */
40381db7 1869 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1870 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1871 zlog_debug("%s [Update:SEND] %pFX is filtered",
1872 peer->host, p);
3dc339cd 1873 return false;
d62a17ae 1874 }
3f9c7369 1875
d62a17ae 1876 /* AS path loop check. */
2b31007c
RZ
1877 if (onlypeer && onlypeer->as_path_loop_detection
1878 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1879 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1880 zlog_debug(
3efd0893 1881 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1882 onlypeer->host, onlypeer->as);
3dc339cd 1883 return false;
d62a17ae 1884 }
3f9c7369 1885
d62a17ae 1886 /* If we're a CONFED we need to loop check the CONFED ID too */
1887 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1888 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1889 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1890 zlog_debug(
3efd0893 1891 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1892 peer->host, bgp->confed_id);
3dc339cd 1893 return false;
d62a17ae 1894 }
3f9c7369 1895 }
3f9c7369 1896
d62a17ae 1897 /* Route-Reflect check. */
1898 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1899 reflect = 1;
1900 else
1901 reflect = 0;
1902
1903 /* IBGP reflection check. */
1904 if (reflect && !samepeer_safe) {
1905 /* A route from a Client peer. */
1906 if (CHECK_FLAG(from->af_flags[afi][safi],
1907 PEER_FLAG_REFLECTOR_CLIENT)) {
1908 /* Reflect to all the Non-Client peers and also to the
1909 Client peers other than the originator. Originator
1910 check
1911 is already done. So there is noting to do. */
1912 /* no bgp client-to-client reflection check. */
892fedb6
DA
1913 if (CHECK_FLAG(bgp->flags,
1914 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1915 if (CHECK_FLAG(peer->af_flags[afi][safi],
1916 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1917 return false;
d62a17ae 1918 } else {
1919 /* A route from a Non-client peer. Reflect to all other
1920 clients. */
1921 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1922 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1923 return false;
d62a17ae 1924 }
1925 }
3f9c7369 1926
d62a17ae 1927 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1928 *attr = *piattr;
d62a17ae 1929
1930 /* If local-preference is not set. */
1931 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1932 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1933 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1934 attr->local_pref = bgp->default_local_pref;
3f9c7369 1935 }
3f9c7369 1936
d62a17ae 1937 /* If originator-id is not set and the route is to be reflected,
1938 set the originator id */
1939 if (reflect
1940 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1941 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1942 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1943 }
3f9c7369 1944
d62a17ae 1945 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1946 */
1947 if (peer->sort == BGP_PEER_EBGP
1948 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1949 if (from != bgp->peer_self && !transparent
1950 && !CHECK_FLAG(peer->af_flags[afi][safi],
1951 PEER_FLAG_MED_UNCHANGED))
1952 attr->flag &=
1953 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1954 }
3f9c7369 1955
d62a17ae 1956 /* Since the nexthop attribute can vary per peer, it is not explicitly
1957 * set
1958 * in announce check, only certain flags and length (or number of
1959 * nexthops
1960 * -- for IPv6/MP_REACH) are set here in order to guide the update
1961 * formation
1962 * code in setting the nexthop(s) on a per peer basis in
1963 * reformat_peer().
1964 * Typically, the source nexthop in the attribute is preserved but in
1965 * the
1966 * scenarios where we know it will always be overwritten, we reset the
1967 * nexthop to "0" in an attempt to achieve better Update packing. An
1968 * example of this is when a prefix from each of 2 IBGP peers needs to
1969 * be
1970 * announced to an EBGP peer (and they have the same attributes barring
1971 * their nexthop).
1972 */
1973 if (reflect)
1974 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1975
1976#define NEXTHOP_IS_V6 \
1977 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1978 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1979 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1980 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1981
1982 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1983 * if
1984 * the peer (group) is configured to receive link-local nexthop
1985 * unchanged
c728d027
DA
1986 * and it is available in the prefix OR we're not reflecting the route,
1987 * link-local nexthop address is valid and
d62a17ae 1988 * the peer (group) to whom we're going to announce is on a shared
1989 * network
1990 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1991 * By checking if nexthop LL address is valid we are sure that
1992 * we do not announce LL address as `::`.
d62a17ae 1993 */
1994 if (NEXTHOP_IS_V6) {
1995 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1996 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1997 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1998 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1999 || (!reflect
2000 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2001 && peer->shared_network
d62a17ae 2002 && (from == bgp->peer_self
2003 || peer->sort == BGP_PEER_EBGP))) {
2004 attr->mp_nexthop_len =
2005 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2006 }
3f9c7369 2007
d62a17ae 2008 /* Clear off link-local nexthop in source, whenever it is not
2009 * needed to
2010 * ensure more prefixes share the same attribute for
2011 * announcement.
2012 */
2013 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2014 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2015 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2016 }
3f9c7369 2017
d62a17ae 2018 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2019 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2020
2021 /* Route map & unsuppress-map apply. */
7f7940e6 2022 if (!skip_rmap_check
e73c112e 2023 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2024 struct bgp_path_info rmap_path = {0};
2025 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2026 struct attr dummy_attr = {0};
d62a17ae 2027
e34291b8 2028 /* Fill temp path_info */
9bcb3eef
DS
2029 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2030 pi, peer, attr);
16f7ce2b 2031
d62a17ae 2032 /* don't confuse inbound and outbound setting */
2033 RESET_FLAG(attr->rmap_change_flags);
2034
2035 /*
2036 * The route reflector is not allowed to modify the attributes
2037 * of the reflected IBGP routes unless explicitly allowed.
2038 */
2039 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2040 && !CHECK_FLAG(bgp->flags,
2041 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2042 dummy_attr = *attr;
40381db7 2043 rmap_path.attr = &dummy_attr;
d62a17ae 2044 }
3f9c7369 2045
d62a17ae 2046 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2047
4056a5f6 2048 if (bgp_path_suppressed(pi))
d62a17ae 2049 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 2050 RMAP_BGP, &rmap_path);
d62a17ae 2051 else
2052 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 2053 RMAP_BGP, &rmap_path);
d62a17ae 2054
2055 peer->rmap_type = 0;
2056
2057 if (ret == RMAP_DENYMATCH) {
778048bf 2058 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2059 zlog_debug(
2060 "%s [Update:SEND] %pFX is filtered by route-map",
2061 peer->host, p);
778048bf 2062
d62a17ae 2063 bgp_attr_flush(attr);
3dc339cd 2064 return false;
d62a17ae 2065 }
3f9c7369 2066 }
3f9c7369 2067
9dac9fc8
DA
2068 /* RFC 8212 to prevent route leaks.
2069 * This specification intends to improve this situation by requiring the
2070 * explicit configuration of both BGP Import and Export Policies for any
2071 * External BGP (EBGP) session such as customers, peers, or
2072 * confederation boundaries for all enabled address families. Through
2073 * codification of the aforementioned requirement, operators will
2074 * benefit from consistent behavior across different BGP
2075 * implementations.
2076 */
1d3fdccf 2077 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2078 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2079 return false;
9dac9fc8 2080
fb29348a
DA
2081 /* draft-ietf-idr-deprecate-as-set-confed-set
2082 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2083 * Eventually, This document (if approved) updates RFC 4271
2084 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2085 * and obsoletes RFC 6472.
2086 */
7f972cd8 2087 if (peer->bgp->reject_as_sets)
fb29348a 2088 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2089 return false;
fb29348a 2090
33d022bc
DA
2091 /* Codification of AS 0 Processing */
2092 if (aspath_check_as_zero(attr->aspath))
e2369003 2093 return false;
33d022bc 2094
637e5ba4 2095 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2096 if (peer->sort == BGP_PEER_IBGP
2097 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2098 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2099 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2100 } else {
2101 bgp_attr_add_gshut_community(attr);
2102 }
2103 }
2104
d62a17ae 2105 /* After route-map has been applied, we check to see if the nexthop to
2106 * be carried in the attribute (that is used for the announcement) can
2107 * be cleared off or not. We do this in all cases where we would be
2108 * setting the nexthop to "ourselves". For IPv6, we only need to
2109 * consider
2110 * the global nexthop here; the link-local nexthop would have been
2111 * cleared
2112 * already, and if not, it is required by the update formation code.
2113 * Also see earlier comments in this function.
2114 */
2115 /*
2116 * If route-map has performed some operation on the nexthop or the peer
2117 * configuration says to pass it unchanged, we cannot reset the nexthop
2118 * here, so only attempt to do it if these aren't true. Note that the
2119 * route-map handler itself might have cleared the nexthop, if for
2120 * example,
2121 * it is configured as 'peer-address'.
2122 */
2123 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2124 piattr->rmap_change_flags)
d62a17ae 2125 && !transparent
2126 && !CHECK_FLAG(peer->af_flags[afi][safi],
2127 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2128 /* We can reset the nexthop, if setting (or forcing) it to
2129 * 'self' */
2130 if (CHECK_FLAG(peer->af_flags[afi][safi],
2131 PEER_FLAG_NEXTHOP_SELF)
2132 || CHECK_FLAG(peer->af_flags[afi][safi],
2133 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2134 if (!reflect
2135 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2136 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2137 subgroup_announce_reset_nhop(
2138 (peer_cap_enhe(peer, afi, safi)
2139 ? AF_INET6
2140 : p->family),
2141 attr);
7b651a32 2142 nh_reset = true;
2143 }
d62a17ae 2144 } else if (peer->sort == BGP_PEER_EBGP) {
2145 /* Can also reset the nexthop if announcing to EBGP, but
2146 * only if
2147 * no peer in the subgroup is on a shared subnet.
2148 * Note: 3rd party nexthop currently implemented for
2149 * IPv4 only.
2150 */
737af885
BS
2151 if ((p->family == AF_INET) &&
2152 (!bgp_subgrp_multiaccess_check_v4(
2153 piattr->nexthop,
7b651a32 2154 subgrp, from))) {
d62a17ae 2155 subgroup_announce_reset_nhop(
2156 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2157 ? AF_INET6
2158 : p->family),
737af885 2159 attr);
7b651a32 2160 nh_reset = true;
2161 }
737af885
BS
2162
2163 if ((p->family == AF_INET6) &&
2164 (!bgp_subgrp_multiaccess_check_v6(
2165 piattr->mp_nexthop_global,
7b651a32 2166 subgrp, from))) {
737af885
BS
2167 subgroup_announce_reset_nhop(
2168 (peer_cap_enhe(peer, afi, safi)
2169 ? AF_INET6
2170 : p->family),
2171 attr);
7b651a32 2172 nh_reset = true;
2173 }
737af885
BS
2174
2175
2176
40381db7 2177 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2178 /*
2179 * This flag is used for leaked vpn-vrf routes
2180 */
2181 int family = p->family;
2182
2183 if (peer_cap_enhe(peer, afi, safi))
2184 family = AF_INET6;
2185
2186 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2187 zlog_debug(
1defdda8 2188 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2189 __func__, family2str(family));
2190 subgroup_announce_reset_nhop(family, attr);
7b651a32 2191 nh_reset = true;
d62a17ae 2192 }
63696f1d 2193 }
960035b2 2194
63696f1d 2195 /* If IPv6/MP and nexthop does not have any override and happens
2196 * to
2197 * be a link-local address, reset it so that we don't pass along
2198 * the
2199 * source's link-local IPv6 address to recipients who may not be
2200 * on
2201 * the same interface.
2202 */
2203 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2204 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2205 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2206 nh_reset = true;
2207 }
d62a17ae 2208 }
3f9c7369 2209
7b651a32 2210 /*
2211 * When the next hop is set to ourselves, if all multipaths have
2212 * link-bandwidth announce the cumulative bandwidth as that makes
2213 * the most sense. However, don't modify if the link-bandwidth has
2214 * been explicitly set by user policy.
2215 */
2216 if (nh_reset &&
f7e1c681 2217 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2218 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2219 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2220 attr->ecommunity = ecommunity_replace_linkbw(
2221 bgp->as, attr->ecommunity, cum_bw);
2222
3dc339cd 2223 return true;
3f9c7369
DS
2224}
2225
f009ff26 2226static int bgp_route_select_timer_expire(struct thread *thread)
2227{
2228 struct afi_safi_info *info;
2229 afi_t afi;
2230 safi_t safi;
2231 struct bgp *bgp;
2232
2233 info = THREAD_ARG(thread);
2234 afi = info->afi;
2235 safi = info->safi;
2236 bgp = info->bgp;
2237
2238 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2239 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2240 safi);
f009ff26 2241
2242 bgp->gr_info[afi][safi].t_route_select = NULL;
2243
2244 XFREE(MTYPE_TMP, info);
2245
2246 /* Best path selection */
2247 return bgp_best_path_select_defer(bgp, afi, safi);
2248}
2249
9bcb3eef 2250void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2251 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2252 struct bgp_path_info_pair *result, afi_t afi,
2253 safi_t safi)
2254{
2255 struct bgp_path_info *new_select;
2256 struct bgp_path_info *old_select;
40381db7
DS
2257 struct bgp_path_info *pi;
2258 struct bgp_path_info *pi1;
2259 struct bgp_path_info *pi2;
2260 struct bgp_path_info *nextpi = NULL;
d62a17ae 2261 int paths_eq, do_mpath, debug;
2262 struct list mp_list;
2263 char pfx_buf[PREFIX2STR_BUFFER];
2264 char path_buf[PATH_ADDPATH_STR_BUFFER];
2265
2266 bgp_mp_list_init(&mp_list);
2267 do_mpath =
2268 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2269
9bcb3eef 2270 debug = bgp_debug_bestpath(dest);
d62a17ae 2271
2272 if (debug)
9bcb3eef 2273 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2274
9bcb3eef 2275 dest->reason = bgp_path_selection_none;
d62a17ae 2276 /* bgp deterministic-med */
2277 new_select = NULL;
892fedb6 2278 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2279
1defdda8 2280 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2281 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2282 pi1 = pi1->next)
9bcb3eef 2283 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2284 BGP_PATH_DMED_SELECTED);
d62a17ae 2285
9bcb3eef 2286 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2287 pi1 = pi1->next) {
40381db7 2288 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2289 continue;
40381db7 2290 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2291 continue;
ea8b2282 2292 if (pi1->peer != bgp->peer_self)
40381db7 2293 if (pi1->peer->status != Established)
d62a17ae 2294 continue;
2295
40381db7
DS
2296 new_select = pi1;
2297 if (pi1->next) {
2298 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2299 if (CHECK_FLAG(pi2->flags,
1defdda8 2300 BGP_PATH_DMED_CHECK))
d62a17ae 2301 continue;
40381db7 2302 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2303 continue;
ea8b2282 2304 if (pi2->peer != bgp->peer_self
d62a17ae 2305 && !CHECK_FLAG(
ea8b2282
DS
2306 pi2->peer->sflags,
2307 PEER_STATUS_NSF_WAIT))
40381db7 2308 if (pi2->peer->status
d62a17ae 2309 != Established)
2310 continue;
2311
121e245d
DS
2312 if (!aspath_cmp_left(pi1->attr->aspath,
2313 pi2->attr->aspath)
2314 && !aspath_cmp_left_confed(
40381db7 2315 pi1->attr->aspath,
121e245d
DS
2316 pi2->attr->aspath))
2317 continue;
d62a17ae 2318
121e245d
DS
2319 if (bgp_path_info_cmp(
2320 bgp, pi2, new_select,
2321 &paths_eq, mpath_cfg, debug,
fdf81fa0 2322 pfx_buf, afi, safi,
9bcb3eef 2323 &dest->reason)) {
121e245d 2324 bgp_path_info_unset_flag(
9bcb3eef 2325 dest, new_select,
121e245d
DS
2326 BGP_PATH_DMED_SELECTED);
2327 new_select = pi2;
d62a17ae 2328 }
121e245d
DS
2329
2330 bgp_path_info_set_flag(
9bcb3eef 2331 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2332 }
2333 }
9bcb3eef 2334 bgp_path_info_set_flag(dest, new_select,
18ee8310 2335 BGP_PATH_DMED_CHECK);
9bcb3eef 2336 bgp_path_info_set_flag(dest, new_select,
18ee8310 2337 BGP_PATH_DMED_SELECTED);
d62a17ae 2338
2339 if (debug) {
18ee8310
DS
2340 bgp_path_info_path_with_addpath_rx_str(
2341 new_select, path_buf);
8228a9a7
DS
2342 zlog_debug(
2343 "%pBD: %s is the bestpath from AS %u",
2344 dest, path_buf,
2345 aspath_get_first_as(
2346 new_select->attr->aspath));
d62a17ae 2347 }
2348 }
2349 }
96450faf 2350
d62a17ae 2351 /* Check old selected route and new selected route. */
2352 old_select = NULL;
2353 new_select = NULL;
9bcb3eef 2354 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2355 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2356 enum bgp_path_selection_reason reason;
2357
40381db7
DS
2358 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2359 old_select = pi;
d62a17ae 2360
40381db7 2361 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2362 /* reap REMOVED routes, if needs be
2363 * selected route must stay for a while longer though
2364 */
40381db7
DS
2365 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2366 && (pi != old_select))
9bcb3eef 2367 bgp_path_info_reap(dest, pi);
d62a17ae 2368
ddb5b488 2369 if (debug)
40381db7
DS
2370 zlog_debug("%s: pi %p in holddown", __func__,
2371 pi);
ddb5b488 2372
d62a17ae 2373 continue;
2374 }
96450faf 2375
40381db7
DS
2376 if (pi->peer && pi->peer != bgp->peer_self
2377 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2378 if (pi->peer->status != Established) {
ddb5b488
PZ
2379
2380 if (debug)
2381 zlog_debug(
40381db7
DS
2382 "%s: pi %p non self peer %s not estab state",
2383 __func__, pi, pi->peer->host);
ddb5b488 2384
d62a17ae 2385 continue;
ddb5b488 2386 }
9fbdd100 2387
892fedb6 2388 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2389 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2390 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2391 if (debug)
40381db7 2392 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2393 continue;
2394 }
9fbdd100 2395
9bcb3eef 2396 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2397
9bcb3eef 2398 reason = dest->reason;
40381db7 2399 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2400 debug, pfx_buf, afi, safi,
2401 &dest->reason)) {
19ea4cec
DS
2402 if (new_select == NULL &&
2403 reason != bgp_path_selection_none)
9bcb3eef 2404 dest->reason = reason;
40381db7 2405 new_select = pi;
d62a17ae 2406 }
2407 }
718e3744 2408
d62a17ae 2409 /* Now that we know which path is the bestpath see if any of the other
2410 * paths
2411 * qualify as multipaths
2412 */
2413 if (debug) {
2414 if (new_select)
18ee8310
DS
2415 bgp_path_info_path_with_addpath_rx_str(new_select,
2416 path_buf);
d62a17ae 2417 else
772270f3 2418 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2419 zlog_debug(
8228a9a7
DS
2420 "%pBD: After path selection, newbest is %s oldbest was %s",
2421 dest, path_buf,
d62a17ae 2422 old_select ? old_select->peer->host : "NONE");
96450faf 2423 }
9fbdd100 2424
d62a17ae 2425 if (do_mpath && new_select) {
9bcb3eef 2426 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2427 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2428
2429 if (debug)
18ee8310 2430 bgp_path_info_path_with_addpath_rx_str(
40381db7 2431 pi, path_buf);
d62a17ae 2432
40381db7 2433 if (pi == new_select) {
d62a17ae 2434 if (debug)
2435 zlog_debug(
8228a9a7
DS
2436 "%pBD: %s is the bestpath, add to the multipath list",
2437 dest, path_buf);
40381db7 2438 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2439 continue;
2440 }
2441
40381db7 2442 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2443 continue;
2444
40381db7
DS
2445 if (pi->peer && pi->peer != bgp->peer_self
2446 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2447 PEER_STATUS_NSF_WAIT))
40381db7 2448 if (pi->peer->status != Established)
d62a17ae 2449 continue;
2450
40381db7 2451 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2452 if (debug)
2453 zlog_debug(
8228a9a7
DS
2454 "%pBD: %s has the same nexthop as the bestpath, skip it",
2455 dest, path_buf);
d62a17ae 2456 continue;
2457 }
2458
40381db7 2459 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2460 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2461 &dest->reason);
d62a17ae 2462
2463 if (paths_eq) {
2464 if (debug)
2465 zlog_debug(
8228a9a7
DS
2466 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2467 dest, path_buf);
40381db7 2468 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2469 }
2470 }
2471 }
fee0f4c6 2472
9bcb3eef 2473 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2474 mpath_cfg);
2475 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2476 bgp_mp_list_clear(&mp_list);
96450faf 2477
9bcb3eef 2478 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2479
d62a17ae 2480 result->old = old_select;
2481 result->new = new_select;
96450faf 2482
d62a17ae 2483 return;
fee0f4c6 2484}
2485
3f9c7369
DS
2486/*
2487 * A new route/change in bestpath of an existing route. Evaluate the path
2488 * for advertisement to the subgroup.
2489 */
3dc339cd
DA
2490void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2491 struct bgp_path_info *selected,
9bcb3eef 2492 struct bgp_dest *dest,
3dc339cd 2493 uint32_t addpath_tx_id)
d62a17ae 2494{
b54892e0 2495 const struct prefix *p;
d62a17ae 2496 struct peer *onlypeer;
2497 struct attr attr;
2498 afi_t afi;
2499 safi_t safi;
a77e2f4b
S
2500 struct bgp *bgp;
2501 bool advertise;
adbac85e 2502
9bcb3eef 2503 p = bgp_dest_get_prefix(dest);
d62a17ae 2504 afi = SUBGRP_AFI(subgrp);
2505 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2506 bgp = SUBGRP_INST(subgrp);
d62a17ae 2507 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2508 : NULL);
2509
2dbe669b
DA
2510 if (BGP_DEBUG(update, UPDATE_OUT))
2511 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2512
d62a17ae 2513 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2514 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2515 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2516 return;
d62a17ae 2517
2518 memset(&attr, 0, sizeof(struct attr));
2519 /* It's initialized in bgp_announce_check() */
2520
a77e2f4b
S
2521 /* Announcement to the subgroup. If the route is filtered withdraw it.
2522 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2523 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2524 * route
d62a17ae 2525 */
a77e2f4b
S
2526 advertise = bgp_check_advertise(bgp, dest);
2527
d62a17ae 2528 if (selected) {
7f7940e6 2529 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2530 false)) {
2531 /* Route is selected, if the route is already installed
2532 * in FIB, then it is advertised
2533 */
2534 if (advertise)
2535 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2536 selected);
2537 } else
9bcb3eef 2538 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2539 addpath_tx_id);
d62a17ae 2540 }
2541
2542 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2543 else {
9bcb3eef 2544 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2545 }
200df115 2546}
fee0f4c6 2547
3064bf43 2548/*
e1072051 2549 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2550 * This is called at the end of route processing.
3064bf43 2551 */
9bcb3eef 2552void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2553{
40381db7 2554 struct bgp_path_info *pi;
3064bf43 2555
9bcb3eef 2556 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2557 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2558 continue;
40381db7
DS
2559 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2560 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2561 }
3064bf43 2562}
2563
2564/*
2565 * Has the route changed from the RIB's perspective? This is invoked only
2566 * if the route selection returns the same best route as earlier - to
2567 * determine if we need to update zebra or not.
2568 */
9bcb3eef 2569bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2570{
4b7e6066 2571 struct bgp_path_info *mpinfo;
d62a17ae 2572
2bb9eff4
DS
2573 /* If this is multipath, check all selected paths for any nexthop
2574 * change or attribute change. Some attribute changes (e.g., community)
2575 * aren't of relevance to the RIB, but we'll update zebra to ensure
2576 * we handle the case of BGP nexthop change. This is the behavior
2577 * when the best path has an attribute change anyway.
d62a17ae 2578 */
1defdda8 2579 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2580 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2581 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2582 return true;
d62a17ae 2583
2bb9eff4
DS
2584 /*
2585 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2586 */
18ee8310
DS
2587 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2588 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2589 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2590 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2591 return true;
d62a17ae 2592 }
3064bf43 2593
d62a17ae 2594 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2595 return false;
3064bf43 2596}
2597
d62a17ae 2598struct bgp_process_queue {
2599 struct bgp *bgp;
9bcb3eef 2600 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2601#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2602 unsigned int flags;
2603 unsigned int queued;
200df115 2604};
2605
3b0c17e1 2606static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2607 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2608 struct bgp_path_info *new_select,
2609 struct bgp_path_info *old_select)
2610{
9bcb3eef 2611 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2612
2613 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2614 return;
2615
2616 if (advertise_type5_routes(bgp, afi) && new_select
2617 && is_route_injectable_into_evpn(new_select)) {
2618
2619 /* apply the route-map */
2620 if (bgp->adv_cmd_rmap[afi][safi].map) {
2621 route_map_result_t ret;
2622 struct bgp_path_info rmap_path;
2623 struct bgp_path_info_extra rmap_path_extra;
2624 struct attr dummy_attr;
2625
2626 dummy_attr = *new_select->attr;
2627
2628 /* Fill temp path_info */
9bcb3eef 2629 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2630 new_select, new_select->peer,
2631 &dummy_attr);
2632
2633 RESET_FLAG(dummy_attr.rmap_change_flags);
2634
2635 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2636 p, RMAP_BGP, &rmap_path);
2637
2638 if (ret == RMAP_DENYMATCH) {
2639 bgp_attr_flush(&dummy_attr);
2640 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2641 safi);
2642 } else
2643 bgp_evpn_advertise_type5_route(
2644 bgp, p, &dummy_attr, afi, safi);
2645 } else {
2646 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2647 afi, safi);
2648 }
2649 } else if (advertise_type5_routes(bgp, afi) && old_select
2650 && is_route_injectable_into_evpn(old_select))
2651 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2652}
2653
3103e8d2
DS
2654/*
2655 * old_select = The old best path
2656 * new_select = the new best path
2657 *
2658 * if (!old_select && new_select)
2659 * We are sending new information on.
2660 *
2661 * if (old_select && new_select) {
2662 * if (new_select != old_select)
2663 * We have a new best path send a change
2664 * else
2665 * We've received a update with new attributes that needs
2666 * to be passed on.
2667 * }
2668 *
2669 * if (old_select && !new_select)
2670 * We have no eligible route that we can announce or the rn
2671 * is being removed.
2672 */
9bcb3eef 2673static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2674 afi_t afi, safi_t safi)
d62a17ae 2675{
4b7e6066
DS
2676 struct bgp_path_info *new_select;
2677 struct bgp_path_info *old_select;
2678 struct bgp_path_info_pair old_and_new;
ddb5b488 2679 int debug = 0;
d62a17ae 2680
892fedb6 2681 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2682 if (dest)
2683 debug = bgp_debug_bestpath(dest);
b54892e0 2684 if (debug)
f4c713ae 2685 zlog_debug(
56ca3b5b 2686 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2687 __func__, dest);
f4c713ae
LB
2688 return;
2689 }
d62a17ae 2690 /* Is it end of initial update? (after startup) */
9bcb3eef 2691 if (!dest) {
d62a17ae 2692 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2693 sizeof(bgp->update_delay_zebra_resume_time));
2694
2695 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2696 FOREACH_AFI_SAFI (afi, safi) {
2697 if (bgp_fibupd_safi(safi))
2698 bgp_zebra_announce_table(bgp, afi, safi);
2699 }
d62a17ae 2700 bgp->main_peers_update_hold = 0;
2701
2702 bgp_start_routeadv(bgp);
aac24838 2703 return;
d62a17ae 2704 }
cb1faec9 2705
9bcb3eef 2706 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2707
9bcb3eef 2708 debug = bgp_debug_bestpath(dest);
b54892e0 2709 if (debug)
56ca3b5b 2710 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2711 afi2str(afi), safi2str(safi));
ddb5b488 2712
f009ff26 2713 /* The best path calculation for the route is deferred if
2714 * BGP_NODE_SELECT_DEFER is set
2715 */
9bcb3eef 2716 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2717 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2718 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2719 return;
2720 }
2721
d62a17ae 2722 /* Best path selection. */
9bcb3eef 2723 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2724 afi, safi);
2725 old_select = old_and_new.old;
2726 new_select = old_and_new.new;
2727
2728 /* Do we need to allocate or free labels?
2729 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2730 * necessary to do this upon changes to best path. Exceptions:
2731 * - label index has changed -> recalculate resulting label
2732 * - path_info sub_type changed -> switch to/from implicit-null
2733 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2734 */
318cac96 2735 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2736 if (new_select) {
2737 if (!old_select
2738 || bgp_label_index_differs(new_select, old_select)
57592a53 2739 || new_select->sub_type != old_select->sub_type
9bcb3eef 2740 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2741 /* Enforced penultimate hop popping:
2742 * implicit-null for local routes, aggregate
2743 * and redistributed routes
2744 */
d62a17ae 2745 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2746 || new_select->sub_type
2747 == BGP_ROUTE_AGGREGATE
2748 || new_select->sub_type
2749 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2750 if (CHECK_FLAG(
9bcb3eef 2751 dest->flags,
d62a17ae 2752 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2753 bgp_unregister_for_label(dest);
70e98a7f 2754 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2755 &dest->local_label);
2756 bgp_set_valid_label(&dest->local_label);
d62a17ae 2757 } else
9bcb3eef
DS
2758 bgp_register_for_label(dest,
2759 new_select);
d62a17ae 2760 }
9bcb3eef 2761 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2762 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2763 bgp_unregister_for_label(dest);
318cac96 2764 }
9bcb3eef
DS
2765 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2766 bgp_unregister_for_label(dest);
d62a17ae 2767 }
cd1964ff 2768
b54892e0 2769 if (debug)
ddb5b488 2770 zlog_debug(
56ca3b5b 2771 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2772 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2773 old_select, new_select);
ddb5b488 2774
d62a17ae 2775 /* If best route remains the same and this is not due to user-initiated
2776 * clear, see exactly what needs to be done.
2777 */
d62a17ae 2778 if (old_select && old_select == new_select
9bcb3eef 2779 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2780 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2781 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2782 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2783#ifdef ENABLE_BGP_VNC
d62a17ae 2784 vnc_import_bgp_add_route(bgp, p, old_select);
2785 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2786#endif
bb744275 2787 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2788 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2789
2790 if (new_select->type == ZEBRA_ROUTE_BGP
2791 && (new_select->sub_type == BGP_ROUTE_NORMAL
2792 || new_select->sub_type
2793 == BGP_ROUTE_IMPORTED))
2794
9bcb3eef 2795 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2796 bgp, afi, safi);
2797 }
d62a17ae 2798 }
d62a17ae 2799
2800 /* If there is a change of interest to peers, reannounce the
2801 * route. */
1defdda8 2802 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2803 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2804 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2805 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2806
2807 /* unicast routes must also be annouced to
2808 * labeled-unicast update-groups */
2809 if (safi == SAFI_UNICAST)
2810 group_announce_route(bgp, afi,
9bcb3eef 2811 SAFI_LABELED_UNICAST, dest,
d62a17ae 2812 new_select);
2813
1defdda8 2814 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2815 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2816 }
fee0f4c6 2817
3b0c17e1 2818 /* advertise/withdraw type-5 routes */
2819 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2820 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2821 bgp_process_evpn_route_injection(
9bcb3eef 2822 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2823
b1875e65 2824 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2825 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2826 bgp_zebra_clear_route_change_flags(dest);
2827 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2828 return;
d62a17ae 2829 }
8ad7271d 2830
d62a17ae 2831 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2832 */
9bcb3eef 2833 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2834
2835 /* bestpath has changed; bump version */
2836 if (old_select || new_select) {
9bcb3eef 2837 bgp_bump_version(dest);
d62a17ae 2838
2839 if (!bgp->t_rmap_def_originate_eval) {
2840 bgp_lock(bgp);
2841 thread_add_timer(
2842 bm->master,
2843 update_group_refresh_default_originate_route_map,
2844 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2845 &bgp->t_rmap_def_originate_eval);
2846 }
2847 }
3f9c7369 2848
d62a17ae 2849 if (old_select)
9bcb3eef 2850 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2851 if (new_select) {
ddb5b488
PZ
2852 if (debug)
2853 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2854 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2855 bgp_path_info_unset_flag(dest, new_select,
2856 BGP_PATH_ATTR_CHANGED);
1defdda8 2857 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2858 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2859 }
338b3424 2860
49e5a4a0 2861#ifdef ENABLE_BGP_VNC
d62a17ae 2862 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2863 if (old_select != new_select) {
2864 if (old_select) {
2865 vnc_import_bgp_exterior_del_route(bgp, p,
2866 old_select);
2867 vnc_import_bgp_del_route(bgp, p, old_select);
2868 }
2869 if (new_select) {
2870 vnc_import_bgp_exterior_add_route(bgp, p,
2871 new_select);
2872 vnc_import_bgp_add_route(bgp, p, new_select);
2873 }
2874 }
2875 }
65efcfce
LB
2876#endif
2877
9bcb3eef 2878 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2879
2880 /* unicast routes must also be annouced to labeled-unicast update-groups
2881 */
2882 if (safi == SAFI_UNICAST)
9bcb3eef 2883 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2884 new_select);
2885
2886 /* FIB update. */
2887 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2888 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2889 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2890 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2891 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2892 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2893
2894 /* if this is an evpn imported type-5 prefix,
2895 * we need to withdraw the route first to clear
2896 * the nh neigh and the RMAC entry.
2897 */
2898 if (old_select &&
2899 is_route_parent_evpn(old_select))
2900 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2901
9bcb3eef 2902 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2903 } else {
d62a17ae 2904 /* Withdraw the route from the kernel. */
2905 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2906 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2907 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2908 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2909
568e10ca 2910 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2911 }
718e3744 2912 }
3064bf43 2913
9bcb3eef 2914 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2915 old_select);
5424b7ba 2916
d62a17ae 2917 /* Clear any route change flags. */
9bcb3eef 2918 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2919
18ee8310 2920 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2921 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2922 bgp_path_info_reap(dest, old_select);
d62a17ae 2923
9bcb3eef 2924 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2925 return;
718e3744 2926}
2927
f009ff26 2928/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2929int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2930{
9bcb3eef 2931 struct bgp_dest *dest;
f009ff26 2932 int cnt = 0;
2933 struct afi_safi_info *thread_info;
f009ff26 2934
56c226e7
DS
2935 if (bgp->gr_info[afi][safi].t_route_select) {
2936 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2937
2938 thread_info = THREAD_ARG(t);
2939 XFREE(MTYPE_TMP, thread_info);
f009ff26 2940 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2941 }
f009ff26 2942
2943 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2944 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2945 get_afi_safi_str(afi, safi, false),
26742171 2946 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2947 }
2948
2949 /* Process the route list */
6338d242
DS
2950 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2951 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2952 dest = bgp_route_next(dest)) {
2953 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2954 continue;
2955
2956 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2957 bgp->gr_info[afi][safi].gr_deferred--;
2958 bgp_process_main_one(bgp, dest, afi, safi);
2959 cnt++;
2960 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2961 bgp_dest_unlock_node(dest);
2962 break;
f009ff26 2963 }
f009ff26 2964 }
2965
9e3b51a7 2966 /* Send EOR message when all routes are processed */
6338d242 2967 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2968 bgp_send_delayed_eor(bgp);
8c48b3b6 2969 /* Send route processing complete message to RIB */
2970 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2971 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2972 return 0;
9e3b51a7 2973 }
f009ff26 2974
2975 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2976
2977 thread_info->afi = afi;
2978 thread_info->safi = safi;
2979 thread_info->bgp = bgp;
2980
2981 /* If there are more routes to be processed, start the
2982 * selection timer
2983 */
2984 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2985 BGP_ROUTE_SELECT_DELAY,
2986 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2987 return 0;
2988}
2989
aac24838 2990static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2991{
aac24838
JB
2992 struct bgp_process_queue *pqnode = data;
2993 struct bgp *bgp = pqnode->bgp;
d62a17ae 2994 struct bgp_table *table;
9bcb3eef 2995 struct bgp_dest *dest;
aac24838
JB
2996
2997 /* eoiu marker */
2998 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2999 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3000 /* should always have dedicated wq call */
3001 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3002 return WQ_SUCCESS;
3003 }
3004
ac021f40 3005 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3006 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3007 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3008 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3009 table = bgp_dest_table(dest);
3010 /* note, new DESTs may be added as part of processing */
3011 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3012
9bcb3eef 3013 bgp_dest_unlock_node(dest);
d62a17ae 3014 bgp_table_unlock(table);
3015 }
aac24838
JB
3016
3017 return WQ_SUCCESS;
3018}
3019
3020static void bgp_processq_del(struct work_queue *wq, void *data)
3021{
3022 struct bgp_process_queue *pqnode = data;
3023
3024 bgp_unlock(pqnode->bgp);
3025
3026 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3027}
3028
b6c386bb 3029void bgp_process_queue_init(struct bgp *bgp)
200df115 3030{
b6c386bb
DS
3031 if (!bgp->process_queue) {
3032 char name[BUFSIZ];
3033
3034 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3035 bgp->process_queue = work_queue_new(bm->master, name);
3036 }
3037
3038 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3039 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3040 bgp->process_queue->spec.max_retries = 0;
3041 bgp->process_queue->spec.hold = 50;
d62a17ae 3042 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3043 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3044}
3045
cfe8d15a 3046static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3047{
3048 struct bgp_process_queue *pqnode;
3049
a4d82a8a
PZ
3050 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3051 sizeof(struct bgp_process_queue));
aac24838
JB
3052
3053 /* unlocked in bgp_processq_del */
3054 pqnode->bgp = bgp_lock(bgp);
3055 STAILQ_INIT(&pqnode->pqueue);
3056
aac24838
JB
3057 return pqnode;
3058}
3059
9bcb3eef 3060void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3061{
aac24838 3062#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3063 struct work_queue *wq = bgp->process_queue;
d62a17ae 3064 struct bgp_process_queue *pqnode;
cfe8d15a 3065 int pqnode_reuse = 0;
495f0b13 3066
d62a17ae 3067 /* already scheduled for processing? */
9bcb3eef 3068 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3069 return;
2e02b9b2 3070
f009ff26 3071 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3072 * the workqueue
3073 */
9bcb3eef 3074 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3075 if (BGP_DEBUG(update, UPDATE_OUT))
3076 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3077 dest);
f009ff26 3078 return;
3079 }
3080
aac24838 3081 if (wq == NULL)
d62a17ae 3082 return;
3083
aac24838 3084 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3085 limit only if is from the same BGP view and it's not an EOIU marker
3086 */
aac24838
JB
3087 if (work_queue_item_count(wq)) {
3088 struct work_queue_item *item = work_queue_last_item(wq);
3089 pqnode = item->data;
228da428 3090
a4d82a8a
PZ
3091 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3092 || pqnode->bgp != bgp
3093 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3094 pqnode = bgp_processq_alloc(bgp);
3095 else
3096 pqnode_reuse = 1;
aac24838 3097 } else
cfe8d15a 3098 pqnode = bgp_processq_alloc(bgp);
aac24838 3099 /* all unlocked in bgp_process_wq */
9bcb3eef 3100 bgp_table_lock(bgp_dest_table(dest));
aac24838 3101
9bcb3eef
DS
3102 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3103 bgp_dest_lock_node(dest);
aac24838 3104
60466a63 3105 /* can't be enqueued twice */
9bcb3eef
DS
3106 assert(STAILQ_NEXT(dest, pq) == NULL);
3107 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3108 pqnode->queued++;
3109
cfe8d15a
LB
3110 if (!pqnode_reuse)
3111 work_queue_add(wq, pqnode);
3112
d62a17ae 3113 return;
fee0f4c6 3114}
0a486e5f 3115
d62a17ae 3116void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3117{
d62a17ae 3118 struct bgp_process_queue *pqnode;
cb1faec9 3119
b6c386bb 3120 if (bgp->process_queue == NULL)
d62a17ae 3121 return;
2e02b9b2 3122
cfe8d15a 3123 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3124
aac24838 3125 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3126 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3127}
3128
d62a17ae 3129static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3130{
d62a17ae 3131 struct peer *peer;
0a486e5f 3132
d62a17ae 3133 peer = THREAD_ARG(thread);
3134 peer->t_pmax_restart = NULL;
0a486e5f 3135
d62a17ae 3136 if (bgp_debug_neighbor_events(peer))
3137 zlog_debug(
3138 "%s Maximum-prefix restart timer expired, restore peering",
3139 peer->host);
0a486e5f 3140
a9bafa95 3141 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3142 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3143
d62a17ae 3144 return 0;
0a486e5f 3145}
3146
9cbd06e0
DA
3147static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3148 safi_t safi)
3149{
3150 uint32_t count = 0;
f41b0459 3151 bool filtered = false;
9cbd06e0
DA
3152 struct bgp_dest *dest;
3153 struct bgp_adj_in *ain;
40bb2ccf 3154 struct attr attr = {};
9cbd06e0
DA
3155 struct bgp_table *table = peer->bgp->rib[afi][safi];
3156
3157 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3158 for (ain = dest->adj_in; ain; ain = ain->next) {
3159 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3160
3161 attr = *ain->attr;
9cbd06e0
DA
3162
3163 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3164 == FILTER_DENY)
f41b0459
DA
3165 filtered = true;
3166
3167 if (bgp_input_modifier(
3168 peer, rn_p, &attr, afi, safi,
3169 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3170 NULL, 0, NULL)
3171 == RMAP_DENY)
3172 filtered = true;
3173
3174 if (filtered)
9cbd06e0 3175 count++;
f41b0459
DA
3176
3177 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3178 }
3179 }
3180
3181 return count;
3182}
3183
3dc339cd
DA
3184bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3185 int always)
718e3744 3186{
d62a17ae 3187 iana_afi_t pkt_afi;
5c525538 3188 iana_safi_t pkt_safi;
9cbd06e0
DA
3189 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3190 PEER_FLAG_MAX_PREFIX_FORCE))
3191 ? bgp_filtered_routes_count(peer, afi, safi)
3192 + peer->pcount[afi][safi]
3193 : peer->pcount[afi][safi];
9cabb64b 3194
d62a17ae 3195 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3196 return false;
e0701b79 3197
9cbd06e0 3198 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3199 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3200 PEER_STATUS_PREFIX_LIMIT)
3201 && !always)
3dc339cd 3202 return false;
e0701b79 3203
d62a17ae 3204 zlog_info(
6cde4b45 3205 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3206 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3207 peer->pmax[afi][safi]);
d62a17ae 3208 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3209
3210 if (CHECK_FLAG(peer->af_flags[afi][safi],
3211 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3212 return false;
d62a17ae 3213
3214 /* Convert AFI, SAFI to values for packet. */
3215 pkt_afi = afi_int2iana(afi);
3216 pkt_safi = safi_int2iana(safi);
3217 {
d7c0a89a 3218 uint8_t ndata[7];
d62a17ae 3219
3220 ndata[0] = (pkt_afi >> 8);
3221 ndata[1] = pkt_afi;
3222 ndata[2] = pkt_safi;
3223 ndata[3] = (peer->pmax[afi][safi] >> 24);
3224 ndata[4] = (peer->pmax[afi][safi] >> 16);
3225 ndata[5] = (peer->pmax[afi][safi] >> 8);
3226 ndata[6] = (peer->pmax[afi][safi]);
3227
3228 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3229 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3230 BGP_NOTIFY_CEASE_MAX_PREFIX,
3231 ndata, 7);
3232 }
3233
3234 /* Dynamic peers will just close their connection. */
3235 if (peer_dynamic_neighbor(peer))
3dc339cd 3236 return true;
d62a17ae 3237
3238 /* restart timer start */
3239 if (peer->pmax_restart[afi][safi]) {
3240 peer->v_pmax_restart =
3241 peer->pmax_restart[afi][safi] * 60;
3242
3243 if (bgp_debug_neighbor_events(peer))
3244 zlog_debug(
3245 "%s Maximum-prefix restart timer started for %d secs",
3246 peer->host, peer->v_pmax_restart);
3247
3248 BGP_TIMER_ON(peer->t_pmax_restart,
3249 bgp_maximum_prefix_restart_timer,
3250 peer->v_pmax_restart);
3251 }
3252
3dc339cd 3253 return true;
d62a17ae 3254 } else
3255 UNSET_FLAG(peer->af_sflags[afi][safi],
3256 PEER_STATUS_PREFIX_LIMIT);
3257
b1823b69
DS
3258 if (pcount
3259 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3260 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3261 PEER_STATUS_PREFIX_THRESHOLD)
3262 && !always)
3dc339cd 3263 return false;
d62a17ae 3264
3265 zlog_info(
6cde4b45 3266 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3267 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3268 peer->pmax[afi][safi]);
d62a17ae 3269 SET_FLAG(peer->af_sflags[afi][safi],
3270 PEER_STATUS_PREFIX_THRESHOLD);
3271 } else
3272 UNSET_FLAG(peer->af_sflags[afi][safi],
3273 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3274 return false;
718e3744 3275}
3276
b40d939b 3277/* Unconditionally remove the route from the RIB, without taking
3278 * damping into consideration (eg, because the session went down)
3279 */
9bcb3eef 3280void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3281 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3282{
f009ff26 3283
3284 struct bgp *bgp = NULL;
3285 bool delete_route = false;
3286
9bcb3eef
DS
3287 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3288 safi);
d62a17ae 3289
f009ff26 3290 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3291 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3292
f009ff26 3293 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3294 * flag
3295 */
3296 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3297 delete_route = true;
9bcb3eef 3298 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3299 delete_route = true;
f009ff26 3300 if (delete_route) {
9bcb3eef
DS
3301 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3302 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3303 bgp = pi->peer->bgp;
26742171 3304 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3305 }
3306 }
3307 }
4a11bf2c 3308
9bcb3eef
DS
3309 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3310 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3311}
3312
9bcb3eef 3313static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3314 struct peer *peer, afi_t afi, safi_t safi,
3315 struct prefix_rd *prd)
3316{
9bcb3eef 3317 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3318
d62a17ae 3319 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3320 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3321 */
3322 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3323 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3324 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3325 == BGP_DAMP_SUPPRESSED) {
b54892e0 3326 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3327 safi);
3328 return;
3329 }
3330
49e5a4a0 3331#ifdef ENABLE_BGP_VNC
d62a17ae 3332 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3333 struct bgp_dest *pdest = NULL;
d62a17ae 3334 struct bgp_table *table = NULL;
3335
9bcb3eef
DS
3336 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3337 (struct prefix *)prd);
3338 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3339 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3340
3341 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3342 peer->bgp, prd, table, p, pi);
d62a17ae 3343 }
9bcb3eef 3344 bgp_dest_unlock_node(pdest);
d62a17ae 3345 }
3346 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3347 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3348
b54892e0
DS
3349 vnc_import_bgp_del_route(peer->bgp, p, pi);
3350 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3351 }
65efcfce 3352 }
d62a17ae 3353#endif
128ea8ab 3354
d62a17ae 3355 /* If this is an EVPN route, process for un-import. */
3356 if (safi == SAFI_EVPN)
b54892e0 3357 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3358
9bcb3eef 3359 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3360}
3361
4b7e6066
DS
3362struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3363 struct peer *peer, struct attr *attr,
9bcb3eef 3364 struct bgp_dest *dest)
fb018d25 3365{
4b7e6066 3366 struct bgp_path_info *new;
fb018d25 3367
d62a17ae 3368 /* Make new BGP info. */
4b7e6066 3369 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3370 new->type = type;
3371 new->instance = instance;
3372 new->sub_type = sub_type;
3373 new->peer = peer;
3374 new->attr = attr;
3375 new->uptime = bgp_clock();
9bcb3eef 3376 new->net = dest;
d62a17ae 3377 return new;
fb018d25
DS
3378}
3379
d62a17ae 3380static void overlay_index_update(struct attr *attr,
d62a17ae 3381 union gw_addr *gw_ip)
684a7227 3382{
d62a17ae 3383 if (!attr)
3384 return;
d62a17ae 3385 if (gw_ip == NULL) {
3386 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3387 } else {
3388 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3389 sizeof(union gw_addr));
3390 }
684a7227
PG
3391}
3392
40381db7 3393static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3394 union gw_addr *gw_ip)
3395{
40381db7 3396 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3397 union {
0a50c248 3398 esi_t esi;
11ebf4ed
DS
3399 union gw_addr ip;
3400 } temp;
d62a17ae 3401
3402 if (afi != AFI_L2VPN)
3403 return true;
11ebf4ed 3404
05864da7 3405 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3406
3407 if (gw_ip == NULL) {
3408 memset(&temp, 0, sizeof(temp));
40381db7 3409 path_gw_ip_remote = &temp.ip;
11ebf4ed 3410 } else
40381db7 3411 path_gw_ip_remote = gw_ip;
11ebf4ed 3412
0a50c248 3413 return !!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3414}
3415
c265ee22 3416/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3417bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3418 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3419 struct bgp_dest *dest)
d62a17ae 3420{
2dbe3fa9 3421 bool ret = false;
b099a5c8
DA
3422 bool is_bgp_static_route =
3423 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3424 : false;
d62a17ae 3425
e8442016
DS
3426 /*
3427 * Only validated for unicast and multicast currently.
3428 * Also valid for EVPN where the nexthop is an IP address.
3429 * If we are a bgp static route being checked then there is
3430 * no need to check to see if the nexthop is martian as
3431 * that it should be ok.
3432 */
3433 if (is_bgp_static_route ||
3434 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3435 return false;
d62a17ae 3436
3437 /* If NEXT_HOP is present, validate it. */
3438 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3439 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3440 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3441 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3442 return true;
d62a17ae 3443 }
c265ee22 3444
d62a17ae 3445 /* If MP_NEXTHOP is present, validate it. */
3446 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3447 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3448 * it is not an IPv6 link-local address.
0355b41d
DA
3449 *
3450 * If we receive an UPDATE with nexthop length set to 32 bytes
3451 * we shouldn't discard an UPDATE if it's set to (::).
3452 * The link-local (2st) is validated along the code path later.
d62a17ae 3453 */
3454 if (attr->mp_nexthop_len) {
3455 switch (attr->mp_nexthop_len) {
3456 case BGP_ATTR_NHLEN_IPV4:
3457 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3458 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3459 || IPV4_CLASS_DE(
3460 ntohl(attr->mp_nexthop_global_in.s_addr))
3461 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3462 dest));
d62a17ae 3463 break;
3464
3465 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3466 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3467 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3468 &attr->mp_nexthop_global)
d62a17ae 3469 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3470 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3471 &attr->mp_nexthop_global)
3472 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3473 dest));
d62a17ae 3474 break;
0355b41d
DA
3475 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3476 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3477 || IN6_IS_ADDR_MULTICAST(
3478 &attr->mp_nexthop_global)
3479 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3480 dest));
0355b41d 3481 break;
d62a17ae 3482
3483 default:
3dc339cd 3484 ret = true;
d62a17ae 3485 break;
3486 }
3487 }
c265ee22 3488
d62a17ae 3489 return ret;
3490}
3491
5a1ae2c2 3492int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3493 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3494 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3495 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3496 struct bgp_route_evpn *evpn)
d62a17ae 3497{
3498 int ret;
3499 int aspath_loop_count = 0;
9bcb3eef 3500 struct bgp_dest *dest;
d62a17ae 3501 struct bgp *bgp;
3502 struct attr new_attr;
3503 struct attr *attr_new;
40381db7 3504 struct bgp_path_info *pi;
4b7e6066
DS
3505 struct bgp_path_info *new;
3506 struct bgp_path_info_extra *extra;
d62a17ae 3507 const char *reason;
3508 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3509 int connected = 0;
3510 int do_loop_check = 1;
3511 int has_valid_label = 0;
7c312383 3512 afi_t nh_afi;
949b0f24 3513 uint8_t pi_type = 0;
3514 uint8_t pi_sub_type = 0;
3515
c7bb4f00 3516 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3517 char pfxprint[PREFIX2STR_BUFFER];
3518
3519 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3520 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3521 afi, safi, attr);
6401252f
QY
3522 }
3523
49e5a4a0 3524#ifdef ENABLE_BGP_VNC
d62a17ae 3525 int vnc_implicit_withdraw = 0;
65efcfce 3526#endif
d62a17ae 3527 int same_attr = 0;
718e3744 3528
d62a17ae 3529 memset(&new_attr, 0, sizeof(struct attr));
3530 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3531 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3532
d62a17ae 3533 bgp = peer->bgp;
9bcb3eef 3534 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3535 /* TODO: Check to see if we can get rid of "is_valid_label" */
3536 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3537 has_valid_label = (num_labels > 0) ? 1 : 0;
3538 else
3539 has_valid_label = bgp_is_valid_label(label);
718e3744 3540
a77e2f4b
S
3541 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3542 * condition :
3543 * Suppress fib is enabled
3544 * BGP_OPT_NO_FIB is not enabled
3545 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3546 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3547 */
3548 if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
3549 (sub_type == BGP_ROUTE_NORMAL) &&
3550 (!bgp_option_check(BGP_OPT_NO_FIB)) &&
3551 (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3552 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3553
d62a17ae 3554 /* When peer's soft reconfiguration enabled. Record input packet in
3555 Adj-RIBs-In. */
3556 if (!soft_reconfig
3557 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3558 && peer != bgp->peer_self)
9bcb3eef 3559 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3560
3561 /* Check previously received route. */
9bcb3eef 3562 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3563 if (pi->peer == peer && pi->type == type
3564 && pi->sub_type == sub_type
3565 && pi->addpath_rx_id == addpath_id)
d62a17ae 3566 break;
3567
3568 /* AS path local-as loop check. */
3569 if (peer->change_local_as) {
c4368918
DW
3570 if (peer->allowas_in[afi][safi])
3571 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3572 else if (!CHECK_FLAG(peer->flags,
3573 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3574 aspath_loop_count = 1;
3575
3576 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3577 > aspath_loop_count) {
b4d46cc9 3578 peer->stat_pfx_aspath_loop++;
9bcb3eef 3579 reason = "as-path contains our own AS A;";
d62a17ae 3580 goto filtered;
3581 }
718e3744 3582 }
718e3744 3583
d62a17ae 3584 /* If the peer is configured for "allowas-in origin" and the last ASN in
3585 * the
3586 * as-path is our ASN then we do not need to call aspath_loop_check
3587 */
3588 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3589 if (aspath_get_last_as(attr->aspath) == bgp->as)
3590 do_loop_check = 0;
3591
3592 /* AS path loop check. */
3593 if (do_loop_check) {
3594 if (aspath_loop_check(attr->aspath, bgp->as)
3595 > peer->allowas_in[afi][safi]
3596 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3597 && aspath_loop_check(attr->aspath, bgp->confed_id)
3598 > peer->allowas_in[afi][safi])) {
b4d46cc9 3599 peer->stat_pfx_aspath_loop++;
d62a17ae 3600 reason = "as-path contains our own AS;";
3601 goto filtered;
3602 }
3603 }
aac9ef6c 3604
d62a17ae 3605 /* Route reflector originator ID check. */
3606 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3607 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3608 peer->stat_pfx_originator_loop++;
d62a17ae 3609 reason = "originator is us;";
3610 goto filtered;
3611 }
718e3744 3612
d62a17ae 3613 /* Route reflector cluster ID check. */
3614 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3615 peer->stat_pfx_cluster_loop++;
d62a17ae 3616 reason = "reflected from the same cluster;";
3617 goto filtered;
3618 }
718e3744 3619
d62a17ae 3620 /* Apply incoming filter. */
3621 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3622 peer->stat_pfx_filter++;
d62a17ae 3623 reason = "filter;";
3624 goto filtered;
3625 }
718e3744 3626
a8b72dc6
DA
3627 /* RFC 8212 to prevent route leaks.
3628 * This specification intends to improve this situation by requiring the
3629 * explicit configuration of both BGP Import and Export Policies for any
3630 * External BGP (EBGP) session such as customers, peers, or
3631 * confederation boundaries for all enabled address families. Through
3632 * codification of the aforementioned requirement, operators will
3633 * benefit from consistent behavior across different BGP
3634 * implementations.
3635 */
1d3fdccf 3636 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3637 if (!bgp_inbound_policy_exists(peer,
3638 &peer->filter[afi][safi])) {
3639 reason = "inbound policy missing";
3640 goto filtered;
3641 }
3642
fb29348a
DA
3643 /* draft-ietf-idr-deprecate-as-set-confed-set
3644 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3645 * Eventually, This document (if approved) updates RFC 4271
3646 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3647 * and obsoletes RFC 6472.
3648 */
7f972cd8 3649 if (peer->bgp->reject_as_sets)
fb29348a
DA
3650 if (aspath_check_as_sets(attr->aspath)) {
3651 reason =
3652 "as-path contains AS_SET or AS_CONFED_SET type;";
3653 goto filtered;
3654 }
3655
6f4f49b2 3656 new_attr = *attr;
d62a17ae 3657
3658 /* Apply incoming route-map.
3659 * NB: new_attr may now contain newly allocated values from route-map
3660 * "set"
3661 * commands, so we need bgp_attr_flush in the error paths, until we
3662 * intern
3663 * the attr (which takes over the memory references) */
9bcb3eef
DS
3664 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3665 num_labels, dest)
3666 == RMAP_DENY) {
b4d46cc9 3667 peer->stat_pfx_filter++;
d62a17ae 3668 reason = "route-map;";
3669 bgp_attr_flush(&new_attr);
3670 goto filtered;
3671 }
718e3744 3672
05864da7 3673 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3674 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3675 /* remove from RIB previous entry */
3676 bgp_zebra_withdraw(p, pi, bgp, safi);
3677 }
3678
7f323236
DW
3679 if (peer->sort == BGP_PEER_EBGP) {
3680
a4d82a8a
PZ
3681 /* If we receive the graceful-shutdown community from an eBGP
3682 * peer we must lower local-preference */
3683 if (new_attr.community
3684 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3685 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3686 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3687
a4d82a8a
PZ
3688 /* If graceful-shutdown is configured then add the GSHUT
3689 * community to all paths received from eBGP peers */
637e5ba4 3690 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3691 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3692 }
3693
949b0f24 3694 if (pi) {
3695 pi_type = pi->type;
3696 pi_sub_type = pi->sub_type;
3697 }
3698
d62a17ae 3699 /* next hop check. */
a4d82a8a 3700 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3701 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3702 &new_attr, dest)) {
b4d46cc9 3703 peer->stat_pfx_nh_invalid++;
d62a17ae 3704 reason = "martian or self next-hop;";
3705 bgp_attr_flush(&new_attr);
3706 goto filtered;
3707 }
718e3744 3708
5c14a191 3709 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3710 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3711 reason = "self mac;";
3712 goto filtered;
3713 }
3714
1e9be514
QY
3715 /* Update Overlay Index */
3716 if (afi == AFI_L2VPN) {
3717 overlay_index_update(&new_attr,
3718 evpn == NULL ? NULL : &evpn->gw_ip);
3719 }
3720
d62a17ae 3721 attr_new = bgp_attr_intern(&new_attr);
3722
9cbd06e0
DA
3723 /* If maximum prefix count is configured and current prefix
3724 * count exeed it.
3725 */
3726 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3727 return -1;
3728
d62a17ae 3729 /* If the update is implicit withdraw. */
40381db7
DS
3730 if (pi) {
3731 pi->uptime = bgp_clock();
3732 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3733
9bcb3eef 3734 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3735
d62a17ae 3736 /* Same attribute comes in. */
40381db7
DS
3737 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3738 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3739 && (!has_valid_label
40381db7 3740 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3741 num_labels * sizeof(mpls_label_t))
d62a17ae 3742 == 0)
3743 && (overlay_index_equal(
0a50c248 3744 afi, pi,
d62a17ae 3745 evpn == NULL ? NULL : &evpn->gw_ip))) {
3746 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3747 BGP_CONFIG_DAMPENING)
3748 && peer->sort == BGP_PEER_EBGP
40381db7 3749 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3750 if (bgp_debug_update(peer, p, NULL, 1)) {
3751 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3752 afi, safi, prd, p, label,
3753 num_labels, addpath_id ? 1 : 0,
3754 addpath_id, pfx_buf,
3755 sizeof(pfx_buf));
d62a17ae 3756 zlog_debug("%s rcvd %s", peer->host,
3757 pfx_buf);
3758 }
3759
9bcb3eef 3760 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3761 != BGP_DAMP_SUPPRESSED) {
40381db7 3762 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3763 safi);
9bcb3eef 3764 bgp_process(bgp, dest, afi, safi);
d62a17ae 3765 }
3766 } else /* Duplicate - odd */
3767 {
3768 if (bgp_debug_update(peer, p, NULL, 1)) {
3769 if (!peer->rcvd_attr_printed) {
3770 zlog_debug(
3771 "%s rcvd UPDATE w/ attr: %s",
3772 peer->host,
3773 peer->rcvd_attr_str);
3774 peer->rcvd_attr_printed = 1;
3775 }
3776
3777 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3778 afi, safi, prd, p, label,
3779 num_labels, addpath_id ? 1 : 0,
3780 addpath_id, pfx_buf,
3781 sizeof(pfx_buf));
d62a17ae 3782 zlog_debug(
3783 "%s rcvd %s...duplicate ignored",
3784 peer->host, pfx_buf);
3785 }
3786
3787 /* graceful restart STALE flag unset. */
40381db7 3788 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3789 bgp_path_info_unset_flag(
9bcb3eef
DS
3790 dest, pi, BGP_PATH_STALE);
3791 bgp_dest_set_defer_flag(dest, false);
3792 bgp_process(bgp, dest, afi, safi);
d62a17ae 3793 }
3794 }
3795
9bcb3eef 3796 bgp_dest_unlock_node(dest);
d62a17ae 3797 bgp_attr_unintern(&attr_new);
3798
3799 return 0;
3800 }
718e3744 3801
d62a17ae 3802 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3803 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3804 if (bgp_debug_update(peer, p, NULL, 1)) {
3805 bgp_debug_rdpfxpath2str(
a4d82a8a 3806 afi, safi, prd, p, label, num_labels,
d62a17ae 3807 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3808 sizeof(pfx_buf));
3809 zlog_debug(
3810 "%s rcvd %s, flapped quicker than processing",
3811 peer->host, pfx_buf);
3812 }
3813
9bcb3eef 3814 bgp_path_info_restore(dest, pi);
d62a17ae 3815 }
718e3744 3816
d62a17ae 3817 /* Received Logging. */
3818 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3819 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3820 num_labels, addpath_id ? 1 : 0,
3821 addpath_id, pfx_buf,
3822 sizeof(pfx_buf));
d62a17ae 3823 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3824 }
718e3744 3825
d62a17ae 3826 /* graceful restart STALE flag unset. */
f009ff26 3827 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3828 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3829 bgp_dest_set_defer_flag(dest, false);
f009ff26 3830 }
d62a17ae 3831
3832 /* The attribute is changed. */
9bcb3eef 3833 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3834
3835 /* implicit withdraw, decrement aggregate and pcount here.
3836 * only if update is accepted, they'll increment below.
3837 */
40381db7 3838 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3839
3840 /* Update bgp route dampening information. */
3841 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3842 && peer->sort == BGP_PEER_EBGP) {
3843 /* This is implicit withdraw so we should update
3844 dampening
3845 information. */
40381db7 3846 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3847 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3848 }
49e5a4a0 3849#ifdef ENABLE_BGP_VNC
d62a17ae 3850 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3851 struct bgp_dest *pdest = NULL;
d62a17ae 3852 struct bgp_table *table = NULL;
3853
9bcb3eef
DS
3854 pdest = bgp_node_get(bgp->rib[afi][safi],
3855 (struct prefix *)prd);
3856 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3857 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3858
3859 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3860 bgp, prd, table, p, pi);
d62a17ae 3861 }
9bcb3eef 3862 bgp_dest_unlock_node(pdest);
d62a17ae 3863 }
3864 if ((afi == AFI_IP || afi == AFI_IP6)
3865 && (safi == SAFI_UNICAST)) {
40381db7 3866 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3867 /*
3868 * Implicit withdraw case.
3869 */
3870 ++vnc_implicit_withdraw;
40381db7
DS
3871 vnc_import_bgp_del_route(bgp, p, pi);
3872 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3873 }
3874 }
65efcfce 3875#endif
128ea8ab 3876
d62a17ae 3877 /* Special handling for EVPN update of an existing route. If the
3878 * extended community attribute has changed, we need to
3879 * un-import
3880 * the route using its existing extended community. It will be
3881 * subsequently processed for import with the new extended
3882 * community.
3883 */
6f8c9c11
PR
3884 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3885 && !same_attr) {
40381db7 3886 if ((pi->attr->flag
d62a17ae 3887 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3888 && (attr_new->flag
3889 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3890 int cmp;
3891
40381db7 3892 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3893 attr_new->ecommunity);
3894 if (!cmp) {
3895 if (bgp_debug_update(peer, p, NULL, 1))
3896 zlog_debug(
3897 "Change in EXT-COMM, existing %s new %s",
3898 ecommunity_str(
40381db7 3899 pi->attr->ecommunity),
d62a17ae 3900 ecommunity_str(
3901 attr_new->ecommunity));
6f8c9c11
PR
3902 if (safi == SAFI_EVPN)
3903 bgp_evpn_unimport_route(
3904 bgp, afi, safi, p, pi);
3905 else /* SAFI_MPLS_VPN */
3906 vpn_leak_to_vrf_withdraw(bgp,
3907 pi);
d62a17ae 3908 }
3909 }
3910 }
718e3744 3911
d62a17ae 3912 /* Update to new attribute. */
40381db7
DS
3913 bgp_attr_unintern(&pi->attr);
3914 pi->attr = attr_new;
d62a17ae 3915
3916 /* Update MPLS label */
3917 if (has_valid_label) {
40381db7 3918 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3919 if (extra->label != label) {
3920 memcpy(&extra->label, label,
dbd587da 3921 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3922 extra->num_labels = num_labels;
3923 }
b57ba6d2
MK
3924 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3925 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3926 }
718e3744 3927
e496b420
HS
3928 /* Update SRv6 SID */
3929 if (attr->srv6_l3vpn) {
3930 extra = bgp_path_info_extra_get(pi);
3931 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3932 sid_copy(&extra->sid[0],
3933 &attr->srv6_l3vpn->sid);
3934 extra->num_sids = 1;
3935 }
3936 } else if (attr->srv6_vpn) {
3937 extra = bgp_path_info_extra_get(pi);
3938 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3939 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3940 extra->num_sids = 1;
3941 }
3942 }
3943
49e5a4a0 3944#ifdef ENABLE_BGP_VNC
d62a17ae 3945 if ((afi == AFI_IP || afi == AFI_IP6)
3946 && (safi == SAFI_UNICAST)) {
3947 if (vnc_implicit_withdraw) {
3948 /*
3949 * Add back the route with its new attributes
3950 * (e.g., nexthop).
3951 * The route is still selected, until the route
3952 * selection
3953 * queued by bgp_process actually runs. We have
3954 * to make this
3955 * update to the VNC side immediately to avoid
3956 * racing against
3957 * configuration changes (e.g., route-map
3958 * changes) which
3959 * trigger re-importation of the entire RIB.
3960 */
40381db7
DS
3961 vnc_import_bgp_add_route(bgp, p, pi);
3962 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3963 }
3964 }
65efcfce
LB
3965#endif
3966
d62a17ae 3967 /* Update bgp route dampening information. */
3968 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3969 && peer->sort == BGP_PEER_EBGP) {
3970 /* Now we do normal update dampening. */
9bcb3eef 3971 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3972 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3973 bgp_dest_unlock_node(dest);
d62a17ae 3974 return 0;
3975 }
3976 }
128ea8ab 3977
d62a17ae 3978 /* Nexthop reachability check - for unicast and
3979 * labeled-unicast.. */
7c312383
AD
3980 if (((afi == AFI_IP || afi == AFI_IP6)
3981 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3982 || (safi == SAFI_EVPN &&
3983 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3984 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3985 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3986 && !CHECK_FLAG(peer->flags,
3987 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3988 && !CHECK_FLAG(bgp->flags,
3989 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3990 connected = 1;
3991 else
3992 connected = 0;
3993
960035b2
PZ
3994 struct bgp *bgp_nexthop = bgp;
3995
40381db7
DS
3996 if (pi->extra && pi->extra->bgp_orig)
3997 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3998
7c312383
AD
3999 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4000
4001 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4002 pi, NULL, connected)
a4d82a8a 4003 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4004 bgp_path_info_set_flag(dest, pi,
4005 BGP_PATH_VALID);
d62a17ae 4006 else {
4007 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4008 zlog_debug("%s(%pI4): NH unresolved",
4009 __func__,
4010 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4011 }
9bcb3eef 4012 bgp_path_info_unset_flag(dest, pi,
18ee8310 4013 BGP_PATH_VALID);
d62a17ae 4014 }
4015 } else
9bcb3eef 4016 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4017
49e5a4a0 4018#ifdef ENABLE_BGP_VNC
d62a17ae 4019 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4020 struct bgp_dest *pdest = NULL;
d62a17ae 4021 struct bgp_table *table = NULL;
4022
9bcb3eef
DS
4023 pdest = bgp_node_get(bgp->rib[afi][safi],
4024 (struct prefix *)prd);
4025 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4026 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4027
4028 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4029 bgp, prd, table, p, pi);
d62a17ae 4030 }
9bcb3eef 4031 bgp_dest_unlock_node(pdest);
d62a17ae 4032 }
4033#endif
718e3744 4034
d62a17ae 4035 /* If this is an EVPN route and some attribute has changed,
4036 * process
4037 * route for import. If the extended community has changed, we
4038 * would
4039 * have done the un-import earlier and the import would result
4040 * in the
4041 * route getting injected into appropriate L2 VNIs. If it is
4042 * just
4043 * some other attribute change, the import will result in
4044 * updating
4045 * the attributes for the route in the VNI(s).
4046 */
7c312383
AD
4047 if (safi == SAFI_EVPN && !same_attr &&
4048 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4049 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4050
4051 /* Process change. */
40381db7 4052 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4053
9bcb3eef
DS
4054 bgp_process(bgp, dest, afi, safi);
4055 bgp_dest_unlock_node(dest);
558d1fec 4056
ddb5b488
PZ
4057 if (SAFI_UNICAST == safi
4058 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4059 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4060
40381db7 4061 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4062 }
4063 if ((SAFI_MPLS_VPN == safi)
4064 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4065
40381db7 4066 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4067 }
4068
49e5a4a0 4069#ifdef ENABLE_BGP_VNC
d62a17ae 4070 if (SAFI_MPLS_VPN == safi) {
4071 mpls_label_t label_decoded = decode_label(label);
28070ee3 4072
d62a17ae 4073 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4074 type, sub_type, &label_decoded);
4075 }
4076 if (SAFI_ENCAP == safi) {
4077 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4078 type, sub_type, NULL);
4079 }
28070ee3
PZ
4080#endif
4081
d62a17ae 4082 return 0;
4083 } // End of implicit withdraw
718e3744 4084
d62a17ae 4085 /* Received Logging. */
4086 if (bgp_debug_update(peer, p, NULL, 1)) {
4087 if (!peer->rcvd_attr_printed) {
4088 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4089 peer->rcvd_attr_str);
4090 peer->rcvd_attr_printed = 1;
4091 }
718e3744 4092
a4d82a8a 4093 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4094 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4095 sizeof(pfx_buf));
4096 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4097 }
718e3744 4098
d62a17ae 4099 /* Make new BGP info. */
9bcb3eef 4100 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4101
d62a17ae 4102 /* Update MPLS label */
4103 if (has_valid_label) {
18ee8310 4104 extra = bgp_path_info_extra_get(new);
8ba71050 4105 if (extra->label != label) {
dbd587da
QY
4106 memcpy(&extra->label, label,
4107 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4108 extra->num_labels = num_labels;
4109 }
b57ba6d2
MK
4110 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4111 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4112 }
718e3744 4113
e496b420
HS
4114 /* Update SRv6 SID */
4115 if (safi == SAFI_MPLS_VPN) {
4116 extra = bgp_path_info_extra_get(new);
4117 if (attr->srv6_l3vpn) {
4118 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4119 extra->num_sids = 1;
4120 } else if (attr->srv6_vpn) {
4121 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4122 extra->num_sids = 1;
4123 }
4124 }
4125
d62a17ae 4126 /* Update Overlay Index */
4127 if (afi == AFI_L2VPN) {
4128 overlay_index_update(new->attr,
d62a17ae 4129 evpn == NULL ? NULL : &evpn->gw_ip);
4130 }
4131 /* Nexthop reachability check. */
7c312383
AD
4132 if (((afi == AFI_IP || afi == AFI_IP6)
4133 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4134 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4135 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4136 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4137 && !CHECK_FLAG(peer->flags,
4138 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4139 && !CHECK_FLAG(bgp->flags,
4140 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4141 connected = 1;
4142 else
4143 connected = 0;
4144
7c312383
AD
4145 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4146
4147 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4148 connected)
a4d82a8a 4149 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4150 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4151 else {
4152 if (BGP_DEBUG(nht, NHT)) {
4153 char buf1[INET6_ADDRSTRLEN];
4154 inet_ntop(AF_INET,
4155 (const void *)&attr_new->nexthop,
4156 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4157 zlog_debug("%s(%s): NH unresolved", __func__,
4158 buf1);
d62a17ae 4159 }
9bcb3eef 4160 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4161 }
4162 } else
9bcb3eef 4163 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4164
d62a17ae 4165 /* Addpath ID */
4166 new->addpath_rx_id = addpath_id;
4167
4168 /* Increment prefix */
4169 bgp_aggregate_increment(bgp, p, new, afi, safi);
4170
4171 /* Register new BGP information. */
9bcb3eef 4172 bgp_path_info_add(dest, new);
d62a17ae 4173
4174 /* route_node_get lock */
9bcb3eef 4175 bgp_dest_unlock_node(dest);
558d1fec 4176
49e5a4a0 4177#ifdef ENABLE_BGP_VNC
d62a17ae 4178 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4179 struct bgp_dest *pdest = NULL;
d62a17ae 4180 struct bgp_table *table = NULL;
4181
9bcb3eef
DS
4182 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4183 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4184 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4185
4186 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4187 bgp, prd, table, p, new);
4188 }
9bcb3eef 4189 bgp_dest_unlock_node(pdest);
d62a17ae 4190 }
65efcfce
LB
4191#endif
4192
d62a17ae 4193 /* If this is an EVPN route, process for import. */
7c312383 4194 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4195 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4196
9bcb3eef 4197 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4198
d62a17ae 4199 /* Process change. */
9bcb3eef 4200 bgp_process(bgp, dest, afi, safi);
718e3744 4201
ddb5b488
PZ
4202 if (SAFI_UNICAST == safi
4203 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4204 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4205 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4206 }
4207 if ((SAFI_MPLS_VPN == safi)
4208 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4209
4210 vpn_leak_to_vrf_update(bgp, new);
4211 }
49e5a4a0 4212#ifdef ENABLE_BGP_VNC
d62a17ae 4213 if (SAFI_MPLS_VPN == safi) {
4214 mpls_label_t label_decoded = decode_label(label);
28070ee3 4215
d62a17ae 4216 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4217 sub_type, &label_decoded);
4218 }
4219 if (SAFI_ENCAP == safi) {
4220 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4221 sub_type, NULL);
4222 }
28070ee3
PZ
4223#endif
4224
d62a17ae 4225 return 0;
718e3744 4226
d62a17ae 4227/* This BGP update is filtered. Log the reason then update BGP
4228 entry. */
4229filtered:
9bcb3eef 4230 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4231
d62a17ae 4232 if (bgp_debug_update(peer, p, NULL, 1)) {
4233 if (!peer->rcvd_attr_printed) {
4234 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4235 peer->rcvd_attr_str);
4236 peer->rcvd_attr_printed = 1;
4237 }
718e3744 4238
a4d82a8a 4239 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4240 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4241 sizeof(pfx_buf));
4242 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4243 peer->host, pfx_buf, reason);
4244 }
128ea8ab 4245
40381db7 4246 if (pi) {
d62a17ae 4247 /* If this is an EVPN route, un-import it as it is now filtered.
4248 */
4249 if (safi == SAFI_EVPN)
40381db7 4250 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4251
ddb5b488
PZ
4252 if (SAFI_UNICAST == safi
4253 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4254 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4255
40381db7 4256 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4257 }
4258 if ((SAFI_MPLS_VPN == safi)
4259 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4260
40381db7 4261 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4262 }
4263
9bcb3eef 4264 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4265 }
4266
9bcb3eef 4267 bgp_dest_unlock_node(dest);
558d1fec 4268
49e5a4a0 4269#ifdef ENABLE_BGP_VNC
d62a17ae 4270 /*
4271 * Filtered update is treated as an implicit withdrawal (see
4272 * bgp_rib_remove()
4273 * a few lines above)
4274 */
4275 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4276 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4277 0);
4278 }
97736e32
PZ
4279#endif
4280
d62a17ae 4281 return 0;
718e3744 4282}
4283
26a3ffd6 4284int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4285 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4286 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4287 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4288{
d62a17ae 4289 struct bgp *bgp;
4290 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4291 struct bgp_dest *dest;
40381db7 4292 struct bgp_path_info *pi;
718e3744 4293
49e5a4a0 4294#ifdef ENABLE_BGP_VNC
d62a17ae 4295 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4296 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4297 0);
4298 }
28070ee3
PZ
4299#endif
4300
d62a17ae 4301 bgp = peer->bgp;
4302
4303 /* Lookup node. */
9bcb3eef 4304 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4305
4306 /* If peer is soft reconfiguration enabled. Record input packet for
4307 * further calculation.
4308 *
4309 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4310 * routes that are filtered. This tanks out Quagga RS pretty badly due
4311 * to
4312 * the iteration over all RS clients.
4313 * Since we need to remove the entry from adj_in anyway, do that first
4314 * and
4315 * if there was no entry, we don't need to do anything more.
4316 */
4317 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4318 && peer != bgp->peer_self)
9bcb3eef 4319 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4320 peer->stat_pfx_dup_withdraw++;
4321
d62a17ae 4322 if (bgp_debug_update(peer, p, NULL, 1)) {
4323 bgp_debug_rdpfxpath2str(
a4d82a8a 4324 afi, safi, prd, p, label, num_labels,
d62a17ae 4325 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4326 sizeof(pfx_buf));
4327 zlog_debug(
4328 "%s withdrawing route %s not in adj-in",
4329 peer->host, pfx_buf);
4330 }
9bcb3eef 4331 bgp_dest_unlock_node(dest);
d62a17ae 4332 return 0;
4333 }
cd808e74 4334
d62a17ae 4335 /* Lookup withdrawn route. */
9bcb3eef 4336 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4337 if (pi->peer == peer && pi->type == type
4338 && pi->sub_type == sub_type
4339 && pi->addpath_rx_id == addpath_id)
d62a17ae 4340 break;
4341
4342 /* Logging. */
4343 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4344 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4345 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4346 sizeof(pfx_buf));
4347 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4348 pfx_buf);
4349 }
718e3744 4350
d62a17ae 4351 /* Withdraw specified route from routing table. */
40381db7 4352 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4353 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4354 if (SAFI_UNICAST == safi
4355 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4356 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4357 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4358 }
4359 if ((SAFI_MPLS_VPN == safi)
4360 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4361
40381db7 4362 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4363 }
4364 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4365 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4366 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4367 sizeof(pfx_buf));
4368 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4369 }
718e3744 4370
d62a17ae 4371 /* Unlock bgp_node_get() lock. */
9bcb3eef 4372 bgp_dest_unlock_node(dest);
d62a17ae 4373
4374 return 0;
718e3744 4375}
6b0655a2 4376
d62a17ae 4377void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4378 int withdraw)
718e3744 4379{
d62a17ae 4380 struct update_subgroup *subgrp;
4381 subgrp = peer_subgroup(peer, afi, safi);
4382 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4383}
6182d65b 4384
718e3744 4385
3f9c7369
DS
4386/*
4387 * bgp_stop_announce_route_timer
4388 */
d62a17ae 4389void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4390{
d62a17ae 4391 if (!paf->t_announce_route)
4392 return;
4393
50478845 4394 thread_cancel(&paf->t_announce_route);
718e3744 4395}
6b0655a2 4396
3f9c7369
DS
4397/*
4398 * bgp_announce_route_timer_expired
4399 *
4400 * Callback that is invoked when the route announcement timer for a
4401 * peer_af expires.
4402 */
d62a17ae 4403static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4404{
d62a17ae 4405 struct peer_af *paf;
4406 struct peer *peer;
558d1fec 4407
d62a17ae 4408 paf = THREAD_ARG(t);
4409 peer = paf->peer;
718e3744 4410
d62a17ae 4411 if (peer->status != Established)
4412 return 0;
3f9c7369 4413
d62a17ae 4414 if (!peer->afc_nego[paf->afi][paf->safi])
4415 return 0;
3f9c7369 4416
d62a17ae 4417 peer_af_announce_route(paf, 1);
c5aec50b
MK
4418
4419 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4420 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4421
d62a17ae 4422 return 0;
718e3744 4423}
4424
3f9c7369
DS
4425/*
4426 * bgp_announce_route
4427 *
4428 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4429 */
d62a17ae 4430void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4431{
4432 struct peer_af *paf;
4433 struct update_subgroup *subgrp;
4434
4435 paf = peer_af_find(peer, afi, safi);
4436 if (!paf)
4437 return;
4438 subgrp = PAF_SUBGRP(paf);
4439
4440 /*
4441 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4442 * or a refresh has already been triggered.
4443 */
4444 if (!subgrp || paf->t_announce_route)
4445 return;
4446
4447 /*
4448 * Start a timer to stagger/delay the announce. This serves
4449 * two purposes - announcement can potentially be combined for
4450 * multiple peers and the announcement doesn't happen in the
4451 * vty context.
4452 */
4453 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4454 (subgrp->peer_count == 1)
4455 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4456 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4457 &paf->t_announce_route);
3f9c7369
DS
4458}
4459
4460/*
4461 * Announce routes from all AF tables to a peer.
4462 *
4463 * This should ONLY be called when there is a need to refresh the
4464 * routes to the peer based on a policy change for this peer alone
4465 * or a route refresh request received from the peer.
4466 * The operation will result in splitting the peer from its existing
4467 * subgroups and putting it in new subgroups.
4468 */
d62a17ae 4469void bgp_announce_route_all(struct peer *peer)
718e3744 4470{
d62a17ae 4471 afi_t afi;
4472 safi_t safi;
4473
05c7a1cc
QY
4474 FOREACH_AFI_SAFI (afi, safi)
4475 bgp_announce_route(peer, afi, safi);
718e3744 4476}
6b0655a2 4477
d62a17ae 4478static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4479 struct bgp_table *table,
4480 struct prefix_rd *prd)
718e3744 4481{
d62a17ae 4482 int ret;
9bcb3eef 4483 struct bgp_dest *dest;
d62a17ae 4484 struct bgp_adj_in *ain;
718e3744 4485
d62a17ae 4486 if (!table)
4487 table = peer->bgp->rib[afi][safi];
718e3744 4488
9bcb3eef
DS
4489 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4490 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4491 if (ain->peer != peer)
4492 continue;
8692c506 4493
d7d15889 4494 struct bgp_path_info *pi;
d7c0a89a 4495 uint32_t num_labels = 0;
b57ba6d2 4496 mpls_label_t *label_pnt = NULL;
8cb687c2 4497 struct bgp_route_evpn evpn;
b57ba6d2 4498
9bcb3eef 4499 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4500 pi = pi->next)
4501 if (pi->peer == peer)
4502 break;
4503
40381db7
DS
4504 if (pi && pi->extra)
4505 num_labels = pi->extra->num_labels;
b57ba6d2 4506 if (num_labels)
40381db7 4507 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4508 if (pi)
4509 memcpy(&evpn, &pi->attr->evpn_overlay,
4510 sizeof(evpn));
4511 else
4512 memset(&evpn, 0, sizeof(evpn));
8692c506 4513
9bcb3eef
DS
4514 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4515 ain->addpath_rx_id, ain->attr, afi,
4516 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4517 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4518 num_labels, 1, &evpn);
ea47320b
DL
4519
4520 if (ret < 0) {
9bcb3eef 4521 bgp_dest_unlock_node(dest);
ea47320b 4522 return;
d62a17ae 4523 }
4524 }
718e3744 4525}
4526
d62a17ae 4527void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4528{
9bcb3eef 4529 struct bgp_dest *dest;
d62a17ae 4530 struct bgp_table *table;
718e3744 4531
d62a17ae 4532 if (peer->status != Established)
4533 return;
718e3744 4534
d62a17ae 4535 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4536 && (safi != SAFI_EVPN))
4537 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4538 else
9bcb3eef
DS
4539 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4540 dest = bgp_route_next(dest)) {
4541 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4542
b54892e0
DS
4543 if (table == NULL)
4544 continue;
8692c506 4545
9bcb3eef 4546 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4547 struct prefix_rd prd;
4548
4549 prd.family = AF_UNSPEC;
4550 prd.prefixlen = 64;
4551 memcpy(&prd.val, p->u.val, 8);
4552
4553 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4554 }
718e3744 4555}
6b0655a2 4556
228da428 4557
d62a17ae 4558struct bgp_clear_node_queue {
9bcb3eef 4559 struct bgp_dest *dest;
228da428
CC
4560};
4561
d62a17ae 4562static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4563{
d62a17ae 4564 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4565 struct bgp_dest *dest = cnq->dest;
d62a17ae 4566 struct peer *peer = wq->spec.data;
40381db7 4567 struct bgp_path_info *pi;
3103e8d2 4568 struct bgp *bgp;
9bcb3eef
DS
4569 afi_t afi = bgp_dest_table(dest)->afi;
4570 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4571
9bcb3eef 4572 assert(dest && peer);
3103e8d2 4573 bgp = peer->bgp;
d62a17ae 4574
4575 /* It is possible that we have multiple paths for a prefix from a peer
4576 * if that peer is using AddPath.
4577 */
9bcb3eef 4578 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4579 if (pi->peer != peer)
ea47320b
DL
4580 continue;
4581
4582 /* graceful restart STALE flag set. */
4583 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4584 && peer->nsf[afi][safi]
40381db7
DS
4585 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4586 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4587 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4588 else {
4589 /* If this is an EVPN route, process for
4590 * un-import. */
4591 if (safi == SAFI_EVPN)
9bcb3eef
DS
4592 bgp_evpn_unimport_route(
4593 bgp, afi, safi,
4594 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4595 /* Handle withdraw for VRF route-leaking and L3VPN */
4596 if (SAFI_UNICAST == safi
4597 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4598 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4599 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4600 bgp, pi);
960035b2 4601 }
3103e8d2 4602 if (SAFI_MPLS_VPN == safi &&
960035b2 4603 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4604 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4605 }
3103e8d2 4606
9bcb3eef 4607 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4608 }
ea47320b 4609 }
d62a17ae 4610 return WQ_SUCCESS;
200df115 4611}
4612
d62a17ae 4613static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4614{
d62a17ae 4615 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4616 struct bgp_dest *dest = cnq->dest;
4617 struct bgp_table *table = bgp_dest_table(dest);
228da428 4618
9bcb3eef 4619 bgp_dest_unlock_node(dest);
d62a17ae 4620 bgp_table_unlock(table);
4621 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4622}
4623
d62a17ae 4624static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4625{
d62a17ae 4626 struct peer *peer = wq->spec.data;
64e580a7 4627
d62a17ae 4628 /* Tickle FSM to start moving again */
4629 BGP_EVENT_ADD(peer, Clearing_Completed);
4630
4631 peer_unlock(peer); /* bgp_clear_route */
200df115 4632}
718e3744 4633
d62a17ae 4634static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4635{
d62a17ae 4636 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4637
4638 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4639#undef CLEAR_QUEUE_NAME_LEN
4640
0ce1ca80 4641 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4642 peer->clear_node_queue->spec.hold = 10;
4643 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4644 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4645 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4646 peer->clear_node_queue->spec.max_retries = 0;
4647
4648 /* we only 'lock' this peer reference when the queue is actually active
4649 */
4650 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4651}
4652
d62a17ae 4653static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4654 struct bgp_table *table)
65ca75e0 4655{
9bcb3eef 4656 struct bgp_dest *dest;
b6c386bb 4657 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4658
d62a17ae 4659 if (!table)
4660 table = peer->bgp->rib[afi][safi];
dc83d712 4661
d62a17ae 4662 /* If still no table => afi/safi isn't configured at all or smth. */
4663 if (!table)
4664 return;
dc83d712 4665
9bcb3eef 4666 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4667 struct bgp_path_info *pi, *next;
d62a17ae 4668 struct bgp_adj_in *ain;
4669 struct bgp_adj_in *ain_next;
4670
4671 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4672 * queued for every clearing peer, regardless of whether it is
4673 * relevant to the peer at hand.
4674 *
4675 * Overview: There are 3 different indices which need to be
4676 * scrubbed, potentially, when a peer is removed:
4677 *
4678 * 1 peer's routes visible via the RIB (ie accepted routes)
4679 * 2 peer's routes visible by the (optional) peer's adj-in index
4680 * 3 other routes visible by the peer's adj-out index
4681 *
4682 * 3 there is no hurry in scrubbing, once the struct peer is
4683 * removed from bgp->peer, we could just GC such deleted peer's
4684 * adj-outs at our leisure.
4685 *
4686 * 1 and 2 must be 'scrubbed' in some way, at least made
4687 * invisible via RIB index before peer session is allowed to be
4688 * brought back up. So one needs to know when such a 'search' is
4689 * complete.
4690 *
4691 * Ideally:
4692 *
4693 * - there'd be a single global queue or a single RIB walker
4694 * - rather than tracking which route_nodes still need to be
4695 * examined on a peer basis, we'd track which peers still
4696 * aren't cleared
4697 *
4698 * Given that our per-peer prefix-counts now should be reliable,
4699 * this may actually be achievable. It doesn't seem to be a huge
4700 * problem at this time,
4701 *
4702 * It is possible that we have multiple paths for a prefix from
4703 * a peer
4704 * if that peer is using AddPath.
4705 */
9bcb3eef 4706 ain = dest->adj_in;
d62a17ae 4707 while (ain) {
4708 ain_next = ain->next;
4709
4710 if (ain->peer == peer) {
9bcb3eef
DS
4711 bgp_adj_in_remove(dest, ain);
4712 bgp_dest_unlock_node(dest);
d62a17ae 4713 }
4714
4715 ain = ain_next;
4716 }
4717
9bcb3eef 4718 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4719 next = pi->next;
4720 if (pi->peer != peer)
d62a17ae 4721 continue;
4722
4723 if (force)
9bcb3eef 4724 bgp_path_info_reap(dest, pi);
d62a17ae 4725 else {
4726 struct bgp_clear_node_queue *cnq;
4727
4728 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4729 bgp_table_lock(bgp_dest_table(dest));
4730 bgp_dest_lock_node(dest);
d62a17ae 4731 cnq = XCALLOC(
4732 MTYPE_BGP_CLEAR_NODE_QUEUE,
4733 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4734 cnq->dest = dest;
d62a17ae 4735 work_queue_add(peer->clear_node_queue, cnq);
4736 break;
4737 }
4738 }
4739 }
4740 return;
4741}
4742
4743void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4744{
9bcb3eef 4745 struct bgp_dest *dest;
d62a17ae 4746 struct bgp_table *table;
4747
4748 if (peer->clear_node_queue == NULL)
4749 bgp_clear_node_queue_init(peer);
4750
4751 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4752 * Idle until it receives a Clearing_Completed event. This protects
4753 * against peers which flap faster than we can we clear, which could
4754 * lead to:
4755 *
4756 * a) race with routes from the new session being installed before
4757 * clear_route_node visits the node (to delete the route of that
4758 * peer)
4759 * b) resource exhaustion, clear_route_node likely leads to an entry
4760 * on the process_main queue. Fast-flapping could cause that queue
4761 * to grow and grow.
4762 */
4763
4764 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4765 * the unlock will happen upon work-queue completion; other wise, the
4766 * unlock happens at the end of this function.
4767 */
4768 if (!peer->clear_node_queue->thread)
4769 peer_lock(peer);
4770
4771 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4772 bgp_clear_route_table(peer, afi, safi, NULL);
4773 else
9bcb3eef
DS
4774 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4775 dest = bgp_route_next(dest)) {
4776 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4777 if (!table)
4778 continue;
4779
4780 bgp_clear_route_table(peer, afi, safi, table);
4781 }
d62a17ae 4782
4783 /* unlock if no nodes got added to the clear-node-queue. */
4784 if (!peer->clear_node_queue->thread)
4785 peer_unlock(peer);
718e3744 4786}
d62a17ae 4787
4788void bgp_clear_route_all(struct peer *peer)
718e3744 4789{
d62a17ae 4790 afi_t afi;
4791 safi_t safi;
718e3744 4792
05c7a1cc
QY
4793 FOREACH_AFI_SAFI (afi, safi)
4794 bgp_clear_route(peer, afi, safi);
65efcfce 4795
49e5a4a0 4796#ifdef ENABLE_BGP_VNC
d62a17ae 4797 rfapiProcessPeerDown(peer);
65efcfce 4798#endif
718e3744 4799}
4800
d62a17ae 4801void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4802{
d62a17ae 4803 struct bgp_table *table;
9bcb3eef 4804 struct bgp_dest *dest;
d62a17ae 4805 struct bgp_adj_in *ain;
4806 struct bgp_adj_in *ain_next;
718e3744 4807
d62a17ae 4808 table = peer->bgp->rib[afi][safi];
718e3744 4809
d62a17ae 4810 /* It is possible that we have multiple paths for a prefix from a peer
4811 * if that peer is using AddPath.
4812 */
9bcb3eef
DS
4813 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4814 ain = dest->adj_in;
43143c8f 4815
d62a17ae 4816 while (ain) {
4817 ain_next = ain->next;
43143c8f 4818
d62a17ae 4819 if (ain->peer == peer) {
9bcb3eef
DS
4820 bgp_adj_in_remove(dest, ain);
4821 bgp_dest_unlock_node(dest);
d62a17ae 4822 }
43143c8f 4823
d62a17ae 4824 ain = ain_next;
4825 }
4826 }
718e3744 4827}
93406d87 4828
d62a17ae 4829void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4830{
9bcb3eef 4831 struct bgp_dest *dest;
40381db7 4832 struct bgp_path_info *pi;
d62a17ae 4833 struct bgp_table *table;
4834
4835 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4836 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4837 dest = bgp_route_next(dest)) {
4838 struct bgp_dest *rm;
d62a17ae 4839
4840 /* look for neighbor in tables */
9bcb3eef 4841 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4842 if (!table)
ea47320b
DL
4843 continue;
4844
4845 for (rm = bgp_table_top(table); rm;
4846 rm = bgp_route_next(rm))
9bcb3eef 4847 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4848 pi = pi->next) {
40381db7 4849 if (pi->peer != peer)
ea47320b 4850 continue;
40381db7 4851 if (!CHECK_FLAG(pi->flags,
1defdda8 4852 BGP_PATH_STALE))
ea47320b
DL
4853 break;
4854
40381db7 4855 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4856 break;
4857 }
d62a17ae 4858 }
4859 } else {
9bcb3eef
DS
4860 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4861 dest = bgp_route_next(dest))
4862 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4863 pi = pi->next) {
40381db7 4864 if (pi->peer != peer)
ea47320b 4865 continue;
40381db7 4866 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4867 break;
9bcb3eef 4868 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4869 break;
4870 }
d62a17ae 4871 }
93406d87 4872}
6b0655a2 4873
3dc339cd 4874bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4875{
e0df4c04 4876 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4877 return true;
e0df4c04 4878
9dac9fc8
DA
4879 if (peer->sort == BGP_PEER_EBGP
4880 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4881 || FILTER_LIST_OUT_NAME(filter)
4882 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4883 return true;
4884 return false;
9dac9fc8
DA
4885}
4886
3dc339cd 4887bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4888{
e0df4c04 4889 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4890 return true;
e0df4c04 4891
9dac9fc8
DA
4892 if (peer->sort == BGP_PEER_EBGP
4893 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4894 || FILTER_LIST_IN_NAME(filter)
4895 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4896 return true;
4897 return false;
9dac9fc8
DA
4898}
4899
568e10ca 4900static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4901 safi_t safi)
bb86c601 4902{
9bcb3eef 4903 struct bgp_dest *dest;
40381db7 4904 struct bgp_path_info *pi;
4b7e6066 4905 struct bgp_path_info *next;
bb86c601 4906
9bcb3eef
DS
4907 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4908 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4909 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4910
40381db7 4911 next = pi->next;
1b7bb747
CS
4912
4913 /* Unimport EVPN routes from VRFs */
4914 if (safi == SAFI_EVPN)
4915 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4916 SAFI_EVPN, p, pi);
1b7bb747 4917
40381db7
DS
4918 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4919 && pi->type == ZEBRA_ROUTE_BGP
4920 && (pi->sub_type == BGP_ROUTE_NORMAL
4921 || pi->sub_type == BGP_ROUTE_AGGREGATE
4922 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4923
d62a17ae 4924 if (bgp_fibupd_safi(safi))
b54892e0 4925 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4926 }
9514b37d 4927
9bcb3eef 4928 bgp_path_info_reap(dest, pi);
d62a17ae 4929 }
bb86c601
LB
4930}
4931
718e3744 4932/* Delete all kernel routes. */
d62a17ae 4933void bgp_cleanup_routes(struct bgp *bgp)
4934{
4935 afi_t afi;
9bcb3eef 4936 struct bgp_dest *dest;
67009e22 4937 struct bgp_table *table;
d62a17ae 4938
4939 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4940 if (afi == AFI_L2VPN)
4941 continue;
568e10ca 4942 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4943 SAFI_UNICAST);
d62a17ae 4944 /*
4945 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4946 */
4947 if (afi != AFI_L2VPN) {
4948 safi_t safi;
4949 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4950 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4951 dest = bgp_route_next(dest)) {
4952 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4953 if (table != NULL) {
4954 bgp_cleanup_table(bgp, table, safi);
4955 bgp_table_finish(&table);
9bcb3eef
DS
4956 bgp_dest_set_bgp_table_info(dest, NULL);
4957 bgp_dest_unlock_node(dest);
d62a17ae 4958 }
4959 }
4960 safi = SAFI_ENCAP;
9bcb3eef
DS
4961 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4962 dest = bgp_route_next(dest)) {
4963 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4964 if (table != NULL) {
4965 bgp_cleanup_table(bgp, table, safi);
4966 bgp_table_finish(&table);
9bcb3eef
DS
4967 bgp_dest_set_bgp_table_info(dest, NULL);
4968 bgp_dest_unlock_node(dest);
d62a17ae 4969 }
4970 }
4971 }
4972 }
9bcb3eef
DS
4973 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4974 dest = bgp_route_next(dest)) {
4975 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4976 if (table != NULL) {
4977 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4978 bgp_table_finish(&table);
9bcb3eef
DS
4979 bgp_dest_set_bgp_table_info(dest, NULL);
4980 bgp_dest_unlock_node(dest);
d62a17ae 4981 }
bb86c601 4982 }
718e3744 4983}
4984
d62a17ae 4985void bgp_reset(void)
718e3744 4986{
d62a17ae 4987 vty_reset();
4988 bgp_zclient_reset();
4989 access_list_reset();
4990 prefix_list_reset();
718e3744 4991}
6b0655a2 4992
d62a17ae 4993static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4994{
d62a17ae 4995 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4996 && CHECK_FLAG(peer->af_cap[afi][safi],
4997 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4998}
4999
718e3744 5000/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5001 value. */
d62a17ae 5002int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5003 struct bgp_nlri *packet)
5004{
d7c0a89a
QY
5005 uint8_t *pnt;
5006 uint8_t *lim;
d62a17ae 5007 struct prefix p;
5008 int psize;
5009 int ret;
5010 afi_t afi;
5011 safi_t safi;
5012 int addpath_encoded;
d7c0a89a 5013 uint32_t addpath_id;
d62a17ae 5014
d62a17ae 5015 pnt = packet->nlri;
5016 lim = pnt + packet->length;
5017 afi = packet->afi;
5018 safi = packet->safi;
5019 addpath_id = 0;
5020 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5021
5022 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5023 syntactic validity. If the field is syntactically incorrect,
5024 then the Error Subcode is set to Invalid Network Field. */
5025 for (; pnt < lim; pnt += psize) {
5026 /* Clear prefix structure. */
5027 memset(&p, 0, sizeof(struct prefix));
5028
5029 if (addpath_encoded) {
5030
5031 /* When packet overflow occurs return immediately. */
761ed665 5032 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5033 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5034
a3a850a1 5035 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5036 addpath_id = ntohl(addpath_id);
d62a17ae 5037 pnt += BGP_ADDPATH_ID_LEN;
5038 }
718e3744 5039
d62a17ae 5040 /* Fetch prefix length. */
5041 p.prefixlen = *pnt++;
5042 /* afi/safi validity already verified by caller,
5043 * bgp_update_receive */
5044 p.family = afi2family(afi);
5045
5046 /* Prefix length check. */
5047 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5048 flog_err(
e50f7cfd 5049 EC_BGP_UPDATE_RCV,
14454c9f 5050 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5051 peer->host, p.prefixlen, packet->afi);
513386b5 5052 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5053 }
6b0655a2 5054
d62a17ae 5055 /* Packet size overflow check. */
5056 psize = PSIZE(p.prefixlen);
5057
5058 /* When packet overflow occur return immediately. */
5059 if (pnt + psize > lim) {
af4c2728 5060 flog_err(
e50f7cfd 5061 EC_BGP_UPDATE_RCV,
d62a17ae 5062 "%s [Error] Update packet error (prefix length %d overflows packet)",
5063 peer->host, p.prefixlen);
513386b5 5064 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5065 }
5066
5067 /* Defensive coding, double-check the psize fits in a struct
5068 * prefix */
5069 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5070 flog_err(
e50f7cfd 5071 EC_BGP_UPDATE_RCV,
d62a17ae 5072 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5073 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5074 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5075 }
5076
5077 /* Fetch prefix from NLRI packet. */
a85297a7 5078 memcpy(p.u.val, pnt, psize);
d62a17ae 5079
5080 /* Check address. */
5081 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5082 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5083 /* From RFC4271 Section 6.3:
5084 *
5085 * If a prefix in the NLRI field is semantically
5086 * incorrect
5087 * (e.g., an unexpected multicast IP address),
5088 * an error SHOULD
5089 * be logged locally, and the prefix SHOULD be
5090 * ignored.
a4d82a8a 5091 */
af4c2728 5092 flog_err(
e50f7cfd 5093 EC_BGP_UPDATE_RCV,
23d0a753
DA
5094 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5095 peer->host, &p.u.prefix4);
d62a17ae 5096 continue;
5097 }
5098 }
5099
5100 /* Check address. */
5101 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5102 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5103 char buf[BUFSIZ];
5104
af4c2728 5105 flog_err(
e50f7cfd 5106 EC_BGP_UPDATE_RCV,
d62a17ae 5107 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5108 peer->host,
5109 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5110 BUFSIZ));
5111
5112 continue;
5113 }
5114 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5115 char buf[BUFSIZ];
5116
af4c2728 5117 flog_err(
e50f7cfd 5118 EC_BGP_UPDATE_RCV,
d62a17ae 5119 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5120 peer->host,
5121 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5122 BUFSIZ));
5123
5124 continue;
5125 }
5126 }
5127
5128 /* Normal process. */
5129 if (attr)
5130 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5131 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5132 NULL, NULL, 0, 0, NULL);
d62a17ae 5133 else
5134 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5135 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5136 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5137 NULL);
d62a17ae 5138
513386b5
DA
5139 /* Do not send BGP notification twice when maximum-prefix count
5140 * overflow. */
5141 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5142 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5143
5144 /* Address family configuration mismatch. */
d62a17ae 5145 if (ret < 0)
513386b5 5146 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5147 }
5148
5149 /* Packet length consistency check. */
5150 if (pnt != lim) {
af4c2728 5151 flog_err(
e50f7cfd 5152 EC_BGP_UPDATE_RCV,
d62a17ae 5153 "%s [Error] Update packet error (prefix length mismatch with total length)",
5154 peer->host);
513386b5 5155 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5156 }
6b0655a2 5157
513386b5 5158 return BGP_NLRI_PARSE_OK;
718e3744 5159}
5160
d62a17ae 5161static struct bgp_static *bgp_static_new(void)
718e3744 5162{
d62a17ae 5163 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5164}
5165
d62a17ae 5166static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5167{
0a22ddfb 5168 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5169 route_map_counter_decrement(bgp_static->rmap.map);
5170
0a22ddfb 5171 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5172 XFREE(MTYPE_BGP_STATIC, bgp_static);
5173}
5174
5f040085 5175void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5176 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5177{
9bcb3eef 5178 struct bgp_dest *dest;
40381db7 5179 struct bgp_path_info *pi;
4b7e6066 5180 struct bgp_path_info *new;
40381db7 5181 struct bgp_path_info rmap_path;
d62a17ae 5182 struct attr attr;
5183 struct attr *attr_new;
b68885f9 5184 route_map_result_t ret;
49e5a4a0 5185#ifdef ENABLE_BGP_VNC
d62a17ae 5186 int vnc_implicit_withdraw = 0;
65efcfce 5187#endif
fee0f4c6 5188
d62a17ae 5189 assert(bgp_static);
dd8103a9 5190
9bcb3eef 5191 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5192
d62a17ae 5193 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5194
d62a17ae 5195 attr.nexthop = bgp_static->igpnexthop;
5196 attr.med = bgp_static->igpmetric;
5197 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5198
d62a17ae 5199 if (bgp_static->atomic)
5200 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5201
d62a17ae 5202 /* Store label index, if required. */
5203 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5204 attr.label_index = bgp_static->label_index;
5205 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5206 }
718e3744 5207
d62a17ae 5208 /* Apply route-map. */
5209 if (bgp_static->rmap.name) {
5210 struct attr attr_tmp = attr;
80ced710 5211
40381db7
DS
5212 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5213 rmap_path.peer = bgp->peer_self;
5214 rmap_path.attr = &attr_tmp;
fee0f4c6 5215
d62a17ae 5216 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5217
40381db7
DS
5218 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5219 &rmap_path);
fee0f4c6 5220
d62a17ae 5221 bgp->peer_self->rmap_type = 0;
718e3744 5222
d62a17ae 5223 if (ret == RMAP_DENYMATCH) {
5224 /* Free uninterned attribute. */
5225 bgp_attr_flush(&attr_tmp);
718e3744 5226
d62a17ae 5227 /* Unintern original. */
5228 aspath_unintern(&attr.aspath);
5229 bgp_static_withdraw(bgp, p, afi, safi);
5230 return;
5231 }
7f323236 5232
637e5ba4 5233 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5234 bgp_attr_add_gshut_community(&attr_tmp);
5235
d62a17ae 5236 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5237 } else {
5238
637e5ba4 5239 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5240 bgp_attr_add_gshut_community(&attr);
5241
d62a17ae 5242 attr_new = bgp_attr_intern(&attr);
7f323236 5243 }
718e3744 5244
9bcb3eef 5245 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5246 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5247 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5248 break;
5249
40381db7
DS
5250 if (pi) {
5251 if (attrhash_cmp(pi->attr, attr_new)
5252 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5253 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5254 bgp_dest_unlock_node(dest);
d62a17ae 5255 bgp_attr_unintern(&attr_new);
5256 aspath_unintern(&attr.aspath);
5257 return;
5258 } else {
5259 /* The attribute is changed. */
9bcb3eef 5260 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5261
5262 /* Rewrite BGP route information. */
40381db7 5263 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5264 bgp_path_info_restore(dest, pi);
d62a17ae 5265 else
40381db7 5266 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5267#ifdef ENABLE_BGP_VNC
d62a17ae 5268 if ((afi == AFI_IP || afi == AFI_IP6)
5269 && (safi == SAFI_UNICAST)) {
40381db7 5270 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5271 /*
5272 * Implicit withdraw case.
40381db7 5273 * We have to do this before pi is
d62a17ae 5274 * changed
5275 */
5276 ++vnc_implicit_withdraw;
40381db7 5277 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5278 vnc_import_bgp_exterior_del_route(
40381db7 5279 bgp, p, pi);
d62a17ae 5280 }
5281 }
65efcfce 5282#endif
40381db7
DS
5283 bgp_attr_unintern(&pi->attr);
5284 pi->attr = attr_new;
5285 pi->uptime = bgp_clock();
49e5a4a0 5286#ifdef ENABLE_BGP_VNC
d62a17ae 5287 if ((afi == AFI_IP || afi == AFI_IP6)
5288 && (safi == SAFI_UNICAST)) {
5289 if (vnc_implicit_withdraw) {
40381db7 5290 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5291 vnc_import_bgp_exterior_add_route(
40381db7 5292 bgp, p, pi);
d62a17ae 5293 }
5294 }
65efcfce 5295#endif
718e3744 5296
d62a17ae 5297 /* Nexthop reachability check. */
892fedb6 5298 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5299 && (safi == SAFI_UNICAST
5300 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5301
5302 struct bgp *bgp_nexthop = bgp;
5303
40381db7
DS
5304 if (pi->extra && pi->extra->bgp_orig)
5305 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5306
5307 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5308 afi, pi, NULL, 0))
9bcb3eef 5309 bgp_path_info_set_flag(dest, pi,
18ee8310 5310 BGP_PATH_VALID);
d62a17ae 5311 else {
5312 if (BGP_DEBUG(nht, NHT)) {
5313 char buf1[INET6_ADDRSTRLEN];
5314 inet_ntop(p->family,
5315 &p->u.prefix, buf1,
5316 INET6_ADDRSTRLEN);
5317 zlog_debug(
5318 "%s(%s): Route not in table, not advertising",
15569c58 5319 __func__, buf1);
d62a17ae 5320 }
18ee8310 5321 bgp_path_info_unset_flag(
9bcb3eef 5322 dest, pi, BGP_PATH_VALID);
d62a17ae 5323 }
5324 } else {
5325 /* Delete the NHT structure if any, if we're
5326 * toggling between
5327 * enabling/disabling import check. We
5328 * deregister the route
5329 * from NHT to avoid overloading NHT and the
5330 * process interaction
5331 */
40381db7 5332 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5333 bgp_path_info_set_flag(dest, pi,
5334 BGP_PATH_VALID);
d62a17ae 5335 }
5336 /* Process change. */
40381db7 5337 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5338 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5339
5340 if (SAFI_UNICAST == safi
5341 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5342 || bgp->inst_type
5343 == BGP_INSTANCE_TYPE_DEFAULT)) {
5344 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5345 pi);
ddb5b488
PZ
5346 }
5347
9bcb3eef 5348 bgp_dest_unlock_node(dest);
d62a17ae 5349 aspath_unintern(&attr.aspath);
5350 return;
5351 }
718e3744 5352 }
718e3744 5353
d62a17ae 5354 /* Make new BGP info. */
5355 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5356 attr_new, dest);
d62a17ae 5357 /* Nexthop reachability check. */
892fedb6 5358 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5359 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5360 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5361 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5362 else {
5363 if (BGP_DEBUG(nht, NHT)) {
5364 char buf1[INET6_ADDRSTRLEN];
5365 inet_ntop(p->family, &p->u.prefix, buf1,
5366 INET6_ADDRSTRLEN);
5367 zlog_debug(
5368 "%s(%s): Route not in table, not advertising",
15569c58 5369 __func__, buf1);
d62a17ae 5370 }
9bcb3eef 5371 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5372 }
5373 } else {
5374 /* Delete the NHT structure if any, if we're toggling between
5375 * enabling/disabling import check. We deregister the route
5376 * from NHT to avoid overloading NHT and the process interaction
5377 */
5378 bgp_unlink_nexthop(new);
5379
9bcb3eef 5380 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5381 }
078430f6 5382
d62a17ae 5383 /* Aggregate address increment. */
5384 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5385
d62a17ae 5386 /* Register new BGP information. */
9bcb3eef 5387 bgp_path_info_add(dest, new);
718e3744 5388
d62a17ae 5389 /* route_node_get lock */
9bcb3eef 5390 bgp_dest_unlock_node(dest);
d62a17ae 5391
5392 /* Process change. */
9bcb3eef 5393 bgp_process(bgp, dest, afi, safi);
d62a17ae 5394
ddb5b488
PZ
5395 if (SAFI_UNICAST == safi
5396 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5397 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5398 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5399 }
5400
d62a17ae 5401 /* Unintern original. */
5402 aspath_unintern(&attr.aspath);
718e3744 5403}
5404
5f040085 5405void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5406 safi_t safi)
718e3744 5407{
9bcb3eef 5408 struct bgp_dest *dest;
40381db7 5409 struct bgp_path_info *pi;
718e3744 5410
9bcb3eef 5411 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5412
d62a17ae 5413 /* Check selected route and self inserted route. */
9bcb3eef 5414 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5415 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5416 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5417 break;
5418
5419 /* Withdraw static BGP route from routing table. */
40381db7 5420 if (pi) {
ddb5b488
PZ
5421 if (SAFI_UNICAST == safi
5422 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5423 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5424 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5425 }
40381db7
DS
5426 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5427 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5428 bgp_path_info_delete(dest, pi);
5429 bgp_process(bgp, dest, afi, safi);
d62a17ae 5430 }
718e3744 5431
d62a17ae 5432 /* Unlock bgp_node_lookup. */
9bcb3eef 5433 bgp_dest_unlock_node(dest);
718e3744 5434}
5435
137446f9
LB
5436/*
5437 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5438 */
5f040085 5439static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5440 afi_t afi, safi_t safi,
5441 struct prefix_rd *prd)
718e3744 5442{
9bcb3eef 5443 struct bgp_dest *dest;
40381db7 5444 struct bgp_path_info *pi;
718e3744 5445
9bcb3eef 5446 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5447
d62a17ae 5448 /* Check selected route and self inserted route. */
9bcb3eef 5449 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5450 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5451 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5452 break;
718e3744 5453
d62a17ae 5454 /* Withdraw static BGP route from routing table. */
40381db7 5455 if (pi) {
49e5a4a0 5456#ifdef ENABLE_BGP_VNC
d62a17ae 5457 rfapiProcessWithdraw(
40381db7 5458 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5459 1); /* Kill, since it is an administrative change */
65efcfce 5460#endif
ddb5b488
PZ
5461 if (SAFI_MPLS_VPN == safi
5462 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5463 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5464 }
40381db7 5465 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5466 bgp_path_info_delete(dest, pi);
5467 bgp_process(bgp, dest, afi, safi);
d62a17ae 5468 }
718e3744 5469
d62a17ae 5470 /* Unlock bgp_node_lookup. */
9bcb3eef 5471 bgp_dest_unlock_node(dest);
718e3744 5472}
5473
5f040085 5474static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5475 struct bgp_static *bgp_static, afi_t afi,
5476 safi_t safi)
137446f9 5477{
9bcb3eef 5478 struct bgp_dest *dest;
4b7e6066 5479 struct bgp_path_info *new;
d62a17ae 5480 struct attr *attr_new;
5481 struct attr attr = {0};
40381db7 5482 struct bgp_path_info *pi;
49e5a4a0 5483#ifdef ENABLE_BGP_VNC
d62a17ae 5484 mpls_label_t label = 0;
65efcfce 5485#endif
d7c0a89a 5486 uint32_t num_labels = 0;
d62a17ae 5487 union gw_addr add;
137446f9 5488
d62a17ae 5489 assert(bgp_static);
137446f9 5490
b57ba6d2
MK
5491 if (bgp_static->label != MPLS_INVALID_LABEL)
5492 num_labels = 1;
9bcb3eef
DS
5493 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5494 &bgp_static->prd);
137446f9 5495
d62a17ae 5496 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5497
d62a17ae 5498 attr.nexthop = bgp_static->igpnexthop;
5499 attr.med = bgp_static->igpmetric;
5500 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5501
d62a17ae 5502 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5503 || (safi == SAFI_ENCAP)) {
5504 if (afi == AFI_IP) {
5505 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5506 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5507 }
5508 }
5509 if (afi == AFI_L2VPN) {
5510 if (bgp_static->gatewayIp.family == AF_INET)
5511 add.ipv4.s_addr =
5512 bgp_static->gatewayIp.u.prefix4.s_addr;
5513 else if (bgp_static->gatewayIp.family == AF_INET6)
5514 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5515 sizeof(struct in6_addr));
0a50c248 5516 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5517 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5518 struct bgp_encap_type_vxlan bet;
5519 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5520 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5521 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5522 }
5523 if (bgp_static->router_mac) {
5524 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5525 }
5526 }
5527 /* Apply route-map. */
5528 if (bgp_static->rmap.name) {
5529 struct attr attr_tmp = attr;
40381db7 5530 struct bgp_path_info rmap_path;
b68885f9 5531 route_map_result_t ret;
137446f9 5532
40381db7
DS
5533 rmap_path.peer = bgp->peer_self;
5534 rmap_path.attr = &attr_tmp;
137446f9 5535
d62a17ae 5536 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5537
40381db7
DS
5538 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5539 &rmap_path);
137446f9 5540
d62a17ae 5541 bgp->peer_self->rmap_type = 0;
137446f9 5542
d62a17ae 5543 if (ret == RMAP_DENYMATCH) {
5544 /* Free uninterned attribute. */
5545 bgp_attr_flush(&attr_tmp);
137446f9 5546
d62a17ae 5547 /* Unintern original. */
5548 aspath_unintern(&attr.aspath);
5549 bgp_static_withdraw_safi(bgp, p, afi, safi,
5550 &bgp_static->prd);
5551 return;
5552 }
137446f9 5553
d62a17ae 5554 attr_new = bgp_attr_intern(&attr_tmp);
5555 } else {
5556 attr_new = bgp_attr_intern(&attr);
5557 }
137446f9 5558
9bcb3eef 5559 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5560 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5561 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5562 break;
5563
40381db7 5564 if (pi) {
d62a17ae 5565 memset(&add, 0, sizeof(union gw_addr));
40381db7 5566 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5567 && overlay_index_equal(afi, pi, &add)
40381db7 5568 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5569 bgp_dest_unlock_node(dest);
d62a17ae 5570 bgp_attr_unintern(&attr_new);
5571 aspath_unintern(&attr.aspath);
5572 return;
5573 } else {
5574 /* The attribute is changed. */
9bcb3eef 5575 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5576
5577 /* Rewrite BGP route information. */
40381db7 5578 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5579 bgp_path_info_restore(dest, pi);
d62a17ae 5580 else
40381db7
DS
5581 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5582 bgp_attr_unintern(&pi->attr);
5583 pi->attr = attr_new;
5584 pi->uptime = bgp_clock();
49e5a4a0 5585#ifdef ENABLE_BGP_VNC
40381db7
DS
5586 if (pi->extra)
5587 label = decode_label(&pi->extra->label[0]);
65efcfce 5588#endif
137446f9 5589
d62a17ae 5590 /* Process change. */
40381db7 5591 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5592 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5593
5594 if (SAFI_MPLS_VPN == safi
5595 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5596 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5597 }
49e5a4a0 5598#ifdef ENABLE_BGP_VNC
40381db7
DS
5599 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5600 pi->attr, afi, safi, pi->type,
5601 pi->sub_type, &label);
65efcfce 5602#endif
9bcb3eef 5603 bgp_dest_unlock_node(dest);
d62a17ae 5604 aspath_unintern(&attr.aspath);
5605 return;
5606 }
5607 }
137446f9
LB
5608
5609
d62a17ae 5610 /* Make new BGP info. */
5611 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5612 attr_new, dest);
1defdda8 5613 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5614 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5615 if (num_labels) {
5616 new->extra->label[0] = bgp_static->label;
5617 new->extra->num_labels = num_labels;
5618 }
49e5a4a0 5619#ifdef ENABLE_BGP_VNC
d62a17ae 5620 label = decode_label(&bgp_static->label);
65efcfce 5621#endif
137446f9 5622
d62a17ae 5623 /* Aggregate address increment. */
5624 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5625
d62a17ae 5626 /* Register new BGP information. */
9bcb3eef 5627 bgp_path_info_add(dest, new);
d62a17ae 5628 /* route_node_get lock */
9bcb3eef 5629 bgp_dest_unlock_node(dest);
137446f9 5630
d62a17ae 5631 /* Process change. */
9bcb3eef 5632 bgp_process(bgp, dest, afi, safi);
137446f9 5633
ddb5b488
PZ
5634 if (SAFI_MPLS_VPN == safi
5635 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5636 vpn_leak_to_vrf_update(bgp, new);
5637 }
49e5a4a0 5638#ifdef ENABLE_BGP_VNC
d62a17ae 5639 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5640 safi, new->type, new->sub_type, &label);
65efcfce
LB
5641#endif
5642
d62a17ae 5643 /* Unintern original. */
5644 aspath_unintern(&attr.aspath);
137446f9
LB
5645}
5646
718e3744 5647/* Configure static BGP network. When user don't run zebra, static
5648 route should be installed as valid. */
37a87b8f
CS
5649int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5650 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5651 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5652{
d62a17ae 5653 struct prefix p;
5654 struct bgp_static *bgp_static;
9bcb3eef 5655 struct bgp_dest *dest;
d7c0a89a 5656 uint8_t need_update = 0;
d62a17ae 5657
37a87b8f 5658 prefix_copy(&p, pfx);
d62a17ae 5659 apply_mask(&p);
718e3744 5660
e2a86ad9 5661 if (negate) {
718e3744 5662
e2a86ad9 5663 /* Set BGP static route configuration. */
9bcb3eef 5664 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5665
9bcb3eef 5666 if (!dest) {
37a87b8f
CS
5667 snprintf(errmsg, errmsg_len,
5668 "Can't find static route specified\n");
5669 return -1;
d62a17ae 5670 }
5671
9bcb3eef 5672 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5673
e2a86ad9
DS
5674 if ((label_index != BGP_INVALID_LABEL_INDEX)
5675 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5676 snprintf(errmsg, errmsg_len,
5677 "label-index doesn't match static route\n");
5678 return -1;
d62a17ae 5679 }
d62a17ae 5680
e2a86ad9
DS
5681 if ((rmap && bgp_static->rmap.name)
5682 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5683 snprintf(errmsg, errmsg_len,
5684 "route-map name doesn't match static route\n");
5685 return -1;
d62a17ae 5686 }
718e3744 5687
e2a86ad9
DS
5688 /* Update BGP RIB. */
5689 if (!bgp_static->backdoor)
5690 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5691
e2a86ad9
DS
5692 /* Clear configuration. */
5693 bgp_static_free(bgp_static);
9bcb3eef
DS
5694 bgp_dest_set_bgp_static_info(dest, NULL);
5695 bgp_dest_unlock_node(dest);
5696 bgp_dest_unlock_node(dest);
e2a86ad9 5697 } else {
718e3744 5698
e2a86ad9 5699 /* Set BGP static route configuration. */
9bcb3eef
DS
5700 dest = bgp_node_get(bgp->route[afi][safi], &p);
5701 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5702 if (bgp_static) {
e2a86ad9 5703 /* Configuration change. */
e2a86ad9
DS
5704 /* Label index cannot be changed. */
5705 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5706 snprintf(errmsg, errmsg_len,
5707 "cannot change label-index\n");
5708 return -1;
e2a86ad9 5709 }
d62a17ae 5710
e2a86ad9 5711 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5712 if (bgp_static->valid
5713 && bgp_static->backdoor != backdoor)
e2a86ad9 5714 need_update = 1;
718e3744 5715
e2a86ad9 5716 bgp_static->backdoor = backdoor;
718e3744 5717
e2a86ad9 5718 if (rmap) {
0a22ddfb
QY
5719 XFREE(MTYPE_ROUTE_MAP_NAME,
5720 bgp_static->rmap.name);
b4897fa5 5721 route_map_counter_decrement(
5722 bgp_static->rmap.map);
e2a86ad9
DS
5723 bgp_static->rmap.name =
5724 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5725 bgp_static->rmap.map =
5726 route_map_lookup_by_name(rmap);
b4897fa5 5727 route_map_counter_increment(
5728 bgp_static->rmap.map);
e2a86ad9 5729 } else {
0a22ddfb
QY
5730 XFREE(MTYPE_ROUTE_MAP_NAME,
5731 bgp_static->rmap.name);
b4897fa5 5732 route_map_counter_decrement(
5733 bgp_static->rmap.map);
e2a86ad9
DS
5734 bgp_static->rmap.map = NULL;
5735 bgp_static->valid = 0;
5736 }
9bcb3eef 5737 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5738 } else {
5739 /* New configuration. */
5740 bgp_static = bgp_static_new();
5741 bgp_static->backdoor = backdoor;
5742 bgp_static->valid = 0;
5743 bgp_static->igpmetric = 0;
975a328e 5744 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5745 bgp_static->label_index = label_index;
718e3744 5746
e2a86ad9 5747 if (rmap) {
0a22ddfb
QY
5748 XFREE(MTYPE_ROUTE_MAP_NAME,
5749 bgp_static->rmap.name);
b4897fa5 5750 route_map_counter_decrement(
5751 bgp_static->rmap.map);
e2a86ad9
DS
5752 bgp_static->rmap.name =
5753 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5754 bgp_static->rmap.map =
5755 route_map_lookup_by_name(rmap);
b4897fa5 5756 route_map_counter_increment(
5757 bgp_static->rmap.map);
e2a86ad9 5758 }
9bcb3eef 5759 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5760 }
d62a17ae 5761
e2a86ad9
DS
5762 bgp_static->valid = 1;
5763 if (need_update)
5764 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5765
e2a86ad9
DS
5766 if (!bgp_static->backdoor)
5767 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5768 }
d62a17ae 5769
37a87b8f 5770 return 0;
d62a17ae 5771}
5772
5773void bgp_static_add(struct bgp *bgp)
5774{
5775 afi_t afi;
5776 safi_t safi;
9bcb3eef
DS
5777 struct bgp_dest *dest;
5778 struct bgp_dest *rm;
d62a17ae 5779 struct bgp_table *table;
5780 struct bgp_static *bgp_static;
5781
05c7a1cc 5782 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5783 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5784 dest = bgp_route_next(dest)) {
5785 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5786 continue;
ea47320b 5787
05c7a1cc
QY
5788 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5789 || (safi == SAFI_EVPN)) {
9bcb3eef 5790 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5791
5792 for (rm = bgp_table_top(table); rm;
5793 rm = bgp_route_next(rm)) {
a78beeb5 5794 bgp_static =
9bcb3eef 5795 bgp_dest_get_bgp_static_info(
5a8ba9fc 5796 rm);
9bcb3eef
DS
5797 bgp_static_update_safi(
5798 bgp, bgp_dest_get_prefix(rm),
5799 bgp_static, afi, safi);
d62a17ae 5800 }
05c7a1cc 5801 } else {
5a8ba9fc 5802 bgp_static_update(
9bcb3eef
DS
5803 bgp, bgp_dest_get_prefix(dest),
5804 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5805 safi);
ea47320b 5806 }
05c7a1cc 5807 }
6aeb9e78
DS
5808}
5809
718e3744 5810/* Called from bgp_delete(). Delete all static routes from the BGP
5811 instance. */
d62a17ae 5812void bgp_static_delete(struct bgp *bgp)
5813{
5814 afi_t afi;
5815 safi_t safi;
9bcb3eef
DS
5816 struct bgp_dest *dest;
5817 struct bgp_dest *rm;
d62a17ae 5818 struct bgp_table *table;
5819 struct bgp_static *bgp_static;
5820
05c7a1cc 5821 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5822 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5823 dest = bgp_route_next(dest)) {
5824 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5825 continue;
ea47320b 5826
05c7a1cc
QY
5827 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5828 || (safi == SAFI_EVPN)) {
9bcb3eef 5829 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5830
5831 for (rm = bgp_table_top(table); rm;
5832 rm = bgp_route_next(rm)) {
a78beeb5 5833 bgp_static =
9bcb3eef 5834 bgp_dest_get_bgp_static_info(
5a8ba9fc 5835 rm);
c7d14ba6
PG
5836 if (!bgp_static)
5837 continue;
5838
05c7a1cc 5839 bgp_static_withdraw_safi(
9bcb3eef 5840 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5841 AFI_IP, safi,
5842 (struct prefix_rd *)
9bcb3eef
DS
5843 bgp_dest_get_prefix(
5844 dest));
ea47320b 5845 bgp_static_free(bgp_static);
811c6797 5846 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5847 NULL);
811c6797 5848 bgp_dest_unlock_node(rm);
d62a17ae 5849 }
05c7a1cc 5850 } else {
9bcb3eef 5851 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5852 bgp_static_withdraw(bgp,
9bcb3eef 5853 bgp_dest_get_prefix(dest),
b54892e0 5854 afi, safi);
05c7a1cc 5855 bgp_static_free(bgp_static);
9bcb3eef
DS
5856 bgp_dest_set_bgp_static_info(dest, NULL);
5857 bgp_dest_unlock_node(dest);
ea47320b 5858 }
05c7a1cc 5859 }
d62a17ae 5860}
5861
5862void bgp_static_redo_import_check(struct bgp *bgp)
5863{
5864 afi_t afi;
5865 safi_t safi;
9bcb3eef
DS
5866 struct bgp_dest *dest;
5867 struct bgp_dest *rm;
d62a17ae 5868 struct bgp_table *table;
5869 struct bgp_static *bgp_static;
5870
5871 /* Use this flag to force reprocessing of the route */
892fedb6 5872 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5873 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5874 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5875 dest = bgp_route_next(dest)) {
5876 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5877 continue;
ea47320b 5878
05c7a1cc
QY
5879 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5880 || (safi == SAFI_EVPN)) {
9bcb3eef 5881 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5882
5883 for (rm = bgp_table_top(table); rm;
5884 rm = bgp_route_next(rm)) {
a78beeb5 5885 bgp_static =
9bcb3eef 5886 bgp_dest_get_bgp_static_info(
5a8ba9fc 5887 rm);
9bcb3eef
DS
5888 bgp_static_update_safi(
5889 bgp, bgp_dest_get_prefix(rm),
5890 bgp_static, afi, safi);
d62a17ae 5891 }
05c7a1cc 5892 } else {
9bcb3eef
DS
5893 bgp_static = bgp_dest_get_bgp_static_info(dest);
5894 bgp_static_update(bgp,
5895 bgp_dest_get_prefix(dest),
5896 bgp_static, afi, safi);
ea47320b 5897 }
05c7a1cc
QY
5898 }
5899 }
892fedb6 5900 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5901}
5902
5903static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5904 safi_t safi)
5905{
5906 struct bgp_table *table;
9bcb3eef 5907 struct bgp_dest *dest;
40381db7 5908 struct bgp_path_info *pi;
d62a17ae 5909
dfb6fd1d
NT
5910 /* Do not install the aggregate route if BGP is in the
5911 * process of termination.
5912 */
892fedb6
DA
5913 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5914 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5915 return;
5916
d62a17ae 5917 table = bgp->rib[afi][safi];
9bcb3eef
DS
5918 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5919 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5920 if (pi->peer == bgp->peer_self
5921 && ((pi->type == ZEBRA_ROUTE_BGP
5922 && pi->sub_type == BGP_ROUTE_STATIC)
5923 || (pi->type != ZEBRA_ROUTE_BGP
5924 && pi->sub_type
d62a17ae 5925 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5926 bgp_aggregate_decrement(
5927 bgp, bgp_dest_get_prefix(dest), pi, afi,
5928 safi);
40381db7 5929 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5930 bgp_path_info_delete(dest, pi);
5931 bgp_process(bgp, dest, afi, safi);
d62a17ae 5932 }
5933 }
5934 }
ad4cbda1 5935}
5936
5937/*
5938 * Purge all networks and redistributed routes from routing table.
5939 * Invoked upon the instance going down.
5940 */
d62a17ae 5941void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5942{
d62a17ae 5943 afi_t afi;
5944 safi_t safi;
ad4cbda1 5945
05c7a1cc
QY
5946 FOREACH_AFI_SAFI (afi, safi)
5947 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5948}
5949
137446f9
LB
5950/*
5951 * gpz 110624
5952 * Currently this is used to set static routes for VPN and ENCAP.
5953 * I think it can probably be factored with bgp_static_set.
5954 */
d62a17ae 5955int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5956 const char *ip_str, const char *rd_str,
5957 const char *label_str, const char *rmap_str,
5958 int evpn_type, const char *esi, const char *gwip,
5959 const char *ethtag, const char *routermac)
5960{
5961 VTY_DECLVAR_CONTEXT(bgp, bgp);
5962 int ret;
5963 struct prefix p;
5964 struct prefix_rd prd;
9bcb3eef
DS
5965 struct bgp_dest *pdest;
5966 struct bgp_dest *dest;
d62a17ae 5967 struct bgp_table *table;
5968 struct bgp_static *bgp_static;
5969 mpls_label_t label = MPLS_INVALID_LABEL;
5970 struct prefix gw_ip;
5971
5972 /* validate ip prefix */
5973 ret = str2prefix(ip_str, &p);
5974 if (!ret) {
5975 vty_out(vty, "%% Malformed prefix\n");
5976 return CMD_WARNING_CONFIG_FAILED;
5977 }
5978 apply_mask(&p);
5979 if ((afi == AFI_L2VPN)
5980 && (bgp_build_evpn_prefix(evpn_type,
5981 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5982 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5983 return CMD_WARNING_CONFIG_FAILED;
5984 }
718e3744 5985
d62a17ae 5986 ret = str2prefix_rd(rd_str, &prd);
5987 if (!ret) {
5988 vty_out(vty, "%% Malformed rd\n");
5989 return CMD_WARNING_CONFIG_FAILED;
5990 }
718e3744 5991
d62a17ae 5992 if (label_str) {
5993 unsigned long label_val;
5994 label_val = strtoul(label_str, NULL, 10);
5995 encode_label(label_val, &label);
5996 }
9bedbb1e 5997
d62a17ae 5998 if (safi == SAFI_EVPN) {
5999 if (esi && str2esi(esi, NULL) == 0) {
6000 vty_out(vty, "%% Malformed ESI\n");
6001 return CMD_WARNING_CONFIG_FAILED;
6002 }
6003 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6004 vty_out(vty, "%% Malformed Router MAC\n");
6005 return CMD_WARNING_CONFIG_FAILED;
6006 }
6007 if (gwip) {
6008 memset(&gw_ip, 0, sizeof(struct prefix));
6009 ret = str2prefix(gwip, &gw_ip);
6010 if (!ret) {
6011 vty_out(vty, "%% Malformed GatewayIp\n");
6012 return CMD_WARNING_CONFIG_FAILED;
6013 }
6014 if ((gw_ip.family == AF_INET
3714a385 6015 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6016 (struct prefix_evpn *)&p))
6017 || (gw_ip.family == AF_INET6
3714a385 6018 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6019 (struct prefix_evpn *)&p))) {
6020 vty_out(vty,
6021 "%% GatewayIp family differs with IP prefix\n");
6022 return CMD_WARNING_CONFIG_FAILED;
6023 }
6024 }
6025 }
9bcb3eef
DS
6026 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6027 if (!bgp_dest_has_bgp_path_info_data(pdest))
6028 bgp_dest_set_bgp_table_info(pdest,
67009e22 6029 bgp_table_init(bgp, afi, safi));
9bcb3eef 6030 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6031
9bcb3eef 6032 dest = bgp_node_get(table, &p);
d62a17ae 6033
9bcb3eef 6034 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6035 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6036 bgp_dest_unlock_node(dest);
d62a17ae 6037 } else {
6038 /* New configuration. */
6039 bgp_static = bgp_static_new();
6040 bgp_static->backdoor = 0;
6041 bgp_static->valid = 0;
6042 bgp_static->igpmetric = 0;
975a328e 6043 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6044 bgp_static->label = label;
6045 bgp_static->prd = prd;
6046
6047 if (rmap_str) {
0a22ddfb 6048 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6049 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6050 bgp_static->rmap.name =
6051 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6052 bgp_static->rmap.map =
6053 route_map_lookup_by_name(rmap_str);
b4897fa5 6054 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6055 }
718e3744 6056
d62a17ae 6057 if (safi == SAFI_EVPN) {
6058 if (esi) {
6059 bgp_static->eth_s_id =
6060 XCALLOC(MTYPE_ATTR,
0a50c248 6061 sizeof(esi_t));
d62a17ae 6062 str2esi(esi, bgp_static->eth_s_id);
6063 }
6064 if (routermac) {
6065 bgp_static->router_mac =
28328ea9 6066 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6067 (void)prefix_str2mac(routermac,
6068 bgp_static->router_mac);
d62a17ae 6069 }
6070 if (gwip)
6071 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6072 }
9bcb3eef 6073 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6074
d62a17ae 6075 bgp_static->valid = 1;
6076 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6077 }
718e3744 6078
d62a17ae 6079 return CMD_SUCCESS;
718e3744 6080}
6081
6082/* Configure static BGP network. */
d62a17ae 6083int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6084 const char *ip_str, const char *rd_str,
6085 const char *label_str, int evpn_type, const char *esi,
6086 const char *gwip, const char *ethtag)
6087{
6088 VTY_DECLVAR_CONTEXT(bgp, bgp);
6089 int ret;
6090 struct prefix p;
6091 struct prefix_rd prd;
9bcb3eef
DS
6092 struct bgp_dest *pdest;
6093 struct bgp_dest *dest;
d62a17ae 6094 struct bgp_table *table;
6095 struct bgp_static *bgp_static;
6096 mpls_label_t label = MPLS_INVALID_LABEL;
6097
6098 /* Convert IP prefix string to struct prefix. */
6099 ret = str2prefix(ip_str, &p);
6100 if (!ret) {
6101 vty_out(vty, "%% Malformed prefix\n");
6102 return CMD_WARNING_CONFIG_FAILED;
6103 }
6104 apply_mask(&p);
6105 if ((afi == AFI_L2VPN)
6106 && (bgp_build_evpn_prefix(evpn_type,
6107 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6108 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6109 return CMD_WARNING_CONFIG_FAILED;
6110 }
6111 ret = str2prefix_rd(rd_str, &prd);
6112 if (!ret) {
6113 vty_out(vty, "%% Malformed rd\n");
6114 return CMD_WARNING_CONFIG_FAILED;
6115 }
718e3744 6116
d62a17ae 6117 if (label_str) {
6118 unsigned long label_val;
6119 label_val = strtoul(label_str, NULL, 10);
6120 encode_label(label_val, &label);
6121 }
718e3744 6122
9bcb3eef
DS
6123 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6124 if (!bgp_dest_has_bgp_path_info_data(pdest))
6125 bgp_dest_set_bgp_table_info(pdest,
67009e22 6126 bgp_table_init(bgp, afi, safi));
d62a17ae 6127 else
9bcb3eef
DS
6128 bgp_dest_unlock_node(pdest);
6129 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6130
9bcb3eef 6131 dest = bgp_node_lookup(table, &p);
6b0655a2 6132
9bcb3eef 6133 if (dest) {
d62a17ae 6134 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6135
9bcb3eef 6136 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6137 bgp_static_free(bgp_static);
9bcb3eef
DS
6138 bgp_dest_set_bgp_static_info(dest, NULL);
6139 bgp_dest_unlock_node(dest);
6140 bgp_dest_unlock_node(dest);
d62a17ae 6141 } else
6142 vty_out(vty, "%% Can't find the route\n");
6143
6144 return CMD_SUCCESS;
6145}
6146
6147static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6148 const char *rmap_name)
6149{
6150 VTY_DECLVAR_CONTEXT(bgp, bgp);
6151 struct bgp_rmap *rmap;
6152
6153 rmap = &bgp->table_map[afi][safi];
6154 if (rmap_name) {
0a22ddfb 6155 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6156 route_map_counter_decrement(rmap->map);
d62a17ae 6157 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6158 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6159 route_map_counter_increment(rmap->map);
d62a17ae 6160 } else {
0a22ddfb 6161 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6162 route_map_counter_decrement(rmap->map);
d62a17ae 6163 rmap->map = NULL;
6164 }
73ac8160 6165
d62a17ae 6166 if (bgp_fibupd_safi(safi))
6167 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6168
d62a17ae 6169 return CMD_SUCCESS;
73ac8160
DS
6170}
6171
d62a17ae 6172static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6173 const char *rmap_name)
73ac8160 6174{
d62a17ae 6175 VTY_DECLVAR_CONTEXT(bgp, bgp);
6176 struct bgp_rmap *rmap;
73ac8160 6177
d62a17ae 6178 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6179 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6180 route_map_counter_decrement(rmap->map);
d62a17ae 6181 rmap->map = NULL;
73ac8160 6182
d62a17ae 6183 if (bgp_fibupd_safi(safi))
6184 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6185
d62a17ae 6186 return CMD_SUCCESS;
73ac8160
DS
6187}
6188
2b791107 6189void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6190 safi_t safi)
73ac8160 6191{
d62a17ae 6192 if (bgp->table_map[afi][safi].name) {
d62a17ae 6193 vty_out(vty, " table-map %s\n",
6194 bgp->table_map[afi][safi].name);
6195 }
73ac8160
DS
6196}
6197
73ac8160
DS
6198DEFUN (bgp_table_map,
6199 bgp_table_map_cmd,
6200 "table-map WORD",
6201 "BGP table to RIB route download filter\n"
6202 "Name of the route map\n")
6203{
d62a17ae 6204 int idx_word = 1;
6205 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6206 argv[idx_word]->arg);
73ac8160
DS
6207}
6208DEFUN (no_bgp_table_map,
6209 no_bgp_table_map_cmd,
6210 "no table-map WORD",
3a2d747c 6211 NO_STR
73ac8160
DS
6212 "BGP table to RIB route download filter\n"
6213 "Name of the route map\n")
6214{
d62a17ae 6215 int idx_word = 2;
6216 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6217 argv[idx_word]->arg);
73ac8160
DS
6218}
6219
37a87b8f
CS
6220DEFPY_YANG (bgp_network, bgp_network_cmd,
6221 "[no] network \
6222 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6223 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6224 backdoor$backdoor}]",
6225 NO_STR
6226 "Specify a network to announce via BGP\n"
6227 "IPv4 prefix\n"
6228 "Network number\n"
6229 "Network mask\n"
6230 "Network mask\n"
6231 "Route-map to modify the attributes\n"
6232 "Name of the route map\n"
6233 "Label index to associate with the prefix\n"
6234 "Label index value\n"
6235 "Specify a BGP backdoor route\n")
6236{
6237 char addr_prefix_str[PREFIX_STRLEN];
6238 char base_xpath[XPATH_MAXLEN];
6239 afi_t afi;
6240 safi_t safi;
e2a86ad9
DS
6241
6242 if (address_str) {
6243 int ret;
718e3744 6244
e2a86ad9
DS
6245 ret = netmask_str2prefix_str(address_str, netmask_str,
6246 addr_prefix_str);
6247 if (!ret) {
6248 vty_out(vty, "%% Inconsistent address and mask\n");
6249 return CMD_WARNING_CONFIG_FAILED;
6250 }
d62a17ae 6251 }
718e3744 6252
37a87b8f
CS
6253 afi = bgp_node_afi(vty);
6254 safi = bgp_node_safi(vty);
6255
6256 if (no) {
6257 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6258 } else {
6259 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6260
6261 if (map_name)
6262 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6263 NB_OP_CREATE, map_name);
6264 else
6265 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6266 NB_OP_DESTROY, NULL);
6267
6268 if (label_index_str)
6269 nb_cli_enqueue_change(vty, "./label-index",
6270 NB_OP_MODIFY, label_index_str);
6271
6272 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6273 backdoor ? "true" : "false");
6274 }
6275
6276 snprintf(
6277 base_xpath, sizeof(base_xpath),
6278 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6279 yang_afi_safi_value2identity(afi, safi),
6280 bgp_afi_safi_get_container_str(afi, safi),
6281 address_str ? addr_prefix_str : prefix_str);
6282
6283 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6284}
6285
37a87b8f
CS
6286DEFPY_YANG (ipv6_bgp_network,
6287 ipv6_bgp_network_cmd,
6288 "[no] network X:X::X:X/M$prefix \
6289 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6290 NO_STR
6291 "Specify a network to announce via BGP\n"
6292 "IPv6 prefix\n"
6293 "Route-map to modify the attributes\n"
6294 "Name of the route map\n"
6295 "Label index to associate with the prefix\n"
6296 "Label index value\n")
6297{
6298 char base_xpath[XPATH_MAXLEN];
6299 afi_t afi;
6300 safi_t safi;
6301
6302 afi = bgp_node_afi(vty);
6303 safi = bgp_node_safi(vty);
6304
6305 if (no) {
6306 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6307 } else {
6308 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6309
6310 if (map_name)
6311 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6312 NB_OP_MODIFY, map_name);
6313 else
6314 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6315 NB_OP_DESTROY, NULL);
6316
6317 if (label_index_str)
6318 nb_cli_enqueue_change(vty, "./label-index",
6319 NB_OP_MODIFY, label_index_str);
6320 }
6321
6322 snprintf(
6323 base_xpath, sizeof(base_xpath),
6324 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6325 yang_afi_safi_value2identity(afi, safi),
6326 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6327
6328 return nb_cli_apply_changes(vty, base_xpath);
6329}
6330
6331void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6332 struct lyd_node *dnode,
6333 bool show_defaults)
718e3744 6334{
37a87b8f
CS
6335 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6336
6337 if (yang_dnode_exists(dnode, "./label-index"))
6338 vty_out(vty, " label-index %s",
6339 yang_dnode_get_string(dnode, "./label-index"));
6340
6341 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6342 vty_out(vty, " route-map %s",
6343 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6344
6345 if (yang_dnode_get_bool(dnode, "./backdoor"))
6346 vty_out(vty, " backdoor");
6347
6348 vty_out(vty, "\n");
1b6d5c7e
VV
6349}
6350
d62a17ae 6351static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6352{
d62a17ae 6353 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6354}
6355
d62a17ae 6356static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6357{
365ab2e7
RZ
6358 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6359 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6360 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6361 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6362 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6363}
718e3744 6364
365ab2e7
RZ
6365/**
6366 * Helper function to avoid repeated code: prepare variables for a
6367 * `route_map_apply` call.
6368 *
6369 * \returns `true` on route map match, otherwise `false`.
6370 */
6371static bool aggr_suppress_map_test(struct bgp *bgp,
6372 struct bgp_aggregate *aggregate,
6373 struct bgp_path_info *pi)
6374{
6375 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6376 route_map_result_t rmr = RMAP_DENYMATCH;
6377 struct bgp_path_info rmap_path = {};
6378 struct attr attr = {};
6379
6380 /* No route map entries created, just don't match. */
6381 if (aggregate->suppress_map == NULL)
6382 return false;
6383
6384 /* Call route map matching and return result. */
6385 attr.aspath = aspath_empty();
6386 rmap_path.peer = bgp->peer_self;
6387 rmap_path.attr = &attr;
6388
6389 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
6390 rmr = route_map_apply(aggregate->suppress_map, p, RMAP_BGP, &rmap_path);
6391 bgp->peer_self->rmap_type = 0;
6392
6393 bgp_attr_flush(&attr);
6394
6395 return rmr == RMAP_PERMITMATCH;
6396}
6397
4056a5f6
RZ
6398/** Test whether the aggregation has suppressed this path or not. */
6399static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6400 struct bgp_path_info *pi)
6401{
6402 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6403 return false;
6404
6405 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6406}
6407
6408/**
6409 * Suppress this path and keep the reference.
6410 *
6411 * \returns `true` if needs processing otherwise `false`.
6412 */
6413static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6414 struct bgp_path_info *pi)
6415{
6416 struct bgp_path_info_extra *pie;
6417
6418 /* Path is already suppressed by this aggregation. */
6419 if (aggr_suppress_exists(aggregate, pi))
6420 return false;
6421
6422 pie = bgp_path_info_extra_get(pi);
6423
6424 /* This is the first suppression, allocate memory and list it. */
6425 if (pie->aggr_suppressors == NULL)
6426 pie->aggr_suppressors = list_new();
6427
6428 listnode_add(pie->aggr_suppressors, aggregate);
6429
6430 /* Only mark for processing if suppressed. */
6431 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6432 if (BGP_DEBUG(update, UPDATE_OUT))
6433 zlog_debug("aggregate-address suppressing: %pFX",
6434 bgp_dest_get_prefix(pi->net));
6435
4056a5f6
RZ
6436 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6437 return true;
6438 }
6439
6440 return false;
6441}
6442
6443/**
6444 * Unsuppress this path and remove the reference.
6445 *
6446 * \returns `true` if needs processing otherwise `false`.
6447 */
6448static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6449 struct bgp_path_info *pi)
6450{
6451 /* Path wasn't suppressed. */
6452 if (!aggr_suppress_exists(aggregate, pi))
6453 return false;
6454
6455 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6456
6457 /* Unsuppress and free extra memory if last item. */
6458 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6459 if (BGP_DEBUG(update, UPDATE_OUT))
6460 zlog_debug("aggregate-address unsuppressing: %pFX",
6461 bgp_dest_get_prefix(pi->net));
6462
4056a5f6
RZ
6463 list_delete(&pi->extra->aggr_suppressors);
6464 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6465 return true;
6466 }
6467
6468 return false;
6469}
6470
3dc339cd
DA
6471static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6472 struct aspath *aspath,
6473 struct community *comm,
6474 struct ecommunity *ecomm,
6475 struct lcommunity *lcomm)
eaaf8adb
DS
6476{
6477 static struct aspath *ae = NULL;
6478
6479 if (!ae)
6480 ae = aspath_empty();
6481
40381db7 6482 if (!pi)
3dc339cd 6483 return false;
eaaf8adb 6484
40381db7 6485 if (origin != pi->attr->origin)
3dc339cd 6486 return false;
eaaf8adb 6487
40381db7 6488 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6489 return false;
29f7d023 6490
40381db7 6491 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6492 return false;
eaaf8adb 6493
3da2cc32 6494 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6495 return false;
eaaf8adb 6496
dd18c5a9 6497 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6498 return false;
dd18c5a9 6499
40381db7 6500 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6501 return false;
7ce8a8e0 6502
3dc339cd 6503 return true;
eaaf8adb
DS
6504}
6505
5f040085
DS
6506static void bgp_aggregate_install(
6507 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6508 uint8_t origin, struct aspath *aspath, struct community *community,
6509 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6510 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6511{
9bcb3eef 6512 struct bgp_dest *dest;
c701010e 6513 struct bgp_table *table;
6f94b685 6514 struct bgp_path_info *pi, *orig, *new;
20894f50 6515 struct attr *attr;
c701010e
DS
6516
6517 table = bgp->rib[afi][safi];
6518
9bcb3eef 6519 dest = bgp_node_get(table, p);
eaaf8adb 6520
9bcb3eef 6521 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6522 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6523 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6524 break;
6525
6aabb15d
RZ
6526 /*
6527 * If we have paths with different MEDs, then don't install
6528 * (or uninstall) the aggregate route.
6529 */
6530 if (aggregate->match_med && aggregate->med_mismatched)
6531 goto uninstall_aggregate_route;
6532
c701010e 6533 if (aggregate->count > 0) {
eaaf8adb
DS
6534 /*
6535 * If the aggregate information has not changed
6536 * no need to re-install it again.
6537 */
6f94b685 6538 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6539 ecommunity, lcommunity)) {
9bcb3eef 6540 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6541
6542 if (aspath)
6543 aspath_free(aspath);
6544 if (community)
3c1f53de 6545 community_free(&community);
3da2cc32
DS
6546 if (ecommunity)
6547 ecommunity_free(&ecommunity);
dd18c5a9
DS
6548 if (lcommunity)
6549 lcommunity_free(&lcommunity);
eaaf8adb
DS
6550
6551 return;
6552 }
6553
6554 /*
6555 * Mark the old as unusable
6556 */
40381db7 6557 if (pi)
9bcb3eef 6558 bgp_path_info_delete(dest, pi);
eaaf8adb 6559
20894f50
DA
6560 attr = bgp_attr_aggregate_intern(
6561 bgp, origin, aspath, community, ecommunity, lcommunity,
6562 aggregate, atomic_aggregate, p);
6563
6564 if (!attr) {
6565 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6566 return;
6567 }
6568
3da2cc32 6569 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6570 bgp->peer_self, attr, dest);
20894f50 6571
1defdda8 6572 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6573
9bcb3eef
DS
6574 bgp_path_info_add(dest, new);
6575 bgp_process(bgp, dest, afi, safi);
c701010e 6576 } else {
6aabb15d 6577 uninstall_aggregate_route:
6f94b685 6578 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6579 if (pi->peer == bgp->peer_self
6580 && pi->type == ZEBRA_ROUTE_BGP
6581 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6582 break;
6583
6584 /* Withdraw static BGP route from routing table. */
40381db7 6585 if (pi) {
9bcb3eef
DS
6586 bgp_path_info_delete(dest, pi);
6587 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6588 }
6589 }
6590
9bcb3eef 6591 bgp_dest_unlock_node(dest);
c701010e
DS
6592}
6593
6aabb15d
RZ
6594/**
6595 * Check if the current path has different MED than other known paths.
6596 *
6597 * \returns `true` if the MED matched the others else `false`.
6598 */
6599static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6600 struct bgp *bgp, struct bgp_path_info *pi)
6601{
6602 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6603
6604 /* This is the first route being analyzed. */
6605 if (!aggregate->med_initialized) {
6606 aggregate->med_initialized = true;
6607 aggregate->med_mismatched = false;
6608 aggregate->med_matched_value = cur_med;
6609 } else {
6610 /* Check if routes with different MED showed up. */
6611 if (cur_med != aggregate->med_matched_value)
6612 aggregate->med_mismatched = true;
6613 }
6614
6615 return !aggregate->med_mismatched;
6616}
6617
6618/**
6619 * Initializes and tests all routes in the aggregate address path for MED
6620 * values.
6621 *
6622 * \returns `true` if all MEDs are the same otherwise `false`.
6623 */
6624static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6625 struct bgp *bgp, const struct prefix *p,
6626 afi_t afi, safi_t safi)
6627{
6628 struct bgp_table *table = bgp->rib[afi][safi];
6629 const struct prefix *dest_p;
6630 struct bgp_dest *dest, *top;
6631 struct bgp_path_info *pi;
6632 bool med_matched = true;
6633
6634 aggregate->med_initialized = false;
6635
6636 top = bgp_node_get(table, p);
6637 for (dest = bgp_node_get(table, p); dest;
6638 dest = bgp_route_next_until(dest, top)) {
6639 dest_p = bgp_dest_get_prefix(dest);
6640 if (dest_p->prefixlen <= p->prefixlen)
6641 continue;
6642
6643 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6644 if (BGP_PATH_HOLDDOWN(pi))
6645 continue;
6646 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6647 continue;
6648 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6649 med_matched = false;
6650 break;
6651 }
6652 }
6653 if (!med_matched)
6654 break;
6655 }
6656 bgp_dest_unlock_node(top);
6657
6658 return med_matched;
6659}
6660
6661/**
6662 * Toggles the route suppression status for this aggregate address
6663 * configuration.
6664 */
4056a5f6
RZ
6665void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6666 struct bgp *bgp, const struct prefix *p,
6667 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6668{
6669 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6670 const struct prefix *dest_p;
6671 struct bgp_dest *dest, *top;
6672 struct bgp_path_info *pi;
6673 bool toggle_suppression;
6674
6675 /* We've found a different MED we must revert any suppressed routes. */
6676 top = bgp_node_get(table, p);
6677 for (dest = bgp_node_get(table, p); dest;
6678 dest = bgp_route_next_until(dest, top)) {
6679 dest_p = bgp_dest_get_prefix(dest);
6680 if (dest_p->prefixlen <= p->prefixlen)
6681 continue;
6682
6683 toggle_suppression = false;
6684 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6685 if (BGP_PATH_HOLDDOWN(pi))
6686 continue;
6687 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6688 continue;
6689
6aabb15d
RZ
6690 /* We are toggling suppression back. */
6691 if (suppress) {
6aabb15d 6692 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6693 if (aggr_suppress_path(aggregate, pi))
6694 toggle_suppression = true;
6aabb15d
RZ
6695 continue;
6696 }
6697
6aabb15d 6698 /* Install route if there is no more suppression. */
4056a5f6 6699 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6700 toggle_suppression = true;
6aabb15d
RZ
6701 }
6702
6703 if (toggle_suppression)
6704 bgp_process(bgp, dest, afi, safi);
6705 }
6706 bgp_dest_unlock_node(top);
6707}
6708
6709/**
6710 * Aggregate address MED matching incremental test: this function is called
6711 * when the initial aggregation occurred and we are only testing a single
6712 * new path.
6713 *
6714 * In addition to testing and setting the MED validity it also installs back
6715 * suppressed routes (if summary is configured).
6716 *
6717 * Must not be called in `bgp_aggregate_route`.
6718 */
6719static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6720 struct bgp *bgp, const struct prefix *p,
6721 afi_t afi, safi_t safi,
6722 struct bgp_path_info *pi, bool is_adding)
6723{
6724 /* MED matching disabled. */
6725 if (!aggregate->match_med)
6726 return;
6727
6728 /* Aggregation with different MED, nothing to do. */
6729 if (aggregate->med_mismatched)
6730 return;
6731
6732 /*
6733 * Test the current entry:
6734 *
6735 * is_adding == true: if the new entry doesn't match then we must
6736 * install all suppressed routes.
6737 *
6738 * is_adding == false: if the entry being removed was the last
6739 * unmatching entry then we can suppress all routes.
6740 */
6741 if (!is_adding) {
6742 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6743 && aggregate->summary_only)
6744 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6745 safi, true);
6746 } else
6747 bgp_aggregate_med_match(aggregate, bgp, pi);
6748
6749 /* No mismatches, just quit. */
6750 if (!aggregate->med_mismatched)
6751 return;
6752
6753 /* Route summarization is disabled. */
6754 if (!aggregate->summary_only)
6755 return;
6756
6757 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6758}
6759
b5d58c32 6760/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6761void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6762 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6763{
6764 struct bgp_table *table;
9bcb3eef
DS
6765 struct bgp_dest *top;
6766 struct bgp_dest *dest;
d7c0a89a 6767 uint8_t origin;
d62a17ae 6768 struct aspath *aspath = NULL;
d62a17ae 6769 struct community *community = NULL;
3da2cc32 6770 struct ecommunity *ecommunity = NULL;
dd18c5a9 6771 struct lcommunity *lcommunity = NULL;
40381db7 6772 struct bgp_path_info *pi;
d62a17ae 6773 unsigned long match = 0;
d7c0a89a 6774 uint8_t atomic_aggregate = 0;
d62a17ae 6775
9f822fa2
S
6776 /* If the bgp instance is being deleted or self peer is deleted
6777 * then do not create aggregate route
6778 */
892fedb6
DA
6779 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6780 || (bgp->peer_self == NULL))
9f822fa2
S
6781 return;
6782
6aabb15d
RZ
6783 /* Initialize and test routes for MED difference. */
6784 if (aggregate->match_med)
6785 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6786
4056a5f6
RZ
6787 /*
6788 * Reset aggregate count: we might've been called from route map
6789 * update so in that case we must retest all more specific routes.
6790 *
6791 * \see `bgp_route_map_process_update`.
6792 */
6793 aggregate->count = 0;
6794 aggregate->incomplete_origin_count = 0;
6795 aggregate->incomplete_origin_count = 0;
6796 aggregate->egp_origin_count = 0;
6797
d62a17ae 6798 /* ORIGIN attribute: If at least one route among routes that are
6799 aggregated has ORIGIN with the value INCOMPLETE, then the
6800 aggregated route must have the ORIGIN attribute with the value
6801 INCOMPLETE. Otherwise, if at least one route among routes that
6802 are aggregated has ORIGIN with the value EGP, then the aggregated
6803 route must have the origin attribute with the value EGP. In all
6804 other case the value of the ORIGIN attribute of the aggregated
6805 route is INTERNAL. */
6806 origin = BGP_ORIGIN_IGP;
718e3744 6807
d62a17ae 6808 table = bgp->rib[afi][safi];
718e3744 6809
d62a17ae 6810 top = bgp_node_get(table, p);
9bcb3eef
DS
6811 for (dest = bgp_node_get(table, p); dest;
6812 dest = bgp_route_next_until(dest, top)) {
6813 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6814
9bcb3eef 6815 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6816 continue;
d62a17ae 6817
a77e2f4b
S
6818 /* If suppress fib is enabled and route not installed
6819 * in FIB, skip the route
6820 */
6821 if (!bgp_check_advertise(bgp, dest))
6822 continue;
6823
c2ff8b3e 6824 match = 0;
d62a17ae 6825
9bcb3eef 6826 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6827 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6828 continue;
718e3744 6829
40381db7 6830 if (pi->attr->flag
c2ff8b3e
DS
6831 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6832 atomic_aggregate = 1;
d62a17ae 6833
40381db7 6834 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6835 continue;
d62a17ae 6836
f273fef1
DS
6837 /*
6838 * summary-only aggregate route suppress
6839 * aggregated route announcements.
6aabb15d
RZ
6840 *
6841 * MED matching:
6842 * Don't create summaries if MED didn't match
6843 * otherwise neither the specific routes and the
6844 * aggregation will be announced.
f273fef1 6845 */
6aabb15d
RZ
6846 if (aggregate->summary_only
6847 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6848 if (aggr_suppress_path(aggregate, pi))
6849 match++;
d62a17ae 6850 }
c2ff8b3e 6851
365ab2e7
RZ
6852 /*
6853 * Suppress more specific routes that match the route
6854 * map results.
6855 *
6856 * MED matching:
6857 * Don't suppress routes if MED matching is enabled and
6858 * it mismatched otherwise we might end up with no
6859 * routes for this path.
6860 */
6861 if (aggregate->suppress_map_name
6862 && AGGREGATE_MED_VALID(aggregate)
6863 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
6864 if (aggr_suppress_path(aggregate, pi))
6865 match++;
d62a17ae 6866 }
c2ff8b3e
DS
6867
6868 aggregate->count++;
6869
f273fef1
DS
6870 /*
6871 * If at least one route among routes that are
6872 * aggregated has ORIGIN with the value INCOMPLETE,
6873 * then the aggregated route MUST have the ORIGIN
6874 * attribute with the value INCOMPLETE. Otherwise, if
6875 * at least one route among routes that are aggregated
6876 * has ORIGIN with the value EGP, then the aggregated
6877 * route MUST have the ORIGIN attribute with the value
6878 * EGP.
6879 */
fc968841
NT
6880 switch (pi->attr->origin) {
6881 case BGP_ORIGIN_INCOMPLETE:
6882 aggregate->incomplete_origin_count++;
6883 break;
6884 case BGP_ORIGIN_EGP:
6885 aggregate->egp_origin_count++;
6886 break;
6887 default:
6888 /*Do nothing.
6889 */
6890 break;
6891 }
c2ff8b3e
DS
6892
6893 if (!aggregate->as_set)
6894 continue;
6895
f273fef1
DS
6896 /*
6897 * as-set aggregate route generate origin, as path,
6898 * and community aggregation.
6899 */
fc968841
NT
6900 /* Compute aggregate route's as-path.
6901 */
ef51a7d8 6902 bgp_compute_aggregate_aspath_hash(aggregate,
6903 pi->attr->aspath);
c2ff8b3e 6904
fc968841
NT
6905 /* Compute aggregate route's community.
6906 */
6907 if (pi->attr->community)
21fec674 6908 bgp_compute_aggregate_community_hash(
fc968841
NT
6909 aggregate,
6910 pi->attr->community);
dd18c5a9 6911
fc968841
NT
6912 /* Compute aggregate route's extended community.
6913 */
6914 if (pi->attr->ecommunity)
4edd83f9 6915 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6916 aggregate,
6917 pi->attr->ecommunity);
6918
6919 /* Compute aggregate route's large community.
6920 */
6921 if (pi->attr->lcommunity)
f1eb1f05 6922 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6923 aggregate,
6924 pi->attr->lcommunity);
d62a17ae 6925 }
c2ff8b3e 6926 if (match)
9bcb3eef 6927 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6928 }
21fec674 6929 if (aggregate->as_set) {
ef51a7d8 6930 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6931 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6932 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6933 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6934 }
6935
f1eb1f05 6936
9bcb3eef 6937 bgp_dest_unlock_node(top);
718e3744 6938
718e3744 6939
fc968841
NT
6940 if (aggregate->incomplete_origin_count > 0)
6941 origin = BGP_ORIGIN_INCOMPLETE;
6942 else if (aggregate->egp_origin_count > 0)
6943 origin = BGP_ORIGIN_EGP;
d62a17ae 6944
229757f1
DA
6945 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6946 origin = aggregate->origin;
6947
fc968841
NT
6948 if (aggregate->as_set) {
6949 if (aggregate->aspath)
6950 /* Retrieve aggregate route's as-path.
6951 */
6952 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6953
fc968841
NT
6954 if (aggregate->community)
6955 /* Retrieve aggregate route's community.
6956 */
6957 community = community_dup(aggregate->community);
3da2cc32 6958
fc968841
NT
6959 if (aggregate->ecommunity)
6960 /* Retrieve aggregate route's ecommunity.
6961 */
6962 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6963
fc968841
NT
6964 if (aggregate->lcommunity)
6965 /* Retrieve aggregate route's lcommunity.
6966 */
6967 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6968 }
718e3744 6969
c701010e 6970 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6971 ecommunity, lcommunity, atomic_aggregate,
6972 aggregate);
718e3744 6973}
6974
5f040085
DS
6975void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6976 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6977{
6978 struct bgp_table *table;
9bcb3eef
DS
6979 struct bgp_dest *top;
6980 struct bgp_dest *dest;
40381db7 6981 struct bgp_path_info *pi;
3b7db173
DS
6982 unsigned long match;
6983
6984 table = bgp->rib[afi][safi];
6985
6986 /* If routes exists below this node, generate aggregate routes. */
6987 top = bgp_node_get(table, p);
9bcb3eef
DS
6988 for (dest = bgp_node_get(table, p); dest;
6989 dest = bgp_route_next_until(dest, top)) {
6990 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6991
9bcb3eef 6992 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
6993 continue;
6994 match = 0;
6995
9bcb3eef 6996 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6997 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6998 continue;
6999
40381db7 7000 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7001 continue;
7002
6aabb15d
RZ
7003 if (aggregate->summary_only && pi->extra
7004 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7005 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7006 match++;
3b7db173 7007 }
3b7db173 7008
365ab2e7
RZ
7009 if (aggregate->suppress_map_name
7010 && AGGREGATE_MED_VALID(aggregate)
7011 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7012 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7013 match++;
3b7db173 7014 }
365ab2e7 7015
3b7db173 7016 aggregate->count--;
fc968841
NT
7017
7018 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7019 aggregate->incomplete_origin_count--;
7020 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7021 aggregate->egp_origin_count--;
7022
7023 if (aggregate->as_set) {
7024 /* Remove as-path from aggregate.
7025 */
ef51a7d8 7026 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7027 aggregate,
7028 pi->attr->aspath);
7029
7030 if (pi->attr->community)
7031 /* Remove community from aggregate.
7032 */
21fec674 7033 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7034 aggregate,
7035 pi->attr->community);
7036
7037 if (pi->attr->ecommunity)
7038 /* Remove ecommunity from aggregate.
7039 */
4edd83f9 7040 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7041 aggregate,
7042 pi->attr->ecommunity);
7043
7044 if (pi->attr->lcommunity)
7045 /* Remove lcommunity from aggregate.
7046 */
f1eb1f05 7047 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7048 aggregate,
7049 pi->attr->lcommunity);
7050 }
3b7db173
DS
7051 }
7052
7053 /* If this node was suppressed, process the change. */
7054 if (match)
9bcb3eef 7055 bgp_process(bgp, dest, afi, safi);
3b7db173 7056 }
f1eb1f05 7057 if (aggregate->as_set) {
ef51a7d8 7058 aspath_free(aggregate->aspath);
7059 aggregate->aspath = NULL;
21fec674 7060 if (aggregate->community)
7061 community_free(&aggregate->community);
4edd83f9 7062 if (aggregate->ecommunity)
7063 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7064 if (aggregate->lcommunity)
7065 lcommunity_free(&aggregate->lcommunity);
7066 }
7067
9bcb3eef 7068 bgp_dest_unlock_node(top);
3b7db173 7069}
718e3744 7070
5f040085
DS
7071static void bgp_add_route_to_aggregate(struct bgp *bgp,
7072 const struct prefix *aggr_p,
fc968841
NT
7073 struct bgp_path_info *pinew, afi_t afi,
7074 safi_t safi,
7075 struct bgp_aggregate *aggregate)
7076{
7077 uint8_t origin;
7078 struct aspath *aspath = NULL;
7079 uint8_t atomic_aggregate = 0;
7080 struct community *community = NULL;
7081 struct ecommunity *ecommunity = NULL;
7082 struct lcommunity *lcommunity = NULL;
7083
7084 /* ORIGIN attribute: If at least one route among routes that are
7085 * aggregated has ORIGIN with the value INCOMPLETE, then the
7086 * aggregated route must have the ORIGIN attribute with the value
7087 * INCOMPLETE. Otherwise, if at least one route among routes that
7088 * are aggregated has ORIGIN with the value EGP, then the aggregated
7089 * route must have the origin attribute with the value EGP. In all
7090 * other case the value of the ORIGIN attribute of the aggregated
7091 * route is INTERNAL.
7092 */
7093 origin = BGP_ORIGIN_IGP;
7094
7095 aggregate->count++;
7096
6aabb15d
RZ
7097 /*
7098 * This must be called before `summary` check to avoid
7099 * "suppressing" twice.
7100 */
7101 if (aggregate->match_med)
7102 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7103 pinew, true);
7104
7105 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7106 aggr_suppress_path(aggregate, pinew);
fc968841 7107
365ab2e7
RZ
7108 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7109 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7110 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7111
7112 switch (pinew->attr->origin) {
7113 case BGP_ORIGIN_INCOMPLETE:
7114 aggregate->incomplete_origin_count++;
7115 break;
7116 case BGP_ORIGIN_EGP:
7117 aggregate->egp_origin_count++;
7118 break;
7119 default:
7120 /* Do nothing.
7121 */
7122 break;
7123 }
7124
7125 if (aggregate->incomplete_origin_count > 0)
7126 origin = BGP_ORIGIN_INCOMPLETE;
7127 else if (aggregate->egp_origin_count > 0)
7128 origin = BGP_ORIGIN_EGP;
7129
229757f1
DA
7130 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7131 origin = aggregate->origin;
7132
fc968841
NT
7133 if (aggregate->as_set) {
7134 /* Compute aggregate route's as-path.
7135 */
7136 bgp_compute_aggregate_aspath(aggregate,
7137 pinew->attr->aspath);
7138
7139 /* Compute aggregate route's community.
7140 */
7141 if (pinew->attr->community)
7142 bgp_compute_aggregate_community(
7143 aggregate,
7144 pinew->attr->community);
7145
7146 /* Compute aggregate route's extended community.
7147 */
7148 if (pinew->attr->ecommunity)
7149 bgp_compute_aggregate_ecommunity(
7150 aggregate,
7151 pinew->attr->ecommunity);
7152
7153 /* Compute aggregate route's large community.
7154 */
7155 if (pinew->attr->lcommunity)
7156 bgp_compute_aggregate_lcommunity(
7157 aggregate,
7158 pinew->attr->lcommunity);
7159
7160 /* Retrieve aggregate route's as-path.
7161 */
7162 if (aggregate->aspath)
7163 aspath = aspath_dup(aggregate->aspath);
7164
7165 /* Retrieve aggregate route's community.
7166 */
7167 if (aggregate->community)
7168 community = community_dup(aggregate->community);
7169
7170 /* Retrieve aggregate route's ecommunity.
7171 */
7172 if (aggregate->ecommunity)
7173 ecommunity = ecommunity_dup(aggregate->ecommunity);
7174
7175 /* Retrieve aggregate route's lcommunity.
7176 */
7177 if (aggregate->lcommunity)
7178 lcommunity = lcommunity_dup(aggregate->lcommunity);
7179 }
7180
7181 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7182 aspath, community, ecommunity,
7183 lcommunity, atomic_aggregate, aggregate);
7184}
7185
7186static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7187 safi_t safi,
7188 struct bgp_path_info *pi,
7189 struct bgp_aggregate *aggregate,
5f040085 7190 const struct prefix *aggr_p)
fc968841
NT
7191{
7192 uint8_t origin;
7193 struct aspath *aspath = NULL;
7194 uint8_t atomic_aggregate = 0;
7195 struct community *community = NULL;
7196 struct ecommunity *ecommunity = NULL;
7197 struct lcommunity *lcommunity = NULL;
7198 unsigned long match = 0;
7199
7200 if (BGP_PATH_HOLDDOWN(pi))
7201 return;
7202
7203 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7204 return;
7205
4056a5f6
RZ
7206 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7207 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7208 match++;
fc968841 7209
365ab2e7 7210 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7211 && aggr_suppress_map_test(bgp, aggregate, pi))
7212 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7213 match++;
fc968841 7214
6aabb15d 7215 /*
365ab2e7 7216 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7217 * "unsuppressing" twice.
7218 */
7219 if (aggregate->match_med)
7220 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7221 true);
7222
fc968841
NT
7223 if (aggregate->count > 0)
7224 aggregate->count--;
7225
7226 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7227 aggregate->incomplete_origin_count--;
7228 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7229 aggregate->egp_origin_count--;
7230
7231 if (aggregate->as_set) {
7232 /* Remove as-path from aggregate.
7233 */
7234 bgp_remove_aspath_from_aggregate(aggregate,
7235 pi->attr->aspath);
7236
7237 if (pi->attr->community)
7238 /* Remove community from aggregate.
7239 */
7240 bgp_remove_community_from_aggregate(
7241 aggregate,
7242 pi->attr->community);
7243
7244 if (pi->attr->ecommunity)
7245 /* Remove ecommunity from aggregate.
7246 */
7247 bgp_remove_ecommunity_from_aggregate(
7248 aggregate,
7249 pi->attr->ecommunity);
7250
7251 if (pi->attr->lcommunity)
7252 /* Remove lcommunity from aggregate.
7253 */
7254 bgp_remove_lcommunity_from_aggregate(
7255 aggregate,
7256 pi->attr->lcommunity);
7257 }
7258
7259 /* If this node was suppressed, process the change. */
7260 if (match)
7261 bgp_process(bgp, pi->net, afi, safi);
7262
7263 origin = BGP_ORIGIN_IGP;
7264 if (aggregate->incomplete_origin_count > 0)
7265 origin = BGP_ORIGIN_INCOMPLETE;
7266 else if (aggregate->egp_origin_count > 0)
7267 origin = BGP_ORIGIN_EGP;
7268
229757f1
DA
7269 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7270 origin = aggregate->origin;
7271
fc968841
NT
7272 if (aggregate->as_set) {
7273 /* Retrieve aggregate route's as-path.
7274 */
7275 if (aggregate->aspath)
7276 aspath = aspath_dup(aggregate->aspath);
7277
7278 /* Retrieve aggregate route's community.
7279 */
7280 if (aggregate->community)
7281 community = community_dup(aggregate->community);
7282
7283 /* Retrieve aggregate route's ecommunity.
7284 */
7285 if (aggregate->ecommunity)
7286 ecommunity = ecommunity_dup(aggregate->ecommunity);
7287
7288 /* Retrieve aggregate route's lcommunity.
7289 */
7290 if (aggregate->lcommunity)
7291 lcommunity = lcommunity_dup(aggregate->lcommunity);
7292 }
7293
7294 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7295 aspath, community, ecommunity,
7296 lcommunity, atomic_aggregate, aggregate);
7297}
7298
5a1ae2c2 7299void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7300 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7301{
9bcb3eef
DS
7302 struct bgp_dest *child;
7303 struct bgp_dest *dest;
d62a17ae 7304 struct bgp_aggregate *aggregate;
7305 struct bgp_table *table;
718e3744 7306
d62a17ae 7307 table = bgp->aggregate[afi][safi];
f018db83 7308
d62a17ae 7309 /* No aggregates configured. */
7310 if (bgp_table_top_nolock(table) == NULL)
7311 return;
f018db83 7312
d62a17ae 7313 if (p->prefixlen == 0)
7314 return;
718e3744 7315
40381db7 7316 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7317 return;
718e3744 7318
a77e2f4b
S
7319 /* If suppress fib is enabled and route not installed
7320 * in FIB, do not update the aggregate route
7321 */
7322 if (!bgp_check_advertise(bgp, pi->net))
7323 return;
7324
d62a17ae 7325 child = bgp_node_get(table, p);
718e3744 7326
d62a17ae 7327 /* Aggregate address configuration check. */
9bcb3eef
DS
7328 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7329 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7330
9bcb3eef
DS
7331 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7332 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7333 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7334 aggregate);
d62a17ae 7335 }
b1e62edd 7336 }
9bcb3eef 7337 bgp_dest_unlock_node(child);
718e3744 7338}
7339
5a1ae2c2 7340void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7341 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7342{
9bcb3eef
DS
7343 struct bgp_dest *child;
7344 struct bgp_dest *dest;
d62a17ae 7345 struct bgp_aggregate *aggregate;
7346 struct bgp_table *table;
718e3744 7347
d62a17ae 7348 table = bgp->aggregate[afi][safi];
718e3744 7349
d62a17ae 7350 /* No aggregates configured. */
7351 if (bgp_table_top_nolock(table) == NULL)
7352 return;
718e3744 7353
d62a17ae 7354 if (p->prefixlen == 0)
7355 return;
718e3744 7356
d62a17ae 7357 child = bgp_node_get(table, p);
718e3744 7358
d62a17ae 7359 /* Aggregate address configuration check. */
9bcb3eef
DS
7360 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7361 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7362
9bcb3eef
DS
7363 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7364 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7365 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7366 aggregate, dest_p);
d62a17ae 7367 }
b1e62edd 7368 }
9bcb3eef 7369 bgp_dest_unlock_node(child);
d62a17ae 7370}
718e3744 7371
718e3744 7372/* Aggregate route attribute. */
7373#define AGGREGATE_SUMMARY_ONLY 1
7374#define AGGREGATE_AS_SET 1
fb29348a 7375#define AGGREGATE_AS_UNSET 0
718e3744 7376
229757f1
DA
7377static const char *bgp_origin2str(uint8_t origin)
7378{
7379 switch (origin) {
7380 case BGP_ORIGIN_IGP:
7381 return "igp";
7382 case BGP_ORIGIN_EGP:
7383 return "egp";
7384 case BGP_ORIGIN_INCOMPLETE:
7385 return "incomplete";
7386 }
7387 return "n/a";
7388}
7389
37a87b8f
CS
7390int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7391 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7392{
9bcb3eef 7393 struct bgp_dest *dest;
d62a17ae 7394 struct bgp_aggregate *aggregate;
718e3744 7395
37a87b8f 7396 apply_mask(prefix);
d62a17ae 7397 /* Old configuration check. */
37a87b8f 7398 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7399 if (!dest) {
37a87b8f
CS
7400 snprintf(errmsg, errmsg_len,
7401 "There is no aggregate-address configuration.\n");
7402 return -1;
d62a17ae 7403 }
f6269b4f 7404
9bcb3eef 7405 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7406 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7407 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7408 0, aggregate);
d62a17ae 7409
7410 /* Unlock aggregate address configuration. */
9bcb3eef 7411 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7412
7413 if (aggregate->community)
7414 community_free(&aggregate->community);
7415
7416 if (aggregate->community_hash) {
7417 /* Delete all communities in the hash.
7418 */
7419 hash_clean(aggregate->community_hash,
7420 bgp_aggr_community_remove);
7421 /* Free up the community_hash.
7422 */
7423 hash_free(aggregate->community_hash);
7424 }
7425
7426 if (aggregate->ecommunity)
7427 ecommunity_free(&aggregate->ecommunity);
7428
7429 if (aggregate->ecommunity_hash) {
7430 /* Delete all ecommunities in the hash.
7431 */
7432 hash_clean(aggregate->ecommunity_hash,
7433 bgp_aggr_ecommunity_remove);
7434 /* Free up the ecommunity_hash.
7435 */
7436 hash_free(aggregate->ecommunity_hash);
7437 }
7438
7439 if (aggregate->lcommunity)
7440 lcommunity_free(&aggregate->lcommunity);
7441
7442 if (aggregate->lcommunity_hash) {
7443 /* Delete all lcommunities in the hash.
7444 */
7445 hash_clean(aggregate->lcommunity_hash,
7446 bgp_aggr_lcommunity_remove);
7447 /* Free up the lcommunity_hash.
7448 */
7449 hash_free(aggregate->lcommunity_hash);
7450 }
7451
7452 if (aggregate->aspath)
7453 aspath_free(aggregate->aspath);
7454
7455 if (aggregate->aspath_hash) {
7456 /* Delete all as-paths in the hash.
7457 */
7458 hash_clean(aggregate->aspath_hash,
7459 bgp_aggr_aspath_remove);
7460 /* Free up the aspath_hash.
7461 */
7462 hash_free(aggregate->aspath_hash);
7463 }
7464
d62a17ae 7465 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7466 bgp_dest_unlock_node(dest);
7467 bgp_dest_unlock_node(dest);
d62a17ae 7468
37a87b8f 7469 return 0;
d62a17ae 7470}
7471
37a87b8f
CS
7472int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7473 safi_t safi, const char *rmap, uint8_t summary_only,
7474 uint8_t as_set, uint8_t origin, bool match_med,
7475 const char *suppress_map,
7476 char *errmsg, size_t errmsg_len)
d62a17ae 7477{
d62a17ae 7478 int ret;
9bcb3eef 7479 struct bgp_dest *dest;
d62a17ae 7480 struct bgp_aggregate *aggregate;
fb29348a 7481 uint8_t as_set_new = as_set;
37a87b8f 7482 char buf[PREFIX2STR_BUFFER];
d62a17ae 7483
365ab2e7 7484 if (suppress_map && summary_only) {
37a87b8f 7485 snprintf(errmsg, errmsg_len,
365ab2e7 7486 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7487 return -1;
365ab2e7
RZ
7488 }
7489
37a87b8f 7490 apply_mask(prefix);
d62a17ae 7491
37a87b8f
CS
7492 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7493 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7494 snprintf(
7495 errmsg, errmsg_len,
7496 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7497 prefix2str(prefix, buf, PREFIX_STRLEN));
7498 return -1;
3624ac81
DS
7499 }
7500
d62a17ae 7501 /* Old configuration check. */
37a87b8f 7502 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7503 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7504
20894f50 7505 if (aggregate) {
37a87b8f
CS
7506 snprintf(errmsg, errmsg_len,
7507 "There is already same aggregate network.\n");
d62a17ae 7508 /* try to remove the old entry */
37a87b8f
CS
7509 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7510 errmsg_len);
d62a17ae 7511 if (ret) {
37a87b8f
CS
7512 snprintf(errmsg, errmsg_len,
7513 "Error deleting aggregate.\n");
9bcb3eef 7514 bgp_dest_unlock_node(dest);
37a87b8f 7515 return -1;
d62a17ae 7516 }
7517 }
718e3744 7518
d62a17ae 7519 /* Make aggregate address structure. */
7520 aggregate = bgp_aggregate_new();
7521 aggregate->summary_only = summary_only;
6aabb15d 7522 aggregate->match_med = match_med;
fb29348a
DA
7523
7524 /* Network operators MUST NOT locally generate any new
7525 * announcements containing AS_SET or AS_CONFED_SET. If they have
7526 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7527 * SHOULD withdraw those routes and re-announce routes for the
7528 * aggregate or component prefixes (i.e., the more-specific routes
7529 * subsumed by the previously aggregated route) without AS_SET
7530 * or AS_CONFED_SET in the updates.
7531 */
7f972cd8 7532 if (bgp->reject_as_sets) {
fb29348a
DA
7533 if (as_set == AGGREGATE_AS_SET) {
7534 as_set_new = AGGREGATE_AS_UNSET;
7535 zlog_warn(
63efca0e 7536 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7537 __func__);
37a87b8f
CS
7538 snprintf(
7539 errmsg, errmsg_len,
fb29348a
DA
7540 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7541 }
7542 }
7543
7544 aggregate->as_set = as_set_new;
d62a17ae 7545 aggregate->safi = safi;
229757f1
DA
7546 /* Override ORIGIN attribute if defined.
7547 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7548 * to IGP which is not what rfc4271 says.
7549 * This enables the same behavior, optionally.
7550 */
7551 aggregate->origin = origin;
20894f50
DA
7552
7553 if (rmap) {
7554 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7555 route_map_counter_decrement(aggregate->rmap.map);
7556 aggregate->rmap.name =
7557 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7558 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7559 route_map_counter_increment(aggregate->rmap.map);
7560 }
365ab2e7
RZ
7561
7562 if (suppress_map) {
7563 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7564 route_map_counter_decrement(aggregate->suppress_map);
7565
7566 aggregate->suppress_map_name =
7567 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7568 aggregate->suppress_map =
7569 route_map_lookup_by_name(aggregate->suppress_map_name);
7570 route_map_counter_increment(aggregate->suppress_map);
7571 }
7572
9bcb3eef 7573 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7574
d62a17ae 7575 /* Aggregate address insert into BGP routing table. */
37a87b8f 7576 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7577
37a87b8f 7578 return 0;
718e3744 7579}
7580
37a87b8f
CS
7581DEFPY_YANG(
7582 aggregate_addressv4, aggregate_addressv4_cmd,
7583 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7584 "as-set$as_set_s"
7585 "|summary-only$summary_only"
7586 "|route-map WORD$rmap_name"
7587 "|origin <egp|igp|incomplete>$origin_s"
7588 "|matching-MED-only$match_med"
90e21f35 7589 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7590 "}",
7591 NO_STR
7592 "Configure BGP aggregate entries\n"
7593 "Aggregate prefix\n"
7594 "Aggregate address\n"
7595 "Aggregate mask\n"
7596 "Generate AS set path information\n"
7597 "Filter more specific routes from updates\n"
7598 "Apply route map to aggregate network\n"
7599 "Route map name\n"
7600 "BGP origin code\n"
7601 "Remote EGP\n"
7602 "Local IGP\n"
7603 "Unknown heritage\n"
7604 "Only aggregate routes with matching MED\n"
90e21f35
CS
7605 "Suppress the selected more specific routes\n"
7606 "Route map with the route selectors\n")
37a87b8f
CS
7607{
7608 char base_xpath[XPATH_MAXLEN];
554b3b10 7609 safi_t safi = bgp_node_safi(vty);
554b3b10 7610 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7611
554b3b10
RZ
7612 if (addr_str) {
7613 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7614 == 0) {
7615 vty_out(vty, "%% Inconsistent address and mask\n");
7616 return CMD_WARNING_CONFIG_FAILED;
7617 }
37a87b8f
CS
7618 } else {
7619 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7620 }
7621
37a87b8f
CS
7622 if (!no && origin_s)
7623 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7624
7625 if (!no && as_set_s)
7626 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7627 else
7628 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7629
7630 if (!no && summary_only)
7631 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7632 "true");
7633 else
7634 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7635 "false");
7636
fa423774
CS
7637 if (!no && match_med)
7638 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7639 else
7640 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7641 "false");
7642
37a87b8f
CS
7643 if (rmap_name)
7644 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7645 rmap_name);
7646 else
7647 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7648 NB_OP_DESTROY, NULL);
7649
90e21f35
CS
7650 if (suppress_map)
7651 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7652 suppress_map);
7653 else
7654 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7655 NULL);
7656
37a87b8f
CS
7657 snprintf(
7658 base_xpath, sizeof(base_xpath),
7659 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7660 yang_afi_safi_value2identity(AFI_IP, safi),
7661 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7662
554b3b10 7663 if (no)
37a87b8f
CS
7664 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7665 else
7666 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7667
7668 return nb_cli_apply_changes(vty, base_xpath);
7669}
7670
7671DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7672 "[no] aggregate-address X:X::X:X/M$prefix {"
7673 "as-set$as_set_s"
7674 "|summary-only$summary_only"
7675 "|route-map WORD$rmap_name"
7676 "|origin <egp|igp|incomplete>$origin_s"
7677 "|matching-MED-only$match_med"
90e21f35 7678 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7679 "}",
7680 NO_STR
7681 "Configure BGP aggregate entries\n"
7682 "Aggregate prefix\n"
7683 "Generate AS set path information\n"
7684 "Filter more specific routes from updates\n"
7685 "Apply route map to aggregate network\n"
7686 "Route map name\n"
7687 "BGP origin code\n"
7688 "Remote EGP\n"
7689 "Local IGP\n"
7690 "Unknown heritage\n"
7691 "Only aggregate routes with matching MED\n"
7692 "Suppress the selected more specific routes\n"
90e21f35 7693 "Route map with the route selectors\n")
37a87b8f
CS
7694{
7695 char base_xpath[XPATH_MAXLEN];
7696 safi_t safi = bgp_node_safi(vty);
7697
7698 if (!no && origin_s)
7699 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7700
7701 if (!no && as_set_s)
7702 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7703 else
7704 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7705
7706 if (!no && summary_only)
7707 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7708 "true");
7709 else
7710 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7711 "false");
7712
fa423774
CS
7713 if (!no && match_med)
7714 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7715 else
7716 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7717 "false");
7718
37a87b8f
CS
7719 if (rmap_name)
7720 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7721 rmap_name);
7722
90e21f35
CS
7723 if (suppress_map)
7724 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7725 suppress_map);
7726 else
7727 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7728 NULL);
7729
37a87b8f
CS
7730 snprintf(
7731 base_xpath, sizeof(base_xpath),
7732 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7733 yang_afi_safi_value2identity(AFI_IP6, safi),
7734 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7735
554b3b10 7736 if (no)
37a87b8f
CS
7737 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7738 else
7739 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7740
37a87b8f
CS
7741 return nb_cli_apply_changes(vty, base_xpath);
7742}
7743
7744void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7745 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7746{
7747 uint8_t origin;
7748
7749 vty_out(vty, " aggregate-address %s",
7750 yang_dnode_get_string(dnode, "./prefix"));
7751
7752 if (yang_dnode_get_bool(dnode, "./as-set"))
7753 vty_out(vty, " as-set");
7754
7755 if (yang_dnode_get_bool(dnode, "./summary-only"))
7756 vty_out(vty, " summary-only");
7757
7758 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7759 vty_out(vty, " route-map %s",
7760 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7761
7762 origin = yang_dnode_get_enum(dnode, "./origin");
7763 if (origin != BGP_ORIGIN_UNSPECIFIED)
7764 vty_out(vty, " origin %s", bgp_origin2str(origin));
7765
fa423774
CS
7766 if (yang_dnode_get_bool(dnode, "./match-med"))
7767 vty_out(vty, " matching-MED-only");
7768
37a87b8f 7769 vty_out(vty, "\n");
718e3744 7770}
7771
718e3744 7772/* Redistribute route treatment. */
d62a17ae 7773void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7774 const union g_addr *nexthop, ifindex_t ifindex,
7775 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7776 uint8_t type, unsigned short instance,
7777 route_tag_t tag)
d62a17ae 7778{
4b7e6066 7779 struct bgp_path_info *new;
40381db7
DS
7780 struct bgp_path_info *bpi;
7781 struct bgp_path_info rmap_path;
9bcb3eef 7782 struct bgp_dest *bn;
d62a17ae 7783 struct attr attr;
7784 struct attr *new_attr;
7785 afi_t afi;
b68885f9 7786 route_map_result_t ret;
d62a17ae 7787 struct bgp_redist *red;
7788
7789 /* Make default attribute. */
7790 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7791 /*
7792 * This must not be NULL to satisfy Coverity SA
7793 */
7794 assert(attr.aspath);
9de1f7ff 7795
a4d82a8a 7796 switch (nhtype) {
9de1f7ff
DS
7797 case NEXTHOP_TYPE_IFINDEX:
7798 break;
7799 case NEXTHOP_TYPE_IPV4:
7800 case NEXTHOP_TYPE_IPV4_IFINDEX:
7801 attr.nexthop = nexthop->ipv4;
7802 break;
7803 case NEXTHOP_TYPE_IPV6:
7804 case NEXTHOP_TYPE_IPV6_IFINDEX:
7805 attr.mp_nexthop_global = nexthop->ipv6;
7806 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7807 break;
7808 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7809 switch (p->family) {
7810 case AF_INET:
9de1f7ff 7811 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7812 break;
7813 case AF_INET6:
9de1f7ff
DS
7814 memset(&attr.mp_nexthop_global, 0,
7815 sizeof(attr.mp_nexthop_global));
74489921 7816 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7817 break;
74489921 7818 }
9de1f7ff 7819 break;
d62a17ae 7820 }
74489921 7821 attr.nh_ifindex = ifindex;
f04a80a5 7822
d62a17ae 7823 attr.med = metric;
7824 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7825 attr.tag = tag;
718e3744 7826
d62a17ae 7827 afi = family2afi(p->family);
6aeb9e78 7828
d62a17ae 7829 red = bgp_redist_lookup(bgp, afi, type, instance);
7830 if (red) {
7831 struct attr attr_new;
718e3744 7832
d62a17ae 7833 /* Copy attribute for modification. */
6f4f49b2 7834 attr_new = attr;
718e3744 7835
d62a17ae 7836 if (red->redist_metric_flag)
7837 attr_new.med = red->redist_metric;
718e3744 7838
d62a17ae 7839 /* Apply route-map. */
7840 if (red->rmap.name) {
40381db7
DS
7841 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7842 rmap_path.peer = bgp->peer_self;
7843 rmap_path.attr = &attr_new;
718e3744 7844
d62a17ae 7845 SET_FLAG(bgp->peer_self->rmap_type,
7846 PEER_RMAP_TYPE_REDISTRIBUTE);
7847
7848 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7849 &rmap_path);
d62a17ae 7850
7851 bgp->peer_self->rmap_type = 0;
7852
7853 if (ret == RMAP_DENYMATCH) {
7854 /* Free uninterned attribute. */
7855 bgp_attr_flush(&attr_new);
7856
7857 /* Unintern original. */
7858 aspath_unintern(&attr.aspath);
7859 bgp_redistribute_delete(bgp, p, type, instance);
7860 return;
7861 }
7862 }
7863
637e5ba4 7864 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
7865 bgp_attr_add_gshut_community(&attr_new);
7866
d62a17ae 7867 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7868 SAFI_UNICAST, p, NULL);
7869
7870 new_attr = bgp_attr_intern(&attr_new);
7871
9bcb3eef 7872 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7873 if (bpi->peer == bgp->peer_self
7874 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7875 break;
7876
40381db7 7877 if (bpi) {
d62a17ae 7878 /* Ensure the (source route) type is updated. */
40381db7
DS
7879 bpi->type = type;
7880 if (attrhash_cmp(bpi->attr, new_attr)
7881 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7882 bgp_attr_unintern(&new_attr);
7883 aspath_unintern(&attr.aspath);
9bcb3eef 7884 bgp_dest_unlock_node(bn);
d62a17ae 7885 return;
7886 } else {
7887 /* The attribute is changed. */
40381db7 7888 bgp_path_info_set_flag(bn, bpi,
18ee8310 7889 BGP_PATH_ATTR_CHANGED);
d62a17ae 7890
7891 /* Rewrite BGP route information. */
40381db7
DS
7892 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7893 bgp_path_info_restore(bn, bpi);
d62a17ae 7894 else
40381db7
DS
7895 bgp_aggregate_decrement(
7896 bgp, p, bpi, afi, SAFI_UNICAST);
7897 bgp_attr_unintern(&bpi->attr);
7898 bpi->attr = new_attr;
7899 bpi->uptime = bgp_clock();
d62a17ae 7900
7901 /* Process change. */
40381db7 7902 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7903 SAFI_UNICAST);
7904 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7905 bgp_dest_unlock_node(bn);
d62a17ae 7906 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7907
7908 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7909 || (bgp->inst_type
7910 == BGP_INSTANCE_TYPE_DEFAULT)) {
7911
7912 vpn_leak_from_vrf_update(
40381db7 7913 bgp_get_default(), bgp, bpi);
ddb5b488 7914 }
d62a17ae 7915 return;
7916 }
7917 }
7918
7919 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7920 bgp->peer_self, new_attr, bn);
1defdda8 7921 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7922
7923 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7924 bgp_path_info_add(bn, new);
9bcb3eef 7925 bgp_dest_unlock_node(bn);
d62a17ae 7926 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7927
7928 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7929 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7930
7931 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7932 }
d62a17ae 7933 }
7934
7935 /* Unintern original. */
7936 aspath_unintern(&attr.aspath);
718e3744 7937}
7938
d7c0a89a
QY
7939void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7940 unsigned short instance)
718e3744 7941{
d62a17ae 7942 afi_t afi;
9bcb3eef 7943 struct bgp_dest *dest;
40381db7 7944 struct bgp_path_info *pi;
d62a17ae 7945 struct bgp_redist *red;
718e3744 7946
d62a17ae 7947 afi = family2afi(p->family);
718e3744 7948
d62a17ae 7949 red = bgp_redist_lookup(bgp, afi, type, instance);
7950 if (red) {
9bcb3eef
DS
7951 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7952 SAFI_UNICAST, p, NULL);
d62a17ae 7953
9bcb3eef 7954 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7955 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7956 break;
7957
40381db7 7958 if (pi) {
ddb5b488
PZ
7959 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7960 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7961
7962 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7963 bgp, pi);
ddb5b488 7964 }
40381db7 7965 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7966 bgp_path_info_delete(dest, pi);
7967 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7968 }
9bcb3eef 7969 bgp_dest_unlock_node(dest);
d62a17ae 7970 }
7971}
7972
7973/* Withdraw specified route type's route. */
7974void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7975 unsigned short instance)
d62a17ae 7976{
9bcb3eef 7977 struct bgp_dest *dest;
40381db7 7978 struct bgp_path_info *pi;
d62a17ae 7979 struct bgp_table *table;
7980
7981 table = bgp->rib[afi][SAFI_UNICAST];
7982
9bcb3eef
DS
7983 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7984 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7985 if (pi->peer == bgp->peer_self && pi->type == type
7986 && pi->instance == instance)
d62a17ae 7987 break;
7988
40381db7 7989 if (pi) {
ddb5b488
PZ
7990 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7991 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7992
7993 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7994 bgp, pi);
ddb5b488 7995 }
9bcb3eef 7996 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 7997 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7998 bgp_path_info_delete(dest, pi);
7999 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8000 }
718e3744 8001 }
718e3744 8002}
6b0655a2 8003
718e3744 8004/* Static function to display route. */
bd494ec5 8005static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8006 json_object *json, bool wide)
718e3744 8007{
be054588 8008 int len = 0;
d62a17ae 8009 char buf[BUFSIZ];
50e05855 8010 char buf2[BUFSIZ];
718e3744 8011
d62a17ae 8012 if (p->family == AF_INET) {
c6462ff4 8013 if (!json) {
8228a9a7 8014 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8015 } else {
8016 json_object_string_add(json, "prefix",
8017 inet_ntop(p->family,
8018 &p->u.prefix, buf,
8019 BUFSIZ));
8020 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8021 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8022 json_object_string_add(json, "network", buf2);
c6462ff4 8023 }
d62a17ae 8024 } else if (p->family == AF_ETHERNET) {
8228a9a7 8025 len = vty_out(vty, "%pFX", p);
b03b8898 8026 } else if (p->family == AF_EVPN) {
57f7feb6 8027 if (!json)
2dbe669b 8028 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8029 else
60466a63 8030 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8031 } else if (p->family == AF_FLOWSPEC) {
8032 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8033 json ?
8034 NLRI_STRING_FORMAT_JSON_SIMPLE :
8035 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8036 } else {
c6462ff4 8037 if (!json)
8228a9a7 8038 len = vty_out(vty, "%pFX", p);
50e05855
AD
8039 else {
8040 json_object_string_add(json, "prefix",
8041 inet_ntop(p->family,
8042 &p->u.prefix, buf,
8043 BUFSIZ));
8044 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8045 prefix2str(p, buf2, PREFIX_STRLEN);
8046 json_object_string_add(json, "network", buf2);
8047 }
9c92b5f7 8048 }
d62a17ae 8049
9c92b5f7 8050 if (!json) {
ae248832 8051 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8052 if (len < 1)
8053 vty_out(vty, "\n%*s", 20, " ");
8054 else
8055 vty_out(vty, "%*s", len, " ");
8056 }
718e3744 8057}
8058
d62a17ae 8059enum bgp_display_type {
8060 normal_list,
718e3744 8061};
8062
18ee8310 8063/* Print the short form route status for a bgp_path_info */
4b7e6066 8064static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8065 struct bgp_path_info *path,
d62a17ae 8066 json_object *json_path)
718e3744 8067{
d62a17ae 8068 if (json_path) {
b05a1c8b 8069
d62a17ae 8070 /* Route status display. */
9b6d8fcf 8071 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8072 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8073
9b6d8fcf 8074 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8075 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8076
4056a5f6 8077 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8078 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8079
9b6d8fcf
DS
8080 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8081 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8082 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8083
d62a17ae 8084 /* Selected */
9b6d8fcf 8085 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8086 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8087
9b6d8fcf 8088 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8089 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8090
9b6d8fcf 8091 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8092 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 8093
9b6d8fcf 8094 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8095 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8096
d62a17ae 8097 /* Internal route. */
9b6d8fcf
DS
8098 if ((path->peer->as)
8099 && (path->peer->as == path->peer->local_as))
d62a17ae 8100 json_object_string_add(json_path, "pathFrom",
8101 "internal");
8102 else
8103 json_object_string_add(json_path, "pathFrom",
8104 "external");
b05a1c8b 8105
d62a17ae 8106 return;
8107 }
b05a1c8b 8108
d62a17ae 8109 /* Route status display. */
9b6d8fcf 8110 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8111 vty_out(vty, "R");
9b6d8fcf 8112 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8113 vty_out(vty, "S");
4056a5f6 8114 else if (bgp_path_suppressed(path))
d62a17ae 8115 vty_out(vty, "s");
9b6d8fcf
DS
8116 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8117 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8118 vty_out(vty, "*");
8119 else
8120 vty_out(vty, " ");
8121
8122 /* Selected */
9b6d8fcf 8123 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8124 vty_out(vty, "h");
9b6d8fcf 8125 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8126 vty_out(vty, "d");
9b6d8fcf 8127 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8128 vty_out(vty, ">");
9b6d8fcf 8129 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8130 vty_out(vty, "=");
8131 else
8132 vty_out(vty, " ");
718e3744 8133
d62a17ae 8134 /* Internal route. */
9b6d8fcf
DS
8135 if (path->peer && (path->peer->as)
8136 && (path->peer->as == path->peer->local_as))
d62a17ae 8137 vty_out(vty, "i");
8138 else
8139 vty_out(vty, " ");
b40d939b 8140}
8141
2ba93fd6
DA
8142static char *bgp_nexthop_hostname(struct peer *peer,
8143 struct bgp_nexthop_cache *bnc)
25b5da8d 8144{
892fedb6 8145 if (peer->hostname
aef999a2 8146 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8147 return peer->hostname;
8148 return NULL;
8149}
8150
b40d939b 8151/* called from terminal list command */
bd494ec5 8152void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8153 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8154 json_object *json_paths, bool wide)
d62a17ae 8155{
aef999a2 8156 int len;
515c2602 8157 struct attr *attr = path->attr;
d62a17ae 8158 json_object *json_path = NULL;
8159 json_object *json_nexthops = NULL;
8160 json_object *json_nexthop_global = NULL;
8161 json_object *json_nexthop_ll = NULL;
6f214dd3 8162 json_object *json_ext_community = NULL;
9df8b37c 8163 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8164 bool nexthop_self =
9b6d8fcf 8165 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8166 bool nexthop_othervrf = false;
43089216 8167 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8168 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8169 char *nexthop_hostname =
8170 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8171 char esi_buf[ESI_STR_LEN];
d62a17ae 8172
8173 if (json_paths)
8174 json_path = json_object_new_object();
8175
8176 /* short status lead text */
9b6d8fcf 8177 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8178
8179 if (!json_paths) {
8180 /* print prefix and mask */
8181 if (!display)
ae248832 8182 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8183 else
ae248832 8184 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8185 } else {
ae248832 8186 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8187 }
47fc97cc 8188
9df8b37c
PZ
8189 /*
8190 * If vrf id of nexthop is different from that of prefix,
8191 * set up printable string to append
8192 */
9b6d8fcf 8193 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8194 const char *self = "";
8195
8196 if (nexthop_self)
8197 self = "<";
8198
8199 nexthop_othervrf = true;
9b6d8fcf 8200 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8201
9b6d8fcf 8202 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8203 snprintf(vrf_id_str, sizeof(vrf_id_str),
8204 "@%s%s", VRFID_NONE_STR, self);
8205 else
8206 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8207 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8208
9b6d8fcf
DS
8209 if (path->extra->bgp_orig->inst_type
8210 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8211
9b6d8fcf 8212 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8213 } else {
8214 const char *self = "";
8215
8216 if (nexthop_self)
8217 self = "<";
8218
8219 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8220 }
8221
445c2480
DS
8222 /*
8223 * For ENCAP and EVPN routes, nexthop address family is not
8224 * neccessarily the same as the prefix address family.
8225 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8226 * EVPN routes are also exchanged with a MP nexthop. Currently,
8227 * this
8228 * is only IPv4, the value will be present in either
8229 * attr->nexthop or
8230 * attr->mp_nexthop_global_in
8231 */
8232 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8233 char buf[BUFSIZ];
8234 char nexthop[128];
8235 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8236
8237 switch (af) {
8238 case AF_INET:
772270f3
QY
8239 snprintf(nexthop, sizeof(nexthop), "%s",
8240 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8241 BUFSIZ));
445c2480
DS
8242 break;
8243 case AF_INET6:
772270f3
QY
8244 snprintf(nexthop, sizeof(nexthop), "%s",
8245 inet_ntop(af, &attr->mp_nexthop_global, buf,
8246 BUFSIZ));
445c2480
DS
8247 break;
8248 default:
772270f3 8249 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8250 break;
d62a17ae 8251 }
d62a17ae 8252
445c2480
DS
8253 if (json_paths) {
8254 json_nexthop_global = json_object_new_object();
8255
515c2602
DA
8256 json_object_string_add(json_nexthop_global, "ip",
8257 nexthop);
8258
939a97f4 8259 if (path->peer->hostname)
515c2602
DA
8260 json_object_string_add(json_nexthop_global,
8261 "hostname",
939a97f4 8262 path->peer->hostname);
515c2602
DA
8263
8264 json_object_string_add(json_nexthop_global, "afi",
8265 (af == AF_INET) ? "ipv4"
8266 : "ipv6");
445c2480
DS
8267 json_object_boolean_true_add(json_nexthop_global,
8268 "used");
aef999a2
DA
8269 } else {
8270 if (nexthop_hostname)
8271 len = vty_out(vty, "%s(%s)%s", nexthop,
8272 nexthop_hostname, vrf_id_str);
8273 else
8274 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8275
ae248832 8276 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8277 if (len < 1)
8278 vty_out(vty, "\n%*s", 36, " ");
8279 else
8280 vty_out(vty, "%*s", len, " ");
8281 }
445c2480
DS
8282 } else if (safi == SAFI_EVPN) {
8283 if (json_paths) {
23d0a753
DA
8284 char buf[BUFSIZ] = {0};
8285
445c2480
DS
8286 json_nexthop_global = json_object_new_object();
8287
515c2602 8288 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8289 inet_ntop(AF_INET,
8290 &attr->nexthop, buf,
8291 sizeof(buf)));
515c2602 8292
939a97f4 8293 if (path->peer->hostname)
515c2602
DA
8294 json_object_string_add(json_nexthop_global,
8295 "hostname",
939a97f4 8296 path->peer->hostname);
515c2602 8297
a4d82a8a
PZ
8298 json_object_string_add(json_nexthop_global, "afi",
8299 "ipv4");
445c2480
DS
8300 json_object_boolean_true_add(json_nexthop_global,
8301 "used");
aef999a2
DA
8302 } else {
8303 if (nexthop_hostname)
8304 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8305 nexthop_hostname, vrf_id_str);
8306 else
8307 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8308 vrf_id_str);
8309
ae248832 8310 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8311 if (len < 1)
8312 vty_out(vty, "\n%*s", 36, " ");
8313 else
8314 vty_out(vty, "%*s", len, " ");
8315 }
d33fc23b 8316 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8317 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8318 if (json_paths) {
23d0a753
DA
8319 char buf[BUFSIZ] = {0};
8320
026b914a 8321 json_nexthop_global = json_object_new_object();
515c2602 8322
026b914a
PG
8323 json_object_string_add(json_nexthop_global,
8324 "afi", "ipv4");
515c2602
DA
8325 json_object_string_add(
8326 json_nexthop_global, "ip",
23d0a753
DA
8327 inet_ntop(AF_INET, &attr->nexthop, buf,
8328 sizeof(buf)));
515c2602 8329
939a97f4 8330 if (path->peer->hostname)
515c2602
DA
8331 json_object_string_add(
8332 json_nexthop_global, "hostname",
939a97f4 8333 path->peer->hostname);
515c2602 8334
50e05855
AD
8335 json_object_boolean_true_add(
8336 json_nexthop_global,
026b914a
PG
8337 "used");
8338 } else {
aef999a2
DA
8339 if (nexthop_hostname)
8340 len = vty_out(vty, "%pI4(%s)%s",
8341 &attr->nexthop,
8342 nexthop_hostname,
8343 vrf_id_str);
8344 else
8345 len = vty_out(vty, "%pI4%s",
8346 &attr->nexthop,
8347 vrf_id_str);
8348
ae248832 8349 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8350 if (len < 1)
8351 vty_out(vty, "\n%*s", 36, " ");
8352 else
8353 vty_out(vty, "%*s", len, " ");
026b914a
PG
8354 }
8355 }
d33fc23b 8356 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8357 if (json_paths) {
23d0a753
DA
8358 char buf[BUFSIZ] = {0};
8359
445c2480 8360 json_nexthop_global = json_object_new_object();
d62a17ae 8361
515c2602 8362 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8363 inet_ntop(AF_INET,
8364 &attr->nexthop, buf,
8365 sizeof(buf)));
515c2602 8366
939a97f4 8367 if (path->peer->hostname)
515c2602
DA
8368 json_object_string_add(json_nexthop_global,
8369 "hostname",
939a97f4 8370 path->peer->hostname);
445c2480 8371
a4d82a8a
PZ
8372 json_object_string_add(json_nexthop_global, "afi",
8373 "ipv4");
445c2480
DS
8374 json_object_boolean_true_add(json_nexthop_global,
8375 "used");
8376 } else {
aef999a2
DA
8377 if (nexthop_hostname)
8378 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8379 nexthop_hostname, vrf_id_str);
8380 else
8381 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8382 vrf_id_str);
9df8b37c 8383
ae248832 8384 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8385 if (len < 1)
8386 vty_out(vty, "\n%*s", 36, " ");
8387 else
8388 vty_out(vty, "%*s", len, " ");
d62a17ae 8389 }
445c2480 8390 }
b05a1c8b 8391
445c2480 8392 /* IPv6 Next Hop */
a4d82a8a 8393 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8394 char buf[BUFSIZ];
d62a17ae 8395
445c2480
DS
8396 if (json_paths) {
8397 json_nexthop_global = json_object_new_object();
a4d82a8a 8398 json_object_string_add(
515c2602
DA
8399 json_nexthop_global, "ip",
8400 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8401 buf, BUFSIZ));
8402
939a97f4 8403 if (path->peer->hostname)
515c2602
DA
8404 json_object_string_add(json_nexthop_global,
8405 "hostname",
939a97f4 8406 path->peer->hostname);
515c2602 8407
a4d82a8a
PZ
8408 json_object_string_add(json_nexthop_global, "afi",
8409 "ipv6");
8410 json_object_string_add(json_nexthop_global, "scope",
8411 "global");
445c2480
DS
8412
8413 /* We display both LL & GL if both have been
8414 * received */
0606039c
DA
8415 if ((attr->mp_nexthop_len
8416 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8417 || (path->peer->conf_if)) {
a4d82a8a 8418 json_nexthop_ll = json_object_new_object();
d62a17ae 8419 json_object_string_add(
515c2602
DA
8420 json_nexthop_ll, "ip",
8421 inet_ntop(AF_INET6,
8422 &attr->mp_nexthop_local, buf,
8423 BUFSIZ));
8424
939a97f4 8425 if (path->peer->hostname)
515c2602
DA
8426 json_object_string_add(
8427 json_nexthop_ll, "hostname",
939a97f4 8428 path->peer->hostname);
515c2602 8429
a4d82a8a
PZ
8430 json_object_string_add(json_nexthop_ll, "afi",
8431 "ipv6");
8432 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8433 "link-local");
d62a17ae 8434
a4d82a8a
PZ
8435 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8436 &attr->mp_nexthop_local)
445c2480
DS
8437 != 0)
8438 && !attr->mp_nexthop_prefer_global)
d62a17ae 8439 json_object_boolean_true_add(
a4d82a8a 8440 json_nexthop_ll, "used");
445c2480
DS
8441 else
8442 json_object_boolean_true_add(
a4d82a8a 8443 json_nexthop_global, "used");
445c2480
DS
8444 } else
8445 json_object_boolean_true_add(
8446 json_nexthop_global, "used");
8447 } else {
8448 /* Display LL if LL/Global both in table unless
8449 * prefer-global is set */
0606039c
DA
8450 if (((attr->mp_nexthop_len
8451 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8452 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8453 || (path->peer->conf_if)) {
8454 if (path->peer->conf_if) {
a4d82a8a 8455 len = vty_out(vty, "%s",
9b6d8fcf 8456 path->peer->conf_if);
ae248832
MK
8457 /* len of IPv6 addr + max len of def
8458 * ifname */
8459 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8460
8461 if (len < 1)
a4d82a8a 8462 vty_out(vty, "\n%*s", 36, " ");
445c2480 8463 else
a4d82a8a 8464 vty_out(vty, "%*s", len, " ");
d62a17ae 8465 } else {
aef999a2
DA
8466 if (nexthop_hostname)
8467 len = vty_out(
8468 vty, "%pI6(%s)%s",
8469 &attr->mp_nexthop_local,
8470 nexthop_hostname,
8471 vrf_id_str);
8472 else
8473 len = vty_out(
8474 vty, "%pI6%s",
8475 &attr->mp_nexthop_local,
8476 vrf_id_str);
8477
ae248832 8478 len = wide ? (41 - len) : (16 - len);
d62a17ae 8479
8480 if (len < 1)
a4d82a8a 8481 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8482 else
a4d82a8a 8483 vty_out(vty, "%*s", len, " ");
d62a17ae 8484 }
445c2480 8485 } else {
aef999a2
DA
8486 if (nexthop_hostname)
8487 len = vty_out(vty, "%pI6(%s)%s",
8488 &attr->mp_nexthop_global,
8489 nexthop_hostname,
8490 vrf_id_str);
8491 else
8492 len = vty_out(vty, "%pI6%s",
8493 &attr->mp_nexthop_global,
8494 vrf_id_str);
8495
ae248832 8496 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8497
8498 if (len < 1)
8499 vty_out(vty, "\n%*s", 36, " ");
8500 else
8501 vty_out(vty, "%*s", len, " ");
d62a17ae 8502 }
8503 }
445c2480 8504 }
718e3744 8505
445c2480
DS
8506 /* MED/Metric */
8507 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8508 if (json_paths)
50e05855 8509 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8510 else if (wide)
8511 vty_out(vty, "%7u", attr->med);
0fbac0b4 8512 else
445c2480 8513 vty_out(vty, "%10u", attr->med);
ae248832
MK
8514 else if (!json_paths) {
8515 if (wide)
8516 vty_out(vty, "%*s", 7, " ");
8517 else
8518 vty_out(vty, "%*s", 10, " ");
8519 }
d62a17ae 8520
445c2480
DS
8521 /* Local Pref */
8522 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8523 if (json_paths)
50e05855 8524 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8525 attr->local_pref);
8526 else
445c2480
DS
8527 vty_out(vty, "%7u", attr->local_pref);
8528 else if (!json_paths)
8529 vty_out(vty, " ");
d62a17ae 8530
445c2480
DS
8531 if (json_paths)
8532 json_object_int_add(json_path, "weight", attr->weight);
8533 else
8534 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8535
445c2480
DS
8536 if (json_paths) {
8537 char buf[BUFSIZ];
a4d82a8a
PZ
8538 json_object_string_add(
8539 json_path, "peerId",
9b6d8fcf 8540 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8541 }
b05a1c8b 8542
445c2480
DS
8543 /* Print aspath */
8544 if (attr->aspath) {
0fbac0b4 8545 if (json_paths)
50e05855 8546 json_object_string_add(json_path, "path",
0fbac0b4
DA
8547 attr->aspath->str);
8548 else
445c2480 8549 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8550 }
f1aa5d8a 8551
445c2480
DS
8552 /* Print origin */
8553 if (json_paths)
a4d82a8a
PZ
8554 json_object_string_add(json_path, "origin",
8555 bgp_origin_long_str[attr->origin]);
445c2480
DS
8556 else
8557 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8558
9df8b37c 8559 if (json_paths) {
d071f237 8560 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8561 json_object_string_add(json_path, "esi",
8562 esi_to_str(&attr->esi,
8563 esi_buf, sizeof(esi_buf)));
8564 }
6f214dd3
CS
8565 if (safi == SAFI_EVPN &&
8566 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8567 json_ext_community = json_object_new_object();
8568 json_object_string_add(json_ext_community,
8569 "string",
8570 attr->ecommunity->str);
8571 json_object_object_add(json_path,
8572 "extendedCommunity",
8573 json_ext_community);
8574 }
8575
9df8b37c
PZ
8576 if (nexthop_self)
8577 json_object_boolean_true_add(json_path,
8578 "announceNexthopSelf");
8579 if (nexthop_othervrf) {
8580 json_object_string_add(json_path, "nhVrfName",
8581 nexthop_vrfname);
8582
8583 json_object_int_add(json_path, "nhVrfId",
8584 ((nexthop_vrfid == VRF_UNKNOWN)
8585 ? -1
8586 : (int)nexthop_vrfid));
8587 }
8588 }
8589
d62a17ae 8590 if (json_paths) {
8591 if (json_nexthop_global || json_nexthop_ll) {
8592 json_nexthops = json_object_new_array();
f1aa5d8a 8593
d62a17ae 8594 if (json_nexthop_global)
8595 json_object_array_add(json_nexthops,
8596 json_nexthop_global);
f1aa5d8a 8597
d62a17ae 8598 if (json_nexthop_ll)
8599 json_object_array_add(json_nexthops,
8600 json_nexthop_ll);
f1aa5d8a 8601
d62a17ae 8602 json_object_object_add(json_path, "nexthops",
8603 json_nexthops);
8604 }
8605
8606 json_object_array_add(json_paths, json_path);
8607 } else {
8608 vty_out(vty, "\n");
6f214dd3 8609
b5e140c8 8610 if (safi == SAFI_EVPN) {
d071f237 8611 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8612 vty_out(vty, "%*s", 20, " ");
8613 vty_out(vty, "ESI:%s\n",
8614 esi_to_str(&attr->esi,
8615 esi_buf, sizeof(esi_buf)));
8616 }
8617 if (attr->flag &
8618 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8619 vty_out(vty, "%*s", 20, " ");
8620 vty_out(vty, "%s\n", attr->ecommunity->str);
8621 }
6f214dd3
CS
8622 }
8623
49e5a4a0 8624#ifdef ENABLE_BGP_VNC
d62a17ae 8625 /* prints an additional line, indented, with VNC info, if
8626 * present */
8627 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8628 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8629#endif
d62a17ae 8630 }
8631}
718e3744 8632
8633/* called from terminal list command */
5f040085
DS
8634void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8635 struct attr *attr, safi_t safi, bool use_json,
ae248832 8636 json_object *json_ar, bool wide)
d62a17ae 8637{
8638 json_object *json_status = NULL;
8639 json_object *json_net = NULL;
aef999a2 8640 int len;
d62a17ae 8641 char buff[BUFSIZ];
dc387b0f 8642
d62a17ae 8643 /* Route status display. */
8644 if (use_json) {
8645 json_status = json_object_new_object();
8646 json_net = json_object_new_object();
8647 } else {
8648 vty_out(vty, "*");
8649 vty_out(vty, ">");
8650 vty_out(vty, " ");
8651 }
718e3744 8652
d62a17ae 8653 /* print prefix and mask */
50e05855 8654 if (use_json) {
dc387b0f
LK
8655 if (safi == SAFI_EVPN)
8656 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8657 else if (p->family == AF_INET || p->family == AF_INET6) {
8658 json_object_string_add(
8659 json_net, "addrPrefix",
8660 inet_ntop(p->family, &p->u.prefix, buff,
8661 BUFSIZ));
8662 json_object_int_add(json_net, "prefixLen",
8663 p->prefixlen);
8664 prefix2str(p, buff, PREFIX_STRLEN);
8665 json_object_string_add(json_net, "network", buff);
8666 }
50e05855 8667 } else
ae248832 8668 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8669
8670 /* Print attribute */
8671 if (attr) {
8672 if (use_json) {
23d0a753
DA
8673 char buf[BUFSIZ] = {0};
8674
d62a17ae 8675 if (p->family == AF_INET
8676 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8677 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8678 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8679 json_object_string_add(
8680 json_net, "nextHop",
23d0a753
DA
8681 inet_ntop(
8682 AF_INET,
8683 &attr->mp_nexthop_global_in,
8684 buf, sizeof(buf)));
d62a17ae 8685 else
8686 json_object_string_add(
8687 json_net, "nextHop",
23d0a753
DA
8688 inet_ntop(AF_INET,
8689 &attr->nexthop, buf,
8690 sizeof(buf)));
d62a17ae 8691 } else if (p->family == AF_INET6
8692 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8693 char buf[BUFSIZ];
8694
8695 json_object_string_add(
aa0a10fc 8696 json_net, "nextHopGlobal",
d62a17ae 8697 inet_ntop(AF_INET6,
8698 &attr->mp_nexthop_global, buf,
8699 BUFSIZ));
23d0a753
DA
8700 } else if (p->family == AF_EVPN
8701 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8702 char buf[BUFSIZ] = {0};
8703
8704 json_object_string_add(
8705 json_net, "nextHop",
8706 inet_ntop(AF_INET,
8707 &attr->mp_nexthop_global_in,
8708 buf, sizeof(buf)));
8709 }
d62a17ae 8710
8711 if (attr->flag
8712 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8713 json_object_int_add(json_net, "metric",
8714 attr->med);
8715
0fbac0b4 8716 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8717 json_object_int_add(json_net, "locPrf",
0fbac0b4 8718 attr->local_pref);
d62a17ae 8719
8720 json_object_int_add(json_net, "weight", attr->weight);
8721
8722 /* Print aspath */
0fbac0b4 8723 if (attr->aspath)
50e05855 8724 json_object_string_add(json_net, "path",
0fbac0b4 8725 attr->aspath->str);
d62a17ae 8726
8727 /* Print origin */
8728 json_object_string_add(json_net, "bgpOriginCode",
8729 bgp_origin_str[attr->origin]);
8730 } else {
8731 if (p->family == AF_INET
8732 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8733 || safi == SAFI_EVPN
8734 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8735 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8736 || safi == SAFI_EVPN)
23d0a753
DA
8737 vty_out(vty, "%-16pI4",
8738 &attr->mp_nexthop_global_in);
ae248832 8739 else if (wide)
23d0a753 8740 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8741 else
23d0a753 8742 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8743 } else if (p->family == AF_INET6
8744 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8745 char buf[BUFSIZ];
8746
8747 len = vty_out(
8748 vty, "%s",
8749 inet_ntop(AF_INET6,
8750 &attr->mp_nexthop_global, buf,
8751 BUFSIZ));
ae248832 8752 len = wide ? (41 - len) : (16 - len);
d62a17ae 8753 if (len < 1)
8754 vty_out(vty, "\n%*s", 36, " ");
8755 else
8756 vty_out(vty, "%*s", len, " ");
8757 }
8758 if (attr->flag
8759 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8760 if (wide)
8761 vty_out(vty, "%7u", attr->med);
8762 else
8763 vty_out(vty, "%10u", attr->med);
8764 else if (wide)
8765 vty_out(vty, " ");
d62a17ae 8766 else
8767 vty_out(vty, " ");
718e3744 8768
d62a17ae 8769 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8770 vty_out(vty, "%7u", attr->local_pref);
8771 else
8772 vty_out(vty, " ");
8773
8774 vty_out(vty, "%7u ", attr->weight);
8775
8776 /* Print aspath */
8777 if (attr->aspath)
8778 aspath_print_vty(vty, "%s", attr->aspath, " ");
8779
8780 /* Print origin */
8781 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8782 }
8783 }
8784 if (use_json) {
8785 json_object_boolean_true_add(json_status, "*");
8786 json_object_boolean_true_add(json_status, ">");
8787 json_object_object_add(json_net, "appliedStatusSymbols",
8788 json_status);
1608ff77 8789
dc387b0f
LK
8790 prefix2str(p, buff, PREFIX_STRLEN);
8791 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8792 } else
8793 vty_out(vty, "\n");
8794}
8795
bd494ec5 8796void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8797 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8798 json_object *json)
8799{
8800 json_object *json_out = NULL;
8801 struct attr *attr;
8802 mpls_label_t label = MPLS_INVALID_LABEL;
8803
9b6d8fcf 8804 if (!path->extra)
d62a17ae 8805 return;
8806
8807 if (json)
8808 json_out = json_object_new_object();
8809
8810 /* short status lead text */
9b6d8fcf 8811 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8812
8813 /* print prefix and mask */
8814 if (json == NULL) {
8815 if (!display)
ae248832 8816 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8817 else
8818 vty_out(vty, "%*s", 17, " ");
8819 }
8820
8821 /* Print attribute */
9b6d8fcf 8822 attr = path->attr;
05864da7
DS
8823 if (((p->family == AF_INET)
8824 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8825 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8826 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
8827 char buf[BUFSIZ] = {0};
8828
05864da7
DS
8829 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8830 || safi == SAFI_EVPN) {
8831 if (json)
8832 json_object_string_add(
8833 json_out, "mpNexthopGlobalIn",
23d0a753
DA
8834 inet_ntop(AF_INET,
8835 &attr->mp_nexthop_global_in,
8836 buf, sizeof(buf)));
05864da7 8837 else
23d0a753
DA
8838 vty_out(vty, "%-16pI4",
8839 &attr->mp_nexthop_global_in);
05864da7
DS
8840 } else {
8841 if (json)
8842 json_object_string_add(
8843 json_out, "nexthop",
23d0a753
DA
8844 inet_ntop(AF_INET, &attr->nexthop, buf,
8845 sizeof(buf)));
05864da7 8846 else
23d0a753 8847 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
8848 }
8849 } else if (((p->family == AF_INET6)
8850 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8851 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8852 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8853 char buf_a[512];
8854
8855 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8856 if (json)
8857 json_object_string_add(
8858 json_out, "mpNexthopGlobalIn",
8859 inet_ntop(AF_INET6,
8860 &attr->mp_nexthop_global,
8861 buf_a, sizeof(buf_a)));
8862 else
8863 vty_out(vty, "%s",
8864 inet_ntop(AF_INET6,
8865 &attr->mp_nexthop_global,
8866 buf_a, sizeof(buf_a)));
8867 } else if (attr->mp_nexthop_len
8868 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8869 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8870 &attr->mp_nexthop_global,
8871 &attr->mp_nexthop_local);
8872 if (json)
8873 json_object_string_add(json_out,
8874 "mpNexthopGlobalLocal",
8875 buf_a);
8876 else
8877 vty_out(vty, "%s", buf_a);
d62a17ae 8878 }
8879 }
8880
9b6d8fcf 8881 label = decode_label(&path->extra->label[0]);
d62a17ae 8882
8883 if (bgp_is_valid_label(&label)) {
8884 if (json) {
8885 json_object_int_add(json_out, "notag", label);
8886 json_object_array_add(json, json_out);
8887 } else {
8888 vty_out(vty, "notag/%d", label);
8889 vty_out(vty, "\n");
8890 }
8891 }
8892}
718e3744 8893
bd494ec5 8894void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8895 struct bgp_path_info *path, int display,
d62a17ae 8896 json_object *json_paths)
718e3744 8897{
d62a17ae 8898 struct attr *attr;
14f51eba 8899 char buf[BUFSIZ] = {0};
d62a17ae 8900 json_object *json_path = NULL;
14f51eba
LK
8901 json_object *json_nexthop = NULL;
8902 json_object *json_overlay = NULL;
856ca177 8903
9b6d8fcf 8904 if (!path->extra)
d62a17ae 8905 return;
718e3744 8906
14f51eba
LK
8907 if (json_paths) {
8908 json_path = json_object_new_object();
8909 json_overlay = json_object_new_object();
8910 json_nexthop = json_object_new_object();
8911 }
8912
d62a17ae 8913 /* short status lead text */
9b6d8fcf 8914 route_vty_short_status_out(vty, path, json_path);
856ca177 8915
d62a17ae 8916 /* print prefix and mask */
8917 if (!display)
ae248832 8918 route_vty_out_route(p, vty, json_path, false);
d62a17ae 8919 else
8920 vty_out(vty, "%*s", 17, " ");
8921
8922 /* Print attribute */
9b6d8fcf 8923 attr = path->attr;
05864da7
DS
8924 char buf1[BUFSIZ];
8925 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8926
05864da7
DS
8927 switch (af) {
8928 case AF_INET:
8929 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8930 if (!json_path) {
8931 vty_out(vty, "%-16s", buf);
8932 } else {
8933 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8934
05864da7 8935 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8936
05864da7
DS
8937 json_object_object_add(json_path, "nexthop",
8938 json_nexthop);
8939 }
8940 break;
8941 case AF_INET6:
8942 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8943 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8944 if (!json_path) {
8945 vty_out(vty, "%s(%s)", buf, buf1);
8946 } else {
8947 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8948
05864da7
DS
8949 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8950 buf1);
14f51eba 8951
05864da7 8952 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8953
05864da7
DS
8954 json_object_object_add(json_path, "nexthop",
8955 json_nexthop);
8956 }
8957 break;
8958 default:
8959 if (!json_path) {
8960 vty_out(vty, "?");
8961 } else {
8962 json_object_string_add(json_nexthop, "Error",
8963 "Unsupported address-family");
d62a17ae 8964 }
05864da7 8965 }
988258b4 8966
05864da7
DS
8967 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8968 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8969 BUFSIZ);
8970 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8971 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8972 BUFSIZ);
8973 }
14f51eba 8974
05864da7
DS
8975 if (!json_path)
8976 vty_out(vty, "/%s", buf);
8977 else
8978 json_object_string_add(json_overlay, "gw", buf);
8979
8980 if (attr->ecommunity) {
8981 char *mac = NULL;
8982 struct ecommunity_val *routermac = ecommunity_lookup(
8983 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8984 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8985
8986 if (routermac)
8987 mac = ecom_mac2str((char *)routermac->val);
8988 if (mac) {
8989 if (!json_path) {
c4efd0f4 8990 vty_out(vty, "/%s", mac);
05864da7
DS
8991 } else {
8992 json_object_string_add(json_overlay, "rmac",
8993 mac);
988258b4 8994 }
05864da7 8995 XFREE(MTYPE_TMP, mac);
988258b4 8996 }
05864da7 8997 }
718e3744 8998
05864da7
DS
8999 if (!json_path) {
9000 vty_out(vty, "\n");
9001 } else {
9002 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9003
05864da7 9004 json_object_array_add(json_paths, json_path);
14f51eba 9005 }
d62a17ae 9006}
718e3744 9007
d62a17ae 9008/* dampening route */
5f040085
DS
9009static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9010 struct bgp_path_info *path, int display,
9011 afi_t afi, safi_t safi, bool use_json,
9012 json_object *json)
d62a17ae 9013{
9014 struct attr *attr;
9015 int len;
9016 char timebuf[BGP_UPTIME_LEN];
9017
9018 /* short status lead text */
9b6d8fcf 9019 route_vty_short_status_out(vty, path, json);
d62a17ae 9020
9021 /* print prefix and mask */
9022 if (!use_json) {
9023 if (!display)
ae248832 9024 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9025 else
9026 vty_out(vty, "%*s", 17, " ");
9027 }
9028
9b6d8fcf 9029 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9030 len = 17 - len;
9031 if (len < 1) {
9032 if (!use_json)
9033 vty_out(vty, "\n%*s", 34, " ");
9034 } else {
9035 if (use_json)
9036 json_object_int_add(json, "peerHost", len);
9037 else
9038 vty_out(vty, "%*s", len, " ");
9039 }
9040
9041 if (use_json)
a935f597
DA
9042 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9043 safi, use_json, json);
d62a17ae 9044 else
9b6d8fcf
DS
9045 vty_out(vty, "%s ",
9046 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9047 BGP_UPTIME_LEN, afi, safi,
9048 use_json, json));
d62a17ae 9049
9050 /* Print attribute */
9b6d8fcf 9051 attr = path->attr;
d62a17ae 9052
05864da7
DS
9053 /* Print aspath */
9054 if (attr->aspath) {
d62a17ae 9055 if (use_json)
05864da7
DS
9056 json_object_string_add(json, "asPath",
9057 attr->aspath->str);
d62a17ae 9058 else
05864da7 9059 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9060 }
05864da7
DS
9061
9062 /* Print origin */
9063 if (use_json)
9064 json_object_string_add(json, "origin",
9065 bgp_origin_str[attr->origin]);
9066 else
9067 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9068
d62a17ae 9069 if (!use_json)
9070 vty_out(vty, "\n");
9071}
718e3744 9072
d62a17ae 9073/* flap route */
5f040085
DS
9074static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9075 struct bgp_path_info *path, int display,
9076 afi_t afi, safi_t safi, bool use_json,
9077 json_object *json)
784d3a42 9078{
d62a17ae 9079 struct attr *attr;
9080 struct bgp_damp_info *bdi;
9081 char timebuf[BGP_UPTIME_LEN];
9082 int len;
784d3a42 9083
9b6d8fcf 9084 if (!path->extra)
d62a17ae 9085 return;
784d3a42 9086
9b6d8fcf 9087 bdi = path->extra->damp_info;
784d3a42 9088
d62a17ae 9089 /* short status lead text */
9b6d8fcf 9090 route_vty_short_status_out(vty, path, json);
784d3a42 9091
d62a17ae 9092 /* print prefix and mask */
9093 if (!use_json) {
9094 if (!display)
ae248832 9095 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9096 else
9097 vty_out(vty, "%*s", 17, " ");
9098 }
784d3a42 9099
9b6d8fcf 9100 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9101 len = 16 - len;
9102 if (len < 1) {
9103 if (!use_json)
9104 vty_out(vty, "\n%*s", 33, " ");
9105 } else {
9106 if (use_json)
9107 json_object_int_add(json, "peerHost", len);
9108 else
9109 vty_out(vty, "%*s", len, " ");
9110 }
784d3a42 9111
d62a17ae 9112 len = vty_out(vty, "%d", bdi->flap);
9113 len = 5 - len;
9114 if (len < 1) {
9115 if (!use_json)
9116 vty_out(vty, " ");
9117 } else {
9118 if (use_json)
9119 json_object_int_add(json, "bdiFlap", len);
9120 else
9121 vty_out(vty, "%*s", len, " ");
9122 }
9123
9124 if (use_json)
9125 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9126 json);
9127 else
996c9314
LB
9128 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9129 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9130
9b6d8fcf
DS
9131 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9132 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9133 if (use_json)
9b6d8fcf 9134 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9135 BGP_UPTIME_LEN, afi, safi,
9136 use_json, json);
d62a17ae 9137 else
9138 vty_out(vty, "%s ",
9b6d8fcf 9139 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9140 BGP_UPTIME_LEN, afi,
9141 safi, use_json, json));
d62a17ae 9142 } else {
9143 if (!use_json)
9144 vty_out(vty, "%*s ", 8, " ");
9145 }
9146
9147 /* Print attribute */
9b6d8fcf 9148 attr = path->attr;
d62a17ae 9149
05864da7
DS
9150 /* Print aspath */
9151 if (attr->aspath) {
d62a17ae 9152 if (use_json)
05864da7
DS
9153 json_object_string_add(json, "asPath",
9154 attr->aspath->str);
d62a17ae 9155 else
05864da7 9156 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9157 }
05864da7
DS
9158
9159 /* Print origin */
9160 if (use_json)
9161 json_object_string_add(json, "origin",
9162 bgp_origin_str[attr->origin]);
9163 else
9164 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9165
d62a17ae 9166 if (!use_json)
9167 vty_out(vty, "\n");
9168}
9169
9170static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9171 int *first, const char *header,
9172 json_object *json_adv_to)
9173{
9174 char buf1[INET6_ADDRSTRLEN];
9175 json_object *json_peer = NULL;
9176
9177 if (json_adv_to) {
9178 /* 'advertised-to' is a dictionary of peers we have advertised
9179 * this
9180 * prefix too. The key is the peer's IP or swpX, the value is
9181 * the
9182 * hostname if we know it and "" if not.
9183 */
9184 json_peer = json_object_new_object();
9185
9186 if (peer->hostname)
9187 json_object_string_add(json_peer, "hostname",
9188 peer->hostname);
9189
9190 if (peer->conf_if)
9191 json_object_object_add(json_adv_to, peer->conf_if,
9192 json_peer);
9193 else
9194 json_object_object_add(
9195 json_adv_to,
9196 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9197 json_peer);
9198 } else {
9199 if (*first) {
9200 vty_out(vty, "%s", header);
9201 *first = 0;
9202 }
9203
9204 if (peer->hostname
892fedb6 9205 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9206 if (peer->conf_if)
9207 vty_out(vty, " %s(%s)", peer->hostname,
9208 peer->conf_if);
9209 else
9210 vty_out(vty, " %s(%s)", peer->hostname,
9211 sockunion2str(&peer->su, buf1,
9212 SU_ADDRSTRLEN));
9213 } else {
9214 if (peer->conf_if)
9215 vty_out(vty, " %s", peer->conf_if);
9216 else
9217 vty_out(vty, " %s",
9218 sockunion2str(&peer->su, buf1,
9219 SU_ADDRSTRLEN));
9220 }
9221 }
784d3a42
PG
9222}
9223
dcc68b5e
MS
9224static void route_vty_out_tx_ids(struct vty *vty,
9225 struct bgp_addpath_info_data *d)
9226{
9227 int i;
9228
9229 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9230 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9231 d->addpath_tx_id[i],
9232 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9233 }
9234}
9235
0dc8ee70
DS
9236static const char *bgp_path_selection_reason2str(
9237 enum bgp_path_selection_reason reason)
9238{
9239 switch (reason) {
9240 case bgp_path_selection_none:
9241 return "Nothing to Select";
0dc8ee70
DS
9242 case bgp_path_selection_first:
9243 return "First path received";
0dc8ee70
DS
9244 case bgp_path_selection_evpn_sticky_mac:
9245 return "EVPN Sticky Mac";
0dc8ee70
DS
9246 case bgp_path_selection_evpn_seq:
9247 return "EVPN sequence number";
0dc8ee70
DS
9248 case bgp_path_selection_evpn_lower_ip:
9249 return "EVPN lower IP";
d071f237
AK
9250 case bgp_path_selection_evpn_local_path:
9251 return "EVPN local ES path";
9252 case bgp_path_selection_evpn_non_proxy:
9253 return "EVPN non proxy";
0dc8ee70
DS
9254 case bgp_path_selection_weight:
9255 return "Weight";
0dc8ee70
DS
9256 case bgp_path_selection_local_pref:
9257 return "Local Pref";
0dc8ee70
DS
9258 case bgp_path_selection_local_route:
9259 return "Local Route";
0dc8ee70
DS
9260 case bgp_path_selection_confed_as_path:
9261 return "Confederation based AS Path";
0dc8ee70
DS
9262 case bgp_path_selection_as_path:
9263 return "AS Path";
0dc8ee70
DS
9264 case bgp_path_selection_origin:
9265 return "Origin";
0dc8ee70
DS
9266 case bgp_path_selection_med:
9267 return "MED";
0dc8ee70
DS
9268 case bgp_path_selection_peer:
9269 return "Peer Type";
0dc8ee70
DS
9270 case bgp_path_selection_confed:
9271 return "Confed Peer Type";
0dc8ee70
DS
9272 case bgp_path_selection_igp_metric:
9273 return "IGP Metric";
0dc8ee70
DS
9274 case bgp_path_selection_older:
9275 return "Older Path";
0dc8ee70
DS
9276 case bgp_path_selection_router_id:
9277 return "Router ID";
0dc8ee70
DS
9278 case bgp_path_selection_cluster_length:
9279 return "Cluser length";
0dc8ee70
DS
9280 case bgp_path_selection_stale:
9281 return "Path Staleness";
0dc8ee70
DS
9282 case bgp_path_selection_local_configured:
9283 return "Locally configured route";
0dc8ee70
DS
9284 case bgp_path_selection_neighbor_ip:
9285 return "Neighbor IP";
0dc8ee70
DS
9286 case bgp_path_selection_default:
9287 return "Nothing left to compare";
0dc8ee70 9288 }
a74879b2 9289 return "Invalid (internal error)";
0dc8ee70
DS
9290}
9291
5e4d4c8a
AK
9292static void route_vty_out_detail_es_info(struct vty *vty,
9293 struct attr *attr, json_object *json_path)
9294{
9295 char esi_buf[ESI_STR_LEN];
9296 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9297 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9298 ATTR_ES_PEER_ROUTER);
9299 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9300 ATTR_ES_PEER_ACTIVE);
9301 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9302 ATTR_ES_PEER_PROXY);
9303
9304 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9305 if (json_path) {
9306 json_object *json_es_info = NULL;
9307
9308 json_object_string_add(
9309 json_path, "esi",
9310 esi_buf);
9311 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9312 json_es_info = json_object_new_object();
9313 if (es_local)
9314 json_object_boolean_true_add(
9315 json_es_info, "localEs");
9316 if (peer_active)
9317 json_object_boolean_true_add(
9318 json_es_info, "peerActive");
9319 if (peer_proxy)
9320 json_object_boolean_true_add(
9321 json_es_info, "peerProxy");
9322 if (peer_router)
9323 json_object_boolean_true_add(
9324 json_es_info, "peerRouter");
9325 if (attr->mm_sync_seqnum)
9326 json_object_int_add(
9327 json_es_info, "peerSeq",
9328 attr->mm_sync_seqnum);
9329 json_object_object_add(
9330 json_path, "es_info",
9331 json_es_info);
9332 }
9333 } else {
9334 if (bgp_evpn_attr_is_sync(attr))
9335 vty_out(vty,
9336 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9337 esi_buf,
9338 es_local ? "local-es":"",
9339 peer_proxy ? "proxy " : "",
9340 peer_active ? "active ":"",
9341 peer_router ? "router ":"",
9342 attr->mm_sync_seqnum);
9343 else
9344 vty_out(vty, " ESI %s %s\n",
9345 esi_buf,
9346 es_local ? "local-es":"");
9347 }
9348}
9349
9350void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9351 struct bgp_dest *bn, struct bgp_path_info *path,
9352 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9353{
9354 char buf[INET6_ADDRSTRLEN];
9355 char buf1[BUFSIZ];
515c2602 9356 struct attr *attr = path->attr;
d62a17ae 9357 int sockunion_vty_out(struct vty *, union sockunion *);
9358 time_t tbuf;
9359 json_object *json_bestpath = NULL;
9360 json_object *json_cluster_list = NULL;
9361 json_object *json_cluster_list_list = NULL;
9362 json_object *json_ext_community = NULL;
9363 json_object *json_last_update = NULL;
7fd077aa 9364 json_object *json_pmsi = NULL;
d62a17ae 9365 json_object *json_nexthop_global = NULL;
9366 json_object *json_nexthop_ll = NULL;
9367 json_object *json_nexthops = NULL;
9368 json_object *json_path = NULL;
9369 json_object *json_peer = NULL;
9370 json_object *json_string = NULL;
9371 json_object *json_adv_to = NULL;
9372 int first = 0;
9373 struct listnode *node, *nnode;
9374 struct peer *peer;
9375 int addpath_capable;
9376 int has_adj;
9377 unsigned int first_as;
1defdda8 9378 bool nexthop_self =
9b6d8fcf 9379 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9380 int i;
2ba93fd6
DA
9381 char *nexthop_hostname =
9382 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9383
9384 if (json_paths) {
9385 json_path = json_object_new_object();
9386 json_peer = json_object_new_object();
9387 json_nexthop_global = json_object_new_object();
9388 }
9389
44c69747 9390 if (path->extra) {
b57ba6d2 9391 char tag_buf[30];
d62a17ae 9392
d62a17ae 9393 tag_buf[0] = '\0';
9b6d8fcf
DS
9394 if (path->extra && path->extra->num_labels) {
9395 bgp_evpn_label2str(path->extra->label,
9396 path->extra->num_labels, tag_buf,
a4d82a8a 9397 sizeof(tag_buf));
d62a17ae 9398 }
d7325ee7 9399 if (safi == SAFI_EVPN) {
44c69747 9400 if (!json_paths) {
2dbe669b
DA
9401 vty_out(vty, " Route %pFX",
9402 (struct prefix_evpn *)
9403 bgp_dest_get_prefix(bn));
44c69747
LK
9404 if (tag_buf[0] != '\0')
9405 vty_out(vty, " VNI %s", tag_buf);
9406 vty_out(vty, "\n");
9407 } else {
9408 if (tag_buf[0])
9409 json_object_string_add(json_path, "VNI",
9410 tag_buf);
9411 }
d7325ee7
DD
9412 }
9413
44c69747 9414 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9415 struct bgp_path_info *parent_ri;
9bcb3eef 9416 struct bgp_dest *dest, *pdest;
d62a17ae 9417
9b6d8fcf 9418 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9419 dest = parent_ri->net;
9420 if (dest && dest->pdest) {
9421 pdest = dest->pdest;
9422 prefix_rd2str(
9423 (struct prefix_rd *)bgp_dest_get_prefix(
9424 pdest),
9425 buf1, sizeof(buf1));
d7325ee7 9426 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9427 vty_out(vty,
9428 " Imported from %s:%pFX, VNI %s\n",
9429 buf1,
9430 (struct prefix_evpn *)
9431 bgp_dest_get_prefix(
9432 dest),
9433 tag_buf);
d7325ee7 9434 } else
2dbe669b
DA
9435 vty_out(vty,
9436 " Imported from %s:%pFX\n",
9437 buf1,
9438 (struct prefix_evpn *)
9439 bgp_dest_get_prefix(
9440 dest));
d62a17ae 9441 }
9442 }
9443 }
d62a17ae 9444
05864da7
DS
9445 /* Line1 display AS-path, Aggregator */
9446 if (attr->aspath) {
9447 if (json_paths) {
9448 if (!attr->aspath->json)
9449 aspath_str_update(attr->aspath, true);
9450 json_object_lock(attr->aspath->json);
9451 json_object_object_add(json_path, "aspath",
9452 attr->aspath->json);
9453 } else {
9454 if (attr->aspath->segments)
9455 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9456 else
05864da7 9457 vty_out(vty, " Local");
d62a17ae 9458 }
05864da7 9459 }
d62a17ae 9460
05864da7
DS
9461 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9462 if (json_paths)
9463 json_object_boolean_true_add(json_path, "removed");
9464 else
9465 vty_out(vty, ", (removed)");
9466 }
d62a17ae 9467
05864da7
DS
9468 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9469 if (json_paths)
9470 json_object_boolean_true_add(json_path, "stale");
9471 else
9472 vty_out(vty, ", (stale)");
9473 }
d62a17ae 9474
05864da7
DS
9475 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9476 if (json_paths) {
23d0a753
DA
9477 char buf[BUFSIZ] = {0};
9478
05864da7
DS
9479 json_object_int_add(json_path, "aggregatorAs",
9480 attr->aggregator_as);
23d0a753
DA
9481 json_object_string_add(json_path, "aggregatorId",
9482 inet_ntop(AF_INET,
9483 &attr->aggregator_addr,
9484 buf, sizeof(buf)));
87c82131
DA
9485 if (attr->aggregator_as == BGP_AS_ZERO)
9486 json_object_boolean_true_add(
9487 json_path, "aggregatorAsMalformed");
9488 else
9489 json_object_boolean_false_add(
9490 json_path, "aggregatorAsMalformed");
05864da7 9491 } else {
87c82131
DA
9492 if (attr->aggregator_as == BGP_AS_ZERO)
9493 vty_out(vty,
23d0a753 9494 ", (aggregated by %u(malformed) %pI4)",
87c82131 9495 attr->aggregator_as,
23d0a753 9496 &attr->aggregator_addr);
87c82131 9497 else
23d0a753 9498 vty_out(vty, ", (aggregated by %u %pI4)",
87c82131 9499 attr->aggregator_as,
23d0a753 9500 &attr->aggregator_addr);
d62a17ae 9501 }
05864da7 9502 }
d62a17ae 9503
05864da7
DS
9504 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9505 PEER_FLAG_REFLECTOR_CLIENT)) {
9506 if (json_paths)
9507 json_object_boolean_true_add(json_path,
9508 "rxedFromRrClient");
9509 else
9510 vty_out(vty, ", (Received from a RR-client)");
9511 }
d62a17ae 9512
05864da7
DS
9513 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9514 PEER_FLAG_RSERVER_CLIENT)) {
9515 if (json_paths)
9516 json_object_boolean_true_add(json_path,
9517 "rxedFromRsClient");
9518 else
9519 vty_out(vty, ", (Received from a RS-client)");
9520 }
d62a17ae 9521
05864da7
DS
9522 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9523 if (json_paths)
9524 json_object_boolean_true_add(json_path,
9525 "dampeningHistoryEntry");
9526 else
9527 vty_out(vty, ", (history entry)");
9528 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9529 if (json_paths)
9530 json_object_boolean_true_add(json_path,
9531 "dampeningSuppressed");
9532 else
9533 vty_out(vty, ", (suppressed due to dampening)");
9534 }
d62a17ae 9535
05864da7
DS
9536 if (!json_paths)
9537 vty_out(vty, "\n");
d62a17ae 9538
05864da7
DS
9539 /* Line2 display Next-hop, Neighbor, Router-id */
9540 /* Display the nexthop */
9bcb3eef 9541 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9542
9543 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9544 || bn_p->family == AF_EVPN)
05864da7
DS
9545 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9546 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9547 char buf[BUFSIZ] = {0};
9548
05864da7
DS
9549 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9550 || safi == SAFI_EVPN) {
515c2602 9551 if (json_paths) {
d62a17ae 9552 json_object_string_add(
515c2602 9553 json_nexthop_global, "ip",
23d0a753
DA
9554 inet_ntop(AF_INET,
9555 &attr->mp_nexthop_global_in,
9556 buf, sizeof(buf)));
515c2602 9557
939a97f4 9558 if (path->peer->hostname)
515c2602
DA
9559 json_object_string_add(
9560 json_nexthop_global, "hostname",
939a97f4 9561 path->peer->hostname);
aef999a2
DA
9562 } else {
9563 if (nexthop_hostname)
9564 vty_out(vty, " %pI4(%s)",
9565 &attr->mp_nexthop_global_in,
9566 nexthop_hostname);
9567 else
9568 vty_out(vty, " %pI4",
9569 &attr->mp_nexthop_global_in);
9570 }
d62a17ae 9571 } else {
515c2602 9572 if (json_paths) {
05864da7 9573 json_object_string_add(
515c2602 9574 json_nexthop_global, "ip",
23d0a753
DA
9575 inet_ntop(AF_INET, &attr->nexthop, buf,
9576 sizeof(buf)));
515c2602 9577
939a97f4 9578 if (path->peer->hostname)
515c2602
DA
9579 json_object_string_add(
9580 json_nexthop_global, "hostname",
939a97f4 9581 path->peer->hostname);
aef999a2
DA
9582 } else {
9583 if (nexthop_hostname)
9584 vty_out(vty, " %pI4(%s)",
9585 &attr->nexthop,
9586 nexthop_hostname);
9587 else
9588 vty_out(vty, " %pI4",
9589 &attr->nexthop);
9590 }
d62a17ae 9591 }
9592
05864da7
DS
9593 if (json_paths)
9594 json_object_string_add(json_nexthop_global, "afi",
9595 "ipv4");
9596 } else {
9597 if (json_paths) {
9598 json_object_string_add(
515c2602
DA
9599 json_nexthop_global, "ip",
9600 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9601 buf, INET6_ADDRSTRLEN));
9602
939a97f4 9603 if (path->peer->hostname)
515c2602
DA
9604 json_object_string_add(json_nexthop_global,
9605 "hostname",
939a97f4 9606 path->peer->hostname);
515c2602 9607
05864da7
DS
9608 json_object_string_add(json_nexthop_global, "afi",
9609 "ipv6");
9610 json_object_string_add(json_nexthop_global, "scope",
9611 "global");
9612 } else {
aef999a2
DA
9613 if (nexthop_hostname)
9614 vty_out(vty, " %pI6(%s)",
9615 &attr->mp_nexthop_global,
9616 nexthop_hostname);
9617 else
9618 vty_out(vty, " %pI6",
9619 &attr->mp_nexthop_global);
d62a17ae 9620 }
05864da7 9621 }
d62a17ae 9622
05864da7
DS
9623 /* Display the IGP cost or 'inaccessible' */
9624 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9625 if (json_paths)
9626 json_object_boolean_false_add(json_nexthop_global,
9627 "accessible");
9628 else
9629 vty_out(vty, " (inaccessible)");
9630 } else {
9631 if (path->extra && path->extra->igpmetric) {
d62a17ae 9632 if (json_paths)
05864da7
DS
9633 json_object_int_add(json_nexthop_global,
9634 "metric",
9635 path->extra->igpmetric);
d62a17ae 9636 else
05864da7
DS
9637 vty_out(vty, " (metric %u)",
9638 path->extra->igpmetric);
d62a17ae 9639 }
9640
05864da7 9641 /* IGP cost is 0, display this only for json */
d62a17ae 9642 else {
d62a17ae 9643 if (json_paths)
05864da7
DS
9644 json_object_int_add(json_nexthop_global,
9645 "metric", 0);
d62a17ae 9646 }
d62a17ae 9647
05864da7
DS
9648 if (json_paths)
9649 json_object_boolean_true_add(json_nexthop_global,
9650 "accessible");
9651 }
d62a17ae 9652
05864da7
DS
9653 /* Display peer "from" output */
9654 /* This path was originated locally */
9655 if (path->peer == bgp->peer_self) {
d62a17ae 9656
05864da7 9657 if (safi == SAFI_EVPN
b54892e0 9658 || (bn_p->family == AF_INET
05864da7 9659 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9660 if (json_paths)
05864da7
DS
9661 json_object_string_add(json_peer, "peerId",
9662 "0.0.0.0");
d62a17ae 9663 else
05864da7
DS
9664 vty_out(vty, " from 0.0.0.0 ");
9665 } else {
d62a17ae 9666 if (json_paths)
05864da7
DS
9667 json_object_string_add(json_peer, "peerId",
9668 "::");
d62a17ae 9669 else
05864da7 9670 vty_out(vty, " from :: ");
d62a17ae 9671 }
d62a17ae 9672
23d0a753
DA
9673 if (json_paths) {
9674 char buf[BUFSIZ] = {0};
9675
05864da7 9676 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9677 inet_ntop(AF_INET,
9678 &bgp->router_id, buf,
9679 sizeof(buf)));
9680 } else {
9681 vty_out(vty, "(%pI4)", &bgp->router_id);
9682 }
05864da7 9683 }
d62a17ae 9684
05864da7
DS
9685 /* We RXed this path from one of our peers */
9686 else {
9687
9688 if (json_paths) {
9689 json_object_string_add(json_peer, "peerId",
9690 sockunion2str(&path->peer->su,
9691 buf,
9692 SU_ADDRSTRLEN));
9693 json_object_string_add(json_peer, "routerId",
9694 inet_ntop(AF_INET,
9695 &path->peer->remote_id,
9696 buf1, sizeof(buf1)));
9697
9698 if (path->peer->hostname)
9699 json_object_string_add(json_peer, "hostname",
9700 path->peer->hostname);
9701
9702 if (path->peer->domainname)
9703 json_object_string_add(json_peer, "domainname",
9704 path->peer->domainname);
9705
9706 if (path->peer->conf_if)
9707 json_object_string_add(json_peer, "interface",
9708 path->peer->conf_if);
9709 } else {
9710 if (path->peer->conf_if) {
9711 if (path->peer->hostname
892fedb6
DA
9712 && CHECK_FLAG(path->peer->bgp->flags,
9713 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9714 vty_out(vty, " from %s(%s)",
9715 path->peer->hostname,
9716 path->peer->conf_if);
d62a17ae 9717 else
05864da7 9718 vty_out(vty, " from %s",
9b6d8fcf 9719 path->peer->conf_if);
d62a17ae 9720 } else {
05864da7 9721 if (path->peer->hostname
892fedb6
DA
9722 && CHECK_FLAG(path->peer->bgp->flags,
9723 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9724 vty_out(vty, " from %s(%s)",
9725 path->peer->hostname,
9726 path->peer->host);
d62a17ae 9727 else
05864da7
DS
9728 vty_out(vty, " from %s",
9729 sockunion2str(&path->peer->su,
9730 buf,
9731 SU_ADDRSTRLEN));
d62a17ae 9732 }
d62a17ae 9733
05864da7 9734 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9735 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9736 else
9737 vty_out(vty, " (%s)",
9738 inet_ntop(AF_INET,
9739 &path->peer->remote_id, buf1,
9740 sizeof(buf1)));
d62a17ae 9741 }
05864da7 9742 }
9df8b37c 9743
05864da7
DS
9744 /*
9745 * Note when vrfid of nexthop is different from that of prefix
9746 */
9747 if (path->extra && path->extra->bgp_orig) {
9748 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9749
05864da7
DS
9750 if (json_paths) {
9751 const char *vn;
9df8b37c 9752
05864da7
DS
9753 if (path->extra->bgp_orig->inst_type
9754 == BGP_INSTANCE_TYPE_DEFAULT)
9755 vn = VRF_DEFAULT_NAME;
9756 else
9757 vn = path->extra->bgp_orig->name;
9df8b37c 9758
05864da7 9759 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9760
05864da7
DS
9761 if (nexthop_vrfid == VRF_UNKNOWN) {
9762 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9763 } else {
05864da7
DS
9764 json_object_int_add(json_path, "nhVrfId",
9765 (int)nexthop_vrfid);
9df8b37c 9766 }
05864da7
DS
9767 } else {
9768 if (nexthop_vrfid == VRF_UNKNOWN)
9769 vty_out(vty, " vrf ?");
137147c6
DS
9770 else {
9771 struct vrf *vrf;
9772
9773 vrf = vrf_lookup_by_id(nexthop_vrfid);
9774 vty_out(vty, " vrf %s(%u)",
9775 VRF_LOGNAME(vrf), nexthop_vrfid);
9776 }
9df8b37c 9777 }
05864da7 9778 }
9df8b37c 9779
05864da7
DS
9780 if (nexthop_self) {
9781 if (json_paths) {
9782 json_object_boolean_true_add(json_path,
9783 "announceNexthopSelf");
9784 } else {
9785 vty_out(vty, " announce-nh-self");
9df8b37c 9786 }
05864da7 9787 }
9df8b37c 9788
05864da7
DS
9789 if (!json_paths)
9790 vty_out(vty, "\n");
d62a17ae 9791
05864da7
DS
9792 /* display the link-local nexthop */
9793 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9794 if (json_paths) {
9795 json_nexthop_ll = json_object_new_object();
9796 json_object_string_add(
515c2602
DA
9797 json_nexthop_ll, "ip",
9798 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9799 buf, INET6_ADDRSTRLEN));
9800
939a97f4 9801 if (path->peer->hostname)
515c2602
DA
9802 json_object_string_add(json_nexthop_ll,
9803 "hostname",
939a97f4 9804 path->peer->hostname);
515c2602 9805
05864da7
DS
9806 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9807 json_object_string_add(json_nexthop_ll, "scope",
9808 "link-local");
d62a17ae 9809
05864da7
DS
9810 json_object_boolean_true_add(json_nexthop_ll,
9811 "accessible");
d62a17ae 9812
05864da7 9813 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9814 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9815 "used");
9816 else
9817 json_object_boolean_true_add(
9818 json_nexthop_global, "used");
9819 } else {
9820 vty_out(vty, " (%s) %s\n",
9821 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9822 buf, INET6_ADDRSTRLEN),
9823 attr->mp_nexthop_prefer_global
9824 ? "(prefer-global)"
9825 : "(used)");
d62a17ae 9826 }
05864da7
DS
9827 }
9828 /* If we do not have a link-local nexthop then we must flag the
9829 global as "used" */
9830 else {
9831 if (json_paths)
9832 json_object_boolean_true_add(json_nexthop_global,
9833 "used");
9834 }
d62a17ae 9835
b5e140c8 9836 if (safi == SAFI_EVPN &&
5e4d4c8a
AK
9837 bgp_evpn_is_esi_valid(&attr->esi)) {
9838 route_vty_out_detail_es_info(vty, attr, json_path);
b5e140c8
AK
9839 }
9840
05864da7
DS
9841 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9842 * Int/Ext/Local, Atomic, best */
9843 if (json_paths)
9844 json_object_string_add(json_path, "origin",
9845 bgp_origin_long_str[attr->origin]);
9846 else
9847 vty_out(vty, " Origin %s",
9848 bgp_origin_long_str[attr->origin]);
9df8b37c 9849
05864da7 9850 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9851 if (json_paths)
05864da7 9852 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9853 else
05864da7
DS
9854 vty_out(vty, ", metric %u", attr->med);
9855 }
9df8b37c 9856
05864da7
DS
9857 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9858 if (json_paths)
0fbac0b4 9859 json_object_int_add(json_path, "locPrf",
05864da7
DS
9860 attr->local_pref);
9861 else
9862 vty_out(vty, ", localpref %u", attr->local_pref);
9863 }
9df8b37c 9864
05864da7
DS
9865 if (attr->weight != 0) {
9866 if (json_paths)
9867 json_object_int_add(json_path, "weight", attr->weight);
9868 else
9869 vty_out(vty, ", weight %u", attr->weight);
9870 }
9df8b37c 9871
05864da7
DS
9872 if (attr->tag != 0) {
9873 if (json_paths)
9874 json_object_int_add(json_path, "tag", attr->tag);
9875 else
9876 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9877 }
9df8b37c 9878
05864da7
DS
9879 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9880 if (json_paths)
9881 json_object_boolean_false_add(json_path, "valid");
9882 else
9883 vty_out(vty, ", invalid");
9884 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9885 if (json_paths)
9886 json_object_boolean_true_add(json_path, "valid");
9887 else
9888 vty_out(vty, ", valid");
9889 }
9df8b37c 9890
05864da7
DS
9891 if (path->peer != bgp->peer_self) {
9892 if (path->peer->as == path->peer->local_as) {
9893 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9894 if (json_paths)
9895 json_object_string_add(
9896 json_peer, "type",
9897 "confed-internal");
d62a17ae 9898 else
05864da7 9899 vty_out(vty, ", confed-internal");
d62a17ae 9900 } else {
05864da7
DS
9901 if (json_paths)
9902 json_object_string_add(
9903 json_peer, "type", "internal");
9904 else
9905 vty_out(vty, ", internal");
9df8b37c 9906 }
05864da7
DS
9907 } else {
9908 if (bgp_confederation_peers_check(bgp,
9909 path->peer->as)) {
9910 if (json_paths)
9911 json_object_string_add(
9912 json_peer, "type",
9913 "confed-external");
d62a17ae 9914 else
05864da7 9915 vty_out(vty, ", confed-external");
d62a17ae 9916 } else {
05864da7
DS
9917 if (json_paths)
9918 json_object_string_add(
9919 json_peer, "type", "external");
9920 else
9921 vty_out(vty, ", external");
d62a17ae 9922 }
9923 }
05864da7
DS
9924 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9925 if (json_paths) {
9926 json_object_boolean_true_add(json_path, "aggregated");
9927 json_object_boolean_true_add(json_path, "local");
9928 } else {
9929 vty_out(vty, ", aggregated, local");
9930 }
9931 } else if (path->type != ZEBRA_ROUTE_BGP) {
9932 if (json_paths)
9933 json_object_boolean_true_add(json_path, "sourced");
9934 else
9935 vty_out(vty, ", sourced");
9936 } else {
9937 if (json_paths) {
9938 json_object_boolean_true_add(json_path, "sourced");
9939 json_object_boolean_true_add(json_path, "local");
9940 } else {
9941 vty_out(vty, ", sourced, local");
d62a17ae 9942 }
05864da7 9943 }
718e3744 9944
05864da7 9945 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9946 if (json_paths)
05864da7
DS
9947 json_object_boolean_true_add(json_path,
9948 "atomicAggregate");
d62a17ae 9949 else
05864da7
DS
9950 vty_out(vty, ", atomic-aggregate");
9951 }
d62a17ae 9952
05864da7
DS
9953 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9954 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9955 && bgp_path_info_mpath_count(path))) {
9956 if (json_paths)
9957 json_object_boolean_true_add(json_path, "multipath");
9958 else
9959 vty_out(vty, ", multipath");
9960 }
50e05855 9961
05864da7
DS
9962 // Mark the bestpath(s)
9963 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9964 first_as = aspath_get_first_as(attr->aspath);
718e3744 9965
05864da7
DS
9966 if (json_paths) {
9967 if (!json_bestpath)
9968 json_bestpath = json_object_new_object();
9969 json_object_int_add(json_bestpath, "bestpathFromAs",
9970 first_as);
9971 } else {
9972 if (first_as)
9973 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9974 else
05864da7 9975 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9976 }
05864da7 9977 }
718e3744 9978
05864da7
DS
9979 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9980 if (json_paths) {
9981 if (!json_bestpath)
9982 json_bestpath = json_object_new_object();
9983 json_object_boolean_true_add(json_bestpath, "overall");
9984 json_object_string_add(
9985 json_bestpath, "selectionReason",
9986 bgp_path_selection_reason2str(bn->reason));
9987 } else {
9988 vty_out(vty, ", best");
9989 vty_out(vty, " (%s)",
9990 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9991 }
05864da7 9992 }
718e3744 9993
05864da7
DS
9994 if (json_bestpath)
9995 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9996
05864da7
DS
9997 if (!json_paths)
9998 vty_out(vty, "\n");
9999
10000 /* Line 4 display Community */
10001 if (attr->community) {
10002 if (json_paths) {
10003 if (!attr->community->json)
10004 community_str(attr->community, true);
10005 json_object_lock(attr->community->json);
10006 json_object_object_add(json_path, "community",
10007 attr->community->json);
10008 } else {
10009 vty_out(vty, " Community: %s\n",
10010 attr->community->str);
d62a17ae 10011 }
05864da7 10012 }
718e3744 10013
05864da7
DS
10014 /* Line 5 display Extended-community */
10015 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10016 if (json_paths) {
10017 json_ext_community = json_object_new_object();
10018 json_object_string_add(json_ext_community, "string",
10019 attr->ecommunity->str);
10020 json_object_object_add(json_path, "extendedCommunity",
10021 json_ext_community);
d62a17ae 10022 } else {
05864da7
DS
10023 vty_out(vty, " Extended Community: %s\n",
10024 attr->ecommunity->str);
d62a17ae 10025 }
05864da7 10026 }
718e3744 10027
05864da7
DS
10028 /* Line 6 display Large community */
10029 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10030 if (json_paths) {
10031 if (!attr->lcommunity->json)
10032 lcommunity_str(attr->lcommunity, true);
10033 json_object_lock(attr->lcommunity->json);
10034 json_object_object_add(json_path, "largeCommunity",
10035 attr->lcommunity->json);
10036 } else {
10037 vty_out(vty, " Large Community: %s\n",
10038 attr->lcommunity->str);
d62a17ae 10039 }
05864da7 10040 }
718e3744 10041
05864da7
DS
10042 /* Line 7 display Originator, Cluster-id */
10043 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10044 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10045 char buf[BUFSIZ] = {0};
10046
05864da7 10047 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10048 if (json_paths)
05864da7
DS
10049 json_object_string_add(
10050 json_path, "originatorId",
23d0a753
DA
10051 inet_ntop(AF_INET, &attr->originator_id,
10052 buf, sizeof(buf)));
d62a17ae 10053 else
23d0a753
DA
10054 vty_out(vty, " Originator: %pI4",
10055 &attr->originator_id);
d62a17ae 10056 }
856ca177 10057
05864da7
DS
10058 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
10059 int i;
d62a17ae 10060
10061 if (json_paths) {
05864da7
DS
10062 json_cluster_list = json_object_new_object();
10063 json_cluster_list_list =
10064 json_object_new_array();
10065
10066 for (i = 0; i < attr->cluster->length / 4;
10067 i++) {
10068 json_string = json_object_new_string(
23d0a753
DA
10069 inet_ntop(
10070 AF_INET,
10071 &attr->cluster->list[i],
10072 buf, sizeof(buf)));
05864da7
DS
10073 json_object_array_add(
10074 json_cluster_list_list,
10075 json_string);
10076 }
718e3744 10077
05864da7
DS
10078 /*
10079 * struct cluster_list does not have
10080 * "str" variable like aspath and community
10081 * do. Add this someday if someone asks
10082 * for it.
10083 * json_object_string_add(json_cluster_list,
10084 * "string", attr->cluster->str);
10085 */
10086 json_object_object_add(json_cluster_list,
10087 "list",
10088 json_cluster_list_list);
10089 json_object_object_add(json_path, "clusterList",
10090 json_cluster_list);
0dc8ee70 10091 } else {
05864da7
DS
10092 vty_out(vty, ", Cluster list: ");
10093
10094 for (i = 0; i < attr->cluster->length / 4;
10095 i++) {
23d0a753
DA
10096 vty_out(vty, "%pI4 ",
10097 &attr->cluster->list[i]);
05864da7 10098 }
0dc8ee70 10099 }
d62a17ae 10100 }
718e3744 10101
d62a17ae 10102 if (!json_paths)
10103 vty_out(vty, "\n");
05864da7 10104 }
d62a17ae 10105
05864da7 10106 if (path->extra && path->extra->damp_info)
a935f597 10107 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10108
05864da7
DS
10109 /* Remote Label */
10110 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10111 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10112 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10113
05864da7
DS
10114 if (json_paths)
10115 json_object_int_add(json_path, "remoteLabel", label);
10116 else
10117 vty_out(vty, " Remote label: %d\n", label);
10118 }
d62a17ae 10119
e496b420
HS
10120 /* Remote SID */
10121 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10122 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10123 if (json_paths)
10124 json_object_string_add(json_path, "remoteSid", buf);
10125 else
10126 vty_out(vty, " Remote SID: %s\n", buf);
10127 }
10128
05864da7
DS
10129 /* Label Index */
10130 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10131 if (json_paths)
10132 json_object_int_add(json_path, "labelIndex",
10133 attr->label_index);
10134 else
10135 vty_out(vty, " Label Index: %d\n",
10136 attr->label_index);
10137 }
d62a17ae 10138
05864da7
DS
10139 /* Line 8 display Addpath IDs */
10140 if (path->addpath_rx_id
10141 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10142 if (json_paths) {
10143 json_object_int_add(json_path, "addpathRxId",
10144 path->addpath_rx_id);
d62a17ae 10145
05864da7
DS
10146 /* Keep backwards compatibility with the old API
10147 * by putting TX All's ID in the old field
10148 */
10149 json_object_int_add(
10150 json_path, "addpathTxId",
10151 path->tx_addpath
10152 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10153
05864da7
DS
10154 /* ... but create a specific field for each
10155 * strategy
10156 */
10157 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10158 json_object_int_add(
10159 json_path,
10160 bgp_addpath_names(i)->id_json_name,
10161 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10162 }
05864da7
DS
10163 } else {
10164 vty_out(vty, " AddPath ID: RX %u, ",
10165 path->addpath_rx_id);
d62a17ae 10166
05864da7 10167 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10168 }
05864da7 10169 }
520d5d76 10170
05864da7
DS
10171 /* If we used addpath to TX a non-bestpath we need to display
10172 * "Advertised to" on a path-by-path basis
10173 */
10174 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10175 first = 1;
dcc68b5e 10176
05864da7
DS
10177 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10178 addpath_capable =
10179 bgp_addpath_encode_tx(peer, afi, safi);
10180 has_adj = bgp_adj_out_lookup(
10181 peer, path->net,
10182 bgp_addpath_id_for_peer(peer, afi, safi,
10183 &path->tx_addpath));
10184
10185 if ((addpath_capable && has_adj)
10186 || (!addpath_capable && has_adj
10187 && CHECK_FLAG(path->flags,
10188 BGP_PATH_SELECTED))) {
10189 if (json_path && !json_adv_to)
10190 json_adv_to = json_object_new_object();
dcc68b5e 10191
05864da7
DS
10192 route_vty_out_advertised_to(
10193 vty, peer, &first,
10194 " Advertised to:", json_adv_to);
d62a17ae 10195 }
10196 }
718e3744 10197
05864da7
DS
10198 if (json_path) {
10199 if (json_adv_to) {
10200 json_object_object_add(
10201 json_path, "advertisedTo", json_adv_to);
d62a17ae 10202 }
05864da7
DS
10203 } else {
10204 if (!first) {
10205 vty_out(vty, "\n");
d62a17ae 10206 }
10207 }
05864da7 10208 }
b05a1c8b 10209
05864da7
DS
10210 /* Line 9 display Uptime */
10211 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10212 if (json_paths) {
10213 json_last_update = json_object_new_object();
10214 json_object_int_add(json_last_update, "epoch", tbuf);
10215 json_object_string_add(json_last_update, "string",
10216 ctime(&tbuf));
10217 json_object_object_add(json_path, "lastUpdate",
10218 json_last_update);
10219 } else
10220 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10221
05864da7
DS
10222 /* Line 10 display PMSI tunnel attribute, if present */
10223 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
10224 const char *str =
10225 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
10226 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10227
05864da7
DS
10228 if (json_paths) {
10229 json_pmsi = json_object_new_object();
10230 json_object_string_add(json_pmsi, "tunnelType", str);
10231 json_object_int_add(json_pmsi, "label",
10232 label2vni(&attr->label));
10233 json_object_object_add(json_path, "pmsi", json_pmsi);
10234 } else
10235 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10236 str, label2vni(&attr->label));
d62a17ae 10237 }
f1aa5d8a 10238
d62a17ae 10239 /* We've constructed the json object for this path, add it to the json
10240 * array of paths
10241 */
10242 if (json_paths) {
10243 if (json_nexthop_global || json_nexthop_ll) {
10244 json_nexthops = json_object_new_array();
f1aa5d8a 10245
d62a17ae 10246 if (json_nexthop_global)
10247 json_object_array_add(json_nexthops,
10248 json_nexthop_global);
f1aa5d8a 10249
d62a17ae 10250 if (json_nexthop_ll)
10251 json_object_array_add(json_nexthops,
10252 json_nexthop_ll);
f1aa5d8a 10253
d62a17ae 10254 json_object_object_add(json_path, "nexthops",
10255 json_nexthops);
10256 }
10257
10258 json_object_object_add(json_path, "peer", json_peer);
10259 json_object_array_add(json_paths, json_path);
05864da7 10260 }
b366b518
BB
10261}
10262
96ade3ed 10263#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10264#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10265#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10266
d62a17ae 10267static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10268 const char *prefix_list_str, afi_t afi,
10269 safi_t safi, enum bgp_show_type type);
10270static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10271 const char *filter, afi_t afi, safi_t safi,
10272 enum bgp_show_type type);
10273static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10274 const char *rmap_str, afi_t afi, safi_t safi,
10275 enum bgp_show_type type);
10276static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10277 const char *com, int exact, afi_t afi,
10278 safi_t safi);
10279static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10280 const char *prefix, afi_t afi, safi_t safi,
10281 enum bgp_show_type type);
a4d82a8a 10282static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10283 afi_t afi, safi_t safi, enum bgp_show_type type,
10284 bool use_json);
7f323236
DW
10285static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10286 const char *comstr, int exact, afi_t afi,
96f3485c 10287 safi_t safi, uint8_t show_flags);
d62a17ae 10288
1ae44dfc
LB
10289
10290static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10291 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10292 void *output_arg, char *rd, int is_last,
10293 unsigned long *output_cum, unsigned long *total_cum,
10294 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10295{
40381db7 10296 struct bgp_path_info *pi;
9bcb3eef 10297 struct bgp_dest *dest;
d62a17ae 10298 int header = 1;
10299 int display;
1ae44dfc
LB
10300 unsigned long output_count = 0;
10301 unsigned long total_count = 0;
d62a17ae 10302 struct prefix *p;
d62a17ae 10303 json_object *json_paths = NULL;
10304 int first = 1;
96f3485c
MK
10305 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10306 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10307 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10308
1ae44dfc
LB
10309 if (output_cum && *output_cum != 0)
10310 header = 0;
10311
9386b588 10312 if (use_json && !*json_header_depth) {
96f3485c
MK
10313 if (all)
10314 *json_header_depth = 1;
10315 else {
10316 vty_out(vty, "{\n");
10317 *json_header_depth = 2;
10318 }
10319
d62a17ae 10320 vty_out(vty,
23d0a753
DA
10321 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10322 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10323 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10324 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10325 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10326 ? VRF_DEFAULT_NAME
10327 : bgp->name,
10328 table->version, &bgp->router_id,
01eced22 10329 bgp->default_local_pref, bgp->as);
9386b588 10330 if (rd) {
445c2480 10331 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10332 ++*json_header_depth;
10333 }
d62a17ae 10334 }
718e3744 10335
445c2480
DS
10336 if (use_json && rd) {
10337 vty_out(vty, " \"%s\" : { ", rd);
10338 }
10339
d62a17ae 10340 /* Start processing of routes. */
9bcb3eef
DS
10341 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10342 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10343
9bcb3eef 10344 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10345 if (pi == NULL)
98ce9a06 10346 continue;
d62a17ae 10347
98ce9a06 10348 display = 0;
98ce9a06
DS
10349 if (use_json)
10350 json_paths = json_object_new_array();
10351 else
10352 json_paths = NULL;
d62a17ae 10353
6f94b685 10354 for (; pi; pi = pi->next) {
98ce9a06
DS
10355 total_count++;
10356 if (type == bgp_show_type_flap_statistics
10357 || type == bgp_show_type_flap_neighbor
10358 || type == bgp_show_type_dampend_paths
10359 || type == bgp_show_type_damp_neighbor) {
40381db7 10360 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10361 continue;
10362 }
10363 if (type == bgp_show_type_regexp) {
10364 regex_t *regex = output_arg;
d62a17ae 10365
40381db7 10366 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10367 == REG_NOMATCH)
10368 continue;
10369 }
10370 if (type == bgp_show_type_prefix_list) {
10371 struct prefix_list *plist = output_arg;
d62a17ae 10372
9bcb3eef 10373 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10374 != PREFIX_PERMIT)
10375 continue;
10376 }
10377 if (type == bgp_show_type_filter_list) {
10378 struct as_list *as_list = output_arg;
d62a17ae 10379
40381db7 10380 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10381 != AS_FILTER_PERMIT)
10382 continue;
10383 }
10384 if (type == bgp_show_type_route_map) {
10385 struct route_map *rmap = output_arg;
9b6d8fcf 10386 struct bgp_path_info path;
98ce9a06 10387 struct attr dummy_attr;
b68885f9 10388 route_map_result_t ret;
d62a17ae 10389
6f4f49b2 10390 dummy_attr = *pi->attr;
d62a17ae 10391
40381db7 10392 path.peer = pi->peer;
9b6d8fcf 10393 path.attr = &dummy_attr;
d62a17ae 10394
9bcb3eef 10395 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 10396 &path);
98ce9a06
DS
10397 if (ret == RMAP_DENYMATCH)
10398 continue;
10399 }
10400 if (type == bgp_show_type_neighbor
10401 || type == bgp_show_type_flap_neighbor
10402 || type == bgp_show_type_damp_neighbor) {
10403 union sockunion *su = output_arg;
10404
40381db7
DS
10405 if (pi->peer == NULL
10406 || pi->peer->su_remote == NULL
10407 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10408 continue;
10409 }
10410 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10411 uint32_t destination;
d62a17ae 10412
9bcb3eef 10413 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10414 if (IN_CLASSC(destination)
9bcb3eef 10415 && dest_p->prefixlen == 24)
98ce9a06
DS
10416 continue;
10417 if (IN_CLASSB(destination)
9bcb3eef 10418 && dest_p->prefixlen == 16)
98ce9a06
DS
10419 continue;
10420 if (IN_CLASSA(destination)
9bcb3eef 10421 && dest_p->prefixlen == 8)
98ce9a06
DS
10422 continue;
10423 }
10424 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10425 p = output_arg;
9bcb3eef 10426 if (!prefix_match(p, dest_p))
98ce9a06
DS
10427 continue;
10428 }
10429 if (type == bgp_show_type_community_all) {
40381db7 10430 if (!pi->attr->community)
98ce9a06
DS
10431 continue;
10432 }
10433 if (type == bgp_show_type_community) {
10434 struct community *com = output_arg;
d62a17ae 10435
40381db7
DS
10436 if (!pi->attr->community
10437 || !community_match(pi->attr->community,
98ce9a06
DS
10438 com))
10439 continue;
10440 }
10441 if (type == bgp_show_type_community_exact) {
10442 struct community *com = output_arg;
d62a17ae 10443
40381db7
DS
10444 if (!pi->attr->community
10445 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10446 continue;
10447 }
10448 if (type == bgp_show_type_community_list) {
10449 struct community_list *list = output_arg;
d62a17ae 10450
40381db7 10451 if (!community_list_match(pi->attr->community,
a4d82a8a 10452 list))
98ce9a06
DS
10453 continue;
10454 }
a4d82a8a 10455 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10456 struct community_list *list = output_arg;
d62a17ae 10457
98ce9a06 10458 if (!community_list_exact_match(
40381db7 10459 pi->attr->community, list))
98ce9a06
DS
10460 continue;
10461 }
10462 if (type == bgp_show_type_lcommunity) {
10463 struct lcommunity *lcom = output_arg;
d62a17ae 10464
40381db7
DS
10465 if (!pi->attr->lcommunity
10466 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10467 lcom))
10468 continue;
10469 }
36a206db 10470
10471 if (type == bgp_show_type_lcommunity_exact) {
10472 struct lcommunity *lcom = output_arg;
10473
10474 if (!pi->attr->lcommunity
10475 || !lcommunity_cmp(pi->attr->lcommunity,
10476 lcom))
10477 continue;
10478 }
98ce9a06
DS
10479 if (type == bgp_show_type_lcommunity_list) {
10480 struct community_list *list = output_arg;
d62a17ae 10481
40381db7 10482 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10483 list))
98ce9a06
DS
10484 continue;
10485 }
36a206db 10486 if (type
10487 == bgp_show_type_lcommunity_list_exact) {
10488 struct community_list *list = output_arg;
10489
10490 if (!lcommunity_list_exact_match(
10491 pi->attr->lcommunity, list))
10492 continue;
10493 }
98ce9a06 10494 if (type == bgp_show_type_lcommunity_all) {
40381db7 10495 if (!pi->attr->lcommunity)
98ce9a06
DS
10496 continue;
10497 }
10498 if (type == bgp_show_type_dampend_paths
10499 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10500 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10501 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10502 continue;
10503 }
10504
10505 if (!use_json && header) {
23d0a753
DA
10506 vty_out(vty,
10507 "BGP table version is %" PRIu64
10508 ", local router ID is %pI4, vrf id ",
10509 table->version, &bgp->router_id);
9df8b37c
PZ
10510 if (bgp->vrf_id == VRF_UNKNOWN)
10511 vty_out(vty, "%s", VRFID_NONE_STR);
10512 else
10513 vty_out(vty, "%u", bgp->vrf_id);
10514 vty_out(vty, "\n");
01eced22
AD
10515 vty_out(vty, "Default local pref %u, ",
10516 bgp->default_local_pref);
10517 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10518 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10519 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10520 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10521 if (type == bgp_show_type_dampend_paths
10522 || type == bgp_show_type_damp_neighbor)
98ce9a06 10523 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10524 else if (type == bgp_show_type_flap_statistics
10525 || type == bgp_show_type_flap_neighbor)
98ce9a06 10526 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10527 else
ae248832
MK
10528 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10529 : BGP_SHOW_HEADER));
98ce9a06 10530 header = 0;
d62a17ae 10531 }
98ce9a06
DS
10532 if (rd != NULL && !display && !output_count) {
10533 if (!use_json)
10534 vty_out(vty,
10535 "Route Distinguisher: %s\n",
10536 rd);
d62a17ae 10537 }
98ce9a06
DS
10538 if (type == bgp_show_type_dampend_paths
10539 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10540 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10541 AFI_IP, safi, use_json,
10542 json_paths);
98ce9a06
DS
10543 else if (type == bgp_show_type_flap_statistics
10544 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10545 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10546 AFI_IP, safi, use_json,
10547 json_paths);
98ce9a06 10548 else
9bcb3eef 10549 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10550 json_paths, wide);
98ce9a06 10551 display++;
d62a17ae 10552 }
10553
98ce9a06
DS
10554 if (display) {
10555 output_count++;
10556 if (!use_json)
10557 continue;
10558
625d2931 10559 /* encode prefix */
9bcb3eef 10560 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10561 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10562
1840384b 10563
b54892e0
DS
10564 bgp_fs_nlri_get_string(
10565 (unsigned char *)
9bcb3eef
DS
10566 dest_p->u.prefix_flowspec.ptr,
10567 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10568 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10569 family2afi(dest_p->u
10570 .prefix_flowspec.family));
625d2931 10571 if (first)
b54892e0 10572 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10573 dest_p->u.prefix_flowspec
b54892e0 10574 .prefixlen);
625d2931 10575 else
b54892e0 10576 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10577 dest_p->u.prefix_flowspec
b54892e0 10578 .prefixlen);
625d2931 10579 } else {
625d2931 10580 if (first)
1b78780b 10581 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10582 else
1b78780b 10583 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10584 }
98ce9a06 10585 vty_out(vty, "%s",
f4ec52f7
DA
10586 json_object_to_json_string_ext(
10587 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10588 json_object_free(json_paths);
449feb8e 10589 json_paths = NULL;
98ce9a06 10590 first = 0;
1f83ed02
DS
10591 } else
10592 json_object_free(json_paths);
98ce9a06
DS
10593 }
10594
1ae44dfc
LB
10595 if (output_cum) {
10596 output_count += *output_cum;
10597 *output_cum = output_count;
10598 }
10599 if (total_cum) {
10600 total_count += *total_cum;
10601 *total_cum = total_count;
10602 }
d62a17ae 10603 if (use_json) {
9386b588 10604 if (rd) {
a4d82a8a 10605 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10606 }
10607 if (is_last) {
a4d82a8a
PZ
10608 unsigned long i;
10609 for (i = 0; i < *json_header_depth; ++i)
10610 vty_out(vty, " } ");
96f3485c
MK
10611 if (!all)
10612 vty_out(vty, "\n");
9386b588 10613 }
d62a17ae 10614 } else {
1ae44dfc
LB
10615 if (is_last) {
10616 /* No route is displayed */
10617 if (output_count == 0) {
10618 if (type == bgp_show_type_normal)
10619 vty_out(vty,
10620 "No BGP prefixes displayed, %ld exist\n",
10621 total_count);
10622 } else
d62a17ae 10623 vty_out(vty,
1ae44dfc
LB
10624 "\nDisplayed %ld routes and %ld total paths\n",
10625 output_count, total_count);
10626 }
d62a17ae 10627 }
718e3744 10628
d62a17ae 10629 return CMD_SUCCESS;
718e3744 10630}
10631
1ae44dfc
LB
10632int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10633 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10634 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10635{
9bcb3eef 10636 struct bgp_dest *dest, *next;
1ae44dfc
LB
10637 unsigned long output_cum = 0;
10638 unsigned long total_cum = 0;
9386b588 10639 unsigned long json_header_depth = 0;
67009e22 10640 struct bgp_table *itable;
0136788c 10641 bool show_msg;
96f3485c 10642 uint8_t show_flags = 0;
0136788c
LB
10643
10644 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10645
96f3485c
MK
10646 if (use_json)
10647 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10648
9bcb3eef
DS
10649 for (dest = bgp_table_top(table); dest; dest = next) {
10650 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10651
9bcb3eef
DS
10652 next = bgp_route_next(dest);
10653 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10654 continue;
67009e22 10655
9bcb3eef 10656 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10657 if (itable != NULL) {
1ae44dfc 10658 struct prefix_rd prd;
06b9f471 10659 char rd[RD_ADDRSTRLEN];
1ae44dfc 10660
9bcb3eef 10661 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10662 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10663 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10664 rd, next == NULL, &output_cum,
10665 &total_cum, &json_header_depth,
10666 show_flags);
0136788c
LB
10667 if (next == NULL)
10668 show_msg = false;
1ae44dfc
LB
10669 }
10670 }
0136788c
LB
10671 if (show_msg) {
10672 if (output_cum == 0)
10673 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10674 total_cum);
10675 else
10676 vty_out(vty,
10677 "\nDisplayed %ld routes and %ld total paths\n",
10678 output_cum, total_cum);
10679 }
1ae44dfc
LB
10680 return CMD_SUCCESS;
10681}
d62a17ae 10682static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10683 enum bgp_show_type type, void *output_arg,
10684 uint8_t show_flags)
fee0f4c6 10685{
d62a17ae 10686 struct bgp_table *table;
9386b588 10687 unsigned long json_header_depth = 0;
96f3485c 10688 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10689
d62a17ae 10690 if (bgp == NULL) {
10691 bgp = bgp_get_default();
10692 }
fee0f4c6 10693
d62a17ae 10694 if (bgp == NULL) {
10695 if (!use_json)
10696 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10697 else
10698 vty_out(vty, "{}\n");
d62a17ae 10699 return CMD_WARNING;
10700 }
4dd6177e 10701
1ae44dfc 10702 table = bgp->rib[afi][safi];
d62a17ae 10703 /* use MPLS and ENCAP specific shows until they are merged */
10704 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10705 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10706 output_arg, use_json);
d62a17ae 10707 }
dba3c1d3
PG
10708
10709 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10710 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10711 output_arg, use_json,
10712 1, NULL, NULL);
10713 }
d62a17ae 10714 /* labeled-unicast routes live in the unicast table */
10715 else if (safi == SAFI_LABELED_UNICAST)
10716 safi = SAFI_UNICAST;
fee0f4c6 10717
96f3485c
MK
10718 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10719 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10720}
10721
d62a17ae 10722static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10723 safi_t safi, uint8_t show_flags)
f186de26 10724{
d62a17ae 10725 struct listnode *node, *nnode;
10726 struct bgp *bgp;
10727 int is_first = 1;
9f049418 10728 bool route_output = false;
96f3485c 10729 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10730
d62a17ae 10731 if (use_json)
10732 vty_out(vty, "{\n");
9f689658 10733
d62a17ae 10734 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10735 route_output = true;
d62a17ae 10736 if (use_json) {
10737 if (!is_first)
10738 vty_out(vty, ",\n");
10739 else
10740 is_first = 0;
10741
10742 vty_out(vty, "\"%s\":",
10743 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10744 ? VRF_DEFAULT_NAME
d62a17ae 10745 : bgp->name);
10746 } else {
10747 vty_out(vty, "\nInstance %s:\n",
10748 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10749 ? VRF_DEFAULT_NAME
d62a17ae 10750 : bgp->name);
10751 }
10752 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10753 show_flags);
d62a17ae 10754 }
9f689658 10755
d62a17ae 10756 if (use_json)
10757 vty_out(vty, "}\n");
9f049418
DS
10758 else if (!route_output)
10759 vty_out(vty, "%% BGP instance not found\n");
f186de26 10760}
10761
718e3744 10762/* Header of detailed BGP route information */
d62a17ae 10763void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10764 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10765 afi_t afi, safi_t safi, json_object *json)
10766{
40381db7 10767 struct bgp_path_info *pi;
b54892e0 10768 const struct prefix *p;
d62a17ae 10769 struct peer *peer;
10770 struct listnode *node, *nnode;
06b9f471 10771 char buf1[RD_ADDRSTRLEN];
0291c246 10772 char prefix_str[BUFSIZ];
d62a17ae 10773 int count = 0;
10774 int best = 0;
10775 int suppress = 0;
c5f1e1b2
C
10776 int accept_own = 0;
10777 int route_filter_translated_v4 = 0;
10778 int route_filter_v4 = 0;
10779 int route_filter_translated_v6 = 0;
10780 int route_filter_v6 = 0;
10781 int llgr_stale = 0;
10782 int no_llgr = 0;
10783 int accept_own_nexthop = 0;
10784 int blackhole = 0;
d62a17ae 10785 int no_export = 0;
10786 int no_advertise = 0;
10787 int local_as = 0;
c5f1e1b2 10788 int no_peer = 0;
d62a17ae 10789 int first = 1;
10790 int has_valid_label = 0;
10791 mpls_label_t label = 0;
10792 json_object *json_adv_to = NULL;
9bedbb1e 10793
9bcb3eef
DS
10794 p = bgp_dest_get_prefix(dest);
10795 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10796
10797 if (has_valid_label)
9bcb3eef 10798 label = label_pton(&dest->local_label);
d62a17ae 10799
44c69747 10800 if (safi == SAFI_EVPN) {
d62a17ae 10801
44c69747 10802 if (!json) {
2dbe669b 10803 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 10804 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 10805 : "",
2dbe669b 10806 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
10807 } else {
10808 json_object_string_add(json, "rd",
10809 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10810 "");
10811 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10812 }
10813 } else {
10814 if (!json) {
8228a9a7 10815 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 10816 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
10817 ? prefix_rd2str(prd, buf1,
10818 sizeof(buf1))
10819 : ""),
10820 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 10821
44c69747
LK
10822 } else
10823 json_object_string_add(json, "prefix",
10824 prefix2str(p, prefix_str, sizeof(prefix_str)));
10825 }
10826
10827 if (has_valid_label) {
10828 if (json)
10829 json_object_int_add(json, "localLabel", label);
10830 else
d62a17ae 10831 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10832 }
10833
10834 if (!json)
d62a17ae 10835 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10836 vty_out(vty, "not allocated\n");
718e3744 10837
9bcb3eef 10838 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10839 count++;
40381db7 10840 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10841 best = count;
4056a5f6 10842 if (bgp_path_suppressed(pi))
d62a17ae 10843 suppress = 1;
cee9c031 10844
40381db7 10845 if (pi->attr->community == NULL)
cee9c031
QY
10846 continue;
10847
10848 no_advertise += community_include(
40381db7
DS
10849 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10850 no_export += community_include(pi->attr->community,
cee9c031 10851 COMMUNITY_NO_EXPORT);
40381db7 10852 local_as += community_include(pi->attr->community,
cee9c031 10853 COMMUNITY_LOCAL_AS);
40381db7 10854 accept_own += community_include(pi->attr->community,
cee9c031
QY
10855 COMMUNITY_ACCEPT_OWN);
10856 route_filter_translated_v4 += community_include(
40381db7 10857 pi->attr->community,
cee9c031
QY
10858 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10859 route_filter_translated_v6 += community_include(
40381db7 10860 pi->attr->community,
cee9c031
QY
10861 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10862 route_filter_v4 += community_include(
40381db7 10863 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10864 route_filter_v6 += community_include(
40381db7
DS
10865 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10866 llgr_stale += community_include(pi->attr->community,
cee9c031 10867 COMMUNITY_LLGR_STALE);
40381db7 10868 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10869 COMMUNITY_NO_LLGR);
10870 accept_own_nexthop +=
40381db7 10871 community_include(pi->attr->community,
cee9c031 10872 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10873 blackhole += community_include(pi->attr->community,
cee9c031 10874 COMMUNITY_BLACKHOLE);
40381db7 10875 no_peer += community_include(pi->attr->community,
cee9c031 10876 COMMUNITY_NO_PEER);
d62a17ae 10877 }
718e3744 10878 }
718e3744 10879
d62a17ae 10880 if (!json) {
10881 vty_out(vty, "Paths: (%d available", count);
10882 if (best) {
10883 vty_out(vty, ", best #%d", best);
b84060bb
PG
10884 if (safi == SAFI_UNICAST) {
10885 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10886 vty_out(vty, ", table %s",
10887 VRF_DEFAULT_NAME);
10888 else
10889 vty_out(vty, ", vrf %s",
10890 bgp->name);
10891 }
d62a17ae 10892 } else
10893 vty_out(vty, ", no best path");
10894
c5f1e1b2
C
10895 if (accept_own)
10896 vty_out(vty,
10897 ", accept own local route exported and imported in different VRF");
10898 else if (route_filter_translated_v4)
10899 vty_out(vty,
10900 ", mark translated RTs for VPNv4 route filtering");
10901 else if (route_filter_v4)
10902 vty_out(vty,
10903 ", attach RT as-is for VPNv4 route filtering");
10904 else if (route_filter_translated_v6)
10905 vty_out(vty,
10906 ", mark translated RTs for VPNv6 route filtering");
10907 else if (route_filter_v6)
10908 vty_out(vty,
10909 ", attach RT as-is for VPNv6 route filtering");
10910 else if (llgr_stale)
10911 vty_out(vty,
10912 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10913 else if (no_llgr)
10914 vty_out(vty,
10915 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10916 else if (accept_own_nexthop)
10917 vty_out(vty,
10918 ", accept local nexthop");
10919 else if (blackhole)
10920 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10921 else if (no_export)
10922 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10923 else if (no_advertise)
10924 vty_out(vty, ", not advertised to any peer");
d62a17ae 10925 else if (local_as)
10926 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10927 else if (no_peer)
10928 vty_out(vty,
10929 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10930
10931 if (suppress)
10932 vty_out(vty,
10933 ", Advertisements suppressed by an aggregate.");
10934 vty_out(vty, ")\n");
10935 }
718e3744 10936
d62a17ae 10937 /* If we are not using addpath then we can display Advertised to and
10938 * that will
10939 * show what peers we advertised the bestpath to. If we are using
10940 * addpath
10941 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10942 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10943 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10944 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10945 if (json && !json_adv_to)
10946 json_adv_to = json_object_new_object();
10947
10948 route_vty_out_advertised_to(
10949 vty, peer, &first,
10950 " Advertised to non peer-group peers:\n ",
10951 json_adv_to);
10952 }
10953 }
10954
10955 if (json) {
10956 if (json_adv_to) {
10957 json_object_object_add(json, "advertisedTo",
10958 json_adv_to);
10959 }
10960 } else {
10961 if (first)
10962 vty_out(vty, " Not advertised to any peer");
10963 vty_out(vty, "\n");
10964 }
10965 }
718e3744 10966}
10967
44c69747 10968static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10969 struct bgp_dest *bgp_node, struct vty *vty,
10970 struct bgp *bgp, afi_t afi, safi_t safi,
10971 json_object *json, enum bgp_path_type pathtype,
10972 int *display)
44c69747
LK
10973{
10974 struct bgp_path_info *pi;
10975 int header = 1;
10976 char rdbuf[RD_ADDRSTRLEN];
10977 json_object *json_header = NULL;
10978 json_object *json_paths = NULL;
10979
9bcb3eef 10980 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10981
10982 if (json && !json_paths) {
10983 /* Instantiate json_paths only if path is valid */
10984 json_paths = json_object_new_array();
10985 if (pfx_rd) {
10986 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10987 json_header = json_object_new_object();
10988 } else
10989 json_header = json;
10990 }
10991
10992 if (header) {
10993 route_vty_out_detail_header(
10994 vty, bgp, bgp_node, pfx_rd,
10995 AFI_IP, safi, json_header);
10996 header = 0;
10997 }
10998 (*display)++;
10999
11000 if (pathtype == BGP_PATH_SHOW_ALL
11001 || (pathtype == BGP_PATH_SHOW_BESTPATH
11002 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11003 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11004 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11005 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11006 route_vty_out_detail(vty, bgp, bgp_node,
11007 pi, AFI_IP, safi,
11008 json_paths);
11009 }
11010
11011 if (json && json_paths) {
11012 json_object_object_add(json_header, "paths", json_paths);
11013
11014 if (pfx_rd)
11015 json_object_object_add(json, rdbuf, json_header);
11016 }
11017}
11018
718e3744 11019/* Display specified route of BGP table. */
d62a17ae 11020static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11021 struct bgp_table *rib, const char *ip_str,
11022 afi_t afi, safi_t safi,
11023 struct prefix_rd *prd, int prefix_check,
9f049418 11024 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11025{
11026 int ret;
d62a17ae 11027 int display = 0;
11028 struct prefix match;
9bcb3eef
DS
11029 struct bgp_dest *dest;
11030 struct bgp_dest *rm;
d62a17ae 11031 struct bgp_table *table;
11032 json_object *json = NULL;
11033 json_object *json_paths = NULL;
11034
11035 /* Check IP address argument. */
11036 ret = str2prefix(ip_str, &match);
11037 if (!ret) {
11038 vty_out(vty, "address is malformed\n");
11039 return CMD_WARNING;
11040 }
718e3744 11041
d62a17ae 11042 match.family = afi2family(afi);
b05a1c8b 11043
44c69747 11044 if (use_json)
d62a17ae 11045 json = json_object_new_object();
718e3744 11046
44c69747 11047 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11048 for (dest = bgp_table_top(rib); dest;
11049 dest = bgp_route_next(dest)) {
11050 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11051
9bcb3eef 11052 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11053 continue;
9bcb3eef 11054 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11055 if (!table)
ea47320b 11056 continue;
d62a17ae 11057
ea47320b
DL
11058 if ((rm = bgp_node_match(table, &match)) == NULL)
11059 continue;
d62a17ae 11060
9bcb3eef 11061 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11062 if (prefix_check
b54892e0 11063 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11064 bgp_dest_unlock_node(rm);
ea47320b
DL
11065 continue;
11066 }
d62a17ae 11067
9bcb3eef 11068 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11069 bgp, afi, safi, json, pathtype,
11070 &display);
44c69747 11071
9bcb3eef 11072 bgp_dest_unlock_node(rm);
44c69747
LK
11073 }
11074 } else if (safi == SAFI_EVPN) {
9bcb3eef 11075 struct bgp_dest *longest_pfx;
cded3b72 11076 bool is_exact_pfxlen_match = false;
44c69747 11077
9bcb3eef
DS
11078 for (dest = bgp_table_top(rib); dest;
11079 dest = bgp_route_next(dest)) {
11080 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11081
9bcb3eef 11082 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11083 continue;
9bcb3eef 11084 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11085 if (!table)
11086 continue;
11087
11088 longest_pfx = NULL;
cded3b72 11089 is_exact_pfxlen_match = false;
44c69747
LK
11090 /*
11091 * Search through all the prefixes for a match. The
11092 * pfx's are enumerated in ascending order of pfxlens.
11093 * So, the last pfx match is the longest match. Set
11094 * is_exact_pfxlen_match when we get exact pfxlen match
11095 */
11096 for (rm = bgp_table_top(table); rm;
11097 rm = bgp_route_next(rm)) {
b54892e0 11098 const struct prefix *rm_p =
9bcb3eef 11099 bgp_dest_get_prefix(rm);
44c69747
LK
11100 /*
11101 * Get prefixlen of the ip-prefix within type5
11102 * evpn route
11103 */
b54892e0
DS
11104 if (evpn_type5_prefix_match(rm_p, &match)
11105 && rm->info) {
44c69747
LK
11106 longest_pfx = rm;
11107 int type5_pfxlen =
b54892e0
DS
11108 bgp_evpn_get_type5_prefixlen(
11109 rm_p);
44c69747 11110 if (type5_pfxlen == match.prefixlen) {
cded3b72 11111 is_exact_pfxlen_match = true;
9bcb3eef 11112 bgp_dest_unlock_node(rm);
44c69747
LK
11113 break;
11114 }
d62a17ae 11115 }
11116 }
ea47320b 11117
44c69747
LK
11118 if (!longest_pfx)
11119 continue;
11120
11121 if (prefix_check && !is_exact_pfxlen_match)
11122 continue;
11123
11124 rm = longest_pfx;
9bcb3eef 11125 bgp_dest_lock_node(rm);
44c69747 11126
9bcb3eef 11127 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11128 bgp, afi, safi, json, pathtype,
11129 &display);
44c69747 11130
9bcb3eef 11131 bgp_dest_unlock_node(rm);
d62a17ae 11132 }
98a9dbc7 11133 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11134 if (use_json)
11135 json_paths = json_object_new_array();
11136
63a0b7a9
PG
11137 display = bgp_flowspec_display_match_per_ip(afi, rib,
11138 &match, prefix_check,
11139 vty,
11140 use_json,
11141 json_paths);
44c69747
LK
11142 if (use_json && display)
11143 json_object_object_add(json, "paths", json_paths);
d62a17ae 11144 } else {
9bcb3eef
DS
11145 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11146 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11147 if (!prefix_check
9bcb3eef
DS
11148 || dest_p->prefixlen == match.prefixlen) {
11149 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11150 safi, json, pathtype,
11151 &display);
d62a17ae 11152 }
11153
9bcb3eef 11154 bgp_dest_unlock_node(dest);
d62a17ae 11155 }
11156 }
e5eee9af 11157
d62a17ae 11158 if (use_json) {
996c9314 11159 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11160 json, JSON_C_TO_STRING_PRETTY |
11161 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11162 json_object_free(json);
11163 } else {
11164 if (!display) {
11165 vty_out(vty, "%% Network not in table\n");
11166 return CMD_WARNING;
11167 }
11168 }
b05a1c8b 11169
d62a17ae 11170 return CMD_SUCCESS;
718e3744 11171}
11172
fee0f4c6 11173/* Display specified route of Main RIB */
d62a17ae 11174static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11175 afi_t afi, safi_t safi, struct prefix_rd *prd,
11176 int prefix_check, enum bgp_path_type pathtype,
9f049418 11177 bool use_json)
d62a17ae 11178{
9b86009a 11179 if (!bgp) {
d62a17ae 11180 bgp = bgp_get_default();
9b86009a
RW
11181 if (!bgp) {
11182 if (!use_json)
11183 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11184 else
11185 vty_out(vty, "{}\n");
9b86009a
RW
11186 return CMD_WARNING;
11187 }
11188 }
d62a17ae 11189
11190 /* labeled-unicast routes live in the unicast table */
11191 if (safi == SAFI_LABELED_UNICAST)
11192 safi = SAFI_UNICAST;
11193
11194 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11195 afi, safi, prd, prefix_check, pathtype,
11196 use_json);
11197}
11198
11199static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11200 struct cmd_token **argv, bool exact, afi_t afi,
11201 safi_t safi, bool uj)
d62a17ae 11202{
11203 struct lcommunity *lcom;
11204 struct buffer *b;
11205 int i;
11206 char *str;
11207 int first = 0;
96f3485c
MK
11208 uint8_t show_flags = 0;
11209
11210 if (uj)
11211 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11212
11213 b = buffer_new(1024);
11214 for (i = 0; i < argc; i++) {
11215 if (first)
11216 buffer_putc(b, ' ');
11217 else {
11218 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11219 first = 1;
11220 buffer_putstr(b, argv[i]->arg);
11221 }
11222 }
11223 }
11224 buffer_putc(b, '\0');
57d187bc 11225
d62a17ae 11226 str = buffer_getstr(b);
11227 buffer_free(b);
57d187bc 11228
d62a17ae 11229 lcom = lcommunity_str2com(str);
11230 XFREE(MTYPE_TMP, str);
11231 if (!lcom) {
11232 vty_out(vty, "%% Large-community malformed\n");
11233 return CMD_WARNING;
11234 }
57d187bc 11235
36a206db 11236 return bgp_show(vty, bgp, afi, safi,
11237 (exact ? bgp_show_type_lcommunity_exact
ae248832 11238 : bgp_show_type_lcommunity),
96f3485c 11239 lcom, show_flags);
57d187bc
JS
11240}
11241
d62a17ae 11242static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11243 const char *lcom, bool exact, afi_t afi,
11244 safi_t safi, bool uj)
57d187bc 11245{
d62a17ae 11246 struct community_list *list;
96f3485c
MK
11247 uint8_t show_flags = 0;
11248
11249 if (uj)
11250 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11251
57d187bc 11252
e237b0d2 11253 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11254 LARGE_COMMUNITY_LIST_MASTER);
11255 if (list == NULL) {
11256 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11257 lcom);
11258 return CMD_WARNING;
11259 }
57d187bc 11260
36a206db 11261 return bgp_show(vty, bgp, afi, safi,
11262 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11263 : bgp_show_type_lcommunity_list),
96f3485c 11264 list, show_flags);
fee0f4c6 11265}
11266
52951b63
DS
11267DEFUN (show_ip_bgp_large_community_list,
11268 show_ip_bgp_large_community_list_cmd,
36a206db 11269 "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
11270 SHOW_STR
11271 IP_STR
11272 BGP_STR
11273 BGP_INSTANCE_HELP_STR
9bedbb1e 11274 BGP_AFI_HELP_STR
4dd6177e 11275 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11276 "Display routes matching the large-community-list\n"
11277 "large-community-list number\n"
11278 "large-community-list name\n"
36a206db 11279 "Exact match of the large-communities\n"
52951b63
DS
11280 JSON_STR)
11281{
d62a17ae 11282 afi_t afi = AFI_IP6;
11283 safi_t safi = SAFI_UNICAST;
11284 int idx = 0;
36a206db 11285 bool exact_match = 0;
4d678463 11286 struct bgp *bgp = NULL;
9f049418 11287 bool uj = use_json(argc, argv);
d62a17ae 11288
4d678463
KA
11289 if (uj)
11290 argc--;
11291
11292 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11293 &bgp, uj);
11294 if (!idx)
11295 return CMD_WARNING;
d62a17ae 11296
11297 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11298
11299 const char *clist_number_or_name = argv[++idx]->arg;
11300
11301 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11302 exact_match = 1;
11303
11304 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11305 exact_match, afi, safi, uj);
52951b63
DS
11306}
11307DEFUN (show_ip_bgp_large_community,
11308 show_ip_bgp_large_community_cmd,
36a206db 11309 "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
11310 SHOW_STR
11311 IP_STR
11312 BGP_STR
11313 BGP_INSTANCE_HELP_STR
9bedbb1e 11314 BGP_AFI_HELP_STR
4dd6177e 11315 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11316 "Display routes matching the large-communities\n"
11317 "List of large-community numbers\n"
36a206db 11318 "Exact match of the large-communities\n"
52951b63
DS
11319 JSON_STR)
11320{
d62a17ae 11321 afi_t afi = AFI_IP6;
11322 safi_t safi = SAFI_UNICAST;
11323 int idx = 0;
36a206db 11324 bool exact_match = 0;
4d678463 11325 struct bgp *bgp = NULL;
9f049418 11326 bool uj = use_json(argc, argv);
96f3485c 11327 uint8_t show_flags = 0;
d62a17ae 11328
96f3485c
MK
11329 if (uj) {
11330 argc--;
11331 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11332 }
4d678463 11333
96f3485c
MK
11334 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11335 &bgp, uj);
11336 if (!idx)
11337 return CMD_WARNING;
d62a17ae 11338
36a206db 11339 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11340 if (argv_find(argv, argc, "exact-match", &idx))
11341 exact_match = 1;
11342 return bgp_show_lcommunity(vty, bgp, argc, argv,
11343 exact_match, afi, safi, uj);
11344 } else
d62a17ae 11345 return bgp_show(vty, bgp, afi, safi,
96f3485c 11346 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11347}
11348
71f1613a
DA
11349static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11350 safi_t safi, struct json_object *json_array);
d62a17ae 11351static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11352 safi_t safi, struct json_object *json);
e01ca200 11353
7b2ff250 11354
9ab0cf58
PG
11355DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11356 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11357 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11358 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11359{
11360 bool uj = use_json(argc, argv);
11361 struct bgp *bgp = NULL;
ec76a1d1
DA
11362 safi_t safi = SAFI_UNICAST;
11363 afi_t afi = AFI_IP6;
4265b261 11364 int idx = 0;
6c9d22e2
PG
11365 struct json_object *json_all = NULL;
11366 struct json_object *json_afi_safi = NULL;
4265b261
PG
11367
11368 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11369 &bgp, false);
71f1613a 11370 if (!idx)
4265b261 11371 return CMD_WARNING;
6c9d22e2 11372
4265b261 11373 if (uj)
6c9d22e2 11374 json_all = json_object_new_object();
4265b261 11375
9ab0cf58
PG
11376 FOREACH_AFI_SAFI (afi, safi) {
11377 /*
11378 * So limit output to those afi/safi pairs that
11379 * actually have something interesting in them
11380 */
11381 if (strmatch(get_afi_safi_str(afi, safi, true),
11382 "Unknown")) {
11383 continue;
11384 }
11385 if (uj) {
11386 json_afi_safi = json_object_new_array();
11387 json_object_object_add(
11388 json_all,
11389 get_afi_safi_str(afi, safi, true),
11390 json_afi_safi);
11391 } else {
11392 json_afi_safi = NULL;
6c9d22e2 11393 }
9ab0cf58
PG
11394
11395 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11396 }
6c9d22e2
PG
11397
11398 if (uj) {
9ab0cf58
PG
11399 vty_out(vty, "%s",
11400 json_object_to_json_string_ext(
11401 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11402 json_object_free(json_all);
4265b261 11403 }
6c9d22e2 11404
4265b261
PG
11405 return CMD_SUCCESS;
11406}
11407
7b2ff250 11408/* BGP route print out function without JSON */
14718643
PG
11409DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11410 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11411 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11412 SHOW_STR
11413 IP_STR
11414 BGP_STR
11415 BGP_INSTANCE_HELP_STR
11416 L2VPN_HELP_STR
11417 EVPN_HELP_STR
11418 "BGP RIB advertisement statistics\n"
11419 JSON_STR)
11420{
ec76a1d1
DA
11421 afi_t afi = AFI_IP6;
11422 safi_t safi = SAFI_UNICAST;
14718643
PG
11423 struct bgp *bgp = NULL;
11424 int idx = 0, ret;
11425 bool uj = use_json(argc, argv);
11426 struct json_object *json_afi_safi = NULL, *json = NULL;
11427
11428 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11429 &bgp, false);
11430 if (!idx)
11431 return CMD_WARNING;
11432
11433 if (uj)
11434 json_afi_safi = json_object_new_array();
11435 else
11436 json_afi_safi = NULL;
11437
11438 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11439
11440 if (uj) {
11441 json = json_object_new_object();
11442 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11443 json_afi_safi);
11444 vty_out(vty, "%s", json_object_to_json_string_ext(
11445 json, JSON_C_TO_STRING_PRETTY));
11446 json_object_free(json);
11447 }
11448 return ret;
11449}
11450
893cccd0 11451/* BGP route print out function without JSON */
9ab0cf58
PG
11452DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11453 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11454 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11455 "]]\
893cccd0 11456 statistics [json]",
9ab0cf58
PG
11457 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11458 BGP_SAFI_WITH_LABEL_HELP_STR
11459 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11460{
ec76a1d1
DA
11461 afi_t afi = AFI_IP6;
11462 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11463 struct bgp *bgp = NULL;
11464 int idx = 0, ret;
11465 bool uj = use_json(argc, argv);
6c9d22e2 11466 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11467
11468 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11469 &bgp, false);
11470 if (!idx)
11471 return CMD_WARNING;
6c9d22e2 11472
893cccd0 11473 if (uj)
6c9d22e2
PG
11474 json_afi_safi = json_object_new_array();
11475 else
11476 json_afi_safi = NULL;
11477
11478 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11479
11480 if (uj) {
11481 json = json_object_new_object();
11482 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11483 json_afi_safi);
9ab0cf58
PG
11484 vty_out(vty, "%s",
11485 json_object_to_json_string_ext(
11486 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11487 json_object_free(json);
11488 }
11489 return ret;
893cccd0 11490}
7b2ff250
DW
11491
11492/* BGP route print out function without JSON */
96f3485c 11493DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11494 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11495 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11496 "]]\
96f3485c 11497 <[all$all] dampening <parameters>\
7b2ff250
DW
11498 |route-map WORD\
11499 |prefix-list WORD\
11500 |filter-list WORD\
7b2ff250
DW
11501 |community-list <(1-500)|WORD> [exact-match]\
11502 |A.B.C.D/M longer-prefixes\
11503 |X:X::X:X/M longer-prefixes\
893cccd0 11504 >",
9ab0cf58
PG
11505 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11506 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11507 "Display the entries for all address families\n"
9ab0cf58
PG
11508 "Display detailed information about dampening\n"
11509 "Display detail of configured dampening parameters\n"
11510 "Display routes matching the route-map\n"
11511 "A route-map to match on\n"
11512 "Display routes conforming to the prefix-list\n"
11513 "Prefix-list name\n"
11514 "Display routes conforming to the filter-list\n"
11515 "Regular expression access list name\n"
11516 "Display routes matching the community-list\n"
11517 "community-list number\n"
11518 "community-list name\n"
11519 "Exact match of the communities\n"
11520 "IPv4 prefix\n"
11521 "Display route and more specific routes\n"
11522 "IPv6 prefix\n"
11523 "Display route and more specific routes\n")
718e3744 11524{
d62a17ae 11525 afi_t afi = AFI_IP6;
11526 safi_t safi = SAFI_UNICAST;
11527 int exact_match = 0;
d62a17ae 11528 struct bgp *bgp = NULL;
11529 int idx = 0;
96f3485c
MK
11530 uint8_t show_flags = 0;
11531
11532 /* [<ipv4|ipv6> [all]] */
11533 if (all) {
11534 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11535 if (argv_find(argv, argc, "ipv4", &idx))
11536 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11537
11538 if (argv_find(argv, argc, "ipv6", &idx))
11539 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11540 }
d62a17ae 11541
11542 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11543 &bgp, false);
d62a17ae 11544 if (!idx)
11545 return CMD_WARNING;
11546
d62a17ae 11547 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11548 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11549 return bgp_show_dampening_parameters(vty, afi, safi,
11550 show_flags);
d62a17ae 11551 }
c016b6c7 11552
d62a17ae 11553 if (argv_find(argv, argc, "prefix-list", &idx))
11554 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11555 safi, bgp_show_type_prefix_list);
11556
11557 if (argv_find(argv, argc, "filter-list", &idx))
11558 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11559 safi, bgp_show_type_filter_list);
11560
d62a17ae 11561 if (argv_find(argv, argc, "route-map", &idx))
11562 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11563 safi, bgp_show_type_route_map);
11564
d62a17ae 11565 if (argv_find(argv, argc, "community-list", &idx)) {
11566 const char *clist_number_or_name = argv[++idx]->arg;
11567 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11568 exact_match = 1;
11569 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11570 exact_match, afi, safi);
11571 }
11572 /* prefix-longer */
11573 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11574 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11575 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11576 safi,
11577 bgp_show_type_prefix_longer);
11578
7b2ff250
DW
11579 return CMD_WARNING;
11580}
11581
11582/* BGP route print out function with JSON */
ae248832 11583DEFPY (show_ip_bgp_json,
7b2ff250
DW
11584 show_ip_bgp_json_cmd,
11585 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11586 [all$all]\
cf4898bc
QY
11587 [cidr-only\
11588 |dampening <flap-statistics|dampened-paths>\
11589 |community [AA:NN|local-AS|no-advertise|no-export\
11590 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11591 |accept-own|accept-own-nexthop|route-filter-v6\
11592 |route-filter-v4|route-filter-translated-v6\
11593 |route-filter-translated-v4] [exact-match]\
ae248832 11594 ] [json$uj | wide$wide]",
7b2ff250
DW
11595 SHOW_STR
11596 IP_STR
11597 BGP_STR
11598 BGP_INSTANCE_HELP_STR
11599 BGP_AFI_HELP_STR
11600 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11601 "Display the entries for all address families\n"
7b2ff250
DW
11602 "Display only routes with non-natural netmasks\n"
11603 "Display detailed information about dampening\n"
11604 "Display flap statistics of routes\n"
11605 "Display paths suppressed due to dampening\n"
11606 "Display routes matching the communities\n"
d0086e8e
AD
11607 COMMUNITY_AANN_STR
11608 "Do not send outside local AS (well-known community)\n"
11609 "Do not advertise to any peer (well-known community)\n"
11610 "Do not export to next AS (well-known community)\n"
11611 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11612 "Do not export to any peer (well-known community)\n"
11613 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11614 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11615 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11616 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11617 "Should accept VPN route with local nexthop (well-known community)\n"
11618 "RT VPNv6 route filtering (well-known community)\n"
11619 "RT VPNv4 route filtering (well-known community)\n"
11620 "RT translated VPNv6 route filtering (well-known community)\n"
11621 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11622 "Exact match of the communities\n"
ae248832
MK
11623 JSON_STR
11624 "Increase table width for longer prefixes\n")
7b2ff250
DW
11625{
11626 afi_t afi = AFI_IP6;
11627 safi_t safi = SAFI_UNICAST;
11628 enum bgp_show_type sh_type = bgp_show_type_normal;
11629 struct bgp *bgp = NULL;
11630 int idx = 0;
d0086e8e 11631 int exact_match = 0;
96f3485c
MK
11632 char *community = NULL;
11633 bool first = true;
11634 uint8_t show_flags = 0;
9f049418 11635
96f3485c
MK
11636
11637 if (uj) {
9f049418 11638 argc--;
96f3485c
MK
11639 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11640 }
11641
11642 /* [<ipv4|ipv6> [all]] */
11643 if (all) {
11644 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11645
11646 if (argv_find(argv, argc, "ipv4", &idx))
11647 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11648
11649 if (argv_find(argv, argc, "ipv6", &idx))
11650 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11651 }
11652
11653 if (wide)
11654 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11655
11656 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11657 &bgp, uj);
7b2ff250
DW
11658 if (!idx)
11659 return CMD_WARNING;
11660
7b2ff250 11661 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11662 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11663
11664 if (argv_find(argv, argc, "dampening", &idx)) {
11665 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11666 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11667 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11668 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11669 }
11670
11671 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11672 char *maybecomm = NULL;
d0086e8e 11673
79bc257a
RW
11674 if (idx + 1 < argc) {
11675 if (argv[idx + 1]->type == VARIABLE_TKN)
11676 maybecomm = argv[idx + 1]->arg;
11677 else
11678 maybecomm = argv[idx + 1]->text;
11679 }
11680
cf4898bc
QY
11681 if (maybecomm && !strmatch(maybecomm, "json")
11682 && !strmatch(maybecomm, "exact-match"))
11683 community = maybecomm;
d0086e8e 11684
cf4898bc
QY
11685 if (argv_find(argv, argc, "exact-match", &idx))
11686 exact_match = 1;
d0086e8e 11687
96f3485c
MK
11688 if (!community)
11689 sh_type = bgp_show_type_community_all;
11690 }
11691
11692 if (!all) {
11693 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11694 if (community)
11695 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11696 exact_match, afi, safi,
11697 show_flags);
cf4898bc 11698 else
96f3485c
MK
11699 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11700 show_flags);
11701 } else {
11702 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11703 * AFI_IP6 */
11704
11705 if (uj)
11706 vty_out(vty, "{\n");
11707
11708 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11709 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11710 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11711 ? AFI_IP
11712 : AFI_IP6;
11713 FOREACH_SAFI (safi) {
11714 if (strmatch(get_afi_safi_str(afi, safi, true),
11715 "Unknown"))
11716 continue;
11717
11718 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11719 continue;
11720
11721 if (uj) {
11722 if (first)
11723 first = false;
11724 else
11725 vty_out(vty, ",\n");
11726 vty_out(vty, "\"%s\":{\n",
11727 get_afi_safi_str(afi, safi,
11728 true));
11729 } else
11730 vty_out(vty,
11731 "\nFor address family: %s\n",
11732 get_afi_safi_str(afi, safi,
11733 false));
11734
11735 if (community)
11736 bgp_show_community(vty, bgp, community,
11737 exact_match, afi,
11738 safi, show_flags);
11739 else
11740 bgp_show(vty, bgp, afi, safi, sh_type,
11741 NULL, show_flags);
11742 if (uj)
11743 vty_out(vty, "}\n");
11744 }
11745 } else {
11746 /* show <ip> bgp all: for each AFI and SAFI*/
11747 FOREACH_AFI_SAFI (afi, safi) {
11748 if (strmatch(get_afi_safi_str(afi, safi, true),
11749 "Unknown"))
11750 continue;
11751
11752 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11753 continue;
11754
11755 if (uj) {
11756 if (first)
11757 first = false;
11758 else
11759 vty_out(vty, ",\n");
d0086e8e 11760
96f3485c
MK
11761 vty_out(vty, "\"%s\":{\n",
11762 get_afi_safi_str(afi, safi,
11763 true));
11764 } else
11765 vty_out(vty,
11766 "\nFor address family: %s\n",
11767 get_afi_safi_str(afi, safi,
11768 false));
11769
11770 if (community)
11771 bgp_show_community(vty, bgp, community,
11772 exact_match, afi,
11773 safi, show_flags);
11774 else
11775 bgp_show(vty, bgp, afi, safi, sh_type,
11776 NULL, show_flags);
11777 if (uj)
11778 vty_out(vty, "}\n");
11779 }
11780 }
11781 if (uj)
11782 vty_out(vty, "}\n");
11783 }
11784 return CMD_SUCCESS;
a636c635 11785}
47fc97cc 11786
718e3744 11787DEFUN (show_ip_bgp_route,
11788 show_ip_bgp_route_cmd,
3efd0893 11789 "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 11790 SHOW_STR
11791 IP_STR
11792 BGP_STR
a636c635 11793 BGP_INSTANCE_HELP_STR
4f280b15 11794 BGP_AFI_HELP_STR
4dd6177e 11795 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11796 "Network in the BGP routing table to display\n"
0c7b1b01 11797 "IPv4 prefix\n"
8c3deaae 11798 "Network in the BGP routing table to display\n"
0c7b1b01 11799 "IPv6 prefix\n"
4092b06c 11800 "Display only the bestpath\n"
b05a1c8b 11801 "Display only multipaths\n"
9973d184 11802 JSON_STR)
4092b06c 11803{
d62a17ae 11804 int prefix_check = 0;
ae19d7dd 11805
d62a17ae 11806 afi_t afi = AFI_IP6;
11807 safi_t safi = SAFI_UNICAST;
11808 char *prefix = NULL;
11809 struct bgp *bgp = NULL;
11810 enum bgp_path_type path_type;
9f049418 11811 bool uj = use_json(argc, argv);
b05a1c8b 11812
d62a17ae 11813 int idx = 0;
ae19d7dd 11814
d62a17ae 11815 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11816 &bgp, uj);
d62a17ae 11817 if (!idx)
11818 return CMD_WARNING;
c41247f5 11819
d62a17ae 11820 if (!bgp) {
11821 vty_out(vty,
11822 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11823 return CMD_WARNING;
11824 }
a636c635 11825
d62a17ae 11826 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11827 if (argv_find(argv, argc, "A.B.C.D", &idx)
11828 || argv_find(argv, argc, "X:X::X:X", &idx))
11829 prefix_check = 0;
11830 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11831 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11832 prefix_check = 1;
11833
11834 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11835 && afi != AFI_IP6) {
11836 vty_out(vty,
11837 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11838 return CMD_WARNING;
11839 }
11840 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11841 && afi != AFI_IP) {
11842 vty_out(vty,
11843 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11844 return CMD_WARNING;
11845 }
11846
11847 prefix = argv[idx]->arg;
11848
11849 /* [<bestpath|multipath>] */
11850 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11851 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11852 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11853 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11854 else
360660c6 11855 path_type = BGP_PATH_SHOW_ALL;
a636c635 11856
d62a17ae 11857 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11858 path_type, uj);
4092b06c
DS
11859}
11860
8c3deaae
QY
11861DEFUN (show_ip_bgp_regexp,
11862 show_ip_bgp_regexp_cmd,
3e5b31b3 11863 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11864 SHOW_STR
11865 IP_STR
11866 BGP_STR
b00b230a 11867 BGP_INSTANCE_HELP_STR
4f280b15 11868 BGP_AFI_HELP_STR
4dd6177e 11869 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11870 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11871 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11872 JSON_STR)
8c3deaae 11873{
d62a17ae 11874 afi_t afi = AFI_IP6;
11875 safi_t safi = SAFI_UNICAST;
11876 struct bgp *bgp = NULL;
3e5b31b3
DA
11877 bool uj = use_json(argc, argv);
11878 char *regstr = NULL;
8c3deaae 11879
d62a17ae 11880 int idx = 0;
11881 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11882 &bgp, false);
d62a17ae 11883 if (!idx)
11884 return CMD_WARNING;
8c3deaae 11885
d62a17ae 11886 // get index of regex
3e5b31b3
DA
11887 if (argv_find(argv, argc, "REGEX", &idx))
11888 regstr = argv[idx]->arg;
8c3deaae 11889
5f71d11c 11890 assert(regstr);
3e5b31b3
DA
11891 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11892 bgp_show_type_regexp, uj);
8c3deaae
QY
11893}
11894
ae248832 11895DEFPY (show_ip_bgp_instance_all,
a636c635 11896 show_ip_bgp_instance_all_cmd,
ae248832 11897 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11898 SHOW_STR
a636c635 11899 IP_STR
4092b06c 11900 BGP_STR
a636c635 11901 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11902 BGP_AFI_HELP_STR
4dd6177e 11903 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11904 JSON_STR
11905 "Increase table width for longer prefixes\n")
4092b06c 11906{
d62a17ae 11907 afi_t afi = AFI_IP;
11908 safi_t safi = SAFI_UNICAST;
11909 struct bgp *bgp = NULL;
d62a17ae 11910 int idx = 0;
96f3485c 11911 uint8_t show_flags = 0;
ae19d7dd 11912
96f3485c 11913 if (uj) {
d62a17ae 11914 argc--;
96f3485c
MK
11915 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11916 }
11917
11918 if (wide)
11919 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11920
9f049418
DS
11921 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11922 &bgp, uj);
11923 if (!idx)
11924 return CMD_WARNING;
11925
96f3485c 11926 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11927 return CMD_SUCCESS;
e3e29b32
LB
11928}
11929
a4d82a8a 11930static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11931 afi_t afi, safi_t safi, enum bgp_show_type type,
11932 bool use_json)
718e3744 11933{
d62a17ae 11934 regex_t *regex;
11935 int rc;
96f3485c
MK
11936 uint8_t show_flags = 0;
11937
11938 if (use_json)
11939 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11940
c3900853 11941 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11942 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11943 regstr);
11944 return CMD_WARNING_CONFIG_FAILED;
11945 }
11946
d62a17ae 11947 regex = bgp_regcomp(regstr);
11948 if (!regex) {
11949 vty_out(vty, "Can't compile regexp %s\n", regstr);
11950 return CMD_WARNING;
11951 }
a636c635 11952
96f3485c 11953 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11954 bgp_regex_free(regex);
11955 return rc;
e3e29b32
LB
11956}
11957
d62a17ae 11958static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11959 const char *prefix_list_str, afi_t afi,
11960 safi_t safi, enum bgp_show_type type)
e3e29b32 11961{
d62a17ae 11962 struct prefix_list *plist;
96f3485c 11963 uint8_t show_flags = 0;
718e3744 11964
d62a17ae 11965 plist = prefix_list_lookup(afi, prefix_list_str);
11966 if (plist == NULL) {
11967 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11968 prefix_list_str);
11969 return CMD_WARNING;
11970 }
718e3744 11971
96f3485c 11972 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
11973}
11974
d62a17ae 11975static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11976 const char *filter, afi_t afi, safi_t safi,
11977 enum bgp_show_type type)
4092b06c 11978{
d62a17ae 11979 struct as_list *as_list;
96f3485c 11980 uint8_t show_flags = 0;
718e3744 11981
d62a17ae 11982 as_list = as_list_lookup(filter);
11983 if (as_list == NULL) {
11984 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11985 filter);
11986 return CMD_WARNING;
11987 }
a636c635 11988
96f3485c 11989 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 11990}
11991
d62a17ae 11992static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11993 const char *rmap_str, afi_t afi, safi_t safi,
11994 enum bgp_show_type type)
718e3744 11995{
d62a17ae 11996 struct route_map *rmap;
96f3485c 11997 uint8_t show_flags = 0;
bb46e94f 11998
d62a17ae 11999 rmap = route_map_lookup_by_name(rmap_str);
12000 if (!rmap) {
12001 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12002 return CMD_WARNING;
12003 }
12004
96f3485c 12005 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12006}
12007
7f323236
DW
12008static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12009 const char *comstr, int exact, afi_t afi,
96f3485c 12010 safi_t safi, uint8_t show_flags)
d62a17ae 12011{
12012 struct community *com;
d62a17ae 12013 int ret = 0;
12014
7f323236 12015 com = community_str2com(comstr);
d62a17ae 12016 if (!com) {
7f323236 12017 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12018 return CMD_WARNING;
12019 }
12020
12021 ret = bgp_show(vty, bgp, afi, safi,
12022 (exact ? bgp_show_type_community_exact
12023 : bgp_show_type_community),
96f3485c 12024 com, show_flags);
3c1f53de 12025 community_free(&com);
46c3ce83 12026
d62a17ae 12027 return ret;
718e3744 12028}
12029
d62a17ae 12030static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12031 const char *com, int exact, afi_t afi,
12032 safi_t safi)
50ef26d4 12033{
d62a17ae 12034 struct community_list *list;
96f3485c 12035 uint8_t show_flags = 0;
50ef26d4 12036
e237b0d2 12037 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12038 if (list == NULL) {
12039 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12040 return CMD_WARNING;
12041 }
718e3744 12042
d62a17ae 12043 return bgp_show(vty, bgp, afi, safi,
12044 (exact ? bgp_show_type_community_list_exact
12045 : bgp_show_type_community_list),
96f3485c 12046 list, show_flags);
50ef26d4 12047}
12048
d62a17ae 12049static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12050 const char *prefix, afi_t afi, safi_t safi,
12051 enum bgp_show_type type)
718e3744 12052{
d62a17ae 12053 int ret;
12054 struct prefix *p;
96f3485c 12055 uint8_t show_flags = 0;
47fc97cc 12056
d62a17ae 12057 p = prefix_new();
95cbbd2a 12058
d62a17ae 12059 ret = str2prefix(prefix, p);
12060 if (!ret) {
12061 vty_out(vty, "%% Malformed Prefix\n");
12062 return CMD_WARNING;
12063 }
47e9b292 12064
96f3485c 12065 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12066 prefix_free(&p);
d62a17ae 12067 return ret;
12068}
12069
d62a17ae 12070enum bgp_stats {
12071 BGP_STATS_MAXBITLEN = 0,
12072 BGP_STATS_RIB,
12073 BGP_STATS_PREFIXES,
12074 BGP_STATS_TOTPLEN,
12075 BGP_STATS_UNAGGREGATEABLE,
12076 BGP_STATS_MAX_AGGREGATEABLE,
12077 BGP_STATS_AGGREGATES,
12078 BGP_STATS_SPACE,
12079 BGP_STATS_ASPATH_COUNT,
12080 BGP_STATS_ASPATH_MAXHOPS,
12081 BGP_STATS_ASPATH_TOTHOPS,
12082 BGP_STATS_ASPATH_MAXSIZE,
12083 BGP_STATS_ASPATH_TOTSIZE,
12084 BGP_STATS_ASN_HIGHEST,
12085 BGP_STATS_MAX,
a636c635 12086};
2815e61f 12087
9ab0cf58 12088#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12089#define TABLE_STATS_IDX_JSON 1
12090
12091static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12092 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12093 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12094 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12095 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12096 "unaggregateablePrefixes"},
12097 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12098 "maximumAggregateablePrefixes"},
12099 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12100 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12101 [BGP_STATS_SPACE] = {"Address space advertised",
12102 "addressSpaceAdvertised"},
9ab0cf58
PG
12103 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12104 "advertisementsWithPaths"},
12105 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12106 "longestAsPath"},
12107 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12108 "largestAsPath"},
12109 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12110 "averageAsPathLengthHops"},
12111 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12112 "averageAsPathSizeBytes"},
12113 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12114 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12115};
2815e61f 12116
d62a17ae 12117struct bgp_table_stats {
12118 struct bgp_table *table;
12119 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12120 double total_space;
ff7924f6
PJ
12121};
12122
a636c635
DW
12123#if 0
12124#define TALLY_SIGFIG 100000
12125static unsigned long
12126ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 12127{
a636c635
DW
12128 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
12129 unsigned long res = (newtot * TALLY_SIGFIG) / count;
12130 unsigned long ret = newtot / count;
07d0c4ed 12131
a636c635
DW
12132 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
12133 return ret + 1;
12134 else
12135 return ret;
12136}
12137#endif
ff7924f6 12138
9bcb3eef 12139static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12140 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12141{
9bcb3eef 12142 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12143 struct bgp_path_info *pi;
b54892e0 12144 const struct prefix *rn_p;
d62a17ae 12145
9bcb3eef 12146 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12147 return;
d62a17ae 12148
9bcb3eef 12149 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12150 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12151 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12152
a636c635
DW
12153#if 0
12154 ts->counts[BGP_STATS_AVGPLEN]
12155 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
12156 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 12157 rn_p->prefixlen);
a636c635 12158#endif
d62a17ae 12159
9c14ec72 12160 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12161 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12162 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12163
9bcb3eef 12164 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12165 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12166 /* announced address space */
12167 if (space)
b54892e0 12168 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12169 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12170 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12171
9c14ec72 12172
9bcb3eef 12173 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12174 ts->counts[BGP_STATS_RIB]++;
12175
05864da7
DS
12176 if (CHECK_FLAG(pi->attr->flag,
12177 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12178 ts->counts[BGP_STATS_AGGREGATES]++;
12179
12180 /* as-path stats */
05864da7 12181 if (pi->attr->aspath) {
9c14ec72
RW
12182 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12183 unsigned int size = aspath_size(pi->attr->aspath);
12184 as_t highest = aspath_highest(pi->attr->aspath);
12185
12186 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12187
12188 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12189 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12190
12191 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12192 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12193
12194 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12195 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 12196#if 0
07d0c4ed 12197 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
12198 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12199 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
12200 hops);
12201 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
12202 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
12203 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
12204 size);
12205#endif
9c14ec72
RW
12206 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12207 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12208 }
12209 }
12210}
12211
12212static int bgp_table_stats_walker(struct thread *t)
12213{
9bcb3eef
DS
12214 struct bgp_dest *dest, *ndest;
12215 struct bgp_dest *top;
9c14ec72
RW
12216 struct bgp_table_stats *ts = THREAD_ARG(t);
12217 unsigned int space = 0;
12218
12219 if (!(top = bgp_table_top(ts->table)))
12220 return 0;
12221
12222 switch (ts->table->afi) {
12223 case AFI_IP:
12224 space = IPV4_MAX_BITLEN;
12225 break;
12226 case AFI_IP6:
12227 space = IPV6_MAX_BITLEN;
12228 break;
12229 default:
12230 return 0;
12231 }
12232
12233 ts->counts[BGP_STATS_MAXBITLEN] = space;
12234
9bcb3eef 12235 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12236 if (ts->table->safi == SAFI_MPLS_VPN
12237 || ts->table->safi == SAFI_ENCAP
12238 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12239 struct bgp_table *table;
12240
9bcb3eef 12241 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12242 if (!table)
12243 continue;
12244
12245 top = bgp_table_top(table);
9bcb3eef
DS
12246 for (ndest = bgp_table_top(table); ndest;
12247 ndest = bgp_route_next(ndest))
12248 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12249 } else {
9bcb3eef 12250 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12251 }
12252 }
9c14ec72 12253
d62a17ae 12254 return 0;
2815e61f 12255}
ff7924f6 12256
71f1613a
DA
12257static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12258 struct json_object *json_array)
12259{
12260 struct listnode *node, *nnode;
12261 struct bgp *bgp;
12262
12263 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12264 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12265}
12266
12267static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12268 safi_t safi, struct json_object *json_array)
2815e61f 12269{
d62a17ae 12270 struct bgp_table_stats ts;
12271 unsigned int i;
893cccd0
PG
12272 int ret = CMD_SUCCESS;
12273 char temp_buf[20];
6c9d22e2
PG
12274 struct json_object *json = NULL;
12275
12276 if (json_array)
12277 json = json_object_new_object();
019386c2 12278
d62a17ae 12279 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12280 char warning_msg[50];
12281
12282 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12283 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12284 safi);
6c9d22e2
PG
12285
12286 if (!json)
893cccd0
PG
12287 vty_out(vty, "%s\n", warning_msg);
12288 else
9ab0cf58 12289 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12290
893cccd0
PG
12291 ret = CMD_WARNING;
12292 goto end_table_stats;
d62a17ae 12293 }
019386c2 12294
893cccd0 12295 if (!json)
5290ceab
DA
12296 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12297 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12298 else
12299 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12300
d62a17ae 12301 /* labeled-unicast routes live in the unicast table */
12302 if (safi == SAFI_LABELED_UNICAST)
12303 safi = SAFI_UNICAST;
019386c2 12304
d62a17ae 12305 memset(&ts, 0, sizeof(ts));
12306 ts.table = bgp->rib[afi][safi];
12307 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12308
d62a17ae 12309 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12310 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12311 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12312 continue;
12313
12314 switch (i) {
a636c635
DW
12315#if 0
12316 case BGP_STATS_ASPATH_AVGHOPS:
12317 case BGP_STATS_ASPATH_AVGSIZE:
12318 case BGP_STATS_AVGPLEN:
12319 vty_out (vty, "%-30s: ", table_stats_strs[i]);
12320 vty_out (vty, "%12.2f",
12321 (float)ts.counts[i] / (float)TALLY_SIGFIG);
12322 break;
12323#endif
d62a17ae 12324 case BGP_STATS_ASPATH_TOTHOPS:
12325 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12326 if (!json) {
9ab0cf58
PG
12327 snprintf(
12328 temp_buf, sizeof(temp_buf), "%12.2f",
12329 ts.counts[i]
12330 ? (float)ts.counts[i]
12331 / (float)ts.counts
12332 [BGP_STATS_ASPATH_COUNT]
12333 : 0);
893cccd0 12334 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12335 table_stats_strs[i]
12336 [TABLE_STATS_IDX_VTY],
893cccd0 12337 temp_buf);
9ab0cf58
PG
12338 } else {
12339 json_object_double_add(
12340 json,
12341 table_stats_strs[i]
12342 [TABLE_STATS_IDX_JSON],
12343 ts.counts[i]
12344 ? (double)ts.counts[i]
12345 / (double)ts.counts
d62a17ae 12346 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12347 : 0);
12348 }
d62a17ae 12349 break;
12350 case BGP_STATS_TOTPLEN:
6c9d22e2 12351 if (!json) {
9ab0cf58
PG
12352 snprintf(
12353 temp_buf, sizeof(temp_buf), "%12.2f",
12354 ts.counts[i]
12355 ? (float)ts.counts[i]
12356 / (float)ts.counts
12357 [BGP_STATS_PREFIXES]
12358 : 0);
893cccd0 12359 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12360 table_stats_strs[i]
12361 [TABLE_STATS_IDX_VTY],
893cccd0 12362 temp_buf);
9ab0cf58
PG
12363 } else {
12364 json_object_double_add(
12365 json,
12366 table_stats_strs[i]
12367 [TABLE_STATS_IDX_JSON],
12368 ts.counts[i]
12369 ? (double)ts.counts[i]
12370 / (double)ts.counts
d62a17ae 12371 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12372 : 0);
12373 }
d62a17ae 12374 break;
12375 case BGP_STATS_SPACE:
6c9d22e2
PG
12376 if (!json) {
12377 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12378 ts.total_space);
893cccd0 12379 vty_out(vty, "%-30s: %s\n",
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 (double)ts.total_space);
12389 }
8d0ab76d 12390 if (afi == AFI_IP6) {
6c9d22e2
PG
12391 if (!json) {
12392 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12393 "%12g",
12394 ts.total_space
12395 * pow(2.0, -128 + 32));
6c9d22e2
PG
12396 vty_out(vty, "%30s: %s\n",
12397 "/32 equivalent %s\n",
12398 temp_buf);
9ab0cf58
PG
12399 } else {
12400 json_object_double_add(
12401 json, "/32equivalent",
12402 (double)(ts.total_space
12403 * pow(2.0,
12404 -128 + 32)));
12405 }
6c9d22e2
PG
12406 if (!json) {
12407 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12408 "%12g",
12409 ts.total_space
12410 * pow(2.0, -128 + 48));
6c9d22e2
PG
12411 vty_out(vty, "%30s: %s\n",
12412 "/48 equivalent %s\n",
12413 temp_buf);
9ab0cf58
PG
12414 } else {
12415 json_object_double_add(
12416 json, "/48equivalent",
12417 (double)(ts.total_space
12418 * pow(2.0,
12419 -128 + 48)));
12420 }
8d0ab76d 12421 } else {
6c9d22e2
PG
12422 if (!json) {
12423 snprintf(temp_buf, sizeof(temp_buf),
12424 "%12.2f",
9ab0cf58
PG
12425 ts.total_space * 100.
12426 * pow(2.0, -32));
6c9d22e2 12427 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12428 "% announced ", temp_buf);
12429 } else {
12430 json_object_double_add(
12431 json, "%announced",
12432 (double)(ts.total_space * 100.
12433 * pow(2.0, -32)));
12434 }
6c9d22e2
PG
12435 if (!json) {
12436 snprintf(temp_buf, sizeof(temp_buf),
12437 "%12.2f",
9ab0cf58
PG
12438 ts.total_space
12439 * pow(2.0, -32 + 8));
6c9d22e2
PG
12440 vty_out(vty, "%30s: %s\n",
12441 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12442 } else {
12443 json_object_double_add(
12444 json, "/8equivalent",
12445 (double)(ts.total_space
12446 * pow(2.0, -32 + 8)));
12447 }
6c9d22e2
PG
12448 if (!json) {
12449 snprintf(temp_buf, sizeof(temp_buf),
12450 "%12.2f",
9ab0cf58
PG
12451 ts.total_space
12452 * pow(2.0, -32 + 24));
6c9d22e2 12453 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12454 "/24 equivalent ", temp_buf);
12455 } else {
12456 json_object_double_add(
12457 json, "/24equivalent",
12458 (double)(ts.total_space
12459 * pow(2.0, -32 + 24)));
12460 }
8d0ab76d 12461 }
d62a17ae 12462 break;
12463 default:
6c9d22e2
PG
12464 if (!json) {
12465 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12466 ts.counts[i]);
893cccd0 12467 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12468 table_stats_strs[i]
12469 [TABLE_STATS_IDX_VTY],
12470 temp_buf);
12471 } else {
12472 json_object_int_add(
12473 json,
12474 table_stats_strs[i]
12475 [TABLE_STATS_IDX_JSON],
12476 ts.counts[i]);
12477 }
d62a17ae 12478 }
893cccd0
PG
12479 if (!json)
12480 vty_out(vty, "\n");
d62a17ae 12481 }
9ab0cf58 12482end_table_stats:
6c9d22e2
PG
12483 if (json)
12484 json_object_array_add(json_array, json);
893cccd0 12485 return ret;
d62a17ae 12486}
12487
71f1613a
DA
12488static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12489 safi_t safi, struct json_object *json_array)
12490{
12491 if (!bgp) {
12492 bgp_table_stats_all(vty, afi, safi, json_array);
12493 return CMD_SUCCESS;
12494 }
12495
12496 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12497}
12498
d62a17ae 12499enum bgp_pcounts {
12500 PCOUNT_ADJ_IN = 0,
12501 PCOUNT_DAMPED,
12502 PCOUNT_REMOVED,
12503 PCOUNT_HISTORY,
12504 PCOUNT_STALE,
12505 PCOUNT_VALID,
12506 PCOUNT_ALL,
12507 PCOUNT_COUNTED,
7e3d9632 12508 PCOUNT_BPATH_SELECTED,
d62a17ae 12509 PCOUNT_PFCNT, /* the figure we display to users */
12510 PCOUNT_MAX,
a636c635 12511};
718e3744 12512
2b64873d 12513static const char *const pcount_strs[] = {
9d303b37
DL
12514 [PCOUNT_ADJ_IN] = "Adj-in",
12515 [PCOUNT_DAMPED] = "Damped",
12516 [PCOUNT_REMOVED] = "Removed",
12517 [PCOUNT_HISTORY] = "History",
12518 [PCOUNT_STALE] = "Stale",
12519 [PCOUNT_VALID] = "Valid",
12520 [PCOUNT_ALL] = "All RIB",
12521 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12522 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12523 [PCOUNT_PFCNT] = "Useable",
12524 [PCOUNT_MAX] = NULL,
a636c635 12525};
718e3744 12526
d62a17ae 12527struct peer_pcounts {
12528 unsigned int count[PCOUNT_MAX];
12529 const struct peer *peer;
12530 const struct bgp_table *table;
54317cba 12531 safi_t safi;
a636c635 12532};
47fc97cc 12533
9bcb3eef 12534static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12535{
54317cba
JW
12536 const struct bgp_adj_in *ain;
12537 const struct bgp_path_info *pi;
d62a17ae 12538 const struct peer *peer = pc->peer;
12539
54317cba
JW
12540 for (ain = rn->adj_in; ain; ain = ain->next)
12541 if (ain->peer == peer)
12542 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12543
9bcb3eef 12544 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12545
54317cba
JW
12546 if (pi->peer != peer)
12547 continue;
d62a17ae 12548
54317cba 12549 pc->count[PCOUNT_ALL]++;
d62a17ae 12550
54317cba
JW
12551 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12552 pc->count[PCOUNT_DAMPED]++;
12553 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12554 pc->count[PCOUNT_HISTORY]++;
12555 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12556 pc->count[PCOUNT_REMOVED]++;
12557 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12558 pc->count[PCOUNT_STALE]++;
12559 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12560 pc->count[PCOUNT_VALID]++;
12561 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12562 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12563 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12564 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12565
12566 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12567 pc->count[PCOUNT_COUNTED]++;
12568 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12569 flog_err(
12570 EC_LIB_DEVELOPMENT,
12571 "Attempting to count but flags say it is unusable");
12572 } else {
40381db7 12573 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12574 flog_err(
12575 EC_LIB_DEVELOPMENT,
12576 "Not counted but flags say we should");
d62a17ae 12577 }
12578 }
54317cba
JW
12579}
12580
12581static int bgp_peer_count_walker(struct thread *t)
12582{
9bcb3eef 12583 struct bgp_dest *rn, *rm;
54317cba
JW
12584 const struct bgp_table *table;
12585 struct peer_pcounts *pc = THREAD_ARG(t);
12586
12587 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12588 || pc->safi == SAFI_EVPN) {
12589 /* Special handling for 2-level routing tables. */
12590 for (rn = bgp_table_top(pc->table); rn;
12591 rn = bgp_route_next(rn)) {
9bcb3eef 12592 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12593 if (table != NULL)
12594 for (rm = bgp_table_top(table); rm;
12595 rm = bgp_route_next(rm))
12596 bgp_peer_count_proc(rm, pc);
12597 }
12598 } else
12599 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12600 bgp_peer_count_proc(rn, pc);
12601
d62a17ae 12602 return 0;
718e3744 12603}
12604
d62a17ae 12605static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12606 safi_t safi, bool use_json)
856ca177 12607{
d62a17ae 12608 struct peer_pcounts pcounts = {.peer = peer};
12609 unsigned int i;
12610 json_object *json = NULL;
12611 json_object *json_loop = NULL;
856ca177 12612
d62a17ae 12613 if (use_json) {
12614 json = json_object_new_object();
12615 json_loop = json_object_new_object();
12616 }
718e3744 12617
d62a17ae 12618 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12619 || !peer->bgp->rib[afi][safi]) {
12620 if (use_json) {
12621 json_object_string_add(
12622 json, "warning",
12623 "No such neighbor or address family");
12624 vty_out(vty, "%s\n", json_object_to_json_string(json));
12625 json_object_free(json);
12626 } else
12627 vty_out(vty, "%% No such neighbor or address family\n");
12628
12629 return CMD_WARNING;
12630 }
2a71e9ce 12631
d62a17ae 12632 memset(&pcounts, 0, sizeof(pcounts));
12633 pcounts.peer = peer;
12634 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12635 pcounts.safi = safi;
d62a17ae 12636
12637 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12638 * stats for the thread-walk (i.e. ensure this can't be blamed on
12639 * on just vty_read()).
12640 */
d62a17ae 12641 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12642
12643 if (use_json) {
12644 json_object_string_add(json, "prefixCountsFor", peer->host);
12645 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12646 get_afi_safi_str(afi, safi, true));
d62a17ae 12647 json_object_int_add(json, "pfxCounter",
12648 peer->pcount[afi][safi]);
12649
12650 for (i = 0; i < PCOUNT_MAX; i++)
12651 json_object_int_add(json_loop, pcount_strs[i],
12652 pcounts.count[i]);
12653
12654 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12655
12656 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12657 json_object_string_add(json, "pfxctDriftFor",
12658 peer->host);
12659 json_object_string_add(
12660 json, "recommended",
12661 "Please report this bug, with the above command output");
12662 }
996c9314
LB
12663 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12664 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12665 json_object_free(json);
12666 } else {
12667
12668 if (peer->hostname
892fedb6 12669 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12670 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12671 peer->hostname, peer->host,
5cb5f4d0 12672 get_afi_safi_str(afi, safi, false));
d62a17ae 12673 } else {
12674 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12675 get_afi_safi_str(afi, safi, false));
d62a17ae 12676 }
12677
6cde4b45 12678 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12679 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12680
12681 for (i = 0; i < PCOUNT_MAX; i++)
12682 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12683 pcounts.count[i]);
12684
12685 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12686 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12687 vty_out(vty,
12688 "Please report this bug, with the above command output\n");
12689 }
12690 }
12691
12692 return CMD_SUCCESS;
718e3744 12693}
12694
a636c635
DW
12695DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12696 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12697 "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 12698 SHOW_STR
12699 IP_STR
12700 BGP_STR
8386ac43 12701 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12702 BGP_AFI_HELP_STR
12703 BGP_SAFI_HELP_STR
0b16f239
DS
12704 "Detailed information on TCP and BGP neighbor connections\n"
12705 "Neighbor to display information about\n"
12706 "Neighbor to display information about\n"
91d37724 12707 "Neighbor on BGP configured interface\n"
a636c635 12708 "Display detailed prefix count information\n"
9973d184 12709 JSON_STR)
0b16f239 12710{
d62a17ae 12711 afi_t afi = AFI_IP6;
12712 safi_t safi = SAFI_UNICAST;
12713 struct peer *peer;
12714 int idx = 0;
12715 struct bgp *bgp = NULL;
9f049418
DS
12716 bool uj = use_json(argc, argv);
12717
12718 if (uj)
12719 argc--;
856ca177 12720
d62a17ae 12721 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12722 &bgp, uj);
d62a17ae 12723 if (!idx)
12724 return CMD_WARNING;
0b16f239 12725
d62a17ae 12726 argv_find(argv, argc, "neighbors", &idx);
12727 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12728 if (!peer)
12729 return CMD_WARNING;
bb46e94f 12730
29c8d9da 12731 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12732}
0b16f239 12733
d6902373
PG
12734#ifdef KEEP_OLD_VPN_COMMANDS
12735DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12736 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12737 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12738 SHOW_STR
12739 IP_STR
12740 BGP_STR
d6902373 12741 BGP_VPNVX_HELP_STR
91d37724 12742 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12743 "Detailed information on TCP and BGP neighbor connections\n"
12744 "Neighbor to display information about\n"
12745 "Neighbor to display information about\n"
91d37724 12746 "Neighbor on BGP configured interface\n"
a636c635 12747 "Display detailed prefix count information\n"
9973d184 12748 JSON_STR)
a636c635 12749{
d62a17ae 12750 int idx_peer = 6;
12751 struct peer *peer;
9f049418 12752 bool uj = use_json(argc, argv);
a636c635 12753
d62a17ae 12754 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12755 if (!peer)
12756 return CMD_WARNING;
12757
12758 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12759}
12760
d6902373
PG
12761DEFUN (show_ip_bgp_vpn_all_route_prefix,
12762 show_ip_bgp_vpn_all_route_prefix_cmd,
12763 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12764 SHOW_STR
12765 IP_STR
12766 BGP_STR
d6902373 12767 BGP_VPNVX_HELP_STR
91d37724
QY
12768 "Display information about all VPNv4 NLRIs\n"
12769 "Network in the BGP routing table to display\n"
3a2d747c 12770 "Network in the BGP routing table to display\n"
9973d184 12771 JSON_STR)
91d37724 12772{
d62a17ae 12773 int idx = 0;
12774 char *network = NULL;
12775 struct bgp *bgp = bgp_get_default();
12776 if (!bgp) {
12777 vty_out(vty, "Can't find default instance\n");
12778 return CMD_WARNING;
12779 }
87e34b58 12780
d62a17ae 12781 if (argv_find(argv, argc, "A.B.C.D", &idx))
12782 network = argv[idx]->arg;
12783 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12784 network = argv[idx]->arg;
12785 else {
12786 vty_out(vty, "Unable to figure out Network\n");
12787 return CMD_WARNING;
12788 }
87e34b58 12789
d62a17ae 12790 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12791 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12792}
d6902373 12793#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12794
44c69747
LK
12795DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12796 show_bgp_l2vpn_evpn_route_prefix_cmd,
12797 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12798 SHOW_STR
4c63a661
PG
12799 BGP_STR
12800 L2VPN_HELP_STR
12801 EVPN_HELP_STR
44c69747
LK
12802 "Network in the BGP routing table to display\n"
12803 "Network in the BGP routing table to display\n"
4c63a661
PG
12804 "Network in the BGP routing table to display\n"
12805 "Network in the BGP routing table to display\n"
12806 JSON_STR)
12807{
d62a17ae 12808 int idx = 0;
12809 char *network = NULL;
44c69747 12810 int prefix_check = 0;
a636c635 12811
44c69747
LK
12812 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12813 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12814 network = argv[idx]->arg;
44c69747 12815 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12816 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12817 network = argv[idx]->arg;
44c69747
LK
12818 prefix_check = 1;
12819 } else {
d62a17ae 12820 vty_out(vty, "Unable to figure out Network\n");
12821 return CMD_WARNING;
12822 }
44c69747
LK
12823 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12824 prefix_check, BGP_PATH_SHOW_ALL,
12825 use_json(argc, argv));
d62a17ae 12826}
12827
2f9bc755
DS
12828static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12829 struct bgp_table *table, int *header1,
12830 int *header2, json_object *json,
12831 json_object *json_scode,
12832 json_object *json_ocode, bool wide)
12833{
12834 uint64_t version = table ? table->version : 0;
23d0a753 12835 char buf[BUFSIZ] = {0};
2f9bc755
DS
12836
12837 if (*header1) {
12838 if (json) {
12839 json_object_int_add(json, "bgpTableVersion", version);
12840 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12841 inet_ntop(AF_INET,
12842 &bgp->router_id, buf,
12843 sizeof(buf)));
2f9bc755
DS
12844 json_object_int_add(json, "defaultLocPrf",
12845 bgp->default_local_pref);
12846 json_object_int_add(json, "localAS", bgp->as);
12847 json_object_object_add(json, "bgpStatusCodes",
12848 json_scode);
12849 json_object_object_add(json, "bgpOriginCodes",
12850 json_ocode);
12851 } else {
12852 vty_out(vty,
23d0a753
DA
12853 "BGP table version is %" PRIu64
12854 ", local router ID is %pI4, vrf id ",
12855 version, &bgp->router_id);
2f9bc755
DS
12856 if (bgp->vrf_id == VRF_UNKNOWN)
12857 vty_out(vty, "%s", VRFID_NONE_STR);
12858 else
12859 vty_out(vty, "%u", bgp->vrf_id);
12860 vty_out(vty, "\n");
12861 vty_out(vty, "Default local pref %u, ",
12862 bgp->default_local_pref);
12863 vty_out(vty, "local AS %u\n", bgp->as);
12864 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12865 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12866 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12867 }
12868 *header1 = 0;
12869 }
12870 if (*header2) {
12871 if (!json)
12872 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12873 : BGP_SHOW_HEADER));
12874 *header2 = 0;
12875 }
12876}
12877
d62a17ae 12878static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12879 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12880 const char *rmap_name, json_object *json,
12881 uint8_t show_flags)
d62a17ae 12882{
12883 struct bgp_table *table;
12884 struct bgp_adj_in *ain;
12885 struct bgp_adj_out *adj;
74a630b6
NT
12886 unsigned long output_count = 0;
12887 unsigned long filtered_count = 0;
9bcb3eef 12888 struct bgp_dest *dest;
d62a17ae 12889 int header1 = 1;
12890 struct bgp *bgp;
12891 int header2 = 1;
12892 struct attr attr;
12893 int ret;
12894 struct update_subgroup *subgrp;
12895 json_object *json_scode = NULL;
12896 json_object *json_ocode = NULL;
12897 json_object *json_ar = NULL;
12898 struct peer_af *paf;
f99def61 12899 bool route_filtered;
96f3485c
MK
12900 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12901 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12902
12903 if (use_json) {
12904 json_scode = json_object_new_object();
12905 json_ocode = json_object_new_object();
12906 json_ar = json_object_new_object();
12907
12908 json_object_string_add(json_scode, "suppressed", "s");
12909 json_object_string_add(json_scode, "damped", "d");
12910 json_object_string_add(json_scode, "history", "h");
12911 json_object_string_add(json_scode, "valid", "*");
12912 json_object_string_add(json_scode, "best", ">");
12913 json_object_string_add(json_scode, "multipath", "=");
12914 json_object_string_add(json_scode, "internal", "i");
12915 json_object_string_add(json_scode, "ribFailure", "r");
12916 json_object_string_add(json_scode, "stale", "S");
12917 json_object_string_add(json_scode, "removed", "R");
12918
12919 json_object_string_add(json_ocode, "igp", "i");
12920 json_object_string_add(json_ocode, "egp", "e");
12921 json_object_string_add(json_ocode, "incomplete", "?");
12922 }
a636c635 12923
d62a17ae 12924 bgp = peer->bgp;
a636c635 12925
d62a17ae 12926 if (!bgp) {
12927 if (use_json) {
12928 json_object_string_add(json, "alert", "no BGP");
12929 vty_out(vty, "%s\n", json_object_to_json_string(json));
12930 json_object_free(json);
12931 } else
12932 vty_out(vty, "%% No bgp\n");
12933 return;
12934 }
a636c635 12935
c512a642
EDP
12936 /* labeled-unicast routes live in the unicast table */
12937 if (safi == SAFI_LABELED_UNICAST)
12938 table = bgp->rib[afi][SAFI_UNICAST];
12939 else
12940 table = bgp->rib[afi][safi];
d62a17ae 12941
12942 output_count = filtered_count = 0;
12943 subgrp = peer_subgroup(peer, afi, safi);
12944
6392aaa6 12945 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12946 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
12947 char buf[BUFSIZ] = {0};
12948
d62a17ae 12949 if (use_json) {
12950 json_object_int_add(json, "bgpTableVersion",
12951 table->version);
12952 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
12953 inet_ntop(AF_INET,
12954 &bgp->router_id, buf,
12955 sizeof(buf)));
01eced22
AD
12956 json_object_int_add(json, "defaultLocPrf",
12957 bgp->default_local_pref);
12958 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12959 json_object_object_add(json, "bgpStatusCodes",
12960 json_scode);
12961 json_object_object_add(json, "bgpOriginCodes",
12962 json_ocode);
07d0c4ed
DA
12963 json_object_string_add(
12964 json, "bgpOriginatingDefaultNetwork",
12965 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12966 } else {
23d0a753
DA
12967 vty_out(vty,
12968 "BGP table version is %" PRIu64
12969 ", local router ID is %pI4, vrf id ",
12970 table->version, &bgp->router_id);
9df8b37c
PZ
12971 if (bgp->vrf_id == VRF_UNKNOWN)
12972 vty_out(vty, "%s", VRFID_NONE_STR);
12973 else
12974 vty_out(vty, "%u", bgp->vrf_id);
12975 vty_out(vty, "\n");
01eced22
AD
12976 vty_out(vty, "Default local pref %u, ",
12977 bgp->default_local_pref);
12978 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12979 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12980 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12981 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12982
07d0c4ed
DA
12983 vty_out(vty, "Originating default network %s\n\n",
12984 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12985 }
12986 header1 = 0;
12987 }
a636c635 12988
9bcb3eef 12989 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
12990 if (type == bgp_show_adj_route_received
12991 || type == bgp_show_adj_route_filtered) {
9bcb3eef 12992 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 12993 if (ain->peer != peer)
ea47320b 12994 continue;
6392aaa6 12995
2f9bc755
DS
12996 show_adj_route_header(
12997 vty, bgp, table, &header1, &header2,
12998 json, json_scode, json_ocode, wide);
6392aaa6 12999
6f4f49b2 13000 attr = *ain->attr;
f99def61
AD
13001 route_filtered = false;
13002
13003 /* Filter prefix using distribute list,
13004 * filter list or prefix list
13005 */
b54892e0 13006 const struct prefix *rn_p =
9bcb3eef 13007 bgp_dest_get_prefix(dest);
b54892e0
DS
13008 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13009 safi))
13010 == FILTER_DENY)
f99def61
AD
13011 route_filtered = true;
13012
13013 /* Filter prefix using route-map */
b54892e0
DS
13014 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13015 safi, rmap_name, NULL,
13016 0, NULL);
6392aaa6 13017
13c8e163
AD
13018 if (type == bgp_show_adj_route_filtered &&
13019 !route_filtered && ret != RMAP_DENY) {
b755861b 13020 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13021 continue;
d62a17ae 13022 }
6392aaa6 13023
13c8e163
AD
13024 if (type == bgp_show_adj_route_received &&
13025 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
13026 filtered_count++;
13027
b54892e0 13028 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13029 use_json, json_ar, wide);
b755861b 13030 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13031 output_count++;
d62a17ae 13032 }
6392aaa6 13033 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13034 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13035 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13036 if (paf->peer != peer || !adj->attr)
924c3f6a 13037 continue;
d62a17ae 13038
2f9bc755
DS
13039 show_adj_route_header(
13040 vty, bgp, table, &header1,
13041 &header2, json, json_scode,
13042 json_ocode, wide);
d62a17ae 13043
b54892e0 13044 const struct prefix *rn_p =
9bcb3eef 13045 bgp_dest_get_prefix(dest);
b54892e0 13046
6f4f49b2 13047 attr = *adj->attr;
b755861b 13048 ret = bgp_output_modifier(
b54892e0 13049 peer, rn_p, &attr, afi, safi,
b755861b 13050 rmap_name);
f46d8e1e 13051
b755861b 13052 if (ret != RMAP_DENY) {
b54892e0
DS
13053 route_vty_out_tmp(
13054 vty, rn_p, &attr, safi,
ae248832
MK
13055 use_json, json_ar,
13056 wide);
b755861b
PM
13057 output_count++;
13058 } else {
13059 filtered_count++;
a2addae8 13060 }
b755861b
PM
13061
13062 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13063 }
f20ce998
DS
13064 } else if (type == bgp_show_adj_route_bestpath) {
13065 struct bgp_path_info *pi;
13066
13067 show_adj_route_header(vty, bgp, table, &header1,
13068 &header2, json, json_scode,
13069 json_ocode, wide);
13070
13071 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13072 pi = pi->next) {
13073 if (pi->peer != peer)
13074 continue;
13075
13076 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13077 continue;
13078
13079 route_vty_out_tmp(vty,
13080 bgp_dest_get_prefix(dest),
13081 pi->attr, safi, use_json,
13082 json_ar, wide);
13083 output_count++;
13084 }
d62a17ae 13085 }
13086 }
d62a17ae 13087
d62a17ae 13088 if (use_json) {
6392aaa6
PM
13089 json_object_object_add(json, "advertisedRoutes", json_ar);
13090 json_object_int_add(json, "totalPrefixCounter", output_count);
13091 json_object_int_add(json, "filteredPrefixCounter",
13092 filtered_count);
13093
996c9314
LB
13094 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13095 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
13096
13097 if (!output_count && !filtered_count) {
13098 json_object_free(json_scode);
13099 json_object_free(json_ocode);
13100 }
13101
d62a17ae 13102 json_object_free(json);
6392aaa6
PM
13103 } else if (output_count > 0) {
13104 if (filtered_count > 0)
13105 vty_out(vty,
13106 "\nTotal number of prefixes %ld (%ld filtered)\n",
13107 output_count, filtered_count);
13108 else
13109 vty_out(vty, "\nTotal number of prefixes %ld\n",
13110 output_count);
d62a17ae 13111 }
a636c635 13112}
2a71e9ce 13113
d62a17ae 13114static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13115 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13116 const char *rmap_name, uint8_t show_flags)
0b16f239 13117{
d62a17ae 13118 json_object *json = NULL;
96f3485c 13119 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13120
d62a17ae 13121 if (use_json)
13122 json = json_object_new_object();
0b16f239 13123
d62a17ae 13124 if (!peer || !peer->afc[afi][safi]) {
13125 if (use_json) {
13126 json_object_string_add(
13127 json, "warning",
13128 "No such neighbor or address family");
13129 vty_out(vty, "%s\n", json_object_to_json_string(json));
13130 json_object_free(json);
13131 } else
13132 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13133
d62a17ae 13134 return CMD_WARNING;
13135 }
13136
6392aaa6
PM
13137 if ((type == bgp_show_adj_route_received
13138 || type == bgp_show_adj_route_filtered)
d62a17ae 13139 && !CHECK_FLAG(peer->af_flags[afi][safi],
13140 PEER_FLAG_SOFT_RECONFIG)) {
13141 if (use_json) {
13142 json_object_string_add(
13143 json, "warning",
13144 "Inbound soft reconfiguration not enabled");
13145 vty_out(vty, "%s\n", json_object_to_json_string(json));
13146 json_object_free(json);
13147 } else
13148 vty_out(vty,
13149 "%% Inbound soft reconfiguration not enabled\n");
13150
13151 return CMD_WARNING;
13152 }
0b16f239 13153
96f3485c 13154 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 13155
d62a17ae 13156 return CMD_SUCCESS;
a636c635 13157}
50ef26d4 13158
f20ce998
DS
13159DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13160 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13161 "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]",
13162 SHOW_STR
13163 IP_STR
13164 BGP_STR
13165 BGP_INSTANCE_HELP_STR
13166 BGP_AFI_HELP_STR
13167 BGP_SAFI_WITH_LABEL_HELP_STR
13168 "Detailed information on TCP and BGP neighbor connections\n"
13169 "Neighbor to display information about\n"
13170 "Neighbor to display information about\n"
13171 "Neighbor on BGP configured interface\n"
13172 "Display the routes selected by best path\n"
13173 JSON_STR
13174 "Increase table width for longer prefixes\n")
13175{
13176 afi_t afi = AFI_IP6;
13177 safi_t safi = SAFI_UNICAST;
13178 char *rmap_name = NULL;
13179 char *peerstr = NULL;
13180 struct bgp *bgp = NULL;
13181 struct peer *peer;
13182 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13183 int idx = 0;
96f3485c
MK
13184 uint8_t show_flags = 0;
13185
13186 if (uj)
13187 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13188
13189 if (wide)
13190 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13191
13192 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13193 &bgp, uj);
13194
13195 if (!idx)
13196 return CMD_WARNING;
13197
13198 argv_find(argv, argc, "neighbors", &idx);
13199 peerstr = argv[++idx]->arg;
13200
13201 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13202 if (!peer)
13203 return CMD_WARNING;
13204
96f3485c
MK
13205 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13206 show_flags);
f20ce998
DS
13207}
13208
ae248832 13209DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13210 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13211 "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 13212 SHOW_STR
13213 IP_STR
13214 BGP_STR
a636c635 13215 BGP_INSTANCE_HELP_STR
7395a2c9 13216 BGP_AFI_HELP_STR
4dd6177e 13217 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13218 "Display the entries for all address families\n"
718e3744 13219 "Detailed information on TCP and BGP neighbor connections\n"
13220 "Neighbor to display information about\n"
13221 "Neighbor to display information about\n"
91d37724 13222 "Neighbor on BGP configured interface\n"
a636c635 13223 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13224 "Display the received routes from neighbor\n"
13225 "Display the filtered routes received from neighbor\n"
a636c635
DW
13226 "Route-map to modify the attributes\n"
13227 "Name of the route map\n"
ae248832
MK
13228 JSON_STR
13229 "Increase table width for longer prefixes\n")
718e3744 13230{
d62a17ae 13231 afi_t afi = AFI_IP6;
13232 safi_t safi = SAFI_UNICAST;
13233 char *rmap_name = NULL;
13234 char *peerstr = NULL;
d62a17ae 13235 struct bgp *bgp = NULL;
13236 struct peer *peer;
6392aaa6 13237 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13238 int idx = 0;
96f3485c
MK
13239 bool first = true;
13240 uint8_t show_flags = 0;
6392aaa6 13241
96f3485c 13242 if (uj) {
d62a17ae 13243 argc--;
96f3485c
MK
13244 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13245 }
13246
13247 if (all) {
13248 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13249 if (argv_find(argv, argc, "ipv4", &idx))
13250 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13251
13252 if (argv_find(argv, argc, "ipv6", &idx))
13253 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13254 }
13255
13256 if (wide)
13257 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13258
9f049418
DS
13259 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13260 &bgp, uj);
13261 if (!idx)
13262 return CMD_WARNING;
13263
d62a17ae 13264 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13265 argv_find(argv, argc, "neighbors", &idx);
13266 peerstr = argv[++idx]->arg;
8c3deaae 13267
d62a17ae 13268 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13269 if (!peer)
13270 return CMD_WARNING;
856ca177 13271
d62a17ae 13272 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13273 type = bgp_show_adj_route_advertised;
13274 else if (argv_find(argv, argc, "received-routes", &idx))
13275 type = bgp_show_adj_route_received;
13276 else if (argv_find(argv, argc, "filtered-routes", &idx))
13277 type = bgp_show_adj_route_filtered;
13278
d62a17ae 13279 if (argv_find(argv, argc, "route-map", &idx))
13280 rmap_name = argv[++idx]->arg;
95cbbd2a 13281
96f3485c
MK
13282 if (!all)
13283 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13284 show_flags);
13285 if (uj)
13286 vty_out(vty, "{\n");
13287
13288 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13289 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13290 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13291 : AFI_IP6;
13292 FOREACH_SAFI (safi) {
13293 if (strmatch(get_afi_safi_str(afi, safi, true),
13294 "Unknown"))
13295 continue;
13296
13297 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13298 continue;
13299
13300 if (uj) {
13301 if (first)
13302 first = false;
13303 else
13304 vty_out(vty, ",\n");
13305 vty_out(vty, "\"%s\":",
13306 get_afi_safi_str(afi, safi, true));
13307 } else
13308 vty_out(vty, "\nFor address family: %s\n",
13309 get_afi_safi_str(afi, safi, false));
13310
13311 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13312 show_flags);
13313 }
13314 } else {
13315 FOREACH_AFI_SAFI (afi, safi) {
13316 if (strmatch(get_afi_safi_str(afi, safi, true),
13317 "Unknown"))
13318 continue;
13319
13320 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13321 continue;
13322
13323 if (uj) {
13324 if (first)
13325 first = false;
13326 else
13327 vty_out(vty, ",\n");
13328 vty_out(vty, "\"%s\":",
13329 get_afi_safi_str(afi, safi, true));
13330 } else
13331 vty_out(vty, "\nFor address family: %s\n",
13332 get_afi_safi_str(afi, safi, false));
13333
13334 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13335 show_flags);
13336 }
13337 }
13338 if (uj)
13339 vty_out(vty, "}\n");
13340
13341 return CMD_SUCCESS;
95cbbd2a
ML
13342}
13343
718e3744 13344DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13345 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13346 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13347 SHOW_STR
13348 IP_STR
13349 BGP_STR
8c3deaae
QY
13350 "Address Family\n"
13351 "Address Family\n"
718e3744 13352 "Address Family modifier\n"
13353 "Detailed information on TCP and BGP neighbor connections\n"
13354 "Neighbor to display information about\n"
13355 "Neighbor to display information about\n"
91d37724 13356 "Neighbor on BGP configured interface\n"
718e3744 13357 "Display information received from a BGP neighbor\n"
856ca177 13358 "Display the prefixlist filter\n"
9973d184 13359 JSON_STR)
718e3744 13360{
d62a17ae 13361 afi_t afi = AFI_IP6;
13362 safi_t safi = SAFI_UNICAST;
13363 char *peerstr = NULL;
13364
13365 char name[BUFSIZ];
13366 union sockunion su;
13367 struct peer *peer;
13368 int count, ret;
13369
13370 int idx = 0;
13371
13372 /* show [ip] bgp */
13373 if (argv_find(argv, argc, "ip", &idx))
13374 afi = AFI_IP;
13375 /* [<ipv4|ipv6> [unicast]] */
13376 if (argv_find(argv, argc, "ipv4", &idx))
13377 afi = AFI_IP;
13378 if (argv_find(argv, argc, "ipv6", &idx))
13379 afi = AFI_IP6;
13380 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13381 argv_find(argv, argc, "neighbors", &idx);
13382 peerstr = argv[++idx]->arg;
13383
9f049418 13384 bool uj = use_json(argc, argv);
d62a17ae 13385
13386 ret = str2sockunion(peerstr, &su);
13387 if (ret < 0) {
13388 peer = peer_lookup_by_conf_if(NULL, peerstr);
13389 if (!peer) {
13390 if (uj)
13391 vty_out(vty, "{}\n");
13392 else
13393 vty_out(vty,
13394 "%% Malformed address or name: %s\n",
13395 peerstr);
13396 return CMD_WARNING;
13397 }
13398 } else {
13399 peer = peer_lookup(NULL, &su);
13400 if (!peer) {
13401 if (uj)
13402 vty_out(vty, "{}\n");
13403 else
13404 vty_out(vty, "No peer\n");
13405 return CMD_WARNING;
13406 }
13407 }
718e3744 13408
4ced1a2c 13409 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13410 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13411 if (count) {
13412 if (!uj)
13413 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13414 get_afi_safi_str(afi, safi, false));
d62a17ae 13415 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13416 } else {
13417 if (uj)
13418 vty_out(vty, "{}\n");
13419 else
13420 vty_out(vty, "No functional output\n");
13421 }
718e3744 13422
d62a17ae 13423 return CMD_SUCCESS;
13424}
13425
13426static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13427 afi_t afi, safi_t safi,
9f049418 13428 enum bgp_show_type type, bool use_json)
d62a17ae 13429{
96f3485c
MK
13430 uint8_t show_flags = 0;
13431
13432 if (use_json)
13433 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13434
d62a17ae 13435 if (!peer || !peer->afc[afi][safi]) {
13436 if (use_json) {
13437 json_object *json_no = NULL;
13438 json_no = json_object_new_object();
13439 json_object_string_add(
13440 json_no, "warning",
13441 "No such neighbor or address family");
13442 vty_out(vty, "%s\n",
13443 json_object_to_json_string(json_no));
13444 json_object_free(json_no);
13445 } else
13446 vty_out(vty, "%% No such neighbor or address family\n");
13447 return CMD_WARNING;
13448 }
47fc97cc 13449
7daf25a3
TA
13450 /* labeled-unicast routes live in the unicast table */
13451 if (safi == SAFI_LABELED_UNICAST)
13452 safi = SAFI_UNICAST;
13453
96f3485c 13454 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13455}
13456
dba3c1d3
PG
13457DEFUN (show_ip_bgp_flowspec_routes_detailed,
13458 show_ip_bgp_flowspec_routes_detailed_cmd,
13459 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13460 SHOW_STR
13461 IP_STR
13462 BGP_STR
13463 BGP_INSTANCE_HELP_STR
13464 BGP_AFI_HELP_STR
13465 "SAFI Flowspec\n"
13466 "Detailed information on flowspec entries\n"
13467 JSON_STR)
13468{
13469 afi_t afi = AFI_IP;
13470 safi_t safi = SAFI_UNICAST;
13471 struct bgp *bgp = NULL;
13472 int idx = 0;
9f049418 13473 bool uj = use_json(argc, argv);
96f3485c 13474 uint8_t show_flags = 0;
9f049418 13475
96f3485c 13476 if (uj) {
9f049418 13477 argc--;
96f3485c
MK
13478 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13479 }
dba3c1d3
PG
13480
13481 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13482 &bgp, uj);
dba3c1d3
PG
13483 if (!idx)
13484 return CMD_WARNING;
13485
96f3485c
MK
13486 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13487 show_flags);
dba3c1d3
PG
13488}
13489
718e3744 13490DEFUN (show_ip_bgp_neighbor_routes,
13491 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13492 "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 13493 SHOW_STR
13494 IP_STR
13495 BGP_STR
8386ac43 13496 BGP_INSTANCE_HELP_STR
4f280b15 13497 BGP_AFI_HELP_STR
4dd6177e 13498 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13499 "Detailed information on TCP and BGP neighbor connections\n"
13500 "Neighbor to display information about\n"
13501 "Neighbor to display information about\n"
91d37724 13502 "Neighbor on BGP configured interface\n"
2525cf39 13503 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13504 "Display the dampened routes received from neighbor\n"
13505 "Display routes learned from neighbor\n"
9973d184 13506 JSON_STR)
718e3744 13507{
d62a17ae 13508 char *peerstr = NULL;
13509 struct bgp *bgp = NULL;
13510 afi_t afi = AFI_IP6;
13511 safi_t safi = SAFI_UNICAST;
13512 struct peer *peer;
13513 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13514 int idx = 0;
9f049418
DS
13515 bool uj = use_json(argc, argv);
13516
13517 if (uj)
13518 argc--;
bb46e94f 13519
d62a17ae 13520 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13521 &bgp, uj);
d62a17ae 13522 if (!idx)
13523 return CMD_WARNING;
c493f2d8 13524
d62a17ae 13525 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13526 argv_find(argv, argc, "neighbors", &idx);
13527 peerstr = argv[++idx]->arg;
8c3deaae 13528
d62a17ae 13529 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13530 if (!peer)
d62a17ae 13531 return CMD_WARNING;
bb46e94f 13532
d62a17ae 13533 if (argv_find(argv, argc, "flap-statistics", &idx))
13534 sh_type = bgp_show_type_flap_neighbor;
13535 else if (argv_find(argv, argc, "dampened-routes", &idx))
13536 sh_type = bgp_show_type_damp_neighbor;
13537 else if (argv_find(argv, argc, "routes", &idx))
13538 sh_type = bgp_show_type_neighbor;
2525cf39 13539
d62a17ae 13540 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13541}
6b0655a2 13542
734b349e 13543struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13544
d62a17ae 13545struct bgp_distance {
13546 /* Distance value for the IP source prefix. */
d7c0a89a 13547 uint8_t distance;
718e3744 13548
d62a17ae 13549 /* Name of the access-list to be matched. */
13550 char *access_list;
718e3744 13551};
13552
4f280b15
LB
13553DEFUN (show_bgp_afi_vpn_rd_route,
13554 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13555 "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
13556 SHOW_STR
13557 BGP_STR
13558 BGP_AFI_HELP_STR
13559 "Address Family modifier\n"
13560 "Display information for a route distinguisher\n"
13561 "Route Distinguisher\n"
7395a2c9
DS
13562 "Network in the BGP routing table to display\n"
13563 "Network in the BGP routing table to display\n"
13564 JSON_STR)
4f280b15 13565{
d62a17ae 13566 int ret;
13567 struct prefix_rd prd;
13568 afi_t afi = AFI_MAX;
13569 int idx = 0;
4f280b15 13570
ff6566f3
DS
13571 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13572 vty_out(vty, "%% Malformed Address Family\n");
13573 return CMD_WARNING;
13574 }
13575
d62a17ae 13576 ret = str2prefix_rd(argv[5]->arg, &prd);
13577 if (!ret) {
13578 vty_out(vty, "%% Malformed Route Distinguisher\n");
13579 return CMD_WARNING;
13580 }
ff6566f3 13581
d62a17ae 13582 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13583 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13584}
13585
d62a17ae 13586static struct bgp_distance *bgp_distance_new(void)
718e3744 13587{
d62a17ae 13588 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13589}
13590
d62a17ae 13591static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13592{
d62a17ae 13593 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13594}
13595
37a87b8f
CS
13596int bgp_distance_set(uint8_t distance, const char *ip_str,
13597 const char *access_list_str, afi_t afi, safi_t safi,
13598 char *errmsg, size_t errmsg_len)
718e3744 13599{
d62a17ae 13600 int ret;
d62a17ae 13601 struct prefix p;
9bcb3eef 13602 struct bgp_dest *dest;
d62a17ae 13603 struct bgp_distance *bdistance;
718e3744 13604
d62a17ae 13605 ret = str2prefix(ip_str, &p);
13606 if (ret == 0) {
37a87b8f 13607 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13608 return CMD_WARNING_CONFIG_FAILED;
13609 }
718e3744 13610
d62a17ae 13611 /* Get BGP distance node. */
9bcb3eef
DS
13612 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13613 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13614 if (bdistance)
9bcb3eef 13615 bgp_dest_unlock_node(dest);
ca2e160d 13616 else {
d62a17ae 13617 bdistance = bgp_distance_new();
9bcb3eef 13618 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13619 }
718e3744 13620
d62a17ae 13621 /* Set distance value. */
13622 bdistance->distance = distance;
718e3744 13623
d62a17ae 13624 /* Reset access-list configuration. */
e1b36e13 13625 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13626 if (access_list_str)
13627 bdistance->access_list =
13628 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13629
d62a17ae 13630 return CMD_SUCCESS;
718e3744 13631}
13632
37a87b8f
CS
13633int bgp_distance_unset(uint8_t distance, const char *ip_str,
13634 const char *access_list_str, afi_t afi, safi_t safi,
13635 char *errmsg, size_t errmsg_len)
718e3744 13636{
d62a17ae 13637 int ret;
d62a17ae 13638 struct prefix p;
9bcb3eef 13639 struct bgp_dest *dest;
d62a17ae 13640 struct bgp_distance *bdistance;
718e3744 13641
d62a17ae 13642 ret = str2prefix(ip_str, &p);
13643 if (ret == 0) {
37a87b8f 13644 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13645 return CMD_WARNING_CONFIG_FAILED;
13646 }
718e3744 13647
9bcb3eef
DS
13648 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13649 if (!dest) {
37a87b8f 13650 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13651 return CMD_WARNING_CONFIG_FAILED;
13652 }
718e3744 13653
9bcb3eef 13654 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13655
d62a17ae 13656 if (bdistance->distance != distance) {
37a87b8f
CS
13657 snprintf(errmsg, errmsg_len,
13658 "Distance does not match configured\n");
d62a17ae 13659 return CMD_WARNING_CONFIG_FAILED;
13660 }
718e3744 13661
0a22ddfb 13662 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13663 bgp_distance_free(bdistance);
718e3744 13664
9bcb3eef
DS
13665 bgp_dest_set_bgp_path_info(dest, NULL);
13666 bgp_dest_unlock_node(dest);
13667 bgp_dest_unlock_node(dest);
718e3744 13668
d62a17ae 13669 return CMD_SUCCESS;
718e3744 13670}
13671
718e3744 13672/* Apply BGP information to distance method. */
b8685f9b 13673uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13674 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13675{
9bcb3eef 13676 struct bgp_dest *dest;
d62a17ae 13677 struct prefix q;
13678 struct peer *peer;
13679 struct bgp_distance *bdistance;
13680 struct access_list *alist;
13681 struct bgp_static *bgp_static;
13682
13683 if (!bgp)
13684 return 0;
13685
40381db7 13686 peer = pinfo->peer;
d62a17ae 13687
7b7d48e5
DS
13688 if (pinfo->attr->distance)
13689 return pinfo->attr->distance;
13690
d62a17ae 13691 /* Check source address. */
13692 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
13693 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13694 if (dest) {
13695 bdistance = bgp_dest_get_bgp_distance_info(dest);
13696 bgp_dest_unlock_node(dest);
d62a17ae 13697
13698 if (bdistance->access_list) {
13699 alist = access_list_lookup(afi, bdistance->access_list);
13700 if (alist
13701 && access_list_apply(alist, p) == FILTER_PERMIT)
13702 return bdistance->distance;
13703 } else
13704 return bdistance->distance;
718e3744 13705 }
718e3744 13706
d62a17ae 13707 /* Backdoor check. */
9bcb3eef
DS
13708 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13709 if (dest) {
13710 bgp_static = bgp_dest_get_bgp_static_info(dest);
13711 bgp_dest_unlock_node(dest);
718e3744 13712
d62a17ae 13713 if (bgp_static->backdoor) {
13714 if (bgp->distance_local[afi][safi])
13715 return bgp->distance_local[afi][safi];
13716 else
13717 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13718 }
718e3744 13719 }
718e3744 13720
d62a17ae 13721 if (peer->sort == BGP_PEER_EBGP) {
13722 if (bgp->distance_ebgp[afi][safi])
13723 return bgp->distance_ebgp[afi][safi];
13724 return ZEBRA_EBGP_DISTANCE_DEFAULT;
13725 } else {
13726 if (bgp->distance_ibgp[afi][safi])
13727 return bgp->distance_ibgp[afi][safi];
13728 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13729 }
718e3744 13730}
13731
a612fb77
DA
13732/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13733 * we should tell ZEBRA update the routes for a specific
13734 * AFI/SAFI to reflect changes in RIB.
13735 */
37a87b8f
CS
13736void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
13737 safi_t update_safi)
a612fb77
DA
13738{
13739 afi_t afi;
13740 safi_t safi;
13741
13742 FOREACH_AFI_SAFI (afi, safi) {
13743 if (!bgp_fibupd_safi(safi))
13744 continue;
13745
8b54bc30
DA
13746 if (afi != update_afi && safi != update_safi)
13747 continue;
13748
13749 if (BGP_DEBUG(zebra, ZEBRA))
13750 zlog_debug(
13751 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13752 __func__, afi, safi);
13753 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13754 }
13755}
13756
37a87b8f
CS
13757DEFUN_YANG(bgp_distance, bgp_distance_cmd,
13758 "distance bgp (1-255) (1-255) (1-255)",
13759 "Define an administrative distance\n"
13760 "BGP distance\n"
13761 "Distance for routes external to the AS\n"
13762 "Distance for routes internal to the AS\n"
13763 "Distance for local routes\n")
718e3744 13764{
d62a17ae 13765 int idx_number = 2;
13766 int idx_number_2 = 3;
13767 int idx_number_3 = 4;
13768 afi_t afi;
13769 safi_t safi;
37a87b8f 13770 char xpath[XPATH_MAXLEN];
718e3744 13771
d62a17ae 13772 afi = bgp_node_afi(vty);
13773 safi = bgp_node_safi(vty);
718e3744 13774
37a87b8f
CS
13775 snprintf(
13776 xpath, sizeof(xpath),
13777 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13778 yang_afi_safi_value2identity(afi, safi),
13779 bgp_afi_safi_get_container_str(afi, safi));
13780 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
13781 snprintf(
13782 xpath, sizeof(xpath),
13783 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13784 yang_afi_safi_value2identity(afi, safi),
13785 bgp_afi_safi_get_container_str(afi, safi));
13786 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13787 argv[idx_number_2]->arg);
13788 snprintf(
13789 xpath, sizeof(xpath),
13790 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13791 yang_afi_safi_value2identity(afi, safi),
13792 bgp_afi_safi_get_container_str(afi, safi));
13793
13794 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
13795 argv[idx_number_3]->arg);
13796
13797 return nb_cli_apply_changes(vty, NULL);
13798}
13799
13800DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
13801 "no distance bgp [(1-255) (1-255) (1-255)]",
13802 NO_STR
13803 "Define an administrative distance\n"
13804 "BGP distance\n"
13805 "Distance for routes external to the AS\n"
13806 "Distance for routes internal to the AS\n"
13807 "Distance for local routes\n")
13808{
13809 afi_t afi;
13810 safi_t safi;
13811 char xpath[XPATH_MAXLEN];
13812
13813 afi = bgp_node_afi(vty);
13814 safi = bgp_node_safi(vty);
13815
13816 snprintf(
13817 xpath, sizeof(xpath),
13818 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
13819 yang_afi_safi_value2identity(afi, safi),
13820 bgp_afi_safi_get_container_str(afi, safi));
13821 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13822 snprintf(
13823 xpath, sizeof(xpath),
13824 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
13825 yang_afi_safi_value2identity(afi, safi),
13826 bgp_afi_safi_get_container_str(afi, safi));
13827 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13828 snprintf(
13829 xpath, sizeof(xpath),
13830 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
13831 yang_afi_safi_value2identity(afi, safi),
13832 bgp_afi_safi_get_container_str(afi, safi));
13833
13834 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
13835
13836 return nb_cli_apply_changes(vty, NULL);
718e3744 13837}
13838
37a87b8f
CS
13839void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
13840 struct lyd_node *dnode,
13841 bool show_defaults)
718e3744 13842{
37a87b8f
CS
13843 uint8_t distance_ebgp, distance_ibgp, distance_local;
13844
13845 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
13846 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
13847 distance_local = yang_dnode_get_uint8(dnode, "./local");
13848
13849 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
13850 distance_local);
13851}
13852
8cc7152a
CS
13853DEFPY_YANG(bgp_distance_source,
13854 bgp_distance_source_cmd,
13855 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
13856 NO_STR
13857 "Define an administrative distance\n"
8cc7152a 13858 "Distance value\n"
e12affc1
SW
13859 "IPv4 source prefix\n"
13860 "IPv6 source prefix\n"
37a87b8f 13861 "Access list name\n")
718e3744 13862{
37a87b8f
CS
13863 afi_t afi;
13864 safi_t safi;
13865 char xpath[XPATH_MAXLEN];
13866
13867 afi = bgp_node_afi(vty);
13868 safi = bgp_node_safi(vty);
13869
8cc7152a
CS
13870 if (!no) {
13871 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
13872 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
13873 distance_str);
13874 if (acl)
13875 nb_cli_enqueue_change(vty,
13876 "./access-list-policy-export",
13877 NB_OP_CREATE, acl);
13878 else
13879 nb_cli_enqueue_change(vty,
13880 "./access-list-policy-export",
13881 NB_OP_DESTROY, NULL);
13882 } else {
13883 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
13884 }
37a87b8f
CS
13885
13886 snprintf(
13887 xpath, sizeof(xpath),
13888 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
13889 yang_afi_safi_value2identity(afi, safi),
8cc7152a 13890 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
13891
13892 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
13893}
13894
37a87b8f
CS
13895void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
13896 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
13897{
13898 vty_out(vty, " distance %d %s %s\n",
13899 yang_dnode_get_uint8(dnode, "./distance"),
13900 yang_dnode_get_string(dnode, "./prefix"),
13901 (yang_dnode_exists(dnode, "./access-list-policy-export"))
13902 ? yang_dnode_get_string(dnode,
13903 "./access-list-policy-export")
13904 : "");
13905}
13906
d9ce5113
CS
13907DEFPY_YANG(bgp_dampening,
13908 bgp_dampening_cmd,
13909 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_supress]]",
37a87b8f
CS
13910 NO_STR
13911 "BGP Specific commands\n"
13912 "Enable route-flap dampening\n"
13913 "Half-life time for the penalty\n"
13914 "Value to start reusing a route\n"
13915 "Value to start suppressing a route\n"
13916 "Maximum duration to suppress a stable route\n")
13917{
13918 afi_t afi;
13919 safi_t safi;
13920 char xpath[XPATH_MAXLEN];
718e3744 13921
37a87b8f
CS
13922 afi = bgp_node_afi(vty);
13923 safi = bgp_node_safi(vty);
13924
d9ce5113
CS
13925 if (!no) {
13926 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
13927 if (argc == 6) {
13928 nb_cli_enqueue_change(vty, "./reach-decay",
13929 NB_OP_MODIFY, halflife_str);
13930 nb_cli_enqueue_change(vty, "./reuse-above",
13931 NB_OP_MODIFY, reuse_str);
13932 nb_cli_enqueue_change(vty, "./suppress-above",
13933 NB_OP_MODIFY, suppress_str);
13934 nb_cli_enqueue_change(vty, "./unreach-decay",
13935 NB_OP_MODIFY, max_supress_str);
13936 } if (argc == 3) {
13937 nb_cli_enqueue_change(vty, "./reach-decay",
13938 NB_OP_MODIFY, halflife_str);
13939 }
13940 } else {
13941 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
13942 }
7ebe9748 13943
37a87b8f
CS
13944 snprintf(
13945 xpath, sizeof(xpath),
13946 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
13947 yang_afi_safi_value2identity(afi, safi),
13948 bgp_afi_safi_get_container_str(afi, safi));
13949
13950 return nb_cli_apply_changes(vty, xpath);
718e3744 13951}
13952
37a87b8f
CS
13953void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
13954 struct lyd_node *dnode,
13955 bool show_defaults)
718e3744 13956{
37a87b8f
CS
13957 if (!yang_dnode_get_bool(dnode, "./enable"))
13958 return;
13959
13960 int half = DEFAULT_HALF_LIFE * 60;
13961 int reuse = DEFAULT_REUSE;
13962 int suppress = DEFAULT_SUPPRESS;
13963 int max;
13964
13965 half = yang_dnode_get_uint8(dnode, "../reach-decay");
13966 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
13967 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
13968 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
13969
13970 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13971 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13972 vty_out(vty, " bgp dampening\n");
13973 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
13974 && suppress == DEFAULT_SUPPRESS && max == half * 4)
13975 vty_out(vty, " bgp dampening %u\n", half);
13976 else
13977 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
13978 suppress, max);
718e3744 13979}
13980
718e3744 13981/* Display specified route of BGP table. */
d62a17ae 13982static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13983 const char *ip_str, afi_t afi, safi_t safi,
13984 struct prefix_rd *prd, int prefix_check)
13985{
13986 int ret;
13987 struct prefix match;
9bcb3eef
DS
13988 struct bgp_dest *dest;
13989 struct bgp_dest *rm;
40381db7
DS
13990 struct bgp_path_info *pi;
13991 struct bgp_path_info *pi_temp;
d62a17ae 13992 struct bgp *bgp;
13993 struct bgp_table *table;
13994
13995 /* BGP structure lookup. */
13996 if (view_name) {
13997 bgp = bgp_lookup_by_name(view_name);
13998 if (bgp == NULL) {
13999 vty_out(vty, "%% Can't find BGP instance %s\n",
14000 view_name);
14001 return CMD_WARNING;
14002 }
14003 } else {
14004 bgp = bgp_get_default();
14005 if (bgp == NULL) {
14006 vty_out(vty, "%% No BGP process is configured\n");
14007 return CMD_WARNING;
14008 }
718e3744 14009 }
718e3744 14010
d62a17ae 14011 /* Check IP address argument. */
14012 ret = str2prefix(ip_str, &match);
14013 if (!ret) {
14014 vty_out(vty, "%% address is malformed\n");
14015 return CMD_WARNING;
14016 }
718e3744 14017
d62a17ae 14018 match.family = afi2family(afi);
14019
14020 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14021 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14022 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14023 dest = bgp_route_next(dest)) {
14024 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14025
9bcb3eef 14026 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14027 continue;
9bcb3eef 14028 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14029 if (!table)
ea47320b
DL
14030 continue;
14031 if ((rm = bgp_node_match(table, &match)) == NULL)
14032 continue;
d62a17ae 14033
9bcb3eef 14034 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14035
ea47320b 14036 if (!prefix_check
b54892e0 14037 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14038 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14039 while (pi) {
14040 if (pi->extra && pi->extra->damp_info) {
14041 pi_temp = pi->next;
ea47320b 14042 bgp_damp_info_free(
40381db7 14043 pi->extra->damp_info,
a935f597 14044 1, afi, safi);
40381db7 14045 pi = pi_temp;
ea47320b 14046 } else
40381db7 14047 pi = pi->next;
d62a17ae 14048 }
ea47320b
DL
14049 }
14050
9bcb3eef 14051 bgp_dest_unlock_node(rm);
d62a17ae 14052 }
14053 } else {
9bcb3eef 14054 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14055 != NULL) {
9bcb3eef 14056 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14057
d62a17ae 14058 if (!prefix_check
9bcb3eef
DS
14059 || dest_p->prefixlen == match.prefixlen) {
14060 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14061 while (pi) {
14062 if (pi->extra && pi->extra->damp_info) {
14063 pi_temp = pi->next;
d62a17ae 14064 bgp_damp_info_free(
40381db7 14065 pi->extra->damp_info,
a935f597 14066 1, afi, safi);
40381db7 14067 pi = pi_temp;
d62a17ae 14068 } else
40381db7 14069 pi = pi->next;
d62a17ae 14070 }
14071 }
14072
9bcb3eef 14073 bgp_dest_unlock_node(dest);
d62a17ae 14074 }
14075 }
718e3744 14076
d62a17ae 14077 return CMD_SUCCESS;
718e3744 14078}
14079
14080DEFUN (clear_ip_bgp_dampening,
14081 clear_ip_bgp_dampening_cmd,
14082 "clear ip bgp dampening",
14083 CLEAR_STR
14084 IP_STR
14085 BGP_STR
14086 "Clear route flap dampening information\n")
14087{
a935f597 14088 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14089 return CMD_SUCCESS;
718e3744 14090}
14091
14092DEFUN (clear_ip_bgp_dampening_prefix,
14093 clear_ip_bgp_dampening_prefix_cmd,
14094 "clear ip bgp dampening A.B.C.D/M",
14095 CLEAR_STR
14096 IP_STR
14097 BGP_STR
14098 "Clear route flap dampening information\n"
0c7b1b01 14099 "IPv4 prefix\n")
718e3744 14100{
d62a17ae 14101 int idx_ipv4_prefixlen = 4;
14102 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14103 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14104}
14105
14106DEFUN (clear_ip_bgp_dampening_address,
14107 clear_ip_bgp_dampening_address_cmd,
14108 "clear ip bgp dampening A.B.C.D",
14109 CLEAR_STR
14110 IP_STR
14111 BGP_STR
14112 "Clear route flap dampening information\n"
14113 "Network to clear damping information\n")
14114{
d62a17ae 14115 int idx_ipv4 = 4;
14116 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14117 SAFI_UNICAST, NULL, 0);
718e3744 14118}
14119
14120DEFUN (clear_ip_bgp_dampening_address_mask,
14121 clear_ip_bgp_dampening_address_mask_cmd,
14122 "clear ip bgp dampening A.B.C.D A.B.C.D",
14123 CLEAR_STR
14124 IP_STR
14125 BGP_STR
14126 "Clear route flap dampening information\n"
14127 "Network to clear damping information\n"
14128 "Network mask\n")
14129{
d62a17ae 14130 int idx_ipv4 = 4;
14131 int idx_ipv4_2 = 5;
14132 int ret;
14133 char prefix_str[BUFSIZ];
718e3744 14134
d62a17ae 14135 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
14136 prefix_str);
14137 if (!ret) {
14138 vty_out(vty, "%% Inconsistent address and mask\n");
14139 return CMD_WARNING;
14140 }
718e3744 14141
d62a17ae 14142 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14143 NULL, 0);
718e3744 14144}
6b0655a2 14145
e3b78da8 14146static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14147{
14148 struct vty *vty = arg;
e3b78da8 14149 struct peer *peer = bucket->data;
825d9834
DS
14150 char buf[SU_ADDRSTRLEN];
14151
14152 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14153 sockunion2str(&peer->su, buf, sizeof(buf)));
14154}
14155
2a0e69ae
DS
14156DEFUN (show_bgp_listeners,
14157 show_bgp_listeners_cmd,
14158 "show bgp listeners",
14159 SHOW_STR
14160 BGP_STR
14161 "Display Listen Sockets and who created them\n")
14162{
14163 bgp_dump_listener_info(vty);
14164
14165 return CMD_SUCCESS;
14166}
14167
825d9834
DS
14168DEFUN (show_bgp_peerhash,
14169 show_bgp_peerhash_cmd,
14170 "show bgp peerhash",
14171 SHOW_STR
14172 BGP_STR
14173 "Display information about the BGP peerhash\n")
14174{
14175 struct list *instances = bm->bgp;
14176 struct listnode *node;
14177 struct bgp *bgp;
14178
14179 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14180 vty_out(vty, "BGP: %s\n", bgp->name);
14181 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14182 vty);
14183 }
14184
14185 return CMD_SUCCESS;
14186}
14187
587ff0fd 14188/* also used for encap safi */
2b791107
DL
14189static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14190 afi_t afi, safi_t safi)
d62a17ae 14191{
9bcb3eef
DS
14192 struct bgp_dest *pdest;
14193 struct bgp_dest *dest;
d62a17ae 14194 struct bgp_table *table;
b54892e0
DS
14195 const struct prefix *p;
14196 const struct prefix_rd *prd;
d62a17ae 14197 struct bgp_static *bgp_static;
14198 mpls_label_t label;
d62a17ae 14199 char rdbuf[RD_ADDRSTRLEN];
14200
14201 /* Network configuration. */
9bcb3eef
DS
14202 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14203 pdest = bgp_route_next(pdest)) {
14204 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14205 if (!table)
ea47320b 14206 continue;
d62a17ae 14207
9bcb3eef
DS
14208 for (dest = bgp_table_top(table); dest;
14209 dest = bgp_route_next(dest)) {
14210 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14211 if (bgp_static == NULL)
ea47320b 14212 continue;
d62a17ae 14213
9bcb3eef
DS
14214 p = bgp_dest_get_prefix(dest);
14215 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14216 pdest);
d62a17ae 14217
ea47320b 14218 /* "network" configuration display. */
06b9f471 14219 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14220 label = decode_label(&bgp_static->label);
14221
8228a9a7 14222 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14223 if (safi == SAFI_MPLS_VPN)
14224 vty_out(vty, " label %u", label);
14225
14226 if (bgp_static->rmap.name)
14227 vty_out(vty, " route-map %s",
14228 bgp_static->rmap.name);
e2a86ad9
DS
14229
14230 if (bgp_static->backdoor)
14231 vty_out(vty, " backdoor");
14232
ea47320b
DL
14233 vty_out(vty, "\n");
14234 }
14235 }
d62a17ae 14236}
14237
2b791107
DL
14238static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14239 afi_t afi, safi_t safi)
d62a17ae 14240{
9bcb3eef
DS
14241 struct bgp_dest *pdest;
14242 struct bgp_dest *dest;
d62a17ae 14243 struct bgp_table *table;
b54892e0
DS
14244 const struct prefix *p;
14245 const struct prefix_rd *prd;
d62a17ae 14246 struct bgp_static *bgp_static;
ff44f570 14247 char buf[PREFIX_STRLEN * 2];
d62a17ae 14248 char buf2[SU_ADDRSTRLEN];
14249 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14250 char esi_buf[ESI_BYTES];
d62a17ae 14251
14252 /* Network configuration. */
9bcb3eef
DS
14253 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14254 pdest = bgp_route_next(pdest)) {
14255 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14256 if (!table)
ea47320b 14257 continue;
d62a17ae 14258
9bcb3eef
DS
14259 for (dest = bgp_table_top(table); dest;
14260 dest = bgp_route_next(dest)) {
14261 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14262 if (bgp_static == NULL)
ea47320b 14263 continue;
d62a17ae 14264
ea47320b 14265 char *macrouter = NULL;
d62a17ae 14266
ea47320b
DL
14267 if (bgp_static->router_mac)
14268 macrouter = prefix_mac2str(
14269 bgp_static->router_mac, NULL, 0);
14270 if (bgp_static->eth_s_id)
0a50c248
AK
14271 esi_to_str(bgp_static->eth_s_id,
14272 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14273 p = bgp_dest_get_prefix(dest);
14274 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14275
ea47320b 14276 /* "network" configuration display. */
06b9f471 14277 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14278 if (p->u.prefix_evpn.route_type == 5) {
14279 char local_buf[PREFIX_STRLEN];
3714a385 14280 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14281 struct prefix_evpn *)p)
14282 ? AF_INET
14283 : AF_INET6;
3714a385 14284 inet_ntop(family,
14285 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14286 local_buf, PREFIX_STRLEN);
772270f3
QY
14287 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14288 p->u.prefix_evpn.prefix_addr
14289 .ip_prefix_length);
197cb530
PG
14290 } else {
14291 prefix2str(p, buf, sizeof(buf));
14292 }
ea47320b 14293
a4d82a8a
PZ
14294 if (bgp_static->gatewayIp.family == AF_INET
14295 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14296 inet_ntop(bgp_static->gatewayIp.family,
14297 &bgp_static->gatewayIp.u.prefix, buf2,
14298 sizeof(buf2));
ea47320b 14299 vty_out(vty,
7bcc8dac 14300 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14301 buf, rdbuf,
14302 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14303 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14304 macrouter);
14305
0a22ddfb 14306 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14307 }
14308 }
3da6fcd5
PG
14309}
14310
718e3744 14311/* Configuration of static route announcement and aggregate
14312 information. */
2b791107
DL
14313void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14314 safi_t safi)
d62a17ae 14315{
9bcb3eef 14316 struct bgp_dest *dest;
b54892e0 14317 const struct prefix *p;
d62a17ae 14318 struct bgp_static *bgp_static;
14319 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14320
2b791107
DL
14321 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14322 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14323 return;
14324 }
d62a17ae 14325
2b791107
DL
14326 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14327 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14328 return;
14329 }
d62a17ae 14330
14331 /* Network configuration. */
9bcb3eef
DS
14332 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14333 dest = bgp_route_next(dest)) {
14334 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14335 if (bgp_static == NULL)
ea47320b 14336 continue;
d62a17ae 14337
9bcb3eef 14338 p = bgp_dest_get_prefix(dest);
d62a17ae 14339
8228a9a7 14340 vty_out(vty, " network %pFX", p);
d62a17ae 14341
ea47320b
DL
14342 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14343 vty_out(vty, " label-index %u",
14344 bgp_static->label_index);
d62a17ae 14345
ea47320b
DL
14346 if (bgp_static->rmap.name)
14347 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14348
14349 if (bgp_static->backdoor)
14350 vty_out(vty, " backdoor");
718e3744 14351
ea47320b
DL
14352 vty_out(vty, "\n");
14353 }
14354
d62a17ae 14355 /* Aggregate-address configuration. */
9bcb3eef
DS
14356 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14357 dest = bgp_route_next(dest)) {
14358 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14359 if (bgp_aggregate == NULL)
ea47320b 14360 continue;
d62a17ae 14361
9bcb3eef 14362 p = bgp_dest_get_prefix(dest);
d62a17ae 14363
8228a9a7 14364 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14365
ea47320b
DL
14366 if (bgp_aggregate->as_set)
14367 vty_out(vty, " as-set");
d62a17ae 14368
ea47320b
DL
14369 if (bgp_aggregate->summary_only)
14370 vty_out(vty, " summary-only");
718e3744 14371
20894f50
DA
14372 if (bgp_aggregate->rmap.name)
14373 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14374
229757f1
DA
14375 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14376 vty_out(vty, " origin %s",
14377 bgp_origin2str(bgp_aggregate->origin));
14378
6aabb15d
RZ
14379 if (bgp_aggregate->match_med)
14380 vty_out(vty, " matching-MED-only");
14381
365ab2e7
RZ
14382 if (bgp_aggregate->suppress_map_name)
14383 vty_out(vty, " suppress-map %s",
14384 bgp_aggregate->suppress_map_name);
14385
ea47320b
DL
14386 vty_out(vty, "\n");
14387 }
d62a17ae 14388}
734b349e 14389
2b791107 14390void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14391 safi_t safi)
d62a17ae 14392{
9bcb3eef 14393 struct bgp_dest *dest;
d62a17ae 14394 struct bgp_distance *bdistance;
14395
14396 /* Distance configuration. */
14397 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14398 && bgp->distance_local[afi][safi]
14399 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14400 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14401 || bgp->distance_local[afi][safi]
14402 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14403 vty_out(vty, " distance bgp %d %d %d\n",
14404 bgp->distance_ebgp[afi][safi],
14405 bgp->distance_ibgp[afi][safi],
14406 bgp->distance_local[afi][safi]);
14407 }
734b349e 14408
9bcb3eef
DS
14409 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14410 dest = bgp_route_next(dest)) {
14411 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14412 if (bdistance != NULL)
56ca3b5b 14413 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14414 bdistance->distance, dest,
d62a17ae 14415 bdistance->access_list ? bdistance->access_list
14416 : "");
ca2e160d 14417 }
718e3744 14418}
14419
14420/* Allocate routing table structure and install commands. */
d62a17ae 14421void bgp_route_init(void)
14422{
14423 afi_t afi;
14424 safi_t safi;
14425
14426 /* Init BGP distance table. */
05c7a1cc 14427 FOREACH_AFI_SAFI (afi, safi)
960035b2 14428 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14429
14430 /* IPv4 BGP commands. */
14431 install_element(BGP_NODE, &bgp_table_map_cmd);
14432 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14433 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14434
554b3b10 14435 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14436
14437 /* IPv4 unicast configuration. */
14438 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14439 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14440 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14441
554b3b10 14442 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14443
14444 /* IPv4 multicast configuration. */
14445 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14446 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14447 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14448 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14449
14450 /* IPv4 labeled-unicast configuration. */
fb985e0c 14451 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14452 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14453
d62a17ae 14454 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14455 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14456 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14457 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14458 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14459 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14460 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14461 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14462
14463 install_element(VIEW_NODE,
14464 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14465 install_element(VIEW_NODE,
14466 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14467 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14468 install_element(VIEW_NODE,
14469 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14470#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14471 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14472#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14473 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14474 install_element(VIEW_NODE,
44c69747 14475 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14476
d62a17ae 14477 /* BGP dampening clear commands */
14478 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14479 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14480
d62a17ae 14481 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14482 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14483
14484 /* prefix count */
14485 install_element(ENABLE_NODE,
14486 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14487#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14488 install_element(ENABLE_NODE,
14489 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14490#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14491
d62a17ae 14492 /* New config IPv6 BGP commands. */
14493 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14494 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14495 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14496
554b3b10 14497 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14498
14499 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14500
fb985e0c
DA
14501 /* IPv6 labeled unicast address family. */
14502 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14503 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14504
d62a17ae 14505 install_element(BGP_NODE, &bgp_distance_cmd);
14506 install_element(BGP_NODE, &no_bgp_distance_cmd);
14507 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14508 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14509 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14510 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14511 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14512 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14513 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14514 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14515 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14516 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14517 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14518 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14519 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14520
ef5f4b23 14521 /* BGP dampening */
d9ce5113
CS
14522 install_element(BGP_NODE, &bgp_dampening_cmd);
14523 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14524 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14525 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14526 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14527 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14528 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14529
14530 /* Large Communities */
14531 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14532 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14533
14534 /* show bgp ipv4 flowspec detailed */
14535 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14536
2a0e69ae 14537 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14538 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14539}
14540
14541void bgp_route_finish(void)
14542{
14543 afi_t afi;
14544 safi_t safi;
14545
05c7a1cc
QY
14546 FOREACH_AFI_SAFI (afi, safi) {
14547 bgp_table_unlock(bgp_distance_table[afi][safi]);
14548 bgp_distance_table[afi][safi] = NULL;
14549 }
228da428 14550}