]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #7036 from ton31337/fix/do_not_allow_setting_maximum-prefix-out_global
[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
1e9be514
QY
3608 /* Update Overlay Index */
3609 if (afi == AFI_L2VPN) {
3610 overlay_index_update(&new_attr,
3611 evpn == NULL ? NULL : &evpn->gw_ip);
3612 }
3613
d62a17ae 3614 attr_new = bgp_attr_intern(&new_attr);
3615
9cbd06e0
DA
3616 /* If maximum prefix count is configured and current prefix
3617 * count exeed it.
3618 */
3619 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3620 return -1;
3621
d62a17ae 3622 /* If the update is implicit withdraw. */
40381db7
DS
3623 if (pi) {
3624 pi->uptime = bgp_clock();
3625 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3626
9bcb3eef 3627 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3628
d62a17ae 3629 /* Same attribute comes in. */
40381db7
DS
3630 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
3631 && attrhash_cmp(pi->attr, attr_new)
d62a17ae 3632 && (!has_valid_label
40381db7 3633 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3634 num_labels * sizeof(mpls_label_t))
d62a17ae 3635 == 0)
3636 && (overlay_index_equal(
0a50c248 3637 afi, pi,
d62a17ae 3638 evpn == NULL ? NULL : &evpn->gw_ip))) {
3639 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3640 BGP_CONFIG_DAMPENING)
3641 && peer->sort == BGP_PEER_EBGP
40381db7 3642 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3643 if (bgp_debug_update(peer, p, NULL, 1)) {
3644 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3645 afi, safi, prd, p, label,
3646 num_labels, addpath_id ? 1 : 0,
3647 addpath_id, pfx_buf,
3648 sizeof(pfx_buf));
d62a17ae 3649 zlog_debug("%s rcvd %s", peer->host,
3650 pfx_buf);
3651 }
3652
9bcb3eef 3653 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3654 != BGP_DAMP_SUPPRESSED) {
40381db7 3655 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3656 safi);
9bcb3eef 3657 bgp_process(bgp, dest, afi, safi);
d62a17ae 3658 }
3659 } else /* Duplicate - odd */
3660 {
3661 if (bgp_debug_update(peer, p, NULL, 1)) {
3662 if (!peer->rcvd_attr_printed) {
3663 zlog_debug(
3664 "%s rcvd UPDATE w/ attr: %s",
3665 peer->host,
3666 peer->rcvd_attr_str);
3667 peer->rcvd_attr_printed = 1;
3668 }
3669
3670 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3671 afi, safi, prd, p, label,
3672 num_labels, addpath_id ? 1 : 0,
3673 addpath_id, pfx_buf,
3674 sizeof(pfx_buf));
d62a17ae 3675 zlog_debug(
3676 "%s rcvd %s...duplicate ignored",
3677 peer->host, pfx_buf);
3678 }
3679
3680 /* graceful restart STALE flag unset. */
40381db7 3681 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3682 bgp_path_info_unset_flag(
9bcb3eef
DS
3683 dest, pi, BGP_PATH_STALE);
3684 bgp_dest_set_defer_flag(dest, false);
3685 bgp_process(bgp, dest, afi, safi);
d62a17ae 3686 }
3687 }
3688
9bcb3eef 3689 bgp_dest_unlock_node(dest);
d62a17ae 3690 bgp_attr_unintern(&attr_new);
3691
3692 return 0;
3693 }
718e3744 3694
d62a17ae 3695 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3696 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3697 if (bgp_debug_update(peer, p, NULL, 1)) {
3698 bgp_debug_rdpfxpath2str(
a4d82a8a 3699 afi, safi, prd, p, label, num_labels,
d62a17ae 3700 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3701 sizeof(pfx_buf));
3702 zlog_debug(
3703 "%s rcvd %s, flapped quicker than processing",
3704 peer->host, pfx_buf);
3705 }
3706
9bcb3eef 3707 bgp_path_info_restore(dest, pi);
d62a17ae 3708 }
718e3744 3709
d62a17ae 3710 /* Received Logging. */
3711 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3712 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3713 num_labels, addpath_id ? 1 : 0,
3714 addpath_id, pfx_buf,
3715 sizeof(pfx_buf));
d62a17ae 3716 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3717 }
718e3744 3718
d62a17ae 3719 /* graceful restart STALE flag unset. */
f009ff26 3720 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3721 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3722 bgp_dest_set_defer_flag(dest, false);
f009ff26 3723 }
d62a17ae 3724
3725 /* The attribute is changed. */
9bcb3eef 3726 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3727
3728 /* implicit withdraw, decrement aggregate and pcount here.
3729 * only if update is accepted, they'll increment below.
3730 */
40381db7 3731 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3732
3733 /* Update bgp route dampening information. */
3734 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3735 && peer->sort == BGP_PEER_EBGP) {
3736 /* This is implicit withdraw so we should update
3737 dampening
3738 information. */
40381db7 3739 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3740 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3741 }
49e5a4a0 3742#ifdef ENABLE_BGP_VNC
d62a17ae 3743 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3744 struct bgp_dest *pdest = NULL;
d62a17ae 3745 struct bgp_table *table = NULL;
3746
9bcb3eef
DS
3747 pdest = bgp_node_get(bgp->rib[afi][safi],
3748 (struct prefix *)prd);
3749 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3750 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3751
3752 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3753 bgp, prd, table, p, pi);
d62a17ae 3754 }
9bcb3eef 3755 bgp_dest_unlock_node(pdest);
d62a17ae 3756 }
3757 if ((afi == AFI_IP || afi == AFI_IP6)
3758 && (safi == SAFI_UNICAST)) {
40381db7 3759 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3760 /*
3761 * Implicit withdraw case.
3762 */
3763 ++vnc_implicit_withdraw;
40381db7
DS
3764 vnc_import_bgp_del_route(bgp, p, pi);
3765 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3766 }
3767 }
65efcfce 3768#endif
128ea8ab 3769
d62a17ae 3770 /* Special handling for EVPN update of an existing route. If the
3771 * extended community attribute has changed, we need to
3772 * un-import
3773 * the route using its existing extended community. It will be
3774 * subsequently processed for import with the new extended
3775 * community.
3776 */
6f8c9c11
PR
3777 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3778 && !same_attr) {
40381db7 3779 if ((pi->attr->flag
d62a17ae 3780 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3781 && (attr_new->flag
3782 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3783 int cmp;
3784
40381db7 3785 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3786 attr_new->ecommunity);
3787 if (!cmp) {
3788 if (bgp_debug_update(peer, p, NULL, 1))
3789 zlog_debug(
3790 "Change in EXT-COMM, existing %s new %s",
3791 ecommunity_str(
40381db7 3792 pi->attr->ecommunity),
d62a17ae 3793 ecommunity_str(
3794 attr_new->ecommunity));
6f8c9c11
PR
3795 if (safi == SAFI_EVPN)
3796 bgp_evpn_unimport_route(
3797 bgp, afi, safi, p, pi);
3798 else /* SAFI_MPLS_VPN */
3799 vpn_leak_to_vrf_withdraw(bgp,
3800 pi);
d62a17ae 3801 }
3802 }
3803 }
718e3744 3804
d62a17ae 3805 /* Update to new attribute. */
40381db7
DS
3806 bgp_attr_unintern(&pi->attr);
3807 pi->attr = attr_new;
d62a17ae 3808
3809 /* Update MPLS label */
3810 if (has_valid_label) {
40381db7 3811 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3812 if (extra->label != label) {
3813 memcpy(&extra->label, label,
dbd587da 3814 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3815 extra->num_labels = num_labels;
3816 }
b57ba6d2
MK
3817 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
3818 bgp_set_valid_label(&extra->label[0]);
fc9a856f 3819 }
718e3744 3820
e496b420
HS
3821 /* Update SRv6 SID */
3822 if (attr->srv6_l3vpn) {
3823 extra = bgp_path_info_extra_get(pi);
3824 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
3825 sid_copy(&extra->sid[0],
3826 &attr->srv6_l3vpn->sid);
3827 extra->num_sids = 1;
3828 }
3829 } else if (attr->srv6_vpn) {
3830 extra = bgp_path_info_extra_get(pi);
3831 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
3832 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
3833 extra->num_sids = 1;
3834 }
3835 }
3836
49e5a4a0 3837#ifdef ENABLE_BGP_VNC
d62a17ae 3838 if ((afi == AFI_IP || afi == AFI_IP6)
3839 && (safi == SAFI_UNICAST)) {
3840 if (vnc_implicit_withdraw) {
3841 /*
3842 * Add back the route with its new attributes
3843 * (e.g., nexthop).
3844 * The route is still selected, until the route
3845 * selection
3846 * queued by bgp_process actually runs. We have
3847 * to make this
3848 * update to the VNC side immediately to avoid
3849 * racing against
3850 * configuration changes (e.g., route-map
3851 * changes) which
3852 * trigger re-importation of the entire RIB.
3853 */
40381db7
DS
3854 vnc_import_bgp_add_route(bgp, p, pi);
3855 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 3856 }
3857 }
65efcfce
LB
3858#endif
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,
96f3485c 9760 safi_t safi, uint8_t show_flags);
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,
96f3485c
MK
9765 void *output_arg, char *rd, int is_last,
9766 unsigned long *output_cum, unsigned long *total_cum,
9767 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 9768{
40381db7 9769 struct bgp_path_info *pi;
9bcb3eef 9770 struct bgp_dest *dest;
d62a17ae 9771 int header = 1;
9772 int display;
1ae44dfc
LB
9773 unsigned long output_count = 0;
9774 unsigned long total_count = 0;
d62a17ae 9775 struct prefix *p;
d62a17ae 9776 json_object *json_paths = NULL;
9777 int first = 1;
96f3485c
MK
9778 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
9779 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
9780 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 9781
1ae44dfc
LB
9782 if (output_cum && *output_cum != 0)
9783 header = 0;
9784
9386b588 9785 if (use_json && !*json_header_depth) {
96f3485c
MK
9786 if (all)
9787 *json_header_depth = 1;
9788 else {
9789 vty_out(vty, "{\n");
9790 *json_header_depth = 2;
9791 }
9792
d62a17ae 9793 vty_out(vty,
96f3485c 9794 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64",\n \"routerId\": \"%s\",\n \"defaultLocPrf\": %u,\n"
01eced22 9795 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 9796 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b
DS
9797 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
9798 ? VRF_DEFAULT_NAME
9799 : bgp->name,
01eced22
AD
9800 table->version, inet_ntoa(bgp->router_id),
9801 bgp->default_local_pref, bgp->as);
9386b588 9802 if (rd) {
445c2480 9803 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
9804 ++*json_header_depth;
9805 }
d62a17ae 9806 }
718e3744 9807
445c2480
DS
9808 if (use_json && rd) {
9809 vty_out(vty, " \"%s\" : { ", rd);
9810 }
9811
d62a17ae 9812 /* Start processing of routes. */
9bcb3eef
DS
9813 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
9814 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 9815
9bcb3eef 9816 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 9817 if (pi == NULL)
98ce9a06 9818 continue;
d62a17ae 9819
98ce9a06 9820 display = 0;
98ce9a06
DS
9821 if (use_json)
9822 json_paths = json_object_new_array();
9823 else
9824 json_paths = NULL;
d62a17ae 9825
6f94b685 9826 for (; pi; pi = pi->next) {
98ce9a06
DS
9827 total_count++;
9828 if (type == bgp_show_type_flap_statistics
9829 || type == bgp_show_type_flap_neighbor
9830 || type == bgp_show_type_dampend_paths
9831 || type == bgp_show_type_damp_neighbor) {
40381db7 9832 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
9833 continue;
9834 }
9835 if (type == bgp_show_type_regexp) {
9836 regex_t *regex = output_arg;
d62a17ae 9837
40381db7 9838 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
9839 == REG_NOMATCH)
9840 continue;
9841 }
9842 if (type == bgp_show_type_prefix_list) {
9843 struct prefix_list *plist = output_arg;
d62a17ae 9844
9bcb3eef 9845 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
9846 != PREFIX_PERMIT)
9847 continue;
9848 }
9849 if (type == bgp_show_type_filter_list) {
9850 struct as_list *as_list = output_arg;
d62a17ae 9851
40381db7 9852 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
9853 != AS_FILTER_PERMIT)
9854 continue;
9855 }
9856 if (type == bgp_show_type_route_map) {
9857 struct route_map *rmap = output_arg;
9b6d8fcf 9858 struct bgp_path_info path;
98ce9a06 9859 struct attr dummy_attr;
b68885f9 9860 route_map_result_t ret;
d62a17ae 9861
6f4f49b2 9862 dummy_attr = *pi->attr;
d62a17ae 9863
40381db7 9864 path.peer = pi->peer;
9b6d8fcf 9865 path.attr = &dummy_attr;
d62a17ae 9866
9bcb3eef 9867 ret = route_map_apply(rmap, dest_p, RMAP_BGP,
9b6d8fcf 9868 &path);
98ce9a06
DS
9869 if (ret == RMAP_DENYMATCH)
9870 continue;
9871 }
9872 if (type == bgp_show_type_neighbor
9873 || type == bgp_show_type_flap_neighbor
9874 || type == bgp_show_type_damp_neighbor) {
9875 union sockunion *su = output_arg;
9876
40381db7
DS
9877 if (pi->peer == NULL
9878 || pi->peer->su_remote == NULL
9879 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
9880 continue;
9881 }
9882 if (type == bgp_show_type_cidr_only) {
d7c0a89a 9883 uint32_t destination;
d62a17ae 9884
9bcb3eef 9885 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 9886 if (IN_CLASSC(destination)
9bcb3eef 9887 && dest_p->prefixlen == 24)
98ce9a06
DS
9888 continue;
9889 if (IN_CLASSB(destination)
9bcb3eef 9890 && dest_p->prefixlen == 16)
98ce9a06
DS
9891 continue;
9892 if (IN_CLASSA(destination)
9bcb3eef 9893 && dest_p->prefixlen == 8)
98ce9a06
DS
9894 continue;
9895 }
9896 if (type == bgp_show_type_prefix_longer) {
f7813c7c 9897 p = output_arg;
9bcb3eef 9898 if (!prefix_match(p, dest_p))
98ce9a06
DS
9899 continue;
9900 }
9901 if (type == bgp_show_type_community_all) {
40381db7 9902 if (!pi->attr->community)
98ce9a06
DS
9903 continue;
9904 }
9905 if (type == bgp_show_type_community) {
9906 struct community *com = output_arg;
d62a17ae 9907
40381db7
DS
9908 if (!pi->attr->community
9909 || !community_match(pi->attr->community,
98ce9a06
DS
9910 com))
9911 continue;
9912 }
9913 if (type == bgp_show_type_community_exact) {
9914 struct community *com = output_arg;
d62a17ae 9915
40381db7
DS
9916 if (!pi->attr->community
9917 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
9918 continue;
9919 }
9920 if (type == bgp_show_type_community_list) {
9921 struct community_list *list = output_arg;
d62a17ae 9922
40381db7 9923 if (!community_list_match(pi->attr->community,
a4d82a8a 9924 list))
98ce9a06
DS
9925 continue;
9926 }
a4d82a8a 9927 if (type == bgp_show_type_community_list_exact) {
98ce9a06 9928 struct community_list *list = output_arg;
d62a17ae 9929
98ce9a06 9930 if (!community_list_exact_match(
40381db7 9931 pi->attr->community, list))
98ce9a06
DS
9932 continue;
9933 }
9934 if (type == bgp_show_type_lcommunity) {
9935 struct lcommunity *lcom = output_arg;
d62a17ae 9936
40381db7
DS
9937 if (!pi->attr->lcommunity
9938 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
9939 lcom))
9940 continue;
9941 }
36a206db 9942
9943 if (type == bgp_show_type_lcommunity_exact) {
9944 struct lcommunity *lcom = output_arg;
9945
9946 if (!pi->attr->lcommunity
9947 || !lcommunity_cmp(pi->attr->lcommunity,
9948 lcom))
9949 continue;
9950 }
98ce9a06
DS
9951 if (type == bgp_show_type_lcommunity_list) {
9952 struct community_list *list = output_arg;
d62a17ae 9953
40381db7 9954 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 9955 list))
98ce9a06
DS
9956 continue;
9957 }
36a206db 9958 if (type
9959 == bgp_show_type_lcommunity_list_exact) {
9960 struct community_list *list = output_arg;
9961
9962 if (!lcommunity_list_exact_match(
9963 pi->attr->lcommunity, list))
9964 continue;
9965 }
98ce9a06 9966 if (type == bgp_show_type_lcommunity_all) {
40381db7 9967 if (!pi->attr->lcommunity)
98ce9a06
DS
9968 continue;
9969 }
9970 if (type == bgp_show_type_dampend_paths
9971 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
9972 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
9973 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
9974 continue;
9975 }
9976
9977 if (!use_json && header) {
6cde4b45 9978 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
98ce9a06
DS
9979 table->version,
9980 inet_ntoa(bgp->router_id));
9df8b37c
PZ
9981 if (bgp->vrf_id == VRF_UNKNOWN)
9982 vty_out(vty, "%s", VRFID_NONE_STR);
9983 else
9984 vty_out(vty, "%u", bgp->vrf_id);
9985 vty_out(vty, "\n");
01eced22
AD
9986 vty_out(vty, "Default local pref %u, ",
9987 bgp->default_local_pref);
9988 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 9989 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 9990 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 9991 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 9992 if (type == bgp_show_type_dampend_paths
9993 || type == bgp_show_type_damp_neighbor)
98ce9a06 9994 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
9995 else if (type == bgp_show_type_flap_statistics
9996 || type == bgp_show_type_flap_neighbor)
98ce9a06 9997 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 9998 else
ae248832
MK
9999 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10000 : BGP_SHOW_HEADER));
98ce9a06 10001 header = 0;
d62a17ae 10002 }
98ce9a06
DS
10003 if (rd != NULL && !display && !output_count) {
10004 if (!use_json)
10005 vty_out(vty,
10006 "Route Distinguisher: %s\n",
10007 rd);
d62a17ae 10008 }
98ce9a06
DS
10009 if (type == bgp_show_type_dampend_paths
10010 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10011 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10012 AFI_IP, safi, use_json,
10013 json_paths);
98ce9a06
DS
10014 else if (type == bgp_show_type_flap_statistics
10015 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10016 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10017 AFI_IP, safi, use_json,
10018 json_paths);
98ce9a06 10019 else
9bcb3eef 10020 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10021 json_paths, wide);
98ce9a06 10022 display++;
d62a17ae 10023 }
10024
98ce9a06
DS
10025 if (display) {
10026 output_count++;
10027 if (!use_json)
10028 continue;
10029
625d2931 10030 /* encode prefix */
9bcb3eef 10031 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10032 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10033
1840384b 10034
b54892e0
DS
10035 bgp_fs_nlri_get_string(
10036 (unsigned char *)
9bcb3eef
DS
10037 dest_p->u.prefix_flowspec.ptr,
10038 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10039 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10040 family2afi(dest_p->u
10041 .prefix_flowspec.family));
625d2931 10042 if (first)
b54892e0 10043 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10044 dest_p->u.prefix_flowspec
b54892e0 10045 .prefixlen);
625d2931 10046 else
b54892e0 10047 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10048 dest_p->u.prefix_flowspec
b54892e0 10049 .prefixlen);
625d2931 10050 } else {
625d2931 10051 if (first)
1b78780b 10052 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10053 else
1b78780b 10054 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10055 }
98ce9a06 10056 vty_out(vty, "%s",
f4ec52f7
DA
10057 json_object_to_json_string_ext(
10058 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10059 json_object_free(json_paths);
449feb8e 10060 json_paths = NULL;
98ce9a06 10061 first = 0;
1f83ed02
DS
10062 } else
10063 json_object_free(json_paths);
98ce9a06
DS
10064 }
10065
1ae44dfc
LB
10066 if (output_cum) {
10067 output_count += *output_cum;
10068 *output_cum = output_count;
10069 }
10070 if (total_cum) {
10071 total_count += *total_cum;
10072 *total_cum = total_count;
10073 }
d62a17ae 10074 if (use_json) {
9386b588 10075 if (rd) {
a4d82a8a 10076 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10077 }
10078 if (is_last) {
a4d82a8a
PZ
10079 unsigned long i;
10080 for (i = 0; i < *json_header_depth; ++i)
10081 vty_out(vty, " } ");
96f3485c
MK
10082 if (!all)
10083 vty_out(vty, "\n");
9386b588 10084 }
d62a17ae 10085 } else {
1ae44dfc
LB
10086 if (is_last) {
10087 /* No route is displayed */
10088 if (output_count == 0) {
10089 if (type == bgp_show_type_normal)
10090 vty_out(vty,
10091 "No BGP prefixes displayed, %ld exist\n",
10092 total_count);
10093 } else
d62a17ae 10094 vty_out(vty,
1ae44dfc
LB
10095 "\nDisplayed %ld routes and %ld total paths\n",
10096 output_count, total_count);
10097 }
d62a17ae 10098 }
718e3744 10099
d62a17ae 10100 return CMD_SUCCESS;
718e3744 10101}
10102
1ae44dfc
LB
10103int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10104 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10105 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10106{
9bcb3eef 10107 struct bgp_dest *dest, *next;
1ae44dfc
LB
10108 unsigned long output_cum = 0;
10109 unsigned long total_cum = 0;
9386b588 10110 unsigned long json_header_depth = 0;
67009e22 10111 struct bgp_table *itable;
0136788c 10112 bool show_msg;
96f3485c 10113 uint8_t show_flags = 0;
0136788c
LB
10114
10115 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10116
96f3485c
MK
10117 if (use_json)
10118 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10119
9bcb3eef
DS
10120 for (dest = bgp_table_top(table); dest; dest = next) {
10121 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10122
9bcb3eef
DS
10123 next = bgp_route_next(dest);
10124 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10125 continue;
67009e22 10126
9bcb3eef 10127 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10128 if (itable != NULL) {
1ae44dfc 10129 struct prefix_rd prd;
06b9f471 10130 char rd[RD_ADDRSTRLEN];
1ae44dfc 10131
9bcb3eef 10132 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10133 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10134 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10135 rd, next == NULL, &output_cum,
10136 &total_cum, &json_header_depth,
10137 show_flags);
0136788c
LB
10138 if (next == NULL)
10139 show_msg = false;
1ae44dfc
LB
10140 }
10141 }
0136788c
LB
10142 if (show_msg) {
10143 if (output_cum == 0)
10144 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10145 total_cum);
10146 else
10147 vty_out(vty,
10148 "\nDisplayed %ld routes and %ld total paths\n",
10149 output_cum, total_cum);
10150 }
1ae44dfc
LB
10151 return CMD_SUCCESS;
10152}
d62a17ae 10153static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10154 enum bgp_show_type type, void *output_arg,
10155 uint8_t show_flags)
fee0f4c6 10156{
d62a17ae 10157 struct bgp_table *table;
9386b588 10158 unsigned long json_header_depth = 0;
96f3485c 10159 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10160
d62a17ae 10161 if (bgp == NULL) {
10162 bgp = bgp_get_default();
10163 }
fee0f4c6 10164
d62a17ae 10165 if (bgp == NULL) {
10166 if (!use_json)
10167 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10168 else
10169 vty_out(vty, "{}\n");
d62a17ae 10170 return CMD_WARNING;
10171 }
4dd6177e 10172
1ae44dfc 10173 table = bgp->rib[afi][safi];
d62a17ae 10174 /* use MPLS and ENCAP specific shows until they are merged */
10175 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10176 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10177 output_arg, use_json);
d62a17ae 10178 }
dba3c1d3
PG
10179
10180 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10181 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10182 output_arg, use_json,
10183 1, NULL, NULL);
10184 }
d62a17ae 10185 /* labeled-unicast routes live in the unicast table */
10186 else if (safi == SAFI_LABELED_UNICAST)
10187 safi = SAFI_UNICAST;
fee0f4c6 10188
96f3485c
MK
10189 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10190 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10191}
10192
d62a17ae 10193static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10194 safi_t safi, uint8_t show_flags)
f186de26 10195{
d62a17ae 10196 struct listnode *node, *nnode;
10197 struct bgp *bgp;
10198 int is_first = 1;
9f049418 10199 bool route_output = false;
96f3485c 10200 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10201
d62a17ae 10202 if (use_json)
10203 vty_out(vty, "{\n");
9f689658 10204
d62a17ae 10205 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10206 route_output = true;
d62a17ae 10207 if (use_json) {
10208 if (!is_first)
10209 vty_out(vty, ",\n");
10210 else
10211 is_first = 0;
10212
10213 vty_out(vty, "\"%s\":",
10214 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10215 ? VRF_DEFAULT_NAME
d62a17ae 10216 : bgp->name);
10217 } else {
10218 vty_out(vty, "\nInstance %s:\n",
10219 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10220 ? VRF_DEFAULT_NAME
d62a17ae 10221 : bgp->name);
10222 }
10223 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10224 show_flags);
d62a17ae 10225 }
9f689658 10226
d62a17ae 10227 if (use_json)
10228 vty_out(vty, "}\n");
9f049418
DS
10229 else if (!route_output)
10230 vty_out(vty, "%% BGP instance not found\n");
f186de26 10231}
10232
718e3744 10233/* Header of detailed BGP route information */
d62a17ae 10234void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10235 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10236 afi_t afi, safi_t safi, json_object *json)
10237{
40381db7 10238 struct bgp_path_info *pi;
b54892e0 10239 const struct prefix *p;
d62a17ae 10240 struct peer *peer;
10241 struct listnode *node, *nnode;
06b9f471 10242 char buf1[RD_ADDRSTRLEN];
d62a17ae 10243 char buf2[INET6_ADDRSTRLEN];
d62a17ae 10244 char buf3[EVPN_ROUTE_STRLEN];
0291c246 10245 char prefix_str[BUFSIZ];
d62a17ae 10246 int count = 0;
10247 int best = 0;
10248 int suppress = 0;
c5f1e1b2
C
10249 int accept_own = 0;
10250 int route_filter_translated_v4 = 0;
10251 int route_filter_v4 = 0;
10252 int route_filter_translated_v6 = 0;
10253 int route_filter_v6 = 0;
10254 int llgr_stale = 0;
10255 int no_llgr = 0;
10256 int accept_own_nexthop = 0;
10257 int blackhole = 0;
d62a17ae 10258 int no_export = 0;
10259 int no_advertise = 0;
10260 int local_as = 0;
c5f1e1b2 10261 int no_peer = 0;
d62a17ae 10262 int first = 1;
10263 int has_valid_label = 0;
10264 mpls_label_t label = 0;
10265 json_object *json_adv_to = NULL;
9bedbb1e 10266
9bcb3eef
DS
10267 p = bgp_dest_get_prefix(dest);
10268 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 10269
10270 if (has_valid_label)
9bcb3eef 10271 label = label_pton(&dest->local_label);
d62a17ae 10272
44c69747 10273 if (safi == SAFI_EVPN) {
d62a17ae 10274
44c69747 10275 if (!json) {
d62a17ae 10276 vty_out(vty, "BGP routing table entry for %s%s%s\n",
06b9f471 10277 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
44c69747 10278 : "", prd ? ":" : "",
d62a17ae 10279 bgp_evpn_route2str((struct prefix_evpn *)p,
44c69747
LK
10280 buf3, sizeof(buf3)));
10281 } else {
10282 json_object_string_add(json, "rd",
10283 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
10284 "");
10285 bgp_evpn_route2json((struct prefix_evpn *)p, json);
10286 }
10287 } else {
10288 if (!json) {
d62a17ae 10289 vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
10290 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
44c69747
LK
10291 ? prefix_rd2str(prd, buf1,
10292 sizeof(buf1))
10293 : ""),
d62a17ae 10294 safi == SAFI_MPLS_VPN ? ":" : "",
10295 inet_ntop(p->family, &p->u.prefix, buf2,
44c69747 10296 INET6_ADDRSTRLEN),
d62a17ae 10297 p->prefixlen);
cd1964ff 10298
44c69747
LK
10299 } else
10300 json_object_string_add(json, "prefix",
10301 prefix2str(p, prefix_str, sizeof(prefix_str)));
10302 }
10303
10304 if (has_valid_label) {
10305 if (json)
10306 json_object_int_add(json, "localLabel", label);
10307 else
d62a17ae 10308 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
10309 }
10310
10311 if (!json)
d62a17ae 10312 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 10313 vty_out(vty, "not allocated\n");
718e3744 10314
9bcb3eef 10315 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 10316 count++;
40381db7 10317 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 10318 best = count;
40381db7 10319 if (pi->extra && pi->extra->suppress)
d62a17ae 10320 suppress = 1;
cee9c031 10321
40381db7 10322 if (pi->attr->community == NULL)
cee9c031
QY
10323 continue;
10324
10325 no_advertise += community_include(
40381db7
DS
10326 pi->attr->community, COMMUNITY_NO_ADVERTISE);
10327 no_export += community_include(pi->attr->community,
cee9c031 10328 COMMUNITY_NO_EXPORT);
40381db7 10329 local_as += community_include(pi->attr->community,
cee9c031 10330 COMMUNITY_LOCAL_AS);
40381db7 10331 accept_own += community_include(pi->attr->community,
cee9c031
QY
10332 COMMUNITY_ACCEPT_OWN);
10333 route_filter_translated_v4 += community_include(
40381db7 10334 pi->attr->community,
cee9c031
QY
10335 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
10336 route_filter_translated_v6 += community_include(
40381db7 10337 pi->attr->community,
cee9c031
QY
10338 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
10339 route_filter_v4 += community_include(
40381db7 10340 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 10341 route_filter_v6 += community_include(
40381db7
DS
10342 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
10343 llgr_stale += community_include(pi->attr->community,
cee9c031 10344 COMMUNITY_LLGR_STALE);
40381db7 10345 no_llgr += community_include(pi->attr->community,
cee9c031
QY
10346 COMMUNITY_NO_LLGR);
10347 accept_own_nexthop +=
40381db7 10348 community_include(pi->attr->community,
cee9c031 10349 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 10350 blackhole += community_include(pi->attr->community,
cee9c031 10351 COMMUNITY_BLACKHOLE);
40381db7 10352 no_peer += community_include(pi->attr->community,
cee9c031 10353 COMMUNITY_NO_PEER);
d62a17ae 10354 }
718e3744 10355 }
718e3744 10356
d62a17ae 10357 if (!json) {
10358 vty_out(vty, "Paths: (%d available", count);
10359 if (best) {
10360 vty_out(vty, ", best #%d", best);
b84060bb
PG
10361 if (safi == SAFI_UNICAST) {
10362 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
10363 vty_out(vty, ", table %s",
10364 VRF_DEFAULT_NAME);
10365 else
10366 vty_out(vty, ", vrf %s",
10367 bgp->name);
10368 }
d62a17ae 10369 } else
10370 vty_out(vty, ", no best path");
10371
c5f1e1b2
C
10372 if (accept_own)
10373 vty_out(vty,
10374 ", accept own local route exported and imported in different VRF");
10375 else if (route_filter_translated_v4)
10376 vty_out(vty,
10377 ", mark translated RTs for VPNv4 route filtering");
10378 else if (route_filter_v4)
10379 vty_out(vty,
10380 ", attach RT as-is for VPNv4 route filtering");
10381 else if (route_filter_translated_v6)
10382 vty_out(vty,
10383 ", mark translated RTs for VPNv6 route filtering");
10384 else if (route_filter_v6)
10385 vty_out(vty,
10386 ", attach RT as-is for VPNv6 route filtering");
10387 else if (llgr_stale)
10388 vty_out(vty,
10389 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
10390 else if (no_llgr)
10391 vty_out(vty,
10392 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
10393 else if (accept_own_nexthop)
10394 vty_out(vty,
10395 ", accept local nexthop");
10396 else if (blackhole)
10397 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 10398 else if (no_export)
10399 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
10400 else if (no_advertise)
10401 vty_out(vty, ", not advertised to any peer");
d62a17ae 10402 else if (local_as)
10403 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
10404 else if (no_peer)
10405 vty_out(vty,
10406 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 10407
10408 if (suppress)
10409 vty_out(vty,
10410 ", Advertisements suppressed by an aggregate.");
10411 vty_out(vty, ")\n");
10412 }
718e3744 10413
d62a17ae 10414 /* If we are not using addpath then we can display Advertised to and
10415 * that will
10416 * show what peers we advertised the bestpath to. If we are using
10417 * addpath
10418 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 10419 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 10420 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 10421 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 10422 if (json && !json_adv_to)
10423 json_adv_to = json_object_new_object();
10424
10425 route_vty_out_advertised_to(
10426 vty, peer, &first,
10427 " Advertised to non peer-group peers:\n ",
10428 json_adv_to);
10429 }
10430 }
10431
10432 if (json) {
10433 if (json_adv_to) {
10434 json_object_object_add(json, "advertisedTo",
10435 json_adv_to);
10436 }
10437 } else {
10438 if (first)
10439 vty_out(vty, " Not advertised to any peer");
10440 vty_out(vty, "\n");
10441 }
10442 }
718e3744 10443}
10444
44c69747 10445static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
10446 struct bgp_dest *bgp_node, struct vty *vty,
10447 struct bgp *bgp, afi_t afi, safi_t safi,
10448 json_object *json, enum bgp_path_type pathtype,
10449 int *display)
44c69747
LK
10450{
10451 struct bgp_path_info *pi;
10452 int header = 1;
10453 char rdbuf[RD_ADDRSTRLEN];
10454 json_object *json_header = NULL;
10455 json_object *json_paths = NULL;
10456
9bcb3eef 10457 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
10458
10459 if (json && !json_paths) {
10460 /* Instantiate json_paths only if path is valid */
10461 json_paths = json_object_new_array();
10462 if (pfx_rd) {
10463 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
10464 json_header = json_object_new_object();
10465 } else
10466 json_header = json;
10467 }
10468
10469 if (header) {
10470 route_vty_out_detail_header(
10471 vty, bgp, bgp_node, pfx_rd,
10472 AFI_IP, safi, json_header);
10473 header = 0;
10474 }
10475 (*display)++;
10476
10477 if (pathtype == BGP_PATH_SHOW_ALL
10478 || (pathtype == BGP_PATH_SHOW_BESTPATH
10479 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
10480 || (pathtype == BGP_PATH_SHOW_MULTIPATH
10481 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
10482 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
10483 route_vty_out_detail(vty, bgp, bgp_node,
10484 pi, AFI_IP, safi,
10485 json_paths);
10486 }
10487
10488 if (json && json_paths) {
10489 json_object_object_add(json_header, "paths", json_paths);
10490
10491 if (pfx_rd)
10492 json_object_object_add(json, rdbuf, json_header);
10493 }
10494}
10495
718e3744 10496/* Display specified route of BGP table. */
d62a17ae 10497static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
10498 struct bgp_table *rib, const char *ip_str,
10499 afi_t afi, safi_t safi,
10500 struct prefix_rd *prd, int prefix_check,
9f049418 10501 enum bgp_path_type pathtype, bool use_json)
d62a17ae 10502{
10503 int ret;
d62a17ae 10504 int display = 0;
10505 struct prefix match;
9bcb3eef
DS
10506 struct bgp_dest *dest;
10507 struct bgp_dest *rm;
d62a17ae 10508 struct bgp_table *table;
10509 json_object *json = NULL;
10510 json_object *json_paths = NULL;
10511
10512 /* Check IP address argument. */
10513 ret = str2prefix(ip_str, &match);
10514 if (!ret) {
10515 vty_out(vty, "address is malformed\n");
10516 return CMD_WARNING;
10517 }
718e3744 10518
d62a17ae 10519 match.family = afi2family(afi);
b05a1c8b 10520
44c69747 10521 if (use_json)
d62a17ae 10522 json = json_object_new_object();
718e3744 10523
44c69747 10524 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
10525 for (dest = bgp_table_top(rib); dest;
10526 dest = bgp_route_next(dest)) {
10527 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10528
9bcb3eef 10529 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 10530 continue;
9bcb3eef 10531 table = bgp_dest_get_bgp_table_info(dest);
67009e22 10532 if (!table)
ea47320b 10533 continue;
d62a17ae 10534
ea47320b
DL
10535 if ((rm = bgp_node_match(table, &match)) == NULL)
10536 continue;
d62a17ae 10537
9bcb3eef 10538 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 10539 if (prefix_check
b54892e0 10540 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 10541 bgp_dest_unlock_node(rm);
ea47320b
DL
10542 continue;
10543 }
d62a17ae 10544
9bcb3eef 10545 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10546 bgp, afi, safi, json, pathtype,
10547 &display);
44c69747 10548
9bcb3eef 10549 bgp_dest_unlock_node(rm);
44c69747
LK
10550 }
10551 } else if (safi == SAFI_EVPN) {
9bcb3eef 10552 struct bgp_dest *longest_pfx;
cded3b72 10553 bool is_exact_pfxlen_match = false;
44c69747 10554
9bcb3eef
DS
10555 for (dest = bgp_table_top(rib); dest;
10556 dest = bgp_route_next(dest)) {
10557 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10558
9bcb3eef 10559 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 10560 continue;
9bcb3eef 10561 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
10562 if (!table)
10563 continue;
10564
10565 longest_pfx = NULL;
cded3b72 10566 is_exact_pfxlen_match = false;
44c69747
LK
10567 /*
10568 * Search through all the prefixes for a match. The
10569 * pfx's are enumerated in ascending order of pfxlens.
10570 * So, the last pfx match is the longest match. Set
10571 * is_exact_pfxlen_match when we get exact pfxlen match
10572 */
10573 for (rm = bgp_table_top(table); rm;
10574 rm = bgp_route_next(rm)) {
b54892e0 10575 const struct prefix *rm_p =
9bcb3eef 10576 bgp_dest_get_prefix(rm);
44c69747
LK
10577 /*
10578 * Get prefixlen of the ip-prefix within type5
10579 * evpn route
10580 */
b54892e0
DS
10581 if (evpn_type5_prefix_match(rm_p, &match)
10582 && rm->info) {
44c69747
LK
10583 longest_pfx = rm;
10584 int type5_pfxlen =
b54892e0
DS
10585 bgp_evpn_get_type5_prefixlen(
10586 rm_p);
44c69747 10587 if (type5_pfxlen == match.prefixlen) {
cded3b72 10588 is_exact_pfxlen_match = true;
9bcb3eef 10589 bgp_dest_unlock_node(rm);
44c69747
LK
10590 break;
10591 }
d62a17ae 10592 }
10593 }
ea47320b 10594
44c69747
LK
10595 if (!longest_pfx)
10596 continue;
10597
10598 if (prefix_check && !is_exact_pfxlen_match)
10599 continue;
10600
10601 rm = longest_pfx;
9bcb3eef 10602 bgp_dest_lock_node(rm);
44c69747 10603
9bcb3eef 10604 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
10605 bgp, afi, safi, json, pathtype,
10606 &display);
44c69747 10607
9bcb3eef 10608 bgp_dest_unlock_node(rm);
d62a17ae 10609 }
98a9dbc7 10610 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
10611 if (use_json)
10612 json_paths = json_object_new_array();
10613
63a0b7a9
PG
10614 display = bgp_flowspec_display_match_per_ip(afi, rib,
10615 &match, prefix_check,
10616 vty,
10617 use_json,
10618 json_paths);
44c69747
LK
10619 if (use_json && display)
10620 json_object_object_add(json, "paths", json_paths);
d62a17ae 10621 } else {
9bcb3eef
DS
10622 if ((dest = bgp_node_match(rib, &match)) != NULL) {
10623 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 10624 if (!prefix_check
9bcb3eef
DS
10625 || dest_p->prefixlen == match.prefixlen) {
10626 bgp_show_path_info(NULL, dest, vty, bgp, afi,
10627 safi, json, pathtype,
10628 &display);
d62a17ae 10629 }
10630
9bcb3eef 10631 bgp_dest_unlock_node(dest);
d62a17ae 10632 }
10633 }
e5eee9af 10634
d62a17ae 10635 if (use_json) {
996c9314 10636 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
10637 json, JSON_C_TO_STRING_PRETTY |
10638 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 10639 json_object_free(json);
10640 } else {
10641 if (!display) {
10642 vty_out(vty, "%% Network not in table\n");
10643 return CMD_WARNING;
10644 }
10645 }
b05a1c8b 10646
d62a17ae 10647 return CMD_SUCCESS;
718e3744 10648}
10649
fee0f4c6 10650/* Display specified route of Main RIB */
d62a17ae 10651static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
10652 afi_t afi, safi_t safi, struct prefix_rd *prd,
10653 int prefix_check, enum bgp_path_type pathtype,
9f049418 10654 bool use_json)
d62a17ae 10655{
9b86009a 10656 if (!bgp) {
d62a17ae 10657 bgp = bgp_get_default();
9b86009a
RW
10658 if (!bgp) {
10659 if (!use_json)
10660 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10661 else
10662 vty_out(vty, "{}\n");
9b86009a
RW
10663 return CMD_WARNING;
10664 }
10665 }
d62a17ae 10666
10667 /* labeled-unicast routes live in the unicast table */
10668 if (safi == SAFI_LABELED_UNICAST)
10669 safi = SAFI_UNICAST;
10670
10671 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
10672 afi, safi, prd, prefix_check, pathtype,
10673 use_json);
10674}
10675
10676static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 10677 struct cmd_token **argv, bool exact, afi_t afi,
10678 safi_t safi, bool uj)
d62a17ae 10679{
10680 struct lcommunity *lcom;
10681 struct buffer *b;
10682 int i;
10683 char *str;
10684 int first = 0;
96f3485c
MK
10685 uint8_t show_flags = 0;
10686
10687 if (uj)
10688 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 10689
10690 b = buffer_new(1024);
10691 for (i = 0; i < argc; i++) {
10692 if (first)
10693 buffer_putc(b, ' ');
10694 else {
10695 if (strmatch(argv[i]->text, "AA:BB:CC")) {
10696 first = 1;
10697 buffer_putstr(b, argv[i]->arg);
10698 }
10699 }
10700 }
10701 buffer_putc(b, '\0');
57d187bc 10702
d62a17ae 10703 str = buffer_getstr(b);
10704 buffer_free(b);
57d187bc 10705
d62a17ae 10706 lcom = lcommunity_str2com(str);
10707 XFREE(MTYPE_TMP, str);
10708 if (!lcom) {
10709 vty_out(vty, "%% Large-community malformed\n");
10710 return CMD_WARNING;
10711 }
57d187bc 10712
36a206db 10713 return bgp_show(vty, bgp, afi, safi,
10714 (exact ? bgp_show_type_lcommunity_exact
ae248832 10715 : bgp_show_type_lcommunity),
96f3485c 10716 lcom, show_flags);
57d187bc
JS
10717}
10718
d62a17ae 10719static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 10720 const char *lcom, bool exact, afi_t afi,
10721 safi_t safi, bool uj)
57d187bc 10722{
d62a17ae 10723 struct community_list *list;
96f3485c
MK
10724 uint8_t show_flags = 0;
10725
10726 if (uj)
10727 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10728
57d187bc 10729
e237b0d2 10730 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 10731 LARGE_COMMUNITY_LIST_MASTER);
10732 if (list == NULL) {
10733 vty_out(vty, "%% %s is not a valid large-community-list name\n",
10734 lcom);
10735 return CMD_WARNING;
10736 }
57d187bc 10737
36a206db 10738 return bgp_show(vty, bgp, afi, safi,
10739 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 10740 : bgp_show_type_lcommunity_list),
96f3485c 10741 list, show_flags);
fee0f4c6 10742}
10743
52951b63
DS
10744DEFUN (show_ip_bgp_large_community_list,
10745 show_ip_bgp_large_community_list_cmd,
36a206db 10746 "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
10747 SHOW_STR
10748 IP_STR
10749 BGP_STR
10750 BGP_INSTANCE_HELP_STR
9bedbb1e 10751 BGP_AFI_HELP_STR
4dd6177e 10752 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10753 "Display routes matching the large-community-list\n"
10754 "large-community-list number\n"
10755 "large-community-list name\n"
36a206db 10756 "Exact match of the large-communities\n"
52951b63
DS
10757 JSON_STR)
10758{
d62a17ae 10759 afi_t afi = AFI_IP6;
10760 safi_t safi = SAFI_UNICAST;
10761 int idx = 0;
36a206db 10762 bool exact_match = 0;
4d678463 10763 struct bgp *bgp = NULL;
9f049418 10764 bool uj = use_json(argc, argv);
d62a17ae 10765
4d678463
KA
10766 if (uj)
10767 argc--;
10768
10769 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10770 &bgp, uj);
10771 if (!idx)
10772 return CMD_WARNING;
d62a17ae 10773
10774 argv_find(argv, argc, "large-community-list", &idx);
36a206db 10775
10776 const char *clist_number_or_name = argv[++idx]->arg;
10777
10778 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
10779 exact_match = 1;
10780
10781 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
10782 exact_match, afi, safi, uj);
52951b63
DS
10783}
10784DEFUN (show_ip_bgp_large_community,
10785 show_ip_bgp_large_community_cmd,
36a206db 10786 "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
10787 SHOW_STR
10788 IP_STR
10789 BGP_STR
10790 BGP_INSTANCE_HELP_STR
9bedbb1e 10791 BGP_AFI_HELP_STR
4dd6177e 10792 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
10793 "Display routes matching the large-communities\n"
10794 "List of large-community numbers\n"
36a206db 10795 "Exact match of the large-communities\n"
52951b63
DS
10796 JSON_STR)
10797{
d62a17ae 10798 afi_t afi = AFI_IP6;
10799 safi_t safi = SAFI_UNICAST;
10800 int idx = 0;
36a206db 10801 bool exact_match = 0;
4d678463 10802 struct bgp *bgp = NULL;
9f049418 10803 bool uj = use_json(argc, argv);
96f3485c 10804 uint8_t show_flags = 0;
d62a17ae 10805
96f3485c
MK
10806 if (uj) {
10807 argc--;
10808 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10809 }
4d678463 10810
96f3485c
MK
10811 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10812 &bgp, uj);
10813 if (!idx)
10814 return CMD_WARNING;
d62a17ae 10815
36a206db 10816 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
10817 if (argv_find(argv, argc, "exact-match", &idx))
10818 exact_match = 1;
10819 return bgp_show_lcommunity(vty, bgp, argc, argv,
10820 exact_match, afi, safi, uj);
10821 } else
d62a17ae 10822 return bgp_show(vty, bgp, afi, safi,
96f3485c 10823 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
10824}
10825
71f1613a
DA
10826static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
10827 safi_t safi, struct json_object *json_array);
d62a17ae 10828static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 10829 safi_t safi, struct json_object *json);
e01ca200 10830
7b2ff250 10831
9ab0cf58
PG
10832DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
10833 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
10834 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
10835 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
10836{
10837 bool uj = use_json(argc, argv);
10838 struct bgp *bgp = NULL;
ec76a1d1
DA
10839 safi_t safi = SAFI_UNICAST;
10840 afi_t afi = AFI_IP6;
4265b261 10841 int idx = 0;
6c9d22e2
PG
10842 struct json_object *json_all = NULL;
10843 struct json_object *json_afi_safi = NULL;
4265b261
PG
10844
10845 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10846 &bgp, false);
71f1613a 10847 if (!idx)
4265b261 10848 return CMD_WARNING;
6c9d22e2 10849
4265b261 10850 if (uj)
6c9d22e2 10851 json_all = json_object_new_object();
4265b261 10852
9ab0cf58
PG
10853 FOREACH_AFI_SAFI (afi, safi) {
10854 /*
10855 * So limit output to those afi/safi pairs that
10856 * actually have something interesting in them
10857 */
10858 if (strmatch(get_afi_safi_str(afi, safi, true),
10859 "Unknown")) {
10860 continue;
10861 }
10862 if (uj) {
10863 json_afi_safi = json_object_new_array();
10864 json_object_object_add(
10865 json_all,
10866 get_afi_safi_str(afi, safi, true),
10867 json_afi_safi);
10868 } else {
10869 json_afi_safi = NULL;
6c9d22e2 10870 }
9ab0cf58
PG
10871
10872 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 10873 }
6c9d22e2
PG
10874
10875 if (uj) {
9ab0cf58
PG
10876 vty_out(vty, "%s",
10877 json_object_to_json_string_ext(
10878 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 10879 json_object_free(json_all);
4265b261 10880 }
6c9d22e2 10881
4265b261
PG
10882 return CMD_SUCCESS;
10883}
10884
7b2ff250 10885/* BGP route print out function without JSON */
14718643
PG
10886DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
10887 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 10888 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
10889 SHOW_STR
10890 IP_STR
10891 BGP_STR
10892 BGP_INSTANCE_HELP_STR
10893 L2VPN_HELP_STR
10894 EVPN_HELP_STR
10895 "BGP RIB advertisement statistics\n"
10896 JSON_STR)
10897{
ec76a1d1
DA
10898 afi_t afi = AFI_IP6;
10899 safi_t safi = SAFI_UNICAST;
14718643
PG
10900 struct bgp *bgp = NULL;
10901 int idx = 0, ret;
10902 bool uj = use_json(argc, argv);
10903 struct json_object *json_afi_safi = NULL, *json = NULL;
10904
10905 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10906 &bgp, false);
10907 if (!idx)
10908 return CMD_WARNING;
10909
10910 if (uj)
10911 json_afi_safi = json_object_new_array();
10912 else
10913 json_afi_safi = NULL;
10914
10915 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10916
10917 if (uj) {
10918 json = json_object_new_object();
10919 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10920 json_afi_safi);
10921 vty_out(vty, "%s", json_object_to_json_string_ext(
10922 json, JSON_C_TO_STRING_PRETTY));
10923 json_object_free(json);
10924 }
10925 return ret;
10926}
10927
893cccd0 10928/* BGP route print out function without JSON */
9ab0cf58
PG
10929DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
10930 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10931 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10932 "]]\
893cccd0 10933 statistics [json]",
9ab0cf58
PG
10934 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10935 BGP_SAFI_WITH_LABEL_HELP_STR
10936 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 10937{
ec76a1d1
DA
10938 afi_t afi = AFI_IP6;
10939 safi_t safi = SAFI_UNICAST;
893cccd0
PG
10940 struct bgp *bgp = NULL;
10941 int idx = 0, ret;
10942 bool uj = use_json(argc, argv);
6c9d22e2 10943 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
10944
10945 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
10946 &bgp, false);
10947 if (!idx)
10948 return CMD_WARNING;
6c9d22e2 10949
893cccd0 10950 if (uj)
6c9d22e2
PG
10951 json_afi_safi = json_object_new_array();
10952 else
10953 json_afi_safi = NULL;
10954
10955 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
10956
10957 if (uj) {
10958 json = json_object_new_object();
10959 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
10960 json_afi_safi);
9ab0cf58
PG
10961 vty_out(vty, "%s",
10962 json_object_to_json_string_ext(
10963 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
10964 json_object_free(json);
10965 }
10966 return ret;
893cccd0 10967}
7b2ff250
DW
10968
10969/* BGP route print out function without JSON */
96f3485c 10970DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
10971 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
10972 " [" BGP_SAFI_WITH_LABEL_CMD_STR
10973 "]]\
96f3485c 10974 <[all$all] dampening <parameters>\
7b2ff250
DW
10975 |route-map WORD\
10976 |prefix-list WORD\
10977 |filter-list WORD\
7b2ff250
DW
10978 |community-list <(1-500)|WORD> [exact-match]\
10979 |A.B.C.D/M longer-prefixes\
10980 |X:X::X:X/M longer-prefixes\
893cccd0 10981 >",
9ab0cf58
PG
10982 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
10983 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 10984 "Display the entries for all address families\n"
9ab0cf58
PG
10985 "Display detailed information about dampening\n"
10986 "Display detail of configured dampening parameters\n"
10987 "Display routes matching the route-map\n"
10988 "A route-map to match on\n"
10989 "Display routes conforming to the prefix-list\n"
10990 "Prefix-list name\n"
10991 "Display routes conforming to the filter-list\n"
10992 "Regular expression access list name\n"
10993 "Display routes matching the community-list\n"
10994 "community-list number\n"
10995 "community-list name\n"
10996 "Exact match of the communities\n"
10997 "IPv4 prefix\n"
10998 "Display route and more specific routes\n"
10999 "IPv6 prefix\n"
11000 "Display route and more specific routes\n")
718e3744 11001{
d62a17ae 11002 afi_t afi = AFI_IP6;
11003 safi_t safi = SAFI_UNICAST;
11004 int exact_match = 0;
d62a17ae 11005 struct bgp *bgp = NULL;
11006 int idx = 0;
96f3485c
MK
11007 uint8_t show_flags = 0;
11008
11009 /* [<ipv4|ipv6> [all]] */
11010 if (all) {
11011 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11012 if (argv_find(argv, argc, "ipv4", &idx))
11013 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11014
11015 if (argv_find(argv, argc, "ipv6", &idx))
11016 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11017 }
d62a17ae 11018
11019 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11020 &bgp, false);
d62a17ae 11021 if (!idx)
11022 return CMD_WARNING;
11023
d62a17ae 11024 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11025 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11026 return bgp_show_dampening_parameters(vty, afi, safi,
11027 show_flags);
d62a17ae 11028 }
c016b6c7 11029
d62a17ae 11030 if (argv_find(argv, argc, "prefix-list", &idx))
11031 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11032 safi, bgp_show_type_prefix_list);
11033
11034 if (argv_find(argv, argc, "filter-list", &idx))
11035 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11036 safi, bgp_show_type_filter_list);
11037
d62a17ae 11038 if (argv_find(argv, argc, "route-map", &idx))
11039 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11040 safi, bgp_show_type_route_map);
11041
d62a17ae 11042 if (argv_find(argv, argc, "community-list", &idx)) {
11043 const char *clist_number_or_name = argv[++idx]->arg;
11044 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11045 exact_match = 1;
11046 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11047 exact_match, afi, safi);
11048 }
11049 /* prefix-longer */
11050 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11051 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11052 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11053 safi,
11054 bgp_show_type_prefix_longer);
11055
7b2ff250
DW
11056 return CMD_WARNING;
11057}
11058
11059/* BGP route print out function with JSON */
ae248832 11060DEFPY (show_ip_bgp_json,
7b2ff250
DW
11061 show_ip_bgp_json_cmd,
11062 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11063 [all$all]\
cf4898bc
QY
11064 [cidr-only\
11065 |dampening <flap-statistics|dampened-paths>\
11066 |community [AA:NN|local-AS|no-advertise|no-export\
11067 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11068 |accept-own|accept-own-nexthop|route-filter-v6\
11069 |route-filter-v4|route-filter-translated-v6\
11070 |route-filter-translated-v4] [exact-match]\
ae248832 11071 ] [json$uj | wide$wide]",
7b2ff250
DW
11072 SHOW_STR
11073 IP_STR
11074 BGP_STR
11075 BGP_INSTANCE_HELP_STR
11076 BGP_AFI_HELP_STR
11077 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11078 "Display the entries for all address families\n"
7b2ff250
DW
11079 "Display only routes with non-natural netmasks\n"
11080 "Display detailed information about dampening\n"
11081 "Display flap statistics of routes\n"
11082 "Display paths suppressed due to dampening\n"
11083 "Display routes matching the communities\n"
d0086e8e
AD
11084 COMMUNITY_AANN_STR
11085 "Do not send outside local AS (well-known community)\n"
11086 "Do not advertise to any peer (well-known community)\n"
11087 "Do not export to next AS (well-known community)\n"
11088 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11089 "Do not export to any peer (well-known community)\n"
11090 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11091 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11092 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11093 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11094 "Should accept VPN route with local nexthop (well-known community)\n"
11095 "RT VPNv6 route filtering (well-known community)\n"
11096 "RT VPNv4 route filtering (well-known community)\n"
11097 "RT translated VPNv6 route filtering (well-known community)\n"
11098 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11099 "Exact match of the communities\n"
ae248832
MK
11100 JSON_STR
11101 "Increase table width for longer prefixes\n")
7b2ff250
DW
11102{
11103 afi_t afi = AFI_IP6;
11104 safi_t safi = SAFI_UNICAST;
11105 enum bgp_show_type sh_type = bgp_show_type_normal;
11106 struct bgp *bgp = NULL;
11107 int idx = 0;
d0086e8e 11108 int exact_match = 0;
96f3485c
MK
11109 char *community = NULL;
11110 bool first = true;
11111 uint8_t show_flags = 0;
9f049418 11112
96f3485c
MK
11113
11114 if (uj) {
9f049418 11115 argc--;
96f3485c
MK
11116 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11117 }
11118
11119 /* [<ipv4|ipv6> [all]] */
11120 if (all) {
11121 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11122
11123 if (argv_find(argv, argc, "ipv4", &idx))
11124 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11125
11126 if (argv_find(argv, argc, "ipv6", &idx))
11127 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11128 }
11129
11130 if (wide)
11131 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11132
11133 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11134 &bgp, uj);
7b2ff250
DW
11135 if (!idx)
11136 return CMD_WARNING;
11137
7b2ff250 11138 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11139 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11140
11141 if (argv_find(argv, argc, "dampening", &idx)) {
11142 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11143 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11144 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11145 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11146 }
11147
11148 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11149 char *maybecomm = NULL;
d0086e8e 11150
79bc257a
RW
11151 if (idx + 1 < argc) {
11152 if (argv[idx + 1]->type == VARIABLE_TKN)
11153 maybecomm = argv[idx + 1]->arg;
11154 else
11155 maybecomm = argv[idx + 1]->text;
11156 }
11157
cf4898bc
QY
11158 if (maybecomm && !strmatch(maybecomm, "json")
11159 && !strmatch(maybecomm, "exact-match"))
11160 community = maybecomm;
d0086e8e 11161
cf4898bc
QY
11162 if (argv_find(argv, argc, "exact-match", &idx))
11163 exact_match = 1;
d0086e8e 11164
96f3485c
MK
11165 if (!community)
11166 sh_type = bgp_show_type_community_all;
11167 }
11168
11169 if (!all) {
11170 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11171 if (community)
11172 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11173 exact_match, afi, safi,
11174 show_flags);
cf4898bc 11175 else
96f3485c
MK
11176 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11177 show_flags);
11178 } else {
11179 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11180 * AFI_IP6 */
11181
11182 if (uj)
11183 vty_out(vty, "{\n");
11184
11185 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11186 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11187 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11188 ? AFI_IP
11189 : AFI_IP6;
11190 FOREACH_SAFI (safi) {
11191 if (strmatch(get_afi_safi_str(afi, safi, true),
11192 "Unknown"))
11193 continue;
11194
11195 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11196 continue;
11197
11198 if (uj) {
11199 if (first)
11200 first = false;
11201 else
11202 vty_out(vty, ",\n");
11203 vty_out(vty, "\"%s\":{\n",
11204 get_afi_safi_str(afi, safi,
11205 true));
11206 } else
11207 vty_out(vty,
11208 "\nFor address family: %s\n",
11209 get_afi_safi_str(afi, safi,
11210 false));
11211
11212 if (community)
11213 bgp_show_community(vty, bgp, community,
11214 exact_match, afi,
11215 safi, show_flags);
11216 else
11217 bgp_show(vty, bgp, afi, safi, sh_type,
11218 NULL, show_flags);
11219 if (uj)
11220 vty_out(vty, "}\n");
11221 }
11222 } else {
11223 /* show <ip> bgp all: for each AFI and SAFI*/
11224 FOREACH_AFI_SAFI (afi, safi) {
11225 if (strmatch(get_afi_safi_str(afi, safi, true),
11226 "Unknown"))
11227 continue;
11228
11229 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11230 continue;
11231
11232 if (uj) {
11233 if (first)
11234 first = false;
11235 else
11236 vty_out(vty, ",\n");
d0086e8e 11237
96f3485c
MK
11238 vty_out(vty, "\"%s\":{\n",
11239 get_afi_safi_str(afi, safi,
11240 true));
11241 } else
11242 vty_out(vty,
11243 "\nFor address family: %s\n",
11244 get_afi_safi_str(afi, safi,
11245 false));
11246
11247 if (community)
11248 bgp_show_community(vty, bgp, community,
11249 exact_match, afi,
11250 safi, show_flags);
11251 else
11252 bgp_show(vty, bgp, afi, safi, sh_type,
11253 NULL, show_flags);
11254 if (uj)
11255 vty_out(vty, "}\n");
11256 }
11257 }
11258 if (uj)
11259 vty_out(vty, "}\n");
11260 }
11261 return CMD_SUCCESS;
a636c635 11262}
47fc97cc 11263
718e3744 11264DEFUN (show_ip_bgp_route,
11265 show_ip_bgp_route_cmd,
3efd0893 11266 "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 11267 SHOW_STR
11268 IP_STR
11269 BGP_STR
a636c635 11270 BGP_INSTANCE_HELP_STR
4f280b15 11271 BGP_AFI_HELP_STR
4dd6177e 11272 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 11273 "Network in the BGP routing table to display\n"
0c7b1b01 11274 "IPv4 prefix\n"
8c3deaae 11275 "Network in the BGP routing table to display\n"
0c7b1b01 11276 "IPv6 prefix\n"
4092b06c 11277 "Display only the bestpath\n"
b05a1c8b 11278 "Display only multipaths\n"
9973d184 11279 JSON_STR)
4092b06c 11280{
d62a17ae 11281 int prefix_check = 0;
ae19d7dd 11282
d62a17ae 11283 afi_t afi = AFI_IP6;
11284 safi_t safi = SAFI_UNICAST;
11285 char *prefix = NULL;
11286 struct bgp *bgp = NULL;
11287 enum bgp_path_type path_type;
9f049418 11288 bool uj = use_json(argc, argv);
b05a1c8b 11289
d62a17ae 11290 int idx = 0;
ae19d7dd 11291
d62a17ae 11292 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11293 &bgp, uj);
d62a17ae 11294 if (!idx)
11295 return CMD_WARNING;
c41247f5 11296
d62a17ae 11297 if (!bgp) {
11298 vty_out(vty,
11299 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
11300 return CMD_WARNING;
11301 }
a636c635 11302
d62a17ae 11303 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
11304 if (argv_find(argv, argc, "A.B.C.D", &idx)
11305 || argv_find(argv, argc, "X:X::X:X", &idx))
11306 prefix_check = 0;
11307 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11308 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11309 prefix_check = 1;
11310
11311 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
11312 && afi != AFI_IP6) {
11313 vty_out(vty,
11314 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
11315 return CMD_WARNING;
11316 }
11317 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
11318 && afi != AFI_IP) {
11319 vty_out(vty,
11320 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
11321 return CMD_WARNING;
11322 }
11323
11324 prefix = argv[idx]->arg;
11325
11326 /* [<bestpath|multipath>] */
11327 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 11328 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 11329 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 11330 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 11331 else
360660c6 11332 path_type = BGP_PATH_SHOW_ALL;
a636c635 11333
d62a17ae 11334 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
11335 path_type, uj);
4092b06c
DS
11336}
11337
8c3deaae
QY
11338DEFUN (show_ip_bgp_regexp,
11339 show_ip_bgp_regexp_cmd,
3e5b31b3 11340 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
11341 SHOW_STR
11342 IP_STR
11343 BGP_STR
b00b230a 11344 BGP_INSTANCE_HELP_STR
4f280b15 11345 BGP_AFI_HELP_STR
4dd6177e 11346 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 11347 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
11348 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
11349 JSON_STR)
8c3deaae 11350{
d62a17ae 11351 afi_t afi = AFI_IP6;
11352 safi_t safi = SAFI_UNICAST;
11353 struct bgp *bgp = NULL;
3e5b31b3
DA
11354 bool uj = use_json(argc, argv);
11355 char *regstr = NULL;
8c3deaae 11356
d62a17ae 11357 int idx = 0;
11358 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11359 &bgp, false);
d62a17ae 11360 if (!idx)
11361 return CMD_WARNING;
8c3deaae 11362
d62a17ae 11363 // get index of regex
3e5b31b3
DA
11364 if (argv_find(argv, argc, "REGEX", &idx))
11365 regstr = argv[idx]->arg;
8c3deaae 11366
5f71d11c 11367 assert(regstr);
3e5b31b3
DA
11368 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
11369 bgp_show_type_regexp, uj);
8c3deaae
QY
11370}
11371
ae248832 11372DEFPY (show_ip_bgp_instance_all,
a636c635 11373 show_ip_bgp_instance_all_cmd,
ae248832 11374 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 11375 SHOW_STR
a636c635 11376 IP_STR
4092b06c 11377 BGP_STR
a636c635 11378 BGP_INSTANCE_ALL_HELP_STR
4f280b15 11379 BGP_AFI_HELP_STR
4dd6177e 11380 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
11381 JSON_STR
11382 "Increase table width for longer prefixes\n")
4092b06c 11383{
d62a17ae 11384 afi_t afi = AFI_IP;
11385 safi_t safi = SAFI_UNICAST;
11386 struct bgp *bgp = NULL;
d62a17ae 11387 int idx = 0;
96f3485c 11388 uint8_t show_flags = 0;
ae19d7dd 11389
96f3485c 11390 if (uj) {
d62a17ae 11391 argc--;
96f3485c
MK
11392 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11393 }
11394
11395 if (wide)
11396 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 11397
9f049418
DS
11398 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11399 &bgp, uj);
11400 if (!idx)
11401 return CMD_WARNING;
11402
96f3485c 11403 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 11404 return CMD_SUCCESS;
e3e29b32
LB
11405}
11406
a4d82a8a 11407static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
11408 afi_t afi, safi_t safi, enum bgp_show_type type,
11409 bool use_json)
718e3744 11410{
d62a17ae 11411 regex_t *regex;
11412 int rc;
96f3485c
MK
11413 uint8_t show_flags = 0;
11414
11415 if (use_json)
11416 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 11417
c3900853 11418 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 11419 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
11420 regstr);
11421 return CMD_WARNING_CONFIG_FAILED;
11422 }
11423
d62a17ae 11424 regex = bgp_regcomp(regstr);
11425 if (!regex) {
11426 vty_out(vty, "Can't compile regexp %s\n", regstr);
11427 return CMD_WARNING;
11428 }
a636c635 11429
96f3485c 11430 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 11431 bgp_regex_free(regex);
11432 return rc;
e3e29b32
LB
11433}
11434
d62a17ae 11435static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
11436 const char *prefix_list_str, afi_t afi,
11437 safi_t safi, enum bgp_show_type type)
e3e29b32 11438{
d62a17ae 11439 struct prefix_list *plist;
96f3485c 11440 uint8_t show_flags = 0;
718e3744 11441
d62a17ae 11442 plist = prefix_list_lookup(afi, prefix_list_str);
11443 if (plist == NULL) {
11444 vty_out(vty, "%% %s is not a valid prefix-list name\n",
11445 prefix_list_str);
11446 return CMD_WARNING;
11447 }
718e3744 11448
96f3485c 11449 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
11450}
11451
d62a17ae 11452static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
11453 const char *filter, afi_t afi, safi_t safi,
11454 enum bgp_show_type type)
4092b06c 11455{
d62a17ae 11456 struct as_list *as_list;
96f3485c 11457 uint8_t show_flags = 0;
718e3744 11458
d62a17ae 11459 as_list = as_list_lookup(filter);
11460 if (as_list == NULL) {
11461 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
11462 filter);
11463 return CMD_WARNING;
11464 }
a636c635 11465
96f3485c 11466 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 11467}
11468
d62a17ae 11469static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
11470 const char *rmap_str, afi_t afi, safi_t safi,
11471 enum bgp_show_type type)
718e3744 11472{
d62a17ae 11473 struct route_map *rmap;
96f3485c 11474 uint8_t show_flags = 0;
bb46e94f 11475
d62a17ae 11476 rmap = route_map_lookup_by_name(rmap_str);
11477 if (!rmap) {
11478 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
11479 return CMD_WARNING;
11480 }
11481
96f3485c 11482 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 11483}
11484
7f323236
DW
11485static int bgp_show_community(struct vty *vty, struct bgp *bgp,
11486 const char *comstr, int exact, afi_t afi,
96f3485c 11487 safi_t safi, uint8_t show_flags)
d62a17ae 11488{
11489 struct community *com;
d62a17ae 11490 int ret = 0;
11491
7f323236 11492 com = community_str2com(comstr);
d62a17ae 11493 if (!com) {
7f323236 11494 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 11495 return CMD_WARNING;
11496 }
11497
11498 ret = bgp_show(vty, bgp, afi, safi,
11499 (exact ? bgp_show_type_community_exact
11500 : bgp_show_type_community),
96f3485c 11501 com, show_flags);
3c1f53de 11502 community_free(&com);
46c3ce83 11503
d62a17ae 11504 return ret;
718e3744 11505}
11506
d62a17ae 11507static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
11508 const char *com, int exact, afi_t afi,
11509 safi_t safi)
50ef26d4 11510{
d62a17ae 11511 struct community_list *list;
96f3485c 11512 uint8_t show_flags = 0;
50ef26d4 11513
e237b0d2 11514 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 11515 if (list == NULL) {
11516 vty_out(vty, "%% %s is not a valid community-list name\n", com);
11517 return CMD_WARNING;
11518 }
718e3744 11519
d62a17ae 11520 return bgp_show(vty, bgp, afi, safi,
11521 (exact ? bgp_show_type_community_list_exact
11522 : bgp_show_type_community_list),
96f3485c 11523 list, show_flags);
50ef26d4 11524}
11525
d62a17ae 11526static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
11527 const char *prefix, afi_t afi, safi_t safi,
11528 enum bgp_show_type type)
718e3744 11529{
d62a17ae 11530 int ret;
11531 struct prefix *p;
96f3485c 11532 uint8_t show_flags = 0;
47fc97cc 11533
d62a17ae 11534 p = prefix_new();
95cbbd2a 11535
d62a17ae 11536 ret = str2prefix(prefix, p);
11537 if (!ret) {
11538 vty_out(vty, "%% Malformed Prefix\n");
11539 return CMD_WARNING;
11540 }
47e9b292 11541
96f3485c 11542 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 11543 prefix_free(&p);
d62a17ae 11544 return ret;
11545}
11546
d62a17ae 11547enum bgp_stats {
11548 BGP_STATS_MAXBITLEN = 0,
11549 BGP_STATS_RIB,
11550 BGP_STATS_PREFIXES,
11551 BGP_STATS_TOTPLEN,
11552 BGP_STATS_UNAGGREGATEABLE,
11553 BGP_STATS_MAX_AGGREGATEABLE,
11554 BGP_STATS_AGGREGATES,
11555 BGP_STATS_SPACE,
11556 BGP_STATS_ASPATH_COUNT,
11557 BGP_STATS_ASPATH_MAXHOPS,
11558 BGP_STATS_ASPATH_TOTHOPS,
11559 BGP_STATS_ASPATH_MAXSIZE,
11560 BGP_STATS_ASPATH_TOTSIZE,
11561 BGP_STATS_ASN_HIGHEST,
11562 BGP_STATS_MAX,
a636c635 11563};
2815e61f 11564
9ab0cf58 11565#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
11566#define TABLE_STATS_IDX_JSON 1
11567
11568static const char *table_stats_strs[][2] = {
6c9d22e2
PG
11569 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
11570 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
11571 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
11572 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
11573 "unaggregateablePrefixes"},
11574 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
11575 "maximumAggregateablePrefixes"},
11576 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
11577 "bgpAggregateAdvertisements"},
6c9d22e2
PG
11578 [BGP_STATS_SPACE] = {"Address space advertised",
11579 "addressSpaceAdvertised"},
9ab0cf58
PG
11580 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
11581 "advertisementsWithPaths"},
11582 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
11583 "longestAsPath"},
11584 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
11585 "largestAsPath"},
11586 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
11587 "averageAsPathLengthHops"},
11588 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
11589 "averageAsPathSizeBytes"},
11590 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 11591 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 11592};
2815e61f 11593
d62a17ae 11594struct bgp_table_stats {
11595 struct bgp_table *table;
11596 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 11597 double total_space;
ff7924f6
PJ
11598};
11599
a636c635
DW
11600#if 0
11601#define TALLY_SIGFIG 100000
11602static unsigned long
11603ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
ff7924f6 11604{
a636c635
DW
11605 unsigned long newtot = (count-1) * oldavg + (newval * TALLY_SIGFIG);
11606 unsigned long res = (newtot * TALLY_SIGFIG) / count;
11607 unsigned long ret = newtot / count;
07d0c4ed 11608
a636c635
DW
11609 if ((res % TALLY_SIGFIG) > (TALLY_SIGFIG/2))
11610 return ret + 1;
11611 else
11612 return ret;
11613}
11614#endif
ff7924f6 11615
9bcb3eef 11616static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 11617 struct bgp_table_stats *ts, unsigned int space)
2815e61f 11618{
9bcb3eef 11619 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 11620 struct bgp_path_info *pi;
b54892e0 11621 const struct prefix *rn_p;
d62a17ae 11622
9bcb3eef 11623 if (dest == top)
9c14ec72 11624 return;
d62a17ae 11625
9bcb3eef 11626 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 11627 return;
d62a17ae 11628
9bcb3eef 11629 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 11630 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 11631 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 11632
a636c635
DW
11633#if 0
11634 ts->counts[BGP_STATS_AVGPLEN]
11635 = ravg_tally (ts->counts[BGP_STATS_PREFIXES],
11636 ts->counts[BGP_STATS_AVGPLEN],
b54892e0 11637 rn_p->prefixlen);
a636c635 11638#endif
d62a17ae 11639
9c14ec72 11640 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
11641 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
11642 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 11643
9bcb3eef 11644 if (pdest == NULL || pdest == top) {
9c14ec72
RW
11645 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
11646 /* announced address space */
11647 if (space)
b54892e0 11648 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 11649 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 11650 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 11651
9c14ec72 11652
9bcb3eef 11653 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
11654 ts->counts[BGP_STATS_RIB]++;
11655
05864da7
DS
11656 if (CHECK_FLAG(pi->attr->flag,
11657 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
11658 ts->counts[BGP_STATS_AGGREGATES]++;
11659
11660 /* as-path stats */
05864da7 11661 if (pi->attr->aspath) {
9c14ec72
RW
11662 unsigned int hops = aspath_count_hops(pi->attr->aspath);
11663 unsigned int size = aspath_size(pi->attr->aspath);
11664 as_t highest = aspath_highest(pi->attr->aspath);
11665
11666 ts->counts[BGP_STATS_ASPATH_COUNT]++;
11667
11668 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
11669 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
11670
11671 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
11672 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
11673
11674 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
11675 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
a636c635 11676#if 0
07d0c4ed 11677 ts->counts[BGP_STATS_ASPATH_AVGHOPS]
a636c635
DW
11678 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11679 ts->counts[BGP_STATS_ASPATH_AVGHOPS],
11680 hops);
11681 ts->counts[BGP_STATS_ASPATH_AVGSIZE]
11682 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
11683 ts->counts[BGP_STATS_ASPATH_AVGSIZE],
11684 size);
11685#endif
9c14ec72
RW
11686 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
11687 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
11688 }
11689 }
11690}
11691
11692static int bgp_table_stats_walker(struct thread *t)
11693{
9bcb3eef
DS
11694 struct bgp_dest *dest, *ndest;
11695 struct bgp_dest *top;
9c14ec72
RW
11696 struct bgp_table_stats *ts = THREAD_ARG(t);
11697 unsigned int space = 0;
11698
11699 if (!(top = bgp_table_top(ts->table)))
11700 return 0;
11701
11702 switch (ts->table->afi) {
11703 case AFI_IP:
11704 space = IPV4_MAX_BITLEN;
11705 break;
11706 case AFI_IP6:
11707 space = IPV6_MAX_BITLEN;
11708 break;
11709 default:
11710 return 0;
11711 }
11712
11713 ts->counts[BGP_STATS_MAXBITLEN] = space;
11714
9bcb3eef 11715 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
11716 if (ts->table->safi == SAFI_MPLS_VPN
11717 || ts->table->safi == SAFI_ENCAP
11718 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
11719 struct bgp_table *table;
11720
9bcb3eef 11721 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
11722 if (!table)
11723 continue;
11724
11725 top = bgp_table_top(table);
9bcb3eef
DS
11726 for (ndest = bgp_table_top(table); ndest;
11727 ndest = bgp_route_next(ndest))
11728 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 11729 } else {
9bcb3eef 11730 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 11731 }
11732 }
9c14ec72 11733
d62a17ae 11734 return 0;
2815e61f 11735}
ff7924f6 11736
71f1613a
DA
11737static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
11738 struct json_object *json_array)
11739{
11740 struct listnode *node, *nnode;
11741 struct bgp *bgp;
11742
11743 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
11744 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
11745}
11746
11747static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11748 safi_t safi, struct json_object *json_array)
2815e61f 11749{
d62a17ae 11750 struct bgp_table_stats ts;
11751 unsigned int i;
893cccd0
PG
11752 int ret = CMD_SUCCESS;
11753 char temp_buf[20];
6c9d22e2
PG
11754 struct json_object *json = NULL;
11755
11756 if (json_array)
11757 json = json_object_new_object();
019386c2 11758
d62a17ae 11759 if (!bgp->rib[afi][safi]) {
893cccd0
PG
11760 char warning_msg[50];
11761
11762 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
11763 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
11764 safi);
6c9d22e2
PG
11765
11766 if (!json)
893cccd0
PG
11767 vty_out(vty, "%s\n", warning_msg);
11768 else
9ab0cf58 11769 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 11770
893cccd0
PG
11771 ret = CMD_WARNING;
11772 goto end_table_stats;
d62a17ae 11773 }
019386c2 11774
893cccd0 11775 if (!json)
5290ceab
DA
11776 vty_out(vty, "BGP %s RIB statistics (%s)\n",
11777 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
11778 else
11779 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 11780
d62a17ae 11781 /* labeled-unicast routes live in the unicast table */
11782 if (safi == SAFI_LABELED_UNICAST)
11783 safi = SAFI_UNICAST;
019386c2 11784
d62a17ae 11785 memset(&ts, 0, sizeof(ts));
11786 ts.table = bgp->rib[afi][safi];
11787 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 11788
d62a17ae 11789 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
11790 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
11791 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 11792 continue;
11793
11794 switch (i) {
a636c635
DW
11795#if 0
11796 case BGP_STATS_ASPATH_AVGHOPS:
11797 case BGP_STATS_ASPATH_AVGSIZE:
11798 case BGP_STATS_AVGPLEN:
11799 vty_out (vty, "%-30s: ", table_stats_strs[i]);
11800 vty_out (vty, "%12.2f",
11801 (float)ts.counts[i] / (float)TALLY_SIGFIG);
11802 break;
11803#endif
d62a17ae 11804 case BGP_STATS_ASPATH_TOTHOPS:
11805 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 11806 if (!json) {
9ab0cf58
PG
11807 snprintf(
11808 temp_buf, sizeof(temp_buf), "%12.2f",
11809 ts.counts[i]
11810 ? (float)ts.counts[i]
11811 / (float)ts.counts
11812 [BGP_STATS_ASPATH_COUNT]
11813 : 0);
893cccd0 11814 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11815 table_stats_strs[i]
11816 [TABLE_STATS_IDX_VTY],
893cccd0 11817 temp_buf);
9ab0cf58
PG
11818 } else {
11819 json_object_double_add(
11820 json,
11821 table_stats_strs[i]
11822 [TABLE_STATS_IDX_JSON],
11823 ts.counts[i]
11824 ? (double)ts.counts[i]
11825 / (double)ts.counts
d62a17ae 11826 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
11827 : 0);
11828 }
d62a17ae 11829 break;
11830 case BGP_STATS_TOTPLEN:
6c9d22e2 11831 if (!json) {
9ab0cf58
PG
11832 snprintf(
11833 temp_buf, sizeof(temp_buf), "%12.2f",
11834 ts.counts[i]
11835 ? (float)ts.counts[i]
11836 / (float)ts.counts
11837 [BGP_STATS_PREFIXES]
11838 : 0);
893cccd0 11839 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11840 table_stats_strs[i]
11841 [TABLE_STATS_IDX_VTY],
893cccd0 11842 temp_buf);
9ab0cf58
PG
11843 } else {
11844 json_object_double_add(
11845 json,
11846 table_stats_strs[i]
11847 [TABLE_STATS_IDX_JSON],
11848 ts.counts[i]
11849 ? (double)ts.counts[i]
11850 / (double)ts.counts
d62a17ae 11851 [BGP_STATS_PREFIXES]
9ab0cf58
PG
11852 : 0);
11853 }
d62a17ae 11854 break;
11855 case BGP_STATS_SPACE:
6c9d22e2
PG
11856 if (!json) {
11857 snprintf(temp_buf, sizeof(temp_buf), "%12g",
11858 ts.total_space);
893cccd0 11859 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
11860 table_stats_strs[i]
11861 [TABLE_STATS_IDX_VTY],
893cccd0 11862 temp_buf);
9ab0cf58
PG
11863 } else {
11864 json_object_double_add(
11865 json,
11866 table_stats_strs[i]
11867 [TABLE_STATS_IDX_JSON],
11868 (double)ts.total_space);
11869 }
8d0ab76d 11870 if (afi == AFI_IP6) {
6c9d22e2
PG
11871 if (!json) {
11872 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11873 "%12g",
11874 ts.total_space
11875 * pow(2.0, -128 + 32));
6c9d22e2
PG
11876 vty_out(vty, "%30s: %s\n",
11877 "/32 equivalent %s\n",
11878 temp_buf);
9ab0cf58
PG
11879 } else {
11880 json_object_double_add(
11881 json, "/32equivalent",
11882 (double)(ts.total_space
11883 * pow(2.0,
11884 -128 + 32)));
11885 }
6c9d22e2
PG
11886 if (!json) {
11887 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
11888 "%12g",
11889 ts.total_space
11890 * pow(2.0, -128 + 48));
6c9d22e2
PG
11891 vty_out(vty, "%30s: %s\n",
11892 "/48 equivalent %s\n",
11893 temp_buf);
9ab0cf58
PG
11894 } else {
11895 json_object_double_add(
11896 json, "/48equivalent",
11897 (double)(ts.total_space
11898 * pow(2.0,
11899 -128 + 48)));
11900 }
8d0ab76d 11901 } else {
6c9d22e2
PG
11902 if (!json) {
11903 snprintf(temp_buf, sizeof(temp_buf),
11904 "%12.2f",
9ab0cf58
PG
11905 ts.total_space * 100.
11906 * pow(2.0, -32));
6c9d22e2 11907 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11908 "% announced ", temp_buf);
11909 } else {
11910 json_object_double_add(
11911 json, "%announced",
11912 (double)(ts.total_space * 100.
11913 * pow(2.0, -32)));
11914 }
6c9d22e2
PG
11915 if (!json) {
11916 snprintf(temp_buf, sizeof(temp_buf),
11917 "%12.2f",
9ab0cf58
PG
11918 ts.total_space
11919 * pow(2.0, -32 + 8));
6c9d22e2
PG
11920 vty_out(vty, "%30s: %s\n",
11921 "/8 equivalent ", temp_buf);
9ab0cf58
PG
11922 } else {
11923 json_object_double_add(
11924 json, "/8equivalent",
11925 (double)(ts.total_space
11926 * pow(2.0, -32 + 8)));
11927 }
6c9d22e2
PG
11928 if (!json) {
11929 snprintf(temp_buf, sizeof(temp_buf),
11930 "%12.2f",
9ab0cf58
PG
11931 ts.total_space
11932 * pow(2.0, -32 + 24));
6c9d22e2 11933 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
11934 "/24 equivalent ", temp_buf);
11935 } else {
11936 json_object_double_add(
11937 json, "/24equivalent",
11938 (double)(ts.total_space
11939 * pow(2.0, -32 + 24)));
11940 }
8d0ab76d 11941 }
d62a17ae 11942 break;
11943 default:
6c9d22e2
PG
11944 if (!json) {
11945 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
11946 ts.counts[i]);
893cccd0 11947 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
11948 table_stats_strs[i]
11949 [TABLE_STATS_IDX_VTY],
11950 temp_buf);
11951 } else {
11952 json_object_int_add(
11953 json,
11954 table_stats_strs[i]
11955 [TABLE_STATS_IDX_JSON],
11956 ts.counts[i]);
11957 }
d62a17ae 11958 }
893cccd0
PG
11959 if (!json)
11960 vty_out(vty, "\n");
d62a17ae 11961 }
9ab0cf58 11962end_table_stats:
6c9d22e2
PG
11963 if (json)
11964 json_object_array_add(json_array, json);
893cccd0 11965 return ret;
d62a17ae 11966}
11967
71f1613a
DA
11968static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
11969 safi_t safi, struct json_object *json_array)
11970{
11971 if (!bgp) {
11972 bgp_table_stats_all(vty, afi, safi, json_array);
11973 return CMD_SUCCESS;
11974 }
11975
11976 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
11977}
11978
d62a17ae 11979enum bgp_pcounts {
11980 PCOUNT_ADJ_IN = 0,
11981 PCOUNT_DAMPED,
11982 PCOUNT_REMOVED,
11983 PCOUNT_HISTORY,
11984 PCOUNT_STALE,
11985 PCOUNT_VALID,
11986 PCOUNT_ALL,
11987 PCOUNT_COUNTED,
7e3d9632 11988 PCOUNT_BPATH_SELECTED,
d62a17ae 11989 PCOUNT_PFCNT, /* the figure we display to users */
11990 PCOUNT_MAX,
a636c635 11991};
718e3744 11992
2b64873d 11993static const char *const pcount_strs[] = {
9d303b37
DL
11994 [PCOUNT_ADJ_IN] = "Adj-in",
11995 [PCOUNT_DAMPED] = "Damped",
11996 [PCOUNT_REMOVED] = "Removed",
11997 [PCOUNT_HISTORY] = "History",
11998 [PCOUNT_STALE] = "Stale",
11999 [PCOUNT_VALID] = "Valid",
12000 [PCOUNT_ALL] = "All RIB",
12001 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12002 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12003 [PCOUNT_PFCNT] = "Useable",
12004 [PCOUNT_MAX] = NULL,
a636c635 12005};
718e3744 12006
d62a17ae 12007struct peer_pcounts {
12008 unsigned int count[PCOUNT_MAX];
12009 const struct peer *peer;
12010 const struct bgp_table *table;
54317cba 12011 safi_t safi;
a636c635 12012};
47fc97cc 12013
9bcb3eef 12014static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12015{
54317cba
JW
12016 const struct bgp_adj_in *ain;
12017 const struct bgp_path_info *pi;
d62a17ae 12018 const struct peer *peer = pc->peer;
12019
54317cba
JW
12020 for (ain = rn->adj_in; ain; ain = ain->next)
12021 if (ain->peer == peer)
12022 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12023
9bcb3eef 12024 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12025
54317cba
JW
12026 if (pi->peer != peer)
12027 continue;
d62a17ae 12028
54317cba 12029 pc->count[PCOUNT_ALL]++;
d62a17ae 12030
54317cba
JW
12031 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12032 pc->count[PCOUNT_DAMPED]++;
12033 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12034 pc->count[PCOUNT_HISTORY]++;
12035 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12036 pc->count[PCOUNT_REMOVED]++;
12037 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12038 pc->count[PCOUNT_STALE]++;
12039 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12040 pc->count[PCOUNT_VALID]++;
12041 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12042 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12043 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12044 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12045
12046 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12047 pc->count[PCOUNT_COUNTED]++;
12048 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12049 flog_err(
12050 EC_LIB_DEVELOPMENT,
12051 "Attempting to count but flags say it is unusable");
12052 } else {
40381db7 12053 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12054 flog_err(
12055 EC_LIB_DEVELOPMENT,
12056 "Not counted but flags say we should");
d62a17ae 12057 }
12058 }
54317cba
JW
12059}
12060
12061static int bgp_peer_count_walker(struct thread *t)
12062{
9bcb3eef 12063 struct bgp_dest *rn, *rm;
54317cba
JW
12064 const struct bgp_table *table;
12065 struct peer_pcounts *pc = THREAD_ARG(t);
12066
12067 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12068 || pc->safi == SAFI_EVPN) {
12069 /* Special handling for 2-level routing tables. */
12070 for (rn = bgp_table_top(pc->table); rn;
12071 rn = bgp_route_next(rn)) {
9bcb3eef 12072 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12073 if (table != NULL)
12074 for (rm = bgp_table_top(table); rm;
12075 rm = bgp_route_next(rm))
12076 bgp_peer_count_proc(rm, pc);
12077 }
12078 } else
12079 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12080 bgp_peer_count_proc(rn, pc);
12081
d62a17ae 12082 return 0;
718e3744 12083}
12084
d62a17ae 12085static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12086 safi_t safi, bool use_json)
856ca177 12087{
d62a17ae 12088 struct peer_pcounts pcounts = {.peer = peer};
12089 unsigned int i;
12090 json_object *json = NULL;
12091 json_object *json_loop = NULL;
856ca177 12092
d62a17ae 12093 if (use_json) {
12094 json = json_object_new_object();
12095 json_loop = json_object_new_object();
12096 }
718e3744 12097
d62a17ae 12098 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12099 || !peer->bgp->rib[afi][safi]) {
12100 if (use_json) {
12101 json_object_string_add(
12102 json, "warning",
12103 "No such neighbor or address family");
12104 vty_out(vty, "%s\n", json_object_to_json_string(json));
12105 json_object_free(json);
12106 } else
12107 vty_out(vty, "%% No such neighbor or address family\n");
12108
12109 return CMD_WARNING;
12110 }
2a71e9ce 12111
d62a17ae 12112 memset(&pcounts, 0, sizeof(pcounts));
12113 pcounts.peer = peer;
12114 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12115 pcounts.safi = safi;
d62a17ae 12116
12117 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12118 * stats for the thread-walk (i.e. ensure this can't be blamed on
12119 * on just vty_read()).
12120 */
d62a17ae 12121 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12122
12123 if (use_json) {
12124 json_object_string_add(json, "prefixCountsFor", peer->host);
12125 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12126 get_afi_safi_str(afi, safi, true));
d62a17ae 12127 json_object_int_add(json, "pfxCounter",
12128 peer->pcount[afi][safi]);
12129
12130 for (i = 0; i < PCOUNT_MAX; i++)
12131 json_object_int_add(json_loop, pcount_strs[i],
12132 pcounts.count[i]);
12133
12134 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12135
12136 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12137 json_object_string_add(json, "pfxctDriftFor",
12138 peer->host);
12139 json_object_string_add(
12140 json, "recommended",
12141 "Please report this bug, with the above command output");
12142 }
996c9314
LB
12143 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12144 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12145 json_object_free(json);
12146 } else {
12147
12148 if (peer->hostname
892fedb6 12149 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12150 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12151 peer->hostname, peer->host,
5cb5f4d0 12152 get_afi_safi_str(afi, safi, false));
d62a17ae 12153 } else {
12154 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12155 get_afi_safi_str(afi, safi, false));
d62a17ae 12156 }
12157
6cde4b45 12158 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12159 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12160
12161 for (i = 0; i < PCOUNT_MAX; i++)
12162 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12163 pcounts.count[i]);
12164
12165 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12166 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12167 vty_out(vty,
12168 "Please report this bug, with the above command output\n");
12169 }
12170 }
12171
12172 return CMD_SUCCESS;
718e3744 12173}
12174
a636c635
DW
12175DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12176 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12177 "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 12178 SHOW_STR
12179 IP_STR
12180 BGP_STR
8386ac43 12181 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12182 BGP_AFI_HELP_STR
12183 BGP_SAFI_HELP_STR
0b16f239
DS
12184 "Detailed information on TCP and BGP neighbor connections\n"
12185 "Neighbor to display information about\n"
12186 "Neighbor to display information about\n"
91d37724 12187 "Neighbor on BGP configured interface\n"
a636c635 12188 "Display detailed prefix count information\n"
9973d184 12189 JSON_STR)
0b16f239 12190{
d62a17ae 12191 afi_t afi = AFI_IP6;
12192 safi_t safi = SAFI_UNICAST;
12193 struct peer *peer;
12194 int idx = 0;
12195 struct bgp *bgp = NULL;
9f049418
DS
12196 bool uj = use_json(argc, argv);
12197
12198 if (uj)
12199 argc--;
856ca177 12200
d62a17ae 12201 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12202 &bgp, uj);
d62a17ae 12203 if (!idx)
12204 return CMD_WARNING;
0b16f239 12205
d62a17ae 12206 argv_find(argv, argc, "neighbors", &idx);
12207 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12208 if (!peer)
12209 return CMD_WARNING;
bb46e94f 12210
29c8d9da 12211 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12212}
0b16f239 12213
d6902373
PG
12214#ifdef KEEP_OLD_VPN_COMMANDS
12215DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12216 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12217 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12218 SHOW_STR
12219 IP_STR
12220 BGP_STR
d6902373 12221 BGP_VPNVX_HELP_STR
91d37724 12222 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12223 "Detailed information on TCP and BGP neighbor connections\n"
12224 "Neighbor to display information about\n"
12225 "Neighbor to display information about\n"
91d37724 12226 "Neighbor on BGP configured interface\n"
a636c635 12227 "Display detailed prefix count information\n"
9973d184 12228 JSON_STR)
a636c635 12229{
d62a17ae 12230 int idx_peer = 6;
12231 struct peer *peer;
9f049418 12232 bool uj = use_json(argc, argv);
a636c635 12233
d62a17ae 12234 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12235 if (!peer)
12236 return CMD_WARNING;
12237
12238 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12239}
12240
d6902373
PG
12241DEFUN (show_ip_bgp_vpn_all_route_prefix,
12242 show_ip_bgp_vpn_all_route_prefix_cmd,
12243 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12244 SHOW_STR
12245 IP_STR
12246 BGP_STR
d6902373 12247 BGP_VPNVX_HELP_STR
91d37724
QY
12248 "Display information about all VPNv4 NLRIs\n"
12249 "Network in the BGP routing table to display\n"
3a2d747c 12250 "Network in the BGP routing table to display\n"
9973d184 12251 JSON_STR)
91d37724 12252{
d62a17ae 12253 int idx = 0;
12254 char *network = NULL;
12255 struct bgp *bgp = bgp_get_default();
12256 if (!bgp) {
12257 vty_out(vty, "Can't find default instance\n");
12258 return CMD_WARNING;
12259 }
87e34b58 12260
d62a17ae 12261 if (argv_find(argv, argc, "A.B.C.D", &idx))
12262 network = argv[idx]->arg;
12263 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12264 network = argv[idx]->arg;
12265 else {
12266 vty_out(vty, "Unable to figure out Network\n");
12267 return CMD_WARNING;
12268 }
87e34b58 12269
d62a17ae 12270 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12271 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12272}
d6902373 12273#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12274
44c69747
LK
12275DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12276 show_bgp_l2vpn_evpn_route_prefix_cmd,
12277 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12278 SHOW_STR
4c63a661
PG
12279 BGP_STR
12280 L2VPN_HELP_STR
12281 EVPN_HELP_STR
44c69747
LK
12282 "Network in the BGP routing table to display\n"
12283 "Network in the BGP routing table to display\n"
4c63a661
PG
12284 "Network in the BGP routing table to display\n"
12285 "Network in the BGP routing table to display\n"
12286 JSON_STR)
12287{
d62a17ae 12288 int idx = 0;
12289 char *network = NULL;
44c69747 12290 int prefix_check = 0;
a636c635 12291
44c69747
LK
12292 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12293 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12294 network = argv[idx]->arg;
44c69747 12295 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12296 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12297 network = argv[idx]->arg;
44c69747
LK
12298 prefix_check = 1;
12299 } else {
d62a17ae 12300 vty_out(vty, "Unable to figure out Network\n");
12301 return CMD_WARNING;
12302 }
44c69747
LK
12303 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
12304 prefix_check, BGP_PATH_SHOW_ALL,
12305 use_json(argc, argv));
d62a17ae 12306}
12307
2f9bc755
DS
12308static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
12309 struct bgp_table *table, int *header1,
12310 int *header2, json_object *json,
12311 json_object *json_scode,
12312 json_object *json_ocode, bool wide)
12313{
12314 uint64_t version = table ? table->version : 0;
12315
12316 if (*header1) {
12317 if (json) {
12318 json_object_int_add(json, "bgpTableVersion", version);
12319 json_object_string_add(json, "bgpLocalRouterId",
12320 inet_ntoa(bgp->router_id));
12321 json_object_int_add(json, "defaultLocPrf",
12322 bgp->default_local_pref);
12323 json_object_int_add(json, "localAS", bgp->as);
12324 json_object_object_add(json, "bgpStatusCodes",
12325 json_scode);
12326 json_object_object_add(json, "bgpOriginCodes",
12327 json_ocode);
12328 } else {
12329 vty_out(vty,
12330 "BGP table version is %" PRIu64 ", local router ID is %s, vrf id ",
12331 version, inet_ntoa(bgp->router_id));
12332 if (bgp->vrf_id == VRF_UNKNOWN)
12333 vty_out(vty, "%s", VRFID_NONE_STR);
12334 else
12335 vty_out(vty, "%u", bgp->vrf_id);
12336 vty_out(vty, "\n");
12337 vty_out(vty, "Default local pref %u, ",
12338 bgp->default_local_pref);
12339 vty_out(vty, "local AS %u\n", bgp->as);
12340 vty_out(vty, BGP_SHOW_SCODE_HEADER);
12341 vty_out(vty, BGP_SHOW_NCODE_HEADER);
12342 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12343 }
12344 *header1 = 0;
12345 }
12346 if (*header2) {
12347 if (!json)
12348 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
12349 : BGP_SHOW_HEADER));
12350 *header2 = 0;
12351 }
12352}
12353
d62a17ae 12354static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12355 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c
MK
12356 const char *rmap_name, json_object *json,
12357 uint8_t show_flags)
d62a17ae 12358{
12359 struct bgp_table *table;
12360 struct bgp_adj_in *ain;
12361 struct bgp_adj_out *adj;
74a630b6
NT
12362 unsigned long output_count = 0;
12363 unsigned long filtered_count = 0;
9bcb3eef 12364 struct bgp_dest *dest;
d62a17ae 12365 int header1 = 1;
12366 struct bgp *bgp;
12367 int header2 = 1;
12368 struct attr attr;
12369 int ret;
12370 struct update_subgroup *subgrp;
12371 json_object *json_scode = NULL;
12372 json_object *json_ocode = NULL;
12373 json_object *json_ar = NULL;
12374 struct peer_af *paf;
f99def61 12375 bool route_filtered;
96f3485c
MK
12376 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12377 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d62a17ae 12378
12379 if (use_json) {
12380 json_scode = json_object_new_object();
12381 json_ocode = json_object_new_object();
12382 json_ar = json_object_new_object();
12383
12384 json_object_string_add(json_scode, "suppressed", "s");
12385 json_object_string_add(json_scode, "damped", "d");
12386 json_object_string_add(json_scode, "history", "h");
12387 json_object_string_add(json_scode, "valid", "*");
12388 json_object_string_add(json_scode, "best", ">");
12389 json_object_string_add(json_scode, "multipath", "=");
12390 json_object_string_add(json_scode, "internal", "i");
12391 json_object_string_add(json_scode, "ribFailure", "r");
12392 json_object_string_add(json_scode, "stale", "S");
12393 json_object_string_add(json_scode, "removed", "R");
12394
12395 json_object_string_add(json_ocode, "igp", "i");
12396 json_object_string_add(json_ocode, "egp", "e");
12397 json_object_string_add(json_ocode, "incomplete", "?");
12398 }
a636c635 12399
d62a17ae 12400 bgp = peer->bgp;
a636c635 12401
d62a17ae 12402 if (!bgp) {
12403 if (use_json) {
12404 json_object_string_add(json, "alert", "no BGP");
12405 vty_out(vty, "%s\n", json_object_to_json_string(json));
12406 json_object_free(json);
12407 } else
12408 vty_out(vty, "%% No bgp\n");
12409 return;
12410 }
a636c635 12411
c512a642
EDP
12412 /* labeled-unicast routes live in the unicast table */
12413 if (safi == SAFI_LABELED_UNICAST)
12414 table = bgp->rib[afi][SAFI_UNICAST];
12415 else
12416 table = bgp->rib[afi][safi];
d62a17ae 12417
12418 output_count = filtered_count = 0;
12419 subgrp = peer_subgroup(peer, afi, safi);
12420
6392aaa6 12421 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 12422 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
12423 if (use_json) {
12424 json_object_int_add(json, "bgpTableVersion",
12425 table->version);
12426 json_object_string_add(json, "bgpLocalRouterId",
12427 inet_ntoa(bgp->router_id));
01eced22
AD
12428 json_object_int_add(json, "defaultLocPrf",
12429 bgp->default_local_pref);
12430 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 12431 json_object_object_add(json, "bgpStatusCodes",
12432 json_scode);
12433 json_object_object_add(json, "bgpOriginCodes",
12434 json_ocode);
07d0c4ed
DA
12435 json_object_string_add(
12436 json, "bgpOriginatingDefaultNetwork",
12437 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12438 } else {
6cde4b45 12439 vty_out(vty, "BGP table version is %" PRIu64", local router ID is %s, vrf id ",
d62a17ae 12440 table->version, inet_ntoa(bgp->router_id));
9df8b37c
PZ
12441 if (bgp->vrf_id == VRF_UNKNOWN)
12442 vty_out(vty, "%s", VRFID_NONE_STR);
12443 else
12444 vty_out(vty, "%u", bgp->vrf_id);
12445 vty_out(vty, "\n");
01eced22
AD
12446 vty_out(vty, "Default local pref %u, ",
12447 bgp->default_local_pref);
12448 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 12449 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 12450 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 12451 vty_out(vty, BGP_SHOW_OCODE_HEADER);
12452
07d0c4ed
DA
12453 vty_out(vty, "Originating default network %s\n\n",
12454 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 12455 }
12456 header1 = 0;
12457 }
a636c635 12458
9bcb3eef 12459 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
12460 if (type == bgp_show_adj_route_received
12461 || type == bgp_show_adj_route_filtered) {
9bcb3eef 12462 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 12463 if (ain->peer != peer)
ea47320b 12464 continue;
6392aaa6 12465
2f9bc755
DS
12466 show_adj_route_header(
12467 vty, bgp, table, &header1, &header2,
12468 json, json_scode, json_ocode, wide);
6392aaa6 12469
6f4f49b2 12470 attr = *ain->attr;
f99def61
AD
12471 route_filtered = false;
12472
12473 /* Filter prefix using distribute list,
12474 * filter list or prefix list
12475 */
b54892e0 12476 const struct prefix *rn_p =
9bcb3eef 12477 bgp_dest_get_prefix(dest);
b54892e0
DS
12478 if ((bgp_input_filter(peer, rn_p, &attr, afi,
12479 safi))
12480 == FILTER_DENY)
f99def61
AD
12481 route_filtered = true;
12482
12483 /* Filter prefix using route-map */
b54892e0
DS
12484 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
12485 safi, rmap_name, NULL,
12486 0, NULL);
6392aaa6 12487
13c8e163
AD
12488 if (type == bgp_show_adj_route_filtered &&
12489 !route_filtered && ret != RMAP_DENY) {
b755861b 12490 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12491 continue;
d62a17ae 12492 }
6392aaa6 12493
13c8e163
AD
12494 if (type == bgp_show_adj_route_received &&
12495 (route_filtered || ret == RMAP_DENY))
6392aaa6
PM
12496 filtered_count++;
12497
b54892e0 12498 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 12499 use_json, json_ar, wide);
b755861b 12500 bgp_attr_undup(&attr, ain->attr);
6392aaa6 12501 output_count++;
d62a17ae 12502 }
6392aaa6 12503 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 12504 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 12505 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 12506 if (paf->peer != peer || !adj->attr)
924c3f6a 12507 continue;
d62a17ae 12508
2f9bc755
DS
12509 show_adj_route_header(
12510 vty, bgp, table, &header1,
12511 &header2, json, json_scode,
12512 json_ocode, wide);
d62a17ae 12513
b54892e0 12514 const struct prefix *rn_p =
9bcb3eef 12515 bgp_dest_get_prefix(dest);
b54892e0 12516
6f4f49b2 12517 attr = *adj->attr;
b755861b 12518 ret = bgp_output_modifier(
b54892e0 12519 peer, rn_p, &attr, afi, safi,
b755861b 12520 rmap_name);
f46d8e1e 12521
b755861b 12522 if (ret != RMAP_DENY) {
b54892e0
DS
12523 route_vty_out_tmp(
12524 vty, rn_p, &attr, safi,
ae248832
MK
12525 use_json, json_ar,
12526 wide);
b755861b
PM
12527 output_count++;
12528 } else {
12529 filtered_count++;
a2addae8 12530 }
b755861b
PM
12531
12532 bgp_attr_undup(&attr, adj->attr);
924c3f6a 12533 }
f20ce998
DS
12534 } else if (type == bgp_show_adj_route_bestpath) {
12535 struct bgp_path_info *pi;
12536
12537 show_adj_route_header(vty, bgp, table, &header1,
12538 &header2, json, json_scode,
12539 json_ocode, wide);
12540
12541 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
12542 pi = pi->next) {
12543 if (pi->peer != peer)
12544 continue;
12545
12546 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12547 continue;
12548
12549 route_vty_out_tmp(vty,
12550 bgp_dest_get_prefix(dest),
12551 pi->attr, safi, use_json,
12552 json_ar, wide);
12553 output_count++;
12554 }
d62a17ae 12555 }
12556 }
d62a17ae 12557
d62a17ae 12558 if (use_json) {
6392aaa6
PM
12559 json_object_object_add(json, "advertisedRoutes", json_ar);
12560 json_object_int_add(json, "totalPrefixCounter", output_count);
12561 json_object_int_add(json, "filteredPrefixCounter",
12562 filtered_count);
12563
996c9314
LB
12564 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12565 json, JSON_C_TO_STRING_PRETTY));
74a630b6
NT
12566
12567 if (!output_count && !filtered_count) {
12568 json_object_free(json_scode);
12569 json_object_free(json_ocode);
12570 }
12571
d62a17ae 12572 json_object_free(json);
6392aaa6
PM
12573 } else if (output_count > 0) {
12574 if (filtered_count > 0)
12575 vty_out(vty,
12576 "\nTotal number of prefixes %ld (%ld filtered)\n",
12577 output_count, filtered_count);
12578 else
12579 vty_out(vty, "\nTotal number of prefixes %ld\n",
12580 output_count);
d62a17ae 12581 }
a636c635 12582}
2a71e9ce 12583
d62a17ae 12584static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 12585 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 12586 const char *rmap_name, uint8_t show_flags)
0b16f239 12587{
d62a17ae 12588 json_object *json = NULL;
96f3485c 12589 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 12590
d62a17ae 12591 if (use_json)
12592 json = json_object_new_object();
0b16f239 12593
d62a17ae 12594 if (!peer || !peer->afc[afi][safi]) {
12595 if (use_json) {
12596 json_object_string_add(
12597 json, "warning",
12598 "No such neighbor or address family");
12599 vty_out(vty, "%s\n", json_object_to_json_string(json));
12600 json_object_free(json);
12601 } else
12602 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 12603
d62a17ae 12604 return CMD_WARNING;
12605 }
12606
6392aaa6
PM
12607 if ((type == bgp_show_adj_route_received
12608 || type == bgp_show_adj_route_filtered)
d62a17ae 12609 && !CHECK_FLAG(peer->af_flags[afi][safi],
12610 PEER_FLAG_SOFT_RECONFIG)) {
12611 if (use_json) {
12612 json_object_string_add(
12613 json, "warning",
12614 "Inbound soft reconfiguration not enabled");
12615 vty_out(vty, "%s\n", json_object_to_json_string(json));
12616 json_object_free(json);
12617 } else
12618 vty_out(vty,
12619 "%% Inbound soft reconfiguration not enabled\n");
12620
12621 return CMD_WARNING;
12622 }
0b16f239 12623
96f3485c 12624 show_adj_route(vty, peer, afi, safi, type, rmap_name, json, show_flags);
0b16f239 12625
d62a17ae 12626 return CMD_SUCCESS;
a636c635 12627}
50ef26d4 12628
f20ce998
DS
12629DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
12630 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
12631 "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]",
12632 SHOW_STR
12633 IP_STR
12634 BGP_STR
12635 BGP_INSTANCE_HELP_STR
12636 BGP_AFI_HELP_STR
12637 BGP_SAFI_WITH_LABEL_HELP_STR
12638 "Detailed information on TCP and BGP neighbor connections\n"
12639 "Neighbor to display information about\n"
12640 "Neighbor to display information about\n"
12641 "Neighbor on BGP configured interface\n"
12642 "Display the routes selected by best path\n"
12643 JSON_STR
12644 "Increase table width for longer prefixes\n")
12645{
12646 afi_t afi = AFI_IP6;
12647 safi_t safi = SAFI_UNICAST;
12648 char *rmap_name = NULL;
12649 char *peerstr = NULL;
12650 struct bgp *bgp = NULL;
12651 struct peer *peer;
12652 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
12653 int idx = 0;
96f3485c
MK
12654 uint8_t show_flags = 0;
12655
12656 if (uj)
12657 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12658
12659 if (wide)
12660 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
12661
12662 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12663 &bgp, uj);
12664
12665 if (!idx)
12666 return CMD_WARNING;
12667
12668 argv_find(argv, argc, "neighbors", &idx);
12669 peerstr = argv[++idx]->arg;
12670
12671 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12672 if (!peer)
12673 return CMD_WARNING;
12674
96f3485c
MK
12675 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12676 show_flags);
f20ce998
DS
12677}
12678
ae248832 12679DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 12680 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 12681 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map WORD] [json$uj | wide$wide]",
718e3744 12682 SHOW_STR
12683 IP_STR
12684 BGP_STR
a636c635 12685 BGP_INSTANCE_HELP_STR
7395a2c9 12686 BGP_AFI_HELP_STR
4dd6177e 12687 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12688 "Display the entries for all address families\n"
718e3744 12689 "Detailed information on TCP and BGP neighbor connections\n"
12690 "Neighbor to display information about\n"
12691 "Neighbor to display information about\n"
91d37724 12692 "Neighbor on BGP configured interface\n"
a636c635 12693 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
12694 "Display the received routes from neighbor\n"
12695 "Display the filtered routes received from neighbor\n"
a636c635
DW
12696 "Route-map to modify the attributes\n"
12697 "Name of the route map\n"
ae248832
MK
12698 JSON_STR
12699 "Increase table width for longer prefixes\n")
718e3744 12700{
d62a17ae 12701 afi_t afi = AFI_IP6;
12702 safi_t safi = SAFI_UNICAST;
12703 char *rmap_name = NULL;
12704 char *peerstr = NULL;
d62a17ae 12705 struct bgp *bgp = NULL;
12706 struct peer *peer;
6392aaa6 12707 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 12708 int idx = 0;
96f3485c
MK
12709 bool first = true;
12710 uint8_t show_flags = 0;
6392aaa6 12711
96f3485c 12712 if (uj) {
d62a17ae 12713 argc--;
96f3485c
MK
12714 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12715 }
12716
12717 if (all) {
12718 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12719 if (argv_find(argv, argc, "ipv4", &idx))
12720 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12721
12722 if (argv_find(argv, argc, "ipv6", &idx))
12723 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12724 }
12725
12726 if (wide)
12727 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 12728
9f049418
DS
12729 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12730 &bgp, uj);
12731 if (!idx)
12732 return CMD_WARNING;
12733
d62a17ae 12734 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12735 argv_find(argv, argc, "neighbors", &idx);
12736 peerstr = argv[++idx]->arg;
8c3deaae 12737
d62a17ae 12738 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
12739 if (!peer)
12740 return CMD_WARNING;
856ca177 12741
d62a17ae 12742 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
12743 type = bgp_show_adj_route_advertised;
12744 else if (argv_find(argv, argc, "received-routes", &idx))
12745 type = bgp_show_adj_route_received;
12746 else if (argv_find(argv, argc, "filtered-routes", &idx))
12747 type = bgp_show_adj_route_filtered;
12748
d62a17ae 12749 if (argv_find(argv, argc, "route-map", &idx))
12750 rmap_name = argv[++idx]->arg;
95cbbd2a 12751
96f3485c
MK
12752 if (!all)
12753 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12754 show_flags);
12755 if (uj)
12756 vty_out(vty, "{\n");
12757
12758 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12759 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12760 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
12761 : AFI_IP6;
12762 FOREACH_SAFI (safi) {
12763 if (strmatch(get_afi_safi_str(afi, safi, true),
12764 "Unknown"))
12765 continue;
12766
12767 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12768 continue;
12769
12770 if (uj) {
12771 if (first)
12772 first = false;
12773 else
12774 vty_out(vty, ",\n");
12775 vty_out(vty, "\"%s\":",
12776 get_afi_safi_str(afi, safi, true));
12777 } else
12778 vty_out(vty, "\nFor address family: %s\n",
12779 get_afi_safi_str(afi, safi, false));
12780
12781 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12782 show_flags);
12783 }
12784 } else {
12785 FOREACH_AFI_SAFI (afi, safi) {
12786 if (strmatch(get_afi_safi_str(afi, safi, true),
12787 "Unknown"))
12788 continue;
12789
12790 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12791 continue;
12792
12793 if (uj) {
12794 if (first)
12795 first = false;
12796 else
12797 vty_out(vty, ",\n");
12798 vty_out(vty, "\"%s\":",
12799 get_afi_safi_str(afi, safi, true));
12800 } else
12801 vty_out(vty, "\nFor address family: %s\n",
12802 get_afi_safi_str(afi, safi, false));
12803
12804 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
12805 show_flags);
12806 }
12807 }
12808 if (uj)
12809 vty_out(vty, "}\n");
12810
12811 return CMD_SUCCESS;
95cbbd2a
ML
12812}
12813
718e3744 12814DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
12815 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 12816 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 12817 SHOW_STR
12818 IP_STR
12819 BGP_STR
8c3deaae
QY
12820 "Address Family\n"
12821 "Address Family\n"
718e3744 12822 "Address Family modifier\n"
12823 "Detailed information on TCP and BGP neighbor connections\n"
12824 "Neighbor to display information about\n"
12825 "Neighbor to display information about\n"
91d37724 12826 "Neighbor on BGP configured interface\n"
718e3744 12827 "Display information received from a BGP neighbor\n"
856ca177 12828 "Display the prefixlist filter\n"
9973d184 12829 JSON_STR)
718e3744 12830{
d62a17ae 12831 afi_t afi = AFI_IP6;
12832 safi_t safi = SAFI_UNICAST;
12833 char *peerstr = NULL;
12834
12835 char name[BUFSIZ];
12836 union sockunion su;
12837 struct peer *peer;
12838 int count, ret;
12839
12840 int idx = 0;
12841
12842 /* show [ip] bgp */
12843 if (argv_find(argv, argc, "ip", &idx))
12844 afi = AFI_IP;
12845 /* [<ipv4|ipv6> [unicast]] */
12846 if (argv_find(argv, argc, "ipv4", &idx))
12847 afi = AFI_IP;
12848 if (argv_find(argv, argc, "ipv6", &idx))
12849 afi = AFI_IP6;
12850 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12851 argv_find(argv, argc, "neighbors", &idx);
12852 peerstr = argv[++idx]->arg;
12853
9f049418 12854 bool uj = use_json(argc, argv);
d62a17ae 12855
12856 ret = str2sockunion(peerstr, &su);
12857 if (ret < 0) {
12858 peer = peer_lookup_by_conf_if(NULL, peerstr);
12859 if (!peer) {
12860 if (uj)
12861 vty_out(vty, "{}\n");
12862 else
12863 vty_out(vty,
12864 "%% Malformed address or name: %s\n",
12865 peerstr);
12866 return CMD_WARNING;
12867 }
12868 } else {
12869 peer = peer_lookup(NULL, &su);
12870 if (!peer) {
12871 if (uj)
12872 vty_out(vty, "{}\n");
12873 else
12874 vty_out(vty, "No peer\n");
12875 return CMD_WARNING;
12876 }
12877 }
718e3744 12878
4ced1a2c 12879 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 12880 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
12881 if (count) {
12882 if (!uj)
12883 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 12884 get_afi_safi_str(afi, safi, false));
d62a17ae 12885 prefix_bgp_show_prefix_list(vty, afi, name, uj);
12886 } else {
12887 if (uj)
12888 vty_out(vty, "{}\n");
12889 else
12890 vty_out(vty, "No functional output\n");
12891 }
718e3744 12892
d62a17ae 12893 return CMD_SUCCESS;
12894}
12895
12896static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
12897 afi_t afi, safi_t safi,
9f049418 12898 enum bgp_show_type type, bool use_json)
d62a17ae 12899{
96f3485c
MK
12900 uint8_t show_flags = 0;
12901
12902 if (use_json)
12903 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12904
8a893163
DW
12905 /* labeled-unicast routes live in the unicast table */
12906 if (safi == SAFI_LABELED_UNICAST)
12907 safi = SAFI_UNICAST;
12908
d62a17ae 12909 if (!peer || !peer->afc[afi][safi]) {
12910 if (use_json) {
12911 json_object *json_no = NULL;
12912 json_no = json_object_new_object();
12913 json_object_string_add(
12914 json_no, "warning",
12915 "No such neighbor or address family");
12916 vty_out(vty, "%s\n",
12917 json_object_to_json_string(json_no));
12918 json_object_free(json_no);
12919 } else
12920 vty_out(vty, "%% No such neighbor or address family\n");
12921 return CMD_WARNING;
12922 }
47fc97cc 12923
96f3485c 12924 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 12925}
12926
dba3c1d3
PG
12927DEFUN (show_ip_bgp_flowspec_routes_detailed,
12928 show_ip_bgp_flowspec_routes_detailed_cmd,
12929 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
12930 SHOW_STR
12931 IP_STR
12932 BGP_STR
12933 BGP_INSTANCE_HELP_STR
12934 BGP_AFI_HELP_STR
12935 "SAFI Flowspec\n"
12936 "Detailed information on flowspec entries\n"
12937 JSON_STR)
12938{
12939 afi_t afi = AFI_IP;
12940 safi_t safi = SAFI_UNICAST;
12941 struct bgp *bgp = NULL;
12942 int idx = 0;
9f049418 12943 bool uj = use_json(argc, argv);
96f3485c 12944 uint8_t show_flags = 0;
9f049418 12945
96f3485c 12946 if (uj) {
9f049418 12947 argc--;
96f3485c
MK
12948 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12949 }
dba3c1d3
PG
12950
12951 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12952 &bgp, uj);
dba3c1d3
PG
12953 if (!idx)
12954 return CMD_WARNING;
12955
96f3485c
MK
12956 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
12957 show_flags);
dba3c1d3
PG
12958}
12959
718e3744 12960DEFUN (show_ip_bgp_neighbor_routes,
12961 show_ip_bgp_neighbor_routes_cmd,
3efd0893 12962 "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 12963 SHOW_STR
12964 IP_STR
12965 BGP_STR
8386ac43 12966 BGP_INSTANCE_HELP_STR
4f280b15 12967 BGP_AFI_HELP_STR
4dd6177e 12968 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 12969 "Detailed information on TCP and BGP neighbor connections\n"
12970 "Neighbor to display information about\n"
12971 "Neighbor to display information about\n"
91d37724 12972 "Neighbor on BGP configured interface\n"
2525cf39 12973 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
12974 "Display the dampened routes received from neighbor\n"
12975 "Display routes learned from neighbor\n"
9973d184 12976 JSON_STR)
718e3744 12977{
d62a17ae 12978 char *peerstr = NULL;
12979 struct bgp *bgp = NULL;
12980 afi_t afi = AFI_IP6;
12981 safi_t safi = SAFI_UNICAST;
12982 struct peer *peer;
12983 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 12984 int idx = 0;
9f049418
DS
12985 bool uj = use_json(argc, argv);
12986
12987 if (uj)
12988 argc--;
bb46e94f 12989
d62a17ae 12990 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12991 &bgp, uj);
d62a17ae 12992 if (!idx)
12993 return CMD_WARNING;
c493f2d8 12994
d62a17ae 12995 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
12996 argv_find(argv, argc, "neighbors", &idx);
12997 peerstr = argv[++idx]->arg;
8c3deaae 12998
d62a17ae 12999 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13000 if (!peer)
d62a17ae 13001 return CMD_WARNING;
bb46e94f 13002
d62a17ae 13003 if (argv_find(argv, argc, "flap-statistics", &idx))
13004 sh_type = bgp_show_type_flap_neighbor;
13005 else if (argv_find(argv, argc, "dampened-routes", &idx))
13006 sh_type = bgp_show_type_damp_neighbor;
13007 else if (argv_find(argv, argc, "routes", &idx))
13008 sh_type = bgp_show_type_neighbor;
2525cf39 13009
d62a17ae 13010 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13011}
6b0655a2 13012
734b349e 13013struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13014
d62a17ae 13015struct bgp_distance {
13016 /* Distance value for the IP source prefix. */
d7c0a89a 13017 uint8_t distance;
718e3744 13018
d62a17ae 13019 /* Name of the access-list to be matched. */
13020 char *access_list;
718e3744 13021};
13022
4f280b15
LB
13023DEFUN (show_bgp_afi_vpn_rd_route,
13024 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13025 "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
13026 SHOW_STR
13027 BGP_STR
13028 BGP_AFI_HELP_STR
13029 "Address Family modifier\n"
13030 "Display information for a route distinguisher\n"
13031 "Route Distinguisher\n"
7395a2c9
DS
13032 "Network in the BGP routing table to display\n"
13033 "Network in the BGP routing table to display\n"
13034 JSON_STR)
4f280b15 13035{
d62a17ae 13036 int ret;
13037 struct prefix_rd prd;
13038 afi_t afi = AFI_MAX;
13039 int idx = 0;
4f280b15 13040
ff6566f3
DS
13041 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13042 vty_out(vty, "%% Malformed Address Family\n");
13043 return CMD_WARNING;
13044 }
13045
d62a17ae 13046 ret = str2prefix_rd(argv[5]->arg, &prd);
13047 if (!ret) {
13048 vty_out(vty, "%% Malformed Route Distinguisher\n");
13049 return CMD_WARNING;
13050 }
ff6566f3 13051
d62a17ae 13052 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13053 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13054}
13055
d62a17ae 13056static struct bgp_distance *bgp_distance_new(void)
718e3744 13057{
d62a17ae 13058 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13059}
13060
d62a17ae 13061static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13062{
d62a17ae 13063 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13064}
13065
d62a17ae 13066static int bgp_distance_set(struct vty *vty, const char *distance_str,
13067 const char *ip_str, const char *access_list_str)
718e3744 13068{
d62a17ae 13069 int ret;
13070 afi_t afi;
13071 safi_t safi;
13072 struct prefix p;
d7c0a89a 13073 uint8_t distance;
9bcb3eef 13074 struct bgp_dest *dest;
d62a17ae 13075 struct bgp_distance *bdistance;
718e3744 13076
d62a17ae 13077 afi = bgp_node_afi(vty);
13078 safi = bgp_node_safi(vty);
734b349e 13079
d62a17ae 13080 ret = str2prefix(ip_str, &p);
13081 if (ret == 0) {
13082 vty_out(vty, "Malformed prefix\n");
13083 return CMD_WARNING_CONFIG_FAILED;
13084 }
718e3744 13085
d62a17ae 13086 distance = atoi(distance_str);
718e3744 13087
d62a17ae 13088 /* Get BGP distance node. */
9bcb3eef
DS
13089 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13090 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13091 if (bdistance)
9bcb3eef 13092 bgp_dest_unlock_node(dest);
ca2e160d 13093 else {
d62a17ae 13094 bdistance = bgp_distance_new();
9bcb3eef 13095 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13096 }
718e3744 13097
d62a17ae 13098 /* Set distance value. */
13099 bdistance->distance = distance;
718e3744 13100
d62a17ae 13101 /* Reset access-list configuration. */
e1b36e13 13102 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13103 if (access_list_str)
13104 bdistance->access_list =
13105 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13106
d62a17ae 13107 return CMD_SUCCESS;
718e3744 13108}
13109
d62a17ae 13110static int bgp_distance_unset(struct vty *vty, const char *distance_str,
13111 const char *ip_str, const char *access_list_str)
718e3744 13112{
d62a17ae 13113 int ret;
13114 afi_t afi;
13115 safi_t safi;
13116 struct prefix p;
13117 int distance;
9bcb3eef 13118 struct bgp_dest *dest;
d62a17ae 13119 struct bgp_distance *bdistance;
718e3744 13120
d62a17ae 13121 afi = bgp_node_afi(vty);
13122 safi = bgp_node_safi(vty);
734b349e 13123
d62a17ae 13124 ret = str2prefix(ip_str, &p);
13125 if (ret == 0) {
13126 vty_out(vty, "Malformed prefix\n");
13127 return CMD_WARNING_CONFIG_FAILED;
13128 }
718e3744 13129
9bcb3eef
DS
13130 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13131 if (!dest) {
d62a17ae 13132 vty_out(vty, "Can't find specified prefix\n");
13133 return CMD_WARNING_CONFIG_FAILED;
13134 }
718e3744 13135
9bcb3eef 13136 bdistance = bgp_dest_get_bgp_distance_info(dest);
d62a17ae 13137 distance = atoi(distance_str);
1f9a9fff 13138
d62a17ae 13139 if (bdistance->distance != distance) {
13140 vty_out(vty, "Distance does not match configured\n");
13141 return CMD_WARNING_CONFIG_FAILED;
13142 }
718e3744 13143
0a22ddfb 13144 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13145 bgp_distance_free(bdistance);
718e3744 13146
9bcb3eef
DS
13147 bgp_dest_set_bgp_path_info(dest, NULL);
13148 bgp_dest_unlock_node(dest);
13149 bgp_dest_unlock_node(dest);
718e3744 13150
d62a17ae 13151 return CMD_SUCCESS;
718e3744 13152}
13153
718e3744 13154/* Apply BGP information to distance method. */
b8685f9b 13155uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13156 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13157{
9bcb3eef 13158 struct bgp_dest *dest;
d62a17ae 13159 struct prefix q;
13160 struct peer *peer;
13161 struct bgp_distance *bdistance;
13162 struct access_list *alist;
13163 struct bgp_static *bgp_static;
13164
13165 if (!bgp)
13166 return 0;
13167
40381db7 13168 peer = pinfo->peer;
d62a17ae 13169
7b7d48e5
DS
13170 if (pinfo->attr->distance)
13171 return pinfo->attr->distance;
13172
d62a17ae 13173 /* Check source address. */
13174 sockunion2hostprefix(&peer->su, &q);
9bcb3eef
DS
13175 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13176 if (dest) {
13177 bdistance = bgp_dest_get_bgp_distance_info(dest);
13178 bgp_dest_unlock_node(dest);
d62a17ae 13179
13180 if (bdistance->access_list) {
13181 alist = access_list_lookup(afi, bdistance->access_list);
13182 if (alist
13183 && access_list_apply(alist, p) == FILTER_PERMIT)
13184 return bdistance->distance;
13185 } else
13186 return bdistance->distance;
718e3744 13187 }
718e3744 13188
d62a17ae 13189 /* Backdoor check. */
9bcb3eef
DS
13190 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13191 if (dest) {
13192 bgp_static = bgp_dest_get_bgp_static_info(dest);
13193 bgp_dest_unlock_node(dest);
718e3744 13194
d62a17ae 13195 if (bgp_static->backdoor) {
13196 if (bgp->distance_local[afi][safi])
13197 return bgp->distance_local[afi][safi];
13198 else
13199 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13200 }
718e3744 13201 }
718e3744 13202
d62a17ae 13203 if (peer->sort == BGP_PEER_EBGP) {
13204 if (bgp->distance_ebgp[afi][safi])
13205 return bgp->distance_ebgp[afi][safi];
13206 return ZEBRA_EBGP_DISTANCE_DEFAULT;
13207 } else {
13208 if (bgp->distance_ibgp[afi][safi])
13209 return bgp->distance_ibgp[afi][safi];
13210 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13211 }
718e3744 13212}
13213
a612fb77
DA
13214/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
13215 * we should tell ZEBRA update the routes for a specific
13216 * AFI/SAFI to reflect changes in RIB.
13217 */
8b54bc30
DA
13218static void bgp_announce_routes_distance_update(struct bgp *bgp,
13219 afi_t update_afi,
13220 safi_t update_safi)
a612fb77
DA
13221{
13222 afi_t afi;
13223 safi_t safi;
13224
13225 FOREACH_AFI_SAFI (afi, safi) {
13226 if (!bgp_fibupd_safi(safi))
13227 continue;
13228
8b54bc30
DA
13229 if (afi != update_afi && safi != update_safi)
13230 continue;
13231
13232 if (BGP_DEBUG(zebra, ZEBRA))
13233 zlog_debug(
13234 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
13235 __func__, afi, safi);
13236 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
13237 }
13238}
13239
718e3744 13240DEFUN (bgp_distance,
13241 bgp_distance_cmd,
6147e2c6 13242 "distance bgp (1-255) (1-255) (1-255)",
718e3744 13243 "Define an administrative distance\n"
13244 "BGP distance\n"
13245 "Distance for routes external to the AS\n"
13246 "Distance for routes internal to the AS\n"
13247 "Distance for local routes\n")
13248{
d62a17ae 13249 VTY_DECLVAR_CONTEXT(bgp, bgp);
13250 int idx_number = 2;
13251 int idx_number_2 = 3;
13252 int idx_number_3 = 4;
8b54bc30
DA
13253 int distance_ebgp = atoi(argv[idx_number]->arg);
13254 int distance_ibgp = atoi(argv[idx_number_2]->arg);
13255 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 13256 afi_t afi;
13257 safi_t safi;
718e3744 13258
d62a17ae 13259 afi = bgp_node_afi(vty);
13260 safi = bgp_node_safi(vty);
718e3744 13261
8b54bc30
DA
13262 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
13263 || bgp->distance_ibgp[afi][safi] != distance_ibgp
13264 || bgp->distance_local[afi][safi] != distance_local) {
13265 bgp->distance_ebgp[afi][safi] = distance_ebgp;
13266 bgp->distance_ibgp[afi][safi] = distance_ibgp;
13267 bgp->distance_local[afi][safi] = distance_local;
13268 bgp_announce_routes_distance_update(bgp, afi, safi);
13269 }
d62a17ae 13270 return CMD_SUCCESS;
718e3744 13271}
13272
13273DEFUN (no_bgp_distance,
13274 no_bgp_distance_cmd,
a636c635 13275 "no distance bgp [(1-255) (1-255) (1-255)]",
718e3744 13276 NO_STR
13277 "Define an administrative distance\n"
13278 "BGP distance\n"
13279 "Distance for routes external to the AS\n"
13280 "Distance for routes internal to the AS\n"
13281 "Distance for local routes\n")
13282{
d62a17ae 13283 VTY_DECLVAR_CONTEXT(bgp, bgp);
13284 afi_t afi;
13285 safi_t safi;
718e3744 13286
d62a17ae 13287 afi = bgp_node_afi(vty);
13288 safi = bgp_node_safi(vty);
718e3744 13289
8b54bc30
DA
13290 if (bgp->distance_ebgp[afi][safi] != 0
13291 || bgp->distance_ibgp[afi][safi] != 0
13292 || bgp->distance_local[afi][safi] != 0) {
13293 bgp->distance_ebgp[afi][safi] = 0;
13294 bgp->distance_ibgp[afi][safi] = 0;
13295 bgp->distance_local[afi][safi] = 0;
13296 bgp_announce_routes_distance_update(bgp, afi, safi);
13297 }
d62a17ae 13298 return CMD_SUCCESS;
718e3744 13299}
13300
718e3744 13301
13302DEFUN (bgp_distance_source,
13303 bgp_distance_source_cmd,
6147e2c6 13304 "distance (1-255) A.B.C.D/M",
718e3744 13305 "Define an administrative distance\n"
13306 "Administrative distance\n"
13307 "IP source prefix\n")
13308{
d62a17ae 13309 int idx_number = 1;
13310 int idx_ipv4_prefixlen = 2;
13311 bgp_distance_set(vty, argv[idx_number]->arg,
13312 argv[idx_ipv4_prefixlen]->arg, NULL);
13313 return CMD_SUCCESS;
718e3744 13314}
13315
13316DEFUN (no_bgp_distance_source,
13317 no_bgp_distance_source_cmd,
6147e2c6 13318 "no distance (1-255) A.B.C.D/M",
718e3744 13319 NO_STR
13320 "Define an administrative distance\n"
13321 "Administrative distance\n"
13322 "IP source prefix\n")
13323{
d62a17ae 13324 int idx_number = 2;
13325 int idx_ipv4_prefixlen = 3;
13326 bgp_distance_unset(vty, argv[idx_number]->arg,
13327 argv[idx_ipv4_prefixlen]->arg, NULL);
13328 return CMD_SUCCESS;
718e3744 13329}
13330
13331DEFUN (bgp_distance_source_access_list,
13332 bgp_distance_source_access_list_cmd,
6147e2c6 13333 "distance (1-255) A.B.C.D/M WORD",
718e3744 13334 "Define an administrative distance\n"
13335 "Administrative distance\n"
13336 "IP source prefix\n"
13337 "Access list name\n")
13338{
d62a17ae 13339 int idx_number = 1;
13340 int idx_ipv4_prefixlen = 2;
13341 int idx_word = 3;
13342 bgp_distance_set(vty, argv[idx_number]->arg,
13343 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
13344 return CMD_SUCCESS;
718e3744 13345}
13346
13347DEFUN (no_bgp_distance_source_access_list,
13348 no_bgp_distance_source_access_list_cmd,
6147e2c6 13349 "no distance (1-255) A.B.C.D/M WORD",
718e3744 13350 NO_STR
13351 "Define an administrative distance\n"
13352 "Administrative distance\n"
13353 "IP source prefix\n"
13354 "Access list name\n")
13355{
d62a17ae 13356 int idx_number = 2;
13357 int idx_ipv4_prefixlen = 3;
13358 int idx_word = 4;
13359 bgp_distance_unset(vty, argv[idx_number]->arg,
13360 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
13361 return CMD_SUCCESS;
718e3744 13362}
6b0655a2 13363
734b349e
MZ
13364DEFUN (ipv6_bgp_distance_source,
13365 ipv6_bgp_distance_source_cmd,
39e92c06 13366 "distance (1-255) X:X::X:X/M",
734b349e
MZ
13367 "Define an administrative distance\n"
13368 "Administrative distance\n"
13369 "IP source prefix\n")
13370{
d62a17ae 13371 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
13372 return CMD_SUCCESS;
734b349e
MZ
13373}
13374
13375DEFUN (no_ipv6_bgp_distance_source,
13376 no_ipv6_bgp_distance_source_cmd,
39e92c06 13377 "no distance (1-255) X:X::X:X/M",
734b349e
MZ
13378 NO_STR
13379 "Define an administrative distance\n"
13380 "Administrative distance\n"
13381 "IP source prefix\n")
13382{
d62a17ae 13383 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
13384 return CMD_SUCCESS;
734b349e
MZ
13385}
13386
13387DEFUN (ipv6_bgp_distance_source_access_list,
13388 ipv6_bgp_distance_source_access_list_cmd,
39e92c06 13389 "distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
13390 "Define an administrative distance\n"
13391 "Administrative distance\n"
13392 "IP source prefix\n"
13393 "Access list name\n")
13394{
d62a17ae 13395 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
13396 return CMD_SUCCESS;
734b349e
MZ
13397}
13398
13399DEFUN (no_ipv6_bgp_distance_source_access_list,
13400 no_ipv6_bgp_distance_source_access_list_cmd,
39e92c06 13401 "no distance (1-255) X:X::X:X/M WORD",
734b349e
MZ
13402 NO_STR
13403 "Define an administrative distance\n"
13404 "Administrative distance\n"
13405 "IP source prefix\n"
13406 "Access list name\n")
13407{
d62a17ae 13408 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
13409 return CMD_SUCCESS;
734b349e
MZ
13410}
13411
718e3744 13412DEFUN (bgp_damp_set,
13413 bgp_damp_set_cmd,
31500417 13414 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 13415 "BGP Specific commands\n"
13416 "Enable route-flap dampening\n"
13417 "Half-life time for the penalty\n"
13418 "Value to start reusing a route\n"
13419 "Value to start suppressing a route\n"
13420 "Maximum duration to suppress a stable route\n")
13421{
d62a17ae 13422 VTY_DECLVAR_CONTEXT(bgp, bgp);
13423 int idx_half_life = 2;
13424 int idx_reuse = 3;
13425 int idx_suppress = 4;
13426 int idx_max_suppress = 5;
13427 int half = DEFAULT_HALF_LIFE * 60;
13428 int reuse = DEFAULT_REUSE;
13429 int suppress = DEFAULT_SUPPRESS;
13430 int max = 4 * half;
13431
13432 if (argc == 6) {
13433 half = atoi(argv[idx_half_life]->arg) * 60;
13434 reuse = atoi(argv[idx_reuse]->arg);
13435 suppress = atoi(argv[idx_suppress]->arg);
13436 max = atoi(argv[idx_max_suppress]->arg) * 60;
13437 } else if (argc == 3) {
13438 half = atoi(argv[idx_half_life]->arg) * 60;
13439 max = 4 * half;
13440 }
718e3744 13441
6d24b7cc
DS
13442 /*
13443 * These can't be 0 but our SA doesn't understand the
13444 * way our cli is constructed
13445 */
13446 assert(reuse);
13447 assert(half);
d62a17ae 13448 if (suppress < reuse) {
13449 vty_out(vty,
13450 "Suppress value cannot be less than reuse value \n");
13451 return 0;
13452 }
7ebe9748 13453
d62a17ae 13454 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
13455 reuse, suppress, max);
718e3744 13456}
13457
718e3744 13458DEFUN (bgp_damp_unset,
13459 bgp_damp_unset_cmd,
d04c479d 13460 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
718e3744 13461 NO_STR
13462 "BGP Specific commands\n"
16cedbb0
QY
13463 "Enable route-flap dampening\n"
13464 "Half-life time for the penalty\n"
13465 "Value to start reusing a route\n"
13466 "Value to start suppressing a route\n"
13467 "Maximum duration to suppress a stable route\n")
718e3744 13468{
d62a17ae 13469 VTY_DECLVAR_CONTEXT(bgp, bgp);
13470 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 13471}
13472
718e3744 13473/* Display specified route of BGP table. */
d62a17ae 13474static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
13475 const char *ip_str, afi_t afi, safi_t safi,
13476 struct prefix_rd *prd, int prefix_check)
13477{
13478 int ret;
13479 struct prefix match;
9bcb3eef
DS
13480 struct bgp_dest *dest;
13481 struct bgp_dest *rm;
40381db7
DS
13482 struct bgp_path_info *pi;
13483 struct bgp_path_info *pi_temp;
d62a17ae 13484 struct bgp *bgp;
13485 struct bgp_table *table;
13486
13487 /* BGP structure lookup. */
13488 if (view_name) {
13489 bgp = bgp_lookup_by_name(view_name);
13490 if (bgp == NULL) {
13491 vty_out(vty, "%% Can't find BGP instance %s\n",
13492 view_name);
13493 return CMD_WARNING;
13494 }
13495 } else {
13496 bgp = bgp_get_default();
13497 if (bgp == NULL) {
13498 vty_out(vty, "%% No BGP process is configured\n");
13499 return CMD_WARNING;
13500 }
718e3744 13501 }
718e3744 13502
d62a17ae 13503 /* Check IP address argument. */
13504 ret = str2prefix(ip_str, &match);
13505 if (!ret) {
13506 vty_out(vty, "%% address is malformed\n");
13507 return CMD_WARNING;
13508 }
718e3744 13509
d62a17ae 13510 match.family = afi2family(afi);
13511
13512 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13513 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
13514 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
13515 dest = bgp_route_next(dest)) {
13516 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13517
9bcb3eef 13518 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 13519 continue;
9bcb3eef 13520 table = bgp_dest_get_bgp_table_info(dest);
67009e22 13521 if (!table)
ea47320b
DL
13522 continue;
13523 if ((rm = bgp_node_match(table, &match)) == NULL)
13524 continue;
d62a17ae 13525
9bcb3eef 13526 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 13527
ea47320b 13528 if (!prefix_check
b54892e0 13529 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 13530 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
13531 while (pi) {
13532 if (pi->extra && pi->extra->damp_info) {
13533 pi_temp = pi->next;
ea47320b 13534 bgp_damp_info_free(
40381db7 13535 pi->extra->damp_info,
a935f597 13536 1, afi, safi);
40381db7 13537 pi = pi_temp;
ea47320b 13538 } else
40381db7 13539 pi = pi->next;
d62a17ae 13540 }
ea47320b
DL
13541 }
13542
9bcb3eef 13543 bgp_dest_unlock_node(rm);
d62a17ae 13544 }
13545 } else {
9bcb3eef 13546 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 13547 != NULL) {
9bcb3eef 13548 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 13549
d62a17ae 13550 if (!prefix_check
9bcb3eef
DS
13551 || dest_p->prefixlen == match.prefixlen) {
13552 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
13553 while (pi) {
13554 if (pi->extra && pi->extra->damp_info) {
13555 pi_temp = pi->next;
d62a17ae 13556 bgp_damp_info_free(
40381db7 13557 pi->extra->damp_info,
a935f597 13558 1, afi, safi);
40381db7 13559 pi = pi_temp;
d62a17ae 13560 } else
40381db7 13561 pi = pi->next;
d62a17ae 13562 }
13563 }
13564
9bcb3eef 13565 bgp_dest_unlock_node(dest);
d62a17ae 13566 }
13567 }
718e3744 13568
d62a17ae 13569 return CMD_SUCCESS;
718e3744 13570}
13571
13572DEFUN (clear_ip_bgp_dampening,
13573 clear_ip_bgp_dampening_cmd,
13574 "clear ip bgp dampening",
13575 CLEAR_STR
13576 IP_STR
13577 BGP_STR
13578 "Clear route flap dampening information\n")
13579{
a935f597 13580 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 13581 return CMD_SUCCESS;
718e3744 13582}
13583
13584DEFUN (clear_ip_bgp_dampening_prefix,
13585 clear_ip_bgp_dampening_prefix_cmd,
13586 "clear ip bgp dampening A.B.C.D/M",
13587 CLEAR_STR
13588 IP_STR
13589 BGP_STR
13590 "Clear route flap dampening information\n"
0c7b1b01 13591 "IPv4 prefix\n")
718e3744 13592{
d62a17ae 13593 int idx_ipv4_prefixlen = 4;
13594 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
13595 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 13596}
13597
13598DEFUN (clear_ip_bgp_dampening_address,
13599 clear_ip_bgp_dampening_address_cmd,
13600 "clear ip bgp dampening A.B.C.D",
13601 CLEAR_STR
13602 IP_STR
13603 BGP_STR
13604 "Clear route flap dampening information\n"
13605 "Network to clear damping information\n")
13606{
d62a17ae 13607 int idx_ipv4 = 4;
13608 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
13609 SAFI_UNICAST, NULL, 0);
718e3744 13610}
13611
13612DEFUN (clear_ip_bgp_dampening_address_mask,
13613 clear_ip_bgp_dampening_address_mask_cmd,
13614 "clear ip bgp dampening A.B.C.D A.B.C.D",
13615 CLEAR_STR
13616 IP_STR
13617 BGP_STR
13618 "Clear route flap dampening information\n"
13619 "Network to clear damping information\n"
13620 "Network mask\n")
13621{
d62a17ae 13622 int idx_ipv4 = 4;
13623 int idx_ipv4_2 = 5;
13624 int ret;
13625 char prefix_str[BUFSIZ];
718e3744 13626
d62a17ae 13627 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
13628 prefix_str);
13629 if (!ret) {
13630 vty_out(vty, "%% Inconsistent address and mask\n");
13631 return CMD_WARNING;
13632 }
718e3744 13633
d62a17ae 13634 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
13635 NULL, 0);
718e3744 13636}
6b0655a2 13637
e3b78da8 13638static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
13639{
13640 struct vty *vty = arg;
e3b78da8 13641 struct peer *peer = bucket->data;
825d9834
DS
13642 char buf[SU_ADDRSTRLEN];
13643
13644 vty_out(vty, "\tPeer: %s %s\n", peer->host,
13645 sockunion2str(&peer->su, buf, sizeof(buf)));
13646}
13647
2a0e69ae
DS
13648DEFUN (show_bgp_listeners,
13649 show_bgp_listeners_cmd,
13650 "show bgp listeners",
13651 SHOW_STR
13652 BGP_STR
13653 "Display Listen Sockets and who created them\n")
13654{
13655 bgp_dump_listener_info(vty);
13656
13657 return CMD_SUCCESS;
13658}
13659
825d9834
DS
13660DEFUN (show_bgp_peerhash,
13661 show_bgp_peerhash_cmd,
13662 "show bgp peerhash",
13663 SHOW_STR
13664 BGP_STR
13665 "Display information about the BGP peerhash\n")
13666{
13667 struct list *instances = bm->bgp;
13668 struct listnode *node;
13669 struct bgp *bgp;
13670
13671 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
13672 vty_out(vty, "BGP: %s\n", bgp->name);
13673 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
13674 vty);
13675 }
13676
13677 return CMD_SUCCESS;
13678}
13679
587ff0fd 13680/* also used for encap safi */
2b791107
DL
13681static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
13682 afi_t afi, safi_t safi)
d62a17ae 13683{
9bcb3eef
DS
13684 struct bgp_dest *pdest;
13685 struct bgp_dest *dest;
d62a17ae 13686 struct bgp_table *table;
b54892e0
DS
13687 const struct prefix *p;
13688 const struct prefix_rd *prd;
d62a17ae 13689 struct bgp_static *bgp_static;
13690 mpls_label_t label;
13691 char buf[SU_ADDRSTRLEN];
13692 char rdbuf[RD_ADDRSTRLEN];
13693
13694 /* Network configuration. */
9bcb3eef
DS
13695 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13696 pdest = bgp_route_next(pdest)) {
13697 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13698 if (!table)
ea47320b 13699 continue;
d62a17ae 13700
9bcb3eef
DS
13701 for (dest = bgp_table_top(table); dest;
13702 dest = bgp_route_next(dest)) {
13703 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13704 if (bgp_static == NULL)
ea47320b 13705 continue;
d62a17ae 13706
9bcb3eef
DS
13707 p = bgp_dest_get_prefix(dest);
13708 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13709 pdest);
d62a17ae 13710
ea47320b 13711 /* "network" configuration display. */
06b9f471 13712 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
13713 label = decode_label(&bgp_static->label);
13714
13715 vty_out(vty, " network %s/%d rd %s",
13716 inet_ntop(p->family, &p->u.prefix, buf,
13717 SU_ADDRSTRLEN),
13718 p->prefixlen, rdbuf);
13719 if (safi == SAFI_MPLS_VPN)
13720 vty_out(vty, " label %u", label);
13721
13722 if (bgp_static->rmap.name)
13723 vty_out(vty, " route-map %s",
13724 bgp_static->rmap.name);
e2a86ad9
DS
13725
13726 if (bgp_static->backdoor)
13727 vty_out(vty, " backdoor");
13728
ea47320b
DL
13729 vty_out(vty, "\n");
13730 }
13731 }
d62a17ae 13732}
13733
2b791107
DL
13734static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
13735 afi_t afi, safi_t safi)
d62a17ae 13736{
9bcb3eef
DS
13737 struct bgp_dest *pdest;
13738 struct bgp_dest *dest;
d62a17ae 13739 struct bgp_table *table;
b54892e0
DS
13740 const struct prefix *p;
13741 const struct prefix_rd *prd;
d62a17ae 13742 struct bgp_static *bgp_static;
ff44f570 13743 char buf[PREFIX_STRLEN * 2];
d62a17ae 13744 char buf2[SU_ADDRSTRLEN];
13745 char rdbuf[RD_ADDRSTRLEN];
0a50c248 13746 char esi_buf[ESI_BYTES];
d62a17ae 13747
13748 /* Network configuration. */
9bcb3eef
DS
13749 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
13750 pdest = bgp_route_next(pdest)) {
13751 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 13752 if (!table)
ea47320b 13753 continue;
d62a17ae 13754
9bcb3eef
DS
13755 for (dest = bgp_table_top(table); dest;
13756 dest = bgp_route_next(dest)) {
13757 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13758 if (bgp_static == NULL)
ea47320b 13759 continue;
d62a17ae 13760
ea47320b 13761 char *macrouter = NULL;
d62a17ae 13762
ea47320b
DL
13763 if (bgp_static->router_mac)
13764 macrouter = prefix_mac2str(
13765 bgp_static->router_mac, NULL, 0);
13766 if (bgp_static->eth_s_id)
0a50c248
AK
13767 esi_to_str(bgp_static->eth_s_id,
13768 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
13769 p = bgp_dest_get_prefix(dest);
13770 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 13771
ea47320b 13772 /* "network" configuration display. */
06b9f471 13773 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
13774 if (p->u.prefix_evpn.route_type == 5) {
13775 char local_buf[PREFIX_STRLEN];
3714a385 13776 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
13777 struct prefix_evpn *)p)
13778 ? AF_INET
13779 : AF_INET6;
3714a385 13780 inet_ntop(family,
13781 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 13782 local_buf, PREFIX_STRLEN);
772270f3
QY
13783 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
13784 p->u.prefix_evpn.prefix_addr
13785 .ip_prefix_length);
197cb530
PG
13786 } else {
13787 prefix2str(p, buf, sizeof(buf));
13788 }
ea47320b 13789
a4d82a8a
PZ
13790 if (bgp_static->gatewayIp.family == AF_INET
13791 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
13792 inet_ntop(bgp_static->gatewayIp.family,
13793 &bgp_static->gatewayIp.u.prefix, buf2,
13794 sizeof(buf2));
ea47320b 13795 vty_out(vty,
7bcc8dac 13796 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 13797 buf, rdbuf,
13798 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 13799 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
13800 macrouter);
13801
0a22ddfb 13802 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
13803 }
13804 }
3da6fcd5
PG
13805}
13806
718e3744 13807/* Configuration of static route announcement and aggregate
13808 information. */
2b791107
DL
13809void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
13810 safi_t safi)
d62a17ae 13811{
9bcb3eef 13812 struct bgp_dest *dest;
b54892e0 13813 const struct prefix *p;
d62a17ae 13814 struct bgp_static *bgp_static;
13815 struct bgp_aggregate *bgp_aggregate;
13816 char buf[SU_ADDRSTRLEN];
13817
2b791107
DL
13818 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
13819 bgp_config_write_network_vpn(vty, bgp, afi, safi);
13820 return;
13821 }
d62a17ae 13822
2b791107
DL
13823 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
13824 bgp_config_write_network_evpn(vty, bgp, afi, safi);
13825 return;
13826 }
d62a17ae 13827
13828 /* Network configuration. */
9bcb3eef
DS
13829 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
13830 dest = bgp_route_next(dest)) {
13831 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 13832 if (bgp_static == NULL)
ea47320b 13833 continue;
d62a17ae 13834
9bcb3eef 13835 p = bgp_dest_get_prefix(dest);
d62a17ae 13836
d8a9922d
DS
13837 vty_out(vty, " network %s/%d",
13838 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13839 p->prefixlen);
d62a17ae 13840
ea47320b
DL
13841 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
13842 vty_out(vty, " label-index %u",
13843 bgp_static->label_index);
d62a17ae 13844
ea47320b
DL
13845 if (bgp_static->rmap.name)
13846 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
13847
13848 if (bgp_static->backdoor)
13849 vty_out(vty, " backdoor");
718e3744 13850
ea47320b
DL
13851 vty_out(vty, "\n");
13852 }
13853
d62a17ae 13854 /* Aggregate-address configuration. */
9bcb3eef
DS
13855 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
13856 dest = bgp_route_next(dest)) {
13857 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 13858 if (bgp_aggregate == NULL)
ea47320b 13859 continue;
d62a17ae 13860
9bcb3eef 13861 p = bgp_dest_get_prefix(dest);
d62a17ae 13862
d8a9922d
DS
13863 vty_out(vty, " aggregate-address %s/%d",
13864 inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
13865 p->prefixlen);
d62a17ae 13866
ea47320b
DL
13867 if (bgp_aggregate->as_set)
13868 vty_out(vty, " as-set");
d62a17ae 13869
ea47320b
DL
13870 if (bgp_aggregate->summary_only)
13871 vty_out(vty, " summary-only");
718e3744 13872
20894f50
DA
13873 if (bgp_aggregate->rmap.name)
13874 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
13875
229757f1
DA
13876 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
13877 vty_out(vty, " origin %s",
13878 bgp_origin2str(bgp_aggregate->origin));
13879
ea47320b
DL
13880 vty_out(vty, "\n");
13881 }
d62a17ae 13882}
734b349e 13883
2b791107 13884void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 13885 safi_t safi)
d62a17ae 13886{
9bcb3eef 13887 struct bgp_dest *dest;
d62a17ae 13888 struct bgp_distance *bdistance;
13889
13890 /* Distance configuration. */
13891 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
13892 && bgp->distance_local[afi][safi]
13893 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
13894 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
13895 || bgp->distance_local[afi][safi]
13896 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 13897 vty_out(vty, " distance bgp %d %d %d\n",
13898 bgp->distance_ebgp[afi][safi],
13899 bgp->distance_ibgp[afi][safi],
13900 bgp->distance_local[afi][safi]);
13901 }
734b349e 13902
9bcb3eef
DS
13903 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
13904 dest = bgp_route_next(dest)) {
13905 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0
DS
13906 if (bdistance != NULL)
13907 vty_out(vty, " distance %d %pRN %s\n",
9bcb3eef 13908 bdistance->distance, dest,
d62a17ae 13909 bdistance->access_list ? bdistance->access_list
13910 : "");
ca2e160d 13911 }
718e3744 13912}
13913
13914/* Allocate routing table structure and install commands. */
d62a17ae 13915void bgp_route_init(void)
13916{
13917 afi_t afi;
13918 safi_t safi;
13919
13920 /* Init BGP distance table. */
05c7a1cc 13921 FOREACH_AFI_SAFI (afi, safi)
960035b2 13922 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 13923
13924 /* IPv4 BGP commands. */
13925 install_element(BGP_NODE, &bgp_table_map_cmd);
13926 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 13927 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 13928
13929 install_element(BGP_NODE, &aggregate_address_cmd);
13930 install_element(BGP_NODE, &aggregate_address_mask_cmd);
13931 install_element(BGP_NODE, &no_aggregate_address_cmd);
13932 install_element(BGP_NODE, &no_aggregate_address_mask_cmd);
13933
13934 /* IPv4 unicast configuration. */
13935 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
13936 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 13937 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 13938
13939 install_element(BGP_IPV4_NODE, &aggregate_address_cmd);
13940 install_element(BGP_IPV4_NODE, &aggregate_address_mask_cmd);
13941 install_element(BGP_IPV4_NODE, &no_aggregate_address_cmd);
13942 install_element(BGP_IPV4_NODE, &no_aggregate_address_mask_cmd);
13943
13944 /* IPv4 multicast configuration. */
13945 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
13946 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 13947 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
d62a17ae 13948 install_element(BGP_IPV4M_NODE, &aggregate_address_cmd);
13949 install_element(BGP_IPV4M_NODE, &aggregate_address_mask_cmd);
13950 install_element(BGP_IPV4M_NODE, &no_aggregate_address_cmd);
13951 install_element(BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
13952
13953 /* IPv4 labeled-unicast configuration. */
fb985e0c
DA
13954 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
13955 install_element(BGP_IPV4L_NODE, &aggregate_address_cmd);
13956 install_element(BGP_IPV4L_NODE, &aggregate_address_mask_cmd);
13957 install_element(BGP_IPV4L_NODE, &no_aggregate_address_cmd);
13958 install_element(BGP_IPV4L_NODE, &no_aggregate_address_mask_cmd);
13959
d62a17ae 13960 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
13961 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 13962 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 13963 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 13964 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 13965 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
13966 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 13967 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 13968
13969 install_element(VIEW_NODE,
13970 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
13971 install_element(VIEW_NODE,
13972 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 13973 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
13974 install_element(VIEW_NODE,
13975 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 13976#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13977 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 13978#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 13979 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
13980 install_element(VIEW_NODE,
44c69747 13981 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 13982
d62a17ae 13983 /* BGP dampening clear commands */
13984 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
13985 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 13986
d62a17ae 13987 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
13988 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
13989
13990 /* prefix count */
13991 install_element(ENABLE_NODE,
13992 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 13993#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 13994 install_element(ENABLE_NODE,
13995 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 13996#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 13997
d62a17ae 13998 /* New config IPv6 BGP commands. */
13999 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14000 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14001 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14002
14003 install_element(BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
14004 install_element(BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
14005
14006 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14007
fb985e0c
DA
14008 /* IPv6 labeled unicast address family. */
14009 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
14010 install_element(BGP_IPV6L_NODE, &ipv6_aggregate_address_cmd);
14011 install_element(BGP_IPV6L_NODE, &no_ipv6_aggregate_address_cmd);
14012
d62a17ae 14013 install_element(BGP_NODE, &bgp_distance_cmd);
14014 install_element(BGP_NODE, &no_bgp_distance_cmd);
14015 install_element(BGP_NODE, &bgp_distance_source_cmd);
14016 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
14017 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
14018 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
14019 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14020 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14021 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
14022 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
14023 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
14024 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
14025 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14026 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14027 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
14028 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
14029 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
14030 install_element(BGP_IPV4M_NODE,
14031 &no_bgp_distance_source_access_list_cmd);
14032 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14033 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
14034 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
14035 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
14036 install_element(BGP_IPV6_NODE,
14037 &ipv6_bgp_distance_source_access_list_cmd);
14038 install_element(BGP_IPV6_NODE,
14039 &no_ipv6_bgp_distance_source_access_list_cmd);
14040 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14041 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
14042 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
14043 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
14044 install_element(BGP_IPV6M_NODE,
14045 &ipv6_bgp_distance_source_access_list_cmd);
14046 install_element(BGP_IPV6M_NODE,
14047 &no_ipv6_bgp_distance_source_access_list_cmd);
14048
ef5f4b23 14049 /* BGP dampening */
d62a17ae 14050 install_element(BGP_NODE, &bgp_damp_set_cmd);
14051 install_element(BGP_NODE, &bgp_damp_unset_cmd);
14052 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
14053 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
d62a17ae 14054 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
14055 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
ef5f4b23
DA
14056 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
14057 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
14058 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
14059 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
14060 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
14061 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
14062 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
14063 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 14064
14065 /* Large Communities */
14066 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14067 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14068
14069 /* show bgp ipv4 flowspec detailed */
14070 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14071
2a0e69ae 14072 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14073 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14074}
14075
14076void bgp_route_finish(void)
14077{
14078 afi_t afi;
14079 safi_t safi;
14080
05c7a1cc
QY
14081 FOREACH_AFI_SAFI (afi, safi) {
14082 bgp_table_unlock(bgp_distance_table[afi][safi]);
14083 bgp_distance_table[afi][safi] = NULL;
14084 }
228da428 14085}