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