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