]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
bgpd: add `%pBD` for printing `struct bgp_dest *`
[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"
718e3744 73
49e5a4a0 74#ifdef ENABLE_BGP_VNC
f8b6f499
LB
75#include "bgpd/rfapi/rfapi_backend.h"
76#include "bgpd/rfapi/vnc_import_bgp.h"
77#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 78#endif
aee875b5
PG
79#include "bgpd/bgp_encap_types.h"
80#include "bgpd/bgp_encap_tlv.h"
684a7227 81#include "bgpd/bgp_evpn.h"
0a50c248 82#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 83#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 84#include "bgpd/bgp_flowspec.h"
98a9dbc7 85#include "bgpd/bgp_flowspec_util.h"
45918cfb 86#include "bgpd/bgp_pbr.h"
65efcfce 87
e2a86ad9
DS
88#ifndef VTYSH_EXTRACT_PL
89#include "bgpd/bgp_route_clippy.c"
90#endif
aee875b5 91
718e3744 92/* Extern from bgp_dump.c */
dde72586
SH
93extern const char *bgp_origin_str[];
94extern const char *bgp_origin_long_str[];
36235319 95const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
b7d08f5a 96/* PMSI strings. */
97#define PMSI_TNLTYPE_STR_NO_INFO "No info"
98#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
99static const struct message bgp_pmsi_tnltype_str[] = {
100 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
101 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
102 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
103 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
104 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
105 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
106 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
107 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 108 {0}
109};
b7d08f5a 110
9df8b37c
PZ
111#define VRFID_NONE_STR "-"
112
4a11bf2c 113DEFINE_HOOK(bgp_process,
9bcb3eef
DS
114 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
115 struct peer *peer, bool withdraw),
116 (bgp, afi, safi, bn, peer, withdraw))
4a11bf2c
DL
117
118
9bcb3eef 119struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 120 safi_t safi, const struct prefix *p,
d62a17ae 121 struct prefix_rd *prd)
122{
9bcb3eef
DS
123 struct bgp_dest *dest;
124 struct bgp_dest *pdest = NULL;
d62a17ae 125
126 assert(table);
d62a17ae 127
128 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
129 || (safi == SAFI_EVPN)) {
9bcb3eef 130 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 131
9bcb3eef
DS
132 if (!bgp_dest_has_bgp_path_info_data(pdest))
133 bgp_dest_set_bgp_table_info(
134 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 135 else
9bcb3eef
DS
136 bgp_dest_unlock_node(pdest);
137 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 138 }
718e3744 139
9bcb3eef 140 dest = bgp_node_get(table, p);
718e3744 141
d62a17ae 142 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
143 || (safi == SAFI_EVPN))
9bcb3eef 144 dest->pdest = pdest;
718e3744 145
9bcb3eef 146 return dest;
718e3744 147}
6b0655a2 148
9bcb3eef 149struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 150 safi_t safi, const struct prefix *p,
d62a17ae 151 struct prefix_rd *prd)
128ea8ab 152{
9bcb3eef
DS
153 struct bgp_dest *dest;
154 struct bgp_dest *pdest = NULL;
128ea8ab 155
d62a17ae 156 if (!table)
157 return NULL;
128ea8ab 158
d62a17ae 159 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
160 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
161 pdest = bgp_node_lookup(table, (struct prefix *)prd);
162 if (!pdest)
d62a17ae 163 return NULL;
128ea8ab 164
9bcb3eef
DS
165 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
166 bgp_dest_unlock_node(pdest);
d62a17ae 167 return NULL;
168 }
128ea8ab 169
9bcb3eef 170 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 171 }
128ea8ab 172
9bcb3eef 173 dest = bgp_node_lookup(table, p);
128ea8ab 174
9bcb3eef 175 return dest;
128ea8ab 176}
177
18ee8310
DS
178/* Allocate bgp_path_info_extra */
179static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 180{
4b7e6066
DS
181 struct bgp_path_info_extra *new;
182 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
183 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
184 new->label[0] = MPLS_INVALID_LABEL;
185 new->num_labels = 0;
3e3708cb
PG
186 new->bgp_fs_pbr = NULL;
187 new->bgp_fs_iprule = NULL;
d62a17ae 188 return new;
fb982c25
PJ
189}
190
a2e219fe 191void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 192{
4b7e6066 193 struct bgp_path_info_extra *e;
d62a17ae 194
c93a3b77
DS
195 if (!extra || !*extra)
196 return;
d62a17ae 197
c93a3b77
DS
198 e = *extra;
199 if (e->damp_info)
a935f597
DA
200 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
201 e->damp_info->safi);
d62a17ae 202
c93a3b77
DS
203 e->damp_info = NULL;
204 if (e->parent) {
40381db7 205 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 206
40381db7 207 if (bpi->net) {
0e70e6c8
DL
208 /* FIXME: since multiple e may have the same e->parent
209 * and e->parent->net is holding a refcount for each
210 * of them, we need to do some fudging here.
211 *
40381db7
DS
212 * WARNING: if bpi->net->lock drops to 0, bpi may be
213 * freed as well (because bpi->net was holding the
214 * last reference to bpi) => write after free!
0e70e6c8
DL
215 */
216 unsigned refcount;
217
40381db7
DS
218 bpi = bgp_path_info_lock(bpi);
219 refcount = bpi->net->lock - 1;
9bcb3eef 220 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 221 if (!refcount)
40381db7
DS
222 bpi->net = NULL;
223 bgp_path_info_unlock(bpi);
0e70e6c8 224 }
18ee8310 225 bgp_path_info_unlock(e->parent);
c93a3b77 226 e->parent = NULL;
d62a17ae 227 }
c93a3b77
DS
228
229 if (e->bgp_orig)
230 bgp_unlock(e->bgp_orig);
c26edcda 231
ce3c0614
PG
232 if ((*extra)->bgp_fs_iprule)
233 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 234 if ((*extra)->bgp_fs_pbr)
6a154c88 235 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 236 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
237}
238
18ee8310
DS
239/* Get bgp_path_info extra information for the given bgp_path_info, lazy
240 * allocated if required.
fb982c25 241 */
40381db7 242struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 243{
40381db7
DS
244 if (!pi->extra)
245 pi->extra = bgp_path_info_extra_new();
246 return pi->extra;
fb982c25
PJ
247}
248
718e3744 249/* Free bgp route information. */
9b6d8fcf 250static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 251{
05864da7 252 bgp_attr_unintern(&path->attr);
fb018d25 253
9b6d8fcf
DS
254 bgp_unlink_nexthop(path);
255 bgp_path_info_extra_free(&path->extra);
256 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
257 if (path->net)
258 bgp_addpath_free_info_data(&path->tx_addpath,
259 &path->net->tx_addpath);
718e3744 260
9b6d8fcf 261 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 262
9b6d8fcf 263 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 264}
265
9b6d8fcf 266struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 267{
9b6d8fcf
DS
268 path->lock++;
269 return path;
200df115 270}
271
9b6d8fcf 272struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 273{
9b6d8fcf
DS
274 assert(path && path->lock > 0);
275 path->lock--;
d62a17ae 276
9b6d8fcf 277 if (path->lock == 0) {
200df115 278#if 0
279 zlog_debug ("%s: unlocked and freeing", __func__);
280 zlog_backtrace (LOG_DEBUG);
281#endif
9b6d8fcf 282 bgp_path_info_free(path);
d62a17ae 283 return NULL;
284 }
200df115 285
286#if 0
9b6d8fcf 287 if (path->lock == 1)
200df115 288 {
289 zlog_debug ("%s: unlocked to 1", __func__);
290 zlog_backtrace (LOG_DEBUG);
291 }
292#endif
d62a17ae 293
9b6d8fcf 294 return path;
200df115 295}
296
f009ff26 297/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 298static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 299{
300 struct peer *peer;
301 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 302 bool set_flag = false;
f009ff26 303 struct bgp *bgp = NULL;
304 struct bgp_table *table = NULL;
305 afi_t afi = 0;
306 safi_t safi = 0;
f009ff26 307
308 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
309 * then the route selection is deferred
310 */
9bcb3eef 311 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 312 return 0;
313
9bcb3eef 314 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 315 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 316 zlog_debug(
56ca3b5b
DL
317 "Route %pBD is in workqueue and being processed, not deferred.",
318 dest);
b54892e0 319
5f9c1aa2 320 return 0;
321 }
322
9bcb3eef 323 table = bgp_dest_table(dest);
f009ff26 324 if (table) {
325 bgp = table->bgp;
326 afi = table->afi;
327 safi = table->safi;
328 }
329
9bcb3eef 330 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 331 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
332 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
333 continue;
334
335 /* Route selection is deferred if there is a stale path which
336 * which indicates peer is in restart mode
337 */
36235319
QY
338 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
339 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 340 set_flag = true;
f009ff26 341 } else {
342 /* If the peer is graceful restart capable and peer is
343 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
344 */
345 peer = old_pi->peer;
36235319
QY
346 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
347 && BGP_PEER_RESTARTING_MODE(peer)
348 && (old_pi
349 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 350 set_flag = true;
f009ff26 351 }
352 }
353 if (set_flag)
354 break;
355 }
356
357 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
358 * is active
359 */
2ba1fe69 360 if (set_flag && table) {
f009ff26 361 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
9bcb3eef
DS
362 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
363 if (dest->rt_node == NULL)
364 dest->rt_node = listnode_add(
365 bgp->gr_info[afi][safi].route_list,
366 dest);
f009ff26 367 if (BGP_DEBUG(update, UPDATE_OUT))
56ca3b5b 368 zlog_debug("DEFER route %pBD, dest %p, node %p",
9bcb3eef 369 dest, dest, dest->rt_node);
f009ff26 370 return 0;
371 }
372 }
373 return -1;
374}
375
9bcb3eef 376void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 377{
4b7e6066 378 struct bgp_path_info *top;
718e3744 379
9bcb3eef 380 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 381
6f94b685 382 pi->next = top;
40381db7 383 pi->prev = NULL;
d62a17ae 384 if (top)
40381db7 385 top->prev = pi;
9bcb3eef 386 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 387
40381db7 388 bgp_path_info_lock(pi);
9bcb3eef 389 bgp_dest_lock_node(dest);
40381db7 390 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 391 bgp_dest_set_defer_flag(dest, false);
718e3744 392}
393
d62a17ae 394/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 395 completion callback *only* */
9bcb3eef 396void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 397{
40381db7
DS
398 if (pi->next)
399 pi->next->prev = pi->prev;
400 if (pi->prev)
401 pi->prev->next = pi->next;
d62a17ae 402 else
9bcb3eef 403 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 404
40381db7
DS
405 bgp_path_info_mpath_dequeue(pi);
406 bgp_path_info_unlock(pi);
9bcb3eef 407 bgp_dest_unlock_node(dest);
718e3744 408}
409
9bcb3eef 410void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 411{
9bcb3eef 412 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 413 /* set of previous already took care of pcount */
40381db7 414 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 415}
416
18ee8310 417/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
418 called when a route is deleted and then quickly re-added before the
419 deletion has been processed */
9bcb3eef 420void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 421{
9bcb3eef 422 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 423 /* unset of previous already took care of pcount */
40381db7 424 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
425}
426
d62a17ae 427/* Adjust pcount as required */
9bcb3eef 428static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 429{
d62a17ae 430 struct bgp_table *table;
67174041 431
9bcb3eef 432 assert(dest && bgp_dest_table(dest));
40381db7 433 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 434
9bcb3eef 435 table = bgp_dest_table(dest);
67174041 436
40381db7 437 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 438 return;
439
40381db7
DS
440 if (!BGP_PATH_COUNTABLE(pi)
441 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 442
40381db7 443 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 444
445 /* slight hack, but more robust against errors. */
40381db7
DS
446 if (pi->peer->pcount[table->afi][table->safi])
447 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 448 else
450971aa 449 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 450 "Asked to decrement 0 prefix count for peer");
40381db7
DS
451 } else if (BGP_PATH_COUNTABLE(pi)
452 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
453 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
454 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 455 }
1a392d46
PJ
456}
457
40381db7
DS
458static int bgp_label_index_differs(struct bgp_path_info *pi1,
459 struct bgp_path_info *pi2)
28d58fd7 460{
40381db7 461 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 462}
1a392d46 463
18ee8310 464/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
465 * This is here primarily to keep prefix-count in check.
466 */
9bcb3eef 467void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 468 uint32_t flag)
1a392d46 469{
40381db7 470 SET_FLAG(pi->flags, flag);
d62a17ae 471
472 /* early bath if we know it's not a flag that changes countability state
473 */
474 if (!CHECK_FLAG(flag,
1defdda8 475 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 476 return;
477
9bcb3eef 478 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
479}
480
9bcb3eef 481void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 482 uint32_t flag)
1a392d46 483{
40381db7 484 UNSET_FLAG(pi->flags, flag);
d62a17ae 485
486 /* early bath if we know it's not a flag that changes countability state
487 */
488 if (!CHECK_FLAG(flag,
1defdda8 489 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 490 return;
491
9bcb3eef 492 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
493}
494
718e3744 495/* Get MED value. If MED value is missing and "bgp bestpath
496 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 497static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 498{
499 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
500 return attr->med;
501 else {
892fedb6 502 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 503 return BGP_MED_MAX;
504 else
505 return 0;
506 }
718e3744 507}
508
40381db7 509void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
2ec1e66f 510{
40381db7
DS
511 if (pi->addpath_rx_id)
512 sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
513 pi->addpath_rx_id);
d62a17ae 514 else
40381db7 515 sprintf(buf, "path %s", pi->peer->host);
d62a17ae 516}
9fbdd100 517
d62a17ae 518/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
519 */
18ee8310
DS
520static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
521 struct bgp_path_info *exist, int *paths_eq,
522 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
523 char *pfx_buf, afi_t afi, safi_t safi,
524 enum bgp_path_selection_reason *reason)
d62a17ae 525{
526 struct attr *newattr, *existattr;
527 bgp_peer_sort_t new_sort;
528 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
529 uint32_t new_pref;
530 uint32_t exist_pref;
531 uint32_t new_med;
532 uint32_t exist_med;
533 uint32_t new_weight;
534 uint32_t exist_weight;
d62a17ae 535 uint32_t newm, existm;
536 struct in_addr new_id;
537 struct in_addr exist_id;
538 int new_cluster;
539 int exist_cluster;
540 int internal_as_route;
541 int confed_as_route;
04d14c8b 542 int ret = 0;
d62a17ae 543 char new_buf[PATH_ADDPATH_STR_BUFFER];
544 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
545 uint32_t new_mm_seq;
546 uint32_t exist_mm_seq;
6d8c603a 547 int nh_cmp;
d071f237
AK
548 esi_t *exist_esi;
549 esi_t *new_esi;
550 bool same_esi;
551 bool old_proxy;
552 bool new_proxy;
d62a17ae 553
554 *paths_eq = 0;
555
556 /* 0. Null check. */
557 if (new == NULL) {
fdf81fa0 558 *reason = bgp_path_selection_none;
d62a17ae 559 if (debug)
560 zlog_debug("%s: new is NULL", pfx_buf);
561 return 0;
562 }
2ec1e66f 563
d62a17ae 564 if (debug)
18ee8310 565 bgp_path_info_path_with_addpath_rx_str(new, new_buf);
718e3744 566
d62a17ae 567 if (exist == NULL) {
fdf81fa0 568 *reason = bgp_path_selection_first;
d62a17ae 569 if (debug)
570 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
571 new_buf);
572 return 1;
573 }
2ec1e66f 574
d62a17ae 575 if (debug) {
18ee8310 576 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
d62a17ae 577 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
578 pfx_buf, new_buf, new->flags, exist_buf,
579 exist->flags);
580 }
8ff56318 581
d62a17ae 582 newattr = new->attr;
583 existattr = exist->attr;
584
585 /* For EVPN routes, we cannot just go by local vs remote, we have to
586 * look at the MAC mobility sequence number, if present.
587 */
588 if (safi == SAFI_EVPN) {
589 /* This is an error condition described in RFC 7432 Section
590 * 15.2. The RFC
591 * states that in this scenario "the PE MUST alert the operator"
592 * but it
593 * does not state what other action to take. In order to provide
594 * some
595 * consistency in this scenario we are going to prefer the path
596 * with the
597 * sticky flag.
598 */
599 if (newattr->sticky != existattr->sticky) {
600 if (!debug) {
9bcb3eef
DS
601 prefix2str(
602 bgp_dest_get_prefix(new->net), pfx_buf,
603 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310
DS
604 bgp_path_info_path_with_addpath_rx_str(new,
605 new_buf);
606 bgp_path_info_path_with_addpath_rx_str(
607 exist, exist_buf);
d62a17ae 608 }
609
610 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 611 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
612 if (debug)
613 zlog_debug(
614 "%s: %s wins over %s due to sticky MAC flag",
615 pfx_buf, new_buf, exist_buf);
d62a17ae 616 return 1;
617 }
618
619 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 620 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
621 if (debug)
622 zlog_debug(
623 "%s: %s loses to %s due to sticky MAC flag",
624 pfx_buf, new_buf, exist_buf);
d62a17ae 625 return 0;
626 }
627 }
128ea8ab 628
d071f237
AK
629 new_esi = bgp_evpn_attr_get_esi(newattr);
630 exist_esi = bgp_evpn_attr_get_esi(existattr);
631 if (bgp_evpn_is_esi_valid(new_esi) &&
632 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
633 same_esi = true;
634 } else {
635 same_esi = false;
636 }
637
638 /* If both paths have the same non-zero ES and
639 * one path is local it wins.
640 * PS: Note the local path wins even if the remote
641 * has the higher MM seq. The local path's
642 * MM seq will be fixed up to match the highest
643 * rem seq, subsequently.
644 */
645 if (same_esi) {
646 char esi_buf[ESI_STR_LEN];
647
648 if (bgp_evpn_is_path_local(bgp, new)) {
649 *reason = bgp_path_selection_evpn_local_path;
650 if (debug)
651 zlog_debug(
652 "%s: %s wins over %s as ES %s is same and local",
653 pfx_buf, new_buf, exist_buf,
654 esi_to_str(new_esi, esi_buf,
655 sizeof(esi_buf)));
656 return 1;
657 }
658 if (bgp_evpn_is_path_local(bgp, exist)) {
659 *reason = bgp_path_selection_evpn_local_path;
660 if (debug)
661 zlog_debug(
662 "%s: %s loses to %s as ES %s is same and local",
663 pfx_buf, new_buf, exist_buf,
664 esi_to_str(new_esi, esi_buf,
665 sizeof(esi_buf)));
666 return 0;
667 }
668 }
669
d62a17ae 670 new_mm_seq = mac_mobility_seqnum(newattr);
671 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 672
d62a17ae 673 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 674 *reason = bgp_path_selection_evpn_seq;
d62a17ae 675 if (debug)
676 zlog_debug(
677 "%s: %s wins over %s due to MM seq %u > %u",
678 pfx_buf, new_buf, exist_buf, new_mm_seq,
679 exist_mm_seq);
680 return 1;
681 }
8ff56318 682
d62a17ae 683 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 684 *reason = bgp_path_selection_evpn_seq;
d62a17ae 685 if (debug)
686 zlog_debug(
687 "%s: %s loses to %s due to MM seq %u < %u",
688 pfx_buf, new_buf, exist_buf, new_mm_seq,
689 exist_mm_seq);
690 return 0;
691 }
6d8c603a 692
d071f237
AK
693 /* if the sequence numbers and ESI are the same and one path
694 * is non-proxy it wins (over proxy)
695 */
696 new_proxy = bgp_evpn_attr_is_proxy(newattr);
697 old_proxy = bgp_evpn_attr_is_proxy(existattr);
698 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
699 old_proxy != new_proxy) {
700 if (!new_proxy) {
701 *reason = bgp_path_selection_evpn_non_proxy;
702 if (debug)
703 zlog_debug(
704 "%s: %s wins over %s, same seq/es and non-proxy",
705 pfx_buf, new_buf, exist_buf);
706 return 1;
707 }
708
709 *reason = bgp_path_selection_evpn_non_proxy;
710 if (debug)
711 zlog_debug(
712 "%s: %s loses to %s, same seq/es and non-proxy",
713 pfx_buf, new_buf, exist_buf);
714 return 0;
715 }
716
6d8c603a
AK
717 /*
718 * if sequence numbers are the same path with the lowest IP
719 * wins
720 */
721 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
722 if (nh_cmp < 0) {
fdf81fa0 723 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
724 if (debug)
725 zlog_debug(
726 "%s: %s wins over %s due to same MM seq %u and lower IP %s",
727 pfx_buf, new_buf, exist_buf, new_mm_seq,
728 inet_ntoa(new->attr->nexthop));
729 return 1;
730 }
731 if (nh_cmp > 0) {
fdf81fa0 732 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
733 if (debug)
734 zlog_debug(
735 "%s: %s loses to %s due to same MM seq %u and higher IP %s",
736 pfx_buf, new_buf, exist_buf, new_mm_seq,
737 inet_ntoa(new->attr->nexthop));
738 return 0;
739 }
d62a17ae 740 }
9fbdd100 741
d62a17ae 742 /* 1. Weight check. */
d62a17ae 743 new_weight = newattr->weight;
744 exist_weight = existattr->weight;
8ff56318 745
d62a17ae 746 if (new_weight > exist_weight) {
fdf81fa0 747 *reason = bgp_path_selection_weight;
d62a17ae 748 if (debug)
749 zlog_debug("%s: %s wins over %s due to weight %d > %d",
750 pfx_buf, new_buf, exist_buf, new_weight,
751 exist_weight);
752 return 1;
753 }
718e3744 754
d62a17ae 755 if (new_weight < exist_weight) {
fdf81fa0 756 *reason = bgp_path_selection_weight;
d62a17ae 757 if (debug)
758 zlog_debug("%s: %s loses to %s due to weight %d < %d",
759 pfx_buf, new_buf, exist_buf, new_weight,
760 exist_weight);
761 return 0;
762 }
9fbdd100 763
d62a17ae 764 /* 2. Local preference check. */
765 new_pref = exist_pref = bgp->default_local_pref;
766
767 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
768 new_pref = newattr->local_pref;
769 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
770 exist_pref = existattr->local_pref;
771
772 if (new_pref > exist_pref) {
fdf81fa0 773 *reason = bgp_path_selection_local_pref;
d62a17ae 774 if (debug)
775 zlog_debug(
776 "%s: %s wins over %s due to localpref %d > %d",
777 pfx_buf, new_buf, exist_buf, new_pref,
778 exist_pref);
779 return 1;
780 }
718e3744 781
d62a17ae 782 if (new_pref < exist_pref) {
fdf81fa0 783 *reason = bgp_path_selection_local_pref;
d62a17ae 784 if (debug)
785 zlog_debug(
786 "%s: %s loses to %s due to localpref %d < %d",
787 pfx_buf, new_buf, exist_buf, new_pref,
788 exist_pref);
789 return 0;
790 }
9fbdd100 791
d62a17ae 792 /* 3. Local route check. We prefer:
793 * - BGP_ROUTE_STATIC
794 * - BGP_ROUTE_AGGREGATE
795 * - BGP_ROUTE_REDISTRIBUTE
796 */
90f4f482 797 if (!(new->sub_type == BGP_ROUTE_NORMAL ||
798 new->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 799 *reason = bgp_path_selection_local_route;
d62a17ae 800 if (debug)
801 zlog_debug(
802 "%s: %s wins over %s due to preferred BGP_ROUTE type",
803 pfx_buf, new_buf, exist_buf);
804 return 1;
805 }
718e3744 806
90f4f482 807 if (!(exist->sub_type == BGP_ROUTE_NORMAL ||
88493076 808 exist->sub_type == BGP_ROUTE_IMPORTED)) {
fdf81fa0 809 *reason = bgp_path_selection_local_route;
d62a17ae 810 if (debug)
811 zlog_debug(
812 "%s: %s loses to %s due to preferred BGP_ROUTE type",
813 pfx_buf, new_buf, exist_buf);
814 return 0;
6811845b 815 }
718e3744 816
d62a17ae 817 /* 4. AS path length check. */
892fedb6 818 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 819 int exist_hops = aspath_count_hops(existattr->aspath);
820 int exist_confeds = aspath_count_confeds(existattr->aspath);
821
892fedb6 822 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 823 int aspath_hops;
824
825 aspath_hops = aspath_count_hops(newattr->aspath);
826 aspath_hops += aspath_count_confeds(newattr->aspath);
827
828 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 829 *reason = bgp_path_selection_confed_as_path;
d62a17ae 830 if (debug)
831 zlog_debug(
832 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
833 pfx_buf, new_buf, exist_buf,
834 aspath_hops,
835 (exist_hops + exist_confeds));
836 return 1;
837 }
838
839 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 840 *reason = bgp_path_selection_confed_as_path;
d62a17ae 841 if (debug)
842 zlog_debug(
843 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
844 pfx_buf, new_buf, exist_buf,
845 aspath_hops,
846 (exist_hops + exist_confeds));
847 return 0;
848 }
849 } else {
850 int newhops = aspath_count_hops(newattr->aspath);
851
852 if (newhops < exist_hops) {
fdf81fa0 853 *reason = bgp_path_selection_as_path;
d62a17ae 854 if (debug)
855 zlog_debug(
856 "%s: %s wins over %s due to aspath hopcount %d < %d",
857 pfx_buf, new_buf, exist_buf,
858 newhops, exist_hops);
859 return 1;
860 }
861
862 if (newhops > exist_hops) {
fdf81fa0 863 *reason = bgp_path_selection_as_path;
d62a17ae 864 if (debug)
865 zlog_debug(
866 "%s: %s loses to %s due to aspath hopcount %d > %d",
867 pfx_buf, new_buf, exist_buf,
868 newhops, exist_hops);
869 return 0;
870 }
871 }
872 }
9fbdd100 873
d62a17ae 874 /* 5. Origin check. */
875 if (newattr->origin < existattr->origin) {
fdf81fa0 876 *reason = bgp_path_selection_origin;
d62a17ae 877 if (debug)
878 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
879 pfx_buf, new_buf, exist_buf,
880 bgp_origin_long_str[newattr->origin],
881 bgp_origin_long_str[existattr->origin]);
882 return 1;
883 }
718e3744 884
d62a17ae 885 if (newattr->origin > existattr->origin) {
fdf81fa0 886 *reason = bgp_path_selection_origin;
d62a17ae 887 if (debug)
888 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
889 pfx_buf, new_buf, exist_buf,
890 bgp_origin_long_str[newattr->origin],
891 bgp_origin_long_str[existattr->origin]);
892 return 0;
893 }
718e3744 894
d62a17ae 895 /* 6. MED check. */
896 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
897 && aspath_count_hops(existattr->aspath) == 0);
898 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
899 && aspath_count_confeds(existattr->aspath) > 0
900 && aspath_count_hops(newattr->aspath) == 0
901 && aspath_count_hops(existattr->aspath) == 0);
902
892fedb6
DA
903 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
904 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 905 || aspath_cmp_left(newattr->aspath, existattr->aspath)
906 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
907 || internal_as_route) {
908 new_med = bgp_med_value(new->attr, bgp);
909 exist_med = bgp_med_value(exist->attr, bgp);
910
911 if (new_med < exist_med) {
fdf81fa0 912 *reason = bgp_path_selection_med;
d62a17ae 913 if (debug)
914 zlog_debug(
915 "%s: %s wins over %s due to MED %d < %d",
916 pfx_buf, new_buf, exist_buf, new_med,
917 exist_med);
918 return 1;
919 }
8ff56318 920
d62a17ae 921 if (new_med > exist_med) {
fdf81fa0 922 *reason = bgp_path_selection_med;
d62a17ae 923 if (debug)
924 zlog_debug(
925 "%s: %s loses to %s due to MED %d > %d",
926 pfx_buf, new_buf, exist_buf, new_med,
927 exist_med);
928 return 0;
929 }
930 }
9fbdd100 931
d62a17ae 932 /* 7. Peer type check. */
933 new_sort = new->peer->sort;
934 exist_sort = exist->peer->sort;
935
936 if (new_sort == BGP_PEER_EBGP
937 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 938 *reason = bgp_path_selection_peer;
d62a17ae 939 if (debug)
940 zlog_debug(
941 "%s: %s wins over %s due to eBGP peer > iBGP peer",
942 pfx_buf, new_buf, exist_buf);
943 return 1;
944 }
718e3744 945
d62a17ae 946 if (exist_sort == BGP_PEER_EBGP
947 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 948 *reason = bgp_path_selection_peer;
d62a17ae 949 if (debug)
950 zlog_debug(
951 "%s: %s loses to %s due to iBGP peer < eBGP peer",
952 pfx_buf, new_buf, exist_buf);
953 return 0;
954 }
8ff56318 955
d62a17ae 956 /* 8. IGP metric check. */
957 newm = existm = 0;
8ff56318 958
d62a17ae 959 if (new->extra)
960 newm = new->extra->igpmetric;
961 if (exist->extra)
962 existm = exist->extra->igpmetric;
9fbdd100 963
d62a17ae 964 if (newm < existm) {
965 if (debug)
966 zlog_debug(
967 "%s: %s wins over %s due to IGP metric %d < %d",
968 pfx_buf, new_buf, exist_buf, newm, existm);
969 ret = 1;
970 }
718e3744 971
d62a17ae 972 if (newm > existm) {
973 if (debug)
974 zlog_debug(
975 "%s: %s loses to %s due to IGP metric %d > %d",
976 pfx_buf, new_buf, exist_buf, newm, existm);
977 ret = 0;
5e242b0d 978 }
5e242b0d 979
d62a17ae 980 /* 9. Same IGP metric. Compare the cluster list length as
981 representative of IGP hops metric. Rewrite the metric value
982 pair (newm, existm) with the cluster list length. Prefer the
983 path with smaller cluster list length. */
984 if (newm == existm) {
bf0d28dc
DS
985 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
986 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 987 && (mpath_cfg == NULL
988 || CHECK_FLAG(
989 mpath_cfg->ibgp_flags,
990 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
991 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
992 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
993
994 if (newm < existm) {
995 if (debug)
996 zlog_debug(
997 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
998 pfx_buf, new_buf, exist_buf,
999 newm, existm);
1000 ret = 1;
1001 }
1002
1003 if (newm > existm) {
1004 if (debug)
1005 zlog_debug(
1006 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1007 pfx_buf, new_buf, exist_buf,
1008 newm, existm);
1009 ret = 0;
1010 }
1011 }
1012 }
31a4638f 1013
d62a17ae 1014 /* 10. confed-external vs. confed-internal */
1015 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1016 if (new_sort == BGP_PEER_CONFED
1017 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1018 *reason = bgp_path_selection_confed;
d62a17ae 1019 if (debug)
1020 zlog_debug(
1021 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1022 pfx_buf, new_buf, exist_buf);
1023 return 1;
1024 }
718e3744 1025
d62a17ae 1026 if (exist_sort == BGP_PEER_CONFED
1027 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1028 *reason = bgp_path_selection_confed;
d62a17ae 1029 if (debug)
1030 zlog_debug(
1031 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1032 pfx_buf, new_buf, exist_buf);
1033 return 0;
1034 }
1035 }
718e3744 1036
d62a17ae 1037 /* 11. Maximum path check. */
1038 if (newm == existm) {
1039 /* If one path has a label but the other does not, do not treat
1040 * them as equals for multipath
1041 */
a4d82a8a 1042 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1043 != (exist->extra
b57ba6d2 1044 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1045 if (debug)
1046 zlog_debug(
1047 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1048 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1049 } else if (CHECK_FLAG(bgp->flags,
1050 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1051
1052 /*
1053 * For the two paths, all comparison steps till IGP
1054 * metric
1055 * have succeeded - including AS_PATH hop count. Since
1056 * 'bgp
1057 * bestpath as-path multipath-relax' knob is on, we
1058 * don't need
1059 * an exact match of AS_PATH. Thus, mark the paths are
1060 * equal.
1061 * That will trigger both these paths to get into the
1062 * multipath
1063 * array.
1064 */
1065 *paths_eq = 1;
1066
1067 if (debug)
1068 zlog_debug(
1069 "%s: %s and %s are equal via multipath-relax",
1070 pfx_buf, new_buf, exist_buf);
1071 } else if (new->peer->sort == BGP_PEER_IBGP) {
1072 if (aspath_cmp(new->attr->aspath,
1073 exist->attr->aspath)) {
1074 *paths_eq = 1;
1075
1076 if (debug)
1077 zlog_debug(
1078 "%s: %s and %s are equal via matching aspaths",
1079 pfx_buf, new_buf, exist_buf);
1080 }
1081 } else if (new->peer->as == exist->peer->as) {
1082 *paths_eq = 1;
1083
1084 if (debug)
1085 zlog_debug(
1086 "%s: %s and %s are equal via same remote-as",
1087 pfx_buf, new_buf, exist_buf);
1088 }
1089 } else {
1090 /*
1091 * TODO: If unequal cost ibgp multipath is enabled we can
1092 * mark the paths as equal here instead of returning
1093 */
1094 if (debug) {
1095 if (ret == 1)
1096 zlog_debug(
1097 "%s: %s wins over %s after IGP metric comparison",
1098 pfx_buf, new_buf, exist_buf);
1099 else
1100 zlog_debug(
1101 "%s: %s loses to %s after IGP metric comparison",
1102 pfx_buf, new_buf, exist_buf);
1103 }
fdf81fa0 1104 *reason = bgp_path_selection_igp_metric;
d62a17ae 1105 return ret;
1106 }
718e3744 1107
d62a17ae 1108 /* 12. If both paths are external, prefer the path that was received
1109 first (the oldest one). This step minimizes route-flap, since a
1110 newer path won't displace an older one, even if it was the
1111 preferred route based on the additional decision criteria below. */
892fedb6 1112 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1113 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1114 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1115 *reason = bgp_path_selection_older;
d62a17ae 1116 if (debug)
1117 zlog_debug(
1118 "%s: %s wins over %s due to oldest external",
1119 pfx_buf, new_buf, exist_buf);
1120 return 1;
1121 }
9fbdd100 1122
1defdda8 1123 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1124 *reason = bgp_path_selection_older;
d62a17ae 1125 if (debug)
1126 zlog_debug(
1127 "%s: %s loses to %s due to oldest external",
1128 pfx_buf, new_buf, exist_buf);
1129 return 0;
1130 }
1131 }
718e3744 1132
d62a17ae 1133 /* 13. Router-ID comparision. */
1134 /* If one of the paths is "stale", the corresponding peer router-id will
1135 * be 0 and would always win over the other path. If originator id is
1136 * used for the comparision, it will decide which path is better.
1137 */
1138 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1139 new_id.s_addr = newattr->originator_id.s_addr;
1140 else
1141 new_id.s_addr = new->peer->remote_id.s_addr;
1142 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1143 exist_id.s_addr = existattr->originator_id.s_addr;
1144 else
1145 exist_id.s_addr = exist->peer->remote_id.s_addr;
1146
1147 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1148 *reason = bgp_path_selection_router_id;
d62a17ae 1149 if (debug)
1150 zlog_debug(
1151 "%s: %s wins over %s due to Router-ID comparison",
1152 pfx_buf, new_buf, exist_buf);
1153 return 1;
1154 }
718e3744 1155
d62a17ae 1156 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1157 *reason = bgp_path_selection_router_id;
d62a17ae 1158 if (debug)
1159 zlog_debug(
1160 "%s: %s loses to %s due to Router-ID comparison",
1161 pfx_buf, new_buf, exist_buf);
1162 return 0;
1163 }
9fbdd100 1164
d62a17ae 1165 /* 14. Cluster length comparision. */
1166 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1167 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1168
1169 if (new_cluster < exist_cluster) {
fdf81fa0 1170 *reason = bgp_path_selection_cluster_length;
d62a17ae 1171 if (debug)
1172 zlog_debug(
1173 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1174 pfx_buf, new_buf, exist_buf, new_cluster,
1175 exist_cluster);
1176 return 1;
1177 }
718e3744 1178
d62a17ae 1179 if (new_cluster > exist_cluster) {
fdf81fa0 1180 *reason = bgp_path_selection_cluster_length;
d62a17ae 1181 if (debug)
1182 zlog_debug(
1183 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1184 pfx_buf, new_buf, exist_buf, new_cluster,
1185 exist_cluster);
1186 return 0;
1187 }
9fbdd100 1188
d62a17ae 1189 /* 15. Neighbor address comparision. */
1190 /* Do this only if neither path is "stale" as stale paths do not have
1191 * valid peer information (as the connection may or may not be up).
1192 */
1defdda8 1193 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1194 *reason = bgp_path_selection_stale;
d62a17ae 1195 if (debug)
1196 zlog_debug(
1197 "%s: %s wins over %s due to latter path being STALE",
1198 pfx_buf, new_buf, exist_buf);
1199 return 1;
1200 }
0de5153c 1201
1defdda8 1202 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1203 *reason = bgp_path_selection_stale;
d62a17ae 1204 if (debug)
1205 zlog_debug(
1206 "%s: %s loses to %s due to former path being STALE",
1207 pfx_buf, new_buf, exist_buf);
1208 return 0;
1209 }
718e3744 1210
d62a17ae 1211 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1212 if (new->peer->su_remote == NULL) {
1213 *reason = bgp_path_selection_local_configured;
d62a17ae 1214 return 0;
fdf81fa0
DS
1215 }
1216 if (exist->peer->su_remote == NULL) {
1217 *reason = bgp_path_selection_local_configured;
d62a17ae 1218 return 1;
fdf81fa0 1219 }
9fbdd100 1220
d62a17ae 1221 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1222
1223 if (ret == 1) {
fdf81fa0 1224 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1225 if (debug)
1226 zlog_debug(
1227 "%s: %s loses to %s due to Neighor IP comparison",
1228 pfx_buf, new_buf, exist_buf);
1229 return 0;
1230 }
1231
1232 if (ret == -1) {
fdf81fa0 1233 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1234 if (debug)
1235 zlog_debug(
1236 "%s: %s wins over %s due to Neighor IP comparison",
1237 pfx_buf, new_buf, exist_buf);
1238 return 1;
1239 }
9fbdd100 1240
fdf81fa0 1241 *reason = bgp_path_selection_default;
d62a17ae 1242 if (debug)
1243 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1244 pfx_buf, new_buf, exist_buf);
718e3744 1245
d62a17ae 1246 return 1;
718e3744 1247}
1248
d071f237
AK
1249
1250int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1251 struct bgp_path_info *exist, int *paths_eq)
1252{
1253 enum bgp_path_selection_reason reason;
1254 char pfx_buf[PREFIX2STR_BUFFER];
1255
1256 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1257 AFI_L2VPN, SAFI_EVPN, &reason);
1258}
1259
65efcfce
LB
1260/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1261 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1262 * multipath is enabled
65efcfce 1263 * This version is compatible with */
18ee8310
DS
1264int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1265 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1266 afi_t afi, safi_t safi,
1267 enum bgp_path_selection_reason *reason)
d62a17ae 1268{
1269 int paths_eq;
1270 int ret;
18ee8310 1271 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1272 afi, safi, reason);
d62a17ae 1273
1274 if (paths_eq)
1275 ret = 0;
1276 else {
1277 if (ret == 1)
1278 ret = -1;
1279 else
1280 ret = 1;
1281 }
1282 return ret;
65efcfce
LB
1283}
1284
5a1ae2c2
DS
1285static enum filter_type bgp_input_filter(struct peer *peer,
1286 const struct prefix *p,
d62a17ae 1287 struct attr *attr, afi_t afi,
1288 safi_t safi)
718e3744 1289{
d62a17ae 1290 struct bgp_filter *filter;
718e3744 1291
d62a17ae 1292 filter = &peer->filter[afi][safi];
718e3744 1293
d62a17ae 1294#define FILTER_EXIST_WARN(F, f, filter) \
1295 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1296 zlog_debug("%s: Could not find configured input %s-list %s!", \
1297 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1298
1299 if (DISTRIBUTE_IN_NAME(filter)) {
1300 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1301
1302 if (access_list_apply(DISTRIBUTE_IN(filter), p) == FILTER_DENY)
1303 return FILTER_DENY;
1304 }
1305
1306 if (PREFIX_LIST_IN_NAME(filter)) {
1307 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1308
1309 if (prefix_list_apply(PREFIX_LIST_IN(filter), p) == PREFIX_DENY)
1310 return FILTER_DENY;
1311 }
1312
1313 if (FILTER_LIST_IN_NAME(filter)) {
1314 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1315
1316 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
1317 == AS_FILTER_DENY)
1318 return FILTER_DENY;
1319 }
1320
1321 return FILTER_PERMIT;
650f76c2 1322#undef FILTER_EXIST_WARN
718e3744 1323}
1324
b8685f9b
DS
1325static enum filter_type bgp_output_filter(struct peer *peer,
1326 const struct prefix *p,
d62a17ae 1327 struct attr *attr, afi_t afi,
1328 safi_t safi)
718e3744 1329{
d62a17ae 1330 struct bgp_filter *filter;
1331
1332 filter = &peer->filter[afi][safi];
1333
1334#define FILTER_EXIST_WARN(F, f, filter) \
1335 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1336 zlog_debug("%s: Could not find configured output %s-list %s!", \
1337 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1338
d62a17ae 1339 if (DISTRIBUTE_OUT_NAME(filter)) {
1340 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1341
d62a17ae 1342 if (access_list_apply(DISTRIBUTE_OUT(filter), p) == FILTER_DENY)
1343 return FILTER_DENY;
1344 }
1345
1346 if (PREFIX_LIST_OUT_NAME(filter)) {
1347 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1348
d62a17ae 1349 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
1350 == PREFIX_DENY)
1351 return FILTER_DENY;
1352 }
718e3744 1353
d62a17ae 1354 if (FILTER_LIST_OUT_NAME(filter)) {
1355 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1356
d62a17ae 1357 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
1358 == AS_FILTER_DENY)
1359 return FILTER_DENY;
1360 }
718e3744 1361
d62a17ae 1362 return FILTER_PERMIT;
650f76c2 1363#undef FILTER_EXIST_WARN
718e3744 1364}
1365
1366/* If community attribute includes no_export then return 1. */
3dc339cd 1367static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1368{
1369 if (attr->community) {
1370 /* NO_ADVERTISE check. */
1371 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1372 return true;
d62a17ae 1373
1374 /* NO_EXPORT check. */
1375 if (peer->sort == BGP_PEER_EBGP
1376 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1377 return true;
d62a17ae 1378
1379 /* NO_EXPORT_SUBCONFED check. */
1380 if (peer->sort == BGP_PEER_EBGP
1381 || peer->sort == BGP_PEER_CONFED)
1382 if (community_include(attr->community,
1383 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1384 return true;
d62a17ae 1385 }
3dc339cd 1386 return false;
718e3744 1387}
1388
1389/* Route reflection loop check. */
3dc339cd 1390static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1391{
d62a17ae 1392 struct in_addr cluster_id;
718e3744 1393
d62a17ae 1394 if (attr->cluster) {
1395 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1396 cluster_id = peer->bgp->cluster_id;
1397 else
1398 cluster_id = peer->bgp->router_id;
1399
1400 if (cluster_loop_check(attr->cluster, cluster_id))
3dc339cd 1401 return true;
d62a17ae 1402 }
3dc339cd 1403 return false;
718e3744 1404}
6b0655a2 1405
5a1ae2c2 1406static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1407 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1408 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1409 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1410{
d62a17ae 1411 struct bgp_filter *filter;
82b692c0
LK
1412 struct bgp_path_info rmap_path = { 0 };
1413 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1414 route_map_result_t ret;
1415 struct route_map *rmap = NULL;
718e3744 1416
d62a17ae 1417 filter = &peer->filter[afi][safi];
718e3744 1418
d62a17ae 1419 /* Apply default weight value. */
1420 if (peer->weight[afi][safi])
1421 attr->weight = peer->weight[afi][safi];
718e3744 1422
d62a17ae 1423 if (rmap_name) {
1424 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1425
d62a17ae 1426 if (rmap == NULL)
1427 return RMAP_DENY;
1428 } else {
1429 if (ROUTE_MAP_IN_NAME(filter)) {
1430 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1431
d62a17ae 1432 if (rmap == NULL)
1433 return RMAP_DENY;
1434 }
1435 }
0b16f239 1436
d62a17ae 1437 /* Route map apply. */
1438 if (rmap) {
40381db7 1439 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1440 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1441 rmap_path.peer = peer;
1442 rmap_path.attr = attr;
82b692c0 1443 rmap_path.extra = &extra;
9bcb3eef 1444 rmap_path.net = dest;
196c6b09 1445
82b692c0
LK
1446 extra.num_labels = num_labels;
1447 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1448 memcpy(extra.label, label,
1449 num_labels * sizeof(mpls_label_t));
718e3744 1450
d62a17ae 1451 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1452
d62a17ae 1453 /* Apply BGP route map to the attribute. */
40381db7 1454 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
0b16f239 1455
d62a17ae 1456 peer->rmap_type = 0;
0b16f239 1457
1f2263be 1458 if (ret == RMAP_DENYMATCH)
d62a17ae 1459 return RMAP_DENY;
0b16f239 1460 }
d62a17ae 1461 return RMAP_PERMIT;
0b16f239
DS
1462}
1463
5f040085 1464static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1465 struct attr *attr, afi_t afi, safi_t safi,
1466 const char *rmap_name)
0b16f239 1467{
40381db7 1468 struct bgp_path_info rmap_path;
d62a17ae 1469 route_map_result_t ret;
1470 struct route_map *rmap = NULL;
d7c0a89a 1471 uint8_t rmap_type;
0b16f239 1472
b787157a
DS
1473 /*
1474 * So if we get to this point and have no rmap_name
1475 * we want to just show the output as it currently
1476 * exists.
1477 */
1478 if (!rmap_name)
1479 return RMAP_PERMIT;
0b16f239 1480
d62a17ae 1481 /* Apply default weight value. */
1482 if (peer->weight[afi][safi])
1483 attr->weight = peer->weight[afi][safi];
0b16f239 1484
b787157a 1485 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1486
b787157a
DS
1487 /*
1488 * If we have a route map name and we do not find
1489 * the routemap that means we have an implicit
1490 * deny.
1491 */
1492 if (rmap == NULL)
1493 return RMAP_DENY;
0b16f239 1494
40381db7 1495 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1496 /* Route map apply. */
b787157a 1497 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1498 rmap_path.peer = peer;
1499 rmap_path.attr = attr;
0b16f239 1500
0f672529 1501 rmap_type = peer->rmap_type;
b787157a 1502 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1503
b787157a 1504 /* Apply BGP route map to the attribute. */
40381db7 1505 ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
ac41b2a2 1506
0f672529 1507 peer->rmap_type = rmap_type;
b787157a
DS
1508
1509 if (ret == RMAP_DENYMATCH)
1510 /*
1511 * caller has multiple error paths with bgp_attr_flush()
1512 */
1513 return RMAP_DENY;
ac41b2a2 1514
d62a17ae 1515 return RMAP_PERMIT;
718e3744 1516}
6b0655a2 1517
5000f21c 1518/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1519static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1520 struct peer *peer, struct attr *attr)
1521{
1522 if (peer->sort == BGP_PEER_EBGP
1523 && (peer_af_flag_check(peer, afi, safi,
1524 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1525 || peer_af_flag_check(peer, afi, safi,
1526 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1527 || peer_af_flag_check(peer, afi, safi,
1528 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1529 || peer_af_flag_check(peer, afi, safi,
1530 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1531 // Take action on the entire aspath
1532 if (peer_af_flag_check(peer, afi, safi,
1533 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1534 || peer_af_flag_check(peer, afi, safi,
1535 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1536 if (peer_af_flag_check(
1537 peer, afi, safi,
1538 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1539 attr->aspath = aspath_replace_private_asns(
bf26b80e 1540 attr->aspath, bgp->as, peer->as);
d62a17ae 1541
1542 // The entire aspath consists of private ASNs so create
1543 // an empty aspath
1544 else if (aspath_private_as_check(attr->aspath))
1545 attr->aspath = aspath_empty_get();
1546
1547 // There are some public and some private ASNs, remove
1548 // the private ASNs
1549 else
1550 attr->aspath = aspath_remove_private_asns(
bf26b80e 1551 attr->aspath, peer->as);
d62a17ae 1552 }
1553
1554 // 'all' was not specified so the entire aspath must be private
1555 // ASNs
1556 // for us to do anything
1557 else if (aspath_private_as_check(attr->aspath)) {
1558 if (peer_af_flag_check(
1559 peer, afi, safi,
1560 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1561 attr->aspath = aspath_replace_private_asns(
bf26b80e 1562 attr->aspath, bgp->as, peer->as);
d62a17ae 1563 else
1564 attr->aspath = aspath_empty_get();
1565 }
1566 }
5000f21c
DS
1567}
1568
c7122e14 1569/* If this is an EBGP peer with as-override */
d62a17ae 1570static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1571 struct peer *peer, struct attr *attr)
1572{
1573 if (peer->sort == BGP_PEER_EBGP
1574 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1575 if (aspath_single_asn_check(attr->aspath, peer->as))
1576 attr->aspath = aspath_replace_specific_asn(
1577 attr->aspath, peer->as, bgp->as);
1578 }
1579}
1580
7f323236
DW
1581void bgp_attr_add_gshut_community(struct attr *attr)
1582{
1583 struct community *old;
1584 struct community *new;
1585 struct community *merge;
1586 struct community *gshut;
1587
1588 old = attr->community;
1589 gshut = community_str2com("graceful-shutdown");
1590
990f4f91 1591 assert(gshut);
1592
7f323236
DW
1593 if (old) {
1594 merge = community_merge(community_dup(old), gshut);
1595
a4d82a8a 1596 if (old->refcnt == 0)
3c1f53de 1597 community_free(&old);
7f323236
DW
1598
1599 new = community_uniq_sort(merge);
3c1f53de 1600 community_free(&merge);
7f323236
DW
1601 } else {
1602 new = community_dup(gshut);
1603 }
1604
3c1f53de 1605 community_free(&gshut);
7f323236
DW
1606 attr->community = new;
1607 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1608
1609 /* When we add the graceful-shutdown community we must also
1610 * lower the local-preference */
1611 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1612 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1613}
1614
1615
d7c0a89a 1616static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1617{
960035b2 1618 if (family == AF_INET) {
975a328e
DA
1619 attr->nexthop.s_addr = INADDR_ANY;
1620 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1621 }
d62a17ae 1622 if (family == AF_INET6)
1623 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1624 if (family == AF_EVPN)
1625 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1626}
1627
9bcb3eef 1628bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b
DS
1629 struct update_subgroup *subgrp,
1630 const struct prefix *p, struct attr *attr)
d62a17ae 1631{
1632 struct bgp_filter *filter;
1633 struct peer *from;
1634 struct peer *peer;
1635 struct peer *onlypeer;
1636 struct bgp *bgp;
40381db7 1637 struct attr *piattr;
d62a17ae 1638 char buf[PREFIX_STRLEN];
b68885f9 1639 route_map_result_t ret;
d62a17ae 1640 int transparent;
1641 int reflect;
1642 afi_t afi;
1643 safi_t safi;
1644 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1645 bool nh_reset = false;
1646 uint64_t cum_bw;
d62a17ae 1647
1648 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1649 return false;
d62a17ae 1650
1651 afi = SUBGRP_AFI(subgrp);
1652 safi = SUBGRP_SAFI(subgrp);
1653 peer = SUBGRP_PEER(subgrp);
1654 onlypeer = NULL;
1655 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1656 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1657
40381db7 1658 from = pi->peer;
d62a17ae 1659 filter = &peer->filter[afi][safi];
1660 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1661 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1662 : pi->attr;
3f9c7369 1663
49e5a4a0 1664#ifdef ENABLE_BGP_VNC
d62a17ae 1665 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1666 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1667 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1668
1669 /*
1670 * direct and direct_ext type routes originate internally even
1671 * though they can have peer pointers that reference other
1672 * systems
1673 */
1674 prefix2str(p, buf, PREFIX_STRLEN);
1675 zlog_debug("%s: pfx %s bgp_direct->vpn route peer safe",
1676 __func__, buf);
1677 samepeer_safe = 1;
1678 }
65efcfce
LB
1679#endif
1680
ddb5b488
PZ
1681 if (((afi == AFI_IP) || (afi == AFI_IP6))
1682 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1683 && (pi->type == ZEBRA_ROUTE_BGP)
1684 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1685
1686 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1687
1688 samepeer_safe = 1;
1689 }
1690
d62a17ae 1691 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1692 * pi is valid */
1693 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1694 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1695 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1696 return false;
d62a17ae 1697 }
adbac85e 1698
d62a17ae 1699 /* If this is not the bestpath then check to see if there is an enabled
1700 * addpath
1701 * feature that requires us to advertise it */
40381db7 1702 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1703 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1704 return false;
d62a17ae 1705 }
1706 }
06370dac 1707
d62a17ae 1708 /* Aggregate-address suppress check. */
40381db7 1709 if (pi->extra && pi->extra->suppress)
d62a17ae 1710 if (!UNSUPPRESS_MAP_NAME(filter)) {
3dc339cd 1711 return false;
d62a17ae 1712 }
3f9c7369 1713
13b7e7f0
DS
1714 /*
1715 * If we are doing VRF 2 VRF leaking via the import
1716 * statement, we want to prevent the route going
1717 * off box as that the RT and RD created are localy
1718 * significant and globaly useless.
1719 */
40381db7
DS
1720 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1721 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1722 return false;
13b7e7f0 1723
d62a17ae 1724 /* If it's labeled safi, make sure the route has a valid label. */
1725 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1726 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1727 if (!bgp_is_valid_label(&label)) {
1728 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
6cde4b45 1729 zlog_debug("u%" PRIu64 ":s%" PRIu64" %s/%d is filtered - no label (%p)",
d62a17ae 1730 subgrp->update_group->id, subgrp->id,
1731 inet_ntop(p->family, &p->u.prefix,
1732 buf, SU_ADDRSTRLEN),
1733 p->prefixlen, &label);
3dc339cd 1734 return false;
d62a17ae 1735 }
1736 }
cd1964ff 1737
d62a17ae 1738 /* Do not send back route to sender. */
1739 if (onlypeer && from == onlypeer) {
3dc339cd 1740 return false;
d62a17ae 1741 }
3f9c7369 1742
d62a17ae 1743 /* Do not send the default route in the BGP table if the neighbor is
1744 * configured for default-originate */
1745 if (CHECK_FLAG(peer->af_flags[afi][safi],
1746 PEER_FLAG_DEFAULT_ORIGINATE)) {
1747 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1748 return false;
d62a17ae 1749 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1750 return false;
d62a17ae 1751 }
4125bb67 1752
d62a17ae 1753 /* Transparency check. */
1754 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1755 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1756 transparent = 1;
1757 else
1758 transparent = 0;
1759
1760 /* If community is not disabled check the no-export and local. */
40381db7 1761 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1762 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1763 zlog_debug(
1764 "subgrpannouncecheck: community filter check fail");
3dc339cd 1765 return false;
d62a17ae 1766 }
3f9c7369 1767
d62a17ae 1768 /* If the attribute has originator-id and it is same as remote
1769 peer's id. */
40381db7
DS
1770 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1771 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1772 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1773 zlog_debug(
3efd0893 1774 "%s [Update:SEND] %s originator-id is same as remote router-id",
d62a17ae 1775 onlypeer->host,
1776 prefix2str(p, buf, sizeof(buf)));
3dc339cd 1777 return false;
d62a17ae 1778 }
3f9c7369 1779
d62a17ae 1780 /* ORF prefix-list filter check */
1781 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1782 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1783 || CHECK_FLAG(peer->af_cap[afi][safi],
1784 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1785 if (peer->orf_plist[afi][safi]) {
1786 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1787 == PREFIX_DENY) {
1788 if (bgp_debug_update(NULL, p,
1789 subgrp->update_group, 0))
1790 zlog_debug(
1791 "%s [Update:SEND] %s is filtered via ORF",
1792 peer->host,
1793 prefix2str(p, buf,
1794 sizeof(buf)));
3dc339cd 1795 return false;
d62a17ae 1796 }
1797 }
1798
1799 /* Output filter check. */
40381db7 1800 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1801 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1802 zlog_debug("%s [Update:SEND] %s is filtered",
1803 peer->host, prefix2str(p, buf, sizeof(buf)));
3dc339cd 1804 return false;
d62a17ae 1805 }
3f9c7369 1806
d62a17ae 1807 /* AS path loop check. */
2b31007c
RZ
1808 if (onlypeer && onlypeer->as_path_loop_detection
1809 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1810 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1811 zlog_debug(
3efd0893 1812 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1813 onlypeer->host, onlypeer->as);
3dc339cd 1814 return false;
d62a17ae 1815 }
3f9c7369 1816
d62a17ae 1817 /* If we're a CONFED we need to loop check the CONFED ID too */
1818 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1819 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1820 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1821 zlog_debug(
3efd0893 1822 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1823 peer->host, bgp->confed_id);
3dc339cd 1824 return false;
d62a17ae 1825 }
3f9c7369 1826 }
3f9c7369 1827
d62a17ae 1828 /* Route-Reflect check. */
1829 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1830 reflect = 1;
1831 else
1832 reflect = 0;
1833
1834 /* IBGP reflection check. */
1835 if (reflect && !samepeer_safe) {
1836 /* A route from a Client peer. */
1837 if (CHECK_FLAG(from->af_flags[afi][safi],
1838 PEER_FLAG_REFLECTOR_CLIENT)) {
1839 /* Reflect to all the Non-Client peers and also to the
1840 Client peers other than the originator. Originator
1841 check
1842 is already done. So there is noting to do. */
1843 /* no bgp client-to-client reflection check. */
892fedb6
DA
1844 if (CHECK_FLAG(bgp->flags,
1845 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1846 if (CHECK_FLAG(peer->af_flags[afi][safi],
1847 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1848 return false;
d62a17ae 1849 } else {
1850 /* A route from a Non-client peer. Reflect to all other
1851 clients. */
1852 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1853 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1854 return false;
d62a17ae 1855 }
1856 }
3f9c7369 1857
d62a17ae 1858 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1859 *attr = *piattr;
d62a17ae 1860
1861 /* If local-preference is not set. */
1862 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1863 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1864 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1865 attr->local_pref = bgp->default_local_pref;
3f9c7369 1866 }
3f9c7369 1867
d62a17ae 1868 /* If originator-id is not set and the route is to be reflected,
1869 set the originator id */
1870 if (reflect
1871 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1872 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1873 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1874 }
3f9c7369 1875
d62a17ae 1876 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1877 */
1878 if (peer->sort == BGP_PEER_EBGP
1879 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1880 if (from != bgp->peer_self && !transparent
1881 && !CHECK_FLAG(peer->af_flags[afi][safi],
1882 PEER_FLAG_MED_UNCHANGED))
1883 attr->flag &=
1884 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1885 }
3f9c7369 1886
d62a17ae 1887 /* Since the nexthop attribute can vary per peer, it is not explicitly
1888 * set
1889 * in announce check, only certain flags and length (or number of
1890 * nexthops
1891 * -- for IPv6/MP_REACH) are set here in order to guide the update
1892 * formation
1893 * code in setting the nexthop(s) on a per peer basis in
1894 * reformat_peer().
1895 * Typically, the source nexthop in the attribute is preserved but in
1896 * the
1897 * scenarios where we know it will always be overwritten, we reset the
1898 * nexthop to "0" in an attempt to achieve better Update packing. An
1899 * example of this is when a prefix from each of 2 IBGP peers needs to
1900 * be
1901 * announced to an EBGP peer (and they have the same attributes barring
1902 * their nexthop).
1903 */
1904 if (reflect)
1905 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1906
1907#define NEXTHOP_IS_V6 \
1908 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1909 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1910 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1911 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1912
1913 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
1914 * if
1915 * the peer (group) is configured to receive link-local nexthop
1916 * unchanged
c728d027
DA
1917 * and it is available in the prefix OR we're not reflecting the route,
1918 * link-local nexthop address is valid and
d62a17ae 1919 * the peer (group) to whom we're going to announce is on a shared
1920 * network
1921 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
1922 * By checking if nexthop LL address is valid we are sure that
1923 * we do not announce LL address as `::`.
d62a17ae 1924 */
1925 if (NEXTHOP_IS_V6) {
1926 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
1927 if ((CHECK_FLAG(peer->af_flags[afi][safi],
1928 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
1929 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
1930 || (!reflect
1931 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
1932 && peer->shared_network
d62a17ae 1933 && (from == bgp->peer_self
1934 || peer->sort == BGP_PEER_EBGP))) {
1935 attr->mp_nexthop_len =
1936 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
1937 }
3f9c7369 1938
d62a17ae 1939 /* Clear off link-local nexthop in source, whenever it is not
1940 * needed to
1941 * ensure more prefixes share the same attribute for
1942 * announcement.
1943 */
1944 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
1945 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
1946 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
1947 }
3f9c7369 1948
d62a17ae 1949 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
1950 bgp_peer_as_override(bgp, afi, safi, peer, attr);
1951
1952 /* Route map & unsuppress-map apply. */
40381db7 1953 if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) {
b8694ef4
DS
1954 struct bgp_path_info rmap_path = {0};
1955 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
1956 struct attr dummy_attr = {0};
d62a17ae 1957
e34291b8 1958 /* Fill temp path_info */
9bcb3eef
DS
1959 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
1960 pi, peer, attr);
16f7ce2b 1961
d62a17ae 1962 /* don't confuse inbound and outbound setting */
1963 RESET_FLAG(attr->rmap_change_flags);
1964
1965 /*
1966 * The route reflector is not allowed to modify the attributes
1967 * of the reflected IBGP routes unless explicitly allowed.
1968 */
1969 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
1970 && !CHECK_FLAG(bgp->flags,
1971 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 1972 dummy_attr = *attr;
40381db7 1973 rmap_path.attr = &dummy_attr;
d62a17ae 1974 }
3f9c7369 1975
d62a17ae 1976 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 1977
40381db7 1978 if (pi->extra && pi->extra->suppress)
d62a17ae 1979 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
40381db7 1980 RMAP_BGP, &rmap_path);
d62a17ae 1981 else
1982 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
40381db7 1983 RMAP_BGP, &rmap_path);
d62a17ae 1984
1985 peer->rmap_type = 0;
1986
1987 if (ret == RMAP_DENYMATCH) {
778048bf
AD
1988 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1989 zlog_debug("%s [Update:SEND] %s is filtered by route-map",
1990 peer->host, prefix2str(p, buf, sizeof(buf)));
1991
d62a17ae 1992 bgp_attr_flush(attr);
3dc339cd 1993 return false;
d62a17ae 1994 }
3f9c7369 1995 }
3f9c7369 1996
9dac9fc8
DA
1997 /* RFC 8212 to prevent route leaks.
1998 * This specification intends to improve this situation by requiring the
1999 * explicit configuration of both BGP Import and Export Policies for any
2000 * External BGP (EBGP) session such as customers, peers, or
2001 * confederation boundaries for all enabled address families. Through
2002 * codification of the aforementioned requirement, operators will
2003 * benefit from consistent behavior across different BGP
2004 * implementations.
2005 */
1d3fdccf 2006 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2007 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2008 return false;
9dac9fc8 2009
fb29348a
DA
2010 /* draft-ietf-idr-deprecate-as-set-confed-set
2011 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2012 * Eventually, This document (if approved) updates RFC 4271
2013 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2014 * and obsoletes RFC 6472.
2015 */
7f972cd8 2016 if (peer->bgp->reject_as_sets)
fb29348a 2017 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2018 return false;
fb29348a 2019
33d022bc
DA
2020 /* Codification of AS 0 Processing */
2021 if (aspath_check_as_zero(attr->aspath))
e2369003 2022 return false;
33d022bc 2023
637e5ba4 2024 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2025 if (peer->sort == BGP_PEER_IBGP
2026 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2027 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2028 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2029 } else {
2030 bgp_attr_add_gshut_community(attr);
2031 }
2032 }
2033
d62a17ae 2034 /* After route-map has been applied, we check to see if the nexthop to
2035 * be carried in the attribute (that is used for the announcement) can
2036 * be cleared off or not. We do this in all cases where we would be
2037 * setting the nexthop to "ourselves". For IPv6, we only need to
2038 * consider
2039 * the global nexthop here; the link-local nexthop would have been
2040 * cleared
2041 * already, and if not, it is required by the update formation code.
2042 * Also see earlier comments in this function.
2043 */
2044 /*
2045 * If route-map has performed some operation on the nexthop or the peer
2046 * configuration says to pass it unchanged, we cannot reset the nexthop
2047 * here, so only attempt to do it if these aren't true. Note that the
2048 * route-map handler itself might have cleared the nexthop, if for
2049 * example,
2050 * it is configured as 'peer-address'.
2051 */
2052 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2053 piattr->rmap_change_flags)
d62a17ae 2054 && !transparent
2055 && !CHECK_FLAG(peer->af_flags[afi][safi],
2056 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2057 /* We can reset the nexthop, if setting (or forcing) it to
2058 * 'self' */
2059 if (CHECK_FLAG(peer->af_flags[afi][safi],
2060 PEER_FLAG_NEXTHOP_SELF)
2061 || CHECK_FLAG(peer->af_flags[afi][safi],
2062 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2063 if (!reflect
2064 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2065 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2066 subgroup_announce_reset_nhop(
2067 (peer_cap_enhe(peer, afi, safi)
2068 ? AF_INET6
2069 : p->family),
2070 attr);
7b651a32 2071 nh_reset = true;
2072 }
d62a17ae 2073 } else if (peer->sort == BGP_PEER_EBGP) {
2074 /* Can also reset the nexthop if announcing to EBGP, but
2075 * only if
2076 * no peer in the subgroup is on a shared subnet.
2077 * Note: 3rd party nexthop currently implemented for
2078 * IPv4 only.
2079 */
737af885
BS
2080 if ((p->family == AF_INET) &&
2081 (!bgp_subgrp_multiaccess_check_v4(
2082 piattr->nexthop,
7b651a32 2083 subgrp, from))) {
d62a17ae 2084 subgroup_announce_reset_nhop(
2085 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2086 ? AF_INET6
2087 : p->family),
737af885 2088 attr);
7b651a32 2089 nh_reset = true;
2090 }
737af885
BS
2091
2092 if ((p->family == AF_INET6) &&
2093 (!bgp_subgrp_multiaccess_check_v6(
2094 piattr->mp_nexthop_global,
7b651a32 2095 subgrp, from))) {
737af885
BS
2096 subgroup_announce_reset_nhop(
2097 (peer_cap_enhe(peer, afi, safi)
2098 ? AF_INET6
2099 : p->family),
2100 attr);
7b651a32 2101 nh_reset = true;
2102 }
737af885
BS
2103
2104
2105
40381db7 2106 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2107 /*
2108 * This flag is used for leaked vpn-vrf routes
2109 */
2110 int family = p->family;
2111
2112 if (peer_cap_enhe(peer, afi, safi))
2113 family = AF_INET6;
2114
2115 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2116 zlog_debug(
1defdda8 2117 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2118 __func__, family2str(family));
2119 subgroup_announce_reset_nhop(family, attr);
7b651a32 2120 nh_reset = true;
d62a17ae 2121 }
63696f1d 2122 }
960035b2 2123
63696f1d 2124 /* If IPv6/MP and nexthop does not have any override and happens
2125 * to
2126 * be a link-local address, reset it so that we don't pass along
2127 * the
2128 * source's link-local IPv6 address to recipients who may not be
2129 * on
2130 * the same interface.
2131 */
2132 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2133 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2134 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2135 nh_reset = true;
2136 }
d62a17ae 2137 }
3f9c7369 2138
7b651a32 2139 /*
2140 * When the next hop is set to ourselves, if all multipaths have
2141 * link-bandwidth announce the cumulative bandwidth as that makes
2142 * the most sense. However, don't modify if the link-bandwidth has
2143 * been explicitly set by user policy.
2144 */
2145 if (nh_reset &&
f7e1c681 2146 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2147 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2148 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2149 attr->ecommunity = ecommunity_replace_linkbw(
2150 bgp->as, attr->ecommunity, cum_bw);
2151
3dc339cd 2152 return true;
3f9c7369
DS
2153}
2154
f009ff26 2155static int bgp_route_select_timer_expire(struct thread *thread)
2156{
2157 struct afi_safi_info *info;
2158 afi_t afi;
2159 safi_t safi;
2160 struct bgp *bgp;
2161
2162 info = THREAD_ARG(thread);
2163 afi = info->afi;
2164 safi = info->safi;
2165 bgp = info->bgp;
2166
2167 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2168 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2169 safi);
f009ff26 2170
2171 bgp->gr_info[afi][safi].t_route_select = NULL;
2172
2173 XFREE(MTYPE_TMP, info);
2174
2175 /* Best path selection */
2176 return bgp_best_path_select_defer(bgp, afi, safi);
2177}
2178
9bcb3eef 2179void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2180 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2181 struct bgp_path_info_pair *result, afi_t afi,
2182 safi_t safi)
2183{
2184 struct bgp_path_info *new_select;
2185 struct bgp_path_info *old_select;
40381db7
DS
2186 struct bgp_path_info *pi;
2187 struct bgp_path_info *pi1;
2188 struct bgp_path_info *pi2;
2189 struct bgp_path_info *nextpi = NULL;
d62a17ae 2190 int paths_eq, do_mpath, debug;
2191 struct list mp_list;
2192 char pfx_buf[PREFIX2STR_BUFFER];
2193 char path_buf[PATH_ADDPATH_STR_BUFFER];
2194
2195 bgp_mp_list_init(&mp_list);
2196 do_mpath =
2197 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2198
9bcb3eef 2199 debug = bgp_debug_bestpath(dest);
d62a17ae 2200
2201 if (debug)
9bcb3eef 2202 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2203
9bcb3eef 2204 dest->reason = bgp_path_selection_none;
d62a17ae 2205 /* bgp deterministic-med */
2206 new_select = NULL;
892fedb6 2207 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2208
1defdda8 2209 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2210 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2211 pi1 = pi1->next)
9bcb3eef 2212 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2213 BGP_PATH_DMED_SELECTED);
d62a17ae 2214
9bcb3eef 2215 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2216 pi1 = pi1->next) {
40381db7 2217 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2218 continue;
40381db7 2219 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2220 continue;
ea8b2282 2221 if (pi1->peer != bgp->peer_self)
40381db7 2222 if (pi1->peer->status != Established)
d62a17ae 2223 continue;
2224
40381db7
DS
2225 new_select = pi1;
2226 if (pi1->next) {
2227 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2228 if (CHECK_FLAG(pi2->flags,
1defdda8 2229 BGP_PATH_DMED_CHECK))
d62a17ae 2230 continue;
40381db7 2231 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2232 continue;
ea8b2282 2233 if (pi2->peer != bgp->peer_self
d62a17ae 2234 && !CHECK_FLAG(
ea8b2282
DS
2235 pi2->peer->sflags,
2236 PEER_STATUS_NSF_WAIT))
40381db7 2237 if (pi2->peer->status
d62a17ae 2238 != Established)
2239 continue;
2240
121e245d
DS
2241 if (!aspath_cmp_left(pi1->attr->aspath,
2242 pi2->attr->aspath)
2243 && !aspath_cmp_left_confed(
40381db7 2244 pi1->attr->aspath,
121e245d
DS
2245 pi2->attr->aspath))
2246 continue;
d62a17ae 2247
121e245d
DS
2248 if (bgp_path_info_cmp(
2249 bgp, pi2, new_select,
2250 &paths_eq, mpath_cfg, debug,
fdf81fa0 2251 pfx_buf, afi, safi,
9bcb3eef 2252 &dest->reason)) {
121e245d 2253 bgp_path_info_unset_flag(
9bcb3eef 2254 dest, new_select,
121e245d
DS
2255 BGP_PATH_DMED_SELECTED);
2256 new_select = pi2;
d62a17ae 2257 }
121e245d
DS
2258
2259 bgp_path_info_set_flag(
9bcb3eef 2260 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2261 }
2262 }
9bcb3eef 2263 bgp_path_info_set_flag(dest, new_select,
18ee8310 2264 BGP_PATH_DMED_CHECK);
9bcb3eef 2265 bgp_path_info_set_flag(dest, new_select,
18ee8310 2266 BGP_PATH_DMED_SELECTED);
d62a17ae 2267
2268 if (debug) {
18ee8310
DS
2269 bgp_path_info_path_with_addpath_rx_str(
2270 new_select, path_buf);
c66faab1 2271 zlog_debug("%s: %s is the bestpath from AS %u",
d62a17ae 2272 pfx_buf, path_buf,
2273 aspath_get_first_as(
2274 new_select->attr->aspath));
2275 }
2276 }
2277 }
96450faf 2278
d62a17ae 2279 /* Check old selected route and new selected route. */
2280 old_select = NULL;
2281 new_select = NULL;
9bcb3eef 2282 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2283 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2284 enum bgp_path_selection_reason reason;
2285
40381db7
DS
2286 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2287 old_select = pi;
d62a17ae 2288
40381db7 2289 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2290 /* reap REMOVED routes, if needs be
2291 * selected route must stay for a while longer though
2292 */
40381db7
DS
2293 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2294 && (pi != old_select))
9bcb3eef 2295 bgp_path_info_reap(dest, pi);
d62a17ae 2296
ddb5b488 2297 if (debug)
40381db7
DS
2298 zlog_debug("%s: pi %p in holddown", __func__,
2299 pi);
ddb5b488 2300
d62a17ae 2301 continue;
2302 }
96450faf 2303
40381db7
DS
2304 if (pi->peer && pi->peer != bgp->peer_self
2305 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2306 if (pi->peer->status != Established) {
ddb5b488
PZ
2307
2308 if (debug)
2309 zlog_debug(
40381db7
DS
2310 "%s: pi %p non self peer %s not estab state",
2311 __func__, pi, pi->peer->host);
ddb5b488 2312
d62a17ae 2313 continue;
ddb5b488 2314 }
9fbdd100 2315
892fedb6 2316 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2317 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2318 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2319 if (debug)
40381db7 2320 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2321 continue;
2322 }
9fbdd100 2323
9bcb3eef 2324 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2325
9bcb3eef 2326 reason = dest->reason;
40381db7 2327 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2328 debug, pfx_buf, afi, safi,
2329 &dest->reason)) {
19ea4cec
DS
2330 if (new_select == NULL &&
2331 reason != bgp_path_selection_none)
9bcb3eef 2332 dest->reason = reason;
40381db7 2333 new_select = pi;
d62a17ae 2334 }
2335 }
718e3744 2336
d62a17ae 2337 /* Now that we know which path is the bestpath see if any of the other
2338 * paths
2339 * qualify as multipaths
2340 */
2341 if (debug) {
2342 if (new_select)
18ee8310
DS
2343 bgp_path_info_path_with_addpath_rx_str(new_select,
2344 path_buf);
d62a17ae 2345 else
772270f3 2346 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2347 zlog_debug(
2348 "%s: After path selection, newbest is %s oldbest was %s",
2349 pfx_buf, path_buf,
2350 old_select ? old_select->peer->host : "NONE");
96450faf 2351 }
9fbdd100 2352
d62a17ae 2353 if (do_mpath && new_select) {
9bcb3eef 2354 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2355 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2356
2357 if (debug)
18ee8310 2358 bgp_path_info_path_with_addpath_rx_str(
40381db7 2359 pi, path_buf);
d62a17ae 2360
40381db7 2361 if (pi == new_select) {
d62a17ae 2362 if (debug)
2363 zlog_debug(
2364 "%s: %s is the bestpath, add to the multipath list",
2365 pfx_buf, path_buf);
40381db7 2366 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2367 continue;
2368 }
2369
40381db7 2370 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2371 continue;
2372
40381db7
DS
2373 if (pi->peer && pi->peer != bgp->peer_self
2374 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2375 PEER_STATUS_NSF_WAIT))
40381db7 2376 if (pi->peer->status != Established)
d62a17ae 2377 continue;
2378
40381db7 2379 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2380 if (debug)
2381 zlog_debug(
2382 "%s: %s has the same nexthop as the bestpath, skip it",
2383 pfx_buf, path_buf);
2384 continue;
2385 }
2386
40381db7 2387 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2388 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2389 &dest->reason);
d62a17ae 2390
2391 if (paths_eq) {
2392 if (debug)
2393 zlog_debug(
2394 "%s: %s is equivalent to the bestpath, add to the multipath list",
2395 pfx_buf, path_buf);
40381db7 2396 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2397 }
2398 }
2399 }
fee0f4c6 2400
9bcb3eef 2401 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2402 mpath_cfg);
2403 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2404 bgp_mp_list_clear(&mp_list);
96450faf 2405
9bcb3eef 2406 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2407
d62a17ae 2408 result->old = old_select;
2409 result->new = new_select;
96450faf 2410
d62a17ae 2411 return;
fee0f4c6 2412}
2413
3f9c7369
DS
2414/*
2415 * A new route/change in bestpath of an existing route. Evaluate the path
2416 * for advertisement to the subgroup.
2417 */
3dc339cd
DA
2418void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2419 struct bgp_path_info *selected,
9bcb3eef 2420 struct bgp_dest *dest,
3dc339cd 2421 uint32_t addpath_tx_id)
d62a17ae 2422{
b54892e0 2423 const struct prefix *p;
d62a17ae 2424 struct peer *onlypeer;
2425 struct attr attr;
2426 afi_t afi;
2427 safi_t safi;
adbac85e 2428
9bcb3eef 2429 p = bgp_dest_get_prefix(dest);
d62a17ae 2430 afi = SUBGRP_AFI(subgrp);
2431 safi = SUBGRP_SAFI(subgrp);
2432 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2433 : NULL);
2434
e0207895
PZ
2435 if (BGP_DEBUG(update, UPDATE_OUT)) {
2436 char buf_prefix[PREFIX_STRLEN];
2437 prefix2str(p, buf_prefix, sizeof(buf_prefix));
ddb5b488
PZ
2438 zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
2439 selected);
e0207895
PZ
2440 }
2441
d62a17ae 2442 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2443 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2444 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2445 return;
d62a17ae 2446
2447 memset(&attr, 0, sizeof(struct attr));
2448 /* It's initialized in bgp_announce_check() */
2449
2450 /* Announcement to the subgroup. If the route is filtered withdraw it.
2451 */
2452 if (selected) {
9bcb3eef
DS
2453 if (subgroup_announce_check(dest, selected, subgrp, p, &attr))
2454 bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
d62a17ae 2455 else
9bcb3eef 2456 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2457 addpath_tx_id);
d62a17ae 2458 }
2459
2460 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2461 else {
9bcb3eef 2462 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2463 }
200df115 2464}
fee0f4c6 2465
3064bf43 2466/*
e1072051 2467 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2468 * This is called at the end of route processing.
3064bf43 2469 */
9bcb3eef 2470void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2471{
40381db7 2472 struct bgp_path_info *pi;
3064bf43 2473
9bcb3eef 2474 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2475 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2476 continue;
40381db7
DS
2477 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2478 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2479 }
3064bf43 2480}
2481
2482/*
2483 * Has the route changed from the RIB's perspective? This is invoked only
2484 * if the route selection returns the same best route as earlier - to
2485 * determine if we need to update zebra or not.
2486 */
9bcb3eef 2487bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2488{
4b7e6066 2489 struct bgp_path_info *mpinfo;
d62a17ae 2490
2bb9eff4
DS
2491 /* If this is multipath, check all selected paths for any nexthop
2492 * change or attribute change. Some attribute changes (e.g., community)
2493 * aren't of relevance to the RIB, but we'll update zebra to ensure
2494 * we handle the case of BGP nexthop change. This is the behavior
2495 * when the best path has an attribute change anyway.
d62a17ae 2496 */
1defdda8 2497 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2498 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2499 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2500 return true;
d62a17ae 2501
2bb9eff4
DS
2502 /*
2503 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2504 */
18ee8310
DS
2505 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2506 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2507 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2508 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2509 return true;
d62a17ae 2510 }
3064bf43 2511
d62a17ae 2512 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2513 return false;
3064bf43 2514}
2515
d62a17ae 2516struct bgp_process_queue {
2517 struct bgp *bgp;
9bcb3eef 2518 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2519#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2520 unsigned int flags;
2521 unsigned int queued;
200df115 2522};
2523
3b0c17e1 2524static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2525 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2526 struct bgp_path_info *new_select,
2527 struct bgp_path_info *old_select)
2528{
9bcb3eef 2529 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2530
2531 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2532 return;
2533
2534 if (advertise_type5_routes(bgp, afi) && new_select
2535 && is_route_injectable_into_evpn(new_select)) {
2536
2537 /* apply the route-map */
2538 if (bgp->adv_cmd_rmap[afi][safi].map) {
2539 route_map_result_t ret;
2540 struct bgp_path_info rmap_path;
2541 struct bgp_path_info_extra rmap_path_extra;
2542 struct attr dummy_attr;
2543
2544 dummy_attr = *new_select->attr;
2545
2546 /* Fill temp path_info */
9bcb3eef 2547 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2548 new_select, new_select->peer,
2549 &dummy_attr);
2550
2551 RESET_FLAG(dummy_attr.rmap_change_flags);
2552
2553 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
2554 p, RMAP_BGP, &rmap_path);
2555
2556 if (ret == RMAP_DENYMATCH) {
2557 bgp_attr_flush(&dummy_attr);
2558 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2559 safi);
2560 } else
2561 bgp_evpn_advertise_type5_route(
2562 bgp, p, &dummy_attr, afi, safi);
2563 } else {
2564 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2565 afi, safi);
2566 }
2567 } else if (advertise_type5_routes(bgp, afi) && old_select
2568 && is_route_injectable_into_evpn(old_select))
2569 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2570}
2571
3103e8d2
DS
2572/*
2573 * old_select = The old best path
2574 * new_select = the new best path
2575 *
2576 * if (!old_select && new_select)
2577 * We are sending new information on.
2578 *
2579 * if (old_select && new_select) {
2580 * if (new_select != old_select)
2581 * We have a new best path send a change
2582 * else
2583 * We've received a update with new attributes that needs
2584 * to be passed on.
2585 * }
2586 *
2587 * if (old_select && !new_select)
2588 * We have no eligible route that we can announce or the rn
2589 * is being removed.
2590 */
9bcb3eef 2591static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2592 afi_t afi, safi_t safi)
d62a17ae 2593{
4b7e6066
DS
2594 struct bgp_path_info *new_select;
2595 struct bgp_path_info *old_select;
2596 struct bgp_path_info_pair old_and_new;
ddb5b488 2597 int debug = 0;
d62a17ae 2598
892fedb6 2599 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2600 if (dest)
2601 debug = bgp_debug_bestpath(dest);
b54892e0 2602 if (debug)
f4c713ae 2603 zlog_debug(
56ca3b5b 2604 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2605 __func__, dest);
f4c713ae
LB
2606 return;
2607 }
d62a17ae 2608 /* Is it end of initial update? (after startup) */
9bcb3eef 2609 if (!dest) {
d62a17ae 2610 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2611 sizeof(bgp->update_delay_zebra_resume_time));
2612
2613 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2614 FOREACH_AFI_SAFI (afi, safi) {
2615 if (bgp_fibupd_safi(safi))
2616 bgp_zebra_announce_table(bgp, afi, safi);
2617 }
d62a17ae 2618 bgp->main_peers_update_hold = 0;
2619
2620 bgp_start_routeadv(bgp);
aac24838 2621 return;
d62a17ae 2622 }
cb1faec9 2623
9bcb3eef 2624 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2625
9bcb3eef 2626 debug = bgp_debug_bestpath(dest);
b54892e0 2627 if (debug)
56ca3b5b 2628 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2629 afi2str(afi), safi2str(safi));
ddb5b488 2630
f009ff26 2631 /* The best path calculation for the route is deferred if
2632 * BGP_NODE_SELECT_DEFER is set
2633 */
9bcb3eef 2634 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2635 if (BGP_DEBUG(update, UPDATE_OUT))
9bcb3eef 2636 zlog_debug("SELECT_DEFER falg set for route %p", dest);
f009ff26 2637 return;
2638 }
2639
d62a17ae 2640 /* Best path selection. */
9bcb3eef 2641 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2642 afi, safi);
2643 old_select = old_and_new.old;
2644 new_select = old_and_new.new;
2645
2646 /* Do we need to allocate or free labels?
2647 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2648 * necessary to do this upon changes to best path. Exceptions:
2649 * - label index has changed -> recalculate resulting label
2650 * - path_info sub_type changed -> switch to/from implicit-null
2651 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2652 */
318cac96 2653 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2654 if (new_select) {
2655 if (!old_select
2656 || bgp_label_index_differs(new_select, old_select)
57592a53 2657 || new_select->sub_type != old_select->sub_type
9bcb3eef 2658 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2659 /* Enforced penultimate hop popping:
2660 * implicit-null for local routes, aggregate
2661 * and redistributed routes
2662 */
d62a17ae 2663 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2664 || new_select->sub_type
2665 == BGP_ROUTE_AGGREGATE
2666 || new_select->sub_type
2667 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2668 if (CHECK_FLAG(
9bcb3eef 2669 dest->flags,
d62a17ae 2670 BGP_NODE_REGISTERED_FOR_LABEL))
9bcb3eef 2671 bgp_unregister_for_label(dest);
70e98a7f 2672 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2673 &dest->local_label);
2674 bgp_set_valid_label(&dest->local_label);
d62a17ae 2675 } else
9bcb3eef
DS
2676 bgp_register_for_label(dest,
2677 new_select);
d62a17ae 2678 }
9bcb3eef 2679 } else if (CHECK_FLAG(dest->flags,
a4d82a8a 2680 BGP_NODE_REGISTERED_FOR_LABEL)) {
9bcb3eef 2681 bgp_unregister_for_label(dest);
318cac96 2682 }
9bcb3eef
DS
2683 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)) {
2684 bgp_unregister_for_label(dest);
d62a17ae 2685 }
cd1964ff 2686
b54892e0 2687 if (debug)
ddb5b488 2688 zlog_debug(
56ca3b5b 2689 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2690 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2691 old_select, new_select);
ddb5b488 2692
d62a17ae 2693 /* If best route remains the same and this is not due to user-initiated
2694 * clear, see exactly what needs to be done.
2695 */
d62a17ae 2696 if (old_select && old_select == new_select
9bcb3eef 2697 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2698 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2699 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2700 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2701#ifdef ENABLE_BGP_VNC
d62a17ae 2702 vnc_import_bgp_add_route(bgp, p, old_select);
2703 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2704#endif
bb744275 2705 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2706 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2707
2708 if (new_select->type == ZEBRA_ROUTE_BGP
2709 && (new_select->sub_type == BGP_ROUTE_NORMAL
2710 || new_select->sub_type
2711 == BGP_ROUTE_IMPORTED))
2712
9bcb3eef 2713 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2714 bgp, afi, safi);
2715 }
d62a17ae 2716 }
d62a17ae 2717
2718 /* If there is a change of interest to peers, reannounce the
2719 * route. */
1defdda8 2720 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2721 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2722 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2723 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2724
2725 /* unicast routes must also be annouced to
2726 * labeled-unicast update-groups */
2727 if (safi == SAFI_UNICAST)
2728 group_announce_route(bgp, afi,
9bcb3eef 2729 SAFI_LABELED_UNICAST, dest,
d62a17ae 2730 new_select);
2731
1defdda8 2732 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2733 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2734 }
fee0f4c6 2735
3b0c17e1 2736 /* advertise/withdraw type-5 routes */
2737 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2738 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2739 bgp_process_evpn_route_injection(
9bcb3eef 2740 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2741
b1875e65 2742 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2743 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2744 bgp_zebra_clear_route_change_flags(dest);
2745 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2746 return;
d62a17ae 2747 }
8ad7271d 2748
d62a17ae 2749 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2750 */
9bcb3eef 2751 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2752
2753 /* bestpath has changed; bump version */
2754 if (old_select || new_select) {
9bcb3eef 2755 bgp_bump_version(dest);
d62a17ae 2756
2757 if (!bgp->t_rmap_def_originate_eval) {
2758 bgp_lock(bgp);
2759 thread_add_timer(
2760 bm->master,
2761 update_group_refresh_default_originate_route_map,
2762 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2763 &bgp->t_rmap_def_originate_eval);
2764 }
2765 }
3f9c7369 2766
d62a17ae 2767 if (old_select)
9bcb3eef 2768 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2769 if (new_select) {
ddb5b488
PZ
2770 if (debug)
2771 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2772 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2773 bgp_path_info_unset_flag(dest, new_select,
2774 BGP_PATH_ATTR_CHANGED);
1defdda8 2775 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2776 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2777 }
338b3424 2778
49e5a4a0 2779#ifdef ENABLE_BGP_VNC
d62a17ae 2780 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2781 if (old_select != new_select) {
2782 if (old_select) {
2783 vnc_import_bgp_exterior_del_route(bgp, p,
2784 old_select);
2785 vnc_import_bgp_del_route(bgp, p, old_select);
2786 }
2787 if (new_select) {
2788 vnc_import_bgp_exterior_add_route(bgp, p,
2789 new_select);
2790 vnc_import_bgp_add_route(bgp, p, new_select);
2791 }
2792 }
2793 }
65efcfce
LB
2794#endif
2795
9bcb3eef 2796 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2797
2798 /* unicast routes must also be annouced to labeled-unicast update-groups
2799 */
2800 if (safi == SAFI_UNICAST)
9bcb3eef 2801 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2802 new_select);
2803
2804 /* FIB update. */
2805 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2806 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2807 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2808 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2809 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2810 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2811
2812 /* if this is an evpn imported type-5 prefix,
2813 * we need to withdraw the route first to clear
2814 * the nh neigh and the RMAC entry.
2815 */
2816 if (old_select &&
2817 is_route_parent_evpn(old_select))
2818 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2819
9bcb3eef 2820 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2821 } else {
d62a17ae 2822 /* Withdraw the route from the kernel. */
2823 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2824 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2825 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2826 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2827
568e10ca 2828 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2829 }
718e3744 2830 }
3064bf43 2831
9bcb3eef 2832 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2833 old_select);
5424b7ba 2834
d62a17ae 2835 /* Clear any route change flags. */
9bcb3eef 2836 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2837
18ee8310 2838 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2839 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2840 bgp_path_info_reap(dest, old_select);
d62a17ae 2841
9bcb3eef 2842 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2843 return;
718e3744 2844}
2845
f009ff26 2846/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2847int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2848{
9bcb3eef 2849 struct bgp_dest *dest;
f009ff26 2850 int cnt = 0;
2851 struct afi_safi_info *thread_info;
2852 struct listnode *node = NULL, *nnode = NULL;
2853
2854 if (bgp->gr_info[afi][safi].t_route_select)
2855 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
2856
2857 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2858 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2859 get_afi_safi_str(afi, safi, false),
2860 listcount(bgp->gr_info[afi][safi].route_list));
f009ff26 2861 }
2862
2863 /* Process the route list */
2864 node = listhead(bgp->gr_info[afi][safi].route_list);
f009ff26 2865 while (node) {
9bcb3eef 2866 dest = listgetdata(node);
f009ff26 2867 nnode = node->next;
2868 list_delete_node(bgp->gr_info[afi][safi].route_list, node);
9bcb3eef 2869 dest->rt_node = NULL;
f009ff26 2870
9bcb3eef
DS
2871 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
2872 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2873 bgp_process_main_one(bgp, dest, afi, safi);
f009ff26 2874 cnt++;
2875 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
2876 break;
2877 }
2878 node = nnode;
2879 }
2880
9e3b51a7 2881 /* Send EOR message when all routes are processed */
2882 if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
2883 bgp_send_delayed_eor(bgp);
8c48b3b6 2884 /* Send route processing complete message to RIB */
2885 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2886 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2887 return 0;
9e3b51a7 2888 }
f009ff26 2889
2890 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 2891
2892 thread_info->afi = afi;
2893 thread_info->safi = safi;
2894 thread_info->bgp = bgp;
2895
2896 /* If there are more routes to be processed, start the
2897 * selection timer
2898 */
2899 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
2900 BGP_ROUTE_SELECT_DELAY,
2901 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 2902 return 0;
2903}
2904
aac24838 2905static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 2906{
aac24838
JB
2907 struct bgp_process_queue *pqnode = data;
2908 struct bgp *bgp = pqnode->bgp;
d62a17ae 2909 struct bgp_table *table;
9bcb3eef 2910 struct bgp_dest *dest;
aac24838
JB
2911
2912 /* eoiu marker */
2913 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
2914 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
2915 /* should always have dedicated wq call */
2916 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
2917 return WQ_SUCCESS;
2918 }
2919
ac021f40 2920 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 2921 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 2922 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
2923 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
2924 table = bgp_dest_table(dest);
2925 /* note, new DESTs may be added as part of processing */
2926 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 2927
9bcb3eef 2928 bgp_dest_unlock_node(dest);
d62a17ae 2929 bgp_table_unlock(table);
2930 }
aac24838
JB
2931
2932 return WQ_SUCCESS;
2933}
2934
2935static void bgp_processq_del(struct work_queue *wq, void *data)
2936{
2937 struct bgp_process_queue *pqnode = data;
2938
2939 bgp_unlock(pqnode->bgp);
2940
2941 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 2942}
2943
d62a17ae 2944void bgp_process_queue_init(void)
200df115 2945{
0ce1ca80 2946 if (!bm->process_main_queue)
d62a17ae 2947 bm->process_main_queue =
2948 work_queue_new(bm->master, "process_main_queue");
2949
aac24838 2950 bm->process_main_queue->spec.workfunc = &bgp_process_wq;
d62a17ae 2951 bm->process_main_queue->spec.del_item_data = &bgp_processq_del;
2952 bm->process_main_queue->spec.max_retries = 0;
2953 bm->process_main_queue->spec.hold = 50;
2954 /* Use a higher yield value of 50ms for main queue processing */
2955 bm->process_main_queue->spec.yield = 50 * 1000L;
200df115 2956}
2957
cfe8d15a 2958static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
2959{
2960 struct bgp_process_queue *pqnode;
2961
a4d82a8a
PZ
2962 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
2963 sizeof(struct bgp_process_queue));
aac24838
JB
2964
2965 /* unlocked in bgp_processq_del */
2966 pqnode->bgp = bgp_lock(bgp);
2967 STAILQ_INIT(&pqnode->pqueue);
2968
aac24838
JB
2969 return pqnode;
2970}
2971
9bcb3eef 2972void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 2973{
aac24838
JB
2974#define ARBITRARY_PROCESS_QLEN 10000
2975 struct work_queue *wq = bm->process_main_queue;
d62a17ae 2976 struct bgp_process_queue *pqnode;
cfe8d15a 2977 int pqnode_reuse = 0;
495f0b13 2978
d62a17ae 2979 /* already scheduled for processing? */
9bcb3eef 2980 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 2981 return;
2e02b9b2 2982
f009ff26 2983 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
2984 * the workqueue
2985 */
9bcb3eef 2986 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2987 if (BGP_DEBUG(update, UPDATE_OUT))
2988 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 2989 dest);
f009ff26 2990 return;
2991 }
2992
aac24838 2993 if (wq == NULL)
d62a17ae 2994 return;
2995
aac24838 2996 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
2997 limit only if is from the same BGP view and it's not an EOIU marker
2998 */
aac24838
JB
2999 if (work_queue_item_count(wq)) {
3000 struct work_queue_item *item = work_queue_last_item(wq);
3001 pqnode = item->data;
228da428 3002
a4d82a8a
PZ
3003 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3004 || pqnode->bgp != bgp
3005 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3006 pqnode = bgp_processq_alloc(bgp);
3007 else
3008 pqnode_reuse = 1;
aac24838 3009 } else
cfe8d15a 3010 pqnode = bgp_processq_alloc(bgp);
aac24838 3011 /* all unlocked in bgp_process_wq */
9bcb3eef 3012 bgp_table_lock(bgp_dest_table(dest));
aac24838 3013
9bcb3eef
DS
3014 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3015 bgp_dest_lock_node(dest);
aac24838 3016
60466a63 3017 /* can't be enqueued twice */
9bcb3eef
DS
3018 assert(STAILQ_NEXT(dest, pq) == NULL);
3019 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3020 pqnode->queued++;
3021
cfe8d15a
LB
3022 if (!pqnode_reuse)
3023 work_queue_add(wq, pqnode);
3024
d62a17ae 3025 return;
fee0f4c6 3026}
0a486e5f 3027
d62a17ae 3028void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3029{
d62a17ae 3030 struct bgp_process_queue *pqnode;
cb1faec9 3031
d62a17ae 3032 if (bm->process_main_queue == NULL)
3033 return;
2e02b9b2 3034
cfe8d15a 3035 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3036
aac24838 3037 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
cfe8d15a 3038 work_queue_add(bm->process_main_queue, pqnode);
cb1faec9
DS
3039}
3040
d62a17ae 3041static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3042{
d62a17ae 3043 struct peer *peer;
0a486e5f 3044
d62a17ae 3045 peer = THREAD_ARG(thread);
3046 peer->t_pmax_restart = NULL;
0a486e5f 3047
d62a17ae 3048 if (bgp_debug_neighbor_events(peer))
3049 zlog_debug(
3050 "%s Maximum-prefix restart timer expired, restore peering",
3051 peer->host);
0a486e5f 3052
a9bafa95 3053 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3054 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3055
d62a17ae 3056 return 0;
0a486e5f 3057}
3058
9cbd06e0
DA
3059static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3060 safi_t safi)
3061{
3062 uint32_t count = 0;
f41b0459 3063 bool filtered = false;
9cbd06e0
DA
3064 struct bgp_dest *dest;
3065 struct bgp_adj_in *ain;
40bb2ccf 3066 struct attr attr = {};
9cbd06e0
DA
3067 struct bgp_table *table = peer->bgp->rib[afi][safi];
3068
3069 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3070 for (ain = dest->adj_in; ain; ain = ain->next) {
3071 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3072
3073 attr = *ain->attr;
9cbd06e0
DA
3074
3075 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3076 == FILTER_DENY)
f41b0459
DA
3077 filtered = true;
3078
3079 if (bgp_input_modifier(
3080 peer, rn_p, &attr, afi, safi,
3081 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3082 NULL, 0, NULL)
3083 == RMAP_DENY)
3084 filtered = true;
3085
3086 if (filtered)
9cbd06e0 3087 count++;
f41b0459
DA
3088
3089 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3090 }
3091 }
3092
3093 return count;
3094}
3095
3dc339cd
DA
3096bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3097 int always)
718e3744 3098{
d62a17ae 3099 iana_afi_t pkt_afi;
5c525538 3100 iana_safi_t pkt_safi;
9cbd06e0
DA
3101 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3102 PEER_FLAG_MAX_PREFIX_FORCE))
3103 ? bgp_filtered_routes_count(peer, afi, safi)
3104 + peer->pcount[afi][safi]
3105 : peer->pcount[afi][safi];
9cabb64b 3106
d62a17ae 3107 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3108 return false;
e0701b79 3109
9cbd06e0 3110 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3111 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3112 PEER_STATUS_PREFIX_LIMIT)
3113 && !always)
3dc339cd 3114 return false;
e0701b79 3115
d62a17ae 3116 zlog_info(
6cde4b45 3117 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3118 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3119 peer->pmax[afi][safi]);
d62a17ae 3120 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3121
3122 if (CHECK_FLAG(peer->af_flags[afi][safi],
3123 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3124 return false;
d62a17ae 3125
3126 /* Convert AFI, SAFI to values for packet. */
3127 pkt_afi = afi_int2iana(afi);
3128 pkt_safi = safi_int2iana(safi);
3129 {
d7c0a89a 3130 uint8_t ndata[7];
d62a17ae 3131
3132 ndata[0] = (pkt_afi >> 8);
3133 ndata[1] = pkt_afi;
3134 ndata[2] = pkt_safi;
3135 ndata[3] = (peer->pmax[afi][safi] >> 24);
3136 ndata[4] = (peer->pmax[afi][safi] >> 16);
3137 ndata[5] = (peer->pmax[afi][safi] >> 8);
3138 ndata[6] = (peer->pmax[afi][safi]);
3139
3140 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3141 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3142 BGP_NOTIFY_CEASE_MAX_PREFIX,
3143 ndata, 7);
3144 }
3145
3146 /* Dynamic peers will just close their connection. */
3147 if (peer_dynamic_neighbor(peer))
3dc339cd 3148 return true;
d62a17ae 3149
3150 /* restart timer start */
3151 if (peer->pmax_restart[afi][safi]) {
3152 peer->v_pmax_restart =
3153 peer->pmax_restart[afi][safi] * 60;
3154
3155 if (bgp_debug_neighbor_events(peer))
3156 zlog_debug(
3157 "%s Maximum-prefix restart timer started for %d secs",
3158 peer->host, peer->v_pmax_restart);
3159
3160 BGP_TIMER_ON(peer->t_pmax_restart,
3161 bgp_maximum_prefix_restart_timer,
3162 peer->v_pmax_restart);
3163 }
3164
3dc339cd 3165 return true;
d62a17ae 3166 } else
3167 UNSET_FLAG(peer->af_sflags[afi][safi],
3168 PEER_STATUS_PREFIX_LIMIT);
3169
b1823b69
DS
3170 if (pcount
3171 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3172 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3173 PEER_STATUS_PREFIX_THRESHOLD)
3174 && !always)
3dc339cd 3175 return false;
d62a17ae 3176
3177 zlog_info(
6cde4b45 3178 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3179 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3180 peer->pmax[afi][safi]);
d62a17ae 3181 SET_FLAG(peer->af_sflags[afi][safi],
3182 PEER_STATUS_PREFIX_THRESHOLD);
3183 } else
3184 UNSET_FLAG(peer->af_sflags[afi][safi],
3185 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3186 return false;
718e3744 3187}
3188
b40d939b 3189/* Unconditionally remove the route from the RIB, without taking
3190 * damping into consideration (eg, because the session went down)
3191 */
9bcb3eef 3192void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3193 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3194{
f009ff26 3195
3196 struct bgp *bgp = NULL;
3197 bool delete_route = false;
3198
9bcb3eef
DS
3199 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3200 safi);
d62a17ae 3201
f009ff26 3202 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3203 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3204
f009ff26 3205 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3206 * flag
3207 */
3208 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3209 delete_route = true;
9bcb3eef 3210 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3211 delete_route = true;
f009ff26 3212 if (delete_route) {
9bcb3eef
DS
3213 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3214 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3215 bgp = pi->peer->bgp;
9bcb3eef 3216 if ((dest->rt_node)
36235319
QY
3217 && (bgp->gr_info[afi][safi].route_list)) {
3218 list_delete_node(bgp->gr_info[afi][safi]
3219 .route_list,
9bcb3eef
DS
3220 dest->rt_node);
3221 dest->rt_node = NULL;
f009ff26 3222 }
3223 }
3224 }
3225 }
4a11bf2c 3226
9bcb3eef
DS
3227 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3228 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3229}
3230
9bcb3eef 3231static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3232 struct peer *peer, afi_t afi, safi_t safi,
3233 struct prefix_rd *prd)
3234{
9bcb3eef 3235 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3236
d62a17ae 3237 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3238 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3239 */
3240 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3241 && peer->sort == BGP_PEER_EBGP)
9bcb3eef 3242 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
d62a17ae 3243 == BGP_DAMP_SUPPRESSED) {
b54892e0 3244 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
d62a17ae 3245 safi);
3246 return;
3247 }
3248
49e5a4a0 3249#ifdef ENABLE_BGP_VNC
d62a17ae 3250 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3251 struct bgp_dest *pdest = NULL;
d62a17ae 3252 struct bgp_table *table = NULL;
3253
9bcb3eef
DS
3254 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3255 (struct prefix *)prd);
3256 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3257 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3258
3259 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3260 peer->bgp, prd, table, p, pi);
d62a17ae 3261 }
9bcb3eef 3262 bgp_dest_unlock_node(pdest);
d62a17ae 3263 }
3264 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3265 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3266
b54892e0
DS
3267 vnc_import_bgp_del_route(peer->bgp, p, pi);
3268 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3269 }
65efcfce 3270 }
d62a17ae 3271#endif
128ea8ab 3272
d62a17ae 3273 /* If this is an EVPN route, process for un-import. */
3274 if (safi == SAFI_EVPN)
b54892e0 3275 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3276
9bcb3eef 3277 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3278}
3279
4b7e6066
DS
3280struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3281 struct peer *peer, struct attr *attr,
9bcb3eef 3282 struct bgp_dest *dest)
fb018d25 3283{
4b7e6066 3284 struct bgp_path_info *new;
fb018d25 3285
d62a17ae 3286 /* Make new BGP info. */
4b7e6066 3287 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3288 new->type = type;
3289 new->instance = instance;
3290 new->sub_type = sub_type;
3291 new->peer = peer;
3292 new->attr = attr;
3293 new->uptime = bgp_clock();
9bcb3eef 3294 new->net = dest;
d62a17ae 3295 return new;
fb018d25
DS
3296}
3297
d62a17ae 3298static void overlay_index_update(struct attr *attr,
d62a17ae 3299 union gw_addr *gw_ip)
684a7227 3300{
d62a17ae 3301 if (!attr)
3302 return;
d62a17ae 3303 if (gw_ip == NULL) {
3304 memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
3305 } else {
3306 memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
3307 sizeof(union gw_addr));
3308 }
684a7227
PG
3309}
3310
40381db7 3311static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3312 union gw_addr *gw_ip)
3313{
40381db7 3314 union gw_addr *path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3315 union {
0a50c248 3316 esi_t esi;
11ebf4ed
DS
3317 union gw_addr ip;
3318 } temp;
d62a17ae 3319
3320 if (afi != AFI_L2VPN)
3321 return true;
11ebf4ed 3322
05864da7 3323 path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
11ebf4ed
DS
3324
3325 if (gw_ip == NULL) {
3326 memset(&temp, 0, sizeof(temp));
40381db7 3327 path_gw_ip_remote = &temp.ip;
11ebf4ed 3328 } else
40381db7 3329 path_gw_ip_remote = gw_ip;
11ebf4ed 3330
0a50c248 3331 return !!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3332}
3333
c265ee22 3334/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3335bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3336 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3337 struct bgp_dest *dest)
d62a17ae 3338{
2dbe3fa9 3339 bool ret = false;
b099a5c8
DA
3340 bool is_bgp_static_route =
3341 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3342 : false;
d62a17ae 3343
e8442016
DS
3344 /*
3345 * Only validated for unicast and multicast currently.
3346 * Also valid for EVPN where the nexthop is an IP address.
3347 * If we are a bgp static route being checked then there is
3348 * no need to check to see if the nexthop is martian as
3349 * that it should be ok.
3350 */
3351 if (is_bgp_static_route ||
3352 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3353 return false;
d62a17ae 3354
3355 /* If NEXT_HOP is present, validate it. */
3356 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3357 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3358 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3359 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3360 return true;
d62a17ae 3361 }
c265ee22 3362
d62a17ae 3363 /* If MP_NEXTHOP is present, validate it. */
3364 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3365 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3366 * it is not an IPv6 link-local address.
0355b41d
DA
3367 *
3368 * If we receive an UPDATE with nexthop length set to 32 bytes
3369 * we shouldn't discard an UPDATE if it's set to (::).
3370 * The link-local (2st) is validated along the code path later.
d62a17ae 3371 */
3372 if (attr->mp_nexthop_len) {
3373 switch (attr->mp_nexthop_len) {
3374 case BGP_ATTR_NHLEN_IPV4:
3375 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3376 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3377 || IPV4_CLASS_DE(
3378 ntohl(attr->mp_nexthop_global_in.s_addr))
3379 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3380 dest));
d62a17ae 3381 break;
3382
3383 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3384 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3385 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3386 &attr->mp_nexthop_global)
d62a17ae 3387 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3388 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3389 &attr->mp_nexthop_global)
3390 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3391 dest));
d62a17ae 3392 break;
0355b41d
DA
3393 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3394 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3395 || IN6_IS_ADDR_MULTICAST(
3396 &attr->mp_nexthop_global)
3397 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3398 dest));
0355b41d 3399 break;
d62a17ae 3400
3401 default:
3dc339cd 3402 ret = true;
d62a17ae 3403 break;
3404 }
3405 }
c265ee22 3406
d62a17ae 3407 return ret;
3408}
3409
5a1ae2c2 3410int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3411 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3412 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3413 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3414 struct bgp_route_evpn *evpn)
d62a17ae 3415{
3416 int ret;
3417 int aspath_loop_count = 0;
9bcb3eef 3418 struct bgp_dest *dest;
d62a17ae 3419 struct bgp *bgp;
3420 struct attr new_attr;
3421 struct attr *attr_new;
40381db7 3422 struct bgp_path_info *pi;
4b7e6066
DS
3423 struct bgp_path_info *new;
3424 struct bgp_path_info_extra *extra;
d62a17ae 3425 const char *reason;
3426 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3427 int connected = 0;
3428 int do_loop_check = 1;
3429 int has_valid_label = 0;
7c312383 3430 afi_t nh_afi;
949b0f24 3431 uint8_t pi_type = 0;
3432 uint8_t pi_sub_type = 0;
3433
49e5a4a0 3434#ifdef ENABLE_BGP_VNC
d62a17ae 3435 int vnc_implicit_withdraw = 0;
65efcfce 3436#endif
d62a17ae 3437 int same_attr = 0;
718e3744 3438
d62a17ae 3439 memset(&new_attr, 0, sizeof(struct attr));
3440 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3441 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3442
d62a17ae 3443 bgp = peer->bgp;
9bcb3eef 3444 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3445 /* TODO: Check to see if we can get rid of "is_valid_label" */
3446 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3447 has_valid_label = (num_labels > 0) ? 1 : 0;
3448 else
3449 has_valid_label = bgp_is_valid_label(label);
718e3744 3450
d62a17ae 3451 /* When peer's soft reconfiguration enabled. Record input packet in
3452 Adj-RIBs-In. */
3453 if (!soft_reconfig
3454 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3455 && peer != bgp->peer_self)
9bcb3eef 3456 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3457
3458 /* Check previously received route. */
9bcb3eef 3459 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3460 if (pi->peer == peer && pi->type == type
3461 && pi->sub_type == sub_type
3462 && pi->addpath_rx_id == addpath_id)
d62a17ae 3463 break;
3464
3465 /* AS path local-as loop check. */
3466 if (peer->change_local_as) {
c4368918
DW
3467 if (peer->allowas_in[afi][safi])
3468 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3469 else if (!CHECK_FLAG(peer->flags,
3470 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3471 aspath_loop_count = 1;
3472
3473 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3474 > aspath_loop_count) {
b4d46cc9 3475 peer->stat_pfx_aspath_loop++;
9bcb3eef 3476 reason = "as-path contains our own AS A;";
d62a17ae 3477 goto filtered;
3478 }
718e3744 3479 }
718e3744 3480
d62a17ae 3481 /* If the peer is configured for "allowas-in origin" and the last ASN in
3482 * the
3483 * as-path is our ASN then we do not need to call aspath_loop_check
3484 */
3485 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3486 if (aspath_get_last_as(attr->aspath) == bgp->as)
3487 do_loop_check = 0;
3488
3489 /* AS path loop check. */
3490 if (do_loop_check) {
3491 if (aspath_loop_check(attr->aspath, bgp->as)
3492 > peer->allowas_in[afi][safi]
3493 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3494 && aspath_loop_check(attr->aspath, bgp->confed_id)
3495 > peer->allowas_in[afi][safi])) {
b4d46cc9 3496 peer->stat_pfx_aspath_loop++;
d62a17ae 3497 reason = "as-path contains our own AS;";
3498 goto filtered;
3499 }
3500 }
aac9ef6c 3501
d62a17ae 3502 /* Route reflector originator ID check. */
3503 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3504 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3505 peer->stat_pfx_originator_loop++;
d62a17ae 3506 reason = "originator is us;";
3507 goto filtered;
3508 }
718e3744 3509
d62a17ae 3510 /* Route reflector cluster ID check. */
3511 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3512 peer->stat_pfx_cluster_loop++;
d62a17ae 3513 reason = "reflected from the same cluster;";
3514 goto filtered;
3515 }
718e3744 3516
d62a17ae 3517 /* Apply incoming filter. */
3518 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3519 peer->stat_pfx_filter++;
d62a17ae 3520 reason = "filter;";
3521 goto filtered;
3522 }
718e3744 3523
a8b72dc6
DA
3524 /* RFC 8212 to prevent route leaks.
3525 * This specification intends to improve this situation by requiring the
3526 * explicit configuration of both BGP Import and Export Policies for any
3527 * External BGP (EBGP) session such as customers, peers, or
3528 * confederation boundaries for all enabled address families. Through
3529 * codification of the aforementioned requirement, operators will
3530 * benefit from consistent behavior across different BGP
3531 * implementations.
3532 */
1d3fdccf 3533 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3534 if (!bgp_inbound_policy_exists(peer,
3535 &peer->filter[afi][safi])) {
3536 reason = "inbound policy missing";
3537 goto filtered;
3538 }
3539
fb29348a
DA
3540 /* draft-ietf-idr-deprecate-as-set-confed-set
3541 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3542 * Eventually, This document (if approved) updates RFC 4271
3543 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3544 * and obsoletes RFC 6472.
3545 */
7f972cd8 3546 if (peer->bgp->reject_as_sets)
fb29348a
DA
3547 if (aspath_check_as_sets(attr->aspath)) {
3548 reason =
3549 "as-path contains AS_SET or AS_CONFED_SET type;";
3550 goto filtered;
3551 }
3552
6f4f49b2 3553 new_attr = *attr;
d62a17ae 3554
3555 /* Apply incoming route-map.
3556 * NB: new_attr may now contain newly allocated values from route-map
3557 * "set"
3558 * commands, so we need bgp_attr_flush in the error paths, until we
3559 * intern
3560 * the attr (which takes over the memory references) */
9bcb3eef
DS
3561 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3562 num_labels, dest)
3563 == RMAP_DENY) {
b4d46cc9 3564 peer->stat_pfx_filter++;
d62a17ae 3565 reason = "route-map;";
3566 bgp_attr_flush(&new_attr);
3567 goto filtered;
3568 }
718e3744 3569
05864da7 3570 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3571 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3572 /* remove from RIB previous entry */
3573 bgp_zebra_withdraw(p, pi, bgp, safi);
3574 }
3575
7f323236
DW
3576 if (peer->sort == BGP_PEER_EBGP) {
3577
a4d82a8a
PZ
3578 /* If we receive the graceful-shutdown community from an eBGP
3579 * peer we must lower local-preference */
3580 if (new_attr.community
3581 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3582 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3583 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3584
a4d82a8a
PZ
3585 /* If graceful-shutdown is configured then add the GSHUT
3586 * community to all paths received from eBGP peers */
637e5ba4 3587 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3588 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3589 }
3590
949b0f24 3591 if (pi) {
3592 pi_type = pi->type;
3593 pi_sub_type = pi->sub_type;
3594 }
3595
d62a17ae 3596 /* next hop check. */
a4d82a8a 3597 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3598 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3599 &new_attr, dest)) {
b4d46cc9 3600 peer->stat_pfx_nh_invalid++;
d62a17ae 3601 reason = "martian or self next-hop;";
3602 bgp_attr_flush(&new_attr);
3603 goto filtered;
3604 }
718e3744 3605
5c14a191 3606 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3607 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3608 reason = "self mac;";
3609 goto filtered;
3610 }
3611
1e9be514
QY
3612 /* Update Overlay Index */
3613 if (afi == AFI_L2VPN) {
3614 overlay_index_update(&new_attr,
3615 evpn == NULL ? NULL : &evpn->gw_ip);
3616 }
3617
d62a17ae 3618 attr_new = bgp_attr_intern(&new_attr);
3619
9cbd06e0
DA
3620 /* If maximum prefix count is configured and current prefix
3621 * count exeed it.
3622 */
3623 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3624 return -1;
3625
d62a17ae 3626 /* If the update is implicit withdraw. */
40381db7
DS
3627 if (pi) {
3628 pi->uptime = bgp_clock();
3629 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3630
9bcb3eef 3631 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3632
d62a17ae 3633 /* Same attribute comes in. */
40381db7
DS
3634 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3635 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3636 && (!has_valid_label
40381db7 3637 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3638 num_labels * sizeof(mpls_label_t))
d62a17ae 3639 == 0)
3640 && (overlay_index_equal(
0a50c248 3641 afi, pi,
d62a17ae 3642 evpn == NULL ? NULL : &evpn->gw_ip))) {
3643 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3644 BGP_CONFIG_DAMPENING)
3645 && peer->sort == BGP_PEER_EBGP
40381db7 3646 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3647 if (bgp_debug_update(peer, p, NULL, 1)) {
3648 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3649 afi, safi, prd, p, label,
3650 num_labels, addpath_id ? 1 : 0,
3651 addpath_id, pfx_buf,
3652 sizeof(pfx_buf));
d62a17ae 3653 zlog_debug("%s rcvd %s", peer->host,
3654 pfx_buf);
3655 }
3656
9bcb3eef 3657 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3658 != BGP_DAMP_SUPPRESSED) {
40381db7 3659 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3660 safi);
9bcb3eef 3661 bgp_process(bgp, dest, afi, safi);
d62a17ae 3662 }
3663 } else /* Duplicate - odd */
3664 {
3665 if (bgp_debug_update(peer, p, NULL, 1)) {
3666 if (!peer->rcvd_attr_printed) {
3667 zlog_debug(
3668 "%s rcvd UPDATE w/ attr: %s",
3669 peer->host,
3670 peer->rcvd_attr_str);
3671 peer->rcvd_attr_printed = 1;
3672 }
3673
3674 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3675 afi, safi, prd, p, label,
3676 num_labels, addpath_id ? 1 : 0,
3677 addpath_id, pfx_buf,
3678 sizeof(pfx_buf));
d62a17ae 3679 zlog_debug(
3680 "%s rcvd %s...duplicate ignored",
3681 peer->host, pfx_buf);
3682 }
3683
3684 /* graceful restart STALE flag unset. */
40381db7 3685 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3686 bgp_path_info_unset_flag(
9bcb3eef
DS
3687 dest, pi, BGP_PATH_STALE);
3688 bgp_dest_set_defer_flag(dest, false);
3689 bgp_process(bgp, dest, afi, safi);
d62a17ae 3690 }
3691 }
3692
9bcb3eef 3693 bgp_dest_unlock_node(dest);
d62a17ae 3694 bgp_attr_unintern(&attr_new);
3695
3696 return 0;
3697 }
718e3744 3698
d62a17ae 3699 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3700 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3701 if (bgp_debug_update(peer, p, NULL, 1)) {
3702 bgp_debug_rdpfxpath2str(
a4d82a8a 3703 afi, safi, prd, p, label, num_labels,
d62a17ae 3704 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3705 sizeof(pfx_buf));
3706 zlog_debug(
3707 "%s rcvd %s, flapped quicker than processing",
3708 peer->host, pfx_buf);
3709 }
3710
9bcb3eef 3711 bgp_path_info_restore(dest, pi);
d62a17ae 3712 }
718e3744 3713
d62a17ae 3714 /* Received Logging. */
3715 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3716 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3717 num_labels, addpath_id ? 1 : 0,
3718 addpath_id, pfx_buf,
3719 sizeof(pfx_buf));
d62a17ae 3720 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3721 }
718e3744 3722
d62a17ae 3723 /* graceful restart STALE flag unset. */
f009ff26 3724 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3725 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3726 bgp_dest_set_defer_flag(dest, false);
f009ff26 3727 }
d62a17ae 3728
3729 /* The attribute is changed. */
9bcb3eef 3730 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3731
3732 /* implicit withdraw, decrement aggregate and pcount here.
3733 * only if update is accepted, they'll increment below.
3734 */
40381db7 3735 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3736
3737 /* Update bgp route dampening information. */
3738 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3739 && peer->sort == BGP_PEER_EBGP) {
3740 /* This is implicit withdraw so we should update
3741 dampening
3742 information. */
40381db7 3743 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3744 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3745 }
49e5a4a0 3746#ifdef ENABLE_BGP_VNC
d62a17ae 3747 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3748 struct bgp_dest *pdest = NULL;
d62a17ae 3749 struct bgp_table *table = NULL;
3750
9bcb3eef
DS
3751 pdest = bgp_node_get(bgp->rib[afi][safi],
3752 (struct prefix *)prd);
3753 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3754 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3755
3756 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3757 bgp, prd, table, p, pi);
d62a17ae 3758 }
9bcb3eef 3759 bgp_dest_unlock_node(pdest);
d62a17ae 3760 }
3761 if ((afi == AFI_IP || afi == AFI_IP6)
3762 && (safi == SAFI_UNICAST)) {
40381db7 3763 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3764 /*
3765 * Implicit withdraw case.
3766 */
3767 ++vnc_implicit_withdraw;
40381db7
DS
3768 vnc_import_bgp_del_route(bgp, p, pi);
3769 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3770 }
3771 }
65efcfce 3772#endif
128ea8ab 3773
d62a17ae 3774 /* Special handling for EVPN update of an existing route. If the
3775 * extended community attribute has changed, we need to
3776 * un-import
3777 * the route using its existing extended community. It will be
3778 * subsequently processed for import with the new extended
3779 * community.
3780 */
6f8c9c11
PR
3781 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3782 && !same_attr) {
40381db7 3783 if ((pi->attr->flag
d62a17ae 3784 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3785 && (attr_new->flag
3786 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3787 int cmp;
3788
40381db7 3789 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3790 attr_new->ecommunity);
3791 if (!cmp) {
3792 if (bgp_debug_update(peer, p, NULL, 1))
3793 zlog_debug(
3794 "Change in EXT-COMM, existing %s new %s",
3795 ecommunity_str(
40381db7 3796 pi->attr->ecommunity),
d62a17ae 3797 ecommunity_str(
3798 attr_new->ecommunity));
6f8c9c11
PR
3799 if (safi == SAFI_EVPN)
3800 bgp_evpn_unimport_route(
3801 bgp, afi, safi, p, pi);
3802 else /* SAFI_MPLS_VPN */
3803 vpn_leak_to_vrf_withdraw(bgp,
3804 pi);
d62a17ae 3805 }
3806 }
3807 }
718e3744 3808
d62a17ae 3809 /* Update to new attribute. */
40381db7
DS
3810 bgp_attr_unintern(&pi->attr);
3811 pi->attr = attr_new;
d62a17ae 3812
3813 /* Update MPLS label */
3814 if (has_valid_label) {
40381db7 3815 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3816 if (extra->label != label) {
3817 memcpy(&extra->label, label,
dbd587da 3818 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3819 extra->num_labels = num_labels;
3820 }
b57ba6d2
MK
3821 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3822 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3823 }
718e3744 3824
e496b420
HS
3825 /* Update SRv6 SID */
3826 if (attr->srv6_l3vpn) {
3827 extra = bgp_path_info_extra_get(pi);
3828 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3829 sid_copy(&extra->sid[0],
3830 &attr->srv6_l3vpn->sid);
3831 extra->num_sids = 1;
3832 }
3833 } else if (attr->srv6_vpn) {
3834 extra = bgp_path_info_extra_get(pi);
3835 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3836 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3837 extra->num_sids = 1;
3838 }
3839 }
3840
49e5a4a0 3841#ifdef ENABLE_BGP_VNC
d62a17ae 3842 if ((afi == AFI_IP || afi == AFI_IP6)
3843 && (safi == SAFI_UNICAST)) {
3844 if (vnc_implicit_withdraw) {
3845 /*
3846 * Add back the route with its new attributes
3847 * (e.g., nexthop).
3848 * The route is still selected, until the route
3849 * selection
3850 * queued by bgp_process actually runs. We have
3851 * to make this
3852 * update to the VNC side immediately to avoid
3853 * racing against
3854 * configuration changes (e.g., route-map
3855 * changes) which
3856 * trigger re-importation of the entire RIB.
3857 */
40381db7
DS
3858 vnc_import_bgp_add_route(bgp, p, pi);
3859 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3860 }
3861 }
65efcfce
LB
3862#endif
3863
d62a17ae 3864 /* Update bgp route dampening information. */
3865 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3866 && peer->sort == BGP_PEER_EBGP) {
3867 /* Now we do normal update dampening. */
9bcb3eef 3868 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 3869 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 3870 bgp_dest_unlock_node(dest);
d62a17ae 3871 return 0;
3872 }
3873 }
128ea8ab 3874
d62a17ae 3875 /* Nexthop reachability check - for unicast and
3876 * labeled-unicast.. */
7c312383
AD
3877 if (((afi == AFI_IP || afi == AFI_IP6)
3878 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
3879 || (safi == SAFI_EVPN &&
3880 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
3881 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
3882 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 3883 && !CHECK_FLAG(peer->flags,
3884 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
3885 && !CHECK_FLAG(bgp->flags,
3886 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 3887 connected = 1;
3888 else
3889 connected = 0;
3890
960035b2
PZ
3891 struct bgp *bgp_nexthop = bgp;
3892
40381db7
DS
3893 if (pi->extra && pi->extra->bgp_orig)
3894 bgp_nexthop = pi->extra->bgp_orig;
960035b2 3895
7c312383
AD
3896 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
3897
3898 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
3899 pi, NULL, connected)
a4d82a8a 3900 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
3901 bgp_path_info_set_flag(dest, pi,
3902 BGP_PATH_VALID);
d62a17ae 3903 else {
3904 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
3905 zlog_debug("%s(%pI4): NH unresolved",
3906 __func__,
3907 (in_addr_t *)&attr_new->nexthop);
d62a17ae 3908 }
9bcb3eef 3909 bgp_path_info_unset_flag(dest, pi,
18ee8310 3910 BGP_PATH_VALID);
d62a17ae 3911 }
3912 } else
9bcb3eef 3913 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 3914
49e5a4a0 3915#ifdef ENABLE_BGP_VNC
d62a17ae 3916 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3917 struct bgp_dest *pdest = NULL;
d62a17ae 3918 struct bgp_table *table = NULL;
3919
9bcb3eef
DS
3920 pdest = bgp_node_get(bgp->rib[afi][safi],
3921 (struct prefix *)prd);
3922 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3923 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3924
3925 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 3926 bgp, prd, table, p, pi);
d62a17ae 3927 }
9bcb3eef 3928 bgp_dest_unlock_node(pdest);
d62a17ae 3929 }
3930#endif
718e3744 3931
d62a17ae 3932 /* If this is an EVPN route and some attribute has changed,
3933 * process
3934 * route for import. If the extended community has changed, we
3935 * would
3936 * have done the un-import earlier and the import would result
3937 * in the
3938 * route getting injected into appropriate L2 VNIs. If it is
3939 * just
3940 * some other attribute change, the import will result in
3941 * updating
3942 * the attributes for the route in the VNI(s).
3943 */
7c312383
AD
3944 if (safi == SAFI_EVPN && !same_attr &&
3945 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 3946 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 3947
3948 /* Process change. */
40381db7 3949 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 3950
9bcb3eef
DS
3951 bgp_process(bgp, dest, afi, safi);
3952 bgp_dest_unlock_node(dest);
558d1fec 3953
ddb5b488
PZ
3954 if (SAFI_UNICAST == safi
3955 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
3956 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3957
40381db7 3958 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
3959 }
3960 if ((SAFI_MPLS_VPN == safi)
3961 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3962
40381db7 3963 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
3964 }
3965
49e5a4a0 3966#ifdef ENABLE_BGP_VNC
d62a17ae 3967 if (SAFI_MPLS_VPN == safi) {
3968 mpls_label_t label_decoded = decode_label(label);
28070ee3 3969
d62a17ae 3970 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3971 type, sub_type, &label_decoded);
3972 }
3973 if (SAFI_ENCAP == safi) {
3974 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
3975 type, sub_type, NULL);
3976 }
28070ee3
PZ
3977#endif
3978
d62a17ae 3979 return 0;
3980 } // End of implicit withdraw
718e3744 3981
d62a17ae 3982 /* Received Logging. */
3983 if (bgp_debug_update(peer, p, NULL, 1)) {
3984 if (!peer->rcvd_attr_printed) {
3985 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
3986 peer->rcvd_attr_str);
3987 peer->rcvd_attr_printed = 1;
3988 }
718e3744 3989
a4d82a8a 3990 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 3991 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3992 sizeof(pfx_buf));
3993 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3994 }
718e3744 3995
d62a17ae 3996 /* Make new BGP info. */
9bcb3eef 3997 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 3998
d62a17ae 3999 /* Update MPLS label */
4000 if (has_valid_label) {
18ee8310 4001 extra = bgp_path_info_extra_get(new);
8ba71050 4002 if (extra->label != label) {
dbd587da
QY
4003 memcpy(&extra->label, label,
4004 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4005 extra->num_labels = num_labels;
4006 }
b57ba6d2
MK
4007 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4008 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4009 }
718e3744 4010
e496b420
HS
4011 /* Update SRv6 SID */
4012 if (safi == SAFI_MPLS_VPN) {
4013 extra = bgp_path_info_extra_get(new);
4014 if (attr->srv6_l3vpn) {
4015 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4016 extra->num_sids = 1;
4017 } else if (attr->srv6_vpn) {
4018 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4019 extra->num_sids = 1;
4020 }
4021 }
4022
d62a17ae 4023 /* Update Overlay Index */
4024 if (afi == AFI_L2VPN) {
4025 overlay_index_update(new->attr,
d62a17ae 4026 evpn == NULL ? NULL : &evpn->gw_ip);
4027 }
4028 /* Nexthop reachability check. */
7c312383
AD
4029 if (((afi == AFI_IP || afi == AFI_IP6)
4030 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4031 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4032 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4033 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4034 && !CHECK_FLAG(peer->flags,
4035 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4036 && !CHECK_FLAG(bgp->flags,
4037 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4038 connected = 1;
4039 else
4040 connected = 0;
4041
7c312383
AD
4042 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4043
4044 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL,
4045 connected)
a4d82a8a 4046 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4047 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4048 else {
4049 if (BGP_DEBUG(nht, NHT)) {
4050 char buf1[INET6_ADDRSTRLEN];
4051 inet_ntop(AF_INET,
4052 (const void *)&attr_new->nexthop,
4053 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4054 zlog_debug("%s(%s): NH unresolved", __func__,
4055 buf1);
d62a17ae 4056 }
9bcb3eef 4057 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4058 }
4059 } else
9bcb3eef 4060 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4061
d62a17ae 4062 /* Addpath ID */
4063 new->addpath_rx_id = addpath_id;
4064
4065 /* Increment prefix */
4066 bgp_aggregate_increment(bgp, p, new, afi, safi);
4067
4068 /* Register new BGP information. */
9bcb3eef 4069 bgp_path_info_add(dest, new);
d62a17ae 4070
4071 /* route_node_get lock */
9bcb3eef 4072 bgp_dest_unlock_node(dest);
558d1fec 4073
49e5a4a0 4074#ifdef ENABLE_BGP_VNC
d62a17ae 4075 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4076 struct bgp_dest *pdest = NULL;
d62a17ae 4077 struct bgp_table *table = NULL;
4078
9bcb3eef
DS
4079 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4080 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4081 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4082
4083 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4084 bgp, prd, table, p, new);
4085 }
9bcb3eef 4086 bgp_dest_unlock_node(pdest);
d62a17ae 4087 }
65efcfce
LB
4088#endif
4089
d62a17ae 4090 /* If this is an EVPN route, process for import. */
7c312383 4091 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4092 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4093
9bcb3eef 4094 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4095
d62a17ae 4096 /* Process change. */
9bcb3eef 4097 bgp_process(bgp, dest, afi, safi);
718e3744 4098
ddb5b488
PZ
4099 if (SAFI_UNICAST == safi
4100 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4101 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4102 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4103 }
4104 if ((SAFI_MPLS_VPN == safi)
4105 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4106
4107 vpn_leak_to_vrf_update(bgp, new);
4108 }
49e5a4a0 4109#ifdef ENABLE_BGP_VNC
d62a17ae 4110 if (SAFI_MPLS_VPN == safi) {
4111 mpls_label_t label_decoded = decode_label(label);
28070ee3 4112
d62a17ae 4113 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4114 sub_type, &label_decoded);
4115 }
4116 if (SAFI_ENCAP == safi) {
4117 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4118 sub_type, NULL);
4119 }
28070ee3
PZ
4120#endif
4121
d62a17ae 4122 return 0;
718e3744 4123
d62a17ae 4124/* This BGP update is filtered. Log the reason then update BGP
4125 entry. */
4126filtered:
9bcb3eef 4127 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4128
d62a17ae 4129 if (bgp_debug_update(peer, p, NULL, 1)) {
4130 if (!peer->rcvd_attr_printed) {
4131 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4132 peer->rcvd_attr_str);
4133 peer->rcvd_attr_printed = 1;
4134 }
718e3744 4135
a4d82a8a 4136 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4137 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4138 sizeof(pfx_buf));
4139 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4140 peer->host, pfx_buf, reason);
4141 }
128ea8ab 4142
40381db7 4143 if (pi) {
d62a17ae 4144 /* If this is an EVPN route, un-import it as it is now filtered.
4145 */
4146 if (safi == SAFI_EVPN)
40381db7 4147 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4148
ddb5b488
PZ
4149 if (SAFI_UNICAST == safi
4150 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4151 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4152
40381db7 4153 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4154 }
4155 if ((SAFI_MPLS_VPN == safi)
4156 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4157
40381db7 4158 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4159 }
4160
9bcb3eef 4161 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4162 }
4163
9bcb3eef 4164 bgp_dest_unlock_node(dest);
558d1fec 4165
49e5a4a0 4166#ifdef ENABLE_BGP_VNC
d62a17ae 4167 /*
4168 * Filtered update is treated as an implicit withdrawal (see
4169 * bgp_rib_remove()
4170 * a few lines above)
4171 */
4172 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4173 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4174 0);
4175 }
97736e32
PZ
4176#endif
4177
d62a17ae 4178 return 0;
718e3744 4179}
4180
26a3ffd6 4181int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4182 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4183 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4184 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4185{
d62a17ae 4186 struct bgp *bgp;
4187 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4188 struct bgp_dest *dest;
40381db7 4189 struct bgp_path_info *pi;
718e3744 4190
49e5a4a0 4191#ifdef ENABLE_BGP_VNC
d62a17ae 4192 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4193 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4194 0);
4195 }
28070ee3
PZ
4196#endif
4197
d62a17ae 4198 bgp = peer->bgp;
4199
4200 /* Lookup node. */
9bcb3eef 4201 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4202
4203 /* If peer is soft reconfiguration enabled. Record input packet for
4204 * further calculation.
4205 *
4206 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4207 * routes that are filtered. This tanks out Quagga RS pretty badly due
4208 * to
4209 * the iteration over all RS clients.
4210 * Since we need to remove the entry from adj_in anyway, do that first
4211 * and
4212 * if there was no entry, we don't need to do anything more.
4213 */
4214 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4215 && peer != bgp->peer_self)
9bcb3eef 4216 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4217 peer->stat_pfx_dup_withdraw++;
4218
d62a17ae 4219 if (bgp_debug_update(peer, p, NULL, 1)) {
4220 bgp_debug_rdpfxpath2str(
a4d82a8a 4221 afi, safi, prd, p, label, num_labels,
d62a17ae 4222 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4223 sizeof(pfx_buf));
4224 zlog_debug(
4225 "%s withdrawing route %s not in adj-in",
4226 peer->host, pfx_buf);
4227 }
9bcb3eef 4228 bgp_dest_unlock_node(dest);
d62a17ae 4229 return 0;
4230 }
cd808e74 4231
d62a17ae 4232 /* Lookup withdrawn route. */
9bcb3eef 4233 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4234 if (pi->peer == peer && pi->type == type
4235 && pi->sub_type == sub_type
4236 && pi->addpath_rx_id == addpath_id)
d62a17ae 4237 break;
4238
4239 /* Logging. */
4240 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4241 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4242 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4243 sizeof(pfx_buf));
4244 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4245 pfx_buf);
4246 }
718e3744 4247
d62a17ae 4248 /* Withdraw specified route from routing table. */
40381db7 4249 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4250 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4251 if (SAFI_UNICAST == safi
4252 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4253 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4254 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4255 }
4256 if ((SAFI_MPLS_VPN == safi)
4257 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4258
40381db7 4259 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4260 }
4261 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4262 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4263 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4264 sizeof(pfx_buf));
4265 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4266 }
718e3744 4267
d62a17ae 4268 /* Unlock bgp_node_get() lock. */
9bcb3eef 4269 bgp_dest_unlock_node(dest);
d62a17ae 4270
4271 return 0;
718e3744 4272}
6b0655a2 4273
d62a17ae 4274void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4275 int withdraw)
718e3744 4276{
d62a17ae 4277 struct update_subgroup *subgrp;
4278 subgrp = peer_subgroup(peer, afi, safi);
4279 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4280}
6182d65b 4281
718e3744 4282
3f9c7369
DS
4283/*
4284 * bgp_stop_announce_route_timer
4285 */
d62a17ae 4286void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4287{
d62a17ae 4288 if (!paf->t_announce_route)
4289 return;
4290
4291 THREAD_TIMER_OFF(paf->t_announce_route);
718e3744 4292}
6b0655a2 4293
3f9c7369
DS
4294/*
4295 * bgp_announce_route_timer_expired
4296 *
4297 * Callback that is invoked when the route announcement timer for a
4298 * peer_af expires.
4299 */
d62a17ae 4300static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4301{
d62a17ae 4302 struct peer_af *paf;
4303 struct peer *peer;
558d1fec 4304
d62a17ae 4305 paf = THREAD_ARG(t);
4306 peer = paf->peer;
718e3744 4307
d62a17ae 4308 if (peer->status != Established)
4309 return 0;
3f9c7369 4310
d62a17ae 4311 if (!peer->afc_nego[paf->afi][paf->safi])
4312 return 0;
3f9c7369 4313
d62a17ae 4314 peer_af_announce_route(paf, 1);
4315 return 0;
718e3744 4316}
4317
3f9c7369
DS
4318/*
4319 * bgp_announce_route
4320 *
4321 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4322 */
d62a17ae 4323void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4324{
4325 struct peer_af *paf;
4326 struct update_subgroup *subgrp;
4327
4328 paf = peer_af_find(peer, afi, safi);
4329 if (!paf)
4330 return;
4331 subgrp = PAF_SUBGRP(paf);
4332
4333 /*
4334 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4335 * or a refresh has already been triggered.
4336 */
4337 if (!subgrp || paf->t_announce_route)
4338 return;
4339
4340 /*
4341 * Start a timer to stagger/delay the announce. This serves
4342 * two purposes - announcement can potentially be combined for
4343 * multiple peers and the announcement doesn't happen in the
4344 * vty context.
4345 */
4346 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4347 (subgrp->peer_count == 1)
4348 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4349 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4350 &paf->t_announce_route);
3f9c7369
DS
4351}
4352
4353/*
4354 * Announce routes from all AF tables to a peer.
4355 *
4356 * This should ONLY be called when there is a need to refresh the
4357 * routes to the peer based on a policy change for this peer alone
4358 * or a route refresh request received from the peer.
4359 * The operation will result in splitting the peer from its existing
4360 * subgroups and putting it in new subgroups.
4361 */
d62a17ae 4362void bgp_announce_route_all(struct peer *peer)
718e3744 4363{
d62a17ae 4364 afi_t afi;
4365 safi_t safi;
4366
05c7a1cc
QY
4367 FOREACH_AFI_SAFI (afi, safi)
4368 bgp_announce_route(peer, afi, safi);
718e3744 4369}
6b0655a2 4370
d62a17ae 4371static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4372 struct bgp_table *table,
4373 struct prefix_rd *prd)
718e3744 4374{
d62a17ae 4375 int ret;
9bcb3eef 4376 struct bgp_dest *dest;
d62a17ae 4377 struct bgp_adj_in *ain;
718e3744 4378
d62a17ae 4379 if (!table)
4380 table = peer->bgp->rib[afi][safi];
718e3744 4381
9bcb3eef
DS
4382 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4383 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4384 if (ain->peer != peer)
4385 continue;
8692c506 4386
d7d15889 4387 struct bgp_path_info *pi;
d7c0a89a 4388 uint32_t num_labels = 0;
b57ba6d2 4389 mpls_label_t *label_pnt = NULL;
8cb687c2 4390 struct bgp_route_evpn evpn;
b57ba6d2 4391
9bcb3eef 4392 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4393 pi = pi->next)
4394 if (pi->peer == peer)
4395 break;
4396
40381db7
DS
4397 if (pi && pi->extra)
4398 num_labels = pi->extra->num_labels;
b57ba6d2 4399 if (num_labels)
40381db7 4400 label_pnt = &pi->extra->label[0];
8cb687c2
DS
4401 if (pi)
4402 memcpy(&evpn, &pi->attr->evpn_overlay,
4403 sizeof(evpn));
4404 else
4405 memset(&evpn, 0, sizeof(evpn));
8692c506 4406
9bcb3eef
DS
4407 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4408 ain->addpath_rx_id, ain->attr, afi,
4409 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4410 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4411 num_labels, 1, &evpn);
ea47320b
DL
4412
4413 if (ret < 0) {
9bcb3eef 4414 bgp_dest_unlock_node(dest);
ea47320b 4415 return;
d62a17ae 4416 }
4417 }
718e3744 4418}
4419
d62a17ae 4420void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4421{
9bcb3eef 4422 struct bgp_dest *dest;
d62a17ae 4423 struct bgp_table *table;
718e3744 4424
d62a17ae 4425 if (peer->status != Established)
4426 return;
718e3744 4427
d62a17ae 4428 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4429 && (safi != SAFI_EVPN))
4430 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4431 else
9bcb3eef
DS
4432 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4433 dest = bgp_route_next(dest)) {
4434 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4435
b54892e0
DS
4436 if (table == NULL)
4437 continue;
8692c506 4438
9bcb3eef 4439 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4440 struct prefix_rd prd;
4441
4442 prd.family = AF_UNSPEC;
4443 prd.prefixlen = 64;
4444 memcpy(&prd.val, p->u.val, 8);
4445
4446 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4447 }
718e3744 4448}
6b0655a2 4449
228da428 4450
d62a17ae 4451struct bgp_clear_node_queue {
9bcb3eef 4452 struct bgp_dest *dest;
228da428
CC
4453};
4454
d62a17ae 4455static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4456{
d62a17ae 4457 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4458 struct bgp_dest *dest = cnq->dest;
d62a17ae 4459 struct peer *peer = wq->spec.data;
40381db7 4460 struct bgp_path_info *pi;
3103e8d2 4461 struct bgp *bgp;
9bcb3eef
DS
4462 afi_t afi = bgp_dest_table(dest)->afi;
4463 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4464
9bcb3eef 4465 assert(dest && peer);
3103e8d2 4466 bgp = peer->bgp;
d62a17ae 4467
4468 /* It is possible that we have multiple paths for a prefix from a peer
4469 * if that peer is using AddPath.
4470 */
9bcb3eef 4471 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4472 if (pi->peer != peer)
ea47320b
DL
4473 continue;
4474
4475 /* graceful restart STALE flag set. */
4476 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4477 && peer->nsf[afi][safi]
40381db7
DS
4478 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4479 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4480 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4481 else {
4482 /* If this is an EVPN route, process for
4483 * un-import. */
4484 if (safi == SAFI_EVPN)
9bcb3eef
DS
4485 bgp_evpn_unimport_route(
4486 bgp, afi, safi,
4487 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4488 /* Handle withdraw for VRF route-leaking and L3VPN */
4489 if (SAFI_UNICAST == safi
4490 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4491 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4492 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4493 bgp, pi);
960035b2 4494 }
3103e8d2 4495 if (SAFI_MPLS_VPN == safi &&
960035b2 4496 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4497 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4498 }
3103e8d2 4499
9bcb3eef 4500 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4501 }
ea47320b 4502 }
d62a17ae 4503 return WQ_SUCCESS;
200df115 4504}
4505
d62a17ae 4506static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4507{
d62a17ae 4508 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4509 struct bgp_dest *dest = cnq->dest;
4510 struct bgp_table *table = bgp_dest_table(dest);
228da428 4511
9bcb3eef 4512 bgp_dest_unlock_node(dest);
d62a17ae 4513 bgp_table_unlock(table);
4514 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4515}
4516
d62a17ae 4517static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4518{
d62a17ae 4519 struct peer *peer = wq->spec.data;
64e580a7 4520
d62a17ae 4521 /* Tickle FSM to start moving again */
4522 BGP_EVENT_ADD(peer, Clearing_Completed);
4523
4524 peer_unlock(peer); /* bgp_clear_route */
200df115 4525}
718e3744 4526
d62a17ae 4527static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4528{
d62a17ae 4529 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4530
4531 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4532#undef CLEAR_QUEUE_NAME_LEN
4533
0ce1ca80 4534 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4535 peer->clear_node_queue->spec.hold = 10;
4536 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4537 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4538 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4539 peer->clear_node_queue->spec.max_retries = 0;
4540
4541 /* we only 'lock' this peer reference when the queue is actually active
4542 */
4543 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4544}
4545
d62a17ae 4546static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4547 struct bgp_table *table)
65ca75e0 4548{
9bcb3eef 4549 struct bgp_dest *dest;
d62a17ae 4550 int force = bm->process_main_queue ? 0 : 1;
6cf159b9 4551
d62a17ae 4552 if (!table)
4553 table = peer->bgp->rib[afi][safi];
dc83d712 4554
d62a17ae 4555 /* If still no table => afi/safi isn't configured at all or smth. */
4556 if (!table)
4557 return;
dc83d712 4558
9bcb3eef 4559 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4560 struct bgp_path_info *pi, *next;
d62a17ae 4561 struct bgp_adj_in *ain;
4562 struct bgp_adj_in *ain_next;
4563
4564 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4565 * queued for every clearing peer, regardless of whether it is
4566 * relevant to the peer at hand.
4567 *
4568 * Overview: There are 3 different indices which need to be
4569 * scrubbed, potentially, when a peer is removed:
4570 *
4571 * 1 peer's routes visible via the RIB (ie accepted routes)
4572 * 2 peer's routes visible by the (optional) peer's adj-in index
4573 * 3 other routes visible by the peer's adj-out index
4574 *
4575 * 3 there is no hurry in scrubbing, once the struct peer is
4576 * removed from bgp->peer, we could just GC such deleted peer's
4577 * adj-outs at our leisure.
4578 *
4579 * 1 and 2 must be 'scrubbed' in some way, at least made
4580 * invisible via RIB index before peer session is allowed to be
4581 * brought back up. So one needs to know when such a 'search' is
4582 * complete.
4583 *
4584 * Ideally:
4585 *
4586 * - there'd be a single global queue or a single RIB walker
4587 * - rather than tracking which route_nodes still need to be
4588 * examined on a peer basis, we'd track which peers still
4589 * aren't cleared
4590 *
4591 * Given that our per-peer prefix-counts now should be reliable,
4592 * this may actually be achievable. It doesn't seem to be a huge
4593 * problem at this time,
4594 *
4595 * It is possible that we have multiple paths for a prefix from
4596 * a peer
4597 * if that peer is using AddPath.
4598 */
9bcb3eef 4599 ain = dest->adj_in;
d62a17ae 4600 while (ain) {
4601 ain_next = ain->next;
4602
4603 if (ain->peer == peer) {
9bcb3eef
DS
4604 bgp_adj_in_remove(dest, ain);
4605 bgp_dest_unlock_node(dest);
d62a17ae 4606 }
4607
4608 ain = ain_next;
4609 }
4610
9bcb3eef 4611 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4612 next = pi->next;
4613 if (pi->peer != peer)
d62a17ae 4614 continue;
4615
4616 if (force)
9bcb3eef 4617 bgp_path_info_reap(dest, pi);
d62a17ae 4618 else {
4619 struct bgp_clear_node_queue *cnq;
4620
4621 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4622 bgp_table_lock(bgp_dest_table(dest));
4623 bgp_dest_lock_node(dest);
d62a17ae 4624 cnq = XCALLOC(
4625 MTYPE_BGP_CLEAR_NODE_QUEUE,
4626 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4627 cnq->dest = dest;
d62a17ae 4628 work_queue_add(peer->clear_node_queue, cnq);
4629 break;
4630 }
4631 }
4632 }
4633 return;
4634}
4635
4636void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4637{
9bcb3eef 4638 struct bgp_dest *dest;
d62a17ae 4639 struct bgp_table *table;
4640
4641 if (peer->clear_node_queue == NULL)
4642 bgp_clear_node_queue_init(peer);
4643
4644 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4645 * Idle until it receives a Clearing_Completed event. This protects
4646 * against peers which flap faster than we can we clear, which could
4647 * lead to:
4648 *
4649 * a) race with routes from the new session being installed before
4650 * clear_route_node visits the node (to delete the route of that
4651 * peer)
4652 * b) resource exhaustion, clear_route_node likely leads to an entry
4653 * on the process_main queue. Fast-flapping could cause that queue
4654 * to grow and grow.
4655 */
4656
4657 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4658 * the unlock will happen upon work-queue completion; other wise, the
4659 * unlock happens at the end of this function.
4660 */
4661 if (!peer->clear_node_queue->thread)
4662 peer_lock(peer);
4663
4664 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4665 bgp_clear_route_table(peer, afi, safi, NULL);
4666 else
9bcb3eef
DS
4667 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4668 dest = bgp_route_next(dest)) {
4669 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4670 if (!table)
4671 continue;
4672
4673 bgp_clear_route_table(peer, afi, safi, table);
4674 }
d62a17ae 4675
4676 /* unlock if no nodes got added to the clear-node-queue. */
4677 if (!peer->clear_node_queue->thread)
4678 peer_unlock(peer);
718e3744 4679}
d62a17ae 4680
4681void bgp_clear_route_all(struct peer *peer)
718e3744 4682{
d62a17ae 4683 afi_t afi;
4684 safi_t safi;
718e3744 4685
05c7a1cc
QY
4686 FOREACH_AFI_SAFI (afi, safi)
4687 bgp_clear_route(peer, afi, safi);
65efcfce 4688
49e5a4a0 4689#ifdef ENABLE_BGP_VNC
d62a17ae 4690 rfapiProcessPeerDown(peer);
65efcfce 4691#endif
718e3744 4692}
4693
d62a17ae 4694void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4695{
d62a17ae 4696 struct bgp_table *table;
9bcb3eef 4697 struct bgp_dest *dest;
d62a17ae 4698 struct bgp_adj_in *ain;
4699 struct bgp_adj_in *ain_next;
718e3744 4700
d62a17ae 4701 table = peer->bgp->rib[afi][safi];
718e3744 4702
d62a17ae 4703 /* It is possible that we have multiple paths for a prefix from a peer
4704 * if that peer is using AddPath.
4705 */
9bcb3eef
DS
4706 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4707 ain = dest->adj_in;
43143c8f 4708
d62a17ae 4709 while (ain) {
4710 ain_next = ain->next;
43143c8f 4711
d62a17ae 4712 if (ain->peer == peer) {
9bcb3eef
DS
4713 bgp_adj_in_remove(dest, ain);
4714 bgp_dest_unlock_node(dest);
d62a17ae 4715 }
43143c8f 4716
d62a17ae 4717 ain = ain_next;
4718 }
4719 }
718e3744 4720}
93406d87 4721
d62a17ae 4722void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4723{
9bcb3eef 4724 struct bgp_dest *dest;
40381db7 4725 struct bgp_path_info *pi;
d62a17ae 4726 struct bgp_table *table;
4727
4728 if (safi == SAFI_MPLS_VPN) {
9bcb3eef
DS
4729 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4730 dest = bgp_route_next(dest)) {
4731 struct bgp_dest *rm;
d62a17ae 4732
4733 /* look for neighbor in tables */
9bcb3eef 4734 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4735 if (!table)
ea47320b
DL
4736 continue;
4737
4738 for (rm = bgp_table_top(table); rm;
4739 rm = bgp_route_next(rm))
9bcb3eef 4740 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4741 pi = pi->next) {
40381db7 4742 if (pi->peer != peer)
ea47320b 4743 continue;
40381db7 4744 if (!CHECK_FLAG(pi->flags,
1defdda8 4745 BGP_PATH_STALE))
ea47320b
DL
4746 break;
4747
40381db7 4748 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4749 break;
4750 }
d62a17ae 4751 }
4752 } else {
9bcb3eef
DS
4753 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4754 dest = bgp_route_next(dest))
4755 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4756 pi = pi->next) {
40381db7 4757 if (pi->peer != peer)
ea47320b 4758 continue;
40381db7 4759 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4760 break;
9bcb3eef 4761 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4762 break;
4763 }
d62a17ae 4764 }
93406d87 4765}
6b0655a2 4766
3dc339cd 4767bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4768{
e0df4c04 4769 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4770 return true;
e0df4c04 4771
9dac9fc8
DA
4772 if (peer->sort == BGP_PEER_EBGP
4773 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
4774 || FILTER_LIST_OUT_NAME(filter)
4775 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
4776 return true;
4777 return false;
9dac9fc8
DA
4778}
4779
3dc339cd 4780bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 4781{
e0df4c04 4782 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 4783 return true;
e0df4c04 4784
9dac9fc8
DA
4785 if (peer->sort == BGP_PEER_EBGP
4786 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
4787 || FILTER_LIST_IN_NAME(filter)
4788 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
4789 return true;
4790 return false;
9dac9fc8
DA
4791}
4792
568e10ca 4793static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
4794 safi_t safi)
bb86c601 4795{
9bcb3eef 4796 struct bgp_dest *dest;
40381db7 4797 struct bgp_path_info *pi;
4b7e6066 4798 struct bgp_path_info *next;
bb86c601 4799
9bcb3eef
DS
4800 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4801 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
4802 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 4803
40381db7 4804 next = pi->next;
1b7bb747
CS
4805
4806 /* Unimport EVPN routes from VRFs */
4807 if (safi == SAFI_EVPN)
4808 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 4809 SAFI_EVPN, p, pi);
1b7bb747 4810
40381db7
DS
4811 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
4812 && pi->type == ZEBRA_ROUTE_BGP
4813 && (pi->sub_type == BGP_ROUTE_NORMAL
4814 || pi->sub_type == BGP_ROUTE_AGGREGATE
4815 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 4816
d62a17ae 4817 if (bgp_fibupd_safi(safi))
b54892e0 4818 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 4819 }
9514b37d 4820
9bcb3eef 4821 bgp_path_info_reap(dest, pi);
d62a17ae 4822 }
bb86c601
LB
4823}
4824
718e3744 4825/* Delete all kernel routes. */
d62a17ae 4826void bgp_cleanup_routes(struct bgp *bgp)
4827{
4828 afi_t afi;
9bcb3eef 4829 struct bgp_dest *dest;
67009e22 4830 struct bgp_table *table;
d62a17ae 4831
4832 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
4833 if (afi == AFI_L2VPN)
4834 continue;
568e10ca 4835 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
4836 SAFI_UNICAST);
d62a17ae 4837 /*
4838 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
4839 */
4840 if (afi != AFI_L2VPN) {
4841 safi_t safi;
4842 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
4843 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4844 dest = bgp_route_next(dest)) {
4845 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4846 if (table != NULL) {
4847 bgp_cleanup_table(bgp, table, safi);
4848 bgp_table_finish(&table);
9bcb3eef
DS
4849 bgp_dest_set_bgp_table_info(dest, NULL);
4850 bgp_dest_unlock_node(dest);
d62a17ae 4851 }
4852 }
4853 safi = SAFI_ENCAP;
9bcb3eef
DS
4854 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
4855 dest = bgp_route_next(dest)) {
4856 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4857 if (table != NULL) {
4858 bgp_cleanup_table(bgp, table, safi);
4859 bgp_table_finish(&table);
9bcb3eef
DS
4860 bgp_dest_set_bgp_table_info(dest, NULL);
4861 bgp_dest_unlock_node(dest);
d62a17ae 4862 }
4863 }
4864 }
4865 }
9bcb3eef
DS
4866 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
4867 dest = bgp_route_next(dest)) {
4868 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4869 if (table != NULL) {
4870 bgp_cleanup_table(bgp, table, SAFI_EVPN);
4871 bgp_table_finish(&table);
9bcb3eef
DS
4872 bgp_dest_set_bgp_table_info(dest, NULL);
4873 bgp_dest_unlock_node(dest);
d62a17ae 4874 }
bb86c601 4875 }
718e3744 4876}
4877
d62a17ae 4878void bgp_reset(void)
718e3744 4879{
d62a17ae 4880 vty_reset();
4881 bgp_zclient_reset();
4882 access_list_reset();
4883 prefix_list_reset();
718e3744 4884}
6b0655a2 4885
d62a17ae 4886static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 4887{
d62a17ae 4888 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
4889 && CHECK_FLAG(peer->af_cap[afi][safi],
4890 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
4891}
4892
718e3744 4893/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
4894 value. */
d62a17ae 4895int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
4896 struct bgp_nlri *packet)
4897{
d7c0a89a
QY
4898 uint8_t *pnt;
4899 uint8_t *lim;
d62a17ae 4900 struct prefix p;
4901 int psize;
4902 int ret;
4903 afi_t afi;
4904 safi_t safi;
4905 int addpath_encoded;
d7c0a89a 4906 uint32_t addpath_id;
d62a17ae 4907
d62a17ae 4908 pnt = packet->nlri;
4909 lim = pnt + packet->length;
4910 afi = packet->afi;
4911 safi = packet->safi;
4912 addpath_id = 0;
4913 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
4914
4915 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
4916 syntactic validity. If the field is syntactically incorrect,
4917 then the Error Subcode is set to Invalid Network Field. */
4918 for (; pnt < lim; pnt += psize) {
4919 /* Clear prefix structure. */
4920 memset(&p, 0, sizeof(struct prefix));
4921
4922 if (addpath_encoded) {
4923
4924 /* When packet overflow occurs return immediately. */
761ed665 4925 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 4926 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4927
a3a850a1 4928 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 4929 addpath_id = ntohl(addpath_id);
d62a17ae 4930 pnt += BGP_ADDPATH_ID_LEN;
4931 }
718e3744 4932
d62a17ae 4933 /* Fetch prefix length. */
4934 p.prefixlen = *pnt++;
4935 /* afi/safi validity already verified by caller,
4936 * bgp_update_receive */
4937 p.family = afi2family(afi);
4938
4939 /* Prefix length check. */
4940 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 4941 flog_err(
e50f7cfd 4942 EC_BGP_UPDATE_RCV,
14454c9f 4943 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 4944 peer->host, p.prefixlen, packet->afi);
513386b5 4945 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 4946 }
6b0655a2 4947
d62a17ae 4948 /* Packet size overflow check. */
4949 psize = PSIZE(p.prefixlen);
4950
4951 /* When packet overflow occur return immediately. */
4952 if (pnt + psize > lim) {
af4c2728 4953 flog_err(
e50f7cfd 4954 EC_BGP_UPDATE_RCV,
d62a17ae 4955 "%s [Error] Update packet error (prefix length %d overflows packet)",
4956 peer->host, p.prefixlen);
513386b5 4957 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 4958 }
4959
4960 /* Defensive coding, double-check the psize fits in a struct
4961 * prefix */
4962 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 4963 flog_err(
e50f7cfd 4964 EC_BGP_UPDATE_RCV,
d62a17ae 4965 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
4966 peer->host, p.prefixlen, sizeof(p.u));
513386b5 4967 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 4968 }
4969
4970 /* Fetch prefix from NLRI packet. */
a85297a7 4971 memcpy(p.u.val, pnt, psize);
d62a17ae 4972
4973 /* Check address. */
4974 if (afi == AFI_IP && safi == SAFI_UNICAST) {
4975 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
4976 /* From RFC4271 Section 6.3:
4977 *
4978 * If a prefix in the NLRI field is semantically
4979 * incorrect
4980 * (e.g., an unexpected multicast IP address),
4981 * an error SHOULD
4982 * be logged locally, and the prefix SHOULD be
4983 * ignored.
a4d82a8a 4984 */
af4c2728 4985 flog_err(
e50f7cfd 4986 EC_BGP_UPDATE_RCV,
d62a17ae 4987 "%s: IPv4 unicast NLRI is multicast address %s, ignoring",
4988 peer->host, inet_ntoa(p.u.prefix4));
4989 continue;
4990 }
4991 }
4992
4993 /* Check address. */
4994 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
4995 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
4996 char buf[BUFSIZ];
4997
af4c2728 4998 flog_err(
e50f7cfd 4999 EC_BGP_UPDATE_RCV,
d62a17ae 5000 "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
5001 peer->host,
5002 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5003 BUFSIZ));
5004
5005 continue;
5006 }
5007 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
5008 char buf[BUFSIZ];
5009
af4c2728 5010 flog_err(
e50f7cfd 5011 EC_BGP_UPDATE_RCV,
d62a17ae 5012 "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
5013 peer->host,
5014 inet_ntop(AF_INET6, &p.u.prefix6, buf,
5015 BUFSIZ));
5016
5017 continue;
5018 }
5019 }
5020
5021 /* Normal process. */
5022 if (attr)
5023 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5024 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5025 NULL, NULL, 0, 0, NULL);
d62a17ae 5026 else
5027 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5028 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5029 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5030 NULL);
d62a17ae 5031
513386b5
DA
5032 /* Do not send BGP notification twice when maximum-prefix count
5033 * overflow. */
5034 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5035 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5036
5037 /* Address family configuration mismatch. */
d62a17ae 5038 if (ret < 0)
513386b5 5039 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5040 }
5041
5042 /* Packet length consistency check. */
5043 if (pnt != lim) {
af4c2728 5044 flog_err(
e50f7cfd 5045 EC_BGP_UPDATE_RCV,
d62a17ae 5046 "%s [Error] Update packet error (prefix length mismatch with total length)",
5047 peer->host);
513386b5 5048 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5049 }
6b0655a2 5050
513386b5 5051 return BGP_NLRI_PARSE_OK;
718e3744 5052}
5053
d62a17ae 5054static struct bgp_static *bgp_static_new(void)
718e3744 5055{
d62a17ae 5056 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5057}
5058
d62a17ae 5059static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5060{
0a22ddfb 5061 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5062 route_map_counter_decrement(bgp_static->rmap.map);
5063
0a22ddfb 5064 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5065 XFREE(MTYPE_BGP_STATIC, bgp_static);
5066}
5067
5f040085 5068void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5069 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5070{
9bcb3eef 5071 struct bgp_dest *dest;
40381db7 5072 struct bgp_path_info *pi;
4b7e6066 5073 struct bgp_path_info *new;
40381db7 5074 struct bgp_path_info rmap_path;
d62a17ae 5075 struct attr attr;
5076 struct attr *attr_new;
b68885f9 5077 route_map_result_t ret;
49e5a4a0 5078#ifdef ENABLE_BGP_VNC
d62a17ae 5079 int vnc_implicit_withdraw = 0;
65efcfce 5080#endif
fee0f4c6 5081
d62a17ae 5082 assert(bgp_static);
dd8103a9 5083
9bcb3eef 5084 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5085
d62a17ae 5086 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5087
d62a17ae 5088 attr.nexthop = bgp_static->igpnexthop;
5089 attr.med = bgp_static->igpmetric;
5090 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5091
d62a17ae 5092 if (bgp_static->atomic)
5093 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5094
d62a17ae 5095 /* Store label index, if required. */
5096 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5097 attr.label_index = bgp_static->label_index;
5098 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5099 }
718e3744 5100
d62a17ae 5101 /* Apply route-map. */
5102 if (bgp_static->rmap.name) {
5103 struct attr attr_tmp = attr;
80ced710 5104
40381db7
DS
5105 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5106 rmap_path.peer = bgp->peer_self;
5107 rmap_path.attr = &attr_tmp;
fee0f4c6 5108
d62a17ae 5109 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5110
40381db7
DS
5111 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5112 &rmap_path);
fee0f4c6 5113
d62a17ae 5114 bgp->peer_self->rmap_type = 0;
718e3744 5115
d62a17ae 5116 if (ret == RMAP_DENYMATCH) {
5117 /* Free uninterned attribute. */
5118 bgp_attr_flush(&attr_tmp);
718e3744 5119
d62a17ae 5120 /* Unintern original. */
5121 aspath_unintern(&attr.aspath);
5122 bgp_static_withdraw(bgp, p, afi, safi);
5123 return;
5124 }
7f323236 5125
637e5ba4 5126 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5127 bgp_attr_add_gshut_community(&attr_tmp);
5128
d62a17ae 5129 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5130 } else {
5131
637e5ba4 5132 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5133 bgp_attr_add_gshut_community(&attr);
5134
d62a17ae 5135 attr_new = bgp_attr_intern(&attr);
7f323236 5136 }
718e3744 5137
9bcb3eef 5138 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5139 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5140 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5141 break;
5142
40381db7
DS
5143 if (pi) {
5144 if (attrhash_cmp(pi->attr, attr_new)
5145 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5146 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5147 bgp_dest_unlock_node(dest);
d62a17ae 5148 bgp_attr_unintern(&attr_new);
5149 aspath_unintern(&attr.aspath);
5150 return;
5151 } else {
5152 /* The attribute is changed. */
9bcb3eef 5153 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5154
5155 /* Rewrite BGP route information. */
40381db7 5156 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5157 bgp_path_info_restore(dest, pi);
d62a17ae 5158 else
40381db7 5159 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5160#ifdef ENABLE_BGP_VNC
d62a17ae 5161 if ((afi == AFI_IP || afi == AFI_IP6)
5162 && (safi == SAFI_UNICAST)) {
40381db7 5163 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5164 /*
5165 * Implicit withdraw case.
40381db7 5166 * We have to do this before pi is
d62a17ae 5167 * changed
5168 */
5169 ++vnc_implicit_withdraw;
40381db7 5170 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5171 vnc_import_bgp_exterior_del_route(
40381db7 5172 bgp, p, pi);
d62a17ae 5173 }
5174 }
65efcfce 5175#endif
40381db7
DS
5176 bgp_attr_unintern(&pi->attr);
5177 pi->attr = attr_new;
5178 pi->uptime = bgp_clock();
49e5a4a0 5179#ifdef ENABLE_BGP_VNC
d62a17ae 5180 if ((afi == AFI_IP || afi == AFI_IP6)
5181 && (safi == SAFI_UNICAST)) {
5182 if (vnc_implicit_withdraw) {
40381db7 5183 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5184 vnc_import_bgp_exterior_add_route(
40381db7 5185 bgp, p, pi);
d62a17ae 5186 }
5187 }
65efcfce 5188#endif
718e3744 5189
d62a17ae 5190 /* Nexthop reachability check. */
892fedb6 5191 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5192 && (safi == SAFI_UNICAST
5193 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5194
5195 struct bgp *bgp_nexthop = bgp;
5196
40381db7
DS
5197 if (pi->extra && pi->extra->bgp_orig)
5198 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5199
5200 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
40381db7 5201 afi, pi, NULL, 0))
9bcb3eef 5202 bgp_path_info_set_flag(dest, pi,
18ee8310 5203 BGP_PATH_VALID);
d62a17ae 5204 else {
5205 if (BGP_DEBUG(nht, NHT)) {
5206 char buf1[INET6_ADDRSTRLEN];
5207 inet_ntop(p->family,
5208 &p->u.prefix, buf1,
5209 INET6_ADDRSTRLEN);
5210 zlog_debug(
5211 "%s(%s): Route not in table, not advertising",
15569c58 5212 __func__, buf1);
d62a17ae 5213 }
18ee8310 5214 bgp_path_info_unset_flag(
9bcb3eef 5215 dest, pi, BGP_PATH_VALID);
d62a17ae 5216 }
5217 } else {
5218 /* Delete the NHT structure if any, if we're
5219 * toggling between
5220 * enabling/disabling import check. We
5221 * deregister the route
5222 * from NHT to avoid overloading NHT and the
5223 * process interaction
5224 */
40381db7 5225 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5226 bgp_path_info_set_flag(dest, pi,
5227 BGP_PATH_VALID);
d62a17ae 5228 }
5229 /* Process change. */
40381db7 5230 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5231 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5232
5233 if (SAFI_UNICAST == safi
5234 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5235 || bgp->inst_type
5236 == BGP_INSTANCE_TYPE_DEFAULT)) {
5237 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5238 pi);
ddb5b488
PZ
5239 }
5240
9bcb3eef 5241 bgp_dest_unlock_node(dest);
d62a17ae 5242 aspath_unintern(&attr.aspath);
5243 return;
5244 }
718e3744 5245 }
718e3744 5246
d62a17ae 5247 /* Make new BGP info. */
5248 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5249 attr_new, dest);
d62a17ae 5250 /* Nexthop reachability check. */
892fedb6 5251 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5252 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
960035b2 5253 if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
9bcb3eef 5254 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5255 else {
5256 if (BGP_DEBUG(nht, NHT)) {
5257 char buf1[INET6_ADDRSTRLEN];
5258 inet_ntop(p->family, &p->u.prefix, buf1,
5259 INET6_ADDRSTRLEN);
5260 zlog_debug(
5261 "%s(%s): Route not in table, not advertising",
15569c58 5262 __func__, buf1);
d62a17ae 5263 }
9bcb3eef 5264 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5265 }
5266 } else {
5267 /* Delete the NHT structure if any, if we're toggling between
5268 * enabling/disabling import check. We deregister the route
5269 * from NHT to avoid overloading NHT and the process interaction
5270 */
5271 bgp_unlink_nexthop(new);
5272
9bcb3eef 5273 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5274 }
078430f6 5275
d62a17ae 5276 /* Aggregate address increment. */
5277 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5278
d62a17ae 5279 /* Register new BGP information. */
9bcb3eef 5280 bgp_path_info_add(dest, new);
718e3744 5281
d62a17ae 5282 /* route_node_get lock */
9bcb3eef 5283 bgp_dest_unlock_node(dest);
d62a17ae 5284
5285 /* Process change. */
9bcb3eef 5286 bgp_process(bgp, dest, afi, safi);
d62a17ae 5287
ddb5b488
PZ
5288 if (SAFI_UNICAST == safi
5289 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5290 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5291 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5292 }
5293
d62a17ae 5294 /* Unintern original. */
5295 aspath_unintern(&attr.aspath);
718e3744 5296}
5297
5f040085 5298void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5299 safi_t safi)
718e3744 5300{
9bcb3eef 5301 struct bgp_dest *dest;
40381db7 5302 struct bgp_path_info *pi;
718e3744 5303
9bcb3eef 5304 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5305
d62a17ae 5306 /* Check selected route and self inserted route. */
9bcb3eef 5307 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5308 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5309 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5310 break;
5311
5312 /* Withdraw static BGP route from routing table. */
40381db7 5313 if (pi) {
ddb5b488
PZ
5314 if (SAFI_UNICAST == safi
5315 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5316 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5317 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5318 }
40381db7
DS
5319 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5320 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5321 bgp_path_info_delete(dest, pi);
5322 bgp_process(bgp, dest, afi, safi);
d62a17ae 5323 }
718e3744 5324
d62a17ae 5325 /* Unlock bgp_node_lookup. */
9bcb3eef 5326 bgp_dest_unlock_node(dest);
718e3744 5327}
5328
137446f9
LB
5329/*
5330 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5331 */
5f040085 5332static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5333 afi_t afi, safi_t safi,
5334 struct prefix_rd *prd)
718e3744 5335{
9bcb3eef 5336 struct bgp_dest *dest;
40381db7 5337 struct bgp_path_info *pi;
718e3744 5338
9bcb3eef 5339 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5340
d62a17ae 5341 /* Check selected route and self inserted route. */
9bcb3eef 5342 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5343 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5344 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5345 break;
718e3744 5346
d62a17ae 5347 /* Withdraw static BGP route from routing table. */
40381db7 5348 if (pi) {
49e5a4a0 5349#ifdef ENABLE_BGP_VNC
d62a17ae 5350 rfapiProcessWithdraw(
40381db7 5351 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5352 1); /* Kill, since it is an administrative change */
65efcfce 5353#endif
ddb5b488
PZ
5354 if (SAFI_MPLS_VPN == safi
5355 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5356 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5357 }
40381db7 5358 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5359 bgp_path_info_delete(dest, pi);
5360 bgp_process(bgp, dest, afi, safi);
d62a17ae 5361 }
718e3744 5362
d62a17ae 5363 /* Unlock bgp_node_lookup. */
9bcb3eef 5364 bgp_dest_unlock_node(dest);
718e3744 5365}
5366
5f040085 5367static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5368 struct bgp_static *bgp_static, afi_t afi,
5369 safi_t safi)
137446f9 5370{
9bcb3eef 5371 struct bgp_dest *dest;
4b7e6066 5372 struct bgp_path_info *new;
d62a17ae 5373 struct attr *attr_new;
5374 struct attr attr = {0};
40381db7 5375 struct bgp_path_info *pi;
49e5a4a0 5376#ifdef ENABLE_BGP_VNC
d62a17ae 5377 mpls_label_t label = 0;
65efcfce 5378#endif
d7c0a89a 5379 uint32_t num_labels = 0;
d62a17ae 5380 union gw_addr add;
137446f9 5381
d62a17ae 5382 assert(bgp_static);
137446f9 5383
b57ba6d2
MK
5384 if (bgp_static->label != MPLS_INVALID_LABEL)
5385 num_labels = 1;
9bcb3eef
DS
5386 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5387 &bgp_static->prd);
137446f9 5388
d62a17ae 5389 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5390
d62a17ae 5391 attr.nexthop = bgp_static->igpnexthop;
5392 attr.med = bgp_static->igpmetric;
5393 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5394
d62a17ae 5395 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5396 || (safi == SAFI_ENCAP)) {
5397 if (afi == AFI_IP) {
5398 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5399 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5400 }
5401 }
5402 if (afi == AFI_L2VPN) {
5403 if (bgp_static->gatewayIp.family == AF_INET)
5404 add.ipv4.s_addr =
5405 bgp_static->gatewayIp.u.prefix4.s_addr;
5406 else if (bgp_static->gatewayIp.family == AF_INET6)
5407 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5408 sizeof(struct in6_addr));
0a50c248 5409 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5410 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5411 struct bgp_encap_type_vxlan bet;
5412 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5413 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5414 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5415 }
5416 if (bgp_static->router_mac) {
5417 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5418 }
5419 }
5420 /* Apply route-map. */
5421 if (bgp_static->rmap.name) {
5422 struct attr attr_tmp = attr;
40381db7 5423 struct bgp_path_info rmap_path;
b68885f9 5424 route_map_result_t ret;
137446f9 5425
40381db7
DS
5426 rmap_path.peer = bgp->peer_self;
5427 rmap_path.attr = &attr_tmp;
137446f9 5428
d62a17ae 5429 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5430
40381db7
DS
5431 ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
5432 &rmap_path);
137446f9 5433
d62a17ae 5434 bgp->peer_self->rmap_type = 0;
137446f9 5435
d62a17ae 5436 if (ret == RMAP_DENYMATCH) {
5437 /* Free uninterned attribute. */
5438 bgp_attr_flush(&attr_tmp);
137446f9 5439
d62a17ae 5440 /* Unintern original. */
5441 aspath_unintern(&attr.aspath);
5442 bgp_static_withdraw_safi(bgp, p, afi, safi,
5443 &bgp_static->prd);
5444 return;
5445 }
137446f9 5446
d62a17ae 5447 attr_new = bgp_attr_intern(&attr_tmp);
5448 } else {
5449 attr_new = bgp_attr_intern(&attr);
5450 }
137446f9 5451
9bcb3eef 5452 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5453 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5454 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5455 break;
5456
40381db7 5457 if (pi) {
d62a17ae 5458 memset(&add, 0, sizeof(union gw_addr));
40381db7 5459 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5460 && overlay_index_equal(afi, pi, &add)
40381db7 5461 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5462 bgp_dest_unlock_node(dest);
d62a17ae 5463 bgp_attr_unintern(&attr_new);
5464 aspath_unintern(&attr.aspath);
5465 return;
5466 } else {
5467 /* The attribute is changed. */
9bcb3eef 5468 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5469
5470 /* Rewrite BGP route information. */
40381db7 5471 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5472 bgp_path_info_restore(dest, pi);
d62a17ae 5473 else
40381db7
DS
5474 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5475 bgp_attr_unintern(&pi->attr);
5476 pi->attr = attr_new;
5477 pi->uptime = bgp_clock();
49e5a4a0 5478#ifdef ENABLE_BGP_VNC
40381db7
DS
5479 if (pi->extra)
5480 label = decode_label(&pi->extra->label[0]);
65efcfce 5481#endif
137446f9 5482
d62a17ae 5483 /* Process change. */
40381db7 5484 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5485 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5486
5487 if (SAFI_MPLS_VPN == safi
5488 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5489 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5490 }
49e5a4a0 5491#ifdef ENABLE_BGP_VNC
40381db7
DS
5492 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5493 pi->attr, afi, safi, pi->type,
5494 pi->sub_type, &label);
65efcfce 5495#endif
9bcb3eef 5496 bgp_dest_unlock_node(dest);
d62a17ae 5497 aspath_unintern(&attr.aspath);
5498 return;
5499 }
5500 }
137446f9
LB
5501
5502
d62a17ae 5503 /* Make new BGP info. */
5504 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5505 attr_new, dest);
1defdda8 5506 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5507 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5508 if (num_labels) {
5509 new->extra->label[0] = bgp_static->label;
5510 new->extra->num_labels = num_labels;
5511 }
49e5a4a0 5512#ifdef ENABLE_BGP_VNC
d62a17ae 5513 label = decode_label(&bgp_static->label);
65efcfce 5514#endif
137446f9 5515
d62a17ae 5516 /* Aggregate address increment. */
5517 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5518
d62a17ae 5519 /* Register new BGP information. */
9bcb3eef 5520 bgp_path_info_add(dest, new);
d62a17ae 5521 /* route_node_get lock */
9bcb3eef 5522 bgp_dest_unlock_node(dest);
137446f9 5523
d62a17ae 5524 /* Process change. */
9bcb3eef 5525 bgp_process(bgp, dest, afi, safi);
137446f9 5526
ddb5b488
PZ
5527 if (SAFI_MPLS_VPN == safi
5528 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5529 vpn_leak_to_vrf_update(bgp, new);
5530 }
49e5a4a0 5531#ifdef ENABLE_BGP_VNC
d62a17ae 5532 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5533 safi, new->type, new->sub_type, &label);
65efcfce
LB
5534#endif
5535
d62a17ae 5536 /* Unintern original. */
5537 aspath_unintern(&attr.aspath);
137446f9
LB
5538}
5539
718e3744 5540/* Configure static BGP network. When user don't run zebra, static
5541 route should be installed as valid. */
e2a86ad9
DS
5542static int bgp_static_set(struct vty *vty, const char *negate,
5543 const char *ip_str, afi_t afi, safi_t safi,
d7c0a89a 5544 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 5545{
5546 VTY_DECLVAR_CONTEXT(bgp, bgp);
5547 int ret;
5548 struct prefix p;
5549 struct bgp_static *bgp_static;
9bcb3eef 5550 struct bgp_dest *dest;
d7c0a89a 5551 uint8_t need_update = 0;
d62a17ae 5552
5553 /* Convert IP prefix string to struct prefix. */
5554 ret = str2prefix(ip_str, &p);
5555 if (!ret) {
5556 vty_out(vty, "%% Malformed prefix\n");
5557 return CMD_WARNING_CONFIG_FAILED;
5558 }
5559 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
5560 vty_out(vty, "%% Malformed prefix (link-local address)\n");
5561 return CMD_WARNING_CONFIG_FAILED;
5562 }
718e3744 5563
d62a17ae 5564 apply_mask(&p);
718e3744 5565
e2a86ad9 5566 if (negate) {
718e3744 5567
e2a86ad9 5568 /* Set BGP static route configuration. */
9bcb3eef 5569 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5570
9bcb3eef 5571 if (!dest) {
a4d82a8a 5572 vty_out(vty, "%% Can't find static route specified\n");
d62a17ae 5573 return CMD_WARNING_CONFIG_FAILED;
5574 }
5575
9bcb3eef 5576 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5577
e2a86ad9
DS
5578 if ((label_index != BGP_INVALID_LABEL_INDEX)
5579 && (label_index != bgp_static->label_index)) {
5580 vty_out(vty,
5581 "%% label-index doesn't match static route\n");
5582 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5583 }
d62a17ae 5584
e2a86ad9
DS
5585 if ((rmap && bgp_static->rmap.name)
5586 && strcmp(rmap, bgp_static->rmap.name)) {
5587 vty_out(vty,
5588 "%% route-map name doesn't match static route\n");
5589 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 5590 }
718e3744 5591
e2a86ad9
DS
5592 /* Update BGP RIB. */
5593 if (!bgp_static->backdoor)
5594 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5595
e2a86ad9
DS
5596 /* Clear configuration. */
5597 bgp_static_free(bgp_static);
9bcb3eef
DS
5598 bgp_dest_set_bgp_static_info(dest, NULL);
5599 bgp_dest_unlock_node(dest);
5600 bgp_dest_unlock_node(dest);
e2a86ad9 5601 } else {
718e3744 5602
e2a86ad9 5603 /* Set BGP static route configuration. */
9bcb3eef
DS
5604 dest = bgp_node_get(bgp->route[afi][safi], &p);
5605 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5606 if (bgp_static) {
e2a86ad9 5607 /* Configuration change. */
e2a86ad9
DS
5608 /* Label index cannot be changed. */
5609 if (bgp_static->label_index != label_index) {
5610 vty_out(vty, "%% cannot change label-index\n");
5611 return CMD_WARNING_CONFIG_FAILED;
5612 }
d62a17ae 5613
e2a86ad9 5614 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5615 if (bgp_static->valid
5616 && bgp_static->backdoor != backdoor)
e2a86ad9 5617 need_update = 1;
718e3744 5618
e2a86ad9 5619 bgp_static->backdoor = backdoor;
718e3744 5620
e2a86ad9 5621 if (rmap) {
0a22ddfb
QY
5622 XFREE(MTYPE_ROUTE_MAP_NAME,
5623 bgp_static->rmap.name);
b4897fa5 5624 route_map_counter_decrement(
5625 bgp_static->rmap.map);
e2a86ad9
DS
5626 bgp_static->rmap.name =
5627 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5628 bgp_static->rmap.map =
5629 route_map_lookup_by_name(rmap);
b4897fa5 5630 route_map_counter_increment(
5631 bgp_static->rmap.map);
e2a86ad9 5632 } else {
0a22ddfb
QY
5633 XFREE(MTYPE_ROUTE_MAP_NAME,
5634 bgp_static->rmap.name);
b4897fa5 5635 route_map_counter_decrement(
5636 bgp_static->rmap.map);
e2a86ad9
DS
5637 bgp_static->rmap.map = NULL;
5638 bgp_static->valid = 0;
5639 }
9bcb3eef 5640 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5641 } else {
5642 /* New configuration. */
5643 bgp_static = bgp_static_new();
5644 bgp_static->backdoor = backdoor;
5645 bgp_static->valid = 0;
5646 bgp_static->igpmetric = 0;
975a328e 5647 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5648 bgp_static->label_index = label_index;
718e3744 5649
e2a86ad9 5650 if (rmap) {
0a22ddfb
QY
5651 XFREE(MTYPE_ROUTE_MAP_NAME,
5652 bgp_static->rmap.name);
b4897fa5 5653 route_map_counter_decrement(
5654 bgp_static->rmap.map);
e2a86ad9
DS
5655 bgp_static->rmap.name =
5656 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5657 bgp_static->rmap.map =
5658 route_map_lookup_by_name(rmap);
b4897fa5 5659 route_map_counter_increment(
5660 bgp_static->rmap.map);
e2a86ad9 5661 }
9bcb3eef 5662 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5663 }
d62a17ae 5664
e2a86ad9
DS
5665 bgp_static->valid = 1;
5666 if (need_update)
5667 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5668
e2a86ad9
DS
5669 if (!bgp_static->backdoor)
5670 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5671 }
d62a17ae 5672
5673 return CMD_SUCCESS;
5674}
5675
5676void bgp_static_add(struct bgp *bgp)
5677{
5678 afi_t afi;
5679 safi_t safi;
9bcb3eef
DS
5680 struct bgp_dest *dest;
5681 struct bgp_dest *rm;
d62a17ae 5682 struct bgp_table *table;
5683 struct bgp_static *bgp_static;
5684
05c7a1cc 5685 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5686 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5687 dest = bgp_route_next(dest)) {
5688 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5689 continue;
ea47320b 5690
05c7a1cc
QY
5691 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5692 || (safi == SAFI_EVPN)) {
9bcb3eef 5693 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5694
5695 for (rm = bgp_table_top(table); rm;
5696 rm = bgp_route_next(rm)) {
a78beeb5 5697 bgp_static =
9bcb3eef 5698 bgp_dest_get_bgp_static_info(
5a8ba9fc 5699 rm);
9bcb3eef
DS
5700 bgp_static_update_safi(
5701 bgp, bgp_dest_get_prefix(rm),
5702 bgp_static, afi, safi);
d62a17ae 5703 }
05c7a1cc 5704 } else {
5a8ba9fc 5705 bgp_static_update(
9bcb3eef
DS
5706 bgp, bgp_dest_get_prefix(dest),
5707 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5708 safi);
ea47320b 5709 }
05c7a1cc 5710 }
6aeb9e78
DS
5711}
5712
718e3744 5713/* Called from bgp_delete(). Delete all static routes from the BGP
5714 instance. */
d62a17ae 5715void bgp_static_delete(struct bgp *bgp)
5716{
5717 afi_t afi;
5718 safi_t safi;
9bcb3eef
DS
5719 struct bgp_dest *dest;
5720 struct bgp_dest *rm;
d62a17ae 5721 struct bgp_table *table;
5722 struct bgp_static *bgp_static;
5723
05c7a1cc 5724 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5725 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5726 dest = bgp_route_next(dest)) {
5727 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5728 continue;
ea47320b 5729
05c7a1cc
QY
5730 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5731 || (safi == SAFI_EVPN)) {
9bcb3eef 5732 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5733
5734 for (rm = bgp_table_top(table); rm;
5735 rm = bgp_route_next(rm)) {
a78beeb5 5736 bgp_static =
9bcb3eef 5737 bgp_dest_get_bgp_static_info(
5a8ba9fc 5738 rm);
c7d14ba6
PG
5739 if (!bgp_static)
5740 continue;
5741
05c7a1cc 5742 bgp_static_withdraw_safi(
9bcb3eef 5743 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5744 AFI_IP, safi,
5745 (struct prefix_rd *)
9bcb3eef
DS
5746 bgp_dest_get_prefix(
5747 dest));
ea47320b 5748 bgp_static_free(bgp_static);
9bcb3eef
DS
5749 bgp_dest_set_bgp_static_info(dest,
5750 NULL);
5751 bgp_dest_unlock_node(dest);
d62a17ae 5752 }
05c7a1cc 5753 } else {
9bcb3eef 5754 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5755 bgp_static_withdraw(bgp,
9bcb3eef 5756 bgp_dest_get_prefix(dest),
b54892e0 5757 afi, safi);
05c7a1cc 5758 bgp_static_free(bgp_static);
9bcb3eef
DS
5759 bgp_dest_set_bgp_static_info(dest, NULL);
5760 bgp_dest_unlock_node(dest);
ea47320b 5761 }
05c7a1cc 5762 }
d62a17ae 5763}
5764
5765void bgp_static_redo_import_check(struct bgp *bgp)
5766{
5767 afi_t afi;
5768 safi_t safi;
9bcb3eef
DS
5769 struct bgp_dest *dest;
5770 struct bgp_dest *rm;
d62a17ae 5771 struct bgp_table *table;
5772 struct bgp_static *bgp_static;
5773
5774 /* Use this flag to force reprocessing of the route */
892fedb6 5775 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 5776 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
5777 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5778 dest = bgp_route_next(dest)) {
5779 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5780 continue;
ea47320b 5781
05c7a1cc
QY
5782 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5783 || (safi == SAFI_EVPN)) {
9bcb3eef 5784 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5785
5786 for (rm = bgp_table_top(table); rm;
5787 rm = bgp_route_next(rm)) {
a78beeb5 5788 bgp_static =
9bcb3eef 5789 bgp_dest_get_bgp_static_info(
5a8ba9fc 5790 rm);
9bcb3eef
DS
5791 bgp_static_update_safi(
5792 bgp, bgp_dest_get_prefix(rm),
5793 bgp_static, afi, safi);
d62a17ae 5794 }
05c7a1cc 5795 } else {
9bcb3eef
DS
5796 bgp_static = bgp_dest_get_bgp_static_info(dest);
5797 bgp_static_update(bgp,
5798 bgp_dest_get_prefix(dest),
5799 bgp_static, afi, safi);
ea47320b 5800 }
05c7a1cc
QY
5801 }
5802 }
892fedb6 5803 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 5804}
5805
5806static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
5807 safi_t safi)
5808{
5809 struct bgp_table *table;
9bcb3eef 5810 struct bgp_dest *dest;
40381db7 5811 struct bgp_path_info *pi;
d62a17ae 5812
dfb6fd1d
NT
5813 /* Do not install the aggregate route if BGP is in the
5814 * process of termination.
5815 */
892fedb6
DA
5816 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
5817 || (bgp->peer_self == NULL))
dfb6fd1d
NT
5818 return;
5819
d62a17ae 5820 table = bgp->rib[afi][safi];
9bcb3eef
DS
5821 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5822 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
5823 if (pi->peer == bgp->peer_self
5824 && ((pi->type == ZEBRA_ROUTE_BGP
5825 && pi->sub_type == BGP_ROUTE_STATIC)
5826 || (pi->type != ZEBRA_ROUTE_BGP
5827 && pi->sub_type
d62a17ae 5828 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
5829 bgp_aggregate_decrement(
5830 bgp, bgp_dest_get_prefix(dest), pi, afi,
5831 safi);
40381db7 5832 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5833 bgp_path_info_delete(dest, pi);
5834 bgp_process(bgp, dest, afi, safi);
d62a17ae 5835 }
5836 }
5837 }
ad4cbda1 5838}
5839
5840/*
5841 * Purge all networks and redistributed routes from routing table.
5842 * Invoked upon the instance going down.
5843 */
d62a17ae 5844void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 5845{
d62a17ae 5846 afi_t afi;
5847 safi_t safi;
ad4cbda1 5848
05c7a1cc
QY
5849 FOREACH_AFI_SAFI (afi, safi)
5850 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 5851}
5852
137446f9
LB
5853/*
5854 * gpz 110624
5855 * Currently this is used to set static routes for VPN and ENCAP.
5856 * I think it can probably be factored with bgp_static_set.
5857 */
d62a17ae 5858int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
5859 const char *ip_str, const char *rd_str,
5860 const char *label_str, const char *rmap_str,
5861 int evpn_type, const char *esi, const char *gwip,
5862 const char *ethtag, const char *routermac)
5863{
5864 VTY_DECLVAR_CONTEXT(bgp, bgp);
5865 int ret;
5866 struct prefix p;
5867 struct prefix_rd prd;
9bcb3eef
DS
5868 struct bgp_dest *pdest;
5869 struct bgp_dest *dest;
d62a17ae 5870 struct bgp_table *table;
5871 struct bgp_static *bgp_static;
5872 mpls_label_t label = MPLS_INVALID_LABEL;
5873 struct prefix gw_ip;
5874
5875 /* validate ip prefix */
5876 ret = str2prefix(ip_str, &p);
5877 if (!ret) {
5878 vty_out(vty, "%% Malformed prefix\n");
5879 return CMD_WARNING_CONFIG_FAILED;
5880 }
5881 apply_mask(&p);
5882 if ((afi == AFI_L2VPN)
5883 && (bgp_build_evpn_prefix(evpn_type,
5884 ethtag != NULL ? atol(ethtag) : 0, &p))) {
5885 vty_out(vty, "%% L2VPN prefix could not be forged\n");
5886 return CMD_WARNING_CONFIG_FAILED;
5887 }
718e3744 5888
d62a17ae 5889 ret = str2prefix_rd(rd_str, &prd);
5890 if (!ret) {
5891 vty_out(vty, "%% Malformed rd\n");
5892 return CMD_WARNING_CONFIG_FAILED;
5893 }
718e3744 5894
d62a17ae 5895 if (label_str) {
5896 unsigned long label_val;
5897 label_val = strtoul(label_str, NULL, 10);
5898 encode_label(label_val, &label);
5899 }
9bedbb1e 5900
d62a17ae 5901 if (safi == SAFI_EVPN) {
5902 if (esi && str2esi(esi, NULL) == 0) {
5903 vty_out(vty, "%% Malformed ESI\n");
5904 return CMD_WARNING_CONFIG_FAILED;
5905 }
5906 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
5907 vty_out(vty, "%% Malformed Router MAC\n");
5908 return CMD_WARNING_CONFIG_FAILED;
5909 }
5910 if (gwip) {
5911 memset(&gw_ip, 0, sizeof(struct prefix));
5912 ret = str2prefix(gwip, &gw_ip);
5913 if (!ret) {
5914 vty_out(vty, "%% Malformed GatewayIp\n");
5915 return CMD_WARNING_CONFIG_FAILED;
5916 }
5917 if ((gw_ip.family == AF_INET
3714a385 5918 && is_evpn_prefix_ipaddr_v6(
d62a17ae 5919 (struct prefix_evpn *)&p))
5920 || (gw_ip.family == AF_INET6
3714a385 5921 && is_evpn_prefix_ipaddr_v4(
d62a17ae 5922 (struct prefix_evpn *)&p))) {
5923 vty_out(vty,
5924 "%% GatewayIp family differs with IP prefix\n");
5925 return CMD_WARNING_CONFIG_FAILED;
5926 }
5927 }
5928 }
9bcb3eef
DS
5929 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
5930 if (!bgp_dest_has_bgp_path_info_data(pdest))
5931 bgp_dest_set_bgp_table_info(pdest,
67009e22 5932 bgp_table_init(bgp, afi, safi));
9bcb3eef 5933 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 5934
9bcb3eef 5935 dest = bgp_node_get(table, &p);
d62a17ae 5936
9bcb3eef 5937 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 5938 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 5939 bgp_dest_unlock_node(dest);
d62a17ae 5940 } else {
5941 /* New configuration. */
5942 bgp_static = bgp_static_new();
5943 bgp_static->backdoor = 0;
5944 bgp_static->valid = 0;
5945 bgp_static->igpmetric = 0;
975a328e 5946 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 5947 bgp_static->label = label;
5948 bgp_static->prd = prd;
5949
5950 if (rmap_str) {
0a22ddfb 5951 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5952 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 5953 bgp_static->rmap.name =
5954 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
5955 bgp_static->rmap.map =
5956 route_map_lookup_by_name(rmap_str);
b4897fa5 5957 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 5958 }
718e3744 5959
d62a17ae 5960 if (safi == SAFI_EVPN) {
5961 if (esi) {
5962 bgp_static->eth_s_id =
5963 XCALLOC(MTYPE_ATTR,
0a50c248 5964 sizeof(esi_t));
d62a17ae 5965 str2esi(esi, bgp_static->eth_s_id);
5966 }
5967 if (routermac) {
5968 bgp_static->router_mac =
28328ea9 5969 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
5970 (void)prefix_str2mac(routermac,
5971 bgp_static->router_mac);
d62a17ae 5972 }
5973 if (gwip)
5974 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
5975 }
9bcb3eef 5976 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 5977
d62a17ae 5978 bgp_static->valid = 1;
5979 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
5980 }
718e3744 5981
d62a17ae 5982 return CMD_SUCCESS;
718e3744 5983}
5984
5985/* Configure static BGP network. */
d62a17ae 5986int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
5987 const char *ip_str, const char *rd_str,
5988 const char *label_str, int evpn_type, const char *esi,
5989 const char *gwip, const char *ethtag)
5990{
5991 VTY_DECLVAR_CONTEXT(bgp, bgp);
5992 int ret;
5993 struct prefix p;
5994 struct prefix_rd prd;
9bcb3eef
DS
5995 struct bgp_dest *pdest;
5996 struct bgp_dest *dest;
d62a17ae 5997 struct bgp_table *table;
5998 struct bgp_static *bgp_static;
5999 mpls_label_t label = MPLS_INVALID_LABEL;
6000
6001 /* Convert IP prefix string to struct prefix. */
6002 ret = str2prefix(ip_str, &p);
6003 if (!ret) {
6004 vty_out(vty, "%% Malformed prefix\n");
6005 return CMD_WARNING_CONFIG_FAILED;
6006 }
6007 apply_mask(&p);
6008 if ((afi == AFI_L2VPN)
6009 && (bgp_build_evpn_prefix(evpn_type,
6010 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6011 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6012 return CMD_WARNING_CONFIG_FAILED;
6013 }
6014 ret = str2prefix_rd(rd_str, &prd);
6015 if (!ret) {
6016 vty_out(vty, "%% Malformed rd\n");
6017 return CMD_WARNING_CONFIG_FAILED;
6018 }
718e3744 6019
d62a17ae 6020 if (label_str) {
6021 unsigned long label_val;
6022 label_val = strtoul(label_str, NULL, 10);
6023 encode_label(label_val, &label);
6024 }
718e3744 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));
d62a17ae 6030 else
9bcb3eef
DS
6031 bgp_dest_unlock_node(pdest);
6032 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6033
9bcb3eef 6034 dest = bgp_node_lookup(table, &p);
6b0655a2 6035
9bcb3eef 6036 if (dest) {
d62a17ae 6037 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6038
9bcb3eef 6039 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6040 bgp_static_free(bgp_static);
9bcb3eef
DS
6041 bgp_dest_set_bgp_static_info(dest, NULL);
6042 bgp_dest_unlock_node(dest);
6043 bgp_dest_unlock_node(dest);
d62a17ae 6044 } else
6045 vty_out(vty, "%% Can't find the route\n");
6046
6047 return CMD_SUCCESS;
6048}
6049
6050static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6051 const char *rmap_name)
6052{
6053 VTY_DECLVAR_CONTEXT(bgp, bgp);
6054 struct bgp_rmap *rmap;
6055
6056 rmap = &bgp->table_map[afi][safi];
6057 if (rmap_name) {
0a22ddfb 6058 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6059 route_map_counter_decrement(rmap->map);
d62a17ae 6060 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6061 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6062 route_map_counter_increment(rmap->map);
d62a17ae 6063 } else {
0a22ddfb 6064 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6065 route_map_counter_decrement(rmap->map);
d62a17ae 6066 rmap->map = NULL;
6067 }
73ac8160 6068
d62a17ae 6069 if (bgp_fibupd_safi(safi))
6070 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6071
d62a17ae 6072 return CMD_SUCCESS;
73ac8160
DS
6073}
6074
d62a17ae 6075static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6076 const char *rmap_name)
73ac8160 6077{
d62a17ae 6078 VTY_DECLVAR_CONTEXT(bgp, bgp);
6079 struct bgp_rmap *rmap;
73ac8160 6080
d62a17ae 6081 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6082 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6083 route_map_counter_decrement(rmap->map);
d62a17ae 6084 rmap->map = NULL;
73ac8160 6085
d62a17ae 6086 if (bgp_fibupd_safi(safi))
6087 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6088
d62a17ae 6089 return CMD_SUCCESS;
73ac8160
DS
6090}
6091
2b791107 6092void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6093 safi_t safi)
73ac8160 6094{
d62a17ae 6095 if (bgp->table_map[afi][safi].name) {
d62a17ae 6096 vty_out(vty, " table-map %s\n",
6097 bgp->table_map[afi][safi].name);
6098 }
73ac8160
DS
6099}
6100
73ac8160
DS
6101DEFUN (bgp_table_map,
6102 bgp_table_map_cmd,
6103 "table-map WORD",
6104 "BGP table to RIB route download filter\n"
6105 "Name of the route map\n")
6106{
d62a17ae 6107 int idx_word = 1;
6108 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6109 argv[idx_word]->arg);
73ac8160
DS
6110}
6111DEFUN (no_bgp_table_map,
6112 no_bgp_table_map_cmd,
6113 "no table-map WORD",
3a2d747c 6114 NO_STR
73ac8160
DS
6115 "BGP table to RIB route download filter\n"
6116 "Name of the route map\n")
6117{
d62a17ae 6118 int idx_word = 2;
6119 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6120 argv[idx_word]->arg);
73ac8160
DS
6121}
6122
e2a86ad9
DS
6123DEFPY(bgp_network,
6124 bgp_network_cmd,
6125 "[no] network \
6126 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6127 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6128 backdoor$backdoor}]",
6129 NO_STR
6130 "Specify a network to announce via BGP\n"
6131 "IPv4 prefix\n"
6132 "Network number\n"
6133 "Network mask\n"
6134 "Network mask\n"
6135 "Route-map to modify the attributes\n"
6136 "Name of the route map\n"
6137 "Label index to associate with the prefix\n"
6138 "Label index value\n"
6139 "Specify a BGP backdoor route\n")
6140{
6141 char addr_prefix_str[BUFSIZ];
6142
6143 if (address_str) {
6144 int ret;
718e3744 6145
e2a86ad9
DS
6146 ret = netmask_str2prefix_str(address_str, netmask_str,
6147 addr_prefix_str);
6148 if (!ret) {
6149 vty_out(vty, "%% Inconsistent address and mask\n");
6150 return CMD_WARNING_CONFIG_FAILED;
6151 }
d62a17ae 6152 }
718e3744 6153
a4d82a8a
PZ
6154 return bgp_static_set(
6155 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6156 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6157 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6158}
6159
e2a86ad9
DS
6160DEFPY(ipv6_bgp_network,
6161 ipv6_bgp_network_cmd,
6162 "[no] network X:X::X:X/M$prefix \
6163 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6164 NO_STR
6165 "Specify a network to announce via BGP\n"
6166 "IPv6 prefix\n"
6167 "Route-map to modify the attributes\n"
6168 "Name of the route map\n"
6169 "Label index to associate with the prefix\n"
6170 "Label index value\n")
718e3744 6171{
a4d82a8a
PZ
6172 return bgp_static_set(
6173 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6174 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6175}
6176
d62a17ae 6177static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6178{
d62a17ae 6179 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6180}
6181
d62a17ae 6182static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6183{
20894f50
DA
6184 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6185 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6186 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6187}
718e3744 6188
3dc339cd
DA
6189static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6190 struct aspath *aspath,
6191 struct community *comm,
6192 struct ecommunity *ecomm,
6193 struct lcommunity *lcomm)
eaaf8adb
DS
6194{
6195 static struct aspath *ae = NULL;
6196
6197 if (!ae)
6198 ae = aspath_empty();
6199
40381db7 6200 if (!pi)
3dc339cd 6201 return false;
eaaf8adb 6202
40381db7 6203 if (origin != pi->attr->origin)
3dc339cd 6204 return false;
eaaf8adb 6205
40381db7 6206 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6207 return false;
29f7d023 6208
40381db7 6209 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6210 return false;
eaaf8adb 6211
3da2cc32 6212 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6213 return false;
eaaf8adb 6214
dd18c5a9 6215 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6216 return false;
dd18c5a9 6217
40381db7 6218 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6219 return false;
7ce8a8e0 6220
3dc339cd 6221 return true;
eaaf8adb
DS
6222}
6223
5f040085
DS
6224static void bgp_aggregate_install(
6225 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6226 uint8_t origin, struct aspath *aspath, struct community *community,
6227 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6228 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6229{
9bcb3eef 6230 struct bgp_dest *dest;
c701010e 6231 struct bgp_table *table;
6f94b685 6232 struct bgp_path_info *pi, *orig, *new;
20894f50 6233 struct attr *attr;
c701010e
DS
6234
6235 table = bgp->rib[afi][safi];
6236
9bcb3eef 6237 dest = bgp_node_get(table, p);
eaaf8adb 6238
9bcb3eef 6239 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6240 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6241 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6242 break;
6243
6aabb15d
RZ
6244 /*
6245 * If we have paths with different MEDs, then don't install
6246 * (or uninstall) the aggregate route.
6247 */
6248 if (aggregate->match_med && aggregate->med_mismatched)
6249 goto uninstall_aggregate_route;
6250
c701010e 6251 if (aggregate->count > 0) {
eaaf8adb
DS
6252 /*
6253 * If the aggregate information has not changed
6254 * no need to re-install it again.
6255 */
6f94b685 6256 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6257 ecommunity, lcommunity)) {
9bcb3eef 6258 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6259
6260 if (aspath)
6261 aspath_free(aspath);
6262 if (community)
3c1f53de 6263 community_free(&community);
3da2cc32
DS
6264 if (ecommunity)
6265 ecommunity_free(&ecommunity);
dd18c5a9
DS
6266 if (lcommunity)
6267 lcommunity_free(&lcommunity);
eaaf8adb
DS
6268
6269 return;
6270 }
6271
6272 /*
6273 * Mark the old as unusable
6274 */
40381db7 6275 if (pi)
9bcb3eef 6276 bgp_path_info_delete(dest, pi);
eaaf8adb 6277
20894f50
DA
6278 attr = bgp_attr_aggregate_intern(
6279 bgp, origin, aspath, community, ecommunity, lcommunity,
6280 aggregate, atomic_aggregate, p);
6281
6282 if (!attr) {
6283 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
6284 return;
6285 }
6286
3da2cc32 6287 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6288 bgp->peer_self, attr, dest);
20894f50 6289
1defdda8 6290 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6291
9bcb3eef
DS
6292 bgp_path_info_add(dest, new);
6293 bgp_process(bgp, dest, afi, safi);
c701010e 6294 } else {
6aabb15d 6295 uninstall_aggregate_route:
6f94b685 6296 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6297 if (pi->peer == bgp->peer_self
6298 && pi->type == ZEBRA_ROUTE_BGP
6299 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6300 break;
6301
6302 /* Withdraw static BGP route from routing table. */
40381db7 6303 if (pi) {
9bcb3eef
DS
6304 bgp_path_info_delete(dest, pi);
6305 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6306 }
6307 }
6308
9bcb3eef 6309 bgp_dest_unlock_node(dest);
c701010e
DS
6310}
6311
6aabb15d
RZ
6312/**
6313 * Check if the current path has different MED than other known paths.
6314 *
6315 * \returns `true` if the MED matched the others else `false`.
6316 */
6317static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6318 struct bgp *bgp, struct bgp_path_info *pi)
6319{
6320 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6321
6322 /* This is the first route being analyzed. */
6323 if (!aggregate->med_initialized) {
6324 aggregate->med_initialized = true;
6325 aggregate->med_mismatched = false;
6326 aggregate->med_matched_value = cur_med;
6327 } else {
6328 /* Check if routes with different MED showed up. */
6329 if (cur_med != aggregate->med_matched_value)
6330 aggregate->med_mismatched = true;
6331 }
6332
6333 return !aggregate->med_mismatched;
6334}
6335
6336/**
6337 * Initializes and tests all routes in the aggregate address path for MED
6338 * values.
6339 *
6340 * \returns `true` if all MEDs are the same otherwise `false`.
6341 */
6342static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6343 struct bgp *bgp, const struct prefix *p,
6344 afi_t afi, safi_t safi)
6345{
6346 struct bgp_table *table = bgp->rib[afi][safi];
6347 const struct prefix *dest_p;
6348 struct bgp_dest *dest, *top;
6349 struct bgp_path_info *pi;
6350 bool med_matched = true;
6351
6352 aggregate->med_initialized = false;
6353
6354 top = bgp_node_get(table, p);
6355 for (dest = bgp_node_get(table, p); dest;
6356 dest = bgp_route_next_until(dest, top)) {
6357 dest_p = bgp_dest_get_prefix(dest);
6358 if (dest_p->prefixlen <= p->prefixlen)
6359 continue;
6360
6361 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6362 if (BGP_PATH_HOLDDOWN(pi))
6363 continue;
6364 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6365 continue;
6366 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6367 med_matched = false;
6368 break;
6369 }
6370 }
6371 if (!med_matched)
6372 break;
6373 }
6374 bgp_dest_unlock_node(top);
6375
6376 return med_matched;
6377}
6378
6379/**
6380 * Toggles the route suppression status for this aggregate address
6381 * configuration.
6382 */
6383static void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6384 struct bgp *bgp,
6385 const struct prefix *p, afi_t afi,
6386 safi_t safi, bool suppress)
6387{
6388 struct bgp_table *table = bgp->rib[afi][safi];
6389 struct bgp_path_info_extra *pie;
6390 const struct prefix *dest_p;
6391 struct bgp_dest *dest, *top;
6392 struct bgp_path_info *pi;
6393 bool toggle_suppression;
6394
6395 /* We've found a different MED we must revert any suppressed routes. */
6396 top = bgp_node_get(table, p);
6397 for (dest = bgp_node_get(table, p); dest;
6398 dest = bgp_route_next_until(dest, top)) {
6399 dest_p = bgp_dest_get_prefix(dest);
6400 if (dest_p->prefixlen <= p->prefixlen)
6401 continue;
6402
6403 toggle_suppression = false;
6404 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6405 if (BGP_PATH_HOLDDOWN(pi))
6406 continue;
6407 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6408 continue;
6409
6410 /*
6411 * On installation it is possible that pi->extra is
6412 * set to NULL, otherwise it must exists.
6413 */
6414 assert(!suppress && pi->extra != NULL);
6415
6416 /* We are toggling suppression back. */
6417 if (suppress) {
6418 pie = bgp_path_info_extra_get(pi);
6419 /* Suppress route if not suppressed already. */
6420 pie->suppress++;
6421 bgp_path_info_set_flag(dest, pi,
6422 BGP_PATH_ATTR_CHANGED);
6423 toggle_suppression = true;
6424 continue;
6425 }
6426
6427 pie = pi->extra;
6428 assert(pie->suppress > 0);
6429 pie->suppress--;
6430 /* Install route if there is no more suppression. */
6431 if (pie->suppress == 0) {
6432 bgp_path_info_set_flag(dest, pi,
6433 BGP_PATH_ATTR_CHANGED);
6434 toggle_suppression = true;
6435 }
6436 }
6437
6438 if (toggle_suppression)
6439 bgp_process(bgp, dest, afi, safi);
6440 }
6441 bgp_dest_unlock_node(top);
6442}
6443
6444/**
6445 * Aggregate address MED matching incremental test: this function is called
6446 * when the initial aggregation occurred and we are only testing a single
6447 * new path.
6448 *
6449 * In addition to testing and setting the MED validity it also installs back
6450 * suppressed routes (if summary is configured).
6451 *
6452 * Must not be called in `bgp_aggregate_route`.
6453 */
6454static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6455 struct bgp *bgp, const struct prefix *p,
6456 afi_t afi, safi_t safi,
6457 struct bgp_path_info *pi, bool is_adding)
6458{
6459 /* MED matching disabled. */
6460 if (!aggregate->match_med)
6461 return;
6462
6463 /* Aggregation with different MED, nothing to do. */
6464 if (aggregate->med_mismatched)
6465 return;
6466
6467 /*
6468 * Test the current entry:
6469 *
6470 * is_adding == true: if the new entry doesn't match then we must
6471 * install all suppressed routes.
6472 *
6473 * is_adding == false: if the entry being removed was the last
6474 * unmatching entry then we can suppress all routes.
6475 */
6476 if (!is_adding) {
6477 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6478 && aggregate->summary_only)
6479 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6480 safi, true);
6481 } else
6482 bgp_aggregate_med_match(aggregate, bgp, pi);
6483
6484 /* No mismatches, just quit. */
6485 if (!aggregate->med_mismatched)
6486 return;
6487
6488 /* Route summarization is disabled. */
6489 if (!aggregate->summary_only)
6490 return;
6491
6492 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6493}
6494
b5d58c32 6495/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6496void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6497 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6498{
6499 struct bgp_table *table;
9bcb3eef
DS
6500 struct bgp_dest *top;
6501 struct bgp_dest *dest;
d7c0a89a 6502 uint8_t origin;
d62a17ae 6503 struct aspath *aspath = NULL;
d62a17ae 6504 struct community *community = NULL;
3da2cc32 6505 struct ecommunity *ecommunity = NULL;
dd18c5a9 6506 struct lcommunity *lcommunity = NULL;
40381db7 6507 struct bgp_path_info *pi;
d62a17ae 6508 unsigned long match = 0;
d7c0a89a 6509 uint8_t atomic_aggregate = 0;
d62a17ae 6510
9f822fa2
S
6511 /* If the bgp instance is being deleted or self peer is deleted
6512 * then do not create aggregate route
6513 */
892fedb6
DA
6514 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6515 || (bgp->peer_self == NULL))
9f822fa2
S
6516 return;
6517
6aabb15d
RZ
6518 /* Initialize and test routes for MED difference. */
6519 if (aggregate->match_med)
6520 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6521
d62a17ae 6522 /* ORIGIN attribute: If at least one route among routes that are
6523 aggregated has ORIGIN with the value INCOMPLETE, then the
6524 aggregated route must have the ORIGIN attribute with the value
6525 INCOMPLETE. Otherwise, if at least one route among routes that
6526 are aggregated has ORIGIN with the value EGP, then the aggregated
6527 route must have the origin attribute with the value EGP. In all
6528 other case the value of the ORIGIN attribute of the aggregated
6529 route is INTERNAL. */
6530 origin = BGP_ORIGIN_IGP;
718e3744 6531
d62a17ae 6532 table = bgp->rib[afi][safi];
718e3744 6533
d62a17ae 6534 top = bgp_node_get(table, p);
9bcb3eef
DS
6535 for (dest = bgp_node_get(table, p); dest;
6536 dest = bgp_route_next_until(dest, top)) {
6537 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6538
9bcb3eef 6539 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6540 continue;
d62a17ae 6541
c2ff8b3e 6542 match = 0;
d62a17ae 6543
9bcb3eef 6544 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6545 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6546 continue;
718e3744 6547
40381db7 6548 if (pi->attr->flag
c2ff8b3e
DS
6549 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6550 atomic_aggregate = 1;
d62a17ae 6551
40381db7 6552 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6553 continue;
d62a17ae 6554
f273fef1
DS
6555 /*
6556 * summary-only aggregate route suppress
6557 * aggregated route announcements.
6aabb15d
RZ
6558 *
6559 * MED matching:
6560 * Don't create summaries if MED didn't match
6561 * otherwise neither the specific routes and the
6562 * aggregation will be announced.
f273fef1 6563 */
6aabb15d
RZ
6564 if (aggregate->summary_only
6565 && AGGREGATE_MED_VALID(aggregate)) {
40381db7 6566 (bgp_path_info_extra_get(pi))->suppress++;
9bcb3eef 6567 bgp_path_info_set_flag(dest, pi,
18ee8310 6568 BGP_PATH_ATTR_CHANGED);
c2ff8b3e 6569 match++;
d62a17ae 6570 }
c2ff8b3e
DS
6571
6572 aggregate->count++;
6573
f273fef1
DS
6574 /*
6575 * If at least one route among routes that are
6576 * aggregated has ORIGIN with the value INCOMPLETE,
6577 * then the aggregated route MUST have the ORIGIN
6578 * attribute with the value INCOMPLETE. Otherwise, if
6579 * at least one route among routes that are aggregated
6580 * has ORIGIN with the value EGP, then the aggregated
6581 * route MUST have the ORIGIN attribute with the value
6582 * EGP.
6583 */
fc968841
NT
6584 switch (pi->attr->origin) {
6585 case BGP_ORIGIN_INCOMPLETE:
6586 aggregate->incomplete_origin_count++;
6587 break;
6588 case BGP_ORIGIN_EGP:
6589 aggregate->egp_origin_count++;
6590 break;
6591 default:
6592 /*Do nothing.
6593 */
6594 break;
6595 }
c2ff8b3e
DS
6596
6597 if (!aggregate->as_set)
6598 continue;
6599
f273fef1
DS
6600 /*
6601 * as-set aggregate route generate origin, as path,
6602 * and community aggregation.
6603 */
fc968841
NT
6604 /* Compute aggregate route's as-path.
6605 */
ef51a7d8 6606 bgp_compute_aggregate_aspath_hash(aggregate,
6607 pi->attr->aspath);
c2ff8b3e 6608
fc968841
NT
6609 /* Compute aggregate route's community.
6610 */
6611 if (pi->attr->community)
21fec674 6612 bgp_compute_aggregate_community_hash(
fc968841
NT
6613 aggregate,
6614 pi->attr->community);
dd18c5a9 6615
fc968841
NT
6616 /* Compute aggregate route's extended community.
6617 */
6618 if (pi->attr->ecommunity)
4edd83f9 6619 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
6620 aggregate,
6621 pi->attr->ecommunity);
6622
6623 /* Compute aggregate route's large community.
6624 */
6625 if (pi->attr->lcommunity)
f1eb1f05 6626 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
6627 aggregate,
6628 pi->attr->lcommunity);
d62a17ae 6629 }
c2ff8b3e 6630 if (match)
9bcb3eef 6631 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 6632 }
21fec674 6633 if (aggregate->as_set) {
ef51a7d8 6634 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 6635 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 6636 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 6637 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 6638 }
6639
f1eb1f05 6640
9bcb3eef 6641 bgp_dest_unlock_node(top);
718e3744 6642
718e3744 6643
fc968841
NT
6644 if (aggregate->incomplete_origin_count > 0)
6645 origin = BGP_ORIGIN_INCOMPLETE;
6646 else if (aggregate->egp_origin_count > 0)
6647 origin = BGP_ORIGIN_EGP;
d62a17ae 6648
229757f1
DA
6649 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6650 origin = aggregate->origin;
6651
fc968841
NT
6652 if (aggregate->as_set) {
6653 if (aggregate->aspath)
6654 /* Retrieve aggregate route's as-path.
6655 */
6656 aspath = aspath_dup(aggregate->aspath);
d62a17ae 6657
fc968841
NT
6658 if (aggregate->community)
6659 /* Retrieve aggregate route's community.
6660 */
6661 community = community_dup(aggregate->community);
3da2cc32 6662
fc968841
NT
6663 if (aggregate->ecommunity)
6664 /* Retrieve aggregate route's ecommunity.
6665 */
6666 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 6667
fc968841
NT
6668 if (aggregate->lcommunity)
6669 /* Retrieve aggregate route's lcommunity.
6670 */
6671 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 6672 }
718e3744 6673
c701010e 6674 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
6675 ecommunity, lcommunity, atomic_aggregate,
6676 aggregate);
718e3744 6677}
6678
5f040085
DS
6679void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
6680 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
6681{
6682 struct bgp_table *table;
9bcb3eef
DS
6683 struct bgp_dest *top;
6684 struct bgp_dest *dest;
40381db7 6685 struct bgp_path_info *pi;
3b7db173
DS
6686 unsigned long match;
6687
6688 table = bgp->rib[afi][safi];
6689
6690 /* If routes exists below this node, generate aggregate routes. */
6691 top = bgp_node_get(table, p);
9bcb3eef
DS
6692 for (dest = bgp_node_get(table, p); dest;
6693 dest = bgp_route_next_until(dest, top)) {
6694 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6695
9bcb3eef 6696 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
6697 continue;
6698 match = 0;
6699
9bcb3eef 6700 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6701 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
6702 continue;
6703
40381db7 6704 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
6705 continue;
6706
6aabb15d
RZ
6707 if (aggregate->summary_only && pi->extra
6708 && AGGREGATE_MED_VALID(aggregate)) {
40381db7 6709 pi->extra->suppress--;
3b7db173 6710
40381db7 6711 if (pi->extra->suppress == 0) {
18ee8310 6712 bgp_path_info_set_flag(
9bcb3eef
DS
6713 dest, pi,
6714 BGP_PATH_ATTR_CHANGED);
3b7db173
DS
6715 match++;
6716 }
6717 }
6718 aggregate->count--;
fc968841
NT
6719
6720 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6721 aggregate->incomplete_origin_count--;
6722 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6723 aggregate->egp_origin_count--;
6724
6725 if (aggregate->as_set) {
6726 /* Remove as-path from aggregate.
6727 */
ef51a7d8 6728 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
6729 aggregate,
6730 pi->attr->aspath);
6731
6732 if (pi->attr->community)
6733 /* Remove community from aggregate.
6734 */
21fec674 6735 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
6736 aggregate,
6737 pi->attr->community);
6738
6739 if (pi->attr->ecommunity)
6740 /* Remove ecommunity from aggregate.
6741 */
4edd83f9 6742 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
6743 aggregate,
6744 pi->attr->ecommunity);
6745
6746 if (pi->attr->lcommunity)
6747 /* Remove lcommunity from aggregate.
6748 */
f1eb1f05 6749 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
6750 aggregate,
6751 pi->attr->lcommunity);
6752 }
3b7db173
DS
6753 }
6754
6755 /* If this node was suppressed, process the change. */
6756 if (match)
9bcb3eef 6757 bgp_process(bgp, dest, afi, safi);
3b7db173 6758 }
f1eb1f05 6759 if (aggregate->as_set) {
ef51a7d8 6760 aspath_free(aggregate->aspath);
6761 aggregate->aspath = NULL;
21fec674 6762 if (aggregate->community)
6763 community_free(&aggregate->community);
4edd83f9 6764 if (aggregate->ecommunity)
6765 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 6766 if (aggregate->lcommunity)
6767 lcommunity_free(&aggregate->lcommunity);
6768 }
6769
9bcb3eef 6770 bgp_dest_unlock_node(top);
3b7db173 6771}
718e3744 6772
5f040085
DS
6773static void bgp_add_route_to_aggregate(struct bgp *bgp,
6774 const struct prefix *aggr_p,
fc968841
NT
6775 struct bgp_path_info *pinew, afi_t afi,
6776 safi_t safi,
6777 struct bgp_aggregate *aggregate)
6778{
6779 uint8_t origin;
6780 struct aspath *aspath = NULL;
6781 uint8_t atomic_aggregate = 0;
6782 struct community *community = NULL;
6783 struct ecommunity *ecommunity = NULL;
6784 struct lcommunity *lcommunity = NULL;
6785
6786 /* ORIGIN attribute: If at least one route among routes that are
6787 * aggregated has ORIGIN with the value INCOMPLETE, then the
6788 * aggregated route must have the ORIGIN attribute with the value
6789 * INCOMPLETE. Otherwise, if at least one route among routes that
6790 * are aggregated has ORIGIN with the value EGP, then the aggregated
6791 * route must have the origin attribute with the value EGP. In all
6792 * other case the value of the ORIGIN attribute of the aggregated
6793 * route is INTERNAL.
6794 */
6795 origin = BGP_ORIGIN_IGP;
6796
6797 aggregate->count++;
6798
6aabb15d
RZ
6799 /*
6800 * This must be called before `summary` check to avoid
6801 * "suppressing" twice.
6802 */
6803 if (aggregate->match_med)
6804 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
6805 pinew, true);
6806
6807 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
fc968841
NT
6808 (bgp_path_info_extra_get(pinew))->suppress++;
6809
6810 switch (pinew->attr->origin) {
6811 case BGP_ORIGIN_INCOMPLETE:
6812 aggregate->incomplete_origin_count++;
6813 break;
6814 case BGP_ORIGIN_EGP:
6815 aggregate->egp_origin_count++;
6816 break;
6817 default:
6818 /* Do nothing.
6819 */
6820 break;
6821 }
6822
6823 if (aggregate->incomplete_origin_count > 0)
6824 origin = BGP_ORIGIN_INCOMPLETE;
6825 else if (aggregate->egp_origin_count > 0)
6826 origin = BGP_ORIGIN_EGP;
6827
229757f1
DA
6828 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6829 origin = aggregate->origin;
6830
fc968841
NT
6831 if (aggregate->as_set) {
6832 /* Compute aggregate route's as-path.
6833 */
6834 bgp_compute_aggregate_aspath(aggregate,
6835 pinew->attr->aspath);
6836
6837 /* Compute aggregate route's community.
6838 */
6839 if (pinew->attr->community)
6840 bgp_compute_aggregate_community(
6841 aggregate,
6842 pinew->attr->community);
6843
6844 /* Compute aggregate route's extended community.
6845 */
6846 if (pinew->attr->ecommunity)
6847 bgp_compute_aggregate_ecommunity(
6848 aggregate,
6849 pinew->attr->ecommunity);
6850
6851 /* Compute aggregate route's large community.
6852 */
6853 if (pinew->attr->lcommunity)
6854 bgp_compute_aggregate_lcommunity(
6855 aggregate,
6856 pinew->attr->lcommunity);
6857
6858 /* Retrieve aggregate route's as-path.
6859 */
6860 if (aggregate->aspath)
6861 aspath = aspath_dup(aggregate->aspath);
6862
6863 /* Retrieve aggregate route's community.
6864 */
6865 if (aggregate->community)
6866 community = community_dup(aggregate->community);
6867
6868 /* Retrieve aggregate route's ecommunity.
6869 */
6870 if (aggregate->ecommunity)
6871 ecommunity = ecommunity_dup(aggregate->ecommunity);
6872
6873 /* Retrieve aggregate route's lcommunity.
6874 */
6875 if (aggregate->lcommunity)
6876 lcommunity = lcommunity_dup(aggregate->lcommunity);
6877 }
6878
6879 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6880 aspath, community, ecommunity,
6881 lcommunity, atomic_aggregate, aggregate);
6882}
6883
6884static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
6885 safi_t safi,
6886 struct bgp_path_info *pi,
6887 struct bgp_aggregate *aggregate,
5f040085 6888 const struct prefix *aggr_p)
fc968841
NT
6889{
6890 uint8_t origin;
6891 struct aspath *aspath = NULL;
6892 uint8_t atomic_aggregate = 0;
6893 struct community *community = NULL;
6894 struct ecommunity *ecommunity = NULL;
6895 struct lcommunity *lcommunity = NULL;
6896 unsigned long match = 0;
6897
6898 if (BGP_PATH_HOLDDOWN(pi))
6899 return;
6900
6901 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6902 return;
6903
6aabb15d
RZ
6904 if (aggregate->summary_only && pi->extra && pi->extra->suppress > 0
6905 && AGGREGATE_MED_VALID(aggregate)) {
fc968841
NT
6906 pi->extra->suppress--;
6907
6908 if (pi->extra->suppress == 0) {
6909 bgp_path_info_set_flag(pi->net, pi,
6910 BGP_PATH_ATTR_CHANGED);
6911 match++;
6912 }
6913 }
6914
6aabb15d
RZ
6915 /*
6916 * This must be called after `summary` check to avoid
6917 * "unsuppressing" twice.
6918 */
6919 if (aggregate->match_med)
6920 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
6921 true);
6922
fc968841
NT
6923 if (aggregate->count > 0)
6924 aggregate->count--;
6925
6926 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
6927 aggregate->incomplete_origin_count--;
6928 else if (pi->attr->origin == BGP_ORIGIN_EGP)
6929 aggregate->egp_origin_count--;
6930
6931 if (aggregate->as_set) {
6932 /* Remove as-path from aggregate.
6933 */
6934 bgp_remove_aspath_from_aggregate(aggregate,
6935 pi->attr->aspath);
6936
6937 if (pi->attr->community)
6938 /* Remove community from aggregate.
6939 */
6940 bgp_remove_community_from_aggregate(
6941 aggregate,
6942 pi->attr->community);
6943
6944 if (pi->attr->ecommunity)
6945 /* Remove ecommunity from aggregate.
6946 */
6947 bgp_remove_ecommunity_from_aggregate(
6948 aggregate,
6949 pi->attr->ecommunity);
6950
6951 if (pi->attr->lcommunity)
6952 /* Remove lcommunity from aggregate.
6953 */
6954 bgp_remove_lcommunity_from_aggregate(
6955 aggregate,
6956 pi->attr->lcommunity);
6957 }
6958
6959 /* If this node was suppressed, process the change. */
6960 if (match)
6961 bgp_process(bgp, pi->net, afi, safi);
6962
6963 origin = BGP_ORIGIN_IGP;
6964 if (aggregate->incomplete_origin_count > 0)
6965 origin = BGP_ORIGIN_INCOMPLETE;
6966 else if (aggregate->egp_origin_count > 0)
6967 origin = BGP_ORIGIN_EGP;
6968
229757f1
DA
6969 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
6970 origin = aggregate->origin;
6971
fc968841
NT
6972 if (aggregate->as_set) {
6973 /* Retrieve aggregate route's as-path.
6974 */
6975 if (aggregate->aspath)
6976 aspath = aspath_dup(aggregate->aspath);
6977
6978 /* Retrieve aggregate route's community.
6979 */
6980 if (aggregate->community)
6981 community = community_dup(aggregate->community);
6982
6983 /* Retrieve aggregate route's ecommunity.
6984 */
6985 if (aggregate->ecommunity)
6986 ecommunity = ecommunity_dup(aggregate->ecommunity);
6987
6988 /* Retrieve aggregate route's lcommunity.
6989 */
6990 if (aggregate->lcommunity)
6991 lcommunity = lcommunity_dup(aggregate->lcommunity);
6992 }
6993
6994 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
6995 aspath, community, ecommunity,
6996 lcommunity, atomic_aggregate, aggregate);
6997}
6998
5a1ae2c2 6999void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7000 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7001{
9bcb3eef
DS
7002 struct bgp_dest *child;
7003 struct bgp_dest *dest;
d62a17ae 7004 struct bgp_aggregate *aggregate;
7005 struct bgp_table *table;
718e3744 7006
d62a17ae 7007 table = bgp->aggregate[afi][safi];
f018db83 7008
d62a17ae 7009 /* No aggregates configured. */
7010 if (bgp_table_top_nolock(table) == NULL)
7011 return;
f018db83 7012
d62a17ae 7013 if (p->prefixlen == 0)
7014 return;
718e3744 7015
40381db7 7016 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7017 return;
718e3744 7018
d62a17ae 7019 child = bgp_node_get(table, p);
718e3744 7020
d62a17ae 7021 /* Aggregate address configuration check. */
9bcb3eef
DS
7022 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7023 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7024
9bcb3eef
DS
7025 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7026 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7027 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7028 aggregate);
d62a17ae 7029 }
b1e62edd 7030 }
9bcb3eef 7031 bgp_dest_unlock_node(child);
718e3744 7032}
7033
5a1ae2c2 7034void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7035 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7036{
9bcb3eef
DS
7037 struct bgp_dest *child;
7038 struct bgp_dest *dest;
d62a17ae 7039 struct bgp_aggregate *aggregate;
7040 struct bgp_table *table;
718e3744 7041
d62a17ae 7042 table = bgp->aggregate[afi][safi];
718e3744 7043
d62a17ae 7044 /* No aggregates configured. */
7045 if (bgp_table_top_nolock(table) == NULL)
7046 return;
718e3744 7047
d62a17ae 7048 if (p->prefixlen == 0)
7049 return;
718e3744 7050
d62a17ae 7051 child = bgp_node_get(table, p);
718e3744 7052
d62a17ae 7053 /* Aggregate address configuration check. */
9bcb3eef
DS
7054 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7055 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7056
9bcb3eef
DS
7057 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7058 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7059 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7060 aggregate, dest_p);
d62a17ae 7061 }
b1e62edd 7062 }
9bcb3eef 7063 bgp_dest_unlock_node(child);
d62a17ae 7064}
718e3744 7065
718e3744 7066/* Aggregate route attribute. */
7067#define AGGREGATE_SUMMARY_ONLY 1
7068#define AGGREGATE_AS_SET 1
fb29348a 7069#define AGGREGATE_AS_UNSET 0
718e3744 7070
229757f1
DA
7071static const char *bgp_origin2str(uint8_t origin)
7072{
7073 switch (origin) {
7074 case BGP_ORIGIN_IGP:
7075 return "igp";
7076 case BGP_ORIGIN_EGP:
7077 return "egp";
7078 case BGP_ORIGIN_INCOMPLETE:
7079 return "incomplete";
7080 }
7081 return "n/a";
7082}
7083
d62a17ae 7084static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7085 afi_t afi, safi_t safi)
718e3744 7086{
d62a17ae 7087 VTY_DECLVAR_CONTEXT(bgp, bgp);
7088 int ret;
7089 struct prefix p;
9bcb3eef 7090 struct bgp_dest *dest;
d62a17ae 7091 struct bgp_aggregate *aggregate;
718e3744 7092
d62a17ae 7093 /* Convert string to prefix structure. */
7094 ret = str2prefix(prefix_str, &p);
7095 if (!ret) {
7096 vty_out(vty, "Malformed prefix\n");
7097 return CMD_WARNING_CONFIG_FAILED;
7098 }
7099 apply_mask(&p);
7100
7101 /* Old configuration check. */
9bcb3eef
DS
7102 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
7103 if (!dest) {
d62a17ae 7104 vty_out(vty,
7105 "%% There is no aggregate-address configuration.\n");
7106 return CMD_WARNING_CONFIG_FAILED;
7107 }
f6269b4f 7108
9bcb3eef 7109 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
09990cdd 7110 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
dd18c5a9
DS
7111 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
7112 NULL, NULL, 0, aggregate);
d62a17ae 7113
7114 /* Unlock aggregate address configuration. */
9bcb3eef 7115 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7116
7117 if (aggregate->community)
7118 community_free(&aggregate->community);
7119
7120 if (aggregate->community_hash) {
7121 /* Delete all communities in the hash.
7122 */
7123 hash_clean(aggregate->community_hash,
7124 bgp_aggr_community_remove);
7125 /* Free up the community_hash.
7126 */
7127 hash_free(aggregate->community_hash);
7128 }
7129
7130 if (aggregate->ecommunity)
7131 ecommunity_free(&aggregate->ecommunity);
7132
7133 if (aggregate->ecommunity_hash) {
7134 /* Delete all ecommunities in the hash.
7135 */
7136 hash_clean(aggregate->ecommunity_hash,
7137 bgp_aggr_ecommunity_remove);
7138 /* Free up the ecommunity_hash.
7139 */
7140 hash_free(aggregate->ecommunity_hash);
7141 }
7142
7143 if (aggregate->lcommunity)
7144 lcommunity_free(&aggregate->lcommunity);
7145
7146 if (aggregate->lcommunity_hash) {
7147 /* Delete all lcommunities in the hash.
7148 */
7149 hash_clean(aggregate->lcommunity_hash,
7150 bgp_aggr_lcommunity_remove);
7151 /* Free up the lcommunity_hash.
7152 */
7153 hash_free(aggregate->lcommunity_hash);
7154 }
7155
7156 if (aggregate->aspath)
7157 aspath_free(aggregate->aspath);
7158
7159 if (aggregate->aspath_hash) {
7160 /* Delete all as-paths in the hash.
7161 */
7162 hash_clean(aggregate->aspath_hash,
7163 bgp_aggr_aspath_remove);
7164 /* Free up the aspath_hash.
7165 */
7166 hash_free(aggregate->aspath_hash);
7167 }
7168
d62a17ae 7169 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7170 bgp_dest_unlock_node(dest);
7171 bgp_dest_unlock_node(dest);
d62a17ae 7172
7173 return CMD_SUCCESS;
7174}
7175
7176static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
229757f1
DA
7177 safi_t safi, const char *rmap,
7178 uint8_t summary_only, uint8_t as_set,
6aabb15d 7179 uint8_t origin, bool match_med)
d62a17ae 7180{
7181 VTY_DECLVAR_CONTEXT(bgp, bgp);
7182 int ret;
7183 struct prefix p;
9bcb3eef 7184 struct bgp_dest *dest;
d62a17ae 7185 struct bgp_aggregate *aggregate;
fb29348a 7186 uint8_t as_set_new = as_set;
d62a17ae 7187
7188 /* Convert string to prefix structure. */
7189 ret = str2prefix(prefix_str, &p);
7190 if (!ret) {
7191 vty_out(vty, "Malformed prefix\n");
7192 return CMD_WARNING_CONFIG_FAILED;
7193 }
7194 apply_mask(&p);
7195
3624ac81
DS
7196 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
7197 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
7198 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7199 prefix_str);
7200 return CMD_WARNING_CONFIG_FAILED;
7201 }
7202
d62a17ae 7203 /* Old configuration check. */
9bcb3eef
DS
7204 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
7205 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7206
20894f50 7207 if (aggregate) {
d62a17ae 7208 vty_out(vty, "There is already same aggregate network.\n");
7209 /* try to remove the old entry */
7210 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
7211 if (ret) {
7212 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 7213 bgp_dest_unlock_node(dest);
d62a17ae 7214 return CMD_WARNING_CONFIG_FAILED;
7215 }
7216 }
718e3744 7217
d62a17ae 7218 /* Make aggregate address structure. */
7219 aggregate = bgp_aggregate_new();
7220 aggregate->summary_only = summary_only;
6aabb15d 7221 aggregate->match_med = match_med;
fb29348a
DA
7222
7223 /* Network operators MUST NOT locally generate any new
7224 * announcements containing AS_SET or AS_CONFED_SET. If they have
7225 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7226 * SHOULD withdraw those routes and re-announce routes for the
7227 * aggregate or component prefixes (i.e., the more-specific routes
7228 * subsumed by the previously aggregated route) without AS_SET
7229 * or AS_CONFED_SET in the updates.
7230 */
7f972cd8 7231 if (bgp->reject_as_sets) {
fb29348a
DA
7232 if (as_set == AGGREGATE_AS_SET) {
7233 as_set_new = AGGREGATE_AS_UNSET;
7234 zlog_warn(
63efca0e 7235 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a
DA
7236 __func__);
7237 vty_out(vty,
7238 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7239 }
7240 }
7241
7242 aggregate->as_set = as_set_new;
d62a17ae 7243 aggregate->safi = safi;
229757f1
DA
7244 /* Override ORIGIN attribute if defined.
7245 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7246 * to IGP which is not what rfc4271 says.
7247 * This enables the same behavior, optionally.
7248 */
7249 aggregate->origin = origin;
20894f50
DA
7250
7251 if (rmap) {
7252 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7253 route_map_counter_decrement(aggregate->rmap.map);
7254 aggregate->rmap.name =
7255 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7256 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7257 route_map_counter_increment(aggregate->rmap.map);
7258 }
9bcb3eef 7259 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7260
d62a17ae 7261 /* Aggregate address insert into BGP routing table. */
fc968841 7262 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 7263
d62a17ae 7264 return CMD_SUCCESS;
718e3744 7265}
7266
554b3b10
RZ
7267DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
7268 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7269 "as-set$as_set_s"
7270 "|summary-only$summary_only"
7271 "|route-map WORD$rmap_name"
7272 "|origin <egp|igp|incomplete>$origin_s"
6aabb15d 7273 "|matching-MED-only$match_med"
554b3b10
RZ
7274 "}",
7275 NO_STR
7276 "Configure BGP aggregate entries\n"
7277 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
7278 "Generate AS set path information\n"
7279 "Filter more specific routes from updates\n"
7280 "Apply route map to aggregate network\n"
7281 "Route map name\n"
7282 "BGP origin code\n"
7283 "Remote EGP\n"
7284 "Local IGP\n"
6aabb15d
RZ
7285 "Unknown heritage\n"
7286 "Only aggregate routes with matching MED\n")
554b3b10
RZ
7287{
7288 const char *prefix_s = NULL;
7289 safi_t safi = bgp_node_safi(vty);
229757f1 7290 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
554b3b10
RZ
7291 int as_set = AGGREGATE_AS_UNSET;
7292 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7293
554b3b10
RZ
7294 if (addr_str) {
7295 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
7296 == 0) {
7297 vty_out(vty, "%% Inconsistent address and mask\n");
7298 return CMD_WARNING_CONFIG_FAILED;
7299 }
7300 prefix_s = prefix_buf;
7301 } else
7302 prefix_s = prefix_str;
718e3744 7303
554b3b10
RZ
7304 if (origin_s) {
7305 if (strcmp(origin_s, "egp") == 0)
229757f1 7306 origin = BGP_ORIGIN_EGP;
554b3b10
RZ
7307 else if (strcmp(origin_s, "igp") == 0)
7308 origin = BGP_ORIGIN_IGP;
7309 else if (strcmp(origin_s, "incomplete") == 0)
229757f1
DA
7310 origin = BGP_ORIGIN_INCOMPLETE;
7311 }
7312
554b3b10
RZ
7313 if (as_set_s)
7314 as_set = AGGREGATE_AS_SET;
7315
7316 /* Handle configuration removal, otherwise installation. */
7317 if (no)
7318 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
7319
7320 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
6aabb15d
RZ
7321 summary_only != NULL, as_set, origin,
7322 match_med != NULL);
554b3b10
RZ
7323}
7324
7325DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
7326 "[no] aggregate-address X:X::X:X/M$prefix {"
7327 "as-set$as_set_s"
7328 "|summary-only$summary_only"
7329 "|route-map WORD$rmap_name"
7330 "|origin <egp|igp|incomplete>$origin_s"
6aabb15d 7331 "|matching-MED-only$match_med"
554b3b10
RZ
7332 "}",
7333 NO_STR
7334 "Configure BGP aggregate entries\n"
7335 "Aggregate prefix\n"
7336 "Generate AS set path information\n"
7337 "Filter more specific routes from updates\n"
7338 "Apply route map to aggregate network\n"
7339 "Route map name\n"
7340 "BGP origin code\n"
7341 "Remote EGP\n"
7342 "Local IGP\n"
6aabb15d
RZ
7343 "Unknown heritage\n"
7344 "Only aggregate routes with matching MED\n")
718e3744 7345{
229757f1 7346 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
554b3b10 7347 int as_set = AGGREGATE_AS_UNSET;
5101fece 7348
554b3b10
RZ
7349 if (origin_s) {
7350 if (strcmp(origin_s, "egp") == 0)
229757f1 7351 origin = BGP_ORIGIN_EGP;
554b3b10
RZ
7352 else if (strcmp(origin_s, "igp") == 0)
7353 origin = BGP_ORIGIN_IGP;
7354 else if (strcmp(origin_s, "incomplete") == 0)
229757f1
DA
7355 origin = BGP_ORIGIN_INCOMPLETE;
7356 }
7357
554b3b10
RZ
7358 if (as_set_s)
7359 as_set = AGGREGATE_AS_SET;
718e3744 7360
554b3b10
RZ
7361 /* Handle configuration removal, otherwise installation. */
7362 if (no)
7363 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
7364 SAFI_UNICAST);
7365
7366 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
7367 rmap_name, summary_only != NULL, as_set,
6aabb15d 7368 origin, match_med != NULL);
718e3744 7369}
7370
718e3744 7371/* Redistribute route treatment. */
d62a17ae 7372void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7373 const union g_addr *nexthop, ifindex_t ifindex,
7374 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7375 uint8_t type, unsigned short instance,
7376 route_tag_t tag)
d62a17ae 7377{
4b7e6066 7378 struct bgp_path_info *new;
40381db7
DS
7379 struct bgp_path_info *bpi;
7380 struct bgp_path_info rmap_path;
9bcb3eef 7381 struct bgp_dest *bn;
d62a17ae 7382 struct attr attr;
7383 struct attr *new_attr;
7384 afi_t afi;
b68885f9 7385 route_map_result_t ret;
d62a17ae 7386 struct bgp_redist *red;
7387
7388 /* Make default attribute. */
7389 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7390 /*
7391 * This must not be NULL to satisfy Coverity SA
7392 */
7393 assert(attr.aspath);
9de1f7ff 7394
a4d82a8a 7395 switch (nhtype) {
9de1f7ff
DS
7396 case NEXTHOP_TYPE_IFINDEX:
7397 break;
7398 case NEXTHOP_TYPE_IPV4:
7399 case NEXTHOP_TYPE_IPV4_IFINDEX:
7400 attr.nexthop = nexthop->ipv4;
7401 break;
7402 case NEXTHOP_TYPE_IPV6:
7403 case NEXTHOP_TYPE_IPV6_IFINDEX:
7404 attr.mp_nexthop_global = nexthop->ipv6;
7405 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7406 break;
7407 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7408 switch (p->family) {
7409 case AF_INET:
9de1f7ff 7410 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7411 break;
7412 case AF_INET6:
9de1f7ff
DS
7413 memset(&attr.mp_nexthop_global, 0,
7414 sizeof(attr.mp_nexthop_global));
74489921 7415 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 7416 break;
74489921 7417 }
9de1f7ff 7418 break;
d62a17ae 7419 }
74489921 7420 attr.nh_ifindex = ifindex;
f04a80a5 7421
d62a17ae 7422 attr.med = metric;
7423 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
7424 attr.tag = tag;
718e3744 7425
d62a17ae 7426 afi = family2afi(p->family);
6aeb9e78 7427
d62a17ae 7428 red = bgp_redist_lookup(bgp, afi, type, instance);
7429 if (red) {
7430 struct attr attr_new;
718e3744 7431
d62a17ae 7432 /* Copy attribute for modification. */
6f4f49b2 7433 attr_new = attr;
718e3744 7434
d62a17ae 7435 if (red->redist_metric_flag)
7436 attr_new.med = red->redist_metric;
718e3744 7437
d62a17ae 7438 /* Apply route-map. */
7439 if (red->rmap.name) {
40381db7
DS
7440 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
7441 rmap_path.peer = bgp->peer_self;
7442 rmap_path.attr = &attr_new;
718e3744 7443
d62a17ae 7444 SET_FLAG(bgp->peer_self->rmap_type,
7445 PEER_RMAP_TYPE_REDISTRIBUTE);
7446
7447 ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
40381db7 7448 &rmap_path);
d62a17ae 7449
7450 bgp->peer_self->rmap_type = 0;
7451
7452 if (ret == RMAP_DENYMATCH) {
7453 /* Free uninterned attribute. */
7454 bgp_attr_flush(&attr_new);
7455
7456 /* Unintern original. */
7457 aspath_unintern(&attr.aspath);
7458 bgp_redistribute_delete(bgp, p, type, instance);
7459 return;
7460 }
7461 }
7462
637e5ba4 7463 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
7464 bgp_attr_add_gshut_community(&attr_new);
7465
d62a17ae 7466 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7467 SAFI_UNICAST, p, NULL);
7468
7469 new_attr = bgp_attr_intern(&attr_new);
7470
9bcb3eef 7471 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
7472 if (bpi->peer == bgp->peer_self
7473 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 7474 break;
7475
40381db7 7476 if (bpi) {
d62a17ae 7477 /* Ensure the (source route) type is updated. */
40381db7
DS
7478 bpi->type = type;
7479 if (attrhash_cmp(bpi->attr, new_attr)
7480 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 7481 bgp_attr_unintern(&new_attr);
7482 aspath_unintern(&attr.aspath);
9bcb3eef 7483 bgp_dest_unlock_node(bn);
d62a17ae 7484 return;
7485 } else {
7486 /* The attribute is changed. */
40381db7 7487 bgp_path_info_set_flag(bn, bpi,
18ee8310 7488 BGP_PATH_ATTR_CHANGED);
d62a17ae 7489
7490 /* Rewrite BGP route information. */
40381db7
DS
7491 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
7492 bgp_path_info_restore(bn, bpi);
d62a17ae 7493 else
40381db7
DS
7494 bgp_aggregate_decrement(
7495 bgp, p, bpi, afi, SAFI_UNICAST);
7496 bgp_attr_unintern(&bpi->attr);
7497 bpi->attr = new_attr;
7498 bpi->uptime = bgp_clock();
d62a17ae 7499
7500 /* Process change. */
40381db7 7501 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 7502 SAFI_UNICAST);
7503 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 7504 bgp_dest_unlock_node(bn);
d62a17ae 7505 aspath_unintern(&attr.aspath);
ddb5b488
PZ
7506
7507 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7508 || (bgp->inst_type
7509 == BGP_INSTANCE_TYPE_DEFAULT)) {
7510
7511 vpn_leak_from_vrf_update(
40381db7 7512 bgp_get_default(), bgp, bpi);
ddb5b488 7513 }
d62a17ae 7514 return;
7515 }
7516 }
7517
7518 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
7519 bgp->peer_self, new_attr, bn);
1defdda8 7520 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 7521
7522 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 7523 bgp_path_info_add(bn, new);
9bcb3eef 7524 bgp_dest_unlock_node(bn);
d62a17ae 7525 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
7526
7527 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7528 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7529
7530 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
7531 }
d62a17ae 7532 }
7533
7534 /* Unintern original. */
7535 aspath_unintern(&attr.aspath);
718e3744 7536}
7537
d7c0a89a
QY
7538void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
7539 unsigned short instance)
718e3744 7540{
d62a17ae 7541 afi_t afi;
9bcb3eef 7542 struct bgp_dest *dest;
40381db7 7543 struct bgp_path_info *pi;
d62a17ae 7544 struct bgp_redist *red;
718e3744 7545
d62a17ae 7546 afi = family2afi(p->family);
718e3744 7547
d62a17ae 7548 red = bgp_redist_lookup(bgp, afi, type, instance);
7549 if (red) {
9bcb3eef
DS
7550 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
7551 SAFI_UNICAST, p, NULL);
d62a17ae 7552
9bcb3eef 7553 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 7554 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 7555 break;
7556
40381db7 7557 if (pi) {
ddb5b488
PZ
7558 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7559 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7560
7561 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7562 bgp, pi);
ddb5b488 7563 }
40381db7 7564 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7565 bgp_path_info_delete(dest, pi);
7566 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7567 }
9bcb3eef 7568 bgp_dest_unlock_node(dest);
d62a17ae 7569 }
7570}
7571
7572/* Withdraw specified route type's route. */
7573void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 7574 unsigned short instance)
d62a17ae 7575{
9bcb3eef 7576 struct bgp_dest *dest;
40381db7 7577 struct bgp_path_info *pi;
d62a17ae 7578 struct bgp_table *table;
7579
7580 table = bgp->rib[afi][SAFI_UNICAST];
7581
9bcb3eef
DS
7582 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
7583 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
7584 if (pi->peer == bgp->peer_self && pi->type == type
7585 && pi->instance == instance)
d62a17ae 7586 break;
7587
40381db7 7588 if (pi) {
ddb5b488
PZ
7589 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
7590 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
7591
7592 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 7593 bgp, pi);
ddb5b488 7594 }
9bcb3eef 7595 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 7596 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
7597 bgp_path_info_delete(dest, pi);
7598 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 7599 }
718e3744 7600 }
718e3744 7601}
6b0655a2 7602
718e3744 7603/* Static function to display route. */
bd494ec5 7604static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 7605 json_object *json, bool wide)
718e3744 7606{
be054588 7607 int len = 0;
d62a17ae 7608 char buf[BUFSIZ];
50e05855 7609 char buf2[BUFSIZ];
718e3744 7610
d62a17ae 7611 if (p->family == AF_INET) {
c6462ff4 7612 if (!json) {
89e5e9f0
PM
7613 len = vty_out(
7614 vty, "%s/%d",
7615 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7616 p->prefixlen);
c6462ff4
MK
7617 } else {
7618 json_object_string_add(json, "prefix",
7619 inet_ntop(p->family,
7620 &p->u.prefix, buf,
7621 BUFSIZ));
7622 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 7623 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 7624 json_object_string_add(json, "network", buf2);
c6462ff4 7625 }
d62a17ae 7626 } else if (p->family == AF_ETHERNET) {
b03b8898
DS
7627 prefix2str(p, buf, PREFIX_STRLEN);
7628 len = vty_out(vty, "%s", buf);
7629 } else if (p->family == AF_EVPN) {
57f7feb6 7630 if (!json)
60466a63
QY
7631 len = vty_out(
7632 vty, "%s",
7633 bgp_evpn_route2str((struct prefix_evpn *)p, buf,
7634 BUFSIZ));
57f7feb6 7635 else
60466a63 7636 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
7637 } else if (p->family == AF_FLOWSPEC) {
7638 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
7639 json ?
7640 NLRI_STRING_FORMAT_JSON_SIMPLE :
7641 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 7642 } else {
c6462ff4 7643 if (!json)
60466a63
QY
7644 len = vty_out(
7645 vty, "%s/%d",
7646 inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ),
7647 p->prefixlen);
50e05855
AD
7648 else {
7649 json_object_string_add(json, "prefix",
7650 inet_ntop(p->family,
7651 &p->u.prefix, buf,
7652 BUFSIZ));
7653 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
7654 prefix2str(p, buf2, PREFIX_STRLEN);
7655 json_object_string_add(json, "network", buf2);
7656 }
9c92b5f7 7657 }
d62a17ae 7658
9c92b5f7 7659 if (!json) {
ae248832 7660 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
7661 if (len < 1)
7662 vty_out(vty, "\n%*s", 20, " ");
7663 else
7664 vty_out(vty, "%*s", len, " ");
7665 }
718e3744 7666}
7667
d62a17ae 7668enum bgp_display_type {
7669 normal_list,
718e3744 7670};
7671
18ee8310 7672/* Print the short form route status for a bgp_path_info */
4b7e6066 7673static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 7674 struct bgp_path_info *path,
d62a17ae 7675 json_object *json_path)
718e3744 7676{
d62a17ae 7677 if (json_path) {
b05a1c8b 7678
d62a17ae 7679 /* Route status display. */
9b6d8fcf 7680 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7681 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 7682
9b6d8fcf 7683 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7684 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 7685
9b6d8fcf 7686 if (path->extra && path->extra->suppress)
d62a17ae 7687 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 7688
9b6d8fcf
DS
7689 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7690 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7691 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 7692
d62a17ae 7693 /* Selected */
9b6d8fcf 7694 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7695 json_object_boolean_true_add(json_path, "history");
b05a1c8b 7696
9b6d8fcf 7697 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7698 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 7699
9b6d8fcf 7700 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7701 json_object_boolean_true_add(json_path, "bestpath");
b05a1c8b 7702
9b6d8fcf 7703 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7704 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 7705
d62a17ae 7706 /* Internal route. */
9b6d8fcf
DS
7707 if ((path->peer->as)
7708 && (path->peer->as == path->peer->local_as))
d62a17ae 7709 json_object_string_add(json_path, "pathFrom",
7710 "internal");
7711 else
7712 json_object_string_add(json_path, "pathFrom",
7713 "external");
b05a1c8b 7714
d62a17ae 7715 return;
7716 }
b05a1c8b 7717
d62a17ae 7718 /* Route status display. */
9b6d8fcf 7719 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 7720 vty_out(vty, "R");
9b6d8fcf 7721 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 7722 vty_out(vty, "S");
9b6d8fcf 7723 else if (path->extra && path->extra->suppress)
d62a17ae 7724 vty_out(vty, "s");
9b6d8fcf
DS
7725 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
7726 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7727 vty_out(vty, "*");
7728 else
7729 vty_out(vty, " ");
7730
7731 /* Selected */
9b6d8fcf 7732 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 7733 vty_out(vty, "h");
9b6d8fcf 7734 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 7735 vty_out(vty, "d");
9b6d8fcf 7736 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 7737 vty_out(vty, ">");
9b6d8fcf 7738 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 7739 vty_out(vty, "=");
7740 else
7741 vty_out(vty, " ");
718e3744 7742
d62a17ae 7743 /* Internal route. */
9b6d8fcf
DS
7744 if (path->peer && (path->peer->as)
7745 && (path->peer->as == path->peer->local_as))
d62a17ae 7746 vty_out(vty, "i");
7747 else
7748 vty_out(vty, " ");
b40d939b 7749}
7750
2ba93fd6
DA
7751static char *bgp_nexthop_hostname(struct peer *peer,
7752 struct bgp_nexthop_cache *bnc)
25b5da8d 7753{
892fedb6 7754 if (peer->hostname
aef999a2 7755 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
7756 return peer->hostname;
7757 return NULL;
7758}
7759
b40d939b 7760/* called from terminal list command */
bd494ec5 7761void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 7762 struct bgp_path_info *path, int display, safi_t safi,
ae248832 7763 json_object *json_paths, bool wide)
d62a17ae 7764{
aef999a2 7765 int len;
515c2602 7766 struct attr *attr = path->attr;
d62a17ae 7767 json_object *json_path = NULL;
7768 json_object *json_nexthops = NULL;
7769 json_object *json_nexthop_global = NULL;
7770 json_object *json_nexthop_ll = NULL;
6f214dd3 7771 json_object *json_ext_community = NULL;
9df8b37c 7772 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 7773 bool nexthop_self =
9b6d8fcf 7774 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 7775 bool nexthop_othervrf = false;
43089216 7776 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 7777 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
7778 char *nexthop_hostname =
7779 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 7780 char esi_buf[ESI_STR_LEN];
d62a17ae 7781
7782 if (json_paths)
7783 json_path = json_object_new_object();
7784
7785 /* short status lead text */
9b6d8fcf 7786 route_vty_short_status_out(vty, path, json_path);
d62a17ae 7787
7788 if (!json_paths) {
7789 /* print prefix and mask */
7790 if (!display)
ae248832 7791 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 7792 else
ae248832 7793 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 7794 } else {
ae248832 7795 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 7796 }
47fc97cc 7797
9df8b37c
PZ
7798 /*
7799 * If vrf id of nexthop is different from that of prefix,
7800 * set up printable string to append
7801 */
9b6d8fcf 7802 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
7803 const char *self = "";
7804
7805 if (nexthop_self)
7806 self = "<";
7807
7808 nexthop_othervrf = true;
9b6d8fcf 7809 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 7810
9b6d8fcf 7811 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
7812 snprintf(vrf_id_str, sizeof(vrf_id_str),
7813 "@%s%s", VRFID_NONE_STR, self);
7814 else
7815 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 7816 path->extra->bgp_orig->vrf_id, self);
9df8b37c 7817
9b6d8fcf
DS
7818 if (path->extra->bgp_orig->inst_type
7819 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 7820
9b6d8fcf 7821 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
7822 } else {
7823 const char *self = "";
7824
7825 if (nexthop_self)
7826 self = "<";
7827
7828 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
7829 }
7830
445c2480
DS
7831 /*
7832 * For ENCAP and EVPN routes, nexthop address family is not
7833 * neccessarily the same as the prefix address family.
7834 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
7835 * EVPN routes are also exchanged with a MP nexthop. Currently,
7836 * this
7837 * is only IPv4, the value will be present in either
7838 * attr->nexthop or
7839 * attr->mp_nexthop_global_in
7840 */
7841 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
7842 char buf[BUFSIZ];
7843 char nexthop[128];
7844 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
7845
7846 switch (af) {
7847 case AF_INET:
772270f3
QY
7848 snprintf(nexthop, sizeof(nexthop), "%s",
7849 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
7850 BUFSIZ));
445c2480
DS
7851 break;
7852 case AF_INET6:
772270f3
QY
7853 snprintf(nexthop, sizeof(nexthop), "%s",
7854 inet_ntop(af, &attr->mp_nexthop_global, buf,
7855 BUFSIZ));
445c2480
DS
7856 break;
7857 default:
772270f3 7858 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 7859 break;
d62a17ae 7860 }
d62a17ae 7861
445c2480
DS
7862 if (json_paths) {
7863 json_nexthop_global = json_object_new_object();
7864
515c2602
DA
7865 json_object_string_add(json_nexthop_global, "ip",
7866 nexthop);
7867
939a97f4 7868 if (path->peer->hostname)
515c2602
DA
7869 json_object_string_add(json_nexthop_global,
7870 "hostname",
939a97f4 7871 path->peer->hostname);
515c2602
DA
7872
7873 json_object_string_add(json_nexthop_global, "afi",
7874 (af == AF_INET) ? "ipv4"
7875 : "ipv6");
445c2480
DS
7876 json_object_boolean_true_add(json_nexthop_global,
7877 "used");
aef999a2
DA
7878 } else {
7879 if (nexthop_hostname)
7880 len = vty_out(vty, "%s(%s)%s", nexthop,
7881 nexthop_hostname, vrf_id_str);
7882 else
7883 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
7884
ae248832 7885 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7886 if (len < 1)
7887 vty_out(vty, "\n%*s", 36, " ");
7888 else
7889 vty_out(vty, "%*s", len, " ");
7890 }
445c2480
DS
7891 } else if (safi == SAFI_EVPN) {
7892 if (json_paths) {
7893 json_nexthop_global = json_object_new_object();
7894
515c2602
DA
7895 json_object_string_add(json_nexthop_global, "ip",
7896 inet_ntoa(attr->nexthop));
7897
939a97f4 7898 if (path->peer->hostname)
515c2602
DA
7899 json_object_string_add(json_nexthop_global,
7900 "hostname",
939a97f4 7901 path->peer->hostname);
515c2602 7902
a4d82a8a
PZ
7903 json_object_string_add(json_nexthop_global, "afi",
7904 "ipv4");
445c2480
DS
7905 json_object_boolean_true_add(json_nexthop_global,
7906 "used");
aef999a2
DA
7907 } else {
7908 if (nexthop_hostname)
7909 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7910 nexthop_hostname, vrf_id_str);
7911 else
7912 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7913 vrf_id_str);
7914
ae248832 7915 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7916 if (len < 1)
7917 vty_out(vty, "\n%*s", 36, " ");
7918 else
7919 vty_out(vty, "%*s", len, " ");
7920 }
d33fc23b 7921 } else if (safi == SAFI_FLOWSPEC) {
975a328e 7922 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a
PG
7923 if (json_paths) {
7924 json_nexthop_global = json_object_new_object();
515c2602 7925
026b914a
PG
7926 json_object_string_add(json_nexthop_global,
7927 "afi", "ipv4");
515c2602
DA
7928 json_object_string_add(
7929 json_nexthop_global, "ip",
7930 inet_ntoa(attr->nexthop));
7931
939a97f4 7932 if (path->peer->hostname)
515c2602
DA
7933 json_object_string_add(
7934 json_nexthop_global, "hostname",
939a97f4 7935 path->peer->hostname);
515c2602 7936
50e05855
AD
7937 json_object_boolean_true_add(
7938 json_nexthop_global,
026b914a
PG
7939 "used");
7940 } else {
aef999a2
DA
7941 if (nexthop_hostname)
7942 len = vty_out(vty, "%pI4(%s)%s",
7943 &attr->nexthop,
7944 nexthop_hostname,
7945 vrf_id_str);
7946 else
7947 len = vty_out(vty, "%pI4%s",
7948 &attr->nexthop,
7949 vrf_id_str);
7950
ae248832 7951 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7952 if (len < 1)
7953 vty_out(vty, "\n%*s", 36, " ");
7954 else
7955 vty_out(vty, "%*s", len, " ");
026b914a
PG
7956 }
7957 }
d33fc23b 7958 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480
DS
7959 if (json_paths) {
7960 json_nexthop_global = json_object_new_object();
d62a17ae 7961
515c2602
DA
7962 json_object_string_add(json_nexthop_global, "ip",
7963 inet_ntoa(attr->nexthop));
7964
939a97f4 7965 if (path->peer->hostname)
515c2602
DA
7966 json_object_string_add(json_nexthop_global,
7967 "hostname",
939a97f4 7968 path->peer->hostname);
445c2480 7969
a4d82a8a
PZ
7970 json_object_string_add(json_nexthop_global, "afi",
7971 "ipv4");
445c2480
DS
7972 json_object_boolean_true_add(json_nexthop_global,
7973 "used");
7974 } else {
aef999a2
DA
7975 if (nexthop_hostname)
7976 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
7977 nexthop_hostname, vrf_id_str);
7978 else
7979 len = vty_out(vty, "%pI4%s", &attr->nexthop,
7980 vrf_id_str);
9df8b37c 7981
ae248832 7982 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
7983 if (len < 1)
7984 vty_out(vty, "\n%*s", 36, " ");
7985 else
7986 vty_out(vty, "%*s", len, " ");
d62a17ae 7987 }
445c2480 7988 }
b05a1c8b 7989
445c2480 7990 /* IPv6 Next Hop */
a4d82a8a 7991 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 7992 char buf[BUFSIZ];
d62a17ae 7993
445c2480
DS
7994 if (json_paths) {
7995 json_nexthop_global = json_object_new_object();
a4d82a8a 7996 json_object_string_add(
515c2602
DA
7997 json_nexthop_global, "ip",
7998 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
7999 buf, BUFSIZ));
8000
939a97f4 8001 if (path->peer->hostname)
515c2602
DA
8002 json_object_string_add(json_nexthop_global,
8003 "hostname",
939a97f4 8004 path->peer->hostname);
515c2602 8005
a4d82a8a
PZ
8006 json_object_string_add(json_nexthop_global, "afi",
8007 "ipv6");
8008 json_object_string_add(json_nexthop_global, "scope",
8009 "global");
445c2480
DS
8010
8011 /* We display both LL & GL if both have been
8012 * received */
0606039c
DA
8013 if ((attr->mp_nexthop_len
8014 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8015 || (path->peer->conf_if)) {
a4d82a8a 8016 json_nexthop_ll = json_object_new_object();
d62a17ae 8017 json_object_string_add(
515c2602
DA
8018 json_nexthop_ll, "ip",
8019 inet_ntop(AF_INET6,
8020 &attr->mp_nexthop_local, buf,
8021 BUFSIZ));
8022
939a97f4 8023 if (path->peer->hostname)
515c2602
DA
8024 json_object_string_add(
8025 json_nexthop_ll, "hostname",
939a97f4 8026 path->peer->hostname);
515c2602 8027
a4d82a8a
PZ
8028 json_object_string_add(json_nexthop_ll, "afi",
8029 "ipv6");
8030 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8031 "link-local");
d62a17ae 8032
a4d82a8a
PZ
8033 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8034 &attr->mp_nexthop_local)
445c2480
DS
8035 != 0)
8036 && !attr->mp_nexthop_prefer_global)
d62a17ae 8037 json_object_boolean_true_add(
a4d82a8a 8038 json_nexthop_ll, "used");
445c2480
DS
8039 else
8040 json_object_boolean_true_add(
a4d82a8a 8041 json_nexthop_global, "used");
445c2480
DS
8042 } else
8043 json_object_boolean_true_add(
8044 json_nexthop_global, "used");
8045 } else {
8046 /* Display LL if LL/Global both in table unless
8047 * prefer-global is set */
0606039c
DA
8048 if (((attr->mp_nexthop_len
8049 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8050 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8051 || (path->peer->conf_if)) {
8052 if (path->peer->conf_if) {
a4d82a8a 8053 len = vty_out(vty, "%s",
9b6d8fcf 8054 path->peer->conf_if);
ae248832
MK
8055 /* len of IPv6 addr + max len of def
8056 * ifname */
8057 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8058
8059 if (len < 1)
a4d82a8a 8060 vty_out(vty, "\n%*s", 36, " ");
445c2480 8061 else
a4d82a8a 8062 vty_out(vty, "%*s", len, " ");
d62a17ae 8063 } else {
aef999a2
DA
8064 if (nexthop_hostname)
8065 len = vty_out(
8066 vty, "%pI6(%s)%s",
8067 &attr->mp_nexthop_local,
8068 nexthop_hostname,
8069 vrf_id_str);
8070 else
8071 len = vty_out(
8072 vty, "%pI6%s",
8073 &attr->mp_nexthop_local,
8074 vrf_id_str);
8075
ae248832 8076 len = wide ? (41 - len) : (16 - len);
d62a17ae 8077
8078 if (len < 1)
a4d82a8a 8079 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8080 else
a4d82a8a 8081 vty_out(vty, "%*s", len, " ");
d62a17ae 8082 }
445c2480 8083 } else {
aef999a2
DA
8084 if (nexthop_hostname)
8085 len = vty_out(vty, "%pI6(%s)%s",
8086 &attr->mp_nexthop_global,
8087 nexthop_hostname,
8088 vrf_id_str);
8089 else
8090 len = vty_out(vty, "%pI6%s",
8091 &attr->mp_nexthop_global,
8092 vrf_id_str);
8093
ae248832 8094 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8095
8096 if (len < 1)
8097 vty_out(vty, "\n%*s", 36, " ");
8098 else
8099 vty_out(vty, "%*s", len, " ");
d62a17ae 8100 }
8101 }
445c2480 8102 }
718e3744 8103
445c2480
DS
8104 /* MED/Metric */
8105 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8106 if (json_paths)
50e05855 8107 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8108 else if (wide)
8109 vty_out(vty, "%7u", attr->med);
0fbac0b4 8110 else
445c2480 8111 vty_out(vty, "%10u", attr->med);
ae248832
MK
8112 else if (!json_paths) {
8113 if (wide)
8114 vty_out(vty, "%*s", 7, " ");
8115 else
8116 vty_out(vty, "%*s", 10, " ");
8117 }
d62a17ae 8118
445c2480
DS
8119 /* Local Pref */
8120 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8121 if (json_paths)
50e05855 8122 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8123 attr->local_pref);
8124 else
445c2480
DS
8125 vty_out(vty, "%7u", attr->local_pref);
8126 else if (!json_paths)
8127 vty_out(vty, " ");
d62a17ae 8128
445c2480
DS
8129 if (json_paths)
8130 json_object_int_add(json_path, "weight", attr->weight);
8131 else
8132 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8133
445c2480
DS
8134 if (json_paths) {
8135 char buf[BUFSIZ];
a4d82a8a
PZ
8136 json_object_string_add(
8137 json_path, "peerId",
9b6d8fcf 8138 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8139 }
b05a1c8b 8140
445c2480
DS
8141 /* Print aspath */
8142 if (attr->aspath) {
0fbac0b4 8143 if (json_paths)
50e05855 8144 json_object_string_add(json_path, "path",
0fbac0b4
DA
8145 attr->aspath->str);
8146 else
445c2480 8147 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8148 }
f1aa5d8a 8149
445c2480
DS
8150 /* Print origin */
8151 if (json_paths)
a4d82a8a
PZ
8152 json_object_string_add(json_path, "origin",
8153 bgp_origin_long_str[attr->origin]);
445c2480
DS
8154 else
8155 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8156
9df8b37c 8157 if (json_paths) {
d071f237 8158 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8159 json_object_string_add(json_path, "esi",
8160 esi_to_str(&attr->esi,
8161 esi_buf, sizeof(esi_buf)));
8162 }
6f214dd3
CS
8163 if (safi == SAFI_EVPN &&
8164 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8165 json_ext_community = json_object_new_object();
8166 json_object_string_add(json_ext_community,
8167 "string",
8168 attr->ecommunity->str);
8169 json_object_object_add(json_path,
8170 "extendedCommunity",
8171 json_ext_community);
8172 }
8173
9df8b37c
PZ
8174 if (nexthop_self)
8175 json_object_boolean_true_add(json_path,
8176 "announceNexthopSelf");
8177 if (nexthop_othervrf) {
8178 json_object_string_add(json_path, "nhVrfName",
8179 nexthop_vrfname);
8180
8181 json_object_int_add(json_path, "nhVrfId",
8182 ((nexthop_vrfid == VRF_UNKNOWN)
8183 ? -1
8184 : (int)nexthop_vrfid));
8185 }
8186 }
8187
d62a17ae 8188 if (json_paths) {
8189 if (json_nexthop_global || json_nexthop_ll) {
8190 json_nexthops = json_object_new_array();
f1aa5d8a 8191
d62a17ae 8192 if (json_nexthop_global)
8193 json_object_array_add(json_nexthops,
8194 json_nexthop_global);
f1aa5d8a 8195
d62a17ae 8196 if (json_nexthop_ll)
8197 json_object_array_add(json_nexthops,
8198 json_nexthop_ll);
f1aa5d8a 8199
d62a17ae 8200 json_object_object_add(json_path, "nexthops",
8201 json_nexthops);
8202 }
8203
8204 json_object_array_add(json_paths, json_path);
8205 } else {
8206 vty_out(vty, "\n");
6f214dd3 8207
b5e140c8 8208 if (safi == SAFI_EVPN) {
d071f237 8209 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8210 vty_out(vty, "%*s", 20, " ");
8211 vty_out(vty, "ESI:%s\n",
8212 esi_to_str(&attr->esi,
8213 esi_buf, sizeof(esi_buf)));
8214 }
8215 if (attr->flag &
8216 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8217 vty_out(vty, "%*s", 20, " ");
8218 vty_out(vty, "%s\n", attr->ecommunity->str);
8219 }
6f214dd3
CS
8220 }
8221
49e5a4a0 8222#ifdef ENABLE_BGP_VNC
d62a17ae 8223 /* prints an additional line, indented, with VNC info, if
8224 * present */
8225 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8226 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8227#endif
d62a17ae 8228 }
8229}
718e3744 8230
8231/* called from terminal list command */
5f040085
DS
8232void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8233 struct attr *attr, safi_t safi, bool use_json,
ae248832 8234 json_object *json_ar, bool wide)
d62a17ae 8235{
8236 json_object *json_status = NULL;
8237 json_object *json_net = NULL;
aef999a2 8238 int len;
d62a17ae 8239 char buff[BUFSIZ];
dc387b0f 8240
d62a17ae 8241 /* Route status display. */
8242 if (use_json) {
8243 json_status = json_object_new_object();
8244 json_net = json_object_new_object();
8245 } else {
8246 vty_out(vty, "*");
8247 vty_out(vty, ">");
8248 vty_out(vty, " ");
8249 }
718e3744 8250
d62a17ae 8251 /* print prefix and mask */
50e05855 8252 if (use_json) {
dc387b0f
LK
8253 if (safi == SAFI_EVPN)
8254 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8255 else if (p->family == AF_INET || p->family == AF_INET6) {
8256 json_object_string_add(
8257 json_net, "addrPrefix",
8258 inet_ntop(p->family, &p->u.prefix, buff,
8259 BUFSIZ));
8260 json_object_int_add(json_net, "prefixLen",
8261 p->prefixlen);
8262 prefix2str(p, buff, PREFIX_STRLEN);
8263 json_object_string_add(json_net, "network", buff);
8264 }
50e05855 8265 } else
ae248832 8266 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8267
8268 /* Print attribute */
8269 if (attr) {
8270 if (use_json) {
8271 if (p->family == AF_INET
8272 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8273 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8274 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8275 json_object_string_add(
8276 json_net, "nextHop",
8277 inet_ntoa(
8278 attr->mp_nexthop_global_in));
8279 else
8280 json_object_string_add(
8281 json_net, "nextHop",
8282 inet_ntoa(attr->nexthop));
8283 } else if (p->family == AF_INET6
8284 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8285 char buf[BUFSIZ];
8286
8287 json_object_string_add(
aa0a10fc 8288 json_net, "nextHopGlobal",
d62a17ae 8289 inet_ntop(AF_INET6,
8290 &attr->mp_nexthop_global, buf,
8291 BUFSIZ));
dc387b0f
LK
8292 } else if (p->family == AF_EVPN &&
8293 !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8294 json_object_string_add(json_net,
8295 "nextHop", inet_ntoa(
8296 attr->mp_nexthop_global_in));
d62a17ae 8297
8298 if (attr->flag
8299 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8300 json_object_int_add(json_net, "metric",
8301 attr->med);
8302
0fbac0b4 8303 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8304 json_object_int_add(json_net, "locPrf",
0fbac0b4 8305 attr->local_pref);
d62a17ae 8306
8307 json_object_int_add(json_net, "weight", attr->weight);
8308
8309 /* Print aspath */
0fbac0b4 8310 if (attr->aspath)
50e05855 8311 json_object_string_add(json_net, "path",
0fbac0b4 8312 attr->aspath->str);
d62a17ae 8313
8314 /* Print origin */
8315 json_object_string_add(json_net, "bgpOriginCode",
8316 bgp_origin_str[attr->origin]);
8317 } else {
8318 if (p->family == AF_INET
8319 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8320 || safi == SAFI_EVPN
8321 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8322 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8323 || safi == SAFI_EVPN)
8324 vty_out(vty, "%-16s",
8325 inet_ntoa(
8326 attr->mp_nexthop_global_in));
ae248832
MK
8327 else if (wide)
8328 vty_out(vty, "%-41s",
8329 inet_ntoa(attr->nexthop));
d62a17ae 8330 else
8331 vty_out(vty, "%-16s",
8332 inet_ntoa(attr->nexthop));
8333 } else if (p->family == AF_INET6
8334 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 8335 char buf[BUFSIZ];
8336
8337 len = vty_out(
8338 vty, "%s",
8339 inet_ntop(AF_INET6,
8340 &attr->mp_nexthop_global, buf,
8341 BUFSIZ));
ae248832 8342 len = wide ? (41 - len) : (16 - len);
d62a17ae 8343 if (len < 1)
8344 vty_out(vty, "\n%*s", 36, " ");
8345 else
8346 vty_out(vty, "%*s", len, " ");
8347 }
8348 if (attr->flag
8349 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
8350 if (wide)
8351 vty_out(vty, "%7u", attr->med);
8352 else
8353 vty_out(vty, "%10u", attr->med);
8354 else if (wide)
8355 vty_out(vty, " ");
d62a17ae 8356 else
8357 vty_out(vty, " ");
718e3744 8358
d62a17ae 8359 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
8360 vty_out(vty, "%7u", attr->local_pref);
8361 else
8362 vty_out(vty, " ");
8363
8364 vty_out(vty, "%7u ", attr->weight);
8365
8366 /* Print aspath */
8367 if (attr->aspath)
8368 aspath_print_vty(vty, "%s", attr->aspath, " ");
8369
8370 /* Print origin */
8371 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8372 }
8373 }
8374 if (use_json) {
8375 json_object_boolean_true_add(json_status, "*");
8376 json_object_boolean_true_add(json_status, ">");
8377 json_object_object_add(json_net, "appliedStatusSymbols",
8378 json_status);
1608ff77 8379
dc387b0f
LK
8380 prefix2str(p, buff, PREFIX_STRLEN);
8381 json_object_object_add(json_ar, buff, json_net);
d62a17ae 8382 } else
8383 vty_out(vty, "\n");
8384}
8385
bd494ec5 8386void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 8387 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 8388 json_object *json)
8389{
8390 json_object *json_out = NULL;
8391 struct attr *attr;
8392 mpls_label_t label = MPLS_INVALID_LABEL;
8393
9b6d8fcf 8394 if (!path->extra)
d62a17ae 8395 return;
8396
8397 if (json)
8398 json_out = json_object_new_object();
8399
8400 /* short status lead text */
9b6d8fcf 8401 route_vty_short_status_out(vty, path, json_out);
d62a17ae 8402
8403 /* print prefix and mask */
8404 if (json == NULL) {
8405 if (!display)
ae248832 8406 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8407 else
8408 vty_out(vty, "%*s", 17, " ");
8409 }
8410
8411 /* Print attribute */
9b6d8fcf 8412 attr = path->attr;
05864da7
DS
8413 if (((p->family == AF_INET)
8414 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8415 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8416 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8417 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8418 || safi == SAFI_EVPN) {
8419 if (json)
8420 json_object_string_add(
8421 json_out, "mpNexthopGlobalIn",
8422 inet_ntoa(attr->mp_nexthop_global_in));
8423 else
8424 vty_out(vty, "%-16s",
8425 inet_ntoa(attr->mp_nexthop_global_in));
8426 } else {
8427 if (json)
8428 json_object_string_add(
8429 json_out, "nexthop",
8430 inet_ntoa(attr->nexthop));
8431 else
8432 vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
8433 }
8434 } else if (((p->family == AF_INET6)
8435 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
8436 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
8437 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8438 char buf_a[512];
8439
8440 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
8441 if (json)
8442 json_object_string_add(
8443 json_out, "mpNexthopGlobalIn",
8444 inet_ntop(AF_INET6,
8445 &attr->mp_nexthop_global,
8446 buf_a, sizeof(buf_a)));
8447 else
8448 vty_out(vty, "%s",
8449 inet_ntop(AF_INET6,
8450 &attr->mp_nexthop_global,
8451 buf_a, sizeof(buf_a)));
8452 } else if (attr->mp_nexthop_len
8453 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
8454 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
8455 &attr->mp_nexthop_global,
8456 &attr->mp_nexthop_local);
8457 if (json)
8458 json_object_string_add(json_out,
8459 "mpNexthopGlobalLocal",
8460 buf_a);
8461 else
8462 vty_out(vty, "%s", buf_a);
d62a17ae 8463 }
8464 }
8465
9b6d8fcf 8466 label = decode_label(&path->extra->label[0]);
d62a17ae 8467
8468 if (bgp_is_valid_label(&label)) {
8469 if (json) {
8470 json_object_int_add(json_out, "notag", label);
8471 json_object_array_add(json, json_out);
8472 } else {
8473 vty_out(vty, "notag/%d", label);
8474 vty_out(vty, "\n");
8475 }
8476 }
8477}
718e3744 8478
bd494ec5 8479void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 8480 struct bgp_path_info *path, int display,
d62a17ae 8481 json_object *json_paths)
718e3744 8482{
d62a17ae 8483 struct attr *attr;
14f51eba 8484 char buf[BUFSIZ] = {0};
d62a17ae 8485 json_object *json_path = NULL;
14f51eba
LK
8486 json_object *json_nexthop = NULL;
8487 json_object *json_overlay = NULL;
856ca177 8488
9b6d8fcf 8489 if (!path->extra)
d62a17ae 8490 return;
718e3744 8491
14f51eba
LK
8492 if (json_paths) {
8493 json_path = json_object_new_object();
8494 json_overlay = json_object_new_object();
8495 json_nexthop = json_object_new_object();
8496 }
8497
d62a17ae 8498 /* short status lead text */
9b6d8fcf 8499 route_vty_short_status_out(vty, path, json_path);
856ca177 8500
d62a17ae 8501 /* print prefix and mask */
8502 if (!display)
ae248832 8503 route_vty_out_route(p, vty, json_path, false);
d62a17ae 8504 else
8505 vty_out(vty, "%*s", 17, " ");
8506
8507 /* Print attribute */
9b6d8fcf 8508 attr = path->attr;
05864da7
DS
8509 char buf1[BUFSIZ];
8510 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 8511
05864da7
DS
8512 switch (af) {
8513 case AF_INET:
8514 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
8515 if (!json_path) {
8516 vty_out(vty, "%-16s", buf);
8517 } else {
8518 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 8519
05864da7 8520 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 8521
05864da7
DS
8522 json_object_object_add(json_path, "nexthop",
8523 json_nexthop);
8524 }
8525 break;
8526 case AF_INET6:
8527 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
8528 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
8529 if (!json_path) {
8530 vty_out(vty, "%s(%s)", buf, buf1);
8531 } else {
8532 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 8533
05864da7
DS
8534 json_object_string_add(json_nexthop, "ipv6LinkLocal",
8535 buf1);
14f51eba 8536
05864da7 8537 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 8538
05864da7
DS
8539 json_object_object_add(json_path, "nexthop",
8540 json_nexthop);
8541 }
8542 break;
8543 default:
8544 if (!json_path) {
8545 vty_out(vty, "?");
8546 } else {
8547 json_object_string_add(json_nexthop, "Error",
8548 "Unsupported address-family");
d62a17ae 8549 }
05864da7 8550 }
988258b4 8551
05864da7
DS
8552 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
8553 inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
8554 BUFSIZ);
8555 } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
8556 inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
8557 BUFSIZ);
8558 }
14f51eba 8559
05864da7
DS
8560 if (!json_path)
8561 vty_out(vty, "/%s", buf);
8562 else
8563 json_object_string_add(json_overlay, "gw", buf);
8564
8565 if (attr->ecommunity) {
8566 char *mac = NULL;
8567 struct ecommunity_val *routermac = ecommunity_lookup(
8568 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
8569 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
8570
8571 if (routermac)
8572 mac = ecom_mac2str((char *)routermac->val);
8573 if (mac) {
8574 if (!json_path) {
c4efd0f4 8575 vty_out(vty, "/%s", mac);
05864da7
DS
8576 } else {
8577 json_object_string_add(json_overlay, "rmac",
8578 mac);
988258b4 8579 }
05864da7 8580 XFREE(MTYPE_TMP, mac);
988258b4 8581 }
05864da7 8582 }
718e3744 8583
05864da7
DS
8584 if (!json_path) {
8585 vty_out(vty, "\n");
8586 } else {
8587 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 8588
05864da7 8589 json_object_array_add(json_paths, json_path);
14f51eba 8590 }
d62a17ae 8591}
718e3744 8592
d62a17ae 8593/* dampening route */
5f040085
DS
8594static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
8595 struct bgp_path_info *path, int display,
8596 afi_t afi, safi_t safi, bool use_json,
8597 json_object *json)
d62a17ae 8598{
8599 struct attr *attr;
8600 int len;
8601 char timebuf[BGP_UPTIME_LEN];
8602
8603 /* short status lead text */
9b6d8fcf 8604 route_vty_short_status_out(vty, path, json);
d62a17ae 8605
8606 /* print prefix and mask */
8607 if (!use_json) {
8608 if (!display)
ae248832 8609 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8610 else
8611 vty_out(vty, "%*s", 17, " ");
8612 }
8613
9b6d8fcf 8614 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8615 len = 17 - len;
8616 if (len < 1) {
8617 if (!use_json)
8618 vty_out(vty, "\n%*s", 34, " ");
8619 } else {
8620 if (use_json)
8621 json_object_int_add(json, "peerHost", len);
8622 else
8623 vty_out(vty, "%*s", len, " ");
8624 }
8625
8626 if (use_json)
a935f597
DA
8627 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
8628 safi, use_json, json);
d62a17ae 8629 else
9b6d8fcf
DS
8630 vty_out(vty, "%s ",
8631 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8632 BGP_UPTIME_LEN, afi, safi,
8633 use_json, json));
d62a17ae 8634
8635 /* Print attribute */
9b6d8fcf 8636 attr = path->attr;
d62a17ae 8637
05864da7
DS
8638 /* Print aspath */
8639 if (attr->aspath) {
d62a17ae 8640 if (use_json)
05864da7
DS
8641 json_object_string_add(json, "asPath",
8642 attr->aspath->str);
d62a17ae 8643 else
05864da7 8644 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8645 }
05864da7
DS
8646
8647 /* Print origin */
8648 if (use_json)
8649 json_object_string_add(json, "origin",
8650 bgp_origin_str[attr->origin]);
8651 else
8652 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8653
d62a17ae 8654 if (!use_json)
8655 vty_out(vty, "\n");
8656}
718e3744 8657
d62a17ae 8658/* flap route */
5f040085
DS
8659static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
8660 struct bgp_path_info *path, int display,
8661 afi_t afi, safi_t safi, bool use_json,
8662 json_object *json)
784d3a42 8663{
d62a17ae 8664 struct attr *attr;
8665 struct bgp_damp_info *bdi;
8666 char timebuf[BGP_UPTIME_LEN];
8667 int len;
784d3a42 8668
9b6d8fcf 8669 if (!path->extra)
d62a17ae 8670 return;
784d3a42 8671
9b6d8fcf 8672 bdi = path->extra->damp_info;
784d3a42 8673
d62a17ae 8674 /* short status lead text */
9b6d8fcf 8675 route_vty_short_status_out(vty, path, json);
784d3a42 8676
d62a17ae 8677 /* print prefix and mask */
8678 if (!use_json) {
8679 if (!display)
ae248832 8680 route_vty_out_route(p, vty, NULL, false);
d62a17ae 8681 else
8682 vty_out(vty, "%*s", 17, " ");
8683 }
784d3a42 8684
9b6d8fcf 8685 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 8686 len = 16 - len;
8687 if (len < 1) {
8688 if (!use_json)
8689 vty_out(vty, "\n%*s", 33, " ");
8690 } else {
8691 if (use_json)
8692 json_object_int_add(json, "peerHost", len);
8693 else
8694 vty_out(vty, "%*s", len, " ");
8695 }
784d3a42 8696
d62a17ae 8697 len = vty_out(vty, "%d", bdi->flap);
8698 len = 5 - len;
8699 if (len < 1) {
8700 if (!use_json)
8701 vty_out(vty, " ");
8702 } else {
8703 if (use_json)
8704 json_object_int_add(json, "bdiFlap", len);
8705 else
8706 vty_out(vty, "%*s", len, " ");
8707 }
8708
8709 if (use_json)
8710 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
8711 json);
8712 else
996c9314
LB
8713 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
8714 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 8715
9b6d8fcf
DS
8716 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
8717 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 8718 if (use_json)
9b6d8fcf 8719 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8720 BGP_UPTIME_LEN, afi, safi,
8721 use_json, json);
d62a17ae 8722 else
8723 vty_out(vty, "%s ",
9b6d8fcf 8724 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
8725 BGP_UPTIME_LEN, afi,
8726 safi, use_json, json));
d62a17ae 8727 } else {
8728 if (!use_json)
8729 vty_out(vty, "%*s ", 8, " ");
8730 }
8731
8732 /* Print attribute */
9b6d8fcf 8733 attr = path->attr;
d62a17ae 8734
05864da7
DS
8735 /* Print aspath */
8736 if (attr->aspath) {
d62a17ae 8737 if (use_json)
05864da7
DS
8738 json_object_string_add(json, "asPath",
8739 attr->aspath->str);
d62a17ae 8740 else
05864da7 8741 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8742 }
05864da7
DS
8743
8744 /* Print origin */
8745 if (use_json)
8746 json_object_string_add(json, "origin",
8747 bgp_origin_str[attr->origin]);
8748 else
8749 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8750
d62a17ae 8751 if (!use_json)
8752 vty_out(vty, "\n");
8753}
8754
8755static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
8756 int *first, const char *header,
8757 json_object *json_adv_to)
8758{
8759 char buf1[INET6_ADDRSTRLEN];
8760 json_object *json_peer = NULL;
8761
8762 if (json_adv_to) {
8763 /* 'advertised-to' is a dictionary of peers we have advertised
8764 * this
8765 * prefix too. The key is the peer's IP or swpX, the value is
8766 * the
8767 * hostname if we know it and "" if not.
8768 */
8769 json_peer = json_object_new_object();
8770
8771 if (peer->hostname)
8772 json_object_string_add(json_peer, "hostname",
8773 peer->hostname);
8774
8775 if (peer->conf_if)
8776 json_object_object_add(json_adv_to, peer->conf_if,
8777 json_peer);
8778 else
8779 json_object_object_add(
8780 json_adv_to,
8781 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
8782 json_peer);
8783 } else {
8784 if (*first) {
8785 vty_out(vty, "%s", header);
8786 *first = 0;
8787 }
8788
8789 if (peer->hostname
892fedb6 8790 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 8791 if (peer->conf_if)
8792 vty_out(vty, " %s(%s)", peer->hostname,
8793 peer->conf_if);
8794 else
8795 vty_out(vty, " %s(%s)", peer->hostname,
8796 sockunion2str(&peer->su, buf1,
8797 SU_ADDRSTRLEN));
8798 } else {
8799 if (peer->conf_if)
8800 vty_out(vty, " %s", peer->conf_if);
8801 else
8802 vty_out(vty, " %s",
8803 sockunion2str(&peer->su, buf1,
8804 SU_ADDRSTRLEN));
8805 }
8806 }
784d3a42
PG
8807}
8808
dcc68b5e
MS
8809static void route_vty_out_tx_ids(struct vty *vty,
8810 struct bgp_addpath_info_data *d)
8811{
8812 int i;
8813
8814 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
8815 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
8816 d->addpath_tx_id[i],
8817 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
8818 }
8819}
8820
0dc8ee70
DS
8821static const char *bgp_path_selection_reason2str(
8822 enum bgp_path_selection_reason reason)
8823{
8824 switch (reason) {
8825 case bgp_path_selection_none:
8826 return "Nothing to Select";
0dc8ee70
DS
8827 case bgp_path_selection_first:
8828 return "First path received";
0dc8ee70
DS
8829 case bgp_path_selection_evpn_sticky_mac:
8830 return "EVPN Sticky Mac";
0dc8ee70
DS
8831 case bgp_path_selection_evpn_seq:
8832 return "EVPN sequence number";
0dc8ee70
DS
8833 case bgp_path_selection_evpn_lower_ip:
8834 return "EVPN lower IP";
d071f237
AK
8835 case bgp_path_selection_evpn_local_path:
8836 return "EVPN local ES path";
8837 case bgp_path_selection_evpn_non_proxy:
8838 return "EVPN non proxy";
0dc8ee70
DS
8839 case bgp_path_selection_weight:
8840 return "Weight";
0dc8ee70
DS
8841 case bgp_path_selection_local_pref:
8842 return "Local Pref";
0dc8ee70
DS
8843 case bgp_path_selection_local_route:
8844 return "Local Route";
0dc8ee70
DS
8845 case bgp_path_selection_confed_as_path:
8846 return "Confederation based AS Path";
0dc8ee70
DS
8847 case bgp_path_selection_as_path:
8848 return "AS Path";
0dc8ee70
DS
8849 case bgp_path_selection_origin:
8850 return "Origin";
0dc8ee70
DS
8851 case bgp_path_selection_med:
8852 return "MED";
0dc8ee70
DS
8853 case bgp_path_selection_peer:
8854 return "Peer Type";
0dc8ee70
DS
8855 case bgp_path_selection_confed:
8856 return "Confed Peer Type";
0dc8ee70
DS
8857 case bgp_path_selection_igp_metric:
8858 return "IGP Metric";
0dc8ee70
DS
8859 case bgp_path_selection_older:
8860 return "Older Path";
0dc8ee70
DS
8861 case bgp_path_selection_router_id:
8862 return "Router ID";
0dc8ee70
DS
8863 case bgp_path_selection_cluster_length:
8864 return "Cluser length";
0dc8ee70
DS
8865 case bgp_path_selection_stale:
8866 return "Path Staleness";
0dc8ee70
DS
8867 case bgp_path_selection_local_configured:
8868 return "Locally configured route";
0dc8ee70
DS
8869 case bgp_path_selection_neighbor_ip:
8870 return "Neighbor IP";
0dc8ee70
DS
8871 case bgp_path_selection_default:
8872 return "Nothing left to compare";
0dc8ee70 8873 }
a74879b2 8874 return "Invalid (internal error)";
0dc8ee70
DS
8875}
8876
5e4d4c8a
AK
8877static void route_vty_out_detail_es_info(struct vty *vty,
8878 struct attr *attr, json_object *json_path)
8879{
8880 char esi_buf[ESI_STR_LEN];
8881 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
8882 bool peer_router = !!CHECK_FLAG(attr->es_flags,
8883 ATTR_ES_PEER_ROUTER);
8884 bool peer_active = !!CHECK_FLAG(attr->es_flags,
8885 ATTR_ES_PEER_ACTIVE);
8886 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
8887 ATTR_ES_PEER_PROXY);
8888
8889 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
8890 if (json_path) {
8891 json_object *json_es_info = NULL;
8892
8893 json_object_string_add(
8894 json_path, "esi",
8895 esi_buf);
8896 if (es_local || bgp_evpn_attr_is_sync(attr)) {
8897 json_es_info = json_object_new_object();
8898 if (es_local)
8899 json_object_boolean_true_add(
8900 json_es_info, "localEs");
8901 if (peer_active)
8902 json_object_boolean_true_add(
8903 json_es_info, "peerActive");
8904 if (peer_proxy)
8905 json_object_boolean_true_add(
8906 json_es_info, "peerProxy");
8907 if (peer_router)
8908 json_object_boolean_true_add(
8909 json_es_info, "peerRouter");
8910 if (attr->mm_sync_seqnum)
8911 json_object_int_add(
8912 json_es_info, "peerSeq",
8913 attr->mm_sync_seqnum);
8914 json_object_object_add(
8915 json_path, "es_info",
8916 json_es_info);
8917 }
8918 } else {
8919 if (bgp_evpn_attr_is_sync(attr))
8920 vty_out(vty,
8921 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
8922 esi_buf,
8923 es_local ? "local-es":"",
8924 peer_proxy ? "proxy " : "",
8925 peer_active ? "active ":"",
8926 peer_router ? "router ":"",
8927 attr->mm_sync_seqnum);
8928 else
8929 vty_out(vty, " ESI %s %s\n",
8930 esi_buf,
8931 es_local ? "local-es":"");
8932 }
8933}
8934
8935void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
8936 struct bgp_dest *bn, struct bgp_path_info *path,
8937 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 8938{
8939 char buf[INET6_ADDRSTRLEN];
8940 char buf1[BUFSIZ];
d62a17ae 8941 char buf2[EVPN_ROUTE_STRLEN];
515c2602 8942 struct attr *attr = path->attr;
d62a17ae 8943 int sockunion_vty_out(struct vty *, union sockunion *);
8944 time_t tbuf;
8945 json_object *json_bestpath = NULL;
8946 json_object *json_cluster_list = NULL;
8947 json_object *json_cluster_list_list = NULL;
8948 json_object *json_ext_community = NULL;
8949 json_object *json_last_update = NULL;
7fd077aa 8950 json_object *json_pmsi = NULL;
d62a17ae 8951 json_object *json_nexthop_global = NULL;
8952 json_object *json_nexthop_ll = NULL;
8953 json_object *json_nexthops = NULL;
8954 json_object *json_path = NULL;
8955 json_object *json_peer = NULL;
8956 json_object *json_string = NULL;
8957 json_object *json_adv_to = NULL;
8958 int first = 0;
8959 struct listnode *node, *nnode;
8960 struct peer *peer;
8961 int addpath_capable;
8962 int has_adj;
8963 unsigned int first_as;
1defdda8 8964 bool nexthop_self =
9b6d8fcf 8965 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 8966 int i;
2ba93fd6
DA
8967 char *nexthop_hostname =
8968 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 8969
8970 if (json_paths) {
8971 json_path = json_object_new_object();
8972 json_peer = json_object_new_object();
8973 json_nexthop_global = json_object_new_object();
8974 }
8975
44c69747 8976 if (path->extra) {
b57ba6d2 8977 char tag_buf[30];
d62a17ae 8978
d7325ee7 8979 buf2[0] = '\0';
d62a17ae 8980 tag_buf[0] = '\0';
9b6d8fcf
DS
8981 if (path->extra && path->extra->num_labels) {
8982 bgp_evpn_label2str(path->extra->label,
8983 path->extra->num_labels, tag_buf,
a4d82a8a 8984 sizeof(tag_buf));
d62a17ae 8985 }
d7325ee7 8986 if (safi == SAFI_EVPN) {
44c69747 8987 if (!json_paths) {
b54892e0
DS
8988 bgp_evpn_route2str(
8989 (struct prefix_evpn *)
9bcb3eef 8990 bgp_dest_get_prefix(bn),
b54892e0 8991 buf2, sizeof(buf2));
44c69747
LK
8992 vty_out(vty, " Route %s", buf2);
8993 if (tag_buf[0] != '\0')
8994 vty_out(vty, " VNI %s", tag_buf);
8995 vty_out(vty, "\n");
8996 } else {
8997 if (tag_buf[0])
8998 json_object_string_add(json_path, "VNI",
8999 tag_buf);
9000 }
d7325ee7
DD
9001 }
9002
44c69747 9003 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9004 struct bgp_path_info *parent_ri;
9bcb3eef 9005 struct bgp_dest *dest, *pdest;
d62a17ae 9006
9b6d8fcf 9007 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9008 dest = parent_ri->net;
9009 if (dest && dest->pdest) {
9010 pdest = dest->pdest;
9011 prefix_rd2str(
9012 (struct prefix_rd *)bgp_dest_get_prefix(
9013 pdest),
9014 buf1, sizeof(buf1));
d7325ee7 9015 if (is_pi_family_evpn(parent_ri)) {
b54892e0
DS
9016 bgp_evpn_route2str(
9017 (struct prefix_evpn *)
9bcb3eef
DS
9018 bgp_dest_get_prefix(
9019 dest),
b54892e0 9020 buf2, sizeof(buf2));
d7325ee7
DD
9021 vty_out(vty, " Imported from %s:%s, VNI %s\n", buf1, buf2, tag_buf);
9022 } else
9023 vty_out(vty, " Imported from %s:%s\n", buf1, buf2);
d62a17ae 9024 }
9025 }
9026 }
d62a17ae 9027
05864da7
DS
9028 /* Line1 display AS-path, Aggregator */
9029 if (attr->aspath) {
9030 if (json_paths) {
9031 if (!attr->aspath->json)
9032 aspath_str_update(attr->aspath, true);
9033 json_object_lock(attr->aspath->json);
9034 json_object_object_add(json_path, "aspath",
9035 attr->aspath->json);
9036 } else {
9037 if (attr->aspath->segments)
9038 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9039 else
05864da7 9040 vty_out(vty, " Local");
d62a17ae 9041 }
05864da7 9042 }
d62a17ae 9043
05864da7
DS
9044 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9045 if (json_paths)
9046 json_object_boolean_true_add(json_path, "removed");
9047 else
9048 vty_out(vty, ", (removed)");
9049 }
d62a17ae 9050
05864da7
DS
9051 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9052 if (json_paths)
9053 json_object_boolean_true_add(json_path, "stale");
9054 else
9055 vty_out(vty, ", (stale)");
9056 }
d62a17ae 9057
05864da7
DS
9058 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9059 if (json_paths) {
9060 json_object_int_add(json_path, "aggregatorAs",
9061 attr->aggregator_as);
9062 json_object_string_add(
9063 json_path, "aggregatorId",
9064 inet_ntoa(attr->aggregator_addr));
87c82131
DA
9065 if (attr->aggregator_as == BGP_AS_ZERO)
9066 json_object_boolean_true_add(
9067 json_path, "aggregatorAsMalformed");
9068 else
9069 json_object_boolean_false_add(
9070 json_path, "aggregatorAsMalformed");
05864da7 9071 } else {
87c82131
DA
9072 if (attr->aggregator_as == BGP_AS_ZERO)
9073 vty_out(vty,
9074 ", (aggregated by %u(malformed) %s)",
9075 attr->aggregator_as,
9076 inet_ntoa(attr->aggregator_addr));
9077 else
9078 vty_out(vty, ", (aggregated by %u %s)",
9079 attr->aggregator_as,
9080 inet_ntoa(attr->aggregator_addr));
d62a17ae 9081 }
05864da7 9082 }
d62a17ae 9083
05864da7
DS
9084 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9085 PEER_FLAG_REFLECTOR_CLIENT)) {
9086 if (json_paths)
9087 json_object_boolean_true_add(json_path,
9088 "rxedFromRrClient");
9089 else
9090 vty_out(vty, ", (Received from a RR-client)");
9091 }
d62a17ae 9092
05864da7
DS
9093 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9094 PEER_FLAG_RSERVER_CLIENT)) {
9095 if (json_paths)
9096 json_object_boolean_true_add(json_path,
9097 "rxedFromRsClient");
9098 else
9099 vty_out(vty, ", (Received from a RS-client)");
9100 }
d62a17ae 9101
05864da7
DS
9102 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9103 if (json_paths)
9104 json_object_boolean_true_add(json_path,
9105 "dampeningHistoryEntry");
9106 else
9107 vty_out(vty, ", (history entry)");
9108 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9109 if (json_paths)
9110 json_object_boolean_true_add(json_path,
9111 "dampeningSuppressed");
9112 else
9113 vty_out(vty, ", (suppressed due to dampening)");
9114 }
d62a17ae 9115
05864da7
DS
9116 if (!json_paths)
9117 vty_out(vty, "\n");
d62a17ae 9118
05864da7
DS
9119 /* Line2 display Next-hop, Neighbor, Router-id */
9120 /* Display the nexthop */
9bcb3eef 9121 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9122
9123 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9124 || bn_p->family == AF_EVPN)
05864da7
DS
9125 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9126 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9127 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9128 || safi == SAFI_EVPN) {
515c2602 9129 if (json_paths) {
d62a17ae 9130 json_object_string_add(
515c2602
DA
9131 json_nexthop_global, "ip",
9132 inet_ntoa(attr->mp_nexthop_global_in));
9133
939a97f4 9134 if (path->peer->hostname)
515c2602
DA
9135 json_object_string_add(
9136 json_nexthop_global, "hostname",
939a97f4 9137 path->peer->hostname);
aef999a2
DA
9138 } else {
9139 if (nexthop_hostname)
9140 vty_out(vty, " %pI4(%s)",
9141 &attr->mp_nexthop_global_in,
9142 nexthop_hostname);
9143 else
9144 vty_out(vty, " %pI4",
9145 &attr->mp_nexthop_global_in);
9146 }
d62a17ae 9147 } else {
515c2602 9148 if (json_paths) {
05864da7 9149 json_object_string_add(
515c2602
DA
9150 json_nexthop_global, "ip",
9151 inet_ntoa(attr->nexthop));
9152
939a97f4 9153 if (path->peer->hostname)
515c2602
DA
9154 json_object_string_add(
9155 json_nexthop_global, "hostname",
939a97f4 9156 path->peer->hostname);
aef999a2
DA
9157 } else {
9158 if (nexthop_hostname)
9159 vty_out(vty, " %pI4(%s)",
9160 &attr->nexthop,
9161 nexthop_hostname);
9162 else
9163 vty_out(vty, " %pI4",
9164 &attr->nexthop);
9165 }
d62a17ae 9166 }
9167
05864da7
DS
9168 if (json_paths)
9169 json_object_string_add(json_nexthop_global, "afi",
9170 "ipv4");
9171 } else {
9172 if (json_paths) {
9173 json_object_string_add(
515c2602
DA
9174 json_nexthop_global, "ip",
9175 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9176 buf, INET6_ADDRSTRLEN));
9177
939a97f4 9178 if (path->peer->hostname)
515c2602
DA
9179 json_object_string_add(json_nexthop_global,
9180 "hostname",
939a97f4 9181 path->peer->hostname);
515c2602 9182
05864da7
DS
9183 json_object_string_add(json_nexthop_global, "afi",
9184 "ipv6");
9185 json_object_string_add(json_nexthop_global, "scope",
9186 "global");
9187 } else {
aef999a2
DA
9188 if (nexthop_hostname)
9189 vty_out(vty, " %pI6(%s)",
9190 &attr->mp_nexthop_global,
9191 nexthop_hostname);
9192 else
9193 vty_out(vty, " %pI6",
9194 &attr->mp_nexthop_global);
d62a17ae 9195 }
05864da7 9196 }
d62a17ae 9197
05864da7
DS
9198 /* Display the IGP cost or 'inaccessible' */
9199 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9200 if (json_paths)
9201 json_object_boolean_false_add(json_nexthop_global,
9202 "accessible");
9203 else
9204 vty_out(vty, " (inaccessible)");
9205 } else {
9206 if (path->extra && path->extra->igpmetric) {
d62a17ae 9207 if (json_paths)
05864da7
DS
9208 json_object_int_add(json_nexthop_global,
9209 "metric",
9210 path->extra->igpmetric);
d62a17ae 9211 else
05864da7
DS
9212 vty_out(vty, " (metric %u)",
9213 path->extra->igpmetric);
d62a17ae 9214 }
9215
05864da7 9216 /* IGP cost is 0, display this only for json */
d62a17ae 9217 else {
d62a17ae 9218 if (json_paths)
05864da7
DS
9219 json_object_int_add(json_nexthop_global,
9220 "metric", 0);
d62a17ae 9221 }
d62a17ae 9222
05864da7
DS
9223 if (json_paths)
9224 json_object_boolean_true_add(json_nexthop_global,
9225 "accessible");
9226 }
d62a17ae 9227
05864da7
DS
9228 /* Display peer "from" output */
9229 /* This path was originated locally */
9230 if (path->peer == bgp->peer_self) {
d62a17ae 9231
05864da7 9232 if (safi == SAFI_EVPN
b54892e0 9233 || (bn_p->family == AF_INET
05864da7 9234 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9235 if (json_paths)
05864da7
DS
9236 json_object_string_add(json_peer, "peerId",
9237 "0.0.0.0");
d62a17ae 9238 else
05864da7
DS
9239 vty_out(vty, " from 0.0.0.0 ");
9240 } else {
d62a17ae 9241 if (json_paths)
05864da7
DS
9242 json_object_string_add(json_peer, "peerId",
9243 "::");
d62a17ae 9244 else
05864da7 9245 vty_out(vty, " from :: ");
d62a17ae 9246 }
d62a17ae 9247
05864da7
DS
9248 if (json_paths)
9249 json_object_string_add(json_peer, "routerId",
9250 inet_ntoa(bgp->router_id));
9251 else
9252 vty_out(vty, "(%s)", inet_ntoa(bgp->router_id));
9253 }
d62a17ae 9254
05864da7
DS
9255 /* We RXed this path from one of our peers */
9256 else {
9257
9258 if (json_paths) {
9259 json_object_string_add(json_peer, "peerId",
9260 sockunion2str(&path->peer->su,
9261 buf,
9262 SU_ADDRSTRLEN));
9263 json_object_string_add(json_peer, "routerId",
9264 inet_ntop(AF_INET,
9265 &path->peer->remote_id,
9266 buf1, sizeof(buf1)));
9267
9268 if (path->peer->hostname)
9269 json_object_string_add(json_peer, "hostname",
9270 path->peer->hostname);
9271
9272 if (path->peer->domainname)
9273 json_object_string_add(json_peer, "domainname",
9274 path->peer->domainname);
9275
9276 if (path->peer->conf_if)
9277 json_object_string_add(json_peer, "interface",
9278 path->peer->conf_if);
9279 } else {
9280 if (path->peer->conf_if) {
9281 if (path->peer->hostname
892fedb6
DA
9282 && CHECK_FLAG(path->peer->bgp->flags,
9283 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9284 vty_out(vty, " from %s(%s)",
9285 path->peer->hostname,
9286 path->peer->conf_if);
d62a17ae 9287 else
05864da7 9288 vty_out(vty, " from %s",
9b6d8fcf 9289 path->peer->conf_if);
d62a17ae 9290 } else {
05864da7 9291 if (path->peer->hostname
892fedb6
DA
9292 && CHECK_FLAG(path->peer->bgp->flags,
9293 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9294 vty_out(vty, " from %s(%s)",
9295 path->peer->hostname,
9296 path->peer->host);
d62a17ae 9297 else
05864da7
DS
9298 vty_out(vty, " from %s",
9299 sockunion2str(&path->peer->su,
9300 buf,
9301 SU_ADDRSTRLEN));
d62a17ae 9302 }
d62a17ae 9303
05864da7
DS
9304 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9305 vty_out(vty, " (%s)",
9306 inet_ntoa(attr->originator_id));
9307 else
9308 vty_out(vty, " (%s)",
9309 inet_ntop(AF_INET,
9310 &path->peer->remote_id, buf1,
9311 sizeof(buf1)));
d62a17ae 9312 }
05864da7 9313 }
9df8b37c 9314
05864da7
DS
9315 /*
9316 * Note when vrfid of nexthop is different from that of prefix
9317 */
9318 if (path->extra && path->extra->bgp_orig) {
9319 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9320
05864da7
DS
9321 if (json_paths) {
9322 const char *vn;
9df8b37c 9323
05864da7
DS
9324 if (path->extra->bgp_orig->inst_type
9325 == BGP_INSTANCE_TYPE_DEFAULT)
9326 vn = VRF_DEFAULT_NAME;
9327 else
9328 vn = path->extra->bgp_orig->name;
9df8b37c 9329
05864da7 9330 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9331
05864da7
DS
9332 if (nexthop_vrfid == VRF_UNKNOWN) {
9333 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9334 } else {
05864da7
DS
9335 json_object_int_add(json_path, "nhVrfId",
9336 (int)nexthop_vrfid);
9df8b37c 9337 }
05864da7
DS
9338 } else {
9339 if (nexthop_vrfid == VRF_UNKNOWN)
9340 vty_out(vty, " vrf ?");
137147c6
DS
9341 else {
9342 struct vrf *vrf;
9343
9344 vrf = vrf_lookup_by_id(nexthop_vrfid);
9345 vty_out(vty, " vrf %s(%u)",
9346 VRF_LOGNAME(vrf), nexthop_vrfid);
9347 }
9df8b37c 9348 }
05864da7 9349 }
9df8b37c 9350
05864da7
DS
9351 if (nexthop_self) {
9352 if (json_paths) {
9353 json_object_boolean_true_add(json_path,
9354 "announceNexthopSelf");
9355 } else {
9356 vty_out(vty, " announce-nh-self");
9df8b37c 9357 }
05864da7 9358 }
9df8b37c 9359
05864da7
DS
9360 if (!json_paths)
9361 vty_out(vty, "\n");
d62a17ae 9362
05864da7
DS
9363 /* display the link-local nexthop */
9364 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9365 if (json_paths) {
9366 json_nexthop_ll = json_object_new_object();
9367 json_object_string_add(
515c2602
DA
9368 json_nexthop_ll, "ip",
9369 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9370 buf, INET6_ADDRSTRLEN));
9371
939a97f4 9372 if (path->peer->hostname)
515c2602
DA
9373 json_object_string_add(json_nexthop_ll,
9374 "hostname",
939a97f4 9375 path->peer->hostname);
515c2602 9376
05864da7
DS
9377 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9378 json_object_string_add(json_nexthop_ll, "scope",
9379 "link-local");
d62a17ae 9380
05864da7
DS
9381 json_object_boolean_true_add(json_nexthop_ll,
9382 "accessible");
d62a17ae 9383
05864da7 9384 if (!attr->mp_nexthop_prefer_global)
d62a17ae 9385 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
9386 "used");
9387 else
9388 json_object_boolean_true_add(
9389 json_nexthop_global, "used");
9390 } else {
9391 vty_out(vty, " (%s) %s\n",
9392 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9393 buf, INET6_ADDRSTRLEN),
9394 attr->mp_nexthop_prefer_global
9395 ? "(prefer-global)"
9396 : "(used)");
d62a17ae 9397 }
05864da7
DS
9398 }
9399 /* If we do not have a link-local nexthop then we must flag the
9400 global as "used" */
9401 else {
9402 if (json_paths)
9403 json_object_boolean_true_add(json_nexthop_global,
9404 "used");
9405 }
d62a17ae 9406
b5e140c8 9407 if (safi == SAFI_EVPN &&
5e4d4c8a
AK
9408 bgp_evpn_is_esi_valid(&attr->esi)) {
9409 route_vty_out_detail_es_info(vty, attr, json_path);
b5e140c8
AK
9410 }
9411
05864da7
DS
9412 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
9413 * Int/Ext/Local, Atomic, best */
9414 if (json_paths)
9415 json_object_string_add(json_path, "origin",
9416 bgp_origin_long_str[attr->origin]);
9417 else
9418 vty_out(vty, " Origin %s",
9419 bgp_origin_long_str[attr->origin]);
9df8b37c 9420
05864da7 9421 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 9422 if (json_paths)
05864da7 9423 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 9424 else
05864da7
DS
9425 vty_out(vty, ", metric %u", attr->med);
9426 }
9df8b37c 9427
05864da7
DS
9428 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
9429 if (json_paths)
0fbac0b4 9430 json_object_int_add(json_path, "locPrf",
05864da7
DS
9431 attr->local_pref);
9432 else
9433 vty_out(vty, ", localpref %u", attr->local_pref);
9434 }
9df8b37c 9435
05864da7
DS
9436 if (attr->weight != 0) {
9437 if (json_paths)
9438 json_object_int_add(json_path, "weight", attr->weight);
9439 else
9440 vty_out(vty, ", weight %u", attr->weight);
9441 }
9df8b37c 9442
05864da7
DS
9443 if (attr->tag != 0) {
9444 if (json_paths)
9445 json_object_int_add(json_path, "tag", attr->tag);
9446 else
9447 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
9448 }
9df8b37c 9449
05864da7
DS
9450 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9451 if (json_paths)
9452 json_object_boolean_false_add(json_path, "valid");
9453 else
9454 vty_out(vty, ", invalid");
9455 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9456 if (json_paths)
9457 json_object_boolean_true_add(json_path, "valid");
9458 else
9459 vty_out(vty, ", valid");
9460 }
9df8b37c 9461
05864da7
DS
9462 if (path->peer != bgp->peer_self) {
9463 if (path->peer->as == path->peer->local_as) {
9464 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
9465 if (json_paths)
9466 json_object_string_add(
9467 json_peer, "type",
9468 "confed-internal");
d62a17ae 9469 else
05864da7 9470 vty_out(vty, ", confed-internal");
d62a17ae 9471 } else {
05864da7
DS
9472 if (json_paths)
9473 json_object_string_add(
9474 json_peer, "type", "internal");
9475 else
9476 vty_out(vty, ", internal");
9df8b37c 9477 }
05864da7
DS
9478 } else {
9479 if (bgp_confederation_peers_check(bgp,
9480 path->peer->as)) {
9481 if (json_paths)
9482 json_object_string_add(
9483 json_peer, "type",
9484 "confed-external");
d62a17ae 9485 else
05864da7 9486 vty_out(vty, ", confed-external");
d62a17ae 9487 } else {
05864da7
DS
9488 if (json_paths)
9489 json_object_string_add(
9490 json_peer, "type", "external");
9491 else
9492 vty_out(vty, ", external");
d62a17ae 9493 }
9494 }
05864da7
DS
9495 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
9496 if (json_paths) {
9497 json_object_boolean_true_add(json_path, "aggregated");
9498 json_object_boolean_true_add(json_path, "local");
9499 } else {
9500 vty_out(vty, ", aggregated, local");
9501 }
9502 } else if (path->type != ZEBRA_ROUTE_BGP) {
9503 if (json_paths)
9504 json_object_boolean_true_add(json_path, "sourced");
9505 else
9506 vty_out(vty, ", sourced");
9507 } else {
9508 if (json_paths) {
9509 json_object_boolean_true_add(json_path, "sourced");
9510 json_object_boolean_true_add(json_path, "local");
9511 } else {
9512 vty_out(vty, ", sourced, local");
d62a17ae 9513 }
05864da7 9514 }
718e3744 9515
05864da7 9516 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 9517 if (json_paths)
05864da7
DS
9518 json_object_boolean_true_add(json_path,
9519 "atomicAggregate");
d62a17ae 9520 else
05864da7
DS
9521 vty_out(vty, ", atomic-aggregate");
9522 }
d62a17ae 9523
05864da7
DS
9524 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
9525 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
9526 && bgp_path_info_mpath_count(path))) {
9527 if (json_paths)
9528 json_object_boolean_true_add(json_path, "multipath");
9529 else
9530 vty_out(vty, ", multipath");
9531 }
50e05855 9532
05864da7
DS
9533 // Mark the bestpath(s)
9534 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
9535 first_as = aspath_get_first_as(attr->aspath);
718e3744 9536
05864da7
DS
9537 if (json_paths) {
9538 if (!json_bestpath)
9539 json_bestpath = json_object_new_object();
9540 json_object_int_add(json_bestpath, "bestpathFromAs",
9541 first_as);
9542 } else {
9543 if (first_as)
9544 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 9545 else
05864da7 9546 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 9547 }
05864da7 9548 }
718e3744 9549
05864da7
DS
9550 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
9551 if (json_paths) {
9552 if (!json_bestpath)
9553 json_bestpath = json_object_new_object();
9554 json_object_boolean_true_add(json_bestpath, "overall");
9555 json_object_string_add(
9556 json_bestpath, "selectionReason",
9557 bgp_path_selection_reason2str(bn->reason));
9558 } else {
9559 vty_out(vty, ", best");
9560 vty_out(vty, " (%s)",
9561 bgp_path_selection_reason2str(bn->reason));
d62a17ae 9562 }
05864da7 9563 }
718e3744 9564
05864da7
DS
9565 if (json_bestpath)
9566 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 9567
05864da7
DS
9568 if (!json_paths)
9569 vty_out(vty, "\n");
9570
9571 /* Line 4 display Community */
9572 if (attr->community) {
9573 if (json_paths) {
9574 if (!attr->community->json)
9575 community_str(attr->community, true);
9576 json_object_lock(attr->community->json);
9577 json_object_object_add(json_path, "community",
9578 attr->community->json);
9579 } else {
9580 vty_out(vty, " Community: %s\n",
9581 attr->community->str);
d62a17ae 9582 }
05864da7 9583 }
718e3744 9584
05864da7
DS
9585 /* Line 5 display Extended-community */
9586 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9587 if (json_paths) {
9588 json_ext_community = json_object_new_object();
9589 json_object_string_add(json_ext_community, "string",
9590 attr->ecommunity->str);
9591 json_object_object_add(json_path, "extendedCommunity",
9592 json_ext_community);
d62a17ae 9593 } else {
05864da7
DS
9594 vty_out(vty, " Extended Community: %s\n",
9595 attr->ecommunity->str);
d62a17ae 9596 }
05864da7 9597 }
718e3744 9598
05864da7
DS
9599 /* Line 6 display Large community */
9600 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
9601 if (json_paths) {
9602 if (!attr->lcommunity->json)
9603 lcommunity_str(attr->lcommunity, true);
9604 json_object_lock(attr->lcommunity->json);
9605 json_object_object_add(json_path, "largeCommunity",
9606 attr->lcommunity->json);
9607 } else {
9608 vty_out(vty, " Large Community: %s\n",
9609 attr->lcommunity->str);
d62a17ae 9610 }
05864da7 9611 }
718e3744 9612
05864da7
DS
9613 /* Line 7 display Originator, Cluster-id */
9614 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
9615 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
9616 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 9617 if (json_paths)
05864da7
DS
9618 json_object_string_add(
9619 json_path, "originatorId",
9620 inet_ntoa(attr->originator_id));
d62a17ae 9621 else
05864da7
DS
9622 vty_out(vty, " Originator: %s",
9623 inet_ntoa(attr->originator_id));
d62a17ae 9624 }
856ca177 9625
05864da7
DS
9626 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
9627 int i;
d62a17ae 9628
9629 if (json_paths) {
05864da7
DS
9630 json_cluster_list = json_object_new_object();
9631 json_cluster_list_list =
9632 json_object_new_array();
9633
9634 for (i = 0; i < attr->cluster->length / 4;
9635 i++) {
9636 json_string = json_object_new_string(
9637 inet_ntoa(attr->cluster
9638 ->list[i]));
9639 json_object_array_add(
9640 json_cluster_list_list,
9641 json_string);
9642 }
718e3744 9643
05864da7
DS
9644 /*
9645 * struct cluster_list does not have
9646 * "str" variable like aspath and community
9647 * do. Add this someday if someone asks
9648 * for it.
9649 * json_object_string_add(json_cluster_list,
9650 * "string", attr->cluster->str);
9651 */
9652 json_object_object_add(json_cluster_list,
9653 "list",
9654 json_cluster_list_list);
9655 json_object_object_add(json_path, "clusterList",
9656 json_cluster_list);
0dc8ee70 9657 } else {
05864da7
DS
9658 vty_out(vty, ", Cluster list: ");
9659
9660 for (i = 0; i < attr->cluster->length / 4;
9661 i++) {
9662 vty_out(vty, "%s ",
9663 inet_ntoa(attr->cluster
9664 ->list[i]));
9665 }
0dc8ee70 9666 }
d62a17ae 9667 }
718e3744 9668
d62a17ae 9669 if (!json_paths)
9670 vty_out(vty, "\n");
05864da7 9671 }
d62a17ae 9672
05864da7 9673 if (path->extra && path->extra->damp_info)
a935f597 9674 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 9675
05864da7
DS
9676 /* Remote Label */
9677 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
9678 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
9679 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 9680
05864da7
DS
9681 if (json_paths)
9682 json_object_int_add(json_path, "remoteLabel", label);
9683 else
9684 vty_out(vty, " Remote label: %d\n", label);
9685 }
d62a17ae 9686
e496b420
HS
9687 /* Remote SID */
9688 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
9689 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
9690 if (json_paths)
9691 json_object_string_add(json_path, "remoteSid", buf);
9692 else
9693 vty_out(vty, " Remote SID: %s\n", buf);
9694 }
9695
05864da7
DS
9696 /* Label Index */
9697 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
9698 if (json_paths)
9699 json_object_int_add(json_path, "labelIndex",
9700 attr->label_index);
9701 else
9702 vty_out(vty, " Label Index: %d\n",
9703 attr->label_index);
9704 }
d62a17ae 9705
05864da7
DS
9706 /* Line 8 display Addpath IDs */
9707 if (path->addpath_rx_id
9708 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
9709 if (json_paths) {
9710 json_object_int_add(json_path, "addpathRxId",
9711 path->addpath_rx_id);
d62a17ae 9712
05864da7
DS
9713 /* Keep backwards compatibility with the old API
9714 * by putting TX All's ID in the old field
9715 */
9716 json_object_int_add(
9717 json_path, "addpathTxId",
9718 path->tx_addpath
9719 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 9720
05864da7
DS
9721 /* ... but create a specific field for each
9722 * strategy
9723 */
9724 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9725 json_object_int_add(
9726 json_path,
9727 bgp_addpath_names(i)->id_json_name,
9728 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 9729 }
05864da7
DS
9730 } else {
9731 vty_out(vty, " AddPath ID: RX %u, ",
9732 path->addpath_rx_id);
d62a17ae 9733
05864da7 9734 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 9735 }
05864da7 9736 }
520d5d76 9737
05864da7
DS
9738 /* If we used addpath to TX a non-bestpath we need to display
9739 * "Advertised to" on a path-by-path basis
9740 */
9741 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9742 first = 1;
dcc68b5e 9743
05864da7
DS
9744 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9745 addpath_capable =
9746 bgp_addpath_encode_tx(peer, afi, safi);
9747 has_adj = bgp_adj_out_lookup(
9748 peer, path->net,
9749 bgp_addpath_id_for_peer(peer, afi, safi,
9750 &path->tx_addpath));
9751
9752 if ((addpath_capable && has_adj)
9753 || (!addpath_capable && has_adj
9754 && CHECK_FLAG(path->flags,
9755 BGP_PATH_SELECTED))) {
9756 if (json_path && !json_adv_to)
9757 json_adv_to = json_object_new_object();
dcc68b5e 9758
05864da7
DS
9759 route_vty_out_advertised_to(
9760 vty, peer, &first,
9761 " Advertised to:", json_adv_to);
d62a17ae 9762 }
9763 }
718e3744 9764
05864da7
DS
9765 if (json_path) {
9766 if (json_adv_to) {
9767 json_object_object_add(
9768 json_path, "advertisedTo", json_adv_to);
d62a17ae 9769 }
05864da7
DS
9770 } else {
9771 if (!first) {
9772 vty_out(vty, "\n");
d62a17ae 9773 }
9774 }
05864da7 9775 }
b05a1c8b 9776
05864da7
DS
9777 /* Line 9 display Uptime */
9778 tbuf = time(NULL) - (bgp_clock() - path->uptime);
9779 if (json_paths) {
9780 json_last_update = json_object_new_object();
9781 json_object_int_add(json_last_update, "epoch", tbuf);
9782 json_object_string_add(json_last_update, "string",
9783 ctime(&tbuf));
9784 json_object_object_add(json_path, "lastUpdate",
9785 json_last_update);
9786 } else
9787 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 9788
05864da7
DS
9789 /* Line 10 display PMSI tunnel attribute, if present */
9790 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
9791 const char *str =
9792 lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
9793 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 9794
05864da7
DS
9795 if (json_paths) {
9796 json_pmsi = json_object_new_object();
9797 json_object_string_add(json_pmsi, "tunnelType", str);
9798 json_object_int_add(json_pmsi, "label",
9799 label2vni(&attr->label));
9800 json_object_object_add(json_path, "pmsi", json_pmsi);
9801 } else
9802 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
9803 str, label2vni(&attr->label));
d62a17ae 9804 }
f1aa5d8a 9805
d62a17ae 9806 /* We've constructed the json object for this path, add it to the json
9807 * array of paths
9808 */
9809 if (json_paths) {
9810 if (json_nexthop_global || json_nexthop_ll) {
9811 json_nexthops = json_object_new_array();
f1aa5d8a 9812
d62a17ae 9813 if (json_nexthop_global)
9814 json_object_array_add(json_nexthops,
9815 json_nexthop_global);
f1aa5d8a 9816
d62a17ae 9817 if (json_nexthop_ll)
9818 json_object_array_add(json_nexthops,
9819 json_nexthop_ll);
f1aa5d8a 9820
d62a17ae 9821 json_object_object_add(json_path, "nexthops",
9822 json_nexthops);
9823 }
9824
9825 json_object_object_add(json_path, "peer", json_peer);
9826 json_object_array_add(json_paths, json_path);
05864da7 9827 }
b366b518
BB
9828}
9829
96ade3ed 9830#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
9831#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
9832#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 9833
d62a17ae 9834static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
9835 const char *prefix_list_str, afi_t afi,
9836 safi_t safi, enum bgp_show_type type);
9837static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
9838 const char *filter, afi_t afi, safi_t safi,
9839 enum bgp_show_type type);
9840static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
9841 const char *rmap_str, afi_t afi, safi_t safi,
9842 enum bgp_show_type type);
9843static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
9844 const char *com, int exact, afi_t afi,
9845 safi_t safi);
9846static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
9847 const char *prefix, afi_t afi, safi_t safi,
9848 enum bgp_show_type type);
a4d82a8a 9849static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
9850 afi_t afi, safi_t safi, enum bgp_show_type type,
9851 bool use_json);
7f323236
DW
9852static int bgp_show_community(struct vty *vty, struct bgp *bgp,
9853 const char *comstr, int exact, afi_t afi,
96f3485c 9854 safi_t safi, uint8_t show_flags);
d62a17ae 9855
1ae44dfc
LB
9856
9857static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 9858 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
9859 void *output_arg, char *rd, int is_last,
9860 unsigned long *output_cum, unsigned long *total_cum,
9861 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 9862{
40381db7 9863 struct bgp_path_info *pi;
9bcb3eef 9864 struct bgp_dest *dest;
d62a17ae 9865 int header = 1;
9866 int display;
1ae44dfc
LB
9867 unsigned long output_count = 0;
9868 unsigned long total_count = 0;
d62a17ae 9869 struct prefix *p;
d62a17ae 9870 json_object *json_paths = NULL;
9871 int first = 1;
96f3485c
MK
9872 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
9873 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
9874 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 9875
1ae44dfc
LB
9876 if (output_cum && *output_cum != 0)
9877 header = 0;
9878
9386b588 9879 if (use_json && !*json_header_depth) {
96f3485c
MK
9880 if (all)
9881 *json_header_depth = 1;
9882 else {
9883 vty_out(vty, "{\n");
9884 *json_header_depth = 2;
9885 }
9886
d62a17ae 9887 vty_out(vty,
96f3485c 9888 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
01eced22 9889 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9890 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9891 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9892 ? VRF_DEFAULT_NAME
9893 : bgp->name,
01eced22
AD
9894 table->version, inet_ntoa(bgp->router_id),
9895 bgp->default_local_pref, bgp->as);
9386b588 9896 if (rd) {
445c2480 9897 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9898 ++*json_header_depth;
9899 }
d62a17ae 9900 }
718e3744 9901
445c2480
DS
9902 if (use_json && rd) {
9903 vty_out(vty, " \"%s\" : { ", rd);
9904 }
9905
d62a17ae 9906 /* Start processing of routes. */
9bcb3eef
DS
9907 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
9908 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9909
9bcb3eef 9910 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 9911 if (pi == NULL)
98ce9a06 9912 continue;
d62a17ae 9913
98ce9a06 9914 display = 0;
98ce9a06
DS
9915 if (use_json)
9916 json_paths = json_object_new_array();
9917 else
9918 json_paths = NULL;
d62a17ae 9919
6f94b685 9920 for (; pi; pi = pi->next) {
98ce9a06
DS
9921 total_count++;
9922 if (type == bgp_show_type_flap_statistics
9923 || type == bgp_show_type_flap_neighbor
9924 || type == bgp_show_type_dampend_paths
9925 || type == bgp_show_type_damp_neighbor) {
40381db7 9926 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9927 continue;
9928 }
9929 if (type == bgp_show_type_regexp) {
9930 regex_t *regex = output_arg;
d62a17ae 9931
40381db7 9932 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9933 == REG_NOMATCH)
9934 continue;
9935 }
9936 if (type == bgp_show_type_prefix_list) {
9937 struct prefix_list *plist = output_arg;
d62a17ae 9938
9bcb3eef 9939 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
9940 != PREFIX_PERMIT)
9941 continue;
9942 }
9943 if (type == bgp_show_type_filter_list) {
9944 struct as_list *as_list = output_arg;
d62a17ae 9945
40381db7 9946 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9947 != AS_FILTER_PERMIT)
9948 continue;
9949 }
9950 if (type == bgp_show_type_route_map) {
9951 struct route_map *rmap = output_arg;
9b6d8fcf 9952 struct bgp_path_info path;
98ce9a06 9953 struct attr dummy_attr;
b68885f9 9954 route_map_result_t ret;
d62a17ae 9955
6f4f49b2 9956 dummy_attr = *pi->attr;
d62a17ae 9957
40381db7 9958 path.peer = pi->peer;
9b6d8fcf 9959 path.attr = &dummy_attr;
d62a17ae 9960
9bcb3eef 9961 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 9962 &path);
98ce9a06
DS
9963 if (ret == RMAP_DENYMATCH)
9964 continue;
9965 }
9966 if (type == bgp_show_type_neighbor
9967 || type == bgp_show_type_flap_neighbor
9968 || type == bgp_show_type_damp_neighbor) {
9969 union sockunion *su = output_arg;
9970
40381db7
DS
9971 if (pi->peer == NULL
9972 || pi->peer->su_remote == NULL
9973 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9974 continue;
9975 }
9976 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9977 uint32_t destination;
d62a17ae 9978
9bcb3eef 9979 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 9980 if (IN_CLASSC(destination)
9bcb3eef 9981 && dest_p->prefixlen == 24)
98ce9a06
DS
9982 continue;
9983 if (IN_CLASSB(destination)
9bcb3eef 9984 && dest_p->prefixlen == 16)
98ce9a06
DS
9985 continue;
9986 if (IN_CLASSA(destination)
9bcb3eef 9987 && dest_p->prefixlen == 8)
98ce9a06
DS
9988 continue;
9989 }
9990 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9991 p = output_arg;
9bcb3eef 9992 if (!prefix_match(p, dest_p))
98ce9a06
DS
9993 continue;
9994 }
9995 if (type == bgp_show_type_community_all) {
40381db7 9996 if (!pi->attr->community)
98ce9a06
DS
9997 continue;
9998 }
9999 if (type == bgp_show_type_community) {
10000 struct community *com = output_arg;
d62a17ae 10001
40381db7
DS
10002 if (!pi->attr->community
10003 || !community_match(pi->attr->community,
98ce9a06
DS
10004 com))
10005 continue;
10006 }
10007 if (type == bgp_show_type_community_exact) {
10008 struct community *com = output_arg;
d62a17ae 10009
40381db7
DS
10010 if (!pi->attr->community
10011 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10012 continue;
10013 }
10014 if (type == bgp_show_type_community_list) {
10015 struct community_list *list = output_arg;
d62a17ae 10016
40381db7 10017 if (!community_list_match(pi->attr->community,
a4d82a8a 10018 list))
98ce9a06
DS
10019 continue;
10020 }
a4d82a8a 10021 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10022 struct community_list *list = output_arg;
d62a17ae 10023
98ce9a06 10024 if (!community_list_exact_match(
40381db7 10025 pi->attr->community, list))
98ce9a06
DS
10026 continue;
10027 }
10028 if (type == bgp_show_type_lcommunity) {
10029 struct lcommunity *lcom = output_arg;
d62a17ae 10030
40381db7
DS
10031 if (!pi->attr->lcommunity
10032 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10033 lcom))
10034 continue;
10035 }
36a206db 10036
10037 if (type == bgp_show_type_lcommunity_exact) {
10038 struct lcommunity *lcom = output_arg;
10039
10040 if (!pi->attr->lcommunity
10041 || !lcommunity_cmp(pi->attr->lcommunity,
10042 lcom))
10043 continue;
10044 }
98ce9a06
DS
10045 if (type == bgp_show_type_lcommunity_list) {
10046 struct community_list *list = output_arg;
d62a17ae 10047
40381db7 10048 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10049 list))
98ce9a06
DS
10050 continue;
10051 }
36a206db 10052 if (type
10053 == bgp_show_type_lcommunity_list_exact) {
10054 struct community_list *list = output_arg;
10055
10056 if (!lcommunity_list_exact_match(
10057 pi->attr->lcommunity, list))
10058 continue;
10059 }
98ce9a06 10060 if (type == bgp_show_type_lcommunity_all) {
40381db7 10061 if (!pi->attr->lcommunity)
98ce9a06
DS
10062 continue;
10063 }
10064 if (type == bgp_show_type_dampend_paths
10065 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10066 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10067 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10068 continue;
10069 }
10070
10071 if (!use_json && header) {
6cde4b45 10072 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
98ce9a06
DS
10073 table->version,
10074 inet_ntoa(bgp->router_id));
9df8b37c
PZ
10075 if (bgp->vrf_id == VRF_UNKNOWN)
10076 vty_out(vty, "%s", VRFID_NONE_STR);
10077 else
10078 vty_out(vty, "%u", bgp->vrf_id);
10079 vty_out(vty, "\n");
01eced22
AD
10080 vty_out(vty, "Default local pref %u, ",
10081 bgp->default_local_pref);
10082 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10083 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10084 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10085 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10086 if (type == bgp_show_type_dampend_paths
10087 || type == bgp_show_type_damp_neighbor)
98ce9a06 10088 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10089 else if (type == bgp_show_type_flap_statistics
10090 || type == bgp_show_type_flap_neighbor)
98ce9a06 10091 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10092 else
ae248832
MK
10093 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10094 : BGP_SHOW_HEADER));
98ce9a06 10095 header = 0;
d62a17ae 10096 }
98ce9a06
DS
10097 if (rd != NULL && !display && !output_count) {
10098 if (!use_json)
10099 vty_out(vty,
10100 "Route Distinguisher: %s\n",
10101 rd);
d62a17ae 10102 }
98ce9a06
DS
10103 if (type == bgp_show_type_dampend_paths
10104 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10105 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10106 AFI_IP, safi, use_json,
10107 json_paths);
98ce9a06
DS
10108 else if (type == bgp_show_type_flap_statistics
10109 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10110 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10111 AFI_IP, safi, use_json,
10112 json_paths);
98ce9a06 10113 else
9bcb3eef 10114 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10115 json_paths, wide);
98ce9a06 10116 display++;
d62a17ae 10117 }
10118
98ce9a06
DS
10119 if (display) {
10120 output_count++;
10121 if (!use_json)
10122 continue;
10123
625d2931 10124 /* encode prefix */
9bcb3eef 10125 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10126 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10127
1840384b 10128
b54892e0
DS
10129 bgp_fs_nlri_get_string(
10130 (unsigned char *)
9bcb3eef
DS
10131 dest_p->u.prefix_flowspec.ptr,
10132 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10133 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10134 family2afi(dest_p->u
10135 .prefix_flowspec.family));
625d2931 10136 if (first)
b54892e0 10137 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10138 dest_p->u.prefix_flowspec
b54892e0 10139 .prefixlen);
625d2931 10140 else
b54892e0 10141 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10142 dest_p->u.prefix_flowspec
b54892e0 10143 .prefixlen);
625d2931 10144 } else {
625d2931 10145 if (first)
1b78780b 10146 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10147 else
1b78780b 10148 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10149 }
98ce9a06 10150 vty_out(vty, "%s",
f4ec52f7
DA
10151 json_object_to_json_string_ext(
10152 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10153 json_object_free(json_paths);
449feb8e 10154 json_paths = NULL;
98ce9a06 10155 first = 0;
1f83ed02
DS
10156 } else
10157 json_object_free(json_paths);
98ce9a06
DS
10158 }
10159
1ae44dfc
LB
10160 if (output_cum) {
10161 output_count += *output_cum;
10162 *output_cum = output_count;
10163 }
10164 if (total_cum) {
10165 total_count += *total_cum;
10166 *total_cum = total_count;
10167 }
d62a17ae 10168 if (use_json) {
9386b588 10169 if (rd) {
a4d82a8a 10170 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10171 }
10172 if (is_last) {
a4d82a8a
PZ
10173 unsigned long i;
10174 for (i = 0; i < *json_header_depth; ++i)
10175 vty_out(vty, " } ");
96f3485c
MK
10176 if (!all)
10177 vty_out(vty, "\n");
9386b588 10178 }
d62a17ae 10179 } else {
1ae44dfc
LB
10180 if (is_last) {
10181 /* No route is displayed */
10182 if (output_count == 0) {
10183 if (type == bgp_show_type_normal)
10184 vty_out(vty,
10185 "No BGP prefixes displayed, %ld exist\n",
10186 total_count);
10187 } else
d62a17ae 10188 vty_out(vty,
1ae44dfc
LB
10189 "\nDisplayed %ld routes and %ld total paths\n",
10190 output_count, total_count);
10191 }
d62a17ae 10192 }
718e3744 10193
d62a17ae 10194 return CMD_SUCCESS;
718e3744 10195}
10196
1ae44dfc
LB
10197int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10198 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10199 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10200{
9bcb3eef 10201 struct bgp_dest *dest, *next;
1ae44dfc
LB
10202 unsigned long output_cum = 0;
10203 unsigned long total_cum = 0;
9386b588 10204 unsigned long json_header_depth = 0;
67009e22 10205 struct bgp_table *itable;
0136788c 10206 bool show_msg;
96f3485c 10207 uint8_t show_flags = 0;
0136788c
LB
10208
10209 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10210
96f3485c
MK
10211 if (use_json)
10212 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10213
9bcb3eef
DS
10214 for (dest = bgp_table_top(table); dest; dest = next) {
10215 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10216
9bcb3eef
DS
10217 next = bgp_route_next(dest);
10218 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10219 continue;
67009e22 10220
9bcb3eef 10221 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10222 if (itable != NULL) {
1ae44dfc 10223 struct prefix_rd prd;
06b9f471 10224 char rd[RD_ADDRSTRLEN];
1ae44dfc 10225
9bcb3eef 10226 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10227 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10228 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10229 rd, next == NULL, &output_cum,
10230 &total_cum, &json_header_depth,
10231 show_flags);
0136788c
LB
10232 if (next == NULL)
10233 show_msg = false;
1ae44dfc
LB
10234 }
10235 }
0136788c
LB
10236 if (show_msg) {
10237 if (output_cum == 0)
10238 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10239 total_cum);
10240 else
10241 vty_out(vty,
10242 "\nDisplayed %ld routes and %ld total paths\n",
10243 output_cum, total_cum);
10244 }
1ae44dfc
LB
10245 return CMD_SUCCESS;
10246}
d62a17ae 10247static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10248 enum bgp_show_type type, void *output_arg,
10249 uint8_t show_flags)
fee0f4c6 10250{
d62a17ae 10251 struct bgp_table *table;
9386b588 10252 unsigned long json_header_depth = 0;
96f3485c 10253 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10254
d62a17ae 10255 if (bgp == NULL) {
10256 bgp = bgp_get_default();
10257 }
fee0f4c6 10258
d62a17ae 10259 if (bgp == NULL) {
10260 if (!use_json)
10261 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10262 else
10263 vty_out(vty, "{}\n");
d62a17ae 10264 return CMD_WARNING;
10265 }
4dd6177e 10266
1ae44dfc 10267 table = bgp->rib[afi][safi];
d62a17ae 10268 /* use MPLS and ENCAP specific shows until they are merged */
10269 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10270 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10271 output_arg, use_json);
d62a17ae 10272 }
dba3c1d3
PG
10273
10274 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10275 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10276 output_arg, use_json,
10277 1, NULL, NULL);
10278 }
d62a17ae 10279 /* labeled-unicast routes live in the unicast table */
10280 else if (safi == SAFI_LABELED_UNICAST)
10281 safi = SAFI_UNICAST;
fee0f4c6 10282
96f3485c
MK
10283 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10284 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10285}
10286
d62a17ae 10287static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10288 safi_t safi, uint8_t show_flags)
f186de26 10289{
d62a17ae 10290 struct listnode *node, *nnode;
10291 struct bgp *bgp;
10292 int is_first = 1;
9f049418 10293 bool route_output = false;
96f3485c 10294 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10295
d62a17ae 10296 if (use_json)
10297 vty_out(vty, "{\n");
9f689658 10298
d62a17ae 10299 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10300 route_output = true;
d62a17ae 10301 if (use_json) {
10302 if (!is_first)
10303 vty_out(vty, ",\n");
10304 else
10305 is_first = 0;
10306
10307 vty_out(vty, "\"%s\":",
10308 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10309 ? VRF_DEFAULT_NAME
d62a17ae 10310 : bgp->name);
10311 } else {
10312 vty_out(vty, "\nInstance %s:\n",
10313 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10314 ? VRF_DEFAULT_NAME
d62a17ae 10315 : bgp->name);
10316 }
10317 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10318 show_flags);
d62a17ae 10319 }
9f689658 10320
d62a17ae 10321 if (use_json)
10322 vty_out(vty, "}\n");
9f049418
DS
10323 else if (!route_output)
10324 vty_out(vty, "%% BGP instance not found\n");
f186de26 10325}
10326
718e3744 10327/* Header of detailed BGP route information */
d62a17ae 10328void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10329 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10330 afi_t afi, safi_t safi, json_object *json)
10331{
40381db7 10332 struct bgp_path_info *pi;
b54892e0 10333 const struct prefix *p;
d62a17ae 10334 struct peer *peer;
10335 struct listnode *node, *nnode;
06b9f471 10336 char buf1[RD_ADDRSTRLEN];
d62a17ae 10337 char buf2[INET6_ADDRSTRLEN];
d62a17ae 10338 char buf3[EVPN_ROUTE_STRLEN];
0291c246 10339 char prefix_str[BUFSIZ];
d62a17ae 10340 int count = 0;
10341 int best = 0;
10342 int suppress = 0;
c5f1e1b2
C
10343 int accept_own = 0;
10344 int route_filter_translated_v4 = 0;
10345 int route_filter_v4 = 0;
10346 int route_filter_translated_v6 = 0;
10347 int route_filter_v6 = 0;
10348 int llgr_stale = 0;
10349 int no_llgr = 0;
10350 int accept_own_nexthop = 0;
10351 int blackhole = 0;
d62a17ae 10352 int no_export = 0;
10353 int no_advertise = 0;
10354 int local_as = 0;
c5f1e1b2 10355 int no_peer = 0;
d62a17ae 10356 int first = 1;
10357 int has_valid_label = 0;
10358 mpls_label_t label = 0;
10359 json_object *json_adv_to = NULL;
9bedbb1e 10360
9bcb3eef
DS
10361 p = bgp_dest_get_prefix(dest);
10362 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10363
10364 if (has_valid_label)
9bcb3eef 10365 label = label_pton(&dest->local_label);
d62a17ae 10366
44c69747 10367 if (safi == SAFI_EVPN) {
d62a17ae 10368
44c69747 10369 if (!json) {
d62a17ae 10370 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 10371 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 10372 : "", prd ? ":" : "",
d62a17ae 10373 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
10374 buf3, sizeof(buf3)));
10375 } else {
10376 json_object_string_add(json, "rd",
10377 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10378 "");
10379 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10380 }
10381 } else {
10382 if (!json) {
d62a17ae 10383 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
10384 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
10385 ? prefix_rd2str(prd, buf1,
10386 sizeof(buf1))
10387 : ""),
d62a17ae 10388 safi == SAFI_MPLS_VPN ? ":" : "",
10389 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 10390 INET6_ADDRSTRLEN),
d62a17ae 10391 p->prefixlen);
cd1964ff 10392
44c69747
LK
10393 } else
10394 json_object_string_add(json, "prefix",
10395 prefix2str(p, prefix_str, sizeof(prefix_str)));
10396 }
10397
10398 if (has_valid_label) {
10399 if (json)
10400 json_object_int_add(json, "localLabel", label);
10401 else
d62a17ae 10402 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10403 }
10404
10405 if (!json)
d62a17ae 10406 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10407 vty_out(vty, "not allocated\n");
718e3744 10408
9bcb3eef 10409 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10410 count++;
40381db7 10411 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10412 best = count;
40381db7 10413 if (pi->extra && pi->extra->suppress)
d62a17ae 10414 suppress = 1;
cee9c031 10415
40381db7 10416 if (pi->attr->community == NULL)
cee9c031
QY
10417 continue;
10418
10419 no_advertise += community_include(
40381db7
DS
10420 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10421 no_export += community_include(pi->attr->community,
cee9c031 10422 COMMUNITY_NO_EXPORT);
40381db7 10423 local_as += community_include(pi->attr->community,
cee9c031 10424 COMMUNITY_LOCAL_AS);
40381db7 10425 accept_own += community_include(pi->attr->community,
cee9c031
QY
10426 COMMUNITY_ACCEPT_OWN);
10427 route_filter_translated_v4 += community_include(
40381db7 10428 pi->attr->community,
cee9c031
QY
10429 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10430 route_filter_translated_v6 += community_include(
40381db7 10431 pi->attr->community,
cee9c031
QY
10432 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10433 route_filter_v4 += community_include(
40381db7 10434 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10435 route_filter_v6 += community_include(
40381db7
DS
10436 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10437 llgr_stale += community_include(pi->attr->community,
cee9c031 10438 COMMUNITY_LLGR_STALE);
40381db7 10439 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10440 COMMUNITY_NO_LLGR);
10441 accept_own_nexthop +=
40381db7 10442 community_include(pi->attr->community,
cee9c031 10443 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10444 blackhole += community_include(pi->attr->community,
cee9c031 10445 COMMUNITY_BLACKHOLE);
40381db7 10446 no_peer += community_include(pi->attr->community,
cee9c031 10447 COMMUNITY_NO_PEER);
d62a17ae 10448 }
718e3744 10449 }
718e3744 10450
d62a17ae 10451 if (!json) {
10452 vty_out(vty, "Paths: (%d available", count);
10453 if (best) {
10454 vty_out(vty, ", best #%d", best);
b84060bb
PG
10455 if (safi == SAFI_UNICAST) {
10456 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10457 vty_out(vty, ", table %s",
10458 VRF_DEFAULT_NAME);
10459 else
10460 vty_out(vty, ", vrf %s",
10461 bgp->name);
10462 }
d62a17ae 10463 } else
10464 vty_out(vty, ", no best path");
10465
c5f1e1b2
C
10466 if (accept_own)
10467 vty_out(vty,
10468 ", accept own local route exported and imported in different VRF");
10469 else if (route_filter_translated_v4)
10470 vty_out(vty,
10471 ", mark translated RTs for VPNv4 route filtering");
10472 else if (route_filter_v4)
10473 vty_out(vty,
10474 ", attach RT as-is for VPNv4 route filtering");
10475 else if (route_filter_translated_v6)
10476 vty_out(vty,
10477 ", mark translated RTs for VPNv6 route filtering");
10478 else if (route_filter_v6)
10479 vty_out(vty,
10480 ", attach RT as-is for VPNv6 route filtering");
10481 else if (llgr_stale)
10482 vty_out(vty,
10483 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10484 else if (no_llgr)
10485 vty_out(vty,
10486 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10487 else if (accept_own_nexthop)
10488 vty_out(vty,
10489 ", accept local nexthop");
10490 else if (blackhole)
10491 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10492 else if (no_export)
10493 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10494 else if (no_advertise)
10495 vty_out(vty, ", not advertised to any peer");
d62a17ae 10496 else if (local_as)
10497 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10498 else if (no_peer)
10499 vty_out(vty,
10500 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10501
10502 if (suppress)
10503 vty_out(vty,
10504 ", Advertisements suppressed by an aggregate.");
10505 vty_out(vty, ")\n");
10506 }
718e3744 10507
d62a17ae 10508 /* If we are not using addpath then we can display Advertised to and
10509 * that will
10510 * show what peers we advertised the bestpath to. If we are using
10511 * addpath
10512 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10513 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10514 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10515 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10516 if (json && !json_adv_to)
10517 json_adv_to = json_object_new_object();
10518
10519 route_vty_out_advertised_to(
10520 vty, peer, &first,
10521 " Advertised to non peer-group peers:\n ",
10522 json_adv_to);
10523 }
10524 }
10525
10526 if (json) {
10527 if (json_adv_to) {
10528 json_object_object_add(json, "advertisedTo",
10529 json_adv_to);
10530 }
10531 } else {
10532 if (first)
10533 vty_out(vty, " Not advertised to any peer");
10534 vty_out(vty, "\n");
10535 }
10536 }
718e3744 10537}
10538
44c69747 10539static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10540 struct bgp_dest *bgp_node, struct vty *vty,
10541 struct bgp *bgp, afi_t afi, safi_t safi,
10542 json_object *json, enum bgp_path_type pathtype,
10543 int *display)
44c69747
LK
10544{
10545 struct bgp_path_info *pi;
10546 int header = 1;
10547 char rdbuf[RD_ADDRSTRLEN];
10548 json_object *json_header = NULL;
10549 json_object *json_paths = NULL;
10550
9bcb3eef 10551 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10552
10553 if (json && !json_paths) {
10554 /* Instantiate json_paths only if path is valid */
10555 json_paths = json_object_new_array();
10556 if (pfx_rd) {
10557 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10558 json_header = json_object_new_object();
10559 } else
10560 json_header = json;
10561 }
10562
10563 if (header) {
10564 route_vty_out_detail_header(
10565 vty, bgp, bgp_node, pfx_rd,
10566 AFI_IP, safi, json_header);
10567 header = 0;
10568 }
10569 (*display)++;
10570
10571 if (pathtype == BGP_PATH_SHOW_ALL
10572 || (pathtype == BGP_PATH_SHOW_BESTPATH
10573 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10574 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10575 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10576 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10577 route_vty_out_detail(vty, bgp, bgp_node,
10578 pi, AFI_IP, safi,
10579 json_paths);
10580 }
10581
10582 if (json && json_paths) {
10583 json_object_object_add(json_header, "paths", json_paths);
10584
10585 if (pfx_rd)
10586 json_object_object_add(json, rdbuf, json_header);
10587 }
10588}
10589
718e3744 10590/* Display specified route of BGP table. */
d62a17ae 10591static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10592 struct bgp_table *rib, const char *ip_str,
10593 afi_t afi, safi_t safi,
10594 struct prefix_rd *prd, int prefix_check,
9f049418 10595 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10596{
10597 int ret;
d62a17ae 10598 int display = 0;
10599 struct prefix match;
9bcb3eef
DS
10600 struct bgp_dest *dest;
10601 struct bgp_dest *rm;
d62a17ae 10602 struct bgp_table *table;
10603 json_object *json = NULL;
10604 json_object *json_paths = NULL;
10605
10606 /* Check IP address argument. */
10607 ret = str2prefix(ip_str, &match);
10608 if (!ret) {
10609 vty_out(vty, "address is malformed\n");
10610 return CMD_WARNING;
10611 }
718e3744 10612
d62a17ae 10613 match.family = afi2family(afi);
b05a1c8b 10614
44c69747 10615 if (use_json)
d62a17ae 10616 json = json_object_new_object();
718e3744 10617
44c69747 10618 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
10619 for (dest = bgp_table_top(rib); dest;
10620 dest = bgp_route_next(dest)) {
10621 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10622
9bcb3eef 10623 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 10624 continue;
9bcb3eef 10625 table = bgp_dest_get_bgp_table_info(dest);
67009e22 10626 if (!table)
ea47320b 10627 continue;
d62a17ae 10628
ea47320b
DL
10629 if ((rm = bgp_node_match(table, &match)) == NULL)
10630 continue;
d62a17ae 10631
9bcb3eef 10632 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 10633 if (prefix_check
b54892e0 10634 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 10635 bgp_dest_unlock_node(rm);
ea47320b
DL
10636 continue;
10637 }
d62a17ae 10638
9bcb3eef 10639 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10640 bgp, afi, safi, json, pathtype,
10641 &display);
44c69747 10642
9bcb3eef 10643 bgp_dest_unlock_node(rm);
44c69747
LK
10644 }
10645 } else if (safi == SAFI_EVPN) {
9bcb3eef 10646 struct bgp_dest *longest_pfx;
cded3b72 10647 bool is_exact_pfxlen_match = false;
44c69747 10648
9bcb3eef
DS
10649 for (dest = bgp_table_top(rib); dest;
10650 dest = bgp_route_next(dest)) {
10651 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10652
9bcb3eef 10653 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 10654 continue;
9bcb3eef 10655 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
10656 if (!table)
10657 continue;
10658
10659 longest_pfx = NULL;
cded3b72 10660 is_exact_pfxlen_match = false;
44c69747
LK
10661 /*
10662 * Search through all the prefixes for a match. The
10663 * pfx's are enumerated in ascending order of pfxlens.
10664 * So, the last pfx match is the longest match. Set
10665 * is_exact_pfxlen_match when we get exact pfxlen match
10666 */
10667 for (rm = bgp_table_top(table); rm;
10668 rm = bgp_route_next(rm)) {
b54892e0 10669 const struct prefix *rm_p =
9bcb3eef 10670 bgp_dest_get_prefix(rm);
44c69747
LK
10671 /*
10672 * Get prefixlen of the ip-prefix within type5
10673 * evpn route
10674 */
b54892e0
DS
10675 if (evpn_type5_prefix_match(rm_p, &match)
10676 && rm->info) {
44c69747
LK
10677 longest_pfx = rm;
10678 int type5_pfxlen =
b54892e0
DS
10679 bgp_evpn_get_type5_prefixlen(
10680 rm_p);
44c69747 10681 if (type5_pfxlen == match.prefixlen) {
cded3b72 10682 is_exact_pfxlen_match = true;
9bcb3eef 10683 bgp_dest_unlock_node(rm);
44c69747
LK
10684 break;
10685 }
d62a17ae 10686 }
10687 }
ea47320b 10688
44c69747
LK
10689 if (!longest_pfx)
10690 continue;
10691
10692 if (prefix_check && !is_exact_pfxlen_match)
10693 continue;
10694
10695 rm = longest_pfx;
9bcb3eef 10696 bgp_dest_lock_node(rm);
44c69747 10697
9bcb3eef 10698 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10699 bgp, afi, safi, json, pathtype,
10700 &display);
44c69747 10701
9bcb3eef 10702 bgp_dest_unlock_node(rm);
d62a17ae 10703 }
98a9dbc7 10704 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10705 if (use_json)
10706 json_paths = json_object_new_array();
10707
63a0b7a9
PG
10708 display = bgp_flowspec_display_match_per_ip(afi, rib,
10709 &match, prefix_check,
10710 vty,
10711 use_json,
10712 json_paths);
44c69747
LK
10713 if (use_json && display)
10714 json_object_object_add(json, "paths", json_paths);
d62a17ae 10715 } else {
9bcb3eef
DS
10716 if ((dest = bgp_node_match(rib, &match)) != NULL) {
10717 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 10718 if (!prefix_check
9bcb3eef
DS
10719 || dest_p->prefixlen == match.prefixlen) {
10720 bgp_show_path_info(NULL, dest, vty, bgp, afi,
10721 safi, json, pathtype,
10722 &display);
d62a17ae 10723 }
10724
9bcb3eef 10725 bgp_dest_unlock_node(dest);
d62a17ae 10726 }
10727 }
e5eee9af 10728
d62a17ae 10729 if (use_json) {
996c9314 10730 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10731 json, JSON_C_TO_STRING_PRETTY |
10732 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10733 json_object_free(json);
10734 } else {
10735 if (!display) {
10736 vty_out(vty, "%% Network not in table\n");
10737 return CMD_WARNING;
10738 }
10739 }
b05a1c8b 10740
d62a17ae 10741 return CMD_SUCCESS;
718e3744 10742}
10743
fee0f4c6 10744/* Display specified route of Main RIB */
d62a17ae 10745static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10746 afi_t afi, safi_t safi, struct prefix_rd *prd,
10747 int prefix_check, enum bgp_path_type pathtype,
9f049418 10748 bool use_json)
d62a17ae 10749{
9b86009a 10750 if (!bgp) {
d62a17ae 10751 bgp = bgp_get_default();
9b86009a
RW
10752 if (!bgp) {
10753 if (!use_json)
10754 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10755 else
10756 vty_out(vty, "{}\n");
9b86009a
RW
10757 return CMD_WARNING;
10758 }
10759 }
d62a17ae 10760
10761 /* labeled-unicast routes live in the unicast table */
10762 if (safi == SAFI_LABELED_UNICAST)
10763 safi = SAFI_UNICAST;
10764
10765 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10766 afi, safi, prd, prefix_check, pathtype,
10767 use_json);
10768}
10769
10770static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10771 struct cmd_token **argv, bool exact, afi_t afi,
10772 safi_t safi, bool uj)
d62a17ae 10773{
10774 struct lcommunity *lcom;
10775 struct buffer *b;
10776 int i;
10777 char *str;
10778 int first = 0;
96f3485c
MK
10779 uint8_t show_flags = 0;
10780
10781 if (uj)
10782 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 10783
10784 b = buffer_new(1024);
10785 for (i = 0; i < argc; i++) {
10786 if (first)
10787 buffer_putc(b, ' ');
10788 else {
10789 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10790 first = 1;
10791 buffer_putstr(b, argv[i]->arg);
10792 }
10793 }
10794 }
10795 buffer_putc(b, '\0');
57d187bc 10796
d62a17ae 10797 str = buffer_getstr(b);
10798 buffer_free(b);
57d187bc 10799
d62a17ae 10800 lcom = lcommunity_str2com(str);
10801 XFREE(MTYPE_TMP, str);
10802 if (!lcom) {
10803 vty_out(vty, "%% Large-community malformed\n");
10804 return CMD_WARNING;
10805 }
57d187bc 10806
36a206db 10807 return bgp_show(vty, bgp, afi, safi,
10808 (exact ? bgp_show_type_lcommunity_exact
ae248832 10809 : bgp_show_type_lcommunity),
96f3485c 10810 lcom, show_flags);
57d187bc
JS
10811}
10812
d62a17ae 10813static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10814 const char *lcom, bool exact, afi_t afi,
10815 safi_t safi, bool uj)
57d187bc 10816{
d62a17ae 10817 struct community_list *list;
96f3485c
MK
10818 uint8_t show_flags = 0;
10819
10820 if (uj)
10821 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10822
57d187bc 10823
e237b0d2 10824 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10825 LARGE_COMMUNITY_LIST_MASTER);
10826 if (list == NULL) {
10827 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10828 lcom);
10829 return CMD_WARNING;
10830 }
57d187bc 10831
36a206db 10832 return bgp_show(vty, bgp, afi, safi,
10833 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 10834 : bgp_show_type_lcommunity_list),
96f3485c 10835 list, show_flags);
fee0f4c6 10836}
10837
52951b63
DS
10838DEFUN (show_ip_bgp_large_community_list,
10839 show_ip_bgp_large_community_list_cmd,
36a206db 10840 "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
10841 SHOW_STR
10842 IP_STR
10843 BGP_STR
10844 BGP_INSTANCE_HELP_STR
9bedbb1e 10845 BGP_AFI_HELP_STR
4dd6177e 10846 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10847 "Display routes matching the large-community-list\n"
10848 "large-community-list number\n"
10849 "large-community-list name\n"
36a206db 10850 "Exact match of the large-communities\n"
52951b63
DS
10851 JSON_STR)
10852{
d62a17ae 10853 afi_t afi = AFI_IP6;
10854 safi_t safi = SAFI_UNICAST;
10855 int idx = 0;
36a206db 10856 bool exact_match = 0;
4d678463 10857 struct bgp *bgp = NULL;
9f049418 10858 bool uj = use_json(argc, argv);
d62a17ae 10859
4d678463
KA
10860 if (uj)
10861 argc--;
10862
10863 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10864 &bgp, uj);
10865 if (!idx)
10866 return CMD_WARNING;
d62a17ae 10867
10868 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10869
10870 const char *clist_number_or_name = argv[++idx]->arg;
10871
10872 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10873 exact_match = 1;
10874
10875 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10876 exact_match, afi, safi, uj);
52951b63
DS
10877}
10878DEFUN (show_ip_bgp_large_community,
10879 show_ip_bgp_large_community_cmd,
36a206db 10880 "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
10881 SHOW_STR
10882 IP_STR
10883 BGP_STR
10884 BGP_INSTANCE_HELP_STR
9bedbb1e 10885 BGP_AFI_HELP_STR
4dd6177e 10886 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10887 "Display routes matching the large-communities\n"
10888 "List of large-community numbers\n"
36a206db 10889 "Exact match of the large-communities\n"
52951b63
DS
10890 JSON_STR)
10891{
d62a17ae 10892 afi_t afi = AFI_IP6;
10893 safi_t safi = SAFI_UNICAST;
10894 int idx = 0;
36a206db 10895 bool exact_match = 0;
4d678463 10896 struct bgp *bgp = NULL;
9f049418 10897 bool uj = use_json(argc, argv);
96f3485c 10898 uint8_t show_flags = 0;
d62a17ae 10899
96f3485c
MK
10900 if (uj) {
10901 argc--;
10902 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10903 }
4d678463 10904
96f3485c
MK
10905 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10906 &bgp, uj);
10907 if (!idx)
10908 return CMD_WARNING;
d62a17ae 10909
36a206db 10910 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10911 if (argv_find(argv, argc, "exact-match", &idx))
10912 exact_match = 1;
10913 return bgp_show_lcommunity(vty, bgp, argc, argv,
10914 exact_match, afi, safi, uj);
10915 } else
d62a17ae 10916 return bgp_show(vty, bgp, afi, safi,
96f3485c 10917 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
10918}
10919
71f1613a
DA
10920static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
10921 safi_t safi, struct json_object *json_array);
d62a17ae 10922static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 10923 safi_t safi, struct json_object *json);
e01ca200 10924
7b2ff250 10925
9ab0cf58
PG
10926DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
10927 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10928 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10929 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
10930{
10931 bool uj = use_json(argc, argv);
10932 struct bgp *bgp = NULL;
ec76a1d1
DA
10933 safi_t safi = SAFI_UNICAST;
10934 afi_t afi = AFI_IP6;
4265b261 10935 int idx = 0;
6c9d22e2
PG
10936 struct json_object *json_all = NULL;
10937 struct json_object *json_afi_safi = NULL;
4265b261
PG
10938
10939 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10940 &bgp, false);
71f1613a 10941 if (!idx)
4265b261 10942 return CMD_WARNING;
6c9d22e2 10943
4265b261 10944 if (uj)
6c9d22e2 10945 json_all = json_object_new_object();
4265b261 10946
9ab0cf58
PG
10947 FOREACH_AFI_SAFI (afi, safi) {
10948 /*
10949 * So limit output to those afi/safi pairs that
10950 * actually have something interesting in them
10951 */
10952 if (strmatch(get_afi_safi_str(afi, safi, true),
10953 "Unknown")) {
10954 continue;
10955 }
10956 if (uj) {
10957 json_afi_safi = json_object_new_array();
10958 json_object_object_add(
10959 json_all,
10960 get_afi_safi_str(afi, safi, true),
10961 json_afi_safi);
10962 } else {
10963 json_afi_safi = NULL;
6c9d22e2 10964 }
9ab0cf58
PG
10965
10966 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 10967 }
6c9d22e2
PG
10968
10969 if (uj) {
9ab0cf58
PG
10970 vty_out(vty, "%s",
10971 json_object_to_json_string_ext(
10972 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 10973 json_object_free(json_all);
4265b261 10974 }
6c9d22e2 10975
4265b261
PG
10976 return CMD_SUCCESS;
10977}
10978
7b2ff250 10979/* BGP route print out function without JSON */
14718643
PG
10980DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
10981 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 10982 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
10983 SHOW_STR
10984 IP_STR
10985 BGP_STR
10986 BGP_INSTANCE_HELP_STR
10987 L2VPN_HELP_STR
10988 EVPN_HELP_STR
10989 "BGP RIB advertisement statistics\n"
10990 JSON_STR)
10991{
ec76a1d1
DA
10992 afi_t afi = AFI_IP6;
10993 safi_t safi = SAFI_UNICAST;
14718643
PG
10994 struct bgp *bgp = NULL;
10995 int idx = 0, ret;
10996 bool uj = use_json(argc, argv);
10997 struct json_object *json_afi_safi = NULL, *json = NULL;
10998
10999 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11000 &bgp, false);
11001 if (!idx)
11002 return CMD_WARNING;
11003
11004 if (uj)
11005 json_afi_safi = json_object_new_array();
11006 else
11007 json_afi_safi = NULL;
11008
11009 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11010
11011 if (uj) {
11012 json = json_object_new_object();
11013 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11014 json_afi_safi);
11015 vty_out(vty, "%s", json_object_to_json_string_ext(
11016 json, JSON_C_TO_STRING_PRETTY));
11017 json_object_free(json);
11018 }
11019 return ret;
11020}
11021
893cccd0 11022/* BGP route print out function without JSON */
9ab0cf58
PG
11023DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11024 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11025 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11026 "]]\
893cccd0 11027 statistics [json]",
9ab0cf58
PG
11028 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11029 BGP_SAFI_WITH_LABEL_HELP_STR
11030 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11031{
ec76a1d1
DA
11032 afi_t afi = AFI_IP6;
11033 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11034 struct bgp *bgp = NULL;
11035 int idx = 0, ret;
11036 bool uj = use_json(argc, argv);
6c9d22e2 11037 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11038
11039 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11040 &bgp, false);
11041 if (!idx)
11042 return CMD_WARNING;
6c9d22e2 11043
893cccd0 11044 if (uj)
6c9d22e2
PG
11045 json_afi_safi = json_object_new_array();
11046 else
11047 json_afi_safi = NULL;
11048
11049 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11050
11051 if (uj) {
11052 json = json_object_new_object();
11053 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11054 json_afi_safi);
9ab0cf58
PG
11055 vty_out(vty, "%s",
11056 json_object_to_json_string_ext(
11057 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11058 json_object_free(json);
11059 }
11060 return ret;
893cccd0 11061}
7b2ff250
DW
11062
11063/* BGP route print out function without JSON */
96f3485c 11064DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11065 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11066 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11067 "]]\
96f3485c 11068 <[all$all] dampening <parameters>\
7b2ff250
DW
11069 |route-map WORD\
11070 |prefix-list WORD\
11071 |filter-list WORD\
7b2ff250
DW
11072 |community-list <(1-500)|WORD> [exact-match]\
11073 |A.B.C.D/M longer-prefixes\
11074 |X:X::X:X/M longer-prefixes\
893cccd0 11075 >",
9ab0cf58
PG
11076 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11077 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11078 "Display the entries for all address families\n"
9ab0cf58
PG
11079 "Display detailed information about dampening\n"
11080 "Display detail of configured dampening parameters\n"
11081 "Display routes matching the route-map\n"
11082 "A route-map to match on\n"
11083 "Display routes conforming to the prefix-list\n"
11084 "Prefix-list name\n"
11085 "Display routes conforming to the filter-list\n"
11086 "Regular expression access list name\n"
11087 "Display routes matching the community-list\n"
11088 "community-list number\n"
11089 "community-list name\n"
11090 "Exact match of the communities\n"
11091 "IPv4 prefix\n"
11092 "Display route and more specific routes\n"
11093 "IPv6 prefix\n"
11094 "Display route and more specific routes\n")
718e3744 11095{
d62a17ae 11096 afi_t afi = AFI_IP6;
11097 safi_t safi = SAFI_UNICAST;
11098 int exact_match = 0;
d62a17ae 11099 struct bgp *bgp = NULL;
11100 int idx = 0;
96f3485c
MK
11101 uint8_t show_flags = 0;
11102
11103 /* [<ipv4|ipv6> [all]] */
11104 if (all) {
11105 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11106 if (argv_find(argv, argc, "ipv4", &idx))
11107 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11108
11109 if (argv_find(argv, argc, "ipv6", &idx))
11110 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11111 }
d62a17ae 11112
11113 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11114 &bgp, false);
d62a17ae 11115 if (!idx)
11116 return CMD_WARNING;
11117
d62a17ae 11118 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11119 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11120 return bgp_show_dampening_parameters(vty, afi, safi,
11121 show_flags);
d62a17ae 11122 }
c016b6c7 11123
d62a17ae 11124 if (argv_find(argv, argc, "prefix-list", &idx))
11125 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11126 safi, bgp_show_type_prefix_list);
11127
11128 if (argv_find(argv, argc, "filter-list", &idx))
11129 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11130 safi, bgp_show_type_filter_list);
11131
d62a17ae 11132 if (argv_find(argv, argc, "route-map", &idx))
11133 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11134 safi, bgp_show_type_route_map);
11135
d62a17ae 11136 if (argv_find(argv, argc, "community-list", &idx)) {
11137 const char *clist_number_or_name = argv[++idx]->arg;
11138 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11139 exact_match = 1;
11140 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11141 exact_match, afi, safi);
11142 }
11143 /* prefix-longer */
11144 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11145 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11146 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11147 safi,
11148 bgp_show_type_prefix_longer);
11149
7b2ff250
DW
11150 return CMD_WARNING;
11151}
11152
11153/* BGP route print out function with JSON */
ae248832 11154DEFPY (show_ip_bgp_json,
7b2ff250
DW
11155 show_ip_bgp_json_cmd,
11156 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11157 [all$all]\
cf4898bc
QY
11158 [cidr-only\
11159 |dampening <flap-statistics|dampened-paths>\
11160 |community [AA:NN|local-AS|no-advertise|no-export\
11161 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11162 |accept-own|accept-own-nexthop|route-filter-v6\
11163 |route-filter-v4|route-filter-translated-v6\
11164 |route-filter-translated-v4] [exact-match]\
ae248832 11165 ] [json$uj | wide$wide]",
7b2ff250
DW
11166 SHOW_STR
11167 IP_STR
11168 BGP_STR
11169 BGP_INSTANCE_HELP_STR
11170 BGP_AFI_HELP_STR
11171 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11172 "Display the entries for all address families\n"
7b2ff250
DW
11173 "Display only routes with non-natural netmasks\n"
11174 "Display detailed information about dampening\n"
11175 "Display flap statistics of routes\n"
11176 "Display paths suppressed due to dampening\n"
11177 "Display routes matching the communities\n"
d0086e8e
AD
11178 COMMUNITY_AANN_STR
11179 "Do not send outside local AS (well-known community)\n"
11180 "Do not advertise to any peer (well-known community)\n"
11181 "Do not export to next AS (well-known community)\n"
11182 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11183 "Do not export to any peer (well-known community)\n"
11184 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11185 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11186 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11187 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11188 "Should accept VPN route with local nexthop (well-known community)\n"
11189 "RT VPNv6 route filtering (well-known community)\n"
11190 "RT VPNv4 route filtering (well-known community)\n"
11191 "RT translated VPNv6 route filtering (well-known community)\n"
11192 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11193 "Exact match of the communities\n"
ae248832
MK
11194 JSON_STR
11195 "Increase table width for longer prefixes\n")
7b2ff250
DW
11196{
11197 afi_t afi = AFI_IP6;
11198 safi_t safi = SAFI_UNICAST;
11199 enum bgp_show_type sh_type = bgp_show_type_normal;
11200 struct bgp *bgp = NULL;
11201 int idx = 0;
d0086e8e 11202 int exact_match = 0;
96f3485c
MK
11203 char *community = NULL;
11204 bool first = true;
11205 uint8_t show_flags = 0;
9f049418 11206
96f3485c
MK
11207
11208 if (uj) {
9f049418 11209 argc--;
96f3485c
MK
11210 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11211 }
11212
11213 /* [<ipv4|ipv6> [all]] */
11214 if (all) {
11215 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11216
11217 if (argv_find(argv, argc, "ipv4", &idx))
11218 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11219
11220 if (argv_find(argv, argc, "ipv6", &idx))
11221 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11222 }
11223
11224 if (wide)
11225 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11226
11227 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11228 &bgp, uj);
7b2ff250
DW
11229 if (!idx)
11230 return CMD_WARNING;
11231
7b2ff250 11232 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11233 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11234
11235 if (argv_find(argv, argc, "dampening", &idx)) {
11236 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11237 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11238 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11239 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11240 }
11241
11242 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11243 char *maybecomm = NULL;
d0086e8e 11244
79bc257a
RW
11245 if (idx + 1 < argc) {
11246 if (argv[idx + 1]->type == VARIABLE_TKN)
11247 maybecomm = argv[idx + 1]->arg;
11248 else
11249 maybecomm = argv[idx + 1]->text;
11250 }
11251
cf4898bc
QY
11252 if (maybecomm && !strmatch(maybecomm, "json")
11253 && !strmatch(maybecomm, "exact-match"))
11254 community = maybecomm;
d0086e8e 11255
cf4898bc
QY
11256 if (argv_find(argv, argc, "exact-match", &idx))
11257 exact_match = 1;
d0086e8e 11258
96f3485c
MK
11259 if (!community)
11260 sh_type = bgp_show_type_community_all;
11261 }
11262
11263 if (!all) {
11264 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11265 if (community)
11266 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11267 exact_match, afi, safi,
11268 show_flags);
cf4898bc 11269 else
96f3485c
MK
11270 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11271 show_flags);
11272 } else {
11273 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11274 * AFI_IP6 */
11275
11276 if (uj)
11277 vty_out(vty, "{\n");
11278
11279 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11280 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11281 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11282 ? AFI_IP
11283 : AFI_IP6;
11284 FOREACH_SAFI (safi) {
11285 if (strmatch(get_afi_safi_str(afi, safi, true),
11286 "Unknown"))
11287 continue;
11288
11289 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11290 continue;
11291
11292 if (uj) {
11293 if (first)
11294 first = false;
11295 else
11296 vty_out(vty, ",\n");
11297 vty_out(vty, "\"%s\":{\n",
11298 get_afi_safi_str(afi, safi,
11299 true));
11300 } else
11301 vty_out(vty,
11302 "\nFor address family: %s\n",
11303 get_afi_safi_str(afi, safi,
11304 false));
11305
11306 if (community)
11307 bgp_show_community(vty, bgp, community,
11308 exact_match, afi,
11309 safi, show_flags);
11310 else
11311 bgp_show(vty, bgp, afi, safi, sh_type,
11312 NULL, show_flags);
11313 if (uj)
11314 vty_out(vty, "}\n");
11315 }
11316 } else {
11317 /* show <ip> bgp all: for each AFI and SAFI*/
11318 FOREACH_AFI_SAFI (afi, safi) {
11319 if (strmatch(get_afi_safi_str(afi, safi, true),
11320 "Unknown"))
11321 continue;
11322
11323 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11324 continue;
11325
11326 if (uj) {
11327 if (first)
11328 first = false;
11329 else
11330 vty_out(vty, ",\n");
d0086e8e 11331
96f3485c
MK
11332 vty_out(vty, "\"%s\":{\n",
11333 get_afi_safi_str(afi, safi,
11334 true));
11335 } else
11336 vty_out(vty,
11337 "\nFor address family: %s\n",
11338 get_afi_safi_str(afi, safi,
11339 false));
11340
11341 if (community)
11342 bgp_show_community(vty, bgp, community,
11343 exact_match, afi,
11344 safi, show_flags);
11345 else
11346 bgp_show(vty, bgp, afi, safi, sh_type,
11347 NULL, show_flags);
11348 if (uj)
11349 vty_out(vty, "}\n");
11350 }
11351 }
11352 if (uj)
11353 vty_out(vty, "}\n");
11354 }
11355 return CMD_SUCCESS;
a636c635 11356}
47fc97cc 11357
718e3744 11358DEFUN (show_ip_bgp_route,
11359 show_ip_bgp_route_cmd,
3efd0893 11360 "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 11361 SHOW_STR
11362 IP_STR
11363 BGP_STR
a636c635 11364 BGP_INSTANCE_HELP_STR
4f280b15 11365 BGP_AFI_HELP_STR
4dd6177e 11366 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11367 "Network in the BGP routing table to display\n"
0c7b1b01 11368 "IPv4 prefix\n"
8c3deaae 11369 "Network in the BGP routing table to display\n"
0c7b1b01 11370 "IPv6 prefix\n"
4092b06c 11371 "Display only the bestpath\n"
b05a1c8b 11372 "Display only multipaths\n"
9973d184 11373 JSON_STR)
4092b06c 11374{
d62a17ae 11375 int prefix_check = 0;
ae19d7dd 11376
d62a17ae 11377 afi_t afi = AFI_IP6;
11378 safi_t safi = SAFI_UNICAST;
11379 char *prefix = NULL;
11380 struct bgp *bgp = NULL;
11381 enum bgp_path_type path_type;
9f049418 11382 bool uj = use_json(argc, argv);
b05a1c8b 11383
d62a17ae 11384 int idx = 0;
ae19d7dd 11385
d62a17ae 11386 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11387 &bgp, uj);
d62a17ae 11388 if (!idx)
11389 return CMD_WARNING;
c41247f5 11390
d62a17ae 11391 if (!bgp) {
11392 vty_out(vty,
11393 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11394 return CMD_WARNING;
11395 }
a636c635 11396
d62a17ae 11397 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11398 if (argv_find(argv, argc, "A.B.C.D", &idx)
11399 || argv_find(argv, argc, "X:X::X:X", &idx))
11400 prefix_check = 0;
11401 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11402 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11403 prefix_check = 1;
11404
11405 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11406 && afi != AFI_IP6) {
11407 vty_out(vty,
11408 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11409 return CMD_WARNING;
11410 }
11411 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11412 && afi != AFI_IP) {
11413 vty_out(vty,
11414 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11415 return CMD_WARNING;
11416 }
11417
11418 prefix = argv[idx]->arg;
11419
11420 /* [<bestpath|multipath>] */
11421 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11422 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11423 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11424 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11425 else
360660c6 11426 path_type = BGP_PATH_SHOW_ALL;
a636c635 11427
d62a17ae 11428 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11429 path_type, uj);
4092b06c
DS
11430}
11431
8c3deaae
QY
11432DEFUN (show_ip_bgp_regexp,
11433 show_ip_bgp_regexp_cmd,
3e5b31b3 11434 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11435 SHOW_STR
11436 IP_STR
11437 BGP_STR
b00b230a 11438 BGP_INSTANCE_HELP_STR
4f280b15 11439 BGP_AFI_HELP_STR
4dd6177e 11440 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11441 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11442 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11443 JSON_STR)
8c3deaae 11444{
d62a17ae 11445 afi_t afi = AFI_IP6;
11446 safi_t safi = SAFI_UNICAST;
11447 struct bgp *bgp = NULL;
3e5b31b3
DA
11448 bool uj = use_json(argc, argv);
11449 char *regstr = NULL;
8c3deaae 11450
d62a17ae 11451 int idx = 0;
11452 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11453 &bgp, false);
d62a17ae 11454 if (!idx)
11455 return CMD_WARNING;
8c3deaae 11456
d62a17ae 11457 // get index of regex
3e5b31b3
DA
11458 if (argv_find(argv, argc, "REGEX", &idx))
11459 regstr = argv[idx]->arg;
8c3deaae 11460
5f71d11c 11461 assert(regstr);
3e5b31b3
DA
11462 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11463 bgp_show_type_regexp, uj);
8c3deaae
QY
11464}
11465
ae248832 11466DEFPY (show_ip_bgp_instance_all,
a636c635 11467 show_ip_bgp_instance_all_cmd,
ae248832 11468 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11469 SHOW_STR
a636c635 11470 IP_STR
4092b06c 11471 BGP_STR
a636c635 11472 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11473 BGP_AFI_HELP_STR
4dd6177e 11474 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11475 JSON_STR
11476 "Increase table width for longer prefixes\n")
4092b06c 11477{
d62a17ae 11478 afi_t afi = AFI_IP;
11479 safi_t safi = SAFI_UNICAST;
11480 struct bgp *bgp = NULL;
d62a17ae 11481 int idx = 0;
96f3485c 11482 uint8_t show_flags = 0;
ae19d7dd 11483
96f3485c 11484 if (uj) {
d62a17ae 11485 argc--;
96f3485c
MK
11486 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11487 }
11488
11489 if (wide)
11490 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11491
9f049418
DS
11492 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11493 &bgp, uj);
11494 if (!idx)
11495 return CMD_WARNING;
11496
96f3485c 11497 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11498 return CMD_SUCCESS;
e3e29b32
LB
11499}
11500
a4d82a8a 11501static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11502 afi_t afi, safi_t safi, enum bgp_show_type type,
11503 bool use_json)
718e3744 11504{
d62a17ae 11505 regex_t *regex;
11506 int rc;
96f3485c
MK
11507 uint8_t show_flags = 0;
11508
11509 if (use_json)
11510 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11511
c3900853 11512 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11513 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11514 regstr);
11515 return CMD_WARNING_CONFIG_FAILED;
11516 }
11517
d62a17ae 11518 regex = bgp_regcomp(regstr);
11519 if (!regex) {
11520 vty_out(vty, "Can't compile regexp %s\n", regstr);
11521 return CMD_WARNING;
11522 }
a636c635 11523
96f3485c 11524 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11525 bgp_regex_free(regex);
11526 return rc;
e3e29b32
LB
11527}
11528
d62a17ae 11529static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11530 const char *prefix_list_str, afi_t afi,
11531 safi_t safi, enum bgp_show_type type)
e3e29b32 11532{
d62a17ae 11533 struct prefix_list *plist;
96f3485c 11534 uint8_t show_flags = 0;
718e3744 11535
d62a17ae 11536 plist = prefix_list_lookup(afi, prefix_list_str);
11537 if (plist == NULL) {
11538 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11539 prefix_list_str);
11540 return CMD_WARNING;
11541 }
718e3744 11542
96f3485c 11543 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
11544}
11545
d62a17ae 11546static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11547 const char *filter, afi_t afi, safi_t safi,
11548 enum bgp_show_type type)
4092b06c 11549{
d62a17ae 11550 struct as_list *as_list;
96f3485c 11551 uint8_t show_flags = 0;
718e3744 11552
d62a17ae 11553 as_list = as_list_lookup(filter);
11554 if (as_list == NULL) {
11555 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11556 filter);
11557 return CMD_WARNING;
11558 }
a636c635 11559
96f3485c 11560 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 11561}
11562
d62a17ae 11563static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11564 const char *rmap_str, afi_t afi, safi_t safi,
11565 enum bgp_show_type type)
718e3744 11566{
d62a17ae 11567 struct route_map *rmap;
96f3485c 11568 uint8_t show_flags = 0;
bb46e94f 11569
d62a17ae 11570 rmap = route_map_lookup_by_name(rmap_str);
11571 if (!rmap) {
11572 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
11573 return CMD_WARNING;
11574 }
11575
96f3485c 11576 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 11577}
11578
7f323236
DW
11579static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11580 const char *comstr, int exact, afi_t afi,
96f3485c 11581 safi_t safi, uint8_t show_flags)
d62a17ae 11582{
11583 struct community *com;
d62a17ae 11584 int ret = 0;
11585
7f323236 11586 com = community_str2com(comstr);
d62a17ae 11587 if (!com) {
7f323236 11588 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 11589 return CMD_WARNING;
11590 }
11591
11592 ret = bgp_show(vty, bgp, afi, safi,
11593 (exact ? bgp_show_type_community_exact
11594 : bgp_show_type_community),
96f3485c 11595 com, show_flags);
3c1f53de 11596 community_free(&com);
46c3ce83 11597
d62a17ae 11598 return ret;
718e3744 11599}
11600
d62a17ae 11601static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
11602 const char *com, int exact, afi_t afi,
11603 safi_t safi)
50ef26d4 11604{
d62a17ae 11605 struct community_list *list;
96f3485c 11606 uint8_t show_flags = 0;
50ef26d4 11607
e237b0d2 11608 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 11609 if (list == NULL) {
11610 vty_out(vty, "%% %s is not a valid community-list name\n", com);
11611 return CMD_WARNING;
11612 }
718e3744 11613
d62a17ae 11614 return bgp_show(vty, bgp, afi, safi,
11615 (exact ? bgp_show_type_community_list_exact
11616 : bgp_show_type_community_list),
96f3485c 11617 list, show_flags);
50ef26d4 11618}
11619
d62a17ae 11620static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
11621 const char *prefix, afi_t afi, safi_t safi,
11622 enum bgp_show_type type)
718e3744 11623{
d62a17ae 11624 int ret;
11625 struct prefix *p;
96f3485c 11626 uint8_t show_flags = 0;
47fc97cc 11627
d62a17ae 11628 p = prefix_new();
95cbbd2a 11629
d62a17ae 11630 ret = str2prefix(prefix, p);
11631 if (!ret) {
11632 vty_out(vty, "%% Malformed Prefix\n");
11633 return CMD_WARNING;
11634 }
47e9b292 11635
96f3485c 11636 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 11637 prefix_free(&p);
d62a17ae 11638 return ret;
11639}
11640
d62a17ae 11641enum bgp_stats {
11642 BGP_STATS_MAXBITLEN = 0,
11643 BGP_STATS_RIB,
11644 BGP_STATS_PREFIXES,
11645 BGP_STATS_TOTPLEN,
11646 BGP_STATS_UNAGGREGATEABLE,
11647 BGP_STATS_MAX_AGGREGATEABLE,
11648 BGP_STATS_AGGREGATES,
11649 BGP_STATS_SPACE,
11650 BGP_STATS_ASPATH_COUNT,
11651 BGP_STATS_ASPATH_MAXHOPS,
11652 BGP_STATS_ASPATH_TOTHOPS,
11653 BGP_STATS_ASPATH_MAXSIZE,
11654 BGP_STATS_ASPATH_TOTSIZE,
11655 BGP_STATS_ASN_HIGHEST,
11656 BGP_STATS_MAX,
a636c635 11657};
2815e61f 11658
9ab0cf58 11659#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
11660#define TABLE_STATS_IDX_JSON 1
11661
11662static const char *table_stats_strs[][2] = {
6c9d22e2
PG
11663 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
11664 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
11665 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
11666 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
11667 "unaggregateablePrefixes"},
11668 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
11669 "maximumAggregateablePrefixes"},
11670 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
11671 "bgpAggregateAdvertisements"},
6c9d22e2
PG
11672 [BGP_STATS_SPACE] = {"Address space advertised",
11673 "addressSpaceAdvertised"},
9ab0cf58
PG
11674 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
11675 "advertisementsWithPaths"},
11676 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
11677 "longestAsPath"},
11678 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
11679 "largestAsPath"},
11680 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
11681 "averageAsPathLengthHops"},
11682 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
11683 "averageAsPathSizeBytes"},
11684 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 11685 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 11686};
2815e61f 11687
d62a17ae 11688struct bgp_table_stats {
11689 struct bgp_table *table;
11690 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 11691 double total_space;
ff7924f6
PJ
11692};
11693
a636c635
DW
11694#if 0
11695#define TALLY_SIGFIG 100000
11696static unsigned long
11697ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 11698{
a636c635
DW
11699 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
11700 unsigned long res = (newtot * TALLY_SIGFIG) / count;
11701 unsigned long ret = newtot / count;
07d0c4ed 11702
a636c635
DW
11703 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11704 return ret + 1;
11705 else
11706 return ret;
11707}
11708#endif
ff7924f6 11709
9bcb3eef 11710static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 11711 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11712{
9bcb3eef 11713 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 11714 struct bgp_path_info *pi;
b54892e0 11715 const struct prefix *rn_p;
d62a17ae 11716
9bcb3eef 11717 if (dest == top)
9c14ec72 11718 return;
d62a17ae 11719
9bcb3eef 11720 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 11721 return;
d62a17ae 11722
9bcb3eef 11723 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 11724 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 11725 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 11726
a636c635
DW
11727#if 0
11728 ts->counts[BGP_STATS_AVGPLEN]
11729 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11730 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 11731 rn_p->prefixlen);
a636c635 11732#endif
d62a17ae 11733
9c14ec72 11734 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
11735 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
11736 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 11737
9bcb3eef 11738 if (pdest == NULL || pdest == top) {
9c14ec72
RW
11739 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11740 /* announced address space */
11741 if (space)
b54892e0 11742 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 11743 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 11744 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11745
9c14ec72 11746
9bcb3eef 11747 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
11748 ts->counts[BGP_STATS_RIB]++;
11749
05864da7
DS
11750 if (CHECK_FLAG(pi->attr->flag,
11751 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11752 ts->counts[BGP_STATS_AGGREGATES]++;
11753
11754 /* as-path stats */
05864da7 11755 if (pi->attr->aspath) {
9c14ec72
RW
11756 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11757 unsigned int size = aspath_size(pi->attr->aspath);
11758 as_t highest = aspath_highest(pi->attr->aspath);
11759
11760 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11761
11762 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11763 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11764
11765 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11766 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11767
11768 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11769 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11770#if 0
07d0c4ed 11771 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11772 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11773 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11774 hops);
11775 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11776 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11777 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11778 size);
11779#endif
9c14ec72
RW
11780 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11781 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11782 }
11783 }
11784}
11785
11786static int bgp_table_stats_walker(struct thread *t)
11787{
9bcb3eef
DS
11788 struct bgp_dest *dest, *ndest;
11789 struct bgp_dest *top;
9c14ec72
RW
11790 struct bgp_table_stats *ts = THREAD_ARG(t);
11791 unsigned int space = 0;
11792
11793 if (!(top = bgp_table_top(ts->table)))
11794 return 0;
11795
11796 switch (ts->table->afi) {
11797 case AFI_IP:
11798 space = IPV4_MAX_BITLEN;
11799 break;
11800 case AFI_IP6:
11801 space = IPV6_MAX_BITLEN;
11802 break;
11803 default:
11804 return 0;
11805 }
11806
11807 ts->counts[BGP_STATS_MAXBITLEN] = space;
11808
9bcb3eef 11809 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
11810 if (ts->table->safi == SAFI_MPLS_VPN
11811 || ts->table->safi == SAFI_ENCAP
11812 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
11813 struct bgp_table *table;
11814
9bcb3eef 11815 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
11816 if (!table)
11817 continue;
11818
11819 top = bgp_table_top(table);
9bcb3eef
DS
11820 for (ndest = bgp_table_top(table); ndest;
11821 ndest = bgp_route_next(ndest))
11822 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 11823 } else {
9bcb3eef 11824 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 11825 }
11826 }
9c14ec72 11827
d62a17ae 11828 return 0;
2815e61f 11829}
ff7924f6 11830
71f1613a
DA
11831static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
11832 struct json_object *json_array)
11833{
11834 struct listnode *node, *nnode;
11835 struct bgp *bgp;
11836
11837 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
11838 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
11839}
11840
11841static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11842 safi_t safi, struct json_object *json_array)
2815e61f 11843{
d62a17ae 11844 struct bgp_table_stats ts;
11845 unsigned int i;
893cccd0
PG
11846 int ret = CMD_SUCCESS;
11847 char temp_buf[20];
6c9d22e2
PG
11848 struct json_object *json = NULL;
11849
11850 if (json_array)
11851 json = json_object_new_object();
019386c2 11852
d62a17ae 11853 if (!bgp->rib[afi][safi]) {
893cccd0
PG
11854 char warning_msg[50];
11855
11856 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
11857 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
11858 safi);
6c9d22e2
PG
11859
11860 if (!json)
893cccd0
PG
11861 vty_out(vty, "%s\n", warning_msg);
11862 else
9ab0cf58 11863 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 11864
893cccd0
PG
11865 ret = CMD_WARNING;
11866 goto end_table_stats;
d62a17ae 11867 }
019386c2 11868
893cccd0 11869 if (!json)
5290ceab
DA
11870 vty_out(vty, "BGP %s RIB statistics (%s)\n",
11871 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
11872 else
11873 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 11874
d62a17ae 11875 /* labeled-unicast routes live in the unicast table */
11876 if (safi == SAFI_LABELED_UNICAST)
11877 safi = SAFI_UNICAST;
019386c2 11878
d62a17ae 11879 memset(&ts, 0, sizeof(ts));
11880 ts.table = bgp->rib[afi][safi];
11881 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11882
d62a17ae 11883 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
11884 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
11885 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 11886 continue;
11887
11888 switch (i) {
a636c635
DW
11889#if 0
11890 case BGP_STATS_ASPATH_AVGHOPS:
11891 case BGP_STATS_ASPATH_AVGSIZE:
11892 case BGP_STATS_AVGPLEN:
11893 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11894 vty_out (vty, "%12.2f",
11895 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11896 break;
11897#endif
d62a17ae 11898 case BGP_STATS_ASPATH_TOTHOPS:
11899 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 11900 if (!json) {
9ab0cf58
PG
11901 snprintf(
11902 temp_buf, sizeof(temp_buf), "%12.2f",
11903 ts.counts[i]
11904 ? (float)ts.counts[i]
11905 / (float)ts.counts
11906 [BGP_STATS_ASPATH_COUNT]
11907 : 0);
893cccd0 11908 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11909 table_stats_strs[i]
11910 [TABLE_STATS_IDX_VTY],
893cccd0 11911 temp_buf);
9ab0cf58
PG
11912 } else {
11913 json_object_double_add(
11914 json,
11915 table_stats_strs[i]
11916 [TABLE_STATS_IDX_JSON],
11917 ts.counts[i]
11918 ? (double)ts.counts[i]
11919 / (double)ts.counts
d62a17ae 11920 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
11921 : 0);
11922 }
d62a17ae 11923 break;
11924 case BGP_STATS_TOTPLEN:
6c9d22e2 11925 if (!json) {
9ab0cf58
PG
11926 snprintf(
11927 temp_buf, sizeof(temp_buf), "%12.2f",
11928 ts.counts[i]
11929 ? (float)ts.counts[i]
11930 / (float)ts.counts
11931 [BGP_STATS_PREFIXES]
11932 : 0);
893cccd0 11933 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11934 table_stats_strs[i]
11935 [TABLE_STATS_IDX_VTY],
893cccd0 11936 temp_buf);
9ab0cf58
PG
11937 } else {
11938 json_object_double_add(
11939 json,
11940 table_stats_strs[i]
11941 [TABLE_STATS_IDX_JSON],
11942 ts.counts[i]
11943 ? (double)ts.counts[i]
11944 / (double)ts.counts
d62a17ae 11945 [BGP_STATS_PREFIXES]
9ab0cf58
PG
11946 : 0);
11947 }
d62a17ae 11948 break;
11949 case BGP_STATS_SPACE:
6c9d22e2
PG
11950 if (!json) {
11951 snprintf(temp_buf, sizeof(temp_buf), "%12g",
11952 ts.total_space);
893cccd0 11953 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
11954 table_stats_strs[i]
11955 [TABLE_STATS_IDX_VTY],
893cccd0 11956 temp_buf);
9ab0cf58
PG
11957 } else {
11958 json_object_double_add(
11959 json,
11960 table_stats_strs[i]
11961 [TABLE_STATS_IDX_JSON],
11962 (double)ts.total_space);
11963 }
8d0ab76d 11964 if (afi == AFI_IP6) {
6c9d22e2
PG
11965 if (!json) {
11966 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11967 "%12g",
11968 ts.total_space
11969 * pow(2.0, -128 + 32));
6c9d22e2
PG
11970 vty_out(vty, "%30s: %s\n",
11971 "/32 equivalent %s\n",
11972 temp_buf);
9ab0cf58
PG
11973 } else {
11974 json_object_double_add(
11975 json, "/32equivalent",
11976 (double)(ts.total_space
11977 * pow(2.0,
11978 -128 + 32)));
11979 }
6c9d22e2
PG
11980 if (!json) {
11981 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11982 "%12g",
11983 ts.total_space
11984 * pow(2.0, -128 + 48));
6c9d22e2
PG
11985 vty_out(vty, "%30s: %s\n",
11986 "/48 equivalent %s\n",
11987 temp_buf);
9ab0cf58
PG
11988 } else {
11989 json_object_double_add(
11990 json, "/48equivalent",
11991 (double)(ts.total_space
11992 * pow(2.0,
11993 -128 + 48)));
11994 }
8d0ab76d 11995 } else {
6c9d22e2
PG
11996 if (!json) {
11997 snprintf(temp_buf, sizeof(temp_buf),
11998 "%12.2f",
9ab0cf58
PG
11999 ts.total_space * 100.
12000 * pow(2.0, -32));
6c9d22e2 12001 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12002 "% announced ", temp_buf);
12003 } else {
12004 json_object_double_add(
12005 json, "%announced",
12006 (double)(ts.total_space * 100.
12007 * pow(2.0, -32)));
12008 }
6c9d22e2
PG
12009 if (!json) {
12010 snprintf(temp_buf, sizeof(temp_buf),
12011 "%12.2f",
9ab0cf58
PG
12012 ts.total_space
12013 * pow(2.0, -32 + 8));
6c9d22e2
PG
12014 vty_out(vty, "%30s: %s\n",
12015 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12016 } else {
12017 json_object_double_add(
12018 json, "/8equivalent",
12019 (double)(ts.total_space
12020 * pow(2.0, -32 + 8)));
12021 }
6c9d22e2
PG
12022 if (!json) {
12023 snprintf(temp_buf, sizeof(temp_buf),
12024 "%12.2f",
9ab0cf58
PG
12025 ts.total_space
12026 * pow(2.0, -32 + 24));
6c9d22e2 12027 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12028 "/24 equivalent ", temp_buf);
12029 } else {
12030 json_object_double_add(
12031 json, "/24equivalent",
12032 (double)(ts.total_space
12033 * pow(2.0, -32 + 24)));
12034 }
8d0ab76d 12035 }
d62a17ae 12036 break;
12037 default:
6c9d22e2
PG
12038 if (!json) {
12039 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12040 ts.counts[i]);
893cccd0 12041 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12042 table_stats_strs[i]
12043 [TABLE_STATS_IDX_VTY],
12044 temp_buf);
12045 } else {
12046 json_object_int_add(
12047 json,
12048 table_stats_strs[i]
12049 [TABLE_STATS_IDX_JSON],
12050 ts.counts[i]);
12051 }
d62a17ae 12052 }
893cccd0
PG
12053 if (!json)
12054 vty_out(vty, "\n");
d62a17ae 12055 }
9ab0cf58 12056end_table_stats:
6c9d22e2
PG
12057 if (json)
12058 json_object_array_add(json_array, json);
893cccd0 12059 return ret;
d62a17ae 12060}
12061
71f1613a
DA
12062static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12063 safi_t safi, struct json_object *json_array)
12064{
12065 if (!bgp) {
12066 bgp_table_stats_all(vty, afi, safi, json_array);
12067 return CMD_SUCCESS;
12068 }
12069
12070 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12071}
12072
d62a17ae 12073enum bgp_pcounts {
12074 PCOUNT_ADJ_IN = 0,
12075 PCOUNT_DAMPED,
12076 PCOUNT_REMOVED,
12077 PCOUNT_HISTORY,
12078 PCOUNT_STALE,
12079 PCOUNT_VALID,
12080 PCOUNT_ALL,
12081 PCOUNT_COUNTED,
7e3d9632 12082 PCOUNT_BPATH_SELECTED,
d62a17ae 12083 PCOUNT_PFCNT, /* the figure we display to users */
12084 PCOUNT_MAX,
a636c635 12085};
718e3744 12086
2b64873d 12087static const char *const pcount_strs[] = {
9d303b37
DL
12088 [PCOUNT_ADJ_IN] = "Adj-in",
12089 [PCOUNT_DAMPED] = "Damped",
12090 [PCOUNT_REMOVED] = "Removed",
12091 [PCOUNT_HISTORY] = "History",
12092 [PCOUNT_STALE] = "Stale",
12093 [PCOUNT_VALID] = "Valid",
12094 [PCOUNT_ALL] = "All RIB",
12095 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12096 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12097 [PCOUNT_PFCNT] = "Useable",
12098 [PCOUNT_MAX] = NULL,
a636c635 12099};
718e3744 12100
d62a17ae 12101struct peer_pcounts {
12102 unsigned int count[PCOUNT_MAX];
12103 const struct peer *peer;
12104 const struct bgp_table *table;
54317cba 12105 safi_t safi;
a636c635 12106};
47fc97cc 12107
9bcb3eef 12108static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12109{
54317cba
JW
12110 const struct bgp_adj_in *ain;
12111 const struct bgp_path_info *pi;
d62a17ae 12112 const struct peer *peer = pc->peer;
12113
54317cba
JW
12114 for (ain = rn->adj_in; ain; ain = ain->next)
12115 if (ain->peer == peer)
12116 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12117
9bcb3eef 12118 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12119
54317cba
JW
12120 if (pi->peer != peer)
12121 continue;
d62a17ae 12122
54317cba 12123 pc->count[PCOUNT_ALL]++;
d62a17ae 12124
54317cba
JW
12125 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12126 pc->count[PCOUNT_DAMPED]++;
12127 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12128 pc->count[PCOUNT_HISTORY]++;
12129 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12130 pc->count[PCOUNT_REMOVED]++;
12131 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12132 pc->count[PCOUNT_STALE]++;
12133 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12134 pc->count[PCOUNT_VALID]++;
12135 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12136 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12137 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12138 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12139
12140 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12141 pc->count[PCOUNT_COUNTED]++;
12142 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12143 flog_err(
12144 EC_LIB_DEVELOPMENT,
12145 "Attempting to count but flags say it is unusable");
12146 } else {
40381db7 12147 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12148 flog_err(
12149 EC_LIB_DEVELOPMENT,
12150 "Not counted but flags say we should");
d62a17ae 12151 }
12152 }
54317cba
JW
12153}
12154
12155static int bgp_peer_count_walker(struct thread *t)
12156{
9bcb3eef 12157 struct bgp_dest *rn, *rm;
54317cba
JW
12158 const struct bgp_table *table;
12159 struct peer_pcounts *pc = THREAD_ARG(t);
12160
12161 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12162 || pc->safi == SAFI_EVPN) {
12163 /* Special handling for 2-level routing tables. */
12164 for (rn = bgp_table_top(pc->table); rn;
12165 rn = bgp_route_next(rn)) {
9bcb3eef 12166 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12167 if (table != NULL)
12168 for (rm = bgp_table_top(table); rm;
12169 rm = bgp_route_next(rm))
12170 bgp_peer_count_proc(rm, pc);
12171 }
12172 } else
12173 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12174 bgp_peer_count_proc(rn, pc);
12175
d62a17ae 12176 return 0;
718e3744 12177}
12178
d62a17ae 12179static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12180 safi_t safi, bool use_json)
856ca177 12181{
d62a17ae 12182 struct peer_pcounts pcounts = {.peer = peer};
12183 unsigned int i;
12184 json_object *json = NULL;
12185 json_object *json_loop = NULL;
856ca177 12186
d62a17ae 12187 if (use_json) {
12188 json = json_object_new_object();
12189 json_loop = json_object_new_object();
12190 }
718e3744 12191
d62a17ae 12192 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12193 || !peer->bgp->rib[afi][safi]) {
12194 if (use_json) {
12195 json_object_string_add(
12196 json, "warning",
12197 "No such neighbor or address family");
12198 vty_out(vty, "%s\n", json_object_to_json_string(json));
12199 json_object_free(json);
12200 } else
12201 vty_out(vty, "%% No such neighbor or address family\n");
12202
12203 return CMD_WARNING;
12204 }
2a71e9ce 12205
d62a17ae 12206 memset(&pcounts, 0, sizeof(pcounts));
12207 pcounts.peer = peer;
12208 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12209 pcounts.safi = safi;
d62a17ae 12210
12211 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12212 * stats for the thread-walk (i.e. ensure this can't be blamed on
12213 * on just vty_read()).
12214 */
d62a17ae 12215 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12216
12217 if (use_json) {
12218 json_object_string_add(json, "prefixCountsFor", peer->host);
12219 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12220 get_afi_safi_str(afi, safi, true));
d62a17ae 12221 json_object_int_add(json, "pfxCounter",
12222 peer->pcount[afi][safi]);
12223
12224 for (i = 0; i < PCOUNT_MAX; i++)
12225 json_object_int_add(json_loop, pcount_strs[i],
12226 pcounts.count[i]);
12227
12228 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12229
12230 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12231 json_object_string_add(json, "pfxctDriftFor",
12232 peer->host);
12233 json_object_string_add(
12234 json, "recommended",
12235 "Please report this bug, with the above command output");
12236 }
996c9314
LB
12237 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12238 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12239 json_object_free(json);
12240 } else {
12241
12242 if (peer->hostname
892fedb6 12243 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12244 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12245 peer->hostname, peer->host,
5cb5f4d0 12246 get_afi_safi_str(afi, safi, false));
d62a17ae 12247 } else {
12248 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12249 get_afi_safi_str(afi, safi, false));
d62a17ae 12250 }
12251
6cde4b45 12252 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12253 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12254
12255 for (i = 0; i < PCOUNT_MAX; i++)
12256 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12257 pcounts.count[i]);
12258
12259 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12260 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12261 vty_out(vty,
12262 "Please report this bug, with the above command output\n");
12263 }
12264 }
12265
12266 return CMD_SUCCESS;
718e3744 12267}
12268
a636c635
DW
12269DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12270 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12271 "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 12272 SHOW_STR
12273 IP_STR
12274 BGP_STR
8386ac43 12275 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12276 BGP_AFI_HELP_STR
12277 BGP_SAFI_HELP_STR
0b16f239
DS
12278 "Detailed information on TCP and BGP neighbor connections\n"
12279 "Neighbor to display information about\n"
12280 "Neighbor to display information about\n"
91d37724 12281 "Neighbor on BGP configured interface\n"
a636c635 12282 "Display detailed prefix count information\n"
9973d184 12283 JSON_STR)
0b16f239 12284{
d62a17ae 12285 afi_t afi = AFI_IP6;
12286 safi_t safi = SAFI_UNICAST;
12287 struct peer *peer;
12288 int idx = 0;
12289 struct bgp *bgp = NULL;
9f049418
DS
12290 bool uj = use_json(argc, argv);
12291
12292 if (uj)
12293 argc--;
856ca177 12294
d62a17ae 12295 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12296 &bgp, uj);
d62a17ae 12297 if (!idx)
12298 return CMD_WARNING;
0b16f239 12299
d62a17ae 12300 argv_find(argv, argc, "neighbors", &idx);
12301 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12302 if (!peer)
12303 return CMD_WARNING;
bb46e94f 12304
29c8d9da 12305 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12306}
0b16f239 12307
d6902373
PG
12308#ifdef KEEP_OLD_VPN_COMMANDS
12309DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12310 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12311 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12312 SHOW_STR
12313 IP_STR
12314 BGP_STR
d6902373 12315 BGP_VPNVX_HELP_STR
91d37724 12316 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12317 "Detailed information on TCP and BGP neighbor connections\n"
12318 "Neighbor to display information about\n"
12319 "Neighbor to display information about\n"
91d37724 12320 "Neighbor on BGP configured interface\n"
a636c635 12321 "Display detailed prefix count information\n"
9973d184 12322 JSON_STR)
a636c635 12323{
d62a17ae 12324 int idx_peer = 6;
12325 struct peer *peer;
9f049418 12326 bool uj = use_json(argc, argv);
a636c635 12327
d62a17ae 12328 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12329 if (!peer)
12330 return CMD_WARNING;
12331
12332 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12333}
12334
d6902373
PG
12335DEFUN (show_ip_bgp_vpn_all_route_prefix,
12336 show_ip_bgp_vpn_all_route_prefix_cmd,
12337 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12338 SHOW_STR
12339 IP_STR
12340 BGP_STR
d6902373 12341 BGP_VPNVX_HELP_STR
91d37724
QY
12342 "Display information about all VPNv4 NLRIs\n"
12343 "Network in the BGP routing table to display\n"
3a2d747c 12344 "Network in the BGP routing table to display\n"
9973d184 12345 JSON_STR)
91d37724 12346{
d62a17ae 12347 int idx = 0;
12348 char *network = NULL;
12349 struct bgp *bgp = bgp_get_default();
12350 if (!bgp) {
12351 vty_out(vty, "Can't find default instance\n");
12352 return CMD_WARNING;
12353 }
87e34b58 12354
d62a17ae 12355 if (argv_find(argv, argc, "A.B.C.D", &idx))
12356 network = argv[idx]->arg;
12357 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12358 network = argv[idx]->arg;
12359 else {
12360 vty_out(vty, "Unable to figure out Network\n");
12361 return CMD_WARNING;
12362 }
87e34b58 12363
d62a17ae 12364 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12365 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12366}
d6902373 12367#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12368
44c69747
LK
12369DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12370 show_bgp_l2vpn_evpn_route_prefix_cmd,
12371 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12372 SHOW_STR
4c63a661
PG
12373 BGP_STR
12374 L2VPN_HELP_STR
12375 EVPN_HELP_STR
44c69747
LK
12376 "Network in the BGP routing table to display\n"
12377 "Network in the BGP routing table to display\n"
4c63a661
PG
12378 "Network in the BGP routing table to display\n"
12379 "Network in the BGP routing table to display\n"
12380 JSON_STR)
12381{
d62a17ae 12382 int idx = 0;
12383 char *network = NULL;
44c69747 12384 int prefix_check = 0;
a636c635 12385
44c69747
LK
12386 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12387 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12388 network = argv[idx]->arg;
44c69747 12389 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12390 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12391 network = argv[idx]->arg;
44c69747
LK
12392 prefix_check = 1;
12393 } else {
d62a17ae 12394 vty_out(vty, "Unable to figure out Network\n");
12395 return CMD_WARNING;
12396 }
44c69747
LK
12397 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12398 prefix_check, BGP_PATH_SHOW_ALL,
12399 use_json(argc, argv));
d62a17ae 12400}
12401
2f9bc755
DS
12402static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12403 struct bgp_table *table, int *header1,
12404 int *header2, json_object *json,
12405 json_object *json_scode,
12406 json_object *json_ocode, bool wide)
12407{
12408 uint64_t version = table ? table->version : 0;
12409
12410 if (*header1) {
12411 if (json) {
12412 json_object_int_add(json, "bgpTableVersion", version);
12413 json_object_string_add(json, "bgpLocalRouterId",
12414 inet_ntoa(bgp->router_id));
12415 json_object_int_add(json, "defaultLocPrf",
12416 bgp->default_local_pref);
12417 json_object_int_add(json, "localAS", bgp->as);
12418 json_object_object_add(json, "bgpStatusCodes",
12419 json_scode);
12420 json_object_object_add(json, "bgpOriginCodes",
12421 json_ocode);
12422 } else {
12423 vty_out(vty,
12424 "BGP table version is %" PRIu64 ", local router ID is %s, vrf id ",
12425 version, inet_ntoa(bgp->router_id));
12426 if (bgp->vrf_id == VRF_UNKNOWN)
12427 vty_out(vty, "%s", VRFID_NONE_STR);
12428 else
12429 vty_out(vty, "%u", bgp->vrf_id);
12430 vty_out(vty, "\n");
12431 vty_out(vty, "Default local pref %u, ",
12432 bgp->default_local_pref);
12433 vty_out(vty, "local AS %u\n", bgp->as);
12434 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12435 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12436 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12437 }
12438 *header1 = 0;
12439 }
12440 if (*header2) {
12441 if (!json)
12442 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12443 : BGP_SHOW_HEADER));
12444 *header2 = 0;
12445 }
12446}
12447
d62a17ae 12448static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12449 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12450 const char *rmap_name, json_object *json,
12451 uint8_t show_flags)
d62a17ae 12452{
12453 struct bgp_table *table;
12454 struct bgp_adj_in *ain;
12455 struct bgp_adj_out *adj;
74a630b6
NT
12456 unsigned long output_count = 0;
12457 unsigned long filtered_count = 0;
9bcb3eef 12458 struct bgp_dest *dest;
d62a17ae 12459 int header1 = 1;
12460 struct bgp *bgp;
12461 int header2 = 1;
12462 struct attr attr;
12463 int ret;
12464 struct update_subgroup *subgrp;
12465 json_object *json_scode = NULL;
12466 json_object *json_ocode = NULL;
12467 json_object *json_ar = NULL;
12468 struct peer_af *paf;
f99def61 12469 bool route_filtered;
96f3485c
MK
12470 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12471 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12472
12473 if (use_json) {
12474 json_scode = json_object_new_object();
12475 json_ocode = json_object_new_object();
12476 json_ar = json_object_new_object();
12477
12478 json_object_string_add(json_scode, "suppressed", "s");
12479 json_object_string_add(json_scode, "damped", "d");
12480 json_object_string_add(json_scode, "history", "h");
12481 json_object_string_add(json_scode, "valid", "*");
12482 json_object_string_add(json_scode, "best", ">");
12483 json_object_string_add(json_scode, "multipath", "=");
12484 json_object_string_add(json_scode, "internal", "i");
12485 json_object_string_add(json_scode, "ribFailure", "r");
12486 json_object_string_add(json_scode, "stale", "S");
12487 json_object_string_add(json_scode, "removed", "R");
12488
12489 json_object_string_add(json_ocode, "igp", "i");
12490 json_object_string_add(json_ocode, "egp", "e");
12491 json_object_string_add(json_ocode, "incomplete", "?");
12492 }
a636c635 12493
d62a17ae 12494 bgp = peer->bgp;
a636c635 12495
d62a17ae 12496 if (!bgp) {
12497 if (use_json) {
12498 json_object_string_add(json, "alert", "no BGP");
12499 vty_out(vty, "%s\n", json_object_to_json_string(json));
12500 json_object_free(json);
12501 } else
12502 vty_out(vty, "%% No bgp\n");
12503 return;
12504 }
a636c635 12505
c512a642
EDP
12506 /* labeled-unicast routes live in the unicast table */
12507 if (safi == SAFI_LABELED_UNICAST)
12508 table = bgp->rib[afi][SAFI_UNICAST];
12509 else
12510 table = bgp->rib[afi][safi];
d62a17ae 12511
12512 output_count = filtered_count = 0;
12513 subgrp = peer_subgroup(peer, afi, safi);
12514
6392aaa6 12515 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12516 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
12517 if (use_json) {
12518 json_object_int_add(json, "bgpTableVersion",
12519 table->version);
12520 json_object_string_add(json, "bgpLocalRouterId",
12521 inet_ntoa(bgp->router_id));
01eced22
AD
12522 json_object_int_add(json, "defaultLocPrf",
12523 bgp->default_local_pref);
12524 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12525 json_object_object_add(json, "bgpStatusCodes",
12526 json_scode);
12527 json_object_object_add(json, "bgpOriginCodes",
12528 json_ocode);
07d0c4ed
DA
12529 json_object_string_add(
12530 json, "bgpOriginatingDefaultNetwork",
12531 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12532 } else {
6cde4b45 12533 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
d62a17ae 12534 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
12535 if (bgp->vrf_id == VRF_UNKNOWN)
12536 vty_out(vty, "%s", VRFID_NONE_STR);
12537 else
12538 vty_out(vty, "%u", bgp->vrf_id);
12539 vty_out(vty, "\n");
01eced22
AD
12540 vty_out(vty, "Default local pref %u, ",
12541 bgp->default_local_pref);
12542 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12543 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12544 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12545 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12546
07d0c4ed
DA
12547 vty_out(vty, "Originating default network %s\n\n",
12548 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12549 }
12550 header1 = 0;
12551 }
a636c635 12552
9bcb3eef 12553 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
12554 if (type == bgp_show_adj_route_received
12555 || type == bgp_show_adj_route_filtered) {
9bcb3eef 12556 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 12557 if (ain->peer != peer)
ea47320b 12558 continue;
6392aaa6 12559
2f9bc755
DS
12560 show_adj_route_header(
12561 vty, bgp, table, &header1, &header2,
12562 json, json_scode, json_ocode, wide);
6392aaa6 12563
6f4f49b2 12564 attr = *ain->attr;
f99def61
AD
12565 route_filtered = false;
12566
12567 /* Filter prefix using distribute list,
12568 * filter list or prefix list
12569 */
b54892e0 12570 const struct prefix *rn_p =
9bcb3eef 12571 bgp_dest_get_prefix(dest);
b54892e0
DS
12572 if ((bgp_input_filter(peer, rn_p, &attr, afi,
12573 safi))
12574 == FILTER_DENY)
f99def61
AD
12575 route_filtered = true;
12576
12577 /* Filter prefix using route-map */
b54892e0
DS
12578 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
12579 safi, rmap_name, NULL,
12580 0, NULL);
6392aaa6 12581
13c8e163
AD
12582 if (type == bgp_show_adj_route_filtered &&
12583 !route_filtered && ret != RMAP_DENY) {
b755861b 12584 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12585 continue;
d62a17ae 12586 }
6392aaa6 12587
13c8e163
AD
12588 if (type == bgp_show_adj_route_received &&
12589 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
12590 filtered_count++;
12591
b54892e0 12592 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 12593 use_json, json_ar, wide);
b755861b 12594 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12595 output_count++;
d62a17ae 12596 }
6392aaa6 12597 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 12598 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 12599 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 12600 if (paf->peer != peer || !adj->attr)
924c3f6a 12601 continue;
d62a17ae 12602
2f9bc755
DS
12603 show_adj_route_header(
12604 vty, bgp, table, &header1,
12605 &header2, json, json_scode,
12606 json_ocode, wide);
d62a17ae 12607
b54892e0 12608 const struct prefix *rn_p =
9bcb3eef 12609 bgp_dest_get_prefix(dest);
b54892e0 12610
6f4f49b2 12611 attr = *adj->attr;
b755861b 12612 ret = bgp_output_modifier(
b54892e0 12613 peer, rn_p, &attr, afi, safi,
b755861b 12614 rmap_name);
f46d8e1e 12615
b755861b 12616 if (ret != RMAP_DENY) {
b54892e0
DS
12617 route_vty_out_tmp(
12618 vty, rn_p, &attr, safi,
ae248832
MK
12619 use_json, json_ar,
12620 wide);
b755861b
PM
12621 output_count++;
12622 } else {
12623 filtered_count++;
a2addae8 12624 }
b755861b
PM
12625
12626 bgp_attr_undup(&attr, adj->attr);
924c3f6a 12627 }
f20ce998
DS
12628 } else if (type == bgp_show_adj_route_bestpath) {
12629 struct bgp_path_info *pi;
12630
12631 show_adj_route_header(vty, bgp, table, &header1,
12632 &header2, json, json_scode,
12633 json_ocode, wide);
12634
12635 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
12636 pi = pi->next) {
12637 if (pi->peer != peer)
12638 continue;
12639
12640 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12641 continue;
12642
12643 route_vty_out_tmp(vty,
12644 bgp_dest_get_prefix(dest),
12645 pi->attr, safi, use_json,
12646 json_ar, wide);
12647 output_count++;
12648 }
d62a17ae 12649 }
12650 }
d62a17ae 12651
d62a17ae 12652 if (use_json) {
6392aaa6
PM
12653 json_object_object_add(json, "advertisedRoutes", json_ar);
12654 json_object_int_add(json, "totalPrefixCounter", output_count);
12655 json_object_int_add(json, "filteredPrefixCounter",
12656 filtered_count);
12657
996c9314
LB
12658 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12659 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
12660
12661 if (!output_count && !filtered_count) {
12662 json_object_free(json_scode);
12663 json_object_free(json_ocode);
12664 }
12665
d62a17ae 12666 json_object_free(json);
6392aaa6
PM
12667 } else if (output_count > 0) {
12668 if (filtered_count > 0)
12669 vty_out(vty,
12670 "\nTotal number of prefixes %ld (%ld filtered)\n",
12671 output_count, filtered_count);
12672 else
12673 vty_out(vty, "\nTotal number of prefixes %ld\n",
12674 output_count);
d62a17ae 12675 }
a636c635 12676}
2a71e9ce 12677
d62a17ae 12678static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12679 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 12680 const char *rmap_name, uint8_t show_flags)
0b16f239 12681{
d62a17ae 12682 json_object *json = NULL;
96f3485c 12683 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 12684
d62a17ae 12685 if (use_json)
12686 json = json_object_new_object();
0b16f239 12687
d62a17ae 12688 if (!peer || !peer->afc[afi][safi]) {
12689 if (use_json) {
12690 json_object_string_add(
12691 json, "warning",
12692 "No such neighbor or address family");
12693 vty_out(vty, "%s\n", json_object_to_json_string(json));
12694 json_object_free(json);
12695 } else
12696 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 12697
d62a17ae 12698 return CMD_WARNING;
12699 }
12700
6392aaa6
PM
12701 if ((type == bgp_show_adj_route_received
12702 || type == bgp_show_adj_route_filtered)
d62a17ae 12703 && !CHECK_FLAG(peer->af_flags[afi][safi],
12704 PEER_FLAG_SOFT_RECONFIG)) {
12705 if (use_json) {
12706 json_object_string_add(
12707 json, "warning",
12708 "Inbound soft reconfiguration not enabled");
12709 vty_out(vty, "%s\n", json_object_to_json_string(json));
12710 json_object_free(json);
12711 } else
12712 vty_out(vty,
12713 "%% Inbound soft reconfiguration not enabled\n");
12714
12715 return CMD_WARNING;
12716 }
0b16f239 12717
96f3485c 12718 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 12719
d62a17ae 12720 return CMD_SUCCESS;
a636c635 12721}
50ef26d4 12722
f20ce998
DS
12723DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
12724 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
12725 "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]",
12726 SHOW_STR
12727 IP_STR
12728 BGP_STR
12729 BGP_INSTANCE_HELP_STR
12730 BGP_AFI_HELP_STR
12731 BGP_SAFI_WITH_LABEL_HELP_STR
12732 "Detailed information on TCP and BGP neighbor connections\n"
12733 "Neighbor to display information about\n"
12734 "Neighbor to display information about\n"
12735 "Neighbor on BGP configured interface\n"
12736 "Display the routes selected by best path\n"
12737 JSON_STR
12738 "Increase table width for longer prefixes\n")
12739{
12740 afi_t afi = AFI_IP6;
12741 safi_t safi = SAFI_UNICAST;
12742 char *rmap_name = NULL;
12743 char *peerstr = NULL;
12744 struct bgp *bgp = NULL;
12745 struct peer *peer;
12746 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
12747 int idx = 0;
96f3485c
MK
12748 uint8_t show_flags = 0;
12749
12750 if (uj)
12751 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12752
12753 if (wide)
12754 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
12755
12756 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12757 &bgp, uj);
12758
12759 if (!idx)
12760 return CMD_WARNING;
12761
12762 argv_find(argv, argc, "neighbors", &idx);
12763 peerstr = argv[++idx]->arg;
12764
12765 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12766 if (!peer)
12767 return CMD_WARNING;
12768
96f3485c
MK
12769 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12770 show_flags);
f20ce998
DS
12771}
12772
ae248832 12773DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 12774 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 12775 "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 12776 SHOW_STR
12777 IP_STR
12778 BGP_STR
a636c635 12779 BGP_INSTANCE_HELP_STR
7395a2c9 12780 BGP_AFI_HELP_STR
4dd6177e 12781 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12782 "Display the entries for all address families\n"
718e3744 12783 "Detailed information on TCP and BGP neighbor connections\n"
12784 "Neighbor to display information about\n"
12785 "Neighbor to display information about\n"
91d37724 12786 "Neighbor on BGP configured interface\n"
a636c635 12787 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
12788 "Display the received routes from neighbor\n"
12789 "Display the filtered routes received from neighbor\n"
a636c635
DW
12790 "Route-map to modify the attributes\n"
12791 "Name of the route map\n"
ae248832
MK
12792 JSON_STR
12793 "Increase table width for longer prefixes\n")
718e3744 12794{
d62a17ae 12795 afi_t afi = AFI_IP6;
12796 safi_t safi = SAFI_UNICAST;
12797 char *rmap_name = NULL;
12798 char *peerstr = NULL;
d62a17ae 12799 struct bgp *bgp = NULL;
12800 struct peer *peer;
6392aaa6 12801 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 12802 int idx = 0;
96f3485c
MK
12803 bool first = true;
12804 uint8_t show_flags = 0;
6392aaa6 12805
96f3485c 12806 if (uj) {
d62a17ae 12807 argc--;
96f3485c
MK
12808 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12809 }
12810
12811 if (all) {
12812 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12813 if (argv_find(argv, argc, "ipv4", &idx))
12814 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12815
12816 if (argv_find(argv, argc, "ipv6", &idx))
12817 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12818 }
12819
12820 if (wide)
12821 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 12822
9f049418
DS
12823 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12824 &bgp, uj);
12825 if (!idx)
12826 return CMD_WARNING;
12827
d62a17ae 12828 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12829 argv_find(argv, argc, "neighbors", &idx);
12830 peerstr = argv[++idx]->arg;
8c3deaae 12831
d62a17ae 12832 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12833 if (!peer)
12834 return CMD_WARNING;
856ca177 12835
d62a17ae 12836 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
12837 type = bgp_show_adj_route_advertised;
12838 else if (argv_find(argv, argc, "received-routes", &idx))
12839 type = bgp_show_adj_route_received;
12840 else if (argv_find(argv, argc, "filtered-routes", &idx))
12841 type = bgp_show_adj_route_filtered;
12842
d62a17ae 12843 if (argv_find(argv, argc, "route-map", &idx))
12844 rmap_name = argv[++idx]->arg;
95cbbd2a 12845
96f3485c
MK
12846 if (!all)
12847 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12848 show_flags);
12849 if (uj)
12850 vty_out(vty, "{\n");
12851
12852 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12853 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12854 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
12855 : AFI_IP6;
12856 FOREACH_SAFI (safi) {
12857 if (strmatch(get_afi_safi_str(afi, safi, true),
12858 "Unknown"))
12859 continue;
12860
12861 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12862 continue;
12863
12864 if (uj) {
12865 if (first)
12866 first = false;
12867 else
12868 vty_out(vty, ",\n");
12869 vty_out(vty, "\"%s\":",
12870 get_afi_safi_str(afi, safi, true));
12871 } else
12872 vty_out(vty, "\nFor address family: %s\n",
12873 get_afi_safi_str(afi, safi, false));
12874
12875 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12876 show_flags);
12877 }
12878 } else {
12879 FOREACH_AFI_SAFI (afi, safi) {
12880 if (strmatch(get_afi_safi_str(afi, safi, true),
12881 "Unknown"))
12882 continue;
12883
12884 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12885 continue;
12886
12887 if (uj) {
12888 if (first)
12889 first = false;
12890 else
12891 vty_out(vty, ",\n");
12892 vty_out(vty, "\"%s\":",
12893 get_afi_safi_str(afi, safi, true));
12894 } else
12895 vty_out(vty, "\nFor address family: %s\n",
12896 get_afi_safi_str(afi, safi, false));
12897
12898 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12899 show_flags);
12900 }
12901 }
12902 if (uj)
12903 vty_out(vty, "}\n");
12904
12905 return CMD_SUCCESS;
95cbbd2a
ML
12906}
12907
718e3744 12908DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
12909 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 12910 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 12911 SHOW_STR
12912 IP_STR
12913 BGP_STR
8c3deaae
QY
12914 "Address Family\n"
12915 "Address Family\n"
718e3744 12916 "Address Family modifier\n"
12917 "Detailed information on TCP and BGP neighbor connections\n"
12918 "Neighbor to display information about\n"
12919 "Neighbor to display information about\n"
91d37724 12920 "Neighbor on BGP configured interface\n"
718e3744 12921 "Display information received from a BGP neighbor\n"
856ca177 12922 "Display the prefixlist filter\n"
9973d184 12923 JSON_STR)
718e3744 12924{
d62a17ae 12925 afi_t afi = AFI_IP6;
12926 safi_t safi = SAFI_UNICAST;
12927 char *peerstr = NULL;
12928
12929 char name[BUFSIZ];
12930 union sockunion su;
12931 struct peer *peer;
12932 int count, ret;
12933
12934 int idx = 0;
12935
12936 /* show [ip] bgp */
12937 if (argv_find(argv, argc, "ip", &idx))
12938 afi = AFI_IP;
12939 /* [<ipv4|ipv6> [unicast]] */
12940 if (argv_find(argv, argc, "ipv4", &idx))
12941 afi = AFI_IP;
12942 if (argv_find(argv, argc, "ipv6", &idx))
12943 afi = AFI_IP6;
12944 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12945 argv_find(argv, argc, "neighbors", &idx);
12946 peerstr = argv[++idx]->arg;
12947
9f049418 12948 bool uj = use_json(argc, argv);
d62a17ae 12949
12950 ret = str2sockunion(peerstr, &su);
12951 if (ret < 0) {
12952 peer = peer_lookup_by_conf_if(NULL, peerstr);
12953 if (!peer) {
12954 if (uj)
12955 vty_out(vty, "{}\n");
12956 else
12957 vty_out(vty,
12958 "%% Malformed address or name: %s\n",
12959 peerstr);
12960 return CMD_WARNING;
12961 }
12962 } else {
12963 peer = peer_lookup(NULL, &su);
12964 if (!peer) {
12965 if (uj)
12966 vty_out(vty, "{}\n");
12967 else
12968 vty_out(vty, "No peer\n");
12969 return CMD_WARNING;
12970 }
12971 }
718e3744 12972
4ced1a2c 12973 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 12974 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12975 if (count) {
12976 if (!uj)
12977 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12978 get_afi_safi_str(afi, safi, false));
d62a17ae 12979 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12980 } else {
12981 if (uj)
12982 vty_out(vty, "{}\n");
12983 else
12984 vty_out(vty, "No functional output\n");
12985 }
718e3744 12986
d62a17ae 12987 return CMD_SUCCESS;
12988}
12989
12990static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12991 afi_t afi, safi_t safi,
9f049418 12992 enum bgp_show_type type, bool use_json)
d62a17ae 12993{
96f3485c
MK
12994 uint8_t show_flags = 0;
12995
12996 if (use_json)
12997 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12998
d62a17ae 12999 if (!peer || !peer->afc[afi][safi]) {
13000 if (use_json) {
13001 json_object *json_no = NULL;
13002 json_no = json_object_new_object();
13003 json_object_string_add(
13004 json_no, "warning",
13005 "No such neighbor or address family");
13006 vty_out(vty, "%s\n",
13007 json_object_to_json_string(json_no));
13008 json_object_free(json_no);
13009 } else
13010 vty_out(vty, "%% No such neighbor or address family\n");
13011 return CMD_WARNING;
13012 }
47fc97cc 13013
7daf25a3
TA
13014 /* labeled-unicast routes live in the unicast table */
13015 if (safi == SAFI_LABELED_UNICAST)
13016 safi = SAFI_UNICAST;
13017
96f3485c 13018 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13019}
13020
dba3c1d3
PG
13021DEFUN (show_ip_bgp_flowspec_routes_detailed,
13022 show_ip_bgp_flowspec_routes_detailed_cmd,
13023 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13024 SHOW_STR
13025 IP_STR
13026 BGP_STR
13027 BGP_INSTANCE_HELP_STR
13028 BGP_AFI_HELP_STR
13029 "SAFI Flowspec\n"
13030 "Detailed information on flowspec entries\n"
13031 JSON_STR)
13032{
13033 afi_t afi = AFI_IP;
13034 safi_t safi = SAFI_UNICAST;
13035 struct bgp *bgp = NULL;
13036 int idx = 0;
9f049418 13037 bool uj = use_json(argc, argv);
96f3485c 13038 uint8_t show_flags = 0;
9f049418 13039
96f3485c 13040 if (uj) {
9f049418 13041 argc--;
96f3485c
MK
13042 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13043 }
dba3c1d3
PG
13044
13045 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13046 &bgp, uj);
dba3c1d3
PG
13047 if (!idx)
13048 return CMD_WARNING;
13049
96f3485c
MK
13050 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13051 show_flags);
dba3c1d3
PG
13052}
13053
718e3744 13054DEFUN (show_ip_bgp_neighbor_routes,
13055 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13056 "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 13057 SHOW_STR
13058 IP_STR
13059 BGP_STR
8386ac43 13060 BGP_INSTANCE_HELP_STR
4f280b15 13061 BGP_AFI_HELP_STR
4dd6177e 13062 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13063 "Detailed information on TCP and BGP neighbor connections\n"
13064 "Neighbor to display information about\n"
13065 "Neighbor to display information about\n"
91d37724 13066 "Neighbor on BGP configured interface\n"
2525cf39 13067 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13068 "Display the dampened routes received from neighbor\n"
13069 "Display routes learned from neighbor\n"
9973d184 13070 JSON_STR)
718e3744 13071{
d62a17ae 13072 char *peerstr = NULL;
13073 struct bgp *bgp = NULL;
13074 afi_t afi = AFI_IP6;
13075 safi_t safi = SAFI_UNICAST;
13076 struct peer *peer;
13077 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13078 int idx = 0;
9f049418
DS
13079 bool uj = use_json(argc, argv);
13080
13081 if (uj)
13082 argc--;
bb46e94f 13083
d62a17ae 13084 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13085 &bgp, uj);
d62a17ae 13086 if (!idx)
13087 return CMD_WARNING;
c493f2d8 13088
d62a17ae 13089 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13090 argv_find(argv, argc, "neighbors", &idx);
13091 peerstr = argv[++idx]->arg;
8c3deaae 13092
d62a17ae 13093 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13094 if (!peer)
d62a17ae 13095 return CMD_WARNING;
bb46e94f 13096
d62a17ae 13097 if (argv_find(argv, argc, "flap-statistics", &idx))
13098 sh_type = bgp_show_type_flap_neighbor;
13099 else if (argv_find(argv, argc, "dampened-routes", &idx))
13100 sh_type = bgp_show_type_damp_neighbor;
13101 else if (argv_find(argv, argc, "routes", &idx))
13102 sh_type = bgp_show_type_neighbor;
2525cf39 13103
d62a17ae 13104 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13105}
6b0655a2 13106
734b349e 13107struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13108
d62a17ae 13109struct bgp_distance {
13110 /* Distance value for the IP source prefix. */
d7c0a89a 13111 uint8_t distance;
718e3744 13112
d62a17ae 13113 /* Name of the access-list to be matched. */
13114 char *access_list;
718e3744 13115};
13116
4f280b15
LB
13117DEFUN (show_bgp_afi_vpn_rd_route,
13118 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13119 "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
13120 SHOW_STR
13121 BGP_STR
13122 BGP_AFI_HELP_STR
13123 "Address Family modifier\n"
13124 "Display information for a route distinguisher\n"
13125 "Route Distinguisher\n"
7395a2c9
DS
13126 "Network in the BGP routing table to display\n"
13127 "Network in the BGP routing table to display\n"
13128 JSON_STR)
4f280b15 13129{
d62a17ae 13130 int ret;
13131 struct prefix_rd prd;
13132 afi_t afi = AFI_MAX;
13133 int idx = 0;
4f280b15 13134
ff6566f3
DS
13135 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13136 vty_out(vty, "%% Malformed Address Family\n");
13137 return CMD_WARNING;
13138 }
13139
d62a17ae 13140 ret = str2prefix_rd(argv[5]->arg, &prd);
13141 if (!ret) {
13142 vty_out(vty, "%% Malformed Route Distinguisher\n");
13143 return CMD_WARNING;
13144 }
ff6566f3 13145
d62a17ae 13146 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13147 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13148}
13149
d62a17ae 13150static struct bgp_distance *bgp_distance_new(void)
718e3744 13151{
d62a17ae 13152 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13153}
13154
d62a17ae 13155static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13156{
d62a17ae 13157 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13158}
13159
d62a17ae 13160static int bgp_distance_set(struct vty *vty, const char *distance_str,
13161 const char *ip_str, const char *access_list_str)
718e3744 13162{
d62a17ae 13163 int ret;
13164 afi_t afi;
13165 safi_t safi;
13166 struct prefix p;
d7c0a89a 13167 uint8_t distance;
9bcb3eef 13168 struct bgp_dest *dest;
d62a17ae 13169 struct bgp_distance *bdistance;
718e3744 13170
d62a17ae 13171 afi = bgp_node_afi(vty);
13172 safi = bgp_node_safi(vty);
734b349e 13173
d62a17ae 13174 ret = str2prefix(ip_str, &p);
13175 if (ret == 0) {
13176 vty_out(vty, "Malformed prefix\n");
13177 return CMD_WARNING_CONFIG_FAILED;
13178 }
718e3744 13179
d62a17ae 13180 distance = atoi(distance_str);
718e3744 13181
d62a17ae 13182 /* Get BGP distance node. */
9bcb3eef
DS
13183 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13184 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13185 if (bdistance)
9bcb3eef 13186 bgp_dest_unlock_node(dest);
ca2e160d 13187 else {
d62a17ae 13188 bdistance = bgp_distance_new();
9bcb3eef 13189 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13190 }
718e3744 13191
d62a17ae 13192 /* Set distance value. */
13193 bdistance->distance = distance;
718e3744 13194
d62a17ae 13195 /* Reset access-list configuration. */
e1b36e13 13196 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13197 if (access_list_str)
13198 bdistance->access_list =
13199 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13200
d62a17ae 13201 return CMD_SUCCESS;
718e3744 13202}
13203
d62a17ae 13204static int bgp_distance_unset(struct vty *vty, const char *distance_str,
13205 const char *ip_str, const char *access_list_str)
718e3744 13206{
d62a17ae 13207 int ret;
13208 afi_t afi;
13209 safi_t safi;
13210 struct prefix p;
13211 int distance;
9bcb3eef 13212 struct bgp_dest *dest;
d62a17ae 13213 struct bgp_distance *bdistance;
718e3744 13214
d62a17ae 13215 afi = bgp_node_afi(vty);
13216 safi = bgp_node_safi(vty);
734b349e 13217
d62a17ae 13218 ret = str2prefix(ip_str, &p);
13219 if (ret == 0) {
13220 vty_out(vty, "Malformed prefix\n");
13221 return CMD_WARNING_CONFIG_FAILED;
13222 }
718e3744 13223
9bcb3eef
DS
13224 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13225 if (!dest) {
d62a17ae 13226 vty_out(vty, "Can't find specified prefix\n");
13227 return CMD_WARNING_CONFIG_FAILED;
13228 }
718e3744 13229
9bcb3eef 13230 bdistance = bgp_dest_get_bgp_distance_info(dest);
d62a17ae 13231 distance = atoi(distance_str);
1f9a9fff 13232
d62a17ae 13233 if (bdistance->distance != distance) {
13234 vty_out(vty, "Distance does not match configured\n");
13235 return CMD_WARNING_CONFIG_FAILED;
13236 }
718e3744 13237
0a22ddfb 13238 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13239 bgp_distance_free(bdistance);
718e3744 13240
9bcb3eef
DS
13241 bgp_dest_set_bgp_path_info(dest, NULL);
13242 bgp_dest_unlock_node(dest);
13243 bgp_dest_unlock_node(dest);
718e3744 13244
d62a17ae 13245 return CMD_SUCCESS;
718e3744 13246}
13247
718e3744 13248/* Apply BGP information to distance method. */
b8685f9b 13249uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13250 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13251{
9bcb3eef 13252 struct bgp_dest *dest;
d62a17ae 13253 struct prefix q;
13254 struct peer *peer;
13255 struct bgp_distance *bdistance;
13256 struct access_list *alist;
13257 struct bgp_static *bgp_static;
13258
13259 if (!bgp)
13260 return 0;
13261
40381db7 13262 peer = pinfo->peer;
d62a17ae 13263
7b7d48e5
DS
13264 if (pinfo->attr->distance)
13265 return pinfo->attr->distance;
13266
d62a17ae 13267 /* Check source address. */
13268 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
13269 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13270 if (dest) {
13271 bdistance = bgp_dest_get_bgp_distance_info(dest);
13272 bgp_dest_unlock_node(dest);
d62a17ae 13273
13274 if (bdistance->access_list) {
13275 alist = access_list_lookup(afi, bdistance->access_list);
13276 if (alist
13277 && access_list_apply(alist, p) == FILTER_PERMIT)
13278 return bdistance->distance;
13279 } else
13280 return bdistance->distance;
718e3744 13281 }
718e3744 13282
d62a17ae 13283 /* Backdoor check. */
9bcb3eef
DS
13284 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13285 if (dest) {
13286 bgp_static = bgp_dest_get_bgp_static_info(dest);
13287 bgp_dest_unlock_node(dest);
718e3744 13288
d62a17ae 13289 if (bgp_static->backdoor) {
13290 if (bgp->distance_local[afi][safi])
13291 return bgp->distance_local[afi][safi];
13292 else
13293 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13294 }
718e3744 13295 }
718e3744 13296
d62a17ae 13297 if (peer->sort == BGP_PEER_EBGP) {
13298 if (bgp->distance_ebgp[afi][safi])
13299 return bgp->distance_ebgp[afi][safi];
13300 return ZEBRA_EBGP_DISTANCE_DEFAULT;
13301 } else {
13302 if (bgp->distance_ibgp[afi][safi])
13303 return bgp->distance_ibgp[afi][safi];
13304 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13305 }
718e3744 13306}
13307
a612fb77
DA
13308/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13309 * we should tell ZEBRA update the routes for a specific
13310 * AFI/SAFI to reflect changes in RIB.
13311 */
8b54bc30
DA
13312static void bgp_announce_routes_distance_update(struct bgp *bgp,
13313 afi_t update_afi,
13314 safi_t update_safi)
a612fb77
DA
13315{
13316 afi_t afi;
13317 safi_t safi;
13318
13319 FOREACH_AFI_SAFI (afi, safi) {
13320 if (!bgp_fibupd_safi(safi))
13321 continue;
13322
8b54bc30
DA
13323 if (afi != update_afi && safi != update_safi)
13324 continue;
13325
13326 if (BGP_DEBUG(zebra, ZEBRA))
13327 zlog_debug(
13328 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13329 __func__, afi, safi);
13330 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13331 }
13332}
13333
718e3744 13334DEFUN (bgp_distance,
13335 bgp_distance_cmd,
6147e2c6 13336 "distance bgp (1-255) (1-255) (1-255)",
718e3744 13337 "Define an administrative distance\n"
13338 "BGP distance\n"
13339 "Distance for routes external to the AS\n"
13340 "Distance for routes internal to the AS\n"
13341 "Distance for local routes\n")
13342{
d62a17ae 13343 VTY_DECLVAR_CONTEXT(bgp, bgp);
13344 int idx_number = 2;
13345 int idx_number_2 = 3;
13346 int idx_number_3 = 4;
8b54bc30
DA
13347 int distance_ebgp = atoi(argv[idx_number]->arg);
13348 int distance_ibgp = atoi(argv[idx_number_2]->arg);
13349 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 13350 afi_t afi;
13351 safi_t safi;
718e3744 13352
d62a17ae 13353 afi = bgp_node_afi(vty);
13354 safi = bgp_node_safi(vty);
718e3744 13355
8b54bc30
DA
13356 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
13357 || bgp->distance_ibgp[afi][safi] != distance_ibgp
13358 || bgp->distance_local[afi][safi] != distance_local) {
13359 bgp->distance_ebgp[afi][safi] = distance_ebgp;
13360 bgp->distance_ibgp[afi][safi] = distance_ibgp;
13361 bgp->distance_local[afi][safi] = distance_local;
13362 bgp_announce_routes_distance_update(bgp, afi, safi);
13363 }
d62a17ae 13364 return CMD_SUCCESS;
718e3744 13365}
13366
13367DEFUN (no_bgp_distance,
13368 no_bgp_distance_cmd,
a636c635 13369 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 13370 NO_STR
13371 "Define an administrative distance\n"
13372 "BGP distance\n"
13373 "Distance for routes external to the AS\n"
13374 "Distance for routes internal to the AS\n"
13375 "Distance for local routes\n")
13376{
d62a17ae 13377 VTY_DECLVAR_CONTEXT(bgp, bgp);
13378 afi_t afi;
13379 safi_t safi;
718e3744 13380
d62a17ae 13381 afi = bgp_node_afi(vty);
13382 safi = bgp_node_safi(vty);
718e3744 13383
8b54bc30
DA
13384 if (bgp->distance_ebgp[afi][safi] != 0
13385 || bgp->distance_ibgp[afi][safi] != 0
13386 || bgp->distance_local[afi][safi] != 0) {
13387 bgp->distance_ebgp[afi][safi] = 0;
13388 bgp->distance_ibgp[afi][safi] = 0;
13389 bgp->distance_local[afi][safi] = 0;
13390 bgp_announce_routes_distance_update(bgp, afi, safi);
13391 }
d62a17ae 13392 return CMD_SUCCESS;
718e3744 13393}
13394
718e3744 13395
13396DEFUN (bgp_distance_source,
13397 bgp_distance_source_cmd,
6147e2c6 13398 "distance (1-255) A.B.C.D/M",
718e3744 13399 "Define an administrative distance\n"
13400 "Administrative distance\n"
13401 "IP source prefix\n")
13402{
d62a17ae 13403 int idx_number = 1;
13404 int idx_ipv4_prefixlen = 2;
13405 bgp_distance_set(vty, argv[idx_number]->arg,
13406 argv[idx_ipv4_prefixlen]->arg, NULL);
13407 return CMD_SUCCESS;
718e3744 13408}
13409
13410DEFUN (no_bgp_distance_source,
13411 no_bgp_distance_source_cmd,
6147e2c6 13412 "no distance (1-255) A.B.C.D/M",
718e3744 13413 NO_STR
13414 "Define an administrative distance\n"
13415 "Administrative distance\n"
13416 "IP source prefix\n")
13417{
d62a17ae 13418 int idx_number = 2;
13419 int idx_ipv4_prefixlen = 3;
13420 bgp_distance_unset(vty, argv[idx_number]->arg,
13421 argv[idx_ipv4_prefixlen]->arg, NULL);
13422 return CMD_SUCCESS;
718e3744 13423}
13424
13425DEFUN (bgp_distance_source_access_list,
13426 bgp_distance_source_access_list_cmd,
6147e2c6 13427 "distance (1-255) A.B.C.D/M WORD",
718e3744 13428 "Define an administrative distance\n"
13429 "Administrative distance\n"
13430 "IP source prefix\n"
13431 "Access list name\n")
13432{
d62a17ae 13433 int idx_number = 1;
13434 int idx_ipv4_prefixlen = 2;
13435 int idx_word = 3;
13436 bgp_distance_set(vty, argv[idx_number]->arg,
13437 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
13438 return CMD_SUCCESS;
718e3744 13439}
13440
13441DEFUN (no_bgp_distance_source_access_list,
13442 no_bgp_distance_source_access_list_cmd,
6147e2c6 13443 "no distance (1-255) A.B.C.D/M WORD",
718e3744 13444 NO_STR
13445 "Define an administrative distance\n"
13446 "Administrative distance\n"
13447 "IP source prefix\n"
13448 "Access list name\n")
13449{
d62a17ae 13450 int idx_number = 2;
13451 int idx_ipv4_prefixlen = 3;
13452 int idx_word = 4;
13453 bgp_distance_unset(vty, argv[idx_number]->arg,
13454 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
13455 return CMD_SUCCESS;
718e3744 13456}
6b0655a2 13457
734b349e
MZ
13458DEFUN (ipv6_bgp_distance_source,
13459 ipv6_bgp_distance_source_cmd,
39e92c06 13460 "distance (1-255) X:X::X:X/M",
734b349e
MZ
13461 "Define an administrative distance\n"
13462 "Administrative distance\n"
13463 "IP source prefix\n")
13464{
d62a17ae 13465 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
13466 return CMD_SUCCESS;
734b349e
MZ
13467}
13468
13469DEFUN (no_ipv6_bgp_distance_source,
13470 no_ipv6_bgp_distance_source_cmd,
39e92c06 13471 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
13472 NO_STR
13473 "Define an administrative distance\n"
13474 "Administrative distance\n"
13475 "IP source prefix\n")
13476{
d62a17ae 13477 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
13478 return CMD_SUCCESS;
734b349e
MZ
13479}
13480
13481DEFUN (ipv6_bgp_distance_source_access_list,
13482 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 13483 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
13484 "Define an administrative distance\n"
13485 "Administrative distance\n"
13486 "IP source prefix\n"
13487 "Access list name\n")
13488{
d62a17ae 13489 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
13490 return CMD_SUCCESS;
734b349e
MZ
13491}
13492
13493DEFUN (no_ipv6_bgp_distance_source_access_list,
13494 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 13495 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
13496 NO_STR
13497 "Define an administrative distance\n"
13498 "Administrative distance\n"
13499 "IP source prefix\n"
13500 "Access list name\n")
13501{
d62a17ae 13502 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
13503 return CMD_SUCCESS;
734b349e
MZ
13504}
13505
718e3744 13506DEFUN (bgp_damp_set,
13507 bgp_damp_set_cmd,
31500417 13508 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 13509 "BGP Specific commands\n"
13510 "Enable route-flap dampening\n"
13511 "Half-life time for the penalty\n"
13512 "Value to start reusing a route\n"
13513 "Value to start suppressing a route\n"
13514 "Maximum duration to suppress a stable route\n")
13515{
d62a17ae 13516 VTY_DECLVAR_CONTEXT(bgp, bgp);
13517 int idx_half_life = 2;
13518 int idx_reuse = 3;
13519 int idx_suppress = 4;
13520 int idx_max_suppress = 5;
13521 int half = DEFAULT_HALF_LIFE * 60;
13522 int reuse = DEFAULT_REUSE;
13523 int suppress = DEFAULT_SUPPRESS;
13524 int max = 4 * half;
13525
13526 if (argc == 6) {
13527 half = atoi(argv[idx_half_life]->arg) * 60;
13528 reuse = atoi(argv[idx_reuse]->arg);
13529 suppress = atoi(argv[idx_suppress]->arg);
13530 max = atoi(argv[idx_max_suppress]->arg) * 60;
13531 } else if (argc == 3) {
13532 half = atoi(argv[idx_half_life]->arg) * 60;
13533 max = 4 * half;
13534 }
718e3744 13535
6d24b7cc
DS
13536 /*
13537 * These can't be 0 but our SA doesn't understand the
13538 * way our cli is constructed
13539 */
13540 assert(reuse);
13541 assert(half);
d62a17ae 13542 if (suppress < reuse) {
13543 vty_out(vty,
13544 "Suppress value cannot be less than reuse value \n");
13545 return 0;
13546 }
7ebe9748 13547
d62a17ae 13548 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
13549 reuse, suppress, max);
718e3744 13550}
13551
718e3744 13552DEFUN (bgp_damp_unset,
13553 bgp_damp_unset_cmd,
d04c479d 13554 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 13555 NO_STR
13556 "BGP Specific commands\n"
16cedbb0
QY
13557 "Enable route-flap dampening\n"
13558 "Half-life time for the penalty\n"
13559 "Value to start reusing a route\n"
13560 "Value to start suppressing a route\n"
13561 "Maximum duration to suppress a stable route\n")
718e3744 13562{
d62a17ae 13563 VTY_DECLVAR_CONTEXT(bgp, bgp);
13564 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 13565}
13566
718e3744 13567/* Display specified route of BGP table. */
d62a17ae 13568static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13569 const char *ip_str, afi_t afi, safi_t safi,
13570 struct prefix_rd *prd, int prefix_check)
13571{
13572 int ret;
13573 struct prefix match;
9bcb3eef
DS
13574 struct bgp_dest *dest;
13575 struct bgp_dest *rm;
40381db7
DS
13576 struct bgp_path_info *pi;
13577 struct bgp_path_info *pi_temp;
d62a17ae 13578 struct bgp *bgp;
13579 struct bgp_table *table;
13580
13581 /* BGP structure lookup. */
13582 if (view_name) {
13583 bgp = bgp_lookup_by_name(view_name);
13584 if (bgp == NULL) {
13585 vty_out(vty, "%% Can't find BGP instance %s\n",
13586 view_name);
13587 return CMD_WARNING;
13588 }
13589 } else {
13590 bgp = bgp_get_default();
13591 if (bgp == NULL) {
13592 vty_out(vty, "%% No BGP process is configured\n");
13593 return CMD_WARNING;
13594 }
718e3744 13595 }
718e3744 13596
d62a17ae 13597 /* Check IP address argument. */
13598 ret = str2prefix(ip_str, &match);
13599 if (!ret) {
13600 vty_out(vty, "%% address is malformed\n");
13601 return CMD_WARNING;
13602 }
718e3744 13603
d62a17ae 13604 match.family = afi2family(afi);
13605
13606 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13607 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
13608 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
13609 dest = bgp_route_next(dest)) {
13610 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13611
9bcb3eef 13612 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 13613 continue;
9bcb3eef 13614 table = bgp_dest_get_bgp_table_info(dest);
67009e22 13615 if (!table)
ea47320b
DL
13616 continue;
13617 if ((rm = bgp_node_match(table, &match)) == NULL)
13618 continue;
d62a17ae 13619
9bcb3eef 13620 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 13621
ea47320b 13622 if (!prefix_check
b54892e0 13623 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 13624 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
13625 while (pi) {
13626 if (pi->extra && pi->extra->damp_info) {
13627 pi_temp = pi->next;
ea47320b 13628 bgp_damp_info_free(
40381db7 13629 pi->extra->damp_info,
a935f597 13630 1, afi, safi);
40381db7 13631 pi = pi_temp;
ea47320b 13632 } else
40381db7 13633 pi = pi->next;
d62a17ae 13634 }
ea47320b
DL
13635 }
13636
9bcb3eef 13637 bgp_dest_unlock_node(rm);
d62a17ae 13638 }
13639 } else {
9bcb3eef 13640 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 13641 != NULL) {
9bcb3eef 13642 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13643
d62a17ae 13644 if (!prefix_check
9bcb3eef
DS
13645 || dest_p->prefixlen == match.prefixlen) {
13646 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
13647 while (pi) {
13648 if (pi->extra && pi->extra->damp_info) {
13649 pi_temp = pi->next;
d62a17ae 13650 bgp_damp_info_free(
40381db7 13651 pi->extra->damp_info,
a935f597 13652 1, afi, safi);
40381db7 13653 pi = pi_temp;
d62a17ae 13654 } else
40381db7 13655 pi = pi->next;
d62a17ae 13656 }
13657 }
13658
9bcb3eef 13659 bgp_dest_unlock_node(dest);
d62a17ae 13660 }
13661 }
718e3744 13662
d62a17ae 13663 return CMD_SUCCESS;
718e3744 13664}
13665
13666DEFUN (clear_ip_bgp_dampening,
13667 clear_ip_bgp_dampening_cmd,
13668 "clear ip bgp dampening",
13669 CLEAR_STR
13670 IP_STR
13671 BGP_STR
13672 "Clear route flap dampening information\n")
13673{
a935f597 13674 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 13675 return CMD_SUCCESS;
718e3744 13676}
13677
13678DEFUN (clear_ip_bgp_dampening_prefix,
13679 clear_ip_bgp_dampening_prefix_cmd,
13680 "clear ip bgp dampening A.B.C.D/M",
13681 CLEAR_STR
13682 IP_STR
13683 BGP_STR
13684 "Clear route flap dampening information\n"
0c7b1b01 13685 "IPv4 prefix\n")
718e3744 13686{
d62a17ae 13687 int idx_ipv4_prefixlen = 4;
13688 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
13689 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 13690}
13691
13692DEFUN (clear_ip_bgp_dampening_address,
13693 clear_ip_bgp_dampening_address_cmd,
13694 "clear ip bgp dampening A.B.C.D",
13695 CLEAR_STR
13696 IP_STR
13697 BGP_STR
13698 "Clear route flap dampening information\n"
13699 "Network to clear damping information\n")
13700{
d62a17ae 13701 int idx_ipv4 = 4;
13702 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
13703 SAFI_UNICAST, NULL, 0);
718e3744 13704}
13705
13706DEFUN (clear_ip_bgp_dampening_address_mask,
13707 clear_ip_bgp_dampening_address_mask_cmd,
13708 "clear ip bgp dampening A.B.C.D A.B.C.D",
13709 CLEAR_STR
13710 IP_STR
13711 BGP_STR
13712 "Clear route flap dampening information\n"
13713 "Network to clear damping information\n"
13714 "Network mask\n")
13715{
d62a17ae 13716 int idx_ipv4 = 4;
13717 int idx_ipv4_2 = 5;
13718 int ret;
13719 char prefix_str[BUFSIZ];
718e3744 13720
d62a17ae 13721 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
13722 prefix_str);
13723 if (!ret) {
13724 vty_out(vty, "%% Inconsistent address and mask\n");
13725 return CMD_WARNING;
13726 }
718e3744 13727
d62a17ae 13728 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
13729 NULL, 0);
718e3744 13730}
6b0655a2 13731
e3b78da8 13732static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
13733{
13734 struct vty *vty = arg;
e3b78da8 13735 struct peer *peer = bucket->data;
825d9834
DS
13736 char buf[SU_ADDRSTRLEN];
13737
13738 vty_out(vty, "\tPeer: %s %s\n", peer->host,
13739 sockunion2str(&peer->su, buf, sizeof(buf)));
13740}
13741
2a0e69ae
DS
13742DEFUN (show_bgp_listeners,
13743 show_bgp_listeners_cmd,
13744 "show bgp listeners",
13745 SHOW_STR
13746 BGP_STR
13747 "Display Listen Sockets and who created them\n")
13748{
13749 bgp_dump_listener_info(vty);
13750
13751 return CMD_SUCCESS;
13752}
13753
825d9834
DS
13754DEFUN (show_bgp_peerhash,
13755 show_bgp_peerhash_cmd,
13756 "show bgp peerhash",
13757 SHOW_STR
13758 BGP_STR
13759 "Display information about the BGP peerhash\n")
13760{
13761 struct list *instances = bm->bgp;
13762 struct listnode *node;
13763 struct bgp *bgp;
13764
13765 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
13766 vty_out(vty, "BGP: %s\n", bgp->name);
13767 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
13768 vty);
13769 }
13770
13771 return CMD_SUCCESS;
13772}
13773
587ff0fd 13774/* also used for encap safi */
2b791107
DL
13775static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
13776 afi_t afi, safi_t safi)
d62a17ae 13777{
9bcb3eef
DS
13778 struct bgp_dest *pdest;
13779 struct bgp_dest *dest;
d62a17ae 13780 struct bgp_table *table;
b54892e0
DS
13781 const struct prefix *p;
13782 const struct prefix_rd *prd;
d62a17ae 13783 struct bgp_static *bgp_static;
13784 mpls_label_t label;
13785 char buf[SU_ADDRSTRLEN];
13786 char rdbuf[RD_ADDRSTRLEN];
13787
13788 /* Network configuration. */
9bcb3eef
DS
13789 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13790 pdest = bgp_route_next(pdest)) {
13791 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13792 if (!table)
ea47320b 13793 continue;
d62a17ae 13794
9bcb3eef
DS
13795 for (dest = bgp_table_top(table); dest;
13796 dest = bgp_route_next(dest)) {
13797 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13798 if (bgp_static == NULL)
ea47320b 13799 continue;
d62a17ae 13800
9bcb3eef
DS
13801 p = bgp_dest_get_prefix(dest);
13802 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13803 pdest);
d62a17ae 13804
ea47320b 13805 /* "network" configuration display. */
06b9f471 13806 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
13807 label = decode_label(&bgp_static->label);
13808
13809 vty_out(vty, " network %s/%d rd %s",
13810 inet_ntop(p->family, &p->u.prefix, buf,
13811 SU_ADDRSTRLEN),
13812 p->prefixlen, rdbuf);
13813 if (safi == SAFI_MPLS_VPN)
13814 vty_out(vty, " label %u", label);
13815
13816 if (bgp_static->rmap.name)
13817 vty_out(vty, " route-map %s",
13818 bgp_static->rmap.name);
e2a86ad9
DS
13819
13820 if (bgp_static->backdoor)
13821 vty_out(vty, " backdoor");
13822
ea47320b
DL
13823 vty_out(vty, "\n");
13824 }
13825 }
d62a17ae 13826}
13827
2b791107
DL
13828static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
13829 afi_t afi, safi_t safi)
d62a17ae 13830{
9bcb3eef
DS
13831 struct bgp_dest *pdest;
13832 struct bgp_dest *dest;
d62a17ae 13833 struct bgp_table *table;
b54892e0
DS
13834 const struct prefix *p;
13835 const struct prefix_rd *prd;
d62a17ae 13836 struct bgp_static *bgp_static;
ff44f570 13837 char buf[PREFIX_STRLEN * 2];
d62a17ae 13838 char buf2[SU_ADDRSTRLEN];
13839 char rdbuf[RD_ADDRSTRLEN];
0a50c248 13840 char esi_buf[ESI_BYTES];
d62a17ae 13841
13842 /* Network configuration. */
9bcb3eef
DS
13843 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13844 pdest = bgp_route_next(pdest)) {
13845 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13846 if (!table)
ea47320b 13847 continue;
d62a17ae 13848
9bcb3eef
DS
13849 for (dest = bgp_table_top(table); dest;
13850 dest = bgp_route_next(dest)) {
13851 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13852 if (bgp_static == NULL)
ea47320b 13853 continue;
d62a17ae 13854
ea47320b 13855 char *macrouter = NULL;
d62a17ae 13856
ea47320b
DL
13857 if (bgp_static->router_mac)
13858 macrouter = prefix_mac2str(
13859 bgp_static->router_mac, NULL, 0);
13860 if (bgp_static->eth_s_id)
0a50c248
AK
13861 esi_to_str(bgp_static->eth_s_id,
13862 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
13863 p = bgp_dest_get_prefix(dest);
13864 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 13865
ea47320b 13866 /* "network" configuration display. */
06b9f471 13867 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
13868 if (p->u.prefix_evpn.route_type == 5) {
13869 char local_buf[PREFIX_STRLEN];
3714a385 13870 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
13871 struct prefix_evpn *)p)
13872 ? AF_INET
13873 : AF_INET6;
3714a385 13874 inet_ntop(family,
13875 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 13876 local_buf, PREFIX_STRLEN);
772270f3
QY
13877 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
13878 p->u.prefix_evpn.prefix_addr
13879 .ip_prefix_length);
197cb530
PG
13880 } else {
13881 prefix2str(p, buf, sizeof(buf));
13882 }
ea47320b 13883
a4d82a8a
PZ
13884 if (bgp_static->gatewayIp.family == AF_INET
13885 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
13886 inet_ntop(bgp_static->gatewayIp.family,
13887 &bgp_static->gatewayIp.u.prefix, buf2,
13888 sizeof(buf2));
ea47320b 13889 vty_out(vty,
7bcc8dac 13890 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 13891 buf, rdbuf,
13892 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 13893 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
13894 macrouter);
13895
0a22ddfb 13896 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
13897 }
13898 }
3da6fcd5
PG
13899}
13900
718e3744 13901/* Configuration of static route announcement and aggregate
13902 information. */
2b791107
DL
13903void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
13904 safi_t safi)
d62a17ae 13905{
9bcb3eef 13906 struct bgp_dest *dest;
b54892e0 13907 const struct prefix *p;
d62a17ae 13908 struct bgp_static *bgp_static;
13909 struct bgp_aggregate *bgp_aggregate;
13910 char buf[SU_ADDRSTRLEN];
13911
2b791107
DL
13912 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
13913 bgp_config_write_network_vpn(vty, bgp, afi, safi);
13914 return;
13915 }
d62a17ae 13916
2b791107
DL
13917 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
13918 bgp_config_write_network_evpn(vty, bgp, afi, safi);
13919 return;
13920 }
d62a17ae 13921
13922 /* Network configuration. */
9bcb3eef
DS
13923 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
13924 dest = bgp_route_next(dest)) {
13925 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13926 if (bgp_static == NULL)
ea47320b 13927 continue;
d62a17ae 13928
9bcb3eef 13929 p = bgp_dest_get_prefix(dest);
d62a17ae 13930
d8a9922d
DS
13931 vty_out(vty, " network %s/%d",
13932 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13933 p->prefixlen);
d62a17ae 13934
ea47320b
DL
13935 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
13936 vty_out(vty, " label-index %u",
13937 bgp_static->label_index);
d62a17ae 13938
ea47320b
DL
13939 if (bgp_static->rmap.name)
13940 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
13941
13942 if (bgp_static->backdoor)
13943 vty_out(vty, " backdoor");
718e3744 13944
ea47320b
DL
13945 vty_out(vty, "\n");
13946 }
13947
d62a17ae 13948 /* Aggregate-address configuration. */
9bcb3eef
DS
13949 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
13950 dest = bgp_route_next(dest)) {
13951 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 13952 if (bgp_aggregate == NULL)
ea47320b 13953 continue;
d62a17ae 13954
9bcb3eef 13955 p = bgp_dest_get_prefix(dest);
d62a17ae 13956
d8a9922d
DS
13957 vty_out(vty, " aggregate-address %s/%d",
13958 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13959 p->prefixlen);
d62a17ae 13960
ea47320b
DL
13961 if (bgp_aggregate->as_set)
13962 vty_out(vty, " as-set");
d62a17ae 13963
ea47320b
DL
13964 if (bgp_aggregate->summary_only)
13965 vty_out(vty, " summary-only");
718e3744 13966
20894f50
DA
13967 if (bgp_aggregate->rmap.name)
13968 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
13969
229757f1
DA
13970 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
13971 vty_out(vty, " origin %s",
13972 bgp_origin2str(bgp_aggregate->origin));
13973
6aabb15d
RZ
13974 if (bgp_aggregate->match_med)
13975 vty_out(vty, " matching-MED-only");
13976
ea47320b
DL
13977 vty_out(vty, "\n");
13978 }
d62a17ae 13979}
734b349e 13980
2b791107 13981void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13982 safi_t safi)
d62a17ae 13983{
9bcb3eef 13984 struct bgp_dest *dest;
d62a17ae 13985 struct bgp_distance *bdistance;
13986
13987 /* Distance configuration. */
13988 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13989 && bgp->distance_local[afi][safi]
13990 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13991 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13992 || bgp->distance_local[afi][safi]
13993 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13994 vty_out(vty, " distance bgp %d %d %d\n",
13995 bgp->distance_ebgp[afi][safi],
13996 bgp->distance_ibgp[afi][safi],
13997 bgp->distance_local[afi][safi]);
13998 }
734b349e 13999
9bcb3eef
DS
14000 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14001 dest = bgp_route_next(dest)) {
14002 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14003 if (bdistance != NULL)
56ca3b5b 14004 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14005 bdistance->distance, dest,
d62a17ae 14006 bdistance->access_list ? bdistance->access_list
14007 : "");
ca2e160d 14008 }
718e3744 14009}
14010
14011/* Allocate routing table structure and install commands. */
d62a17ae 14012void bgp_route_init(void)
14013{
14014 afi_t afi;
14015 safi_t safi;
14016
14017 /* Init BGP distance table. */
05c7a1cc 14018 FOREACH_AFI_SAFI (afi, safi)
960035b2 14019 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14020
14021 /* IPv4 BGP commands. */
14022 install_element(BGP_NODE, &bgp_table_map_cmd);
14023 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14024 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14025
554b3b10 14026 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14027
14028 /* IPv4 unicast configuration. */
14029 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14030 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14031 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14032
554b3b10 14033 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14034
14035 /* IPv4 multicast configuration. */
14036 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14037 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14038 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14039 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14040
14041 /* IPv4 labeled-unicast configuration. */
fb985e0c 14042 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14043 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14044
d62a17ae 14045 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14046 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14047 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14048 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14049 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14050 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14051 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14052 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14053
14054 install_element(VIEW_NODE,
14055 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14056 install_element(VIEW_NODE,
14057 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14058 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14059 install_element(VIEW_NODE,
14060 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14061#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14062 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14063#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14064 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14065 install_element(VIEW_NODE,
44c69747 14066 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14067
d62a17ae 14068 /* BGP dampening clear commands */
14069 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14070 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14071
d62a17ae 14072 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14073 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14074
14075 /* prefix count */
14076 install_element(ENABLE_NODE,
14077 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14078#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14079 install_element(ENABLE_NODE,
14080 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14081#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14082
d62a17ae 14083 /* New config IPv6 BGP commands. */
14084 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14085 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14086 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14087
554b3b10 14088 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14089
14090 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14091
fb985e0c
DA
14092 /* IPv6 labeled unicast address family. */
14093 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14094 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14095
d62a17ae 14096 install_element(BGP_NODE, &bgp_distance_cmd);
14097 install_element(BGP_NODE, &no_bgp_distance_cmd);
14098 install_element(BGP_NODE, &bgp_distance_source_cmd);
14099 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
14100 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
14101 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
14102 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14103 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14104 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
14105 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
14106 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
14107 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
14108 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14109 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14110 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
14111 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
14112 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
14113 install_element(BGP_IPV4M_NODE,
14114 &no_bgp_distance_source_access_list_cmd);
14115 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14116 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
14117 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
14118 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
14119 install_element(BGP_IPV6_NODE,
14120 &ipv6_bgp_distance_source_access_list_cmd);
14121 install_element(BGP_IPV6_NODE,
14122 &no_ipv6_bgp_distance_source_access_list_cmd);
14123 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14124 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
14125 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
14126 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
14127 install_element(BGP_IPV6M_NODE,
14128 &ipv6_bgp_distance_source_access_list_cmd);
14129 install_element(BGP_IPV6M_NODE,
14130 &no_ipv6_bgp_distance_source_access_list_cmd);
14131
ef5f4b23 14132 /* BGP dampening */
d62a17ae 14133 install_element(BGP_NODE, &bgp_damp_set_cmd);
14134 install_element(BGP_NODE, &bgp_damp_unset_cmd);
14135 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
14136 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
d62a17ae 14137 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
14138 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
ef5f4b23
DA
14139 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
14140 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
14141 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
14142 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
14143 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
14144 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
14145 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
14146 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 14147
14148 /* Large Communities */
14149 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14150 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14151
14152 /* show bgp ipv4 flowspec detailed */
14153 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14154
2a0e69ae 14155 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14156 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14157}
14158
14159void bgp_route_finish(void)
14160{
14161 afi_t afi;
14162 safi_t safi;
14163
05c7a1cc
QY
14164 FOREACH_AFI_SAFI (afi, safi) {
14165 bgp_table_unlock(bgp_distance_table[afi][safi]);
14166 bgp_distance_table[afi][safi] = NULL;
14167 }
228da428 14168}