]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #8261 from opensourcerouting/log-ids
[mirror_frr.git] / bgpd / bgp_route.c
CommitLineData
718e3744 1/* BGP routing information
896014f4
DL
2 * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
3 * Copyright (C) 2016 Job Snijders <job@instituut.net>
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
718e3744 21
22#include <zebra.h>
8d0ab76d 23#include <math.h>
718e3744 24
2618a52e 25#include "printfrr.h"
718e3744 26#include "prefix.h"
27#include "linklist.h"
28#include "memory.h"
29#include "command.h"
30#include "stream.h"
31#include "filter.h"
718e3744 32#include "log.h"
33#include "routemap.h"
34#include "buffer.h"
35#include "sockunion.h"
36#include "plist.h"
37#include "thread.h"
200df115 38#include "workqueue.h"
3f9c7369 39#include "queue.h"
6e919709 40#include "memory.h"
e496b420 41#include "srv6.h"
4dcadbef 42#include "lib/json.h"
d8d084d9 43#include "lib_errors.h"
8c48b3b6 44#include "zclient.h"
718e3744 45#include "bgpd/bgpd.h"
46#include "bgpd/bgp_table.h"
47#include "bgpd/bgp_route.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_debug.h"
14454c9f 50#include "bgpd/bgp_errors.h"
718e3744 51#include "bgpd/bgp_aspath.h"
52#include "bgpd/bgp_regex.h"
53#include "bgpd/bgp_community.h"
54#include "bgpd/bgp_ecommunity.h"
57d187bc 55#include "bgpd/bgp_lcommunity.h"
718e3744 56#include "bgpd/bgp_clist.h"
57#include "bgpd/bgp_packet.h"
58#include "bgpd/bgp_filter.h"
59#include "bgpd/bgp_fsm.h"
60#include "bgpd/bgp_mplsvpn.h"
61#include "bgpd/bgp_nexthop.h"
62#include "bgpd/bgp_damp.h"
63#include "bgpd/bgp_advertise.h"
64#include "bgpd/bgp_zebra.h"
0a486e5f 65#include "bgpd/bgp_vty.h"
96450faf 66#include "bgpd/bgp_mpath.h"
fc9a856f 67#include "bgpd/bgp_nht.h"
3f9c7369 68#include "bgpd/bgp_updgrp.h"
cd1964ff 69#include "bgpd/bgp_label.h"
dcc68b5e 70#include "bgpd/bgp_addpath.h"
4e802e66 71#include "bgpd/bgp_mac.h"
2a0e69ae 72#include "bgpd/bgp_network.h"
6401252f 73#include "bgpd/bgp_trace.h"
718e3744 74
49e5a4a0 75#ifdef ENABLE_BGP_VNC
f8b6f499
LB
76#include "bgpd/rfapi/rfapi_backend.h"
77#include "bgpd/rfapi/vnc_import_bgp.h"
78#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 79#endif
aee875b5
PG
80#include "bgpd/bgp_encap_types.h"
81#include "bgpd/bgp_encap_tlv.h"
684a7227 82#include "bgpd/bgp_evpn.h"
0a50c248 83#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 84#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 85#include "bgpd/bgp_flowspec.h"
98a9dbc7 86#include "bgpd/bgp_flowspec_util.h"
45918cfb 87#include "bgpd/bgp_pbr.h"
37a87b8f
CS
88#include "northbound.h"
89#include "northbound_cli.h"
90#include "bgpd/bgp_nb.h"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
718e3744 105/* Extern from bgp_dump.c */
dde72586
SH
106extern const char *bgp_origin_str[];
107extern const char *bgp_origin_long_str[];
3742de8d 108
b7d08f5a 109/* PMSI strings. */
110#define PMSI_TNLTYPE_STR_NO_INFO "No info"
111#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
112static const struct message bgp_pmsi_tnltype_str[] = {
113 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
114 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
115 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
116 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
117 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
118 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
119 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
120 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 121 {0}
122};
b7d08f5a 123
9df8b37c
PZ
124#define VRFID_NONE_STR "-"
125
4a11bf2c 126DEFINE_HOOK(bgp_process,
9bcb3eef
DS
127 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
128 struct peer *peer, bool withdraw),
8451921b 129 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 130
4056a5f6
RZ
131/** Test if path is suppressed. */
132static bool bgp_path_suppressed(struct bgp_path_info *pi)
133{
134 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
135 return false;
136
137 return listcount(pi->extra->aggr_suppressors) > 0;
138}
4a11bf2c 139
9bcb3eef 140struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 141 safi_t safi, const struct prefix *p,
d62a17ae 142 struct prefix_rd *prd)
143{
9bcb3eef
DS
144 struct bgp_dest *dest;
145 struct bgp_dest *pdest = NULL;
d62a17ae 146
147 assert(table);
d62a17ae 148
149 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
150 || (safi == SAFI_EVPN)) {
9bcb3eef 151 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 152
9bcb3eef
DS
153 if (!bgp_dest_has_bgp_path_info_data(pdest))
154 bgp_dest_set_bgp_table_info(
155 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 156 else
9bcb3eef
DS
157 bgp_dest_unlock_node(pdest);
158 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 159 }
718e3744 160
9bcb3eef 161 dest = bgp_node_get(table, p);
718e3744 162
d62a17ae 163 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
164 || (safi == SAFI_EVPN))
9bcb3eef 165 dest->pdest = pdest;
718e3744 166
9bcb3eef 167 return dest;
718e3744 168}
6b0655a2 169
9bcb3eef 170struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 171 safi_t safi, const struct prefix *p,
d62a17ae 172 struct prefix_rd *prd)
128ea8ab 173{
9bcb3eef
DS
174 struct bgp_dest *dest;
175 struct bgp_dest *pdest = NULL;
128ea8ab 176
d62a17ae 177 if (!table)
178 return NULL;
128ea8ab 179
d62a17ae 180 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
181 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
182 pdest = bgp_node_lookup(table, (struct prefix *)prd);
183 if (!pdest)
d62a17ae 184 return NULL;
128ea8ab 185
9bcb3eef
DS
186 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
187 bgp_dest_unlock_node(pdest);
d62a17ae 188 return NULL;
189 }
128ea8ab 190
9bcb3eef 191 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 192 }
128ea8ab 193
9bcb3eef 194 dest = bgp_node_lookup(table, p);
128ea8ab 195
9bcb3eef 196 return dest;
128ea8ab 197}
198
18ee8310
DS
199/* Allocate bgp_path_info_extra */
200static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 201{
4b7e6066
DS
202 struct bgp_path_info_extra *new;
203 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
204 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
205 new->label[0] = MPLS_INVALID_LABEL;
206 new->num_labels = 0;
3e3708cb
PG
207 new->bgp_fs_pbr = NULL;
208 new->bgp_fs_iprule = NULL;
d62a17ae 209 return new;
fb982c25
PJ
210}
211
a2e219fe 212void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 213{
4b7e6066 214 struct bgp_path_info_extra *e;
d62a17ae 215
c93a3b77
DS
216 if (!extra || !*extra)
217 return;
d62a17ae 218
c93a3b77 219 e = *extra;
d62a17ae 220
c93a3b77
DS
221 e->damp_info = NULL;
222 if (e->parent) {
40381db7 223 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 224
40381db7 225 if (bpi->net) {
0e70e6c8
DL
226 /* FIXME: since multiple e may have the same e->parent
227 * and e->parent->net is holding a refcount for each
228 * of them, we need to do some fudging here.
229 *
40381db7
DS
230 * WARNING: if bpi->net->lock drops to 0, bpi may be
231 * freed as well (because bpi->net was holding the
232 * last reference to bpi) => write after free!
0e70e6c8
DL
233 */
234 unsigned refcount;
235
40381db7 236 bpi = bgp_path_info_lock(bpi);
c10e14e9 237 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 238 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 239 if (!refcount)
40381db7
DS
240 bpi->net = NULL;
241 bgp_path_info_unlock(bpi);
0e70e6c8 242 }
18ee8310 243 bgp_path_info_unlock(e->parent);
c93a3b77 244 e->parent = NULL;
d62a17ae 245 }
c93a3b77
DS
246
247 if (e->bgp_orig)
248 bgp_unlock(e->bgp_orig);
c26edcda 249
ff3bf9a4
DS
250 if (e->aggr_suppressors)
251 list_delete(&e->aggr_suppressors);
252
26c03e43
AK
253 if (e->es_info)
254 bgp_evpn_path_es_info_free(e->es_info);
255
ce3c0614
PG
256 if ((*extra)->bgp_fs_iprule)
257 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 258 if ((*extra)->bgp_fs_pbr)
6a154c88 259 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 260 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
261}
262
18ee8310
DS
263/* Get bgp_path_info extra information for the given bgp_path_info, lazy
264 * allocated if required.
fb982c25 265 */
40381db7 266struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 267{
40381db7
DS
268 if (!pi->extra)
269 pi->extra = bgp_path_info_extra_new();
270 return pi->extra;
fb982c25
PJ
271}
272
718e3744 273/* Free bgp route information. */
9b6d8fcf 274static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 275{
05864da7 276 bgp_attr_unintern(&path->attr);
fb018d25 277
9b6d8fcf
DS
278 bgp_unlink_nexthop(path);
279 bgp_path_info_extra_free(&path->extra);
280 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
281 if (path->net)
282 bgp_addpath_free_info_data(&path->tx_addpath,
283 &path->net->tx_addpath);
718e3744 284
9b6d8fcf 285 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 286
9b6d8fcf 287 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 288}
289
9b6d8fcf 290struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 291{
9b6d8fcf
DS
292 path->lock++;
293 return path;
200df115 294}
295
9b6d8fcf 296struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 297{
9b6d8fcf
DS
298 assert(path && path->lock > 0);
299 path->lock--;
d62a17ae 300
9b6d8fcf 301 if (path->lock == 0) {
200df115 302#if 0
303 zlog_debug ("%s: unlocked and freeing", __func__);
304 zlog_backtrace (LOG_DEBUG);
305#endif
9b6d8fcf 306 bgp_path_info_free(path);
d62a17ae 307 return NULL;
308 }
200df115 309
310#if 0
9b6d8fcf 311 if (path->lock == 1)
200df115 312 {
313 zlog_debug ("%s: unlocked to 1", __func__);
314 zlog_backtrace (LOG_DEBUG);
315 }
316#endif
d62a17ae 317
9b6d8fcf 318 return path;
200df115 319}
320
f009ff26 321/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 322static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 323{
324 struct peer *peer;
325 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 326 bool set_flag = false;
f009ff26 327 struct bgp *bgp = NULL;
328 struct bgp_table *table = NULL;
329 afi_t afi = 0;
330 safi_t safi = 0;
f009ff26 331
332 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
333 * then the route selection is deferred
334 */
9bcb3eef 335 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 336 return 0;
337
9bcb3eef 338 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 339 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 340 zlog_debug(
56ca3b5b
DL
341 "Route %pBD is in workqueue and being processed, not deferred.",
342 dest);
b54892e0 343
5f9c1aa2 344 return 0;
345 }
346
9bcb3eef 347 table = bgp_dest_table(dest);
f009ff26 348 if (table) {
349 bgp = table->bgp;
350 afi = table->afi;
351 safi = table->safi;
352 }
353
9bcb3eef 354 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 355 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
356 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
357 continue;
358
359 /* Route selection is deferred if there is a stale path which
360 * which indicates peer is in restart mode
361 */
36235319
QY
362 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
363 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 364 set_flag = true;
f009ff26 365 } else {
366 /* If the peer is graceful restart capable and peer is
367 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
368 */
369 peer = old_pi->peer;
36235319
QY
370 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
371 && BGP_PEER_RESTARTING_MODE(peer)
372 && (old_pi
373 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 374 set_flag = true;
f009ff26 375 }
376 }
377 if (set_flag)
378 break;
379 }
380
381 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
382 * is active
383 */
2ba1fe69 384 if (set_flag && table) {
f009ff26 385 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
386 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
387 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 388 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 389 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
390 zlog_debug("DEFER route %pBD, dest %p", dest,
391 dest);
f009ff26 392 return 0;
393 }
394 }
395 return -1;
396}
397
9bcb3eef 398void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 399{
4b7e6066 400 struct bgp_path_info *top;
718e3744 401
9bcb3eef 402 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 403
6f94b685 404 pi->next = top;
40381db7 405 pi->prev = NULL;
d62a17ae 406 if (top)
40381db7 407 top->prev = pi;
9bcb3eef 408 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 409
40381db7 410 bgp_path_info_lock(pi);
9bcb3eef 411 bgp_dest_lock_node(dest);
40381db7 412 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 413 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 414 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 415}
416
d62a17ae 417/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 418 completion callback *only* */
9bcb3eef 419void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 420{
40381db7
DS
421 if (pi->next)
422 pi->next->prev = pi->prev;
423 if (pi->prev)
424 pi->prev->next = pi->next;
d62a17ae 425 else
9bcb3eef 426 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 427
40381db7
DS
428 bgp_path_info_mpath_dequeue(pi);
429 bgp_path_info_unlock(pi);
7fd28dd2 430 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 431 bgp_dest_unlock_node(dest);
718e3744 432}
433
9bcb3eef 434void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 435{
9bcb3eef 436 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 437 /* set of previous already took care of pcount */
40381db7 438 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 439}
440
18ee8310 441/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
442 called when a route is deleted and then quickly re-added before the
443 deletion has been processed */
9bcb3eef 444void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 445{
9bcb3eef 446 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 447 /* unset of previous already took care of pcount */
40381db7 448 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
449}
450
d62a17ae 451/* Adjust pcount as required */
9bcb3eef 452static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 453{
d62a17ae 454 struct bgp_table *table;
67174041 455
9bcb3eef 456 assert(dest && bgp_dest_table(dest));
40381db7 457 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 458
9bcb3eef 459 table = bgp_dest_table(dest);
67174041 460
40381db7 461 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 462 return;
463
40381db7
DS
464 if (!BGP_PATH_COUNTABLE(pi)
465 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 466
40381db7 467 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 468
469 /* slight hack, but more robust against errors. */
40381db7
DS
470 if (pi->peer->pcount[table->afi][table->safi])
471 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 472 else
450971aa 473 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 474 "Asked to decrement 0 prefix count for peer");
40381db7
DS
475 } else if (BGP_PATH_COUNTABLE(pi)
476 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
477 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
478 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 479 }
1a392d46
PJ
480}
481
40381db7
DS
482static int bgp_label_index_differs(struct bgp_path_info *pi1,
483 struct bgp_path_info *pi2)
28d58fd7 484{
40381db7 485 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 486}
1a392d46 487
18ee8310 488/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
489 * This is here primarily to keep prefix-count in check.
490 */
9bcb3eef 491void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 492 uint32_t flag)
1a392d46 493{
40381db7 494 SET_FLAG(pi->flags, flag);
d62a17ae 495
496 /* early bath if we know it's not a flag that changes countability state
497 */
498 if (!CHECK_FLAG(flag,
1defdda8 499 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 500 return;
501
9bcb3eef 502 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
503}
504
9bcb3eef 505void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 506 uint32_t flag)
1a392d46 507{
40381db7 508 UNSET_FLAG(pi->flags, flag);
d62a17ae 509
510 /* early bath if we know it's not a flag that changes countability state
511 */
512 if (!CHECK_FLAG(flag,
1defdda8 513 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 514 return;
515
9bcb3eef 516 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
517}
518
718e3744 519/* Get MED value. If MED value is missing and "bgp bestpath
520 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 521static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 522{
523 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
524 return attr->med;
525 else {
892fedb6 526 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 527 return BGP_MED_MAX;
528 else
529 return 0;
530 }
718e3744 531}
532
7533cad7
QY
533void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
534 size_t buf_len)
2ec1e66f 535{
40381db7 536 if (pi->addpath_rx_id)
7533cad7
QY
537 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
538 pi->peer->host, pi->addpath_rx_id);
d62a17ae 539 else
7533cad7 540 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 541}
9fbdd100 542
d62a17ae 543/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
544 */
18ee8310
DS
545static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
546 struct bgp_path_info *exist, int *paths_eq,
547 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
548 char *pfx_buf, afi_t afi, safi_t safi,
549 enum bgp_path_selection_reason *reason)
d62a17ae 550{
551 struct attr *newattr, *existattr;
552 bgp_peer_sort_t new_sort;
553 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
554 uint32_t new_pref;
555 uint32_t exist_pref;
556 uint32_t new_med;
557 uint32_t exist_med;
558 uint32_t new_weight;
559 uint32_t exist_weight;
d62a17ae 560 uint32_t newm, existm;
561 struct in_addr new_id;
562 struct in_addr exist_id;
563 int new_cluster;
564 int exist_cluster;
565 int internal_as_route;
566 int confed_as_route;
04d14c8b 567 int ret = 0;
d62a17ae 568 char new_buf[PATH_ADDPATH_STR_BUFFER];
569 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
570 uint32_t new_mm_seq;
571 uint32_t exist_mm_seq;
6d8c603a 572 int nh_cmp;
d071f237
AK
573 esi_t *exist_esi;
574 esi_t *new_esi;
575 bool same_esi;
576 bool old_proxy;
577 bool new_proxy;
33c6e933 578 bool new_origin, exist_origin;
d62a17ae 579
580 *paths_eq = 0;
581
582 /* 0. Null check. */
583 if (new == NULL) {
fdf81fa0 584 *reason = bgp_path_selection_none;
d62a17ae 585 if (debug)
586 zlog_debug("%s: new is NULL", pfx_buf);
587 return 0;
588 }
2ec1e66f 589
d62a17ae 590 if (debug)
7533cad7
QY
591 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
592 sizeof(new_buf));
718e3744 593
d62a17ae 594 if (exist == NULL) {
fdf81fa0 595 *reason = bgp_path_selection_first;
d62a17ae 596 if (debug)
597 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
598 new_buf);
599 return 1;
600 }
2ec1e66f 601
d62a17ae 602 if (debug) {
7533cad7
QY
603 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
604 sizeof(exist_buf));
d62a17ae 605 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
606 pfx_buf, new_buf, new->flags, exist_buf,
607 exist->flags);
608 }
8ff56318 609
d62a17ae 610 newattr = new->attr;
611 existattr = exist->attr;
612
613 /* For EVPN routes, we cannot just go by local vs remote, we have to
614 * look at the MAC mobility sequence number, if present.
615 */
616 if (safi == SAFI_EVPN) {
617 /* This is an error condition described in RFC 7432 Section
618 * 15.2. The RFC
619 * states that in this scenario "the PE MUST alert the operator"
620 * but it
621 * does not state what other action to take. In order to provide
622 * some
623 * consistency in this scenario we are going to prefer the path
624 * with the
625 * sticky flag.
626 */
627 if (newattr->sticky != existattr->sticky) {
628 if (!debug) {
9bcb3eef
DS
629 prefix2str(
630 bgp_dest_get_prefix(new->net), pfx_buf,
631 sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
18ee8310 632 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
633 new, new_buf, sizeof(new_buf));
634 bgp_path_info_path_with_addpath_rx_str(
635 exist, exist_buf, sizeof(exist_buf));
d62a17ae 636 }
637
638 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 639 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
640 if (debug)
641 zlog_debug(
642 "%s: %s wins over %s due to sticky MAC flag",
643 pfx_buf, new_buf, exist_buf);
d62a17ae 644 return 1;
645 }
646
647 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 648 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
649 if (debug)
650 zlog_debug(
651 "%s: %s loses to %s due to sticky MAC flag",
652 pfx_buf, new_buf, exist_buf);
d62a17ae 653 return 0;
654 }
655 }
128ea8ab 656
d071f237
AK
657 new_esi = bgp_evpn_attr_get_esi(newattr);
658 exist_esi = bgp_evpn_attr_get_esi(existattr);
659 if (bgp_evpn_is_esi_valid(new_esi) &&
660 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
661 same_esi = true;
662 } else {
663 same_esi = false;
664 }
665
666 /* If both paths have the same non-zero ES and
667 * one path is local it wins.
668 * PS: Note the local path wins even if the remote
669 * has the higher MM seq. The local path's
670 * MM seq will be fixed up to match the highest
671 * rem seq, subsequently.
672 */
673 if (same_esi) {
674 char esi_buf[ESI_STR_LEN];
675
676 if (bgp_evpn_is_path_local(bgp, new)) {
677 *reason = bgp_path_selection_evpn_local_path;
678 if (debug)
679 zlog_debug(
680 "%s: %s wins over %s as ES %s is same and local",
681 pfx_buf, new_buf, exist_buf,
682 esi_to_str(new_esi, esi_buf,
683 sizeof(esi_buf)));
684 return 1;
685 }
686 if (bgp_evpn_is_path_local(bgp, exist)) {
687 *reason = bgp_path_selection_evpn_local_path;
688 if (debug)
689 zlog_debug(
690 "%s: %s loses to %s as ES %s is same and local",
691 pfx_buf, new_buf, exist_buf,
692 esi_to_str(new_esi, esi_buf,
693 sizeof(esi_buf)));
694 return 0;
695 }
696 }
697
d62a17ae 698 new_mm_seq = mac_mobility_seqnum(newattr);
699 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 700
d62a17ae 701 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 702 *reason = bgp_path_selection_evpn_seq;
d62a17ae 703 if (debug)
704 zlog_debug(
705 "%s: %s wins over %s due to MM seq %u > %u",
706 pfx_buf, new_buf, exist_buf, new_mm_seq,
707 exist_mm_seq);
708 return 1;
709 }
8ff56318 710
d62a17ae 711 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 712 *reason = bgp_path_selection_evpn_seq;
d62a17ae 713 if (debug)
714 zlog_debug(
715 "%s: %s loses to %s due to MM seq %u < %u",
716 pfx_buf, new_buf, exist_buf, new_mm_seq,
717 exist_mm_seq);
718 return 0;
719 }
6d8c603a 720
d071f237
AK
721 /* if the sequence numbers and ESI are the same and one path
722 * is non-proxy it wins (over proxy)
723 */
724 new_proxy = bgp_evpn_attr_is_proxy(newattr);
725 old_proxy = bgp_evpn_attr_is_proxy(existattr);
726 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
727 old_proxy != new_proxy) {
728 if (!new_proxy) {
729 *reason = bgp_path_selection_evpn_non_proxy;
730 if (debug)
731 zlog_debug(
732 "%s: %s wins over %s, same seq/es and non-proxy",
733 pfx_buf, new_buf, exist_buf);
734 return 1;
735 }
736
737 *reason = bgp_path_selection_evpn_non_proxy;
738 if (debug)
739 zlog_debug(
740 "%s: %s loses to %s, same seq/es and non-proxy",
741 pfx_buf, new_buf, exist_buf);
742 return 0;
743 }
744
6d8c603a
AK
745 /*
746 * if sequence numbers are the same path with the lowest IP
747 * wins
748 */
749 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
750 if (nh_cmp < 0) {
fdf81fa0 751 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
752 if (debug)
753 zlog_debug(
23d0a753 754 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 755 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 756 &new->attr->nexthop);
6d8c603a
AK
757 return 1;
758 }
759 if (nh_cmp > 0) {
fdf81fa0 760 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
761 if (debug)
762 zlog_debug(
23d0a753 763 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 764 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 765 &new->attr->nexthop);
6d8c603a
AK
766 return 0;
767 }
d62a17ae 768 }
9fbdd100 769
d62a17ae 770 /* 1. Weight check. */
d62a17ae 771 new_weight = newattr->weight;
772 exist_weight = existattr->weight;
8ff56318 773
d62a17ae 774 if (new_weight > exist_weight) {
fdf81fa0 775 *reason = bgp_path_selection_weight;
d62a17ae 776 if (debug)
777 zlog_debug("%s: %s wins over %s due to weight %d > %d",
778 pfx_buf, new_buf, exist_buf, new_weight,
779 exist_weight);
780 return 1;
781 }
718e3744 782
d62a17ae 783 if (new_weight < exist_weight) {
fdf81fa0 784 *reason = bgp_path_selection_weight;
d62a17ae 785 if (debug)
786 zlog_debug("%s: %s loses to %s due to weight %d < %d",
787 pfx_buf, new_buf, exist_buf, new_weight,
788 exist_weight);
789 return 0;
790 }
9fbdd100 791
d62a17ae 792 /* 2. Local preference check. */
793 new_pref = exist_pref = bgp->default_local_pref;
794
795 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
796 new_pref = newattr->local_pref;
797 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
798 exist_pref = existattr->local_pref;
799
800 if (new_pref > exist_pref) {
fdf81fa0 801 *reason = bgp_path_selection_local_pref;
d62a17ae 802 if (debug)
803 zlog_debug(
804 "%s: %s wins over %s due to localpref %d > %d",
805 pfx_buf, new_buf, exist_buf, new_pref,
806 exist_pref);
807 return 1;
808 }
718e3744 809
d62a17ae 810 if (new_pref < exist_pref) {
fdf81fa0 811 *reason = bgp_path_selection_local_pref;
d62a17ae 812 if (debug)
813 zlog_debug(
814 "%s: %s loses to %s due to localpref %d < %d",
815 pfx_buf, new_buf, exist_buf, new_pref,
816 exist_pref);
817 return 0;
818 }
9fbdd100 819
d62a17ae 820 /* 3. Local route check. We prefer:
821 * - BGP_ROUTE_STATIC
822 * - BGP_ROUTE_AGGREGATE
823 * - BGP_ROUTE_REDISTRIBUTE
824 */
33c6e933
DS
825 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
826 new->sub_type == BGP_ROUTE_IMPORTED);
827 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
828 exist->sub_type == BGP_ROUTE_IMPORTED);
829
830 if (new_origin && !exist_origin) {
fdf81fa0 831 *reason = bgp_path_selection_local_route;
d62a17ae 832 if (debug)
833 zlog_debug(
834 "%s: %s wins over %s due to preferred BGP_ROUTE type",
835 pfx_buf, new_buf, exist_buf);
836 return 1;
837 }
718e3744 838
33c6e933 839 if (!new_origin && exist_origin) {
fdf81fa0 840 *reason = bgp_path_selection_local_route;
d62a17ae 841 if (debug)
842 zlog_debug(
843 "%s: %s loses to %s due to preferred BGP_ROUTE type",
844 pfx_buf, new_buf, exist_buf);
845 return 0;
6811845b 846 }
718e3744 847
d62a17ae 848 /* 4. AS path length check. */
892fedb6 849 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 850 int exist_hops = aspath_count_hops(existattr->aspath);
851 int exist_confeds = aspath_count_confeds(existattr->aspath);
852
892fedb6 853 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 854 int aspath_hops;
855
856 aspath_hops = aspath_count_hops(newattr->aspath);
857 aspath_hops += aspath_count_confeds(newattr->aspath);
858
859 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 860 *reason = bgp_path_selection_confed_as_path;
d62a17ae 861 if (debug)
862 zlog_debug(
863 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
864 pfx_buf, new_buf, exist_buf,
865 aspath_hops,
866 (exist_hops + exist_confeds));
867 return 1;
868 }
869
870 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 871 *reason = bgp_path_selection_confed_as_path;
d62a17ae 872 if (debug)
873 zlog_debug(
874 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
875 pfx_buf, new_buf, exist_buf,
876 aspath_hops,
877 (exist_hops + exist_confeds));
878 return 0;
879 }
880 } else {
881 int newhops = aspath_count_hops(newattr->aspath);
882
883 if (newhops < exist_hops) {
fdf81fa0 884 *reason = bgp_path_selection_as_path;
d62a17ae 885 if (debug)
886 zlog_debug(
887 "%s: %s wins over %s due to aspath hopcount %d < %d",
888 pfx_buf, new_buf, exist_buf,
889 newhops, exist_hops);
890 return 1;
891 }
892
893 if (newhops > exist_hops) {
fdf81fa0 894 *reason = bgp_path_selection_as_path;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s loses to %s due to aspath hopcount %d > %d",
898 pfx_buf, new_buf, exist_buf,
899 newhops, exist_hops);
900 return 0;
901 }
902 }
903 }
9fbdd100 904
d62a17ae 905 /* 5. Origin check. */
906 if (newattr->origin < existattr->origin) {
fdf81fa0 907 *reason = bgp_path_selection_origin;
d62a17ae 908 if (debug)
909 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
910 pfx_buf, new_buf, exist_buf,
911 bgp_origin_long_str[newattr->origin],
912 bgp_origin_long_str[existattr->origin]);
913 return 1;
914 }
718e3744 915
d62a17ae 916 if (newattr->origin > existattr->origin) {
fdf81fa0 917 *reason = bgp_path_selection_origin;
d62a17ae 918 if (debug)
919 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
920 pfx_buf, new_buf, exist_buf,
921 bgp_origin_long_str[newattr->origin],
922 bgp_origin_long_str[existattr->origin]);
923 return 0;
924 }
718e3744 925
d62a17ae 926 /* 6. MED check. */
927 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
928 && aspath_count_hops(existattr->aspath) == 0);
929 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
930 && aspath_count_confeds(existattr->aspath) > 0
931 && aspath_count_hops(newattr->aspath) == 0
932 && aspath_count_hops(existattr->aspath) == 0);
933
892fedb6
DA
934 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
935 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 936 || aspath_cmp_left(newattr->aspath, existattr->aspath)
937 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
938 || internal_as_route) {
939 new_med = bgp_med_value(new->attr, bgp);
940 exist_med = bgp_med_value(exist->attr, bgp);
941
942 if (new_med < exist_med) {
fdf81fa0 943 *reason = bgp_path_selection_med;
d62a17ae 944 if (debug)
945 zlog_debug(
946 "%s: %s wins over %s due to MED %d < %d",
947 pfx_buf, new_buf, exist_buf, new_med,
948 exist_med);
949 return 1;
950 }
8ff56318 951
d62a17ae 952 if (new_med > exist_med) {
fdf81fa0 953 *reason = bgp_path_selection_med;
d62a17ae 954 if (debug)
955 zlog_debug(
956 "%s: %s loses to %s due to MED %d > %d",
957 pfx_buf, new_buf, exist_buf, new_med,
958 exist_med);
959 return 0;
960 }
961 }
9fbdd100 962
d62a17ae 963 /* 7. Peer type check. */
964 new_sort = new->peer->sort;
965 exist_sort = exist->peer->sort;
966
967 if (new_sort == BGP_PEER_EBGP
968 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 969 *reason = bgp_path_selection_peer;
d62a17ae 970 if (debug)
971 zlog_debug(
972 "%s: %s wins over %s due to eBGP peer > iBGP peer",
973 pfx_buf, new_buf, exist_buf);
974 return 1;
975 }
718e3744 976
d62a17ae 977 if (exist_sort == BGP_PEER_EBGP
978 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 979 *reason = bgp_path_selection_peer;
d62a17ae 980 if (debug)
981 zlog_debug(
982 "%s: %s loses to %s due to iBGP peer < eBGP peer",
983 pfx_buf, new_buf, exist_buf);
984 return 0;
985 }
8ff56318 986
d62a17ae 987 /* 8. IGP metric check. */
988 newm = existm = 0;
8ff56318 989
d62a17ae 990 if (new->extra)
991 newm = new->extra->igpmetric;
992 if (exist->extra)
993 existm = exist->extra->igpmetric;
9fbdd100 994
d62a17ae 995 if (newm < existm) {
996 if (debug)
997 zlog_debug(
d588b995 998 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 999 pfx_buf, new_buf, exist_buf, newm, existm);
1000 ret = 1;
1001 }
718e3744 1002
d62a17ae 1003 if (newm > existm) {
1004 if (debug)
1005 zlog_debug(
d588b995 1006 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1007 pfx_buf, new_buf, exist_buf, newm, existm);
1008 ret = 0;
5e242b0d 1009 }
5e242b0d 1010
d62a17ae 1011 /* 9. Same IGP metric. Compare the cluster list length as
1012 representative of IGP hops metric. Rewrite the metric value
1013 pair (newm, existm) with the cluster list length. Prefer the
1014 path with smaller cluster list length. */
1015 if (newm == existm) {
bf0d28dc
DS
1016 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1017 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1018 && (mpath_cfg == NULL
1019 || CHECK_FLAG(
1020 mpath_cfg->ibgp_flags,
1021 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1022 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1023 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1024
1025 if (newm < existm) {
1026 if (debug)
1027 zlog_debug(
d588b995 1028 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1029 pfx_buf, new_buf, exist_buf,
1030 newm, existm);
1031 ret = 1;
1032 }
1033
1034 if (newm > existm) {
1035 if (debug)
1036 zlog_debug(
d588b995 1037 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1038 pfx_buf, new_buf, exist_buf,
1039 newm, existm);
1040 ret = 0;
1041 }
1042 }
1043 }
31a4638f 1044
d62a17ae 1045 /* 10. confed-external vs. confed-internal */
1046 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1047 if (new_sort == BGP_PEER_CONFED
1048 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1049 *reason = bgp_path_selection_confed;
d62a17ae 1050 if (debug)
1051 zlog_debug(
1052 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1053 pfx_buf, new_buf, exist_buf);
1054 return 1;
1055 }
718e3744 1056
d62a17ae 1057 if (exist_sort == BGP_PEER_CONFED
1058 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1059 *reason = bgp_path_selection_confed;
d62a17ae 1060 if (debug)
1061 zlog_debug(
1062 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1063 pfx_buf, new_buf, exist_buf);
1064 return 0;
1065 }
1066 }
718e3744 1067
d62a17ae 1068 /* 11. Maximum path check. */
1069 if (newm == existm) {
1070 /* If one path has a label but the other does not, do not treat
1071 * them as equals for multipath
1072 */
a4d82a8a 1073 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1074 != (exist->extra
b57ba6d2 1075 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1076 if (debug)
1077 zlog_debug(
1078 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1079 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1080 } else if (CHECK_FLAG(bgp->flags,
1081 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1082
1083 /*
1084 * For the two paths, all comparison steps till IGP
1085 * metric
1086 * have succeeded - including AS_PATH hop count. Since
1087 * 'bgp
1088 * bestpath as-path multipath-relax' knob is on, we
1089 * don't need
1090 * an exact match of AS_PATH. Thus, mark the paths are
1091 * equal.
1092 * That will trigger both these paths to get into the
1093 * multipath
1094 * array.
1095 */
1096 *paths_eq = 1;
1097
1098 if (debug)
1099 zlog_debug(
1100 "%s: %s and %s are equal via multipath-relax",
1101 pfx_buf, new_buf, exist_buf);
1102 } else if (new->peer->sort == BGP_PEER_IBGP) {
1103 if (aspath_cmp(new->attr->aspath,
1104 exist->attr->aspath)) {
1105 *paths_eq = 1;
1106
1107 if (debug)
1108 zlog_debug(
1109 "%s: %s and %s are equal via matching aspaths",
1110 pfx_buf, new_buf, exist_buf);
1111 }
1112 } else if (new->peer->as == exist->peer->as) {
1113 *paths_eq = 1;
1114
1115 if (debug)
1116 zlog_debug(
1117 "%s: %s and %s are equal via same remote-as",
1118 pfx_buf, new_buf, exist_buf);
1119 }
1120 } else {
1121 /*
1122 * TODO: If unequal cost ibgp multipath is enabled we can
1123 * mark the paths as equal here instead of returning
1124 */
1125 if (debug) {
1126 if (ret == 1)
1127 zlog_debug(
1128 "%s: %s wins over %s after IGP metric comparison",
1129 pfx_buf, new_buf, exist_buf);
1130 else
1131 zlog_debug(
1132 "%s: %s loses to %s after IGP metric comparison",
1133 pfx_buf, new_buf, exist_buf);
1134 }
fdf81fa0 1135 *reason = bgp_path_selection_igp_metric;
d62a17ae 1136 return ret;
1137 }
718e3744 1138
d62a17ae 1139 /* 12. If both paths are external, prefer the path that was received
1140 first (the oldest one). This step minimizes route-flap, since a
1141 newer path won't displace an older one, even if it was the
1142 preferred route based on the additional decision criteria below. */
892fedb6 1143 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1144 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1145 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1146 *reason = bgp_path_selection_older;
d62a17ae 1147 if (debug)
1148 zlog_debug(
1149 "%s: %s wins over %s due to oldest external",
1150 pfx_buf, new_buf, exist_buf);
1151 return 1;
1152 }
9fbdd100 1153
1defdda8 1154 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1155 *reason = bgp_path_selection_older;
d62a17ae 1156 if (debug)
1157 zlog_debug(
1158 "%s: %s loses to %s due to oldest external",
1159 pfx_buf, new_buf, exist_buf);
1160 return 0;
1161 }
1162 }
718e3744 1163
d62a17ae 1164 /* 13. Router-ID comparision. */
1165 /* If one of the paths is "stale", the corresponding peer router-id will
1166 * be 0 and would always win over the other path. If originator id is
1167 * used for the comparision, it will decide which path is better.
1168 */
1169 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1170 new_id.s_addr = newattr->originator_id.s_addr;
1171 else
1172 new_id.s_addr = new->peer->remote_id.s_addr;
1173 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1174 exist_id.s_addr = existattr->originator_id.s_addr;
1175 else
1176 exist_id.s_addr = exist->peer->remote_id.s_addr;
1177
1178 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1179 *reason = bgp_path_selection_router_id;
d62a17ae 1180 if (debug)
1181 zlog_debug(
1182 "%s: %s wins over %s due to Router-ID comparison",
1183 pfx_buf, new_buf, exist_buf);
1184 return 1;
1185 }
718e3744 1186
d62a17ae 1187 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1188 *reason = bgp_path_selection_router_id;
d62a17ae 1189 if (debug)
1190 zlog_debug(
1191 "%s: %s loses to %s due to Router-ID comparison",
1192 pfx_buf, new_buf, exist_buf);
1193 return 0;
1194 }
9fbdd100 1195
d62a17ae 1196 /* 14. Cluster length comparision. */
1197 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1198 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1199
1200 if (new_cluster < exist_cluster) {
fdf81fa0 1201 *reason = bgp_path_selection_cluster_length;
d62a17ae 1202 if (debug)
1203 zlog_debug(
1204 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1205 pfx_buf, new_buf, exist_buf, new_cluster,
1206 exist_cluster);
1207 return 1;
1208 }
718e3744 1209
d62a17ae 1210 if (new_cluster > exist_cluster) {
fdf81fa0 1211 *reason = bgp_path_selection_cluster_length;
d62a17ae 1212 if (debug)
1213 zlog_debug(
1214 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1215 pfx_buf, new_buf, exist_buf, new_cluster,
1216 exist_cluster);
1217 return 0;
1218 }
9fbdd100 1219
d62a17ae 1220 /* 15. Neighbor address comparision. */
1221 /* Do this only if neither path is "stale" as stale paths do not have
1222 * valid peer information (as the connection may or may not be up).
1223 */
1defdda8 1224 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1225 *reason = bgp_path_selection_stale;
d62a17ae 1226 if (debug)
1227 zlog_debug(
1228 "%s: %s wins over %s due to latter path being STALE",
1229 pfx_buf, new_buf, exist_buf);
1230 return 1;
1231 }
0de5153c 1232
1defdda8 1233 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1234 *reason = bgp_path_selection_stale;
d62a17ae 1235 if (debug)
1236 zlog_debug(
1237 "%s: %s loses to %s due to former path being STALE",
1238 pfx_buf, new_buf, exist_buf);
1239 return 0;
1240 }
718e3744 1241
d62a17ae 1242 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1243 if (new->peer->su_remote == NULL) {
1244 *reason = bgp_path_selection_local_configured;
d62a17ae 1245 return 0;
fdf81fa0
DS
1246 }
1247 if (exist->peer->su_remote == NULL) {
1248 *reason = bgp_path_selection_local_configured;
d62a17ae 1249 return 1;
fdf81fa0 1250 }
9fbdd100 1251
d62a17ae 1252 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1253
1254 if (ret == 1) {
fdf81fa0 1255 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1256 if (debug)
1257 zlog_debug(
1258 "%s: %s loses to %s due to Neighor IP comparison",
1259 pfx_buf, new_buf, exist_buf);
1260 return 0;
1261 }
1262
1263 if (ret == -1) {
fdf81fa0 1264 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1265 if (debug)
1266 zlog_debug(
1267 "%s: %s wins over %s due to Neighor IP comparison",
1268 pfx_buf, new_buf, exist_buf);
1269 return 1;
1270 }
9fbdd100 1271
fdf81fa0 1272 *reason = bgp_path_selection_default;
d62a17ae 1273 if (debug)
1274 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1275 pfx_buf, new_buf, exist_buf);
718e3744 1276
d62a17ae 1277 return 1;
718e3744 1278}
1279
d071f237
AK
1280
1281int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1282 struct bgp_path_info *exist, int *paths_eq)
1283{
1284 enum bgp_path_selection_reason reason;
1285 char pfx_buf[PREFIX2STR_BUFFER];
1286
1287 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1288 AFI_L2VPN, SAFI_EVPN, &reason);
1289}
1290
65efcfce
LB
1291/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1292 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1293 * multipath is enabled
65efcfce 1294 * This version is compatible with */
18ee8310
DS
1295int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1296 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1297 afi_t afi, safi_t safi,
1298 enum bgp_path_selection_reason *reason)
d62a17ae 1299{
1300 int paths_eq;
1301 int ret;
18ee8310 1302 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1303 afi, safi, reason);
d62a17ae 1304
1305 if (paths_eq)
1306 ret = 0;
1307 else {
1308 if (ret == 1)
1309 ret = -1;
1310 else
1311 ret = 1;
1312 }
1313 return ret;
65efcfce
LB
1314}
1315
5a1ae2c2
DS
1316static enum filter_type bgp_input_filter(struct peer *peer,
1317 const struct prefix *p,
d62a17ae 1318 struct attr *attr, afi_t afi,
1319 safi_t safi)
718e3744 1320{
d62a17ae 1321 struct bgp_filter *filter;
6401252f 1322 enum filter_type ret = FILTER_PERMIT;
718e3744 1323
d62a17ae 1324 filter = &peer->filter[afi][safi];
718e3744 1325
d62a17ae 1326#define FILTER_EXIST_WARN(F, f, filter) \
1327 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1328 zlog_debug("%s: Could not find configured input %s-list %s!", \
1329 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1330
1331 if (DISTRIBUTE_IN_NAME(filter)) {
1332 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1333
6401252f
QY
1334 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1335 == FILTER_DENY) {
1336 ret = FILTER_DENY;
1337 goto done;
1338 }
d62a17ae 1339 }
1340
1341 if (PREFIX_LIST_IN_NAME(filter)) {
1342 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1343
6401252f
QY
1344 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1345 == PREFIX_DENY) {
1346 ret = FILTER_DENY;
1347 goto done;
1348 }
d62a17ae 1349 }
1350
1351 if (FILTER_LIST_IN_NAME(filter)) {
1352 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1353
1354 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1355 == AS_FILTER_DENY) {
1356 ret = FILTER_DENY;
1357 goto done;
1358 }
d62a17ae 1359 }
1360
6401252f 1361done:
c7bb4f00 1362 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1363 char pfxprint[PREFIX2STR_BUFFER];
1364
1365 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1366 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1367 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1368 }
1369
1370 return ret;
650f76c2 1371#undef FILTER_EXIST_WARN
718e3744 1372}
1373
b8685f9b
DS
1374static enum filter_type bgp_output_filter(struct peer *peer,
1375 const struct prefix *p,
d62a17ae 1376 struct attr *attr, afi_t afi,
1377 safi_t safi)
718e3744 1378{
d62a17ae 1379 struct bgp_filter *filter;
6401252f 1380 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1381
1382 filter = &peer->filter[afi][safi];
1383
1384#define FILTER_EXIST_WARN(F, f, filter) \
1385 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1386 zlog_debug("%s: Could not find configured output %s-list %s!", \
1387 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1388
d62a17ae 1389 if (DISTRIBUTE_OUT_NAME(filter)) {
1390 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1391
6401252f
QY
1392 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1393 == FILTER_DENY) {
1394 ret = FILTER_DENY;
1395 goto done;
1396 }
d62a17ae 1397 }
1398
1399 if (PREFIX_LIST_OUT_NAME(filter)) {
1400 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1401
d62a17ae 1402 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1403 == PREFIX_DENY) {
1404 ret = FILTER_DENY;
1405 goto done;
1406 }
d62a17ae 1407 }
718e3744 1408
d62a17ae 1409 if (FILTER_LIST_OUT_NAME(filter)) {
1410 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1411
d62a17ae 1412 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1413 == AS_FILTER_DENY) {
1414 ret = FILTER_DENY;
1415 goto done;
1416 }
1417 }
1418
c7bb4f00 1419 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1420 char pfxprint[PREFIX2STR_BUFFER];
1421
1422 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1423 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1424 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1425 }
718e3744 1426
6401252f
QY
1427done:
1428 return ret;
650f76c2 1429#undef FILTER_EXIST_WARN
718e3744 1430}
1431
1432/* If community attribute includes no_export then return 1. */
3dc339cd 1433static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1434{
1435 if (attr->community) {
1436 /* NO_ADVERTISE check. */
1437 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1438 return true;
d62a17ae 1439
1440 /* NO_EXPORT check. */
1441 if (peer->sort == BGP_PEER_EBGP
1442 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1443 return true;
d62a17ae 1444
1445 /* NO_EXPORT_SUBCONFED check. */
1446 if (peer->sort == BGP_PEER_EBGP
1447 || peer->sort == BGP_PEER_CONFED)
1448 if (community_include(attr->community,
1449 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1450 return true;
d62a17ae 1451 }
3dc339cd 1452 return false;
718e3744 1453}
1454
1455/* Route reflection loop check. */
3dc339cd 1456static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1457{
d62a17ae 1458 struct in_addr cluster_id;
779fee93 1459 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1460
779fee93 1461 if (cluster) {
d62a17ae 1462 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1463 cluster_id = peer->bgp->cluster_id;
1464 else
1465 cluster_id = peer->bgp->router_id;
1466
779fee93 1467 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1468 return true;
d62a17ae 1469 }
3dc339cd 1470 return false;
718e3744 1471}
6b0655a2 1472
5a1ae2c2 1473static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1474 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1475 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1476 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1477{
d62a17ae 1478 struct bgp_filter *filter;
82b692c0
LK
1479 struct bgp_path_info rmap_path = { 0 };
1480 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1481 route_map_result_t ret;
1482 struct route_map *rmap = NULL;
718e3744 1483
d62a17ae 1484 filter = &peer->filter[afi][safi];
718e3744 1485
d62a17ae 1486 /* Apply default weight value. */
1487 if (peer->weight[afi][safi])
1488 attr->weight = peer->weight[afi][safi];
718e3744 1489
d62a17ae 1490 if (rmap_name) {
1491 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1492
d62a17ae 1493 if (rmap == NULL)
1494 return RMAP_DENY;
1495 } else {
1496 if (ROUTE_MAP_IN_NAME(filter)) {
1497 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1498
d62a17ae 1499 if (rmap == NULL)
1500 return RMAP_DENY;
1501 }
1502 }
0b16f239 1503
d62a17ae 1504 /* Route map apply. */
1505 if (rmap) {
40381db7 1506 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1507 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1508 rmap_path.peer = peer;
1509 rmap_path.attr = attr;
82b692c0 1510 rmap_path.extra = &extra;
9bcb3eef 1511 rmap_path.net = dest;
196c6b09 1512
82b692c0
LK
1513 extra.num_labels = num_labels;
1514 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1515 memcpy(extra.label, label,
1516 num_labels * sizeof(mpls_label_t));
718e3744 1517
d62a17ae 1518 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1519
d62a17ae 1520 /* Apply BGP route map to the attribute. */
1782514f 1521 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1522
d62a17ae 1523 peer->rmap_type = 0;
0b16f239 1524
1f2263be 1525 if (ret == RMAP_DENYMATCH)
d62a17ae 1526 return RMAP_DENY;
0b16f239 1527 }
d62a17ae 1528 return RMAP_PERMIT;
0b16f239
DS
1529}
1530
5f040085 1531static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1532 struct attr *attr, afi_t afi, safi_t safi,
1533 const char *rmap_name)
0b16f239 1534{
40381db7 1535 struct bgp_path_info rmap_path;
d62a17ae 1536 route_map_result_t ret;
1537 struct route_map *rmap = NULL;
d7c0a89a 1538 uint8_t rmap_type;
0b16f239 1539
b787157a
DS
1540 /*
1541 * So if we get to this point and have no rmap_name
1542 * we want to just show the output as it currently
1543 * exists.
1544 */
1545 if (!rmap_name)
1546 return RMAP_PERMIT;
0b16f239 1547
d62a17ae 1548 /* Apply default weight value. */
1549 if (peer->weight[afi][safi])
1550 attr->weight = peer->weight[afi][safi];
0b16f239 1551
b787157a 1552 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1553
b787157a
DS
1554 /*
1555 * If we have a route map name and we do not find
1556 * the routemap that means we have an implicit
1557 * deny.
1558 */
1559 if (rmap == NULL)
1560 return RMAP_DENY;
0b16f239 1561
40381db7 1562 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1563 /* Route map apply. */
b787157a 1564 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1565 rmap_path.peer = peer;
1566 rmap_path.attr = attr;
0b16f239 1567
0f672529 1568 rmap_type = peer->rmap_type;
b787157a 1569 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1570
b787157a 1571 /* Apply BGP route map to the attribute. */
1782514f 1572 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1573
0f672529 1574 peer->rmap_type = rmap_type;
b787157a
DS
1575
1576 if (ret == RMAP_DENYMATCH)
1577 /*
1578 * caller has multiple error paths with bgp_attr_flush()
1579 */
1580 return RMAP_DENY;
ac41b2a2 1581
d62a17ae 1582 return RMAP_PERMIT;
718e3744 1583}
6b0655a2 1584
5000f21c 1585/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1586static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1587 struct peer *peer, struct attr *attr)
1588{
1589 if (peer->sort == BGP_PEER_EBGP
1590 && (peer_af_flag_check(peer, afi, safi,
1591 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1592 || peer_af_flag_check(peer, afi, safi,
1593 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1594 || peer_af_flag_check(peer, afi, safi,
1595 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1596 || peer_af_flag_check(peer, afi, safi,
1597 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1598 // Take action on the entire aspath
1599 if (peer_af_flag_check(peer, afi, safi,
1600 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1601 || peer_af_flag_check(peer, afi, safi,
1602 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1603 if (peer_af_flag_check(
1604 peer, afi, safi,
1605 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1606 attr->aspath = aspath_replace_private_asns(
bf26b80e 1607 attr->aspath, bgp->as, peer->as);
d62a17ae 1608
1609 // The entire aspath consists of private ASNs so create
1610 // an empty aspath
1611 else if (aspath_private_as_check(attr->aspath))
1612 attr->aspath = aspath_empty_get();
1613
1614 // There are some public and some private ASNs, remove
1615 // the private ASNs
1616 else
1617 attr->aspath = aspath_remove_private_asns(
bf26b80e 1618 attr->aspath, peer->as);
d62a17ae 1619 }
1620
1621 // 'all' was not specified so the entire aspath must be private
1622 // ASNs
1623 // for us to do anything
1624 else if (aspath_private_as_check(attr->aspath)) {
1625 if (peer_af_flag_check(
1626 peer, afi, safi,
1627 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1628 attr->aspath = aspath_replace_private_asns(
bf26b80e 1629 attr->aspath, bgp->as, peer->as);
d62a17ae 1630 else
1631 attr->aspath = aspath_empty_get();
1632 }
1633 }
5000f21c
DS
1634}
1635
c7122e14 1636/* If this is an EBGP peer with as-override */
d62a17ae 1637static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1638 struct peer *peer, struct attr *attr)
1639{
1640 if (peer->sort == BGP_PEER_EBGP
1641 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1642 if (aspath_single_asn_check(attr->aspath, peer->as))
1643 attr->aspath = aspath_replace_specific_asn(
1644 attr->aspath, peer->as, bgp->as);
1645 }
1646}
1647
7f323236
DW
1648void bgp_attr_add_gshut_community(struct attr *attr)
1649{
1650 struct community *old;
1651 struct community *new;
1652 struct community *merge;
1653 struct community *gshut;
1654
1655 old = attr->community;
1656 gshut = community_str2com("graceful-shutdown");
1657
990f4f91 1658 assert(gshut);
1659
7f323236
DW
1660 if (old) {
1661 merge = community_merge(community_dup(old), gshut);
1662
a4d82a8a 1663 if (old->refcnt == 0)
3c1f53de 1664 community_free(&old);
7f323236
DW
1665
1666 new = community_uniq_sort(merge);
3c1f53de 1667 community_free(&merge);
7f323236
DW
1668 } else {
1669 new = community_dup(gshut);
1670 }
1671
3c1f53de 1672 community_free(&gshut);
7f323236
DW
1673 attr->community = new;
1674 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1675
1676 /* When we add the graceful-shutdown community we must also
1677 * lower the local-preference */
1678 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1679 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1680}
1681
1682
e73c112e
MK
1683/* Notify BGP Conditional advertisement scanner process. */
1684void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1685{
1686 struct peer *temp_peer;
1687 struct peer *peer = SUBGRP_PEER(subgrp);
1688 struct listnode *temp_node, *temp_nnode = NULL;
1689 afi_t afi = SUBGRP_AFI(subgrp);
1690 safi_t safi = SUBGRP_SAFI(subgrp);
1691 struct bgp *bgp = SUBGRP_INST(subgrp);
1692 struct bgp_filter *filter = &peer->filter[afi][safi];
1693
1694 if (!ADVERTISE_MAP_NAME(filter))
1695 return;
1696
1697 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1698 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1699 continue;
1700
1701 if (peer != temp_peer)
1702 continue;
1703
1704 temp_peer->advmap_table_change = true;
1705 break;
1706 }
1707}
1708
1709
f2ee6d5c 1710void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1711{
960035b2 1712 if (family == AF_INET) {
975a328e
DA
1713 attr->nexthop.s_addr = INADDR_ANY;
1714 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1715 }
d62a17ae 1716 if (family == AF_INET6)
1717 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1718 if (family == AF_EVPN)
1719 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1720}
1721
9bcb3eef 1722bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1723 struct update_subgroup *subgrp,
7f7940e6
MK
1724 const struct prefix *p, struct attr *attr,
1725 bool skip_rmap_check)
d62a17ae 1726{
1727 struct bgp_filter *filter;
1728 struct peer *from;
1729 struct peer *peer;
1730 struct peer *onlypeer;
1731 struct bgp *bgp;
40381db7 1732 struct attr *piattr;
b68885f9 1733 route_map_result_t ret;
d62a17ae 1734 int transparent;
1735 int reflect;
1736 afi_t afi;
1737 safi_t safi;
1738 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1739 bool nh_reset = false;
1740 uint64_t cum_bw;
d62a17ae 1741
1742 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1743 return false;
d62a17ae 1744
1745 afi = SUBGRP_AFI(subgrp);
1746 safi = SUBGRP_SAFI(subgrp);
1747 peer = SUBGRP_PEER(subgrp);
1748 onlypeer = NULL;
1749 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1750 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1751
40381db7 1752 from = pi->peer;
d62a17ae 1753 filter = &peer->filter[afi][safi];
1754 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1755 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1756 : pi->attr;
3f9c7369 1757
49e5a4a0 1758#ifdef ENABLE_BGP_VNC
d62a17ae 1759 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1760 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1761 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1762
1763 /*
1764 * direct and direct_ext type routes originate internally even
1765 * though they can have peer pointers that reference other
1766 * systems
1767 */
8228a9a7
DS
1768 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1769 __func__, p);
d62a17ae 1770 samepeer_safe = 1;
1771 }
65efcfce
LB
1772#endif
1773
ddb5b488
PZ
1774 if (((afi == AFI_IP) || (afi == AFI_IP6))
1775 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1776 && (pi->type == ZEBRA_ROUTE_BGP)
1777 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1778
1779 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1780
1781 samepeer_safe = 1;
1782 }
1783
d62a17ae 1784 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1785 * pi is valid */
1786 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1787 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1788 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1789 return false;
d62a17ae 1790 }
adbac85e 1791
d62a17ae 1792 /* If this is not the bestpath then check to see if there is an enabled
1793 * addpath
1794 * feature that requires us to advertise it */
40381db7 1795 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1796 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1797 return false;
d62a17ae 1798 }
1799 }
06370dac 1800
d62a17ae 1801 /* Aggregate-address suppress check. */
4056a5f6
RZ
1802 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1803 return false;
3f9c7369 1804
13b7e7f0
DS
1805 /*
1806 * If we are doing VRF 2 VRF leaking via the import
1807 * statement, we want to prevent the route going
1808 * off box as that the RT and RD created are localy
1809 * significant and globaly useless.
1810 */
40381db7
DS
1811 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1812 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1813 return false;
13b7e7f0 1814
d62a17ae 1815 /* If it's labeled safi, make sure the route has a valid label. */
1816 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1817 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1818 if (!bgp_is_valid_label(&label)) {
1819 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1820 zlog_debug("u%" PRIu64 ":s%" PRIu64
1821 " %pFX is filtered - no label (%p)",
d62a17ae 1822 subgrp->update_group->id, subgrp->id,
8228a9a7 1823 p, &label);
3dc339cd 1824 return false;
d62a17ae 1825 }
1826 }
cd1964ff 1827
d62a17ae 1828 /* Do not send back route to sender. */
1829 if (onlypeer && from == onlypeer) {
3dc339cd 1830 return false;
d62a17ae 1831 }
3f9c7369 1832
d62a17ae 1833 /* Do not send the default route in the BGP table if the neighbor is
1834 * configured for default-originate */
1835 if (CHECK_FLAG(peer->af_flags[afi][safi],
1836 PEER_FLAG_DEFAULT_ORIGINATE)) {
1837 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1838 return false;
d62a17ae 1839 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1840 return false;
d62a17ae 1841 }
4125bb67 1842
d62a17ae 1843 /* Transparency check. */
1844 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1845 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1846 transparent = 1;
1847 else
1848 transparent = 0;
1849
1850 /* If community is not disabled check the no-export and local. */
40381db7 1851 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1852 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1853 zlog_debug("%s: community filter check fail for %pFX",
1854 __func__, p);
3dc339cd 1855 return false;
d62a17ae 1856 }
3f9c7369 1857
d62a17ae 1858 /* If the attribute has originator-id and it is same as remote
1859 peer's id. */
40381db7
DS
1860 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1861 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1862 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1863 zlog_debug(
8228a9a7
DS
1864 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1865 onlypeer->host, p);
3dc339cd 1866 return false;
d62a17ae 1867 }
3f9c7369 1868
d62a17ae 1869 /* ORF prefix-list filter check */
1870 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1871 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1872 || CHECK_FLAG(peer->af_cap[afi][safi],
1873 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1874 if (peer->orf_plist[afi][safi]) {
1875 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1876 == PREFIX_DENY) {
1877 if (bgp_debug_update(NULL, p,
1878 subgrp->update_group, 0))
1879 zlog_debug(
8228a9a7
DS
1880 "%s [Update:SEND] %pFX is filtered via ORF",
1881 peer->host, p);
3dc339cd 1882 return false;
d62a17ae 1883 }
1884 }
1885
1886 /* Output filter check. */
40381db7 1887 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1888 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1889 zlog_debug("%s [Update:SEND] %pFX is filtered",
1890 peer->host, p);
3dc339cd 1891 return false;
d62a17ae 1892 }
3f9c7369 1893
d62a17ae 1894 /* AS path loop check. */
2b31007c
RZ
1895 if (onlypeer && onlypeer->as_path_loop_detection
1896 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1897 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1898 zlog_debug(
3efd0893 1899 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1900 onlypeer->host, onlypeer->as);
3dc339cd 1901 return false;
d62a17ae 1902 }
3f9c7369 1903
d62a17ae 1904 /* If we're a CONFED we need to loop check the CONFED ID too */
1905 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1906 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1907 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1908 zlog_debug(
3efd0893 1909 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1910 peer->host, bgp->confed_id);
3dc339cd 1911 return false;
d62a17ae 1912 }
3f9c7369 1913 }
3f9c7369 1914
d62a17ae 1915 /* Route-Reflect check. */
1916 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1917 reflect = 1;
1918 else
1919 reflect = 0;
1920
1921 /* IBGP reflection check. */
1922 if (reflect && !samepeer_safe) {
1923 /* A route from a Client peer. */
1924 if (CHECK_FLAG(from->af_flags[afi][safi],
1925 PEER_FLAG_REFLECTOR_CLIENT)) {
1926 /* Reflect to all the Non-Client peers and also to the
1927 Client peers other than the originator. Originator
1928 check
1929 is already done. So there is noting to do. */
1930 /* no bgp client-to-client reflection check. */
892fedb6
DA
1931 if (CHECK_FLAG(bgp->flags,
1932 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1933 if (CHECK_FLAG(peer->af_flags[afi][safi],
1934 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1935 return false;
d62a17ae 1936 } else {
1937 /* A route from a Non-client peer. Reflect to all other
1938 clients. */
1939 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1940 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1941 return false;
d62a17ae 1942 }
1943 }
3f9c7369 1944
d62a17ae 1945 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1946 *attr = *piattr;
d62a17ae 1947
1948 /* If local-preference is not set. */
1949 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1950 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1951 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1952 attr->local_pref = bgp->default_local_pref;
3f9c7369 1953 }
3f9c7369 1954
d62a17ae 1955 /* If originator-id is not set and the route is to be reflected,
1956 set the originator id */
1957 if (reflect
1958 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1959 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
1960 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
1961 }
3f9c7369 1962
d62a17ae 1963 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
1964 */
1965 if (peer->sort == BGP_PEER_EBGP
1966 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
1967 if (from != bgp->peer_self && !transparent
1968 && !CHECK_FLAG(peer->af_flags[afi][safi],
1969 PEER_FLAG_MED_UNCHANGED))
1970 attr->flag &=
1971 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
1972 }
3f9c7369 1973
d62a17ae 1974 /* Since the nexthop attribute can vary per peer, it is not explicitly
1975 * set
1976 * in announce check, only certain flags and length (or number of
1977 * nexthops
1978 * -- for IPv6/MP_REACH) are set here in order to guide the update
1979 * formation
1980 * code in setting the nexthop(s) on a per peer basis in
1981 * reformat_peer().
1982 * Typically, the source nexthop in the attribute is preserved but in
1983 * the
1984 * scenarios where we know it will always be overwritten, we reset the
1985 * nexthop to "0" in an attempt to achieve better Update packing. An
1986 * example of this is when a prefix from each of 2 IBGP peers needs to
1987 * be
1988 * announced to an EBGP peer (and they have the same attributes barring
1989 * their nexthop).
1990 */
1991 if (reflect)
1992 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
1993
1994#define NEXTHOP_IS_V6 \
1995 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
1996 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
1997 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
1998 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
1999
2000 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2001 * if
2002 * the peer (group) is configured to receive link-local nexthop
2003 * unchanged
c728d027
DA
2004 * and it is available in the prefix OR we're not reflecting the route,
2005 * link-local nexthop address is valid and
d62a17ae 2006 * the peer (group) to whom we're going to announce is on a shared
2007 * network
2008 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2009 * By checking if nexthop LL address is valid we are sure that
2010 * we do not announce LL address as `::`.
d62a17ae 2011 */
2012 if (NEXTHOP_IS_V6) {
2013 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2014 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2015 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2016 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2017 || (!reflect
2018 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2019 && peer->shared_network
d62a17ae 2020 && (from == bgp->peer_self
2021 || peer->sort == BGP_PEER_EBGP))) {
2022 attr->mp_nexthop_len =
2023 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2024 }
3f9c7369 2025
d62a17ae 2026 /* Clear off link-local nexthop in source, whenever it is not
2027 * needed to
2028 * ensure more prefixes share the same attribute for
2029 * announcement.
2030 */
2031 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2032 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2033 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2034 }
3f9c7369 2035
d62a17ae 2036 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2037 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2038
2039 /* Route map & unsuppress-map apply. */
7f7940e6 2040 if (!skip_rmap_check
e73c112e 2041 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2042 struct bgp_path_info rmap_path = {0};
2043 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2044 struct attr dummy_attr = {0};
d62a17ae 2045
e34291b8 2046 /* Fill temp path_info */
9bcb3eef
DS
2047 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2048 pi, peer, attr);
16f7ce2b 2049
d62a17ae 2050 /* don't confuse inbound and outbound setting */
2051 RESET_FLAG(attr->rmap_change_flags);
2052
2053 /*
2054 * The route reflector is not allowed to modify the attributes
2055 * of the reflected IBGP routes unless explicitly allowed.
2056 */
2057 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2058 && !CHECK_FLAG(bgp->flags,
2059 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2060 dummy_attr = *attr;
40381db7 2061 rmap_path.attr = &dummy_attr;
d62a17ae 2062 }
3f9c7369 2063
d62a17ae 2064 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2065
4056a5f6 2066 if (bgp_path_suppressed(pi))
d62a17ae 2067 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2068 &rmap_path);
d62a17ae 2069 else
2070 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2071 &rmap_path);
d62a17ae 2072
2073 peer->rmap_type = 0;
2074
2075 if (ret == RMAP_DENYMATCH) {
778048bf 2076 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2077 zlog_debug(
2078 "%s [Update:SEND] %pFX is filtered by route-map",
2079 peer->host, p);
778048bf 2080
d62a17ae 2081 bgp_attr_flush(attr);
3dc339cd 2082 return false;
d62a17ae 2083 }
3f9c7369 2084 }
3f9c7369 2085
9dac9fc8
DA
2086 /* RFC 8212 to prevent route leaks.
2087 * This specification intends to improve this situation by requiring the
2088 * explicit configuration of both BGP Import and Export Policies for any
2089 * External BGP (EBGP) session such as customers, peers, or
2090 * confederation boundaries for all enabled address families. Through
2091 * codification of the aforementioned requirement, operators will
2092 * benefit from consistent behavior across different BGP
2093 * implementations.
2094 */
1d3fdccf 2095 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2096 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2097 return false;
9dac9fc8 2098
fb29348a
DA
2099 /* draft-ietf-idr-deprecate-as-set-confed-set
2100 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2101 * Eventually, This document (if approved) updates RFC 4271
2102 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2103 * and obsoletes RFC 6472.
2104 */
7f972cd8 2105 if (peer->bgp->reject_as_sets)
fb29348a 2106 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2107 return false;
fb29348a 2108
33d022bc
DA
2109 /* Codification of AS 0 Processing */
2110 if (aspath_check_as_zero(attr->aspath))
e2369003 2111 return false;
33d022bc 2112
637e5ba4 2113 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2114 if (peer->sort == BGP_PEER_IBGP
2115 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2116 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2117 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2118 } else {
2119 bgp_attr_add_gshut_community(attr);
2120 }
2121 }
2122
d62a17ae 2123 /* After route-map has been applied, we check to see if the nexthop to
2124 * be carried in the attribute (that is used for the announcement) can
2125 * be cleared off or not. We do this in all cases where we would be
2126 * setting the nexthop to "ourselves". For IPv6, we only need to
2127 * consider
2128 * the global nexthop here; the link-local nexthop would have been
2129 * cleared
2130 * already, and if not, it is required by the update formation code.
2131 * Also see earlier comments in this function.
2132 */
2133 /*
2134 * If route-map has performed some operation on the nexthop or the peer
2135 * configuration says to pass it unchanged, we cannot reset the nexthop
2136 * here, so only attempt to do it if these aren't true. Note that the
2137 * route-map handler itself might have cleared the nexthop, if for
2138 * example,
2139 * it is configured as 'peer-address'.
2140 */
2141 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2142 piattr->rmap_change_flags)
d62a17ae 2143 && !transparent
2144 && !CHECK_FLAG(peer->af_flags[afi][safi],
2145 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2146 /* We can reset the nexthop, if setting (or forcing) it to
2147 * 'self' */
2148 if (CHECK_FLAG(peer->af_flags[afi][safi],
2149 PEER_FLAG_NEXTHOP_SELF)
2150 || CHECK_FLAG(peer->af_flags[afi][safi],
2151 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2152 if (!reflect
2153 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2154 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2155 subgroup_announce_reset_nhop(
2156 (peer_cap_enhe(peer, afi, safi)
2157 ? AF_INET6
2158 : p->family),
2159 attr);
7b651a32 2160 nh_reset = true;
2161 }
d62a17ae 2162 } else if (peer->sort == BGP_PEER_EBGP) {
2163 /* Can also reset the nexthop if announcing to EBGP, but
2164 * only if
2165 * no peer in the subgroup is on a shared subnet.
2166 * Note: 3rd party nexthop currently implemented for
2167 * IPv4 only.
2168 */
737af885
BS
2169 if ((p->family == AF_INET) &&
2170 (!bgp_subgrp_multiaccess_check_v4(
2171 piattr->nexthop,
7b651a32 2172 subgrp, from))) {
d62a17ae 2173 subgroup_announce_reset_nhop(
2174 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2175 ? AF_INET6
2176 : p->family),
737af885 2177 attr);
7b651a32 2178 nh_reset = true;
2179 }
737af885
BS
2180
2181 if ((p->family == AF_INET6) &&
2182 (!bgp_subgrp_multiaccess_check_v6(
2183 piattr->mp_nexthop_global,
7b651a32 2184 subgrp, from))) {
737af885
BS
2185 subgroup_announce_reset_nhop(
2186 (peer_cap_enhe(peer, afi, safi)
2187 ? AF_INET6
2188 : p->family),
2189 attr);
7b651a32 2190 nh_reset = true;
2191 }
737af885
BS
2192
2193
2194
40381db7 2195 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2196 /*
2197 * This flag is used for leaked vpn-vrf routes
2198 */
2199 int family = p->family;
2200
2201 if (peer_cap_enhe(peer, afi, safi))
2202 family = AF_INET6;
2203
2204 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2205 zlog_debug(
1defdda8 2206 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2207 __func__, family2str(family));
2208 subgroup_announce_reset_nhop(family, attr);
7b651a32 2209 nh_reset = true;
d62a17ae 2210 }
63696f1d 2211 }
960035b2 2212
63696f1d 2213 /* If IPv6/MP and nexthop does not have any override and happens
2214 * to
2215 * be a link-local address, reset it so that we don't pass along
2216 * the
2217 * source's link-local IPv6 address to recipients who may not be
2218 * on
2219 * the same interface.
2220 */
2221 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2222 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2223 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2224 nh_reset = true;
2225 }
d62a17ae 2226 }
3f9c7369 2227
7b651a32 2228 /*
2229 * When the next hop is set to ourselves, if all multipaths have
2230 * link-bandwidth announce the cumulative bandwidth as that makes
2231 * the most sense. However, don't modify if the link-bandwidth has
2232 * been explicitly set by user policy.
2233 */
2234 if (nh_reset &&
f7e1c681 2235 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2236 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2237 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2238 attr->ecommunity = ecommunity_replace_linkbw(
2239 bgp->as, attr->ecommunity, cum_bw);
2240
3dc339cd 2241 return true;
3f9c7369
DS
2242}
2243
f009ff26 2244static int bgp_route_select_timer_expire(struct thread *thread)
2245{
2246 struct afi_safi_info *info;
2247 afi_t afi;
2248 safi_t safi;
2249 struct bgp *bgp;
2250
2251 info = THREAD_ARG(thread);
2252 afi = info->afi;
2253 safi = info->safi;
2254 bgp = info->bgp;
2255
2256 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2257 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2258 safi);
f009ff26 2259
2260 bgp->gr_info[afi][safi].t_route_select = NULL;
2261
2262 XFREE(MTYPE_TMP, info);
2263
2264 /* Best path selection */
2265 return bgp_best_path_select_defer(bgp, afi, safi);
2266}
2267
9bcb3eef 2268void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2269 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2270 struct bgp_path_info_pair *result, afi_t afi,
2271 safi_t safi)
2272{
2273 struct bgp_path_info *new_select;
2274 struct bgp_path_info *old_select;
40381db7
DS
2275 struct bgp_path_info *pi;
2276 struct bgp_path_info *pi1;
2277 struct bgp_path_info *pi2;
2278 struct bgp_path_info *nextpi = NULL;
d62a17ae 2279 int paths_eq, do_mpath, debug;
2280 struct list mp_list;
2281 char pfx_buf[PREFIX2STR_BUFFER];
2282 char path_buf[PATH_ADDPATH_STR_BUFFER];
2283
2284 bgp_mp_list_init(&mp_list);
2285 do_mpath =
2286 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2287
9bcb3eef 2288 debug = bgp_debug_bestpath(dest);
d62a17ae 2289
2290 if (debug)
9bcb3eef 2291 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2292
9bcb3eef 2293 dest->reason = bgp_path_selection_none;
d62a17ae 2294 /* bgp deterministic-med */
2295 new_select = NULL;
892fedb6 2296 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2297
1defdda8 2298 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2299 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2300 pi1 = pi1->next)
9bcb3eef 2301 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2302 BGP_PATH_DMED_SELECTED);
d62a17ae 2303
9bcb3eef 2304 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2305 pi1 = pi1->next) {
40381db7 2306 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2307 continue;
40381db7 2308 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2309 continue;
ea8b2282 2310 if (pi1->peer != bgp->peer_self)
40381db7 2311 if (pi1->peer->status != Established)
d62a17ae 2312 continue;
2313
40381db7
DS
2314 new_select = pi1;
2315 if (pi1->next) {
2316 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2317 if (CHECK_FLAG(pi2->flags,
1defdda8 2318 BGP_PATH_DMED_CHECK))
d62a17ae 2319 continue;
40381db7 2320 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2321 continue;
ea8b2282 2322 if (pi2->peer != bgp->peer_self
d62a17ae 2323 && !CHECK_FLAG(
ea8b2282
DS
2324 pi2->peer->sflags,
2325 PEER_STATUS_NSF_WAIT))
40381db7 2326 if (pi2->peer->status
d62a17ae 2327 != Established)
2328 continue;
2329
121e245d
DS
2330 if (!aspath_cmp_left(pi1->attr->aspath,
2331 pi2->attr->aspath)
2332 && !aspath_cmp_left_confed(
40381db7 2333 pi1->attr->aspath,
121e245d
DS
2334 pi2->attr->aspath))
2335 continue;
d62a17ae 2336
121e245d
DS
2337 if (bgp_path_info_cmp(
2338 bgp, pi2, new_select,
2339 &paths_eq, mpath_cfg, debug,
fdf81fa0 2340 pfx_buf, afi, safi,
9bcb3eef 2341 &dest->reason)) {
121e245d 2342 bgp_path_info_unset_flag(
9bcb3eef 2343 dest, new_select,
121e245d
DS
2344 BGP_PATH_DMED_SELECTED);
2345 new_select = pi2;
d62a17ae 2346 }
121e245d
DS
2347
2348 bgp_path_info_set_flag(
9bcb3eef 2349 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2350 }
2351 }
9bcb3eef 2352 bgp_path_info_set_flag(dest, new_select,
18ee8310 2353 BGP_PATH_DMED_CHECK);
9bcb3eef 2354 bgp_path_info_set_flag(dest, new_select,
18ee8310 2355 BGP_PATH_DMED_SELECTED);
d62a17ae 2356
2357 if (debug) {
18ee8310 2358 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2359 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2360 zlog_debug(
2361 "%pBD: %s is the bestpath from AS %u",
2362 dest, path_buf,
2363 aspath_get_first_as(
2364 new_select->attr->aspath));
d62a17ae 2365 }
2366 }
2367 }
96450faf 2368
d62a17ae 2369 /* Check old selected route and new selected route. */
2370 old_select = NULL;
2371 new_select = NULL;
9bcb3eef 2372 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2373 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2374 enum bgp_path_selection_reason reason;
2375
40381db7
DS
2376 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2377 old_select = pi;
d62a17ae 2378
40381db7 2379 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2380 /* reap REMOVED routes, if needs be
2381 * selected route must stay for a while longer though
2382 */
40381db7
DS
2383 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2384 && (pi != old_select))
9bcb3eef 2385 bgp_path_info_reap(dest, pi);
d62a17ae 2386
ddb5b488 2387 if (debug)
40381db7
DS
2388 zlog_debug("%s: pi %p in holddown", __func__,
2389 pi);
ddb5b488 2390
d62a17ae 2391 continue;
2392 }
96450faf 2393
40381db7
DS
2394 if (pi->peer && pi->peer != bgp->peer_self
2395 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
2396 if (pi->peer->status != Established) {
ddb5b488
PZ
2397
2398 if (debug)
2399 zlog_debug(
40381db7
DS
2400 "%s: pi %p non self peer %s not estab state",
2401 __func__, pi, pi->peer->host);
ddb5b488 2402
d62a17ae 2403 continue;
ddb5b488 2404 }
9fbdd100 2405
892fedb6 2406 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2407 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2408 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2409 if (debug)
40381db7 2410 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2411 continue;
2412 }
9fbdd100 2413
9bcb3eef 2414 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2415
9bcb3eef 2416 reason = dest->reason;
40381db7 2417 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2418 debug, pfx_buf, afi, safi,
2419 &dest->reason)) {
19ea4cec
DS
2420 if (new_select == NULL &&
2421 reason != bgp_path_selection_none)
9bcb3eef 2422 dest->reason = reason;
40381db7 2423 new_select = pi;
d62a17ae 2424 }
2425 }
718e3744 2426
d62a17ae 2427 /* Now that we know which path is the bestpath see if any of the other
2428 * paths
2429 * qualify as multipaths
2430 */
2431 if (debug) {
2432 if (new_select)
7533cad7
QY
2433 bgp_path_info_path_with_addpath_rx_str(
2434 new_select, path_buf, sizeof(path_buf));
d62a17ae 2435 else
772270f3 2436 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2437 zlog_debug(
8228a9a7
DS
2438 "%pBD: After path selection, newbest is %s oldbest was %s",
2439 dest, path_buf,
d62a17ae 2440 old_select ? old_select->peer->host : "NONE");
96450faf 2441 }
9fbdd100 2442
d62a17ae 2443 if (do_mpath && new_select) {
9bcb3eef 2444 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2445 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2446
2447 if (debug)
18ee8310 2448 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2449 pi, path_buf, sizeof(path_buf));
d62a17ae 2450
40381db7 2451 if (pi == new_select) {
d62a17ae 2452 if (debug)
2453 zlog_debug(
8228a9a7
DS
2454 "%pBD: %s is the bestpath, add to the multipath list",
2455 dest, path_buf);
40381db7 2456 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2457 continue;
2458 }
2459
40381db7 2460 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2461 continue;
2462
40381db7
DS
2463 if (pi->peer && pi->peer != bgp->peer_self
2464 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2465 PEER_STATUS_NSF_WAIT))
40381db7 2466 if (pi->peer->status != Established)
d62a17ae 2467 continue;
2468
40381db7 2469 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2470 if (debug)
2471 zlog_debug(
8228a9a7
DS
2472 "%pBD: %s has the same nexthop as the bestpath, skip it",
2473 dest, path_buf);
d62a17ae 2474 continue;
2475 }
2476
40381db7 2477 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2478 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2479 &dest->reason);
d62a17ae 2480
2481 if (paths_eq) {
2482 if (debug)
2483 zlog_debug(
8228a9a7
DS
2484 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2485 dest, path_buf);
40381db7 2486 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2487 }
2488 }
2489 }
fee0f4c6 2490
9bcb3eef 2491 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2492 mpath_cfg);
2493 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2494 bgp_mp_list_clear(&mp_list);
96450faf 2495
9bcb3eef 2496 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2497
d62a17ae 2498 result->old = old_select;
2499 result->new = new_select;
96450faf 2500
d62a17ae 2501 return;
fee0f4c6 2502}
2503
3f9c7369
DS
2504/*
2505 * A new route/change in bestpath of an existing route. Evaluate the path
2506 * for advertisement to the subgroup.
2507 */
3dc339cd
DA
2508void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2509 struct bgp_path_info *selected,
9bcb3eef 2510 struct bgp_dest *dest,
3dc339cd 2511 uint32_t addpath_tx_id)
d62a17ae 2512{
b54892e0 2513 const struct prefix *p;
d62a17ae 2514 struct peer *onlypeer;
2515 struct attr attr;
2516 afi_t afi;
2517 safi_t safi;
a77e2f4b
S
2518 struct bgp *bgp;
2519 bool advertise;
adbac85e 2520
9bcb3eef 2521 p = bgp_dest_get_prefix(dest);
d62a17ae 2522 afi = SUBGRP_AFI(subgrp);
2523 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2524 bgp = SUBGRP_INST(subgrp);
d62a17ae 2525 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2526 : NULL);
2527
2dbe669b
DA
2528 if (BGP_DEBUG(update, UPDATE_OUT))
2529 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2530
d62a17ae 2531 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2532 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2533 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2534 return;
d62a17ae 2535
2536 memset(&attr, 0, sizeof(struct attr));
2537 /* It's initialized in bgp_announce_check() */
2538
a77e2f4b
S
2539 /* Announcement to the subgroup. If the route is filtered withdraw it.
2540 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2541 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2542 * route
d62a17ae 2543 */
a77e2f4b
S
2544 advertise = bgp_check_advertise(bgp, dest);
2545
d62a17ae 2546 if (selected) {
7f7940e6 2547 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2548 false)) {
2549 /* Route is selected, if the route is already installed
2550 * in FIB, then it is advertised
2551 */
2552 if (advertise)
2553 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2554 selected);
2555 } else
9bcb3eef 2556 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2557 addpath_tx_id);
d62a17ae 2558 }
2559
2560 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2561 else {
9bcb3eef 2562 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2563 }
200df115 2564}
fee0f4c6 2565
3064bf43 2566/*
e1072051 2567 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2568 * This is called at the end of route processing.
3064bf43 2569 */
9bcb3eef 2570void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2571{
40381db7 2572 struct bgp_path_info *pi;
3064bf43 2573
9bcb3eef 2574 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2575 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2576 continue;
40381db7
DS
2577 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2578 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2579 }
3064bf43 2580}
2581
2582/*
2583 * Has the route changed from the RIB's perspective? This is invoked only
2584 * if the route selection returns the same best route as earlier - to
2585 * determine if we need to update zebra or not.
2586 */
9bcb3eef 2587bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2588{
4b7e6066 2589 struct bgp_path_info *mpinfo;
d62a17ae 2590
2bb9eff4
DS
2591 /* If this is multipath, check all selected paths for any nexthop
2592 * change or attribute change. Some attribute changes (e.g., community)
2593 * aren't of relevance to the RIB, but we'll update zebra to ensure
2594 * we handle the case of BGP nexthop change. This is the behavior
2595 * when the best path has an attribute change anyway.
d62a17ae 2596 */
1defdda8 2597 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2598 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2599 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2600 return true;
d62a17ae 2601
2bb9eff4
DS
2602 /*
2603 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2604 */
18ee8310
DS
2605 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2606 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2607 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2608 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2609 return true;
d62a17ae 2610 }
3064bf43 2611
d62a17ae 2612 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2613 return false;
3064bf43 2614}
2615
d62a17ae 2616struct bgp_process_queue {
2617 struct bgp *bgp;
9bcb3eef 2618 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2619#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2620 unsigned int flags;
2621 unsigned int queued;
200df115 2622};
2623
3b0c17e1 2624static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2625 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2626 struct bgp_path_info *new_select,
2627 struct bgp_path_info *old_select)
2628{
9bcb3eef 2629 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2630
2631 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2632 return;
2633
2634 if (advertise_type5_routes(bgp, afi) && new_select
2635 && is_route_injectable_into_evpn(new_select)) {
2636
2637 /* apply the route-map */
2638 if (bgp->adv_cmd_rmap[afi][safi].map) {
2639 route_map_result_t ret;
2640 struct bgp_path_info rmap_path;
2641 struct bgp_path_info_extra rmap_path_extra;
2642 struct attr dummy_attr;
2643
2644 dummy_attr = *new_select->attr;
2645
2646 /* Fill temp path_info */
9bcb3eef 2647 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2648 new_select, new_select->peer,
2649 &dummy_attr);
2650
2651 RESET_FLAG(dummy_attr.rmap_change_flags);
2652
2653 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2654 p, &rmap_path);
3b0c17e1 2655
2656 if (ret == RMAP_DENYMATCH) {
2657 bgp_attr_flush(&dummy_attr);
2658 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2659 safi);
2660 } else
2661 bgp_evpn_advertise_type5_route(
2662 bgp, p, &dummy_attr, afi, safi);
2663 } else {
2664 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2665 afi, safi);
2666 }
2667 } else if (advertise_type5_routes(bgp, afi) && old_select
2668 && is_route_injectable_into_evpn(old_select))
2669 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2670}
2671
3103e8d2
DS
2672/*
2673 * old_select = The old best path
2674 * new_select = the new best path
2675 *
2676 * if (!old_select && new_select)
2677 * We are sending new information on.
2678 *
2679 * if (old_select && new_select) {
2680 * if (new_select != old_select)
2681 * We have a new best path send a change
2682 * else
2683 * We've received a update with new attributes that needs
2684 * to be passed on.
2685 * }
2686 *
2687 * if (old_select && !new_select)
2688 * We have no eligible route that we can announce or the rn
2689 * is being removed.
2690 */
9bcb3eef 2691static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2692 afi_t afi, safi_t safi)
d62a17ae 2693{
4b7e6066
DS
2694 struct bgp_path_info *new_select;
2695 struct bgp_path_info *old_select;
2696 struct bgp_path_info_pair old_and_new;
ddb5b488 2697 int debug = 0;
d62a17ae 2698
892fedb6 2699 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2700 if (dest)
2701 debug = bgp_debug_bestpath(dest);
b54892e0 2702 if (debug)
f4c713ae 2703 zlog_debug(
56ca3b5b 2704 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2705 __func__, dest);
f4c713ae
LB
2706 return;
2707 }
d62a17ae 2708 /* Is it end of initial update? (after startup) */
9bcb3eef 2709 if (!dest) {
d62a17ae 2710 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2711 sizeof(bgp->update_delay_zebra_resume_time));
2712
2713 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2714 FOREACH_AFI_SAFI (afi, safi) {
2715 if (bgp_fibupd_safi(safi))
2716 bgp_zebra_announce_table(bgp, afi, safi);
2717 }
d62a17ae 2718 bgp->main_peers_update_hold = 0;
2719
2720 bgp_start_routeadv(bgp);
aac24838 2721 return;
d62a17ae 2722 }
cb1faec9 2723
9bcb3eef 2724 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2725
9bcb3eef 2726 debug = bgp_debug_bestpath(dest);
b54892e0 2727 if (debug)
56ca3b5b 2728 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2729 afi2str(afi), safi2str(safi));
ddb5b488 2730
f009ff26 2731 /* The best path calculation for the route is deferred if
2732 * BGP_NODE_SELECT_DEFER is set
2733 */
9bcb3eef 2734 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2735 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2736 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2737 return;
2738 }
2739
d62a17ae 2740 /* Best path selection. */
9bcb3eef 2741 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2742 afi, safi);
2743 old_select = old_and_new.old;
2744 new_select = old_and_new.new;
2745
2746 /* Do we need to allocate or free labels?
2747 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2748 * necessary to do this upon changes to best path. Exceptions:
2749 * - label index has changed -> recalculate resulting label
2750 * - path_info sub_type changed -> switch to/from implicit-null
2751 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2752 */
318cac96 2753 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2754 if (new_select) {
2755 if (!old_select
2756 || bgp_label_index_differs(new_select, old_select)
57592a53 2757 || new_select->sub_type != old_select->sub_type
9bcb3eef 2758 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2759 /* Enforced penultimate hop popping:
2760 * implicit-null for local routes, aggregate
2761 * and redistributed routes
2762 */
d62a17ae 2763 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2764 || new_select->sub_type
2765 == BGP_ROUTE_AGGREGATE
2766 || new_select->sub_type
2767 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2768 if (CHECK_FLAG(
9bcb3eef 2769 dest->flags,
992dd67e
PR
2770 BGP_NODE_REGISTERED_FOR_LABEL)
2771 || CHECK_FLAG(
2772 dest->flags,
2773 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2774 bgp_unregister_for_label(dest);
70e98a7f 2775 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2776 &dest->local_label);
2777 bgp_set_valid_label(&dest->local_label);
d62a17ae 2778 } else
9bcb3eef
DS
2779 bgp_register_for_label(dest,
2780 new_select);
d62a17ae 2781 }
9bcb3eef 2782 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2783 BGP_NODE_REGISTERED_FOR_LABEL)
2784 || CHECK_FLAG(dest->flags,
2785 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2786 bgp_unregister_for_label(dest);
318cac96 2787 }
992dd67e
PR
2788 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2789 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2790 bgp_unregister_for_label(dest);
d62a17ae 2791 }
cd1964ff 2792
b54892e0 2793 if (debug)
ddb5b488 2794 zlog_debug(
56ca3b5b 2795 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2796 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2797 old_select, new_select);
ddb5b488 2798
d62a17ae 2799 /* If best route remains the same and this is not due to user-initiated
2800 * clear, see exactly what needs to be done.
2801 */
d62a17ae 2802 if (old_select && old_select == new_select
9bcb3eef 2803 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2804 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2805 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2806 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2807#ifdef ENABLE_BGP_VNC
d62a17ae 2808 vnc_import_bgp_add_route(bgp, p, old_select);
2809 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2810#endif
bb744275 2811 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2812 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2813
2814 if (new_select->type == ZEBRA_ROUTE_BGP
2815 && (new_select->sub_type == BGP_ROUTE_NORMAL
2816 || new_select->sub_type
2817 == BGP_ROUTE_IMPORTED))
2818
9bcb3eef 2819 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2820 bgp, afi, safi);
2821 }
d62a17ae 2822 }
d62a17ae 2823
2824 /* If there is a change of interest to peers, reannounce the
2825 * route. */
1defdda8 2826 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2827 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2828 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2829 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2830
2831 /* unicast routes must also be annouced to
2832 * labeled-unicast update-groups */
2833 if (safi == SAFI_UNICAST)
2834 group_announce_route(bgp, afi,
9bcb3eef 2835 SAFI_LABELED_UNICAST, dest,
d62a17ae 2836 new_select);
2837
1defdda8 2838 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2839 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2840 }
fee0f4c6 2841
3b0c17e1 2842 /* advertise/withdraw type-5 routes */
2843 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2844 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2845 bgp_process_evpn_route_injection(
9bcb3eef 2846 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2847
b1875e65 2848 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2849 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2850 bgp_zebra_clear_route_change_flags(dest);
2851 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2852 return;
d62a17ae 2853 }
8ad7271d 2854
d62a17ae 2855 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2856 */
9bcb3eef 2857 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2858
2859 /* bestpath has changed; bump version */
2860 if (old_select || new_select) {
9bcb3eef 2861 bgp_bump_version(dest);
d62a17ae 2862
2863 if (!bgp->t_rmap_def_originate_eval) {
2864 bgp_lock(bgp);
2865 thread_add_timer(
2866 bm->master,
2867 update_group_refresh_default_originate_route_map,
2868 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2869 &bgp->t_rmap_def_originate_eval);
2870 }
2871 }
3f9c7369 2872
d62a17ae 2873 if (old_select)
9bcb3eef 2874 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2875 if (new_select) {
ddb5b488
PZ
2876 if (debug)
2877 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2878 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2879 bgp_path_info_unset_flag(dest, new_select,
2880 BGP_PATH_ATTR_CHANGED);
1defdda8 2881 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2882 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2883 }
338b3424 2884
49e5a4a0 2885#ifdef ENABLE_BGP_VNC
d62a17ae 2886 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2887 if (old_select != new_select) {
2888 if (old_select) {
2889 vnc_import_bgp_exterior_del_route(bgp, p,
2890 old_select);
2891 vnc_import_bgp_del_route(bgp, p, old_select);
2892 }
2893 if (new_select) {
2894 vnc_import_bgp_exterior_add_route(bgp, p,
2895 new_select);
2896 vnc_import_bgp_add_route(bgp, p, new_select);
2897 }
2898 }
2899 }
65efcfce
LB
2900#endif
2901
9bcb3eef 2902 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2903
2904 /* unicast routes must also be annouced to labeled-unicast update-groups
2905 */
2906 if (safi == SAFI_UNICAST)
9bcb3eef 2907 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2908 new_select);
2909
2910 /* FIB update. */
2911 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2912 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2913 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2914 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2915 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2916 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2917
2918 /* if this is an evpn imported type-5 prefix,
2919 * we need to withdraw the route first to clear
2920 * the nh neigh and the RMAC entry.
2921 */
2922 if (old_select &&
2923 is_route_parent_evpn(old_select))
2924 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2925
9bcb3eef 2926 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2927 } else {
d62a17ae 2928 /* Withdraw the route from the kernel. */
2929 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2930 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2931 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2932 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2933
568e10ca 2934 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2935 }
718e3744 2936 }
3064bf43 2937
9bcb3eef 2938 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2939 old_select);
5424b7ba 2940
d62a17ae 2941 /* Clear any route change flags. */
9bcb3eef 2942 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2943
18ee8310 2944 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2945 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2946 bgp_path_info_reap(dest, old_select);
d62a17ae 2947
9bcb3eef 2948 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2949 return;
718e3744 2950}
2951
f009ff26 2952/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2953int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2954{
9bcb3eef 2955 struct bgp_dest *dest;
f009ff26 2956 int cnt = 0;
2957 struct afi_safi_info *thread_info;
f009ff26 2958
56c226e7
DS
2959 if (bgp->gr_info[afi][safi].t_route_select) {
2960 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
2961
2962 thread_info = THREAD_ARG(t);
2963 XFREE(MTYPE_TMP, thread_info);
f009ff26 2964 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 2965 }
f009ff26 2966
2967 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
2968 zlog_debug("%s: processing route for %s : cnt %d", __func__,
2969 get_afi_safi_str(afi, safi, false),
26742171 2970 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 2971 }
2972
2973 /* Process the route list */
6338d242
DS
2974 for (dest = bgp_table_top(bgp->rib[afi][safi]);
2975 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
2976 dest = bgp_route_next(dest)) {
2977 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
2978 continue;
2979
2980 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
2981 bgp->gr_info[afi][safi].gr_deferred--;
2982 bgp_process_main_one(bgp, dest, afi, safi);
2983 cnt++;
2984 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
2985 bgp_dest_unlock_node(dest);
2986 break;
f009ff26 2987 }
f009ff26 2988 }
2989
9e3b51a7 2990 /* Send EOR message when all routes are processed */
6338d242 2991 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 2992 bgp_send_delayed_eor(bgp);
8c48b3b6 2993 /* Send route processing complete message to RIB */
2994 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 2995 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 2996 return 0;
9e3b51a7 2997 }
f009ff26 2998
2999 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3000
3001 thread_info->afi = afi;
3002 thread_info->safi = safi;
3003 thread_info->bgp = bgp;
3004
3005 /* If there are more routes to be processed, start the
3006 * selection timer
3007 */
3008 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3009 BGP_ROUTE_SELECT_DELAY,
3010 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3011 return 0;
3012}
3013
aac24838 3014static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3015{
aac24838
JB
3016 struct bgp_process_queue *pqnode = data;
3017 struct bgp *bgp = pqnode->bgp;
d62a17ae 3018 struct bgp_table *table;
9bcb3eef 3019 struct bgp_dest *dest;
aac24838
JB
3020
3021 /* eoiu marker */
3022 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3023 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3024 /* should always have dedicated wq call */
3025 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3026 return WQ_SUCCESS;
3027 }
3028
ac021f40 3029 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3030 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3031 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3032 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3033 table = bgp_dest_table(dest);
3034 /* note, new DESTs may be added as part of processing */
3035 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3036
9bcb3eef 3037 bgp_dest_unlock_node(dest);
d62a17ae 3038 bgp_table_unlock(table);
3039 }
aac24838
JB
3040
3041 return WQ_SUCCESS;
3042}
3043
3044static void bgp_processq_del(struct work_queue *wq, void *data)
3045{
3046 struct bgp_process_queue *pqnode = data;
3047
3048 bgp_unlock(pqnode->bgp);
3049
3050 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3051}
3052
b6c386bb 3053void bgp_process_queue_init(struct bgp *bgp)
200df115 3054{
b6c386bb
DS
3055 if (!bgp->process_queue) {
3056 char name[BUFSIZ];
3057
3058 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3059 bgp->process_queue = work_queue_new(bm->master, name);
3060 }
3061
3062 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3063 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3064 bgp->process_queue->spec.max_retries = 0;
3065 bgp->process_queue->spec.hold = 50;
d62a17ae 3066 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3067 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3068}
3069
cfe8d15a 3070static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3071{
3072 struct bgp_process_queue *pqnode;
3073
a4d82a8a
PZ
3074 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3075 sizeof(struct bgp_process_queue));
aac24838
JB
3076
3077 /* unlocked in bgp_processq_del */
3078 pqnode->bgp = bgp_lock(bgp);
3079 STAILQ_INIT(&pqnode->pqueue);
3080
aac24838
JB
3081 return pqnode;
3082}
3083
9bcb3eef 3084void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3085{
aac24838 3086#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3087 struct work_queue *wq = bgp->process_queue;
d62a17ae 3088 struct bgp_process_queue *pqnode;
cfe8d15a 3089 int pqnode_reuse = 0;
495f0b13 3090
d62a17ae 3091 /* already scheduled for processing? */
9bcb3eef 3092 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3093 return;
2e02b9b2 3094
f009ff26 3095 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3096 * the workqueue
3097 */
9bcb3eef 3098 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3099 if (BGP_DEBUG(update, UPDATE_OUT))
3100 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3101 dest);
f009ff26 3102 return;
3103 }
3104
aac24838 3105 if (wq == NULL)
d62a17ae 3106 return;
3107
aac24838 3108 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3109 limit only if is from the same BGP view and it's not an EOIU marker
3110 */
aac24838
JB
3111 if (work_queue_item_count(wq)) {
3112 struct work_queue_item *item = work_queue_last_item(wq);
3113 pqnode = item->data;
228da428 3114
a4d82a8a
PZ
3115 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3116 || pqnode->bgp != bgp
3117 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3118 pqnode = bgp_processq_alloc(bgp);
3119 else
3120 pqnode_reuse = 1;
aac24838 3121 } else
cfe8d15a 3122 pqnode = bgp_processq_alloc(bgp);
aac24838 3123 /* all unlocked in bgp_process_wq */
9bcb3eef 3124 bgp_table_lock(bgp_dest_table(dest));
aac24838 3125
9bcb3eef
DS
3126 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3127 bgp_dest_lock_node(dest);
aac24838 3128
60466a63 3129 /* can't be enqueued twice */
9bcb3eef
DS
3130 assert(STAILQ_NEXT(dest, pq) == NULL);
3131 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3132 pqnode->queued++;
3133
cfe8d15a
LB
3134 if (!pqnode_reuse)
3135 work_queue_add(wq, pqnode);
3136
d62a17ae 3137 return;
fee0f4c6 3138}
0a486e5f 3139
d62a17ae 3140void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3141{
d62a17ae 3142 struct bgp_process_queue *pqnode;
cb1faec9 3143
b6c386bb 3144 if (bgp->process_queue == NULL)
d62a17ae 3145 return;
2e02b9b2 3146
cfe8d15a 3147 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3148
aac24838 3149 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3150 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3151}
3152
d62a17ae 3153static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3154{
d62a17ae 3155 struct peer *peer;
0a486e5f 3156
d62a17ae 3157 peer = THREAD_ARG(thread);
3158 peer->t_pmax_restart = NULL;
0a486e5f 3159
d62a17ae 3160 if (bgp_debug_neighbor_events(peer))
3161 zlog_debug(
3162 "%s Maximum-prefix restart timer expired, restore peering",
3163 peer->host);
0a486e5f 3164
a9bafa95 3165 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3166 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3167
d62a17ae 3168 return 0;
0a486e5f 3169}
3170
9cbd06e0
DA
3171static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3172 safi_t safi)
3173{
3174 uint32_t count = 0;
f41b0459 3175 bool filtered = false;
9cbd06e0
DA
3176 struct bgp_dest *dest;
3177 struct bgp_adj_in *ain;
40bb2ccf 3178 struct attr attr = {};
9cbd06e0
DA
3179 struct bgp_table *table = peer->bgp->rib[afi][safi];
3180
3181 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3182 for (ain = dest->adj_in; ain; ain = ain->next) {
3183 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3184
3185 attr = *ain->attr;
9cbd06e0
DA
3186
3187 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3188 == FILTER_DENY)
f41b0459
DA
3189 filtered = true;
3190
3191 if (bgp_input_modifier(
3192 peer, rn_p, &attr, afi, safi,
3193 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3194 NULL, 0, NULL)
3195 == RMAP_DENY)
3196 filtered = true;
3197
3198 if (filtered)
9cbd06e0 3199 count++;
f41b0459
DA
3200
3201 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3202 }
3203 }
3204
3205 return count;
3206}
3207
3dc339cd
DA
3208bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3209 int always)
718e3744 3210{
d62a17ae 3211 iana_afi_t pkt_afi;
5c525538 3212 iana_safi_t pkt_safi;
9cbd06e0
DA
3213 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3214 PEER_FLAG_MAX_PREFIX_FORCE))
3215 ? bgp_filtered_routes_count(peer, afi, safi)
3216 + peer->pcount[afi][safi]
3217 : peer->pcount[afi][safi];
9cabb64b 3218
d62a17ae 3219 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3220 return false;
e0701b79 3221
9cbd06e0 3222 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3223 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3224 PEER_STATUS_PREFIX_LIMIT)
3225 && !always)
3dc339cd 3226 return false;
e0701b79 3227
d62a17ae 3228 zlog_info(
6cde4b45 3229 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3230 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3231 peer->pmax[afi][safi]);
d62a17ae 3232 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3233
3234 if (CHECK_FLAG(peer->af_flags[afi][safi],
3235 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3236 return false;
d62a17ae 3237
3238 /* Convert AFI, SAFI to values for packet. */
3239 pkt_afi = afi_int2iana(afi);
3240 pkt_safi = safi_int2iana(safi);
3241 {
d7c0a89a 3242 uint8_t ndata[7];
d62a17ae 3243
3244 ndata[0] = (pkt_afi >> 8);
3245 ndata[1] = pkt_afi;
3246 ndata[2] = pkt_safi;
3247 ndata[3] = (peer->pmax[afi][safi] >> 24);
3248 ndata[4] = (peer->pmax[afi][safi] >> 16);
3249 ndata[5] = (peer->pmax[afi][safi] >> 8);
3250 ndata[6] = (peer->pmax[afi][safi]);
3251
3252 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3253 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3254 BGP_NOTIFY_CEASE_MAX_PREFIX,
3255 ndata, 7);
3256 }
3257
3258 /* Dynamic peers will just close their connection. */
3259 if (peer_dynamic_neighbor(peer))
3dc339cd 3260 return true;
d62a17ae 3261
3262 /* restart timer start */
3263 if (peer->pmax_restart[afi][safi]) {
3264 peer->v_pmax_restart =
3265 peer->pmax_restart[afi][safi] * 60;
3266
3267 if (bgp_debug_neighbor_events(peer))
3268 zlog_debug(
3269 "%s Maximum-prefix restart timer started for %d secs",
3270 peer->host, peer->v_pmax_restart);
3271
3272 BGP_TIMER_ON(peer->t_pmax_restart,
3273 bgp_maximum_prefix_restart_timer,
3274 peer->v_pmax_restart);
3275 }
3276
3dc339cd 3277 return true;
d62a17ae 3278 } else
3279 UNSET_FLAG(peer->af_sflags[afi][safi],
3280 PEER_STATUS_PREFIX_LIMIT);
3281
b1823b69
DS
3282 if (pcount
3283 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3284 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3285 PEER_STATUS_PREFIX_THRESHOLD)
3286 && !always)
3dc339cd 3287 return false;
d62a17ae 3288
3289 zlog_info(
6cde4b45 3290 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3291 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3292 peer->pmax[afi][safi]);
d62a17ae 3293 SET_FLAG(peer->af_sflags[afi][safi],
3294 PEER_STATUS_PREFIX_THRESHOLD);
3295 } else
3296 UNSET_FLAG(peer->af_sflags[afi][safi],
3297 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3298 return false;
718e3744 3299}
3300
b40d939b 3301/* Unconditionally remove the route from the RIB, without taking
3302 * damping into consideration (eg, because the session went down)
3303 */
9bcb3eef 3304void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3305 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3306{
f009ff26 3307
3308 struct bgp *bgp = NULL;
3309 bool delete_route = false;
3310
9bcb3eef
DS
3311 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3312 safi);
d62a17ae 3313
f009ff26 3314 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3315 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3316
f009ff26 3317 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3318 * flag
3319 */
3320 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3321 delete_route = true;
9bcb3eef 3322 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3323 delete_route = true;
f009ff26 3324 if (delete_route) {
9bcb3eef
DS
3325 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3326 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3327 bgp = pi->peer->bgp;
26742171 3328 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3329 }
3330 }
3331 }
4a11bf2c 3332
9bcb3eef
DS
3333 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3334 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3335}
3336
9bcb3eef 3337static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3338 struct peer *peer, afi_t afi, safi_t safi,
3339 struct prefix_rd *prd)
3340{
9bcb3eef 3341 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3342
d62a17ae 3343 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3344 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3345 */
40ec3340
DS
3346 if (peer->sort == BGP_PEER_EBGP) {
3347 if (get_active_bdc_from_pi(pi, afi, safi)) {
3348 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3349 == BGP_DAMP_SUPPRESSED) {
3350 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3351 safi);
3352 return;
3353 }
d62a17ae 3354 }
40ec3340 3355 }
d62a17ae 3356
49e5a4a0 3357#ifdef ENABLE_BGP_VNC
d62a17ae 3358 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3359 struct bgp_dest *pdest = NULL;
d62a17ae 3360 struct bgp_table *table = NULL;
3361
9bcb3eef
DS
3362 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3363 (struct prefix *)prd);
3364 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3365 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3366
3367 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3368 peer->bgp, prd, table, p, pi);
d62a17ae 3369 }
9bcb3eef 3370 bgp_dest_unlock_node(pdest);
d62a17ae 3371 }
3372 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3373 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3374
b54892e0
DS
3375 vnc_import_bgp_del_route(peer->bgp, p, pi);
3376 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3377 }
65efcfce 3378 }
d62a17ae 3379#endif
128ea8ab 3380
d62a17ae 3381 /* If this is an EVPN route, process for un-import. */
3382 if (safi == SAFI_EVPN)
b54892e0 3383 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3384
9bcb3eef 3385 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3386}
3387
4b7e6066
DS
3388struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3389 struct peer *peer, struct attr *attr,
9bcb3eef 3390 struct bgp_dest *dest)
fb018d25 3391{
4b7e6066 3392 struct bgp_path_info *new;
fb018d25 3393
d62a17ae 3394 /* Make new BGP info. */
4b7e6066 3395 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3396 new->type = type;
3397 new->instance = instance;
3398 new->sub_type = sub_type;
3399 new->peer = peer;
3400 new->attr = attr;
3401 new->uptime = bgp_clock();
9bcb3eef 3402 new->net = dest;
d62a17ae 3403 return new;
fb018d25
DS
3404}
3405
d62a17ae 3406static void overlay_index_update(struct attr *attr,
d62a17ae 3407 union gw_addr *gw_ip)
684a7227 3408{
d62a17ae 3409 if (!attr)
3410 return;
d62a17ae 3411 if (gw_ip == NULL) {
6c924775
DS
3412 struct bgp_route_evpn eo;
3413
3414 memset(&eo, 0, sizeof(eo));
3415 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3416 } else {
6c924775
DS
3417 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3418
3419 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3420 }
684a7227
PG
3421}
3422
40381db7 3423static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3424 union gw_addr *gw_ip)
3425{
6c924775
DS
3426 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3427 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3428 union {
0a50c248 3429 esi_t esi;
11ebf4ed
DS
3430 union gw_addr ip;
3431 } temp;
d62a17ae 3432
3433 if (afi != AFI_L2VPN)
3434 return true;
11ebf4ed 3435
6c924775 3436 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3437
3438 if (gw_ip == NULL) {
3439 memset(&temp, 0, sizeof(temp));
40381db7 3440 path_gw_ip_remote = &temp.ip;
11ebf4ed 3441 } else
40381db7 3442 path_gw_ip_remote = gw_ip;
11ebf4ed 3443
6c924775 3444 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3445}
3446
c265ee22 3447/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3448bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3449 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3450 struct bgp_dest *dest)
d62a17ae 3451{
2dbe3fa9 3452 bool ret = false;
b099a5c8
DA
3453 bool is_bgp_static_route =
3454 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3455 : false;
d62a17ae 3456
e8442016
DS
3457 /*
3458 * Only validated for unicast and multicast currently.
3459 * Also valid for EVPN where the nexthop is an IP address.
3460 * If we are a bgp static route being checked then there is
3461 * no need to check to see if the nexthop is martian as
3462 * that it should be ok.
3463 */
3464 if (is_bgp_static_route ||
3465 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3466 return false;
d62a17ae 3467
3468 /* If NEXT_HOP is present, validate it. */
3469 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3470 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3471 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3472 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3473 return true;
d62a17ae 3474 }
c265ee22 3475
d62a17ae 3476 /* If MP_NEXTHOP is present, validate it. */
3477 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3478 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3479 * it is not an IPv6 link-local address.
0355b41d
DA
3480 *
3481 * If we receive an UPDATE with nexthop length set to 32 bytes
3482 * we shouldn't discard an UPDATE if it's set to (::).
3483 * The link-local (2st) is validated along the code path later.
d62a17ae 3484 */
3485 if (attr->mp_nexthop_len) {
3486 switch (attr->mp_nexthop_len) {
3487 case BGP_ATTR_NHLEN_IPV4:
3488 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3489 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3490 || IPV4_CLASS_DE(
3491 ntohl(attr->mp_nexthop_global_in.s_addr))
3492 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3493 dest));
d62a17ae 3494 break;
3495
3496 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3497 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3498 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3499 &attr->mp_nexthop_global)
d62a17ae 3500 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3501 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3502 &attr->mp_nexthop_global)
3503 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3504 dest));
d62a17ae 3505 break;
0355b41d
DA
3506 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3507 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3508 || IN6_IS_ADDR_MULTICAST(
3509 &attr->mp_nexthop_global)
3510 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3511 dest));
0355b41d 3512 break;
d62a17ae 3513
3514 default:
3dc339cd 3515 ret = true;
d62a17ae 3516 break;
3517 }
3518 }
c265ee22 3519
d62a17ae 3520 return ret;
3521}
3522
aade37d7 3523static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3524{
3525 struct community *old;
3526 struct community *new;
3527 struct community *merge;
aade37d7 3528 struct community *no_export;
2721dd61
DA
3529
3530 old = attr->community;
aade37d7 3531 no_export = community_str2com("no-export");
2721dd61 3532
b4efa101
DA
3533 assert(no_export);
3534
2721dd61 3535 if (old) {
aade37d7 3536 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3537
3538 if (!old->refcnt)
3539 community_free(&old);
3540
3541 new = community_uniq_sort(merge);
3542 community_free(&merge);
3543 } else {
aade37d7 3544 new = community_dup(no_export);
2721dd61
DA
3545 }
3546
aade37d7 3547 community_free(&no_export);
2721dd61
DA
3548
3549 attr->community = new;
3550 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3551}
3552
5a1ae2c2 3553int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3554 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3555 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3556 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3557 struct bgp_route_evpn *evpn)
d62a17ae 3558{
3559 int ret;
3560 int aspath_loop_count = 0;
9bcb3eef 3561 struct bgp_dest *dest;
d62a17ae 3562 struct bgp *bgp;
3563 struct attr new_attr;
3564 struct attr *attr_new;
40381db7 3565 struct bgp_path_info *pi;
4b7e6066
DS
3566 struct bgp_path_info *new;
3567 struct bgp_path_info_extra *extra;
d62a17ae 3568 const char *reason;
3569 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3570 int connected = 0;
3571 int do_loop_check = 1;
3572 int has_valid_label = 0;
7c312383 3573 afi_t nh_afi;
949b0f24 3574 uint8_t pi_type = 0;
3575 uint8_t pi_sub_type = 0;
3576
c7bb4f00 3577 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3578 char pfxprint[PREFIX2STR_BUFFER];
3579
3580 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3581 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3582 afi, safi, attr);
6401252f
QY
3583 }
3584
49e5a4a0 3585#ifdef ENABLE_BGP_VNC
d62a17ae 3586 int vnc_implicit_withdraw = 0;
65efcfce 3587#endif
d62a17ae 3588 int same_attr = 0;
718e3744 3589
d62a17ae 3590 memset(&new_attr, 0, sizeof(struct attr));
3591 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3592 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3593
d62a17ae 3594 bgp = peer->bgp;
9bcb3eef 3595 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3596 /* TODO: Check to see if we can get rid of "is_valid_label" */
3597 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3598 has_valid_label = (num_labels > 0) ? 1 : 0;
3599 else
3600 has_valid_label = bgp_is_valid_label(label);
718e3744 3601
28f66de2
MS
3602 if (has_valid_label)
3603 assert(label != NULL);
3604
d62a17ae 3605 /* When peer's soft reconfiguration enabled. Record input packet in
3606 Adj-RIBs-In. */
3607 if (!soft_reconfig
3608 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3609 && peer != bgp->peer_self)
9bcb3eef 3610 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3611
3612 /* Check previously received route. */
9bcb3eef 3613 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3614 if (pi->peer == peer && pi->type == type
3615 && pi->sub_type == sub_type
3616 && pi->addpath_rx_id == addpath_id)
d62a17ae 3617 break;
3618
3619 /* AS path local-as loop check. */
3620 if (peer->change_local_as) {
c4368918
DW
3621 if (peer->allowas_in[afi][safi])
3622 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3623 else if (!CHECK_FLAG(peer->flags,
3624 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3625 aspath_loop_count = 1;
3626
3627 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3628 > aspath_loop_count) {
b4d46cc9 3629 peer->stat_pfx_aspath_loop++;
9bcb3eef 3630 reason = "as-path contains our own AS A;";
d62a17ae 3631 goto filtered;
3632 }
718e3744 3633 }
718e3744 3634
d62a17ae 3635 /* If the peer is configured for "allowas-in origin" and the last ASN in
3636 * the
3637 * as-path is our ASN then we do not need to call aspath_loop_check
3638 */
3639 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3640 if (aspath_get_last_as(attr->aspath) == bgp->as)
3641 do_loop_check = 0;
3642
3643 /* AS path loop check. */
3644 if (do_loop_check) {
3645 if (aspath_loop_check(attr->aspath, bgp->as)
3646 > peer->allowas_in[afi][safi]
3647 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3648 && aspath_loop_check(attr->aspath, bgp->confed_id)
3649 > peer->allowas_in[afi][safi])) {
b4d46cc9 3650 peer->stat_pfx_aspath_loop++;
d62a17ae 3651 reason = "as-path contains our own AS;";
3652 goto filtered;
3653 }
3654 }
aac9ef6c 3655
d62a17ae 3656 /* Route reflector originator ID check. */
3657 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3658 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3659 peer->stat_pfx_originator_loop++;
d62a17ae 3660 reason = "originator is us;";
3661 goto filtered;
3662 }
718e3744 3663
d62a17ae 3664 /* Route reflector cluster ID check. */
3665 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3666 peer->stat_pfx_cluster_loop++;
d62a17ae 3667 reason = "reflected from the same cluster;";
3668 goto filtered;
3669 }
718e3744 3670
d62a17ae 3671 /* Apply incoming filter. */
3672 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3673 peer->stat_pfx_filter++;
d62a17ae 3674 reason = "filter;";
3675 goto filtered;
3676 }
718e3744 3677
a8b72dc6
DA
3678 /* RFC 8212 to prevent route leaks.
3679 * This specification intends to improve this situation by requiring the
3680 * explicit configuration of both BGP Import and Export Policies for any
3681 * External BGP (EBGP) session such as customers, peers, or
3682 * confederation boundaries for all enabled address families. Through
3683 * codification of the aforementioned requirement, operators will
3684 * benefit from consistent behavior across different BGP
3685 * implementations.
3686 */
1d3fdccf 3687 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3688 if (!bgp_inbound_policy_exists(peer,
3689 &peer->filter[afi][safi])) {
3690 reason = "inbound policy missing";
3691 goto filtered;
3692 }
3693
fb29348a
DA
3694 /* draft-ietf-idr-deprecate-as-set-confed-set
3695 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3696 * Eventually, This document (if approved) updates RFC 4271
3697 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3698 * and obsoletes RFC 6472.
3699 */
7f972cd8 3700 if (peer->bgp->reject_as_sets)
fb29348a
DA
3701 if (aspath_check_as_sets(attr->aspath)) {
3702 reason =
3703 "as-path contains AS_SET or AS_CONFED_SET type;";
3704 goto filtered;
3705 }
3706
6f4f49b2 3707 new_attr = *attr;
d62a17ae 3708
3709 /* Apply incoming route-map.
3710 * NB: new_attr may now contain newly allocated values from route-map
3711 * "set"
3712 * commands, so we need bgp_attr_flush in the error paths, until we
3713 * intern
3714 * the attr (which takes over the memory references) */
9bcb3eef
DS
3715 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3716 num_labels, dest)
3717 == RMAP_DENY) {
b4d46cc9 3718 peer->stat_pfx_filter++;
d62a17ae 3719 reason = "route-map;";
3720 bgp_attr_flush(&new_attr);
3721 goto filtered;
3722 }
718e3744 3723
05864da7 3724 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3725 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3726 /* remove from RIB previous entry */
3727 bgp_zebra_withdraw(p, pi, bgp, safi);
3728 }
3729
7f323236
DW
3730 if (peer->sort == BGP_PEER_EBGP) {
3731
2721dd61
DA
3732 /* rfc7999:
3733 * A BGP speaker receiving an announcement tagged with the
3734 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3735 * NO_EXPORT community as defined in RFC1997, or a
3736 * similar community, to prevent propagation of the
3737 * prefix outside the local AS. The community to prevent
3738 * propagation SHOULD be chosen according to the operator's
3739 * routing policy.
3740 */
3741 if (new_attr.community
3742 && community_include(new_attr.community,
3743 COMMUNITY_BLACKHOLE))
aade37d7 3744 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3745
a4d82a8a
PZ
3746 /* If we receive the graceful-shutdown community from an eBGP
3747 * peer we must lower local-preference */
3748 if (new_attr.community
3749 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3750 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3751 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3752
a4d82a8a
PZ
3753 /* If graceful-shutdown is configured then add the GSHUT
3754 * community to all paths received from eBGP peers */
637e5ba4 3755 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3756 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3757 }
3758
949b0f24 3759 if (pi) {
3760 pi_type = pi->type;
3761 pi_sub_type = pi->sub_type;
3762 }
3763
d62a17ae 3764 /* next hop check. */
a4d82a8a 3765 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3766 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3767 &new_attr, dest)) {
b4d46cc9 3768 peer->stat_pfx_nh_invalid++;
d62a17ae 3769 reason = "martian or self next-hop;";
3770 bgp_attr_flush(&new_attr);
3771 goto filtered;
3772 }
718e3744 3773
5c14a191 3774 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3775 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3776 reason = "self mac;";
3777 goto filtered;
3778 }
3779
1e9be514
QY
3780 /* Update Overlay Index */
3781 if (afi == AFI_L2VPN) {
3782 overlay_index_update(&new_attr,
3783 evpn == NULL ? NULL : &evpn->gw_ip);
3784 }
3785
a1b773e2
DS
3786 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3787 * condition :
3788 * Suppress fib is enabled
3789 * BGP_OPT_NO_FIB is not enabled
3790 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3791 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3792 */
3793 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3794 && (sub_type == BGP_ROUTE_NORMAL)
3795 && (!bgp_option_check(BGP_OPT_NO_FIB))
3796 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3797 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3798
d62a17ae 3799 attr_new = bgp_attr_intern(&new_attr);
3800
9cbd06e0
DA
3801 /* If maximum prefix count is configured and current prefix
3802 * count exeed it.
3803 */
3804 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3805 return -1;
3806
d62a17ae 3807 /* If the update is implicit withdraw. */
40381db7
DS
3808 if (pi) {
3809 pi->uptime = bgp_clock();
3810 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3811
9bcb3eef 3812 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3813
d62a17ae 3814 /* Same attribute comes in. */
40381db7 3815 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3816 && same_attr
d62a17ae 3817 && (!has_valid_label
40381db7 3818 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3819 num_labels * sizeof(mpls_label_t))
d62a17ae 3820 == 0)
3821 && (overlay_index_equal(
0a50c248 3822 afi, pi,
d62a17ae 3823 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3824 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3825 && peer->sort == BGP_PEER_EBGP
40381db7 3826 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3827 if (bgp_debug_update(peer, p, NULL, 1)) {
3828 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3829 afi, safi, prd, p, label,
3830 num_labels, addpath_id ? 1 : 0,
3831 addpath_id, pfx_buf,
3832 sizeof(pfx_buf));
d62a17ae 3833 zlog_debug("%s rcvd %s", peer->host,
3834 pfx_buf);
3835 }
3836
9bcb3eef 3837 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3838 != BGP_DAMP_SUPPRESSED) {
40381db7 3839 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3840 safi);
9bcb3eef 3841 bgp_process(bgp, dest, afi, safi);
d62a17ae 3842 }
3843 } else /* Duplicate - odd */
3844 {
3845 if (bgp_debug_update(peer, p, NULL, 1)) {
3846 if (!peer->rcvd_attr_printed) {
3847 zlog_debug(
3848 "%s rcvd UPDATE w/ attr: %s",
3849 peer->host,
3850 peer->rcvd_attr_str);
3851 peer->rcvd_attr_printed = 1;
3852 }
3853
3854 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3855 afi, safi, prd, p, label,
3856 num_labels, addpath_id ? 1 : 0,
3857 addpath_id, pfx_buf,
3858 sizeof(pfx_buf));
d62a17ae 3859 zlog_debug(
3860 "%s rcvd %s...duplicate ignored",
3861 peer->host, pfx_buf);
3862 }
3863
3864 /* graceful restart STALE flag unset. */
40381db7 3865 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3866 bgp_path_info_unset_flag(
9bcb3eef
DS
3867 dest, pi, BGP_PATH_STALE);
3868 bgp_dest_set_defer_flag(dest, false);
3869 bgp_process(bgp, dest, afi, safi);
d62a17ae 3870 }
3871 }
3872
9bcb3eef 3873 bgp_dest_unlock_node(dest);
d62a17ae 3874 bgp_attr_unintern(&attr_new);
3875
3876 return 0;
3877 }
718e3744 3878
d62a17ae 3879 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3880 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3881 if (bgp_debug_update(peer, p, NULL, 1)) {
3882 bgp_debug_rdpfxpath2str(
a4d82a8a 3883 afi, safi, prd, p, label, num_labels,
d62a17ae 3884 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3885 sizeof(pfx_buf));
3886 zlog_debug(
3887 "%s rcvd %s, flapped quicker than processing",
3888 peer->host, pfx_buf);
3889 }
3890
9bcb3eef 3891 bgp_path_info_restore(dest, pi);
d62a17ae 3892 }
718e3744 3893
d62a17ae 3894 /* Received Logging. */
3895 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3896 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3897 num_labels, addpath_id ? 1 : 0,
3898 addpath_id, pfx_buf,
3899 sizeof(pfx_buf));
d62a17ae 3900 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3901 }
718e3744 3902
d62a17ae 3903 /* graceful restart STALE flag unset. */
f009ff26 3904 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3905 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3906 bgp_dest_set_defer_flag(dest, false);
f009ff26 3907 }
d62a17ae 3908
3909 /* The attribute is changed. */
9bcb3eef 3910 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3911
3912 /* implicit withdraw, decrement aggregate and pcount here.
3913 * only if update is accepted, they'll increment below.
3914 */
40381db7 3915 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3916
3917 /* Update bgp route dampening information. */
40ec3340 3918 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3919 && peer->sort == BGP_PEER_EBGP) {
3920 /* This is implicit withdraw so we should update
40ec3340
DS
3921 * dampening information.
3922 */
40381db7 3923 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3924 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3925 }
49e5a4a0 3926#ifdef ENABLE_BGP_VNC
d62a17ae 3927 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3928 struct bgp_dest *pdest = NULL;
d62a17ae 3929 struct bgp_table *table = NULL;
3930
9bcb3eef
DS
3931 pdest = bgp_node_get(bgp->rib[afi][safi],
3932 (struct prefix *)prd);
3933 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3934 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3935
3936 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3937 bgp, prd, table, p, pi);
d62a17ae 3938 }
9bcb3eef 3939 bgp_dest_unlock_node(pdest);
d62a17ae 3940 }
3941 if ((afi == AFI_IP || afi == AFI_IP6)
3942 && (safi == SAFI_UNICAST)) {
40381db7 3943 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3944 /*
3945 * Implicit withdraw case.
3946 */
3947 ++vnc_implicit_withdraw;
40381db7
DS
3948 vnc_import_bgp_del_route(bgp, p, pi);
3949 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3950 }
3951 }
65efcfce 3952#endif
128ea8ab 3953
d62a17ae 3954 /* Special handling for EVPN update of an existing route. If the
3955 * extended community attribute has changed, we need to
3956 * un-import
3957 * the route using its existing extended community. It will be
3958 * subsequently processed for import with the new extended
3959 * community.
3960 */
6f8c9c11
PR
3961 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
3962 && !same_attr) {
40381db7 3963 if ((pi->attr->flag
d62a17ae 3964 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
3965 && (attr_new->flag
3966 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
3967 int cmp;
3968
40381db7 3969 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 3970 attr_new->ecommunity);
3971 if (!cmp) {
3972 if (bgp_debug_update(peer, p, NULL, 1))
3973 zlog_debug(
3974 "Change in EXT-COMM, existing %s new %s",
3975 ecommunity_str(
40381db7 3976 pi->attr->ecommunity),
d62a17ae 3977 ecommunity_str(
3978 attr_new->ecommunity));
6f8c9c11
PR
3979 if (safi == SAFI_EVPN)
3980 bgp_evpn_unimport_route(
3981 bgp, afi, safi, p, pi);
3982 else /* SAFI_MPLS_VPN */
3983 vpn_leak_to_vrf_withdraw(bgp,
3984 pi);
d62a17ae 3985 }
3986 }
3987 }
718e3744 3988
d62a17ae 3989 /* Update to new attribute. */
40381db7
DS
3990 bgp_attr_unintern(&pi->attr);
3991 pi->attr = attr_new;
d62a17ae 3992
3993 /* Update MPLS label */
3994 if (has_valid_label) {
40381db7 3995 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
3996 if (extra->label != label) {
3997 memcpy(&extra->label, label,
dbd587da 3998 num_labels * sizeof(mpls_label_t));
8ba71050
NS
3999 extra->num_labels = num_labels;
4000 }
b57ba6d2
MK
4001 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4002 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4003 }
718e3744 4004
e496b420
HS
4005 /* Update SRv6 SID */
4006 if (attr->srv6_l3vpn) {
4007 extra = bgp_path_info_extra_get(pi);
4008 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4009 sid_copy(&extra->sid[0],
4010 &attr->srv6_l3vpn->sid);
4011 extra->num_sids = 1;
4012 }
4013 } else if (attr->srv6_vpn) {
4014 extra = bgp_path_info_extra_get(pi);
4015 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4016 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4017 extra->num_sids = 1;
4018 }
4019 }
4020
49e5a4a0 4021#ifdef ENABLE_BGP_VNC
d62a17ae 4022 if ((afi == AFI_IP || afi == AFI_IP6)
4023 && (safi == SAFI_UNICAST)) {
4024 if (vnc_implicit_withdraw) {
4025 /*
4026 * Add back the route with its new attributes
4027 * (e.g., nexthop).
4028 * The route is still selected, until the route
4029 * selection
4030 * queued by bgp_process actually runs. We have
4031 * to make this
4032 * update to the VNC side immediately to avoid
4033 * racing against
4034 * configuration changes (e.g., route-map
4035 * changes) which
4036 * trigger re-importation of the entire RIB.
4037 */
40381db7
DS
4038 vnc_import_bgp_add_route(bgp, p, pi);
4039 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4040 }
4041 }
65efcfce
LB
4042#endif
4043
d62a17ae 4044 /* Update bgp route dampening information. */
40ec3340 4045 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4046 && peer->sort == BGP_PEER_EBGP) {
4047 /* Now we do normal update dampening. */
9bcb3eef 4048 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4049 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4050 bgp_dest_unlock_node(dest);
d62a17ae 4051 return 0;
4052 }
4053 }
128ea8ab 4054
d62a17ae 4055 /* Nexthop reachability check - for unicast and
4056 * labeled-unicast.. */
7c312383
AD
4057 if (((afi == AFI_IP || afi == AFI_IP6)
4058 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4059 || (safi == SAFI_EVPN &&
4060 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4061 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4062 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4063 && !CHECK_FLAG(peer->flags,
4064 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4065 && !CHECK_FLAG(bgp->flags,
4066 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4067 connected = 1;
4068 else
4069 connected = 0;
4070
960035b2
PZ
4071 struct bgp *bgp_nexthop = bgp;
4072
40381db7
DS
4073 if (pi->extra && pi->extra->bgp_orig)
4074 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4075
7c312383
AD
4076 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4077
4078 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4053e952 4079 safi, pi, NULL, connected)
a4d82a8a 4080 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4081 bgp_path_info_set_flag(dest, pi,
4082 BGP_PATH_VALID);
d62a17ae 4083 else {
4084 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4085 zlog_debug("%s(%pI4): NH unresolved",
4086 __func__,
4087 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4088 }
9bcb3eef 4089 bgp_path_info_unset_flag(dest, pi,
18ee8310 4090 BGP_PATH_VALID);
d62a17ae 4091 }
4092 } else
9bcb3eef 4093 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4094
49e5a4a0 4095#ifdef ENABLE_BGP_VNC
d62a17ae 4096 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4097 struct bgp_dest *pdest = NULL;
d62a17ae 4098 struct bgp_table *table = NULL;
4099
9bcb3eef
DS
4100 pdest = bgp_node_get(bgp->rib[afi][safi],
4101 (struct prefix *)prd);
4102 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4103 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4104
4105 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4106 bgp, prd, table, p, pi);
d62a17ae 4107 }
9bcb3eef 4108 bgp_dest_unlock_node(pdest);
d62a17ae 4109 }
4110#endif
718e3744 4111
d62a17ae 4112 /* If this is an EVPN route and some attribute has changed,
4113 * process
4114 * route for import. If the extended community has changed, we
4115 * would
4116 * have done the un-import earlier and the import would result
4117 * in the
4118 * route getting injected into appropriate L2 VNIs. If it is
4119 * just
4120 * some other attribute change, the import will result in
4121 * updating
4122 * the attributes for the route in the VNI(s).
4123 */
7c312383
AD
4124 if (safi == SAFI_EVPN && !same_attr &&
4125 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4126 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4127
4128 /* Process change. */
40381db7 4129 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4130
9bcb3eef
DS
4131 bgp_process(bgp, dest, afi, safi);
4132 bgp_dest_unlock_node(dest);
558d1fec 4133
ddb5b488
PZ
4134 if (SAFI_UNICAST == safi
4135 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4136 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4137
40381db7 4138 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4139 }
4140 if ((SAFI_MPLS_VPN == safi)
4141 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4142
40381db7 4143 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4144 }
4145
49e5a4a0 4146#ifdef ENABLE_BGP_VNC
d62a17ae 4147 if (SAFI_MPLS_VPN == safi) {
4148 mpls_label_t label_decoded = decode_label(label);
28070ee3 4149
d62a17ae 4150 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4151 type, sub_type, &label_decoded);
4152 }
4153 if (SAFI_ENCAP == safi) {
4154 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4155 type, sub_type, NULL);
4156 }
28070ee3
PZ
4157#endif
4158
d62a17ae 4159 return 0;
4160 } // End of implicit withdraw
718e3744 4161
d62a17ae 4162 /* Received Logging. */
4163 if (bgp_debug_update(peer, p, NULL, 1)) {
4164 if (!peer->rcvd_attr_printed) {
4165 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4166 peer->rcvd_attr_str);
4167 peer->rcvd_attr_printed = 1;
4168 }
718e3744 4169
a4d82a8a 4170 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4171 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4172 sizeof(pfx_buf));
4173 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4174 }
718e3744 4175
d62a17ae 4176 /* Make new BGP info. */
9bcb3eef 4177 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4178
d62a17ae 4179 /* Update MPLS label */
4180 if (has_valid_label) {
18ee8310 4181 extra = bgp_path_info_extra_get(new);
8ba71050 4182 if (extra->label != label) {
dbd587da
QY
4183 memcpy(&extra->label, label,
4184 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4185 extra->num_labels = num_labels;
4186 }
b57ba6d2
MK
4187 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4188 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4189 }
718e3744 4190
e496b420
HS
4191 /* Update SRv6 SID */
4192 if (safi == SAFI_MPLS_VPN) {
4193 extra = bgp_path_info_extra_get(new);
4194 if (attr->srv6_l3vpn) {
4195 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4196 extra->num_sids = 1;
4197 } else if (attr->srv6_vpn) {
4198 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4199 extra->num_sids = 1;
4200 }
4201 }
4202
d62a17ae 4203 /* Update Overlay Index */
4204 if (afi == AFI_L2VPN) {
4205 overlay_index_update(new->attr,
d62a17ae 4206 evpn == NULL ? NULL : &evpn->gw_ip);
4207 }
4208 /* Nexthop reachability check. */
7c312383
AD
4209 if (((afi == AFI_IP || afi == AFI_IP6)
4210 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4211 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4212 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4213 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4214 && !CHECK_FLAG(peer->flags,
4215 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4216 && !CHECK_FLAG(bgp->flags,
4217 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4218 connected = 1;
4219 else
4220 connected = 0;
4221
7c312383
AD
4222 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4223
4053e952 4224 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
7c312383 4225 connected)
a4d82a8a 4226 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4227 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4228 else {
4229 if (BGP_DEBUG(nht, NHT)) {
4230 char buf1[INET6_ADDRSTRLEN];
4231 inet_ntop(AF_INET,
4232 (const void *)&attr_new->nexthop,
4233 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4234 zlog_debug("%s(%s): NH unresolved", __func__,
4235 buf1);
d62a17ae 4236 }
9bcb3eef 4237 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4238 }
4239 } else
9bcb3eef 4240 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4241
d62a17ae 4242 /* Addpath ID */
4243 new->addpath_rx_id = addpath_id;
4244
4245 /* Increment prefix */
4246 bgp_aggregate_increment(bgp, p, new, afi, safi);
4247
4248 /* Register new BGP information. */
9bcb3eef 4249 bgp_path_info_add(dest, new);
d62a17ae 4250
4251 /* route_node_get lock */
9bcb3eef 4252 bgp_dest_unlock_node(dest);
558d1fec 4253
49e5a4a0 4254#ifdef ENABLE_BGP_VNC
d62a17ae 4255 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4256 struct bgp_dest *pdest = NULL;
d62a17ae 4257 struct bgp_table *table = NULL;
4258
9bcb3eef
DS
4259 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4260 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4261 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4262
4263 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4264 bgp, prd, table, p, new);
4265 }
9bcb3eef 4266 bgp_dest_unlock_node(pdest);
d62a17ae 4267 }
65efcfce
LB
4268#endif
4269
d62a17ae 4270 /* If this is an EVPN route, process for import. */
7c312383 4271 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4272 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4273
9bcb3eef 4274 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4275
d62a17ae 4276 /* Process change. */
9bcb3eef 4277 bgp_process(bgp, dest, afi, safi);
718e3744 4278
ddb5b488
PZ
4279 if (SAFI_UNICAST == safi
4280 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4281 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4282 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4283 }
4284 if ((SAFI_MPLS_VPN == safi)
4285 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4286
4287 vpn_leak_to_vrf_update(bgp, new);
4288 }
49e5a4a0 4289#ifdef ENABLE_BGP_VNC
d62a17ae 4290 if (SAFI_MPLS_VPN == safi) {
4291 mpls_label_t label_decoded = decode_label(label);
28070ee3 4292
d62a17ae 4293 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4294 sub_type, &label_decoded);
4295 }
4296 if (SAFI_ENCAP == safi) {
4297 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4298 sub_type, NULL);
4299 }
28070ee3
PZ
4300#endif
4301
d62a17ae 4302 return 0;
718e3744 4303
d62a17ae 4304/* This BGP update is filtered. Log the reason then update BGP
4305 entry. */
4306filtered:
9bcb3eef 4307 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4308
d62a17ae 4309 if (bgp_debug_update(peer, p, NULL, 1)) {
4310 if (!peer->rcvd_attr_printed) {
4311 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4312 peer->rcvd_attr_str);
4313 peer->rcvd_attr_printed = 1;
4314 }
718e3744 4315
a4d82a8a 4316 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4317 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4318 sizeof(pfx_buf));
4319 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4320 peer->host, pfx_buf, reason);
4321 }
128ea8ab 4322
40381db7 4323 if (pi) {
d62a17ae 4324 /* If this is an EVPN route, un-import it as it is now filtered.
4325 */
4326 if (safi == SAFI_EVPN)
40381db7 4327 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4328
ddb5b488
PZ
4329 if (SAFI_UNICAST == safi
4330 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4331 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4332
40381db7 4333 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4334 }
4335 if ((SAFI_MPLS_VPN == safi)
4336 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4337
40381db7 4338 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4339 }
4340
9bcb3eef 4341 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4342 }
4343
9bcb3eef 4344 bgp_dest_unlock_node(dest);
558d1fec 4345
49e5a4a0 4346#ifdef ENABLE_BGP_VNC
d62a17ae 4347 /*
4348 * Filtered update is treated as an implicit withdrawal (see
4349 * bgp_rib_remove()
4350 * a few lines above)
4351 */
4352 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4353 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4354 0);
4355 }
97736e32
PZ
4356#endif
4357
d62a17ae 4358 return 0;
718e3744 4359}
4360
26a3ffd6 4361int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4362 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4363 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4364 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4365{
d62a17ae 4366 struct bgp *bgp;
4367 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4368 struct bgp_dest *dest;
40381db7 4369 struct bgp_path_info *pi;
718e3744 4370
49e5a4a0 4371#ifdef ENABLE_BGP_VNC
d62a17ae 4372 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4373 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4374 0);
4375 }
28070ee3
PZ
4376#endif
4377
d62a17ae 4378 bgp = peer->bgp;
4379
4380 /* Lookup node. */
9bcb3eef 4381 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4382
4383 /* If peer is soft reconfiguration enabled. Record input packet for
4384 * further calculation.
4385 *
4386 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4387 * routes that are filtered. This tanks out Quagga RS pretty badly due
4388 * to
4389 * the iteration over all RS clients.
4390 * Since we need to remove the entry from adj_in anyway, do that first
4391 * and
4392 * if there was no entry, we don't need to do anything more.
4393 */
4394 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4395 && peer != bgp->peer_self)
9bcb3eef 4396 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4397 peer->stat_pfx_dup_withdraw++;
4398
d62a17ae 4399 if (bgp_debug_update(peer, p, NULL, 1)) {
4400 bgp_debug_rdpfxpath2str(
a4d82a8a 4401 afi, safi, prd, p, label, num_labels,
d62a17ae 4402 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4403 sizeof(pfx_buf));
4404 zlog_debug(
4405 "%s withdrawing route %s not in adj-in",
4406 peer->host, pfx_buf);
4407 }
9bcb3eef 4408 bgp_dest_unlock_node(dest);
d62a17ae 4409 return 0;
4410 }
cd808e74 4411
d62a17ae 4412 /* Lookup withdrawn route. */
9bcb3eef 4413 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4414 if (pi->peer == peer && pi->type == type
4415 && pi->sub_type == sub_type
4416 && pi->addpath_rx_id == addpath_id)
d62a17ae 4417 break;
4418
4419 /* Logging. */
4420 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4421 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4422 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4423 sizeof(pfx_buf));
4424 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4425 pfx_buf);
4426 }
718e3744 4427
d62a17ae 4428 /* Withdraw specified route from routing table. */
40381db7 4429 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4430 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4431 if (SAFI_UNICAST == safi
4432 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4433 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4434 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4435 }
4436 if ((SAFI_MPLS_VPN == safi)
4437 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4438
40381db7 4439 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4440 }
4441 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4442 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4443 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4444 sizeof(pfx_buf));
4445 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4446 }
718e3744 4447
d62a17ae 4448 /* Unlock bgp_node_get() lock. */
9bcb3eef 4449 bgp_dest_unlock_node(dest);
d62a17ae 4450
4451 return 0;
718e3744 4452}
6b0655a2 4453
d62a17ae 4454void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4455 int withdraw)
718e3744 4456{
d62a17ae 4457 struct update_subgroup *subgrp;
4458 subgrp = peer_subgroup(peer, afi, safi);
4459 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4460}
6182d65b 4461
718e3744 4462
3f9c7369
DS
4463/*
4464 * bgp_stop_announce_route_timer
4465 */
d62a17ae 4466void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4467{
d62a17ae 4468 if (!paf->t_announce_route)
4469 return;
4470
50478845 4471 thread_cancel(&paf->t_announce_route);
718e3744 4472}
6b0655a2 4473
3f9c7369
DS
4474/*
4475 * bgp_announce_route_timer_expired
4476 *
4477 * Callback that is invoked when the route announcement timer for a
4478 * peer_af expires.
4479 */
d62a17ae 4480static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4481{
d62a17ae 4482 struct peer_af *paf;
4483 struct peer *peer;
558d1fec 4484
d62a17ae 4485 paf = THREAD_ARG(t);
4486 peer = paf->peer;
718e3744 4487
d62a17ae 4488 if (peer->status != Established)
4489 return 0;
3f9c7369 4490
d62a17ae 4491 if (!peer->afc_nego[paf->afi][paf->safi])
4492 return 0;
3f9c7369 4493
d62a17ae 4494 peer_af_announce_route(paf, 1);
c5aec50b
MK
4495
4496 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4497 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4498
d62a17ae 4499 return 0;
718e3744 4500}
4501
3f9c7369
DS
4502/*
4503 * bgp_announce_route
4504 *
4505 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4506 */
d62a17ae 4507void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4508{
4509 struct peer_af *paf;
4510 struct update_subgroup *subgrp;
4511
4512 paf = peer_af_find(peer, afi, safi);
4513 if (!paf)
4514 return;
4515 subgrp = PAF_SUBGRP(paf);
4516
4517 /*
4518 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4519 * or a refresh has already been triggered.
4520 */
4521 if (!subgrp || paf->t_announce_route)
4522 return;
4523
4524 /*
4525 * Start a timer to stagger/delay the announce. This serves
4526 * two purposes - announcement can potentially be combined for
4527 * multiple peers and the announcement doesn't happen in the
4528 * vty context.
4529 */
4530 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4531 (subgrp->peer_count == 1)
4532 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4533 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4534 &paf->t_announce_route);
3f9c7369
DS
4535}
4536
4537/*
4538 * Announce routes from all AF tables to a peer.
4539 *
4540 * This should ONLY be called when there is a need to refresh the
4541 * routes to the peer based on a policy change for this peer alone
4542 * or a route refresh request received from the peer.
4543 * The operation will result in splitting the peer from its existing
4544 * subgroups and putting it in new subgroups.
4545 */
d62a17ae 4546void bgp_announce_route_all(struct peer *peer)
718e3744 4547{
d62a17ae 4548 afi_t afi;
4549 safi_t safi;
4550
05c7a1cc
QY
4551 FOREACH_AFI_SAFI (afi, safi)
4552 bgp_announce_route(peer, afi, safi);
718e3744 4553}
6b0655a2 4554
d62a17ae 4555static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4556 struct bgp_table *table,
4557 struct prefix_rd *prd)
718e3744 4558{
d62a17ae 4559 int ret;
9bcb3eef 4560 struct bgp_dest *dest;
d62a17ae 4561 struct bgp_adj_in *ain;
718e3744 4562
d62a17ae 4563 if (!table)
4564 table = peer->bgp->rib[afi][safi];
718e3744 4565
9bcb3eef
DS
4566 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4567 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4568 if (ain->peer != peer)
4569 continue;
8692c506 4570
d7d15889 4571 struct bgp_path_info *pi;
d7c0a89a 4572 uint32_t num_labels = 0;
b57ba6d2 4573 mpls_label_t *label_pnt = NULL;
8cb687c2 4574 struct bgp_route_evpn evpn;
b57ba6d2 4575
9bcb3eef 4576 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
d7d15889
DS
4577 pi = pi->next)
4578 if (pi->peer == peer)
4579 break;
4580
40381db7
DS
4581 if (pi && pi->extra)
4582 num_labels = pi->extra->num_labels;
b57ba6d2 4583 if (num_labels)
40381db7 4584 label_pnt = &pi->extra->label[0];
8cb687c2 4585 if (pi)
6c924775
DS
4586 memcpy(&evpn,
4587 bgp_attr_get_evpn_overlay(pi->attr),
8cb687c2
DS
4588 sizeof(evpn));
4589 else
4590 memset(&evpn, 0, sizeof(evpn));
8692c506 4591
9bcb3eef
DS
4592 ret = bgp_update(peer, bgp_dest_get_prefix(dest),
4593 ain->addpath_rx_id, ain->attr, afi,
4594 safi, ZEBRA_ROUTE_BGP,
a4d82a8a 4595 BGP_ROUTE_NORMAL, prd, label_pnt,
8cb687c2 4596 num_labels, 1, &evpn);
ea47320b
DL
4597
4598 if (ret < 0) {
9bcb3eef 4599 bgp_dest_unlock_node(dest);
ea47320b 4600 return;
d62a17ae 4601 }
4602 }
718e3744 4603}
4604
d62a17ae 4605void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4606{
9bcb3eef 4607 struct bgp_dest *dest;
d62a17ae 4608 struct bgp_table *table;
718e3744 4609
d62a17ae 4610 if (peer->status != Established)
4611 return;
718e3744 4612
d62a17ae 4613 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
4614 && (safi != SAFI_EVPN))
4615 bgp_soft_reconfig_table(peer, afi, safi, NULL, NULL);
4616 else
9bcb3eef
DS
4617 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4618 dest = bgp_route_next(dest)) {
4619 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4620
b54892e0
DS
4621 if (table == NULL)
4622 continue;
8692c506 4623
9bcb3eef 4624 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4625 struct prefix_rd prd;
4626
4627 prd.family = AF_UNSPEC;
4628 prd.prefixlen = 64;
4629 memcpy(&prd.val, p->u.val, 8);
4630
4631 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4632 }
718e3744 4633}
6b0655a2 4634
228da428 4635
d62a17ae 4636struct bgp_clear_node_queue {
9bcb3eef 4637 struct bgp_dest *dest;
228da428
CC
4638};
4639
d62a17ae 4640static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4641{
d62a17ae 4642 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4643 struct bgp_dest *dest = cnq->dest;
d62a17ae 4644 struct peer *peer = wq->spec.data;
40381db7 4645 struct bgp_path_info *pi;
3103e8d2 4646 struct bgp *bgp;
9bcb3eef
DS
4647 afi_t afi = bgp_dest_table(dest)->afi;
4648 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4649
9bcb3eef 4650 assert(dest && peer);
3103e8d2 4651 bgp = peer->bgp;
d62a17ae 4652
4653 /* It is possible that we have multiple paths for a prefix from a peer
4654 * if that peer is using AddPath.
4655 */
9bcb3eef 4656 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4657 if (pi->peer != peer)
ea47320b
DL
4658 continue;
4659
4660 /* graceful restart STALE flag set. */
9af52ccf
DA
4661 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4662 && peer->nsf[afi][safi])
4663 || CHECK_FLAG(peer->af_sflags[afi][safi],
4664 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4665 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4666 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4667 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4668 else {
4669 /* If this is an EVPN route, process for
4670 * un-import. */
4671 if (safi == SAFI_EVPN)
9bcb3eef
DS
4672 bgp_evpn_unimport_route(
4673 bgp, afi, safi,
4674 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4675 /* Handle withdraw for VRF route-leaking and L3VPN */
4676 if (SAFI_UNICAST == safi
4677 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4678 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4679 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4680 bgp, pi);
960035b2 4681 }
3103e8d2 4682 if (SAFI_MPLS_VPN == safi &&
960035b2 4683 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4684 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4685 }
3103e8d2 4686
9bcb3eef 4687 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4688 }
ea47320b 4689 }
d62a17ae 4690 return WQ_SUCCESS;
200df115 4691}
4692
d62a17ae 4693static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4694{
d62a17ae 4695 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4696 struct bgp_dest *dest = cnq->dest;
4697 struct bgp_table *table = bgp_dest_table(dest);
228da428 4698
9bcb3eef 4699 bgp_dest_unlock_node(dest);
d62a17ae 4700 bgp_table_unlock(table);
4701 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4702}
4703
d62a17ae 4704static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4705{
d62a17ae 4706 struct peer *peer = wq->spec.data;
64e580a7 4707
d62a17ae 4708 /* Tickle FSM to start moving again */
4709 BGP_EVENT_ADD(peer, Clearing_Completed);
4710
4711 peer_unlock(peer); /* bgp_clear_route */
200df115 4712}
718e3744 4713
d62a17ae 4714static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4715{
d62a17ae 4716 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4717
4718 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4719#undef CLEAR_QUEUE_NAME_LEN
4720
0ce1ca80 4721 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4722 peer->clear_node_queue->spec.hold = 10;
4723 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4724 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4725 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4726 peer->clear_node_queue->spec.max_retries = 0;
4727
4728 /* we only 'lock' this peer reference when the queue is actually active
4729 */
4730 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4731}
4732
d62a17ae 4733static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4734 struct bgp_table *table)
65ca75e0 4735{
9bcb3eef 4736 struct bgp_dest *dest;
b6c386bb 4737 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4738
d62a17ae 4739 if (!table)
4740 table = peer->bgp->rib[afi][safi];
dc83d712 4741
d62a17ae 4742 /* If still no table => afi/safi isn't configured at all or smth. */
4743 if (!table)
4744 return;
dc83d712 4745
9bcb3eef 4746 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4747 struct bgp_path_info *pi, *next;
d62a17ae 4748 struct bgp_adj_in *ain;
4749 struct bgp_adj_in *ain_next;
4750
4751 /* XXX:TODO: This is suboptimal, every non-empty route_node is
4752 * queued for every clearing peer, regardless of whether it is
4753 * relevant to the peer at hand.
4754 *
4755 * Overview: There are 3 different indices which need to be
4756 * scrubbed, potentially, when a peer is removed:
4757 *
4758 * 1 peer's routes visible via the RIB (ie accepted routes)
4759 * 2 peer's routes visible by the (optional) peer's adj-in index
4760 * 3 other routes visible by the peer's adj-out index
4761 *
4762 * 3 there is no hurry in scrubbing, once the struct peer is
4763 * removed from bgp->peer, we could just GC such deleted peer's
4764 * adj-outs at our leisure.
4765 *
4766 * 1 and 2 must be 'scrubbed' in some way, at least made
4767 * invisible via RIB index before peer session is allowed to be
4768 * brought back up. So one needs to know when such a 'search' is
4769 * complete.
4770 *
4771 * Ideally:
4772 *
4773 * - there'd be a single global queue or a single RIB walker
4774 * - rather than tracking which route_nodes still need to be
4775 * examined on a peer basis, we'd track which peers still
4776 * aren't cleared
4777 *
4778 * Given that our per-peer prefix-counts now should be reliable,
4779 * this may actually be achievable. It doesn't seem to be a huge
4780 * problem at this time,
4781 *
4782 * It is possible that we have multiple paths for a prefix from
4783 * a peer
4784 * if that peer is using AddPath.
4785 */
9bcb3eef 4786 ain = dest->adj_in;
d62a17ae 4787 while (ain) {
4788 ain_next = ain->next;
4789
4790 if (ain->peer == peer) {
9bcb3eef
DS
4791 bgp_adj_in_remove(dest, ain);
4792 bgp_dest_unlock_node(dest);
d62a17ae 4793 }
4794
4795 ain = ain_next;
4796 }
4797
9bcb3eef 4798 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
4799 next = pi->next;
4800 if (pi->peer != peer)
d62a17ae 4801 continue;
4802
4803 if (force)
9bcb3eef 4804 bgp_path_info_reap(dest, pi);
d62a17ae 4805 else {
4806 struct bgp_clear_node_queue *cnq;
4807
4808 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
4809 bgp_table_lock(bgp_dest_table(dest));
4810 bgp_dest_lock_node(dest);
d62a17ae 4811 cnq = XCALLOC(
4812 MTYPE_BGP_CLEAR_NODE_QUEUE,
4813 sizeof(struct bgp_clear_node_queue));
9bcb3eef 4814 cnq->dest = dest;
d62a17ae 4815 work_queue_add(peer->clear_node_queue, cnq);
4816 break;
4817 }
4818 }
4819 }
4820 return;
4821}
4822
4823void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
4824{
9bcb3eef 4825 struct bgp_dest *dest;
d62a17ae 4826 struct bgp_table *table;
4827
4828 if (peer->clear_node_queue == NULL)
4829 bgp_clear_node_queue_init(peer);
4830
4831 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
4832 * Idle until it receives a Clearing_Completed event. This protects
4833 * against peers which flap faster than we can we clear, which could
4834 * lead to:
4835 *
4836 * a) race with routes from the new session being installed before
4837 * clear_route_node visits the node (to delete the route of that
4838 * peer)
4839 * b) resource exhaustion, clear_route_node likely leads to an entry
4840 * on the process_main queue. Fast-flapping could cause that queue
4841 * to grow and grow.
4842 */
4843
4844 /* lock peer in assumption that clear-node-queue will get nodes; if so,
4845 * the unlock will happen upon work-queue completion; other wise, the
4846 * unlock happens at the end of this function.
4847 */
4848 if (!peer->clear_node_queue->thread)
4849 peer_lock(peer);
4850
4851 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
4852 bgp_clear_route_table(peer, afi, safi, NULL);
4853 else
9bcb3eef
DS
4854 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4855 dest = bgp_route_next(dest)) {
4856 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
4857 if (!table)
4858 continue;
4859
4860 bgp_clear_route_table(peer, afi, safi, table);
4861 }
d62a17ae 4862
4863 /* unlock if no nodes got added to the clear-node-queue. */
4864 if (!peer->clear_node_queue->thread)
4865 peer_unlock(peer);
718e3744 4866}
d62a17ae 4867
4868void bgp_clear_route_all(struct peer *peer)
718e3744 4869{
d62a17ae 4870 afi_t afi;
4871 safi_t safi;
718e3744 4872
05c7a1cc
QY
4873 FOREACH_AFI_SAFI (afi, safi)
4874 bgp_clear_route(peer, afi, safi);
65efcfce 4875
49e5a4a0 4876#ifdef ENABLE_BGP_VNC
d62a17ae 4877 rfapiProcessPeerDown(peer);
65efcfce 4878#endif
718e3744 4879}
4880
d62a17ae 4881void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4882{
d62a17ae 4883 struct bgp_table *table;
9bcb3eef 4884 struct bgp_dest *dest;
d62a17ae 4885 struct bgp_adj_in *ain;
4886 struct bgp_adj_in *ain_next;
718e3744 4887
d62a17ae 4888 table = peer->bgp->rib[afi][safi];
718e3744 4889
d62a17ae 4890 /* It is possible that we have multiple paths for a prefix from a peer
4891 * if that peer is using AddPath.
4892 */
9bcb3eef
DS
4893 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4894 ain = dest->adj_in;
43143c8f 4895
d62a17ae 4896 while (ain) {
4897 ain_next = ain->next;
43143c8f 4898
d62a17ae 4899 if (ain->peer == peer) {
9bcb3eef
DS
4900 bgp_adj_in_remove(dest, ain);
4901 bgp_dest_unlock_node(dest);
d62a17ae 4902 }
43143c8f 4903
d62a17ae 4904 ain = ain_next;
4905 }
4906 }
718e3744 4907}
93406d87 4908
d62a17ae 4909void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4910{
9bcb3eef 4911 struct bgp_dest *dest;
40381db7 4912 struct bgp_path_info *pi;
d62a17ae 4913 struct bgp_table *table;
4914
9af52ccf 4915 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
4916 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4917 dest = bgp_route_next(dest)) {
4918 struct bgp_dest *rm;
d62a17ae 4919
4920 /* look for neighbor in tables */
9bcb3eef 4921 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4922 if (!table)
ea47320b
DL
4923 continue;
4924
4925 for (rm = bgp_table_top(table); rm;
4926 rm = bgp_route_next(rm))
9bcb3eef 4927 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 4928 pi = pi->next) {
40381db7 4929 if (pi->peer != peer)
ea47320b 4930 continue;
40381db7 4931 if (!CHECK_FLAG(pi->flags,
1defdda8 4932 BGP_PATH_STALE))
ea47320b
DL
4933 break;
4934
40381db7 4935 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
4936 break;
4937 }
d62a17ae 4938 }
4939 } else {
9bcb3eef
DS
4940 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4941 dest = bgp_route_next(dest))
4942 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 4943 pi = pi->next) {
40381db7 4944 if (pi->peer != peer)
ea47320b 4945 continue;
40381db7 4946 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 4947 break;
9bcb3eef 4948 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
4949 break;
4950 }
d62a17ae 4951 }
93406d87 4952}
6b0655a2 4953
9af52ccf
DA
4954void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
4955{
4956 struct bgp_dest *dest, *ndest;
4957 struct bgp_path_info *pi;
4958 struct bgp_table *table;
4959
4960 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
4961 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4962 dest = bgp_route_next(dest)) {
4963 table = bgp_dest_get_bgp_table_info(dest);
4964 if (!table)
4965 continue;
4966
4967 for (ndest = bgp_table_top(table); ndest;
4968 ndest = bgp_route_next(ndest)) {
4969 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
4970 pi = pi->next) {
4971 if (pi->peer != peer)
4972 continue;
4973
4974 if ((CHECK_FLAG(
4975 peer->af_sflags[afi][safi],
4976 PEER_STATUS_ENHANCED_REFRESH))
4977 && !CHECK_FLAG(pi->flags,
4978 BGP_PATH_STALE)
4979 && !CHECK_FLAG(
4980 pi->flags,
4981 BGP_PATH_UNUSEABLE)) {
4982 if (bgp_debug_neighbor_events(
4983 peer))
4984 zlog_debug(
4985 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
4986 peer->host,
4987 afi2str(afi),
4988 safi2str(safi),
4989 bgp_dest_get_prefix(
4990 ndest));
4991
4992 bgp_path_info_set_flag(
4993 ndest, pi,
4994 BGP_PATH_STALE);
4995 }
4996 }
4997 }
4998 }
4999 } else {
5000 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5001 dest = bgp_route_next(dest)) {
5002 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5003 pi = pi->next) {
5004 if (pi->peer != peer)
5005 continue;
5006
5007 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5008 PEER_STATUS_ENHANCED_REFRESH))
5009 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5010 && !CHECK_FLAG(pi->flags,
5011 BGP_PATH_UNUSEABLE)) {
5012 if (bgp_debug_neighbor_events(peer))
5013 zlog_debug(
5014 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5015 peer->host,
5016 afi2str(afi),
5017 safi2str(safi),
5018 bgp_dest_get_prefix(
5019 dest));
5020
5021 bgp_path_info_set_flag(dest, pi,
5022 BGP_PATH_STALE);
5023 }
5024 }
5025 }
5026 }
5027}
5028
3dc339cd 5029bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5030{
e0df4c04 5031 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5032 return true;
e0df4c04 5033
9dac9fc8
DA
5034 if (peer->sort == BGP_PEER_EBGP
5035 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5036 || FILTER_LIST_OUT_NAME(filter)
5037 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5038 return true;
5039 return false;
9dac9fc8
DA
5040}
5041
3dc339cd 5042bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5043{
e0df4c04 5044 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5045 return true;
e0df4c04 5046
9dac9fc8
DA
5047 if (peer->sort == BGP_PEER_EBGP
5048 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5049 || FILTER_LIST_IN_NAME(filter)
5050 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5051 return true;
5052 return false;
9dac9fc8
DA
5053}
5054
568e10ca 5055static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5056 safi_t safi)
bb86c601 5057{
9bcb3eef 5058 struct bgp_dest *dest;
40381db7 5059 struct bgp_path_info *pi;
4b7e6066 5060 struct bgp_path_info *next;
bb86c601 5061
9bcb3eef
DS
5062 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5063 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5064 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5065
40381db7 5066 next = pi->next;
1b7bb747
CS
5067
5068 /* Unimport EVPN routes from VRFs */
5069 if (safi == SAFI_EVPN)
5070 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5071 SAFI_EVPN, p, pi);
1b7bb747 5072
40381db7
DS
5073 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5074 && pi->type == ZEBRA_ROUTE_BGP
5075 && (pi->sub_type == BGP_ROUTE_NORMAL
5076 || pi->sub_type == BGP_ROUTE_AGGREGATE
5077 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5078
d62a17ae 5079 if (bgp_fibupd_safi(safi))
b54892e0 5080 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5081 }
9514b37d 5082
9bcb3eef 5083 bgp_path_info_reap(dest, pi);
d62a17ae 5084 }
bb86c601
LB
5085}
5086
718e3744 5087/* Delete all kernel routes. */
d62a17ae 5088void bgp_cleanup_routes(struct bgp *bgp)
5089{
5090 afi_t afi;
9bcb3eef 5091 struct bgp_dest *dest;
67009e22 5092 struct bgp_table *table;
d62a17ae 5093
5094 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5095 if (afi == AFI_L2VPN)
5096 continue;
568e10ca 5097 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5098 SAFI_UNICAST);
d62a17ae 5099 /*
5100 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5101 */
5102 if (afi != AFI_L2VPN) {
5103 safi_t safi;
5104 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5105 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5106 dest = bgp_route_next(dest)) {
5107 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5108 if (table != NULL) {
5109 bgp_cleanup_table(bgp, table, safi);
5110 bgp_table_finish(&table);
9bcb3eef
DS
5111 bgp_dest_set_bgp_table_info(dest, NULL);
5112 bgp_dest_unlock_node(dest);
d62a17ae 5113 }
5114 }
5115 safi = SAFI_ENCAP;
9bcb3eef
DS
5116 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5117 dest = bgp_route_next(dest)) {
5118 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5119 if (table != NULL) {
5120 bgp_cleanup_table(bgp, table, safi);
5121 bgp_table_finish(&table);
9bcb3eef
DS
5122 bgp_dest_set_bgp_table_info(dest, NULL);
5123 bgp_dest_unlock_node(dest);
d62a17ae 5124 }
5125 }
5126 }
5127 }
9bcb3eef
DS
5128 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5129 dest = bgp_route_next(dest)) {
5130 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5131 if (table != NULL) {
5132 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5133 bgp_table_finish(&table);
9bcb3eef
DS
5134 bgp_dest_set_bgp_table_info(dest, NULL);
5135 bgp_dest_unlock_node(dest);
d62a17ae 5136 }
bb86c601 5137 }
718e3744 5138}
5139
d62a17ae 5140void bgp_reset(void)
718e3744 5141{
d62a17ae 5142 vty_reset();
5143 bgp_zclient_reset();
5144 access_list_reset();
5145 prefix_list_reset();
718e3744 5146}
6b0655a2 5147
d62a17ae 5148static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5149{
d62a17ae 5150 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5151 && CHECK_FLAG(peer->af_cap[afi][safi],
5152 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5153}
5154
718e3744 5155/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5156 value. */
d62a17ae 5157int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5158 struct bgp_nlri *packet)
5159{
d7c0a89a
QY
5160 uint8_t *pnt;
5161 uint8_t *lim;
d62a17ae 5162 struct prefix p;
5163 int psize;
5164 int ret;
5165 afi_t afi;
5166 safi_t safi;
5167 int addpath_encoded;
d7c0a89a 5168 uint32_t addpath_id;
d62a17ae 5169
d62a17ae 5170 pnt = packet->nlri;
5171 lim = pnt + packet->length;
5172 afi = packet->afi;
5173 safi = packet->safi;
5174 addpath_id = 0;
5175 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5176
5177 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5178 syntactic validity. If the field is syntactically incorrect,
5179 then the Error Subcode is set to Invalid Network Field. */
5180 for (; pnt < lim; pnt += psize) {
5181 /* Clear prefix structure. */
5182 memset(&p, 0, sizeof(struct prefix));
5183
5184 if (addpath_encoded) {
5185
5186 /* When packet overflow occurs return immediately. */
761ed665 5187 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5188 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5189
a3a850a1 5190 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5191 addpath_id = ntohl(addpath_id);
d62a17ae 5192 pnt += BGP_ADDPATH_ID_LEN;
5193 }
718e3744 5194
d62a17ae 5195 /* Fetch prefix length. */
5196 p.prefixlen = *pnt++;
5197 /* afi/safi validity already verified by caller,
5198 * bgp_update_receive */
5199 p.family = afi2family(afi);
5200
5201 /* Prefix length check. */
5202 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5203 flog_err(
e50f7cfd 5204 EC_BGP_UPDATE_RCV,
14454c9f 5205 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5206 peer->host, p.prefixlen, packet->afi);
513386b5 5207 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5208 }
6b0655a2 5209
d62a17ae 5210 /* Packet size overflow check. */
5211 psize = PSIZE(p.prefixlen);
5212
5213 /* When packet overflow occur return immediately. */
5214 if (pnt + psize > lim) {
af4c2728 5215 flog_err(
e50f7cfd 5216 EC_BGP_UPDATE_RCV,
d62a17ae 5217 "%s [Error] Update packet error (prefix length %d overflows packet)",
5218 peer->host, p.prefixlen);
513386b5 5219 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5220 }
5221
5222 /* Defensive coding, double-check the psize fits in a struct
5223 * prefix */
5224 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5225 flog_err(
e50f7cfd 5226 EC_BGP_UPDATE_RCV,
d62a17ae 5227 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5228 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5229 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5230 }
5231
5232 /* Fetch prefix from NLRI packet. */
a85297a7 5233 memcpy(p.u.val, pnt, psize);
d62a17ae 5234
5235 /* Check address. */
5236 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5237 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5238 /* From RFC4271 Section 6.3:
5239 *
5240 * If a prefix in the NLRI field is semantically
5241 * incorrect
5242 * (e.g., an unexpected multicast IP address),
5243 * an error SHOULD
5244 * be logged locally, and the prefix SHOULD be
5245 * ignored.
a4d82a8a 5246 */
af4c2728 5247 flog_err(
e50f7cfd 5248 EC_BGP_UPDATE_RCV,
23d0a753
DA
5249 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5250 peer->host, &p.u.prefix4);
d62a17ae 5251 continue;
5252 }
5253 }
5254
5255 /* Check address. */
5256 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5257 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5258 flog_err(
e50f7cfd 5259 EC_BGP_UPDATE_RCV,
c0d72166
DS
5260 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5261 peer->host, &p.u.prefix6);
d62a17ae 5262
5263 continue;
5264 }
5265 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5266 flog_err(
e50f7cfd 5267 EC_BGP_UPDATE_RCV,
c0d72166
DS
5268 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5269 peer->host, &p.u.prefix6);
d62a17ae 5270
5271 continue;
5272 }
5273 }
5274
5275 /* Normal process. */
5276 if (attr)
5277 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5278 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5279 NULL, NULL, 0, 0, NULL);
d62a17ae 5280 else
5281 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5282 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5283 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5284 NULL);
d62a17ae 5285
513386b5
DA
5286 /* Do not send BGP notification twice when maximum-prefix count
5287 * overflow. */
5288 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5289 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5290
5291 /* Address family configuration mismatch. */
d62a17ae 5292 if (ret < 0)
513386b5 5293 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5294 }
5295
5296 /* Packet length consistency check. */
5297 if (pnt != lim) {
af4c2728 5298 flog_err(
e50f7cfd 5299 EC_BGP_UPDATE_RCV,
d62a17ae 5300 "%s [Error] Update packet error (prefix length mismatch with total length)",
5301 peer->host);
513386b5 5302 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5303 }
6b0655a2 5304
513386b5 5305 return BGP_NLRI_PARSE_OK;
718e3744 5306}
5307
d62a17ae 5308static struct bgp_static *bgp_static_new(void)
718e3744 5309{
d62a17ae 5310 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5311}
5312
d62a17ae 5313static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5314{
0a22ddfb 5315 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5316 route_map_counter_decrement(bgp_static->rmap.map);
5317
0a22ddfb 5318 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5319 XFREE(MTYPE_BGP_STATIC, bgp_static);
5320}
5321
5f040085 5322void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5323 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5324{
9bcb3eef 5325 struct bgp_dest *dest;
40381db7 5326 struct bgp_path_info *pi;
4b7e6066 5327 struct bgp_path_info *new;
40381db7 5328 struct bgp_path_info rmap_path;
d62a17ae 5329 struct attr attr;
5330 struct attr *attr_new;
b68885f9 5331 route_map_result_t ret;
49e5a4a0 5332#ifdef ENABLE_BGP_VNC
d62a17ae 5333 int vnc_implicit_withdraw = 0;
65efcfce 5334#endif
fee0f4c6 5335
d62a17ae 5336 assert(bgp_static);
dd8103a9 5337
9bcb3eef 5338 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5339
d62a17ae 5340 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5341
d62a17ae 5342 attr.nexthop = bgp_static->igpnexthop;
5343 attr.med = bgp_static->igpmetric;
5344 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5345
d62a17ae 5346 if (bgp_static->atomic)
5347 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5348
d62a17ae 5349 /* Store label index, if required. */
5350 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5351 attr.label_index = bgp_static->label_index;
5352 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5353 }
718e3744 5354
d62a17ae 5355 /* Apply route-map. */
5356 if (bgp_static->rmap.name) {
5357 struct attr attr_tmp = attr;
80ced710 5358
40381db7
DS
5359 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5360 rmap_path.peer = bgp->peer_self;
5361 rmap_path.attr = &attr_tmp;
fee0f4c6 5362
d62a17ae 5363 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5364
1782514f 5365 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5366
d62a17ae 5367 bgp->peer_self->rmap_type = 0;
718e3744 5368
d62a17ae 5369 if (ret == RMAP_DENYMATCH) {
5370 /* Free uninterned attribute. */
5371 bgp_attr_flush(&attr_tmp);
718e3744 5372
d62a17ae 5373 /* Unintern original. */
5374 aspath_unintern(&attr.aspath);
5375 bgp_static_withdraw(bgp, p, afi, safi);
5376 return;
5377 }
7f323236 5378
637e5ba4 5379 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5380 bgp_attr_add_gshut_community(&attr_tmp);
5381
d62a17ae 5382 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5383 } else {
5384
637e5ba4 5385 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5386 bgp_attr_add_gshut_community(&attr);
5387
d62a17ae 5388 attr_new = bgp_attr_intern(&attr);
7f323236 5389 }
718e3744 5390
9bcb3eef 5391 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5392 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5393 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5394 break;
5395
40381db7
DS
5396 if (pi) {
5397 if (attrhash_cmp(pi->attr, attr_new)
5398 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5399 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5400 bgp_dest_unlock_node(dest);
d62a17ae 5401 bgp_attr_unintern(&attr_new);
5402 aspath_unintern(&attr.aspath);
5403 return;
5404 } else {
5405 /* The attribute is changed. */
9bcb3eef 5406 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5407
5408 /* Rewrite BGP route information. */
40381db7 5409 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5410 bgp_path_info_restore(dest, pi);
d62a17ae 5411 else
40381db7 5412 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5413#ifdef ENABLE_BGP_VNC
d62a17ae 5414 if ((afi == AFI_IP || afi == AFI_IP6)
5415 && (safi == SAFI_UNICAST)) {
40381db7 5416 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5417 /*
5418 * Implicit withdraw case.
40381db7 5419 * We have to do this before pi is
d62a17ae 5420 * changed
5421 */
5422 ++vnc_implicit_withdraw;
40381db7 5423 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5424 vnc_import_bgp_exterior_del_route(
40381db7 5425 bgp, p, pi);
d62a17ae 5426 }
5427 }
65efcfce 5428#endif
40381db7
DS
5429 bgp_attr_unintern(&pi->attr);
5430 pi->attr = attr_new;
5431 pi->uptime = bgp_clock();
49e5a4a0 5432#ifdef ENABLE_BGP_VNC
d62a17ae 5433 if ((afi == AFI_IP || afi == AFI_IP6)
5434 && (safi == SAFI_UNICAST)) {
5435 if (vnc_implicit_withdraw) {
40381db7 5436 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5437 vnc_import_bgp_exterior_add_route(
40381db7 5438 bgp, p, pi);
d62a17ae 5439 }
5440 }
65efcfce 5441#endif
718e3744 5442
d62a17ae 5443 /* Nexthop reachability check. */
892fedb6 5444 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5445 && (safi == SAFI_UNICAST
5446 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5447
5448 struct bgp *bgp_nexthop = bgp;
5449
40381db7
DS
5450 if (pi->extra && pi->extra->bgp_orig)
5451 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5452
5453 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952
PR
5454 afi, safi, pi, NULL,
5455 0))
9bcb3eef 5456 bgp_path_info_set_flag(dest, pi,
18ee8310 5457 BGP_PATH_VALID);
d62a17ae 5458 else {
5459 if (BGP_DEBUG(nht, NHT)) {
5460 char buf1[INET6_ADDRSTRLEN];
5461 inet_ntop(p->family,
5462 &p->u.prefix, buf1,
5463 INET6_ADDRSTRLEN);
5464 zlog_debug(
5465 "%s(%s): Route not in table, not advertising",
15569c58 5466 __func__, buf1);
d62a17ae 5467 }
18ee8310 5468 bgp_path_info_unset_flag(
9bcb3eef 5469 dest, pi, BGP_PATH_VALID);
d62a17ae 5470 }
5471 } else {
5472 /* Delete the NHT structure if any, if we're
5473 * toggling between
5474 * enabling/disabling import check. We
5475 * deregister the route
5476 * from NHT to avoid overloading NHT and the
5477 * process interaction
5478 */
40381db7 5479 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5480 bgp_path_info_set_flag(dest, pi,
5481 BGP_PATH_VALID);
d62a17ae 5482 }
5483 /* Process change. */
40381db7 5484 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5485 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5486
5487 if (SAFI_UNICAST == safi
5488 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5489 || bgp->inst_type
5490 == BGP_INSTANCE_TYPE_DEFAULT)) {
5491 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5492 pi);
ddb5b488
PZ
5493 }
5494
9bcb3eef 5495 bgp_dest_unlock_node(dest);
d62a17ae 5496 aspath_unintern(&attr.aspath);
5497 return;
5498 }
718e3744 5499 }
718e3744 5500
d62a17ae 5501 /* Make new BGP info. */
5502 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5503 attr_new, dest);
d62a17ae 5504 /* Nexthop reachability check. */
892fedb6 5505 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5506 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4053e952 5507 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
9bcb3eef 5508 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5509 else {
5510 if (BGP_DEBUG(nht, NHT)) {
5511 char buf1[INET6_ADDRSTRLEN];
5512 inet_ntop(p->family, &p->u.prefix, buf1,
5513 INET6_ADDRSTRLEN);
5514 zlog_debug(
5515 "%s(%s): Route not in table, not advertising",
15569c58 5516 __func__, buf1);
d62a17ae 5517 }
9bcb3eef 5518 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5519 }
5520 } else {
5521 /* Delete the NHT structure if any, if we're toggling between
5522 * enabling/disabling import check. We deregister the route
5523 * from NHT to avoid overloading NHT and the process interaction
5524 */
5525 bgp_unlink_nexthop(new);
5526
9bcb3eef 5527 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5528 }
078430f6 5529
d62a17ae 5530 /* Aggregate address increment. */
5531 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5532
d62a17ae 5533 /* Register new BGP information. */
9bcb3eef 5534 bgp_path_info_add(dest, new);
718e3744 5535
d62a17ae 5536 /* route_node_get lock */
9bcb3eef 5537 bgp_dest_unlock_node(dest);
d62a17ae 5538
5539 /* Process change. */
9bcb3eef 5540 bgp_process(bgp, dest, afi, safi);
d62a17ae 5541
ddb5b488
PZ
5542 if (SAFI_UNICAST == safi
5543 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5544 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5545 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5546 }
5547
d62a17ae 5548 /* Unintern original. */
5549 aspath_unintern(&attr.aspath);
718e3744 5550}
5551
5f040085 5552void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5553 safi_t safi)
718e3744 5554{
9bcb3eef 5555 struct bgp_dest *dest;
40381db7 5556 struct bgp_path_info *pi;
718e3744 5557
9bcb3eef 5558 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5559
d62a17ae 5560 /* Check selected route and self inserted route. */
9bcb3eef 5561 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5562 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5563 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5564 break;
5565
5566 /* Withdraw static BGP route from routing table. */
40381db7 5567 if (pi) {
ddb5b488
PZ
5568 if (SAFI_UNICAST == safi
5569 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5570 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5571 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5572 }
40381db7
DS
5573 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5574 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5575 bgp_path_info_delete(dest, pi);
5576 bgp_process(bgp, dest, afi, safi);
d62a17ae 5577 }
718e3744 5578
d62a17ae 5579 /* Unlock bgp_node_lookup. */
9bcb3eef 5580 bgp_dest_unlock_node(dest);
718e3744 5581}
5582
137446f9
LB
5583/*
5584 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5585 */
5f040085 5586static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5587 afi_t afi, safi_t safi,
5588 struct prefix_rd *prd)
718e3744 5589{
9bcb3eef 5590 struct bgp_dest *dest;
40381db7 5591 struct bgp_path_info *pi;
718e3744 5592
9bcb3eef 5593 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5594
d62a17ae 5595 /* Check selected route and self inserted route. */
9bcb3eef 5596 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5597 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5598 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5599 break;
718e3744 5600
d62a17ae 5601 /* Withdraw static BGP route from routing table. */
40381db7 5602 if (pi) {
49e5a4a0 5603#ifdef ENABLE_BGP_VNC
d62a17ae 5604 rfapiProcessWithdraw(
40381db7 5605 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5606 1); /* Kill, since it is an administrative change */
65efcfce 5607#endif
ddb5b488
PZ
5608 if (SAFI_MPLS_VPN == safi
5609 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5610 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5611 }
40381db7 5612 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5613 bgp_path_info_delete(dest, pi);
5614 bgp_process(bgp, dest, afi, safi);
d62a17ae 5615 }
718e3744 5616
d62a17ae 5617 /* Unlock bgp_node_lookup. */
9bcb3eef 5618 bgp_dest_unlock_node(dest);
718e3744 5619}
5620
5f040085 5621static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5622 struct bgp_static *bgp_static, afi_t afi,
5623 safi_t safi)
137446f9 5624{
9bcb3eef 5625 struct bgp_dest *dest;
4b7e6066 5626 struct bgp_path_info *new;
d62a17ae 5627 struct attr *attr_new;
5628 struct attr attr = {0};
40381db7 5629 struct bgp_path_info *pi;
49e5a4a0 5630#ifdef ENABLE_BGP_VNC
d62a17ae 5631 mpls_label_t label = 0;
65efcfce 5632#endif
d7c0a89a 5633 uint32_t num_labels = 0;
d62a17ae 5634 union gw_addr add;
137446f9 5635
d62a17ae 5636 assert(bgp_static);
137446f9 5637
b57ba6d2
MK
5638 if (bgp_static->label != MPLS_INVALID_LABEL)
5639 num_labels = 1;
9bcb3eef
DS
5640 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5641 &bgp_static->prd);
137446f9 5642
d62a17ae 5643 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5644
d62a17ae 5645 attr.nexthop = bgp_static->igpnexthop;
5646 attr.med = bgp_static->igpmetric;
5647 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5648
d62a17ae 5649 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5650 || (safi == SAFI_ENCAP)) {
5651 if (afi == AFI_IP) {
5652 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5653 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5654 }
5655 }
5656 if (afi == AFI_L2VPN) {
5657 if (bgp_static->gatewayIp.family == AF_INET)
5658 add.ipv4.s_addr =
5659 bgp_static->gatewayIp.u.prefix4.s_addr;
5660 else if (bgp_static->gatewayIp.family == AF_INET6)
5661 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5662 sizeof(struct in6_addr));
0a50c248 5663 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5664 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5665 struct bgp_encap_type_vxlan bet;
5666 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5667 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5668 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5669 }
5670 if (bgp_static->router_mac) {
5671 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5672 }
5673 }
5674 /* Apply route-map. */
5675 if (bgp_static->rmap.name) {
5676 struct attr attr_tmp = attr;
40381db7 5677 struct bgp_path_info rmap_path;
b68885f9 5678 route_map_result_t ret;
137446f9 5679
40381db7
DS
5680 rmap_path.peer = bgp->peer_self;
5681 rmap_path.attr = &attr_tmp;
137446f9 5682
d62a17ae 5683 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5684
1782514f 5685 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5686
d62a17ae 5687 bgp->peer_self->rmap_type = 0;
137446f9 5688
d62a17ae 5689 if (ret == RMAP_DENYMATCH) {
5690 /* Free uninterned attribute. */
5691 bgp_attr_flush(&attr_tmp);
137446f9 5692
d62a17ae 5693 /* Unintern original. */
5694 aspath_unintern(&attr.aspath);
5695 bgp_static_withdraw_safi(bgp, p, afi, safi,
5696 &bgp_static->prd);
5697 return;
5698 }
137446f9 5699
d62a17ae 5700 attr_new = bgp_attr_intern(&attr_tmp);
5701 } else {
5702 attr_new = bgp_attr_intern(&attr);
5703 }
137446f9 5704
9bcb3eef 5705 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5706 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5707 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5708 break;
5709
40381db7 5710 if (pi) {
d62a17ae 5711 memset(&add, 0, sizeof(union gw_addr));
40381db7 5712 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5713 && overlay_index_equal(afi, pi, &add)
40381db7 5714 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5715 bgp_dest_unlock_node(dest);
d62a17ae 5716 bgp_attr_unintern(&attr_new);
5717 aspath_unintern(&attr.aspath);
5718 return;
5719 } else {
5720 /* The attribute is changed. */
9bcb3eef 5721 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5722
5723 /* Rewrite BGP route information. */
40381db7 5724 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5725 bgp_path_info_restore(dest, pi);
d62a17ae 5726 else
40381db7
DS
5727 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5728 bgp_attr_unintern(&pi->attr);
5729 pi->attr = attr_new;
5730 pi->uptime = bgp_clock();
49e5a4a0 5731#ifdef ENABLE_BGP_VNC
40381db7
DS
5732 if (pi->extra)
5733 label = decode_label(&pi->extra->label[0]);
65efcfce 5734#endif
137446f9 5735
d62a17ae 5736 /* Process change. */
40381db7 5737 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5738 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5739
5740 if (SAFI_MPLS_VPN == safi
5741 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5742 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5743 }
49e5a4a0 5744#ifdef ENABLE_BGP_VNC
40381db7
DS
5745 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5746 pi->attr, afi, safi, pi->type,
5747 pi->sub_type, &label);
65efcfce 5748#endif
9bcb3eef 5749 bgp_dest_unlock_node(dest);
d62a17ae 5750 aspath_unintern(&attr.aspath);
5751 return;
5752 }
5753 }
137446f9
LB
5754
5755
d62a17ae 5756 /* Make new BGP info. */
5757 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5758 attr_new, dest);
1defdda8 5759 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 5760 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
5761 if (num_labels) {
5762 new->extra->label[0] = bgp_static->label;
5763 new->extra->num_labels = num_labels;
5764 }
49e5a4a0 5765#ifdef ENABLE_BGP_VNC
d62a17ae 5766 label = decode_label(&bgp_static->label);
65efcfce 5767#endif
137446f9 5768
d62a17ae 5769 /* Aggregate address increment. */
5770 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 5771
d62a17ae 5772 /* Register new BGP information. */
9bcb3eef 5773 bgp_path_info_add(dest, new);
d62a17ae 5774 /* route_node_get lock */
9bcb3eef 5775 bgp_dest_unlock_node(dest);
137446f9 5776
d62a17ae 5777 /* Process change. */
9bcb3eef 5778 bgp_process(bgp, dest, afi, safi);
137446f9 5779
ddb5b488
PZ
5780 if (SAFI_MPLS_VPN == safi
5781 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
5782 vpn_leak_to_vrf_update(bgp, new);
5783 }
49e5a4a0 5784#ifdef ENABLE_BGP_VNC
d62a17ae 5785 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
5786 safi, new->type, new->sub_type, &label);
65efcfce
LB
5787#endif
5788
d62a17ae 5789 /* Unintern original. */
5790 aspath_unintern(&attr.aspath);
137446f9
LB
5791}
5792
718e3744 5793/* Configure static BGP network. When user don't run zebra, static
5794 route should be installed as valid. */
37a87b8f
CS
5795int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
5796 afi_t afi, safi_t safi, const char *rmap, int backdoor,
5797 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 5798{
d62a17ae 5799 struct prefix p;
5800 struct bgp_static *bgp_static;
9bcb3eef 5801 struct bgp_dest *dest;
d7c0a89a 5802 uint8_t need_update = 0;
d62a17ae 5803
37a87b8f 5804 prefix_copy(&p, pfx);
d62a17ae 5805 apply_mask(&p);
718e3744 5806
e2a86ad9 5807 if (negate) {
718e3744 5808
e2a86ad9 5809 /* Set BGP static route configuration. */
9bcb3eef 5810 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 5811
9bcb3eef 5812 if (!dest) {
37a87b8f
CS
5813 snprintf(errmsg, errmsg_len,
5814 "Can't find static route specified\n");
5815 return -1;
d62a17ae 5816 }
5817
9bcb3eef 5818 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 5819
e2a86ad9
DS
5820 if ((label_index != BGP_INVALID_LABEL_INDEX)
5821 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
5822 snprintf(errmsg, errmsg_len,
5823 "label-index doesn't match static route\n");
5824 return -1;
d62a17ae 5825 }
d62a17ae 5826
e2a86ad9
DS
5827 if ((rmap && bgp_static->rmap.name)
5828 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
5829 snprintf(errmsg, errmsg_len,
5830 "route-map name doesn't match static route\n");
5831 return -1;
d62a17ae 5832 }
718e3744 5833
e2a86ad9
DS
5834 /* Update BGP RIB. */
5835 if (!bgp_static->backdoor)
5836 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 5837
e2a86ad9
DS
5838 /* Clear configuration. */
5839 bgp_static_free(bgp_static);
9bcb3eef
DS
5840 bgp_dest_set_bgp_static_info(dest, NULL);
5841 bgp_dest_unlock_node(dest);
5842 bgp_dest_unlock_node(dest);
e2a86ad9 5843 } else {
718e3744 5844
e2a86ad9 5845 /* Set BGP static route configuration. */
9bcb3eef
DS
5846 dest = bgp_node_get(bgp->route[afi][safi], &p);
5847 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 5848 if (bgp_static) {
e2a86ad9 5849 /* Configuration change. */
e2a86ad9
DS
5850 /* Label index cannot be changed. */
5851 if (bgp_static->label_index != label_index) {
37a87b8f
CS
5852 snprintf(errmsg, errmsg_len,
5853 "cannot change label-index\n");
5854 return -1;
e2a86ad9 5855 }
d62a17ae 5856
e2a86ad9 5857 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
5858 if (bgp_static->valid
5859 && bgp_static->backdoor != backdoor)
e2a86ad9 5860 need_update = 1;
718e3744 5861
e2a86ad9 5862 bgp_static->backdoor = backdoor;
718e3744 5863
e2a86ad9 5864 if (rmap) {
0a22ddfb
QY
5865 XFREE(MTYPE_ROUTE_MAP_NAME,
5866 bgp_static->rmap.name);
b4897fa5 5867 route_map_counter_decrement(
5868 bgp_static->rmap.map);
e2a86ad9
DS
5869 bgp_static->rmap.name =
5870 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5871 bgp_static->rmap.map =
5872 route_map_lookup_by_name(rmap);
b4897fa5 5873 route_map_counter_increment(
5874 bgp_static->rmap.map);
e2a86ad9 5875 } else {
0a22ddfb
QY
5876 XFREE(MTYPE_ROUTE_MAP_NAME,
5877 bgp_static->rmap.name);
b4897fa5 5878 route_map_counter_decrement(
5879 bgp_static->rmap.map);
e2a86ad9
DS
5880 bgp_static->rmap.map = NULL;
5881 bgp_static->valid = 0;
5882 }
9bcb3eef 5883 bgp_dest_unlock_node(dest);
e2a86ad9
DS
5884 } else {
5885 /* New configuration. */
5886 bgp_static = bgp_static_new();
5887 bgp_static->backdoor = backdoor;
5888 bgp_static->valid = 0;
5889 bgp_static->igpmetric = 0;
975a328e 5890 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 5891 bgp_static->label_index = label_index;
718e3744 5892
e2a86ad9 5893 if (rmap) {
0a22ddfb
QY
5894 XFREE(MTYPE_ROUTE_MAP_NAME,
5895 bgp_static->rmap.name);
b4897fa5 5896 route_map_counter_decrement(
5897 bgp_static->rmap.map);
e2a86ad9
DS
5898 bgp_static->rmap.name =
5899 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
5900 bgp_static->rmap.map =
5901 route_map_lookup_by_name(rmap);
b4897fa5 5902 route_map_counter_increment(
5903 bgp_static->rmap.map);
e2a86ad9 5904 }
9bcb3eef 5905 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 5906 }
d62a17ae 5907
e2a86ad9
DS
5908 bgp_static->valid = 1;
5909 if (need_update)
5910 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 5911
e2a86ad9
DS
5912 if (!bgp_static->backdoor)
5913 bgp_static_update(bgp, &p, bgp_static, afi, safi);
5914 }
d62a17ae 5915
37a87b8f 5916 return 0;
d62a17ae 5917}
5918
5919void bgp_static_add(struct bgp *bgp)
5920{
5921 afi_t afi;
5922 safi_t safi;
9bcb3eef
DS
5923 struct bgp_dest *dest;
5924 struct bgp_dest *rm;
d62a17ae 5925 struct bgp_table *table;
5926 struct bgp_static *bgp_static;
5927
05c7a1cc 5928 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5929 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5930 dest = bgp_route_next(dest)) {
5931 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5932 continue;
ea47320b 5933
05c7a1cc
QY
5934 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5935 || (safi == SAFI_EVPN)) {
9bcb3eef 5936 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5937
5938 for (rm = bgp_table_top(table); rm;
5939 rm = bgp_route_next(rm)) {
a78beeb5 5940 bgp_static =
9bcb3eef 5941 bgp_dest_get_bgp_static_info(
5a8ba9fc 5942 rm);
9bcb3eef
DS
5943 bgp_static_update_safi(
5944 bgp, bgp_dest_get_prefix(rm),
5945 bgp_static, afi, safi);
d62a17ae 5946 }
05c7a1cc 5947 } else {
5a8ba9fc 5948 bgp_static_update(
9bcb3eef
DS
5949 bgp, bgp_dest_get_prefix(dest),
5950 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 5951 safi);
ea47320b 5952 }
05c7a1cc 5953 }
6aeb9e78
DS
5954}
5955
718e3744 5956/* Called from bgp_delete(). Delete all static routes from the BGP
5957 instance. */
d62a17ae 5958void bgp_static_delete(struct bgp *bgp)
5959{
5960 afi_t afi;
5961 safi_t safi;
9bcb3eef
DS
5962 struct bgp_dest *dest;
5963 struct bgp_dest *rm;
d62a17ae 5964 struct bgp_table *table;
5965 struct bgp_static *bgp_static;
5966
05c7a1cc 5967 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
5968 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
5969 dest = bgp_route_next(dest)) {
5970 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 5971 continue;
ea47320b 5972
05c7a1cc
QY
5973 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
5974 || (safi == SAFI_EVPN)) {
9bcb3eef 5975 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
5976
5977 for (rm = bgp_table_top(table); rm;
5978 rm = bgp_route_next(rm)) {
a78beeb5 5979 bgp_static =
9bcb3eef 5980 bgp_dest_get_bgp_static_info(
5a8ba9fc 5981 rm);
c7d14ba6
PG
5982 if (!bgp_static)
5983 continue;
5984
05c7a1cc 5985 bgp_static_withdraw_safi(
9bcb3eef 5986 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
5987 AFI_IP, safi,
5988 (struct prefix_rd *)
9bcb3eef
DS
5989 bgp_dest_get_prefix(
5990 dest));
ea47320b 5991 bgp_static_free(bgp_static);
811c6797 5992 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 5993 NULL);
811c6797 5994 bgp_dest_unlock_node(rm);
d62a17ae 5995 }
05c7a1cc 5996 } else {
9bcb3eef 5997 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 5998 bgp_static_withdraw(bgp,
9bcb3eef 5999 bgp_dest_get_prefix(dest),
b54892e0 6000 afi, safi);
05c7a1cc 6001 bgp_static_free(bgp_static);
9bcb3eef
DS
6002 bgp_dest_set_bgp_static_info(dest, NULL);
6003 bgp_dest_unlock_node(dest);
ea47320b 6004 }
05c7a1cc 6005 }
d62a17ae 6006}
6007
6008void bgp_static_redo_import_check(struct bgp *bgp)
6009{
6010 afi_t afi;
6011 safi_t safi;
9bcb3eef
DS
6012 struct bgp_dest *dest;
6013 struct bgp_dest *rm;
d62a17ae 6014 struct bgp_table *table;
6015 struct bgp_static *bgp_static;
6016
6017 /* Use this flag to force reprocessing of the route */
892fedb6 6018 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6019 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6020 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6021 dest = bgp_route_next(dest)) {
6022 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6023 continue;
ea47320b 6024
05c7a1cc
QY
6025 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6026 || (safi == SAFI_EVPN)) {
9bcb3eef 6027 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6028
6029 for (rm = bgp_table_top(table); rm;
6030 rm = bgp_route_next(rm)) {
a78beeb5 6031 bgp_static =
9bcb3eef 6032 bgp_dest_get_bgp_static_info(
5a8ba9fc 6033 rm);
9bcb3eef
DS
6034 bgp_static_update_safi(
6035 bgp, bgp_dest_get_prefix(rm),
6036 bgp_static, afi, safi);
d62a17ae 6037 }
05c7a1cc 6038 } else {
9bcb3eef
DS
6039 bgp_static = bgp_dest_get_bgp_static_info(dest);
6040 bgp_static_update(bgp,
6041 bgp_dest_get_prefix(dest),
6042 bgp_static, afi, safi);
ea47320b 6043 }
05c7a1cc
QY
6044 }
6045 }
892fedb6 6046 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6047}
6048
6049static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6050 safi_t safi)
6051{
6052 struct bgp_table *table;
9bcb3eef 6053 struct bgp_dest *dest;
40381db7 6054 struct bgp_path_info *pi;
d62a17ae 6055
dfb6fd1d
NT
6056 /* Do not install the aggregate route if BGP is in the
6057 * process of termination.
6058 */
892fedb6
DA
6059 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6060 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6061 return;
6062
d62a17ae 6063 table = bgp->rib[afi][safi];
9bcb3eef
DS
6064 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6065 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6066 if (pi->peer == bgp->peer_self
6067 && ((pi->type == ZEBRA_ROUTE_BGP
6068 && pi->sub_type == BGP_ROUTE_STATIC)
6069 || (pi->type != ZEBRA_ROUTE_BGP
6070 && pi->sub_type
d62a17ae 6071 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6072 bgp_aggregate_decrement(
6073 bgp, bgp_dest_get_prefix(dest), pi, afi,
6074 safi);
40381db7 6075 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6076 bgp_path_info_delete(dest, pi);
6077 bgp_process(bgp, dest, afi, safi);
d62a17ae 6078 }
6079 }
6080 }
ad4cbda1 6081}
6082
6083/*
6084 * Purge all networks and redistributed routes from routing table.
6085 * Invoked upon the instance going down.
6086 */
d62a17ae 6087void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6088{
d62a17ae 6089 afi_t afi;
6090 safi_t safi;
ad4cbda1 6091
05c7a1cc
QY
6092 FOREACH_AFI_SAFI (afi, safi)
6093 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6094}
6095
137446f9
LB
6096/*
6097 * gpz 110624
6098 * Currently this is used to set static routes for VPN and ENCAP.
6099 * I think it can probably be factored with bgp_static_set.
6100 */
d62a17ae 6101int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6102 const char *ip_str, const char *rd_str,
6103 const char *label_str, const char *rmap_str,
6104 int evpn_type, const char *esi, const char *gwip,
6105 const char *ethtag, const char *routermac)
6106{
6107 VTY_DECLVAR_CONTEXT(bgp, bgp);
6108 int ret;
6109 struct prefix p;
6110 struct prefix_rd prd;
9bcb3eef
DS
6111 struct bgp_dest *pdest;
6112 struct bgp_dest *dest;
d62a17ae 6113 struct bgp_table *table;
6114 struct bgp_static *bgp_static;
6115 mpls_label_t label = MPLS_INVALID_LABEL;
6116 struct prefix gw_ip;
6117
6118 /* validate ip prefix */
6119 ret = str2prefix(ip_str, &p);
6120 if (!ret) {
6121 vty_out(vty, "%% Malformed prefix\n");
6122 return CMD_WARNING_CONFIG_FAILED;
6123 }
6124 apply_mask(&p);
6125 if ((afi == AFI_L2VPN)
6126 && (bgp_build_evpn_prefix(evpn_type,
6127 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6128 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6129 return CMD_WARNING_CONFIG_FAILED;
6130 }
718e3744 6131
d62a17ae 6132 ret = str2prefix_rd(rd_str, &prd);
6133 if (!ret) {
6134 vty_out(vty, "%% Malformed rd\n");
6135 return CMD_WARNING_CONFIG_FAILED;
6136 }
718e3744 6137
d62a17ae 6138 if (label_str) {
6139 unsigned long label_val;
6140 label_val = strtoul(label_str, NULL, 10);
6141 encode_label(label_val, &label);
6142 }
9bedbb1e 6143
d62a17ae 6144 if (safi == SAFI_EVPN) {
6145 if (esi && str2esi(esi, NULL) == 0) {
6146 vty_out(vty, "%% Malformed ESI\n");
6147 return CMD_WARNING_CONFIG_FAILED;
6148 }
6149 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6150 vty_out(vty, "%% Malformed Router MAC\n");
6151 return CMD_WARNING_CONFIG_FAILED;
6152 }
6153 if (gwip) {
6154 memset(&gw_ip, 0, sizeof(struct prefix));
6155 ret = str2prefix(gwip, &gw_ip);
6156 if (!ret) {
6157 vty_out(vty, "%% Malformed GatewayIp\n");
6158 return CMD_WARNING_CONFIG_FAILED;
6159 }
6160 if ((gw_ip.family == AF_INET
3714a385 6161 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6162 (struct prefix_evpn *)&p))
6163 || (gw_ip.family == AF_INET6
3714a385 6164 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6165 (struct prefix_evpn *)&p))) {
6166 vty_out(vty,
6167 "%% GatewayIp family differs with IP prefix\n");
6168 return CMD_WARNING_CONFIG_FAILED;
6169 }
6170 }
6171 }
9bcb3eef
DS
6172 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6173 if (!bgp_dest_has_bgp_path_info_data(pdest))
6174 bgp_dest_set_bgp_table_info(pdest,
67009e22 6175 bgp_table_init(bgp, afi, safi));
9bcb3eef 6176 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6177
9bcb3eef 6178 dest = bgp_node_get(table, &p);
d62a17ae 6179
9bcb3eef 6180 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6181 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6182 bgp_dest_unlock_node(dest);
d62a17ae 6183 } else {
6184 /* New configuration. */
6185 bgp_static = bgp_static_new();
6186 bgp_static->backdoor = 0;
6187 bgp_static->valid = 0;
6188 bgp_static->igpmetric = 0;
975a328e 6189 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6190 bgp_static->label = label;
6191 bgp_static->prd = prd;
6192
6193 if (rmap_str) {
0a22ddfb 6194 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6195 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6196 bgp_static->rmap.name =
6197 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6198 bgp_static->rmap.map =
6199 route_map_lookup_by_name(rmap_str);
b4897fa5 6200 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6201 }
718e3744 6202
d62a17ae 6203 if (safi == SAFI_EVPN) {
6204 if (esi) {
6205 bgp_static->eth_s_id =
6206 XCALLOC(MTYPE_ATTR,
0a50c248 6207 sizeof(esi_t));
d62a17ae 6208 str2esi(esi, bgp_static->eth_s_id);
6209 }
6210 if (routermac) {
6211 bgp_static->router_mac =
28328ea9 6212 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6213 (void)prefix_str2mac(routermac,
6214 bgp_static->router_mac);
d62a17ae 6215 }
6216 if (gwip)
6217 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6218 }
9bcb3eef 6219 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6220
d62a17ae 6221 bgp_static->valid = 1;
6222 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6223 }
718e3744 6224
d62a17ae 6225 return CMD_SUCCESS;
718e3744 6226}
6227
6228/* Configure static BGP network. */
d62a17ae 6229int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6230 const char *ip_str, const char *rd_str,
6231 const char *label_str, int evpn_type, const char *esi,
6232 const char *gwip, const char *ethtag)
6233{
6234 VTY_DECLVAR_CONTEXT(bgp, bgp);
6235 int ret;
6236 struct prefix p;
6237 struct prefix_rd prd;
9bcb3eef
DS
6238 struct bgp_dest *pdest;
6239 struct bgp_dest *dest;
d62a17ae 6240 struct bgp_table *table;
6241 struct bgp_static *bgp_static;
6242 mpls_label_t label = MPLS_INVALID_LABEL;
6243
6244 /* Convert IP prefix string to struct prefix. */
6245 ret = str2prefix(ip_str, &p);
6246 if (!ret) {
6247 vty_out(vty, "%% Malformed prefix\n");
6248 return CMD_WARNING_CONFIG_FAILED;
6249 }
6250 apply_mask(&p);
6251 if ((afi == AFI_L2VPN)
6252 && (bgp_build_evpn_prefix(evpn_type,
6253 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6254 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6255 return CMD_WARNING_CONFIG_FAILED;
6256 }
6257 ret = str2prefix_rd(rd_str, &prd);
6258 if (!ret) {
6259 vty_out(vty, "%% Malformed rd\n");
6260 return CMD_WARNING_CONFIG_FAILED;
6261 }
718e3744 6262
d62a17ae 6263 if (label_str) {
6264 unsigned long label_val;
6265 label_val = strtoul(label_str, NULL, 10);
6266 encode_label(label_val, &label);
6267 }
718e3744 6268
9bcb3eef
DS
6269 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6270 if (!bgp_dest_has_bgp_path_info_data(pdest))
6271 bgp_dest_set_bgp_table_info(pdest,
67009e22 6272 bgp_table_init(bgp, afi, safi));
d62a17ae 6273 else
9bcb3eef
DS
6274 bgp_dest_unlock_node(pdest);
6275 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6276
9bcb3eef 6277 dest = bgp_node_lookup(table, &p);
6b0655a2 6278
9bcb3eef 6279 if (dest) {
d62a17ae 6280 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6281
9bcb3eef 6282 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6283 bgp_static_free(bgp_static);
9bcb3eef
DS
6284 bgp_dest_set_bgp_static_info(dest, NULL);
6285 bgp_dest_unlock_node(dest);
6286 bgp_dest_unlock_node(dest);
d62a17ae 6287 } else
6288 vty_out(vty, "%% Can't find the route\n");
6289
6290 return CMD_SUCCESS;
6291}
6292
6293static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6294 const char *rmap_name)
6295{
6296 VTY_DECLVAR_CONTEXT(bgp, bgp);
6297 struct bgp_rmap *rmap;
6298
6299 rmap = &bgp->table_map[afi][safi];
6300 if (rmap_name) {
0a22ddfb 6301 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6302 route_map_counter_decrement(rmap->map);
d62a17ae 6303 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6304 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6305 route_map_counter_increment(rmap->map);
d62a17ae 6306 } else {
0a22ddfb 6307 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6308 route_map_counter_decrement(rmap->map);
d62a17ae 6309 rmap->map = NULL;
6310 }
73ac8160 6311
d62a17ae 6312 if (bgp_fibupd_safi(safi))
6313 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6314
d62a17ae 6315 return CMD_SUCCESS;
73ac8160
DS
6316}
6317
d62a17ae 6318static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6319 const char *rmap_name)
73ac8160 6320{
d62a17ae 6321 VTY_DECLVAR_CONTEXT(bgp, bgp);
6322 struct bgp_rmap *rmap;
73ac8160 6323
d62a17ae 6324 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6325 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6326 route_map_counter_decrement(rmap->map);
d62a17ae 6327 rmap->map = NULL;
73ac8160 6328
d62a17ae 6329 if (bgp_fibupd_safi(safi))
6330 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6331
d62a17ae 6332 return CMD_SUCCESS;
73ac8160
DS
6333}
6334
2b791107 6335void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6336 safi_t safi)
73ac8160 6337{
d62a17ae 6338 if (bgp->table_map[afi][safi].name) {
d62a17ae 6339 vty_out(vty, " table-map %s\n",
6340 bgp->table_map[afi][safi].name);
6341 }
73ac8160
DS
6342}
6343
73ac8160
DS
6344DEFUN (bgp_table_map,
6345 bgp_table_map_cmd,
6346 "table-map WORD",
6347 "BGP table to RIB route download filter\n"
6348 "Name of the route map\n")
6349{
d62a17ae 6350 int idx_word = 1;
6351 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6352 argv[idx_word]->arg);
73ac8160
DS
6353}
6354DEFUN (no_bgp_table_map,
6355 no_bgp_table_map_cmd,
6356 "no table-map WORD",
3a2d747c 6357 NO_STR
73ac8160
DS
6358 "BGP table to RIB route download filter\n"
6359 "Name of the route map\n")
6360{
d62a17ae 6361 int idx_word = 2;
6362 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6363 argv[idx_word]->arg);
73ac8160
DS
6364}
6365
37a87b8f
CS
6366DEFPY_YANG (bgp_network, bgp_network_cmd,
6367 "[no] network \
6368 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6369 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6370 backdoor$backdoor}]",
6371 NO_STR
6372 "Specify a network to announce via BGP\n"
6373 "IPv4 prefix\n"
6374 "Network number\n"
6375 "Network mask\n"
6376 "Network mask\n"
6377 "Route-map to modify the attributes\n"
6378 "Name of the route map\n"
6379 "Label index to associate with the prefix\n"
6380 "Label index value\n"
6381 "Specify a BGP backdoor route\n")
6382{
6383 char addr_prefix_str[PREFIX_STRLEN];
6384 char base_xpath[XPATH_MAXLEN];
6385 afi_t afi;
6386 safi_t safi;
e2a86ad9
DS
6387
6388 if (address_str) {
6389 int ret;
718e3744 6390
e2a86ad9 6391 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6392 addr_prefix_str,
6393 sizeof(addr_prefix_str));
e2a86ad9
DS
6394 if (!ret) {
6395 vty_out(vty, "%% Inconsistent address and mask\n");
6396 return CMD_WARNING_CONFIG_FAILED;
6397 }
d62a17ae 6398 }
718e3744 6399
37a87b8f
CS
6400 afi = bgp_node_afi(vty);
6401 safi = bgp_node_safi(vty);
6402
6403 if (no) {
6404 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6405 } else {
6406 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6407
6408 if (map_name)
6409 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6410 NB_OP_CREATE, map_name);
6411 else
6412 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6413 NB_OP_DESTROY, NULL);
6414
6415 if (label_index_str)
6416 nb_cli_enqueue_change(vty, "./label-index",
6417 NB_OP_MODIFY, label_index_str);
6418
6419 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6420 backdoor ? "true" : "false");
6421 }
6422
6423 snprintf(
6424 base_xpath, sizeof(base_xpath),
6425 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6426 yang_afi_safi_value2identity(afi, safi),
6427 bgp_afi_safi_get_container_str(afi, safi),
6428 address_str ? addr_prefix_str : prefix_str);
6429
6430 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6431}
6432
37a87b8f
CS
6433DEFPY_YANG (ipv6_bgp_network,
6434 ipv6_bgp_network_cmd,
6435 "[no] network X:X::X:X/M$prefix \
6436 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6437 NO_STR
6438 "Specify a network to announce via BGP\n"
6439 "IPv6 prefix\n"
6440 "Route-map to modify the attributes\n"
6441 "Name of the route map\n"
6442 "Label index to associate with the prefix\n"
6443 "Label index value\n")
6444{
6445 char base_xpath[XPATH_MAXLEN];
6446 afi_t afi;
6447 safi_t safi;
6448
6449 afi = bgp_node_afi(vty);
6450 safi = bgp_node_safi(vty);
6451
6452 if (no) {
6453 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6454 } else {
6455 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6456
6457 if (map_name)
6458 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6459 NB_OP_MODIFY, map_name);
6460 else
6461 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6462 NB_OP_DESTROY, NULL);
6463
6464 if (label_index_str)
6465 nb_cli_enqueue_change(vty, "./label-index",
6466 NB_OP_MODIFY, label_index_str);
6467 }
6468
6469 snprintf(
6470 base_xpath, sizeof(base_xpath),
6471 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6472 yang_afi_safi_value2identity(afi, safi),
6473 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6474
6475 return nb_cli_apply_changes(vty, base_xpath);
6476}
6477
6478void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6479 struct lyd_node *dnode,
6480 bool show_defaults)
718e3744 6481{
37a87b8f
CS
6482 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6483
6484 if (yang_dnode_exists(dnode, "./label-index"))
6485 vty_out(vty, " label-index %s",
6486 yang_dnode_get_string(dnode, "./label-index"));
6487
6488 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6489 vty_out(vty, " route-map %s",
6490 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6491
6492 if (yang_dnode_get_bool(dnode, "./backdoor"))
6493 vty_out(vty, " backdoor");
6494
6495 vty_out(vty, "\n");
1b6d5c7e
VV
6496}
6497
d62a17ae 6498static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6499{
d62a17ae 6500 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6501}
6502
d62a17ae 6503static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6504{
365ab2e7
RZ
6505 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6506 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6507 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6508 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6509 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6510}
718e3744 6511
365ab2e7
RZ
6512/**
6513 * Helper function to avoid repeated code: prepare variables for a
6514 * `route_map_apply` call.
6515 *
6516 * \returns `true` on route map match, otherwise `false`.
6517 */
6518static bool aggr_suppress_map_test(struct bgp *bgp,
6519 struct bgp_aggregate *aggregate,
6520 struct bgp_path_info *pi)
6521{
6522 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6523 route_map_result_t rmr = RMAP_DENYMATCH;
6524 struct bgp_path_info rmap_path = {};
6525 struct attr attr = {};
6526
6527 /* No route map entries created, just don't match. */
6528 if (aggregate->suppress_map == NULL)
6529 return false;
6530
6531 /* Call route map matching and return result. */
6532 attr.aspath = aspath_empty();
6533 rmap_path.peer = bgp->peer_self;
6534 rmap_path.attr = &attr;
6535
6536 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6537 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6538 bgp->peer_self->rmap_type = 0;
6539
6540 bgp_attr_flush(&attr);
6541
6542 return rmr == RMAP_PERMITMATCH;
6543}
6544
4056a5f6
RZ
6545/** Test whether the aggregation has suppressed this path or not. */
6546static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6547 struct bgp_path_info *pi)
6548{
6549 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6550 return false;
6551
6552 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6553}
6554
6555/**
6556 * Suppress this path and keep the reference.
6557 *
6558 * \returns `true` if needs processing otherwise `false`.
6559 */
6560static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6561 struct bgp_path_info *pi)
6562{
6563 struct bgp_path_info_extra *pie;
6564
6565 /* Path is already suppressed by this aggregation. */
6566 if (aggr_suppress_exists(aggregate, pi))
6567 return false;
6568
6569 pie = bgp_path_info_extra_get(pi);
6570
6571 /* This is the first suppression, allocate memory and list it. */
6572 if (pie->aggr_suppressors == NULL)
6573 pie->aggr_suppressors = list_new();
6574
6575 listnode_add(pie->aggr_suppressors, aggregate);
6576
6577 /* Only mark for processing if suppressed. */
6578 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6579 if (BGP_DEBUG(update, UPDATE_OUT))
6580 zlog_debug("aggregate-address suppressing: %pFX",
6581 bgp_dest_get_prefix(pi->net));
6582
4056a5f6
RZ
6583 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6584 return true;
6585 }
6586
6587 return false;
6588}
6589
6590/**
6591 * Unsuppress this path and remove the reference.
6592 *
6593 * \returns `true` if needs processing otherwise `false`.
6594 */
6595static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6596 struct bgp_path_info *pi)
6597{
6598 /* Path wasn't suppressed. */
6599 if (!aggr_suppress_exists(aggregate, pi))
6600 return false;
6601
6602 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6603
6604 /* Unsuppress and free extra memory if last item. */
6605 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6606 if (BGP_DEBUG(update, UPDATE_OUT))
6607 zlog_debug("aggregate-address unsuppressing: %pFX",
6608 bgp_dest_get_prefix(pi->net));
6609
4056a5f6
RZ
6610 list_delete(&pi->extra->aggr_suppressors);
6611 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6612 return true;
6613 }
6614
6615 return false;
6616}
6617
3dc339cd
DA
6618static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6619 struct aspath *aspath,
6620 struct community *comm,
6621 struct ecommunity *ecomm,
6622 struct lcommunity *lcomm)
eaaf8adb
DS
6623{
6624 static struct aspath *ae = NULL;
6625
6626 if (!ae)
6627 ae = aspath_empty();
6628
40381db7 6629 if (!pi)
3dc339cd 6630 return false;
eaaf8adb 6631
40381db7 6632 if (origin != pi->attr->origin)
3dc339cd 6633 return false;
eaaf8adb 6634
40381db7 6635 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6636 return false;
29f7d023 6637
40381db7 6638 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6639 return false;
eaaf8adb 6640
3da2cc32 6641 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6642 return false;
eaaf8adb 6643
dd18c5a9 6644 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6645 return false;
dd18c5a9 6646
40381db7 6647 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6648 return false;
7ce8a8e0 6649
3dc339cd 6650 return true;
eaaf8adb
DS
6651}
6652
5f040085
DS
6653static void bgp_aggregate_install(
6654 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6655 uint8_t origin, struct aspath *aspath, struct community *community,
6656 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6657 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6658{
9bcb3eef 6659 struct bgp_dest *dest;
c701010e 6660 struct bgp_table *table;
6f94b685 6661 struct bgp_path_info *pi, *orig, *new;
20894f50 6662 struct attr *attr;
c701010e
DS
6663
6664 table = bgp->rib[afi][safi];
6665
9bcb3eef 6666 dest = bgp_node_get(table, p);
eaaf8adb 6667
9bcb3eef 6668 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6669 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6670 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6671 break;
6672
6aabb15d
RZ
6673 /*
6674 * If we have paths with different MEDs, then don't install
6675 * (or uninstall) the aggregate route.
6676 */
6677 if (aggregate->match_med && aggregate->med_mismatched)
6678 goto uninstall_aggregate_route;
6679
c701010e 6680 if (aggregate->count > 0) {
eaaf8adb
DS
6681 /*
6682 * If the aggregate information has not changed
6683 * no need to re-install it again.
6684 */
6f94b685 6685 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6686 ecommunity, lcommunity)) {
9bcb3eef 6687 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6688
6689 if (aspath)
6690 aspath_free(aspath);
6691 if (community)
3c1f53de 6692 community_free(&community);
3da2cc32
DS
6693 if (ecommunity)
6694 ecommunity_free(&ecommunity);
dd18c5a9
DS
6695 if (lcommunity)
6696 lcommunity_free(&lcommunity);
eaaf8adb
DS
6697
6698 return;
6699 }
6700
6701 /*
6702 * Mark the old as unusable
6703 */
40381db7 6704 if (pi)
9bcb3eef 6705 bgp_path_info_delete(dest, pi);
eaaf8adb 6706
20894f50
DA
6707 attr = bgp_attr_aggregate_intern(
6708 bgp, origin, aspath, community, ecommunity, lcommunity,
6709 aggregate, atomic_aggregate, p);
6710
6711 if (!attr) {
6712 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6713 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6714 zlog_debug("%s: %pFX null attribute", __func__,
6715 p);
20894f50
DA
6716 return;
6717 }
6718
3da2cc32 6719 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6720 bgp->peer_self, attr, dest);
20894f50 6721
1defdda8 6722 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6723
9bcb3eef
DS
6724 bgp_path_info_add(dest, new);
6725 bgp_process(bgp, dest, afi, safi);
c701010e 6726 } else {
6aabb15d 6727 uninstall_aggregate_route:
6f94b685 6728 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6729 if (pi->peer == bgp->peer_self
6730 && pi->type == ZEBRA_ROUTE_BGP
6731 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6732 break;
6733
6734 /* Withdraw static BGP route from routing table. */
40381db7 6735 if (pi) {
9bcb3eef
DS
6736 bgp_path_info_delete(dest, pi);
6737 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6738 }
6739 }
6740
9bcb3eef 6741 bgp_dest_unlock_node(dest);
c701010e
DS
6742}
6743
6aabb15d
RZ
6744/**
6745 * Check if the current path has different MED than other known paths.
6746 *
6747 * \returns `true` if the MED matched the others else `false`.
6748 */
6749static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
6750 struct bgp *bgp, struct bgp_path_info *pi)
6751{
6752 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
6753
6754 /* This is the first route being analyzed. */
6755 if (!aggregate->med_initialized) {
6756 aggregate->med_initialized = true;
6757 aggregate->med_mismatched = false;
6758 aggregate->med_matched_value = cur_med;
6759 } else {
6760 /* Check if routes with different MED showed up. */
6761 if (cur_med != aggregate->med_matched_value)
6762 aggregate->med_mismatched = true;
6763 }
6764
6765 return !aggregate->med_mismatched;
6766}
6767
6768/**
6769 * Initializes and tests all routes in the aggregate address path for MED
6770 * values.
6771 *
6772 * \returns `true` if all MEDs are the same otherwise `false`.
6773 */
6774static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
6775 struct bgp *bgp, const struct prefix *p,
6776 afi_t afi, safi_t safi)
6777{
6778 struct bgp_table *table = bgp->rib[afi][safi];
6779 const struct prefix *dest_p;
6780 struct bgp_dest *dest, *top;
6781 struct bgp_path_info *pi;
6782 bool med_matched = true;
6783
6784 aggregate->med_initialized = false;
6785
6786 top = bgp_node_get(table, p);
6787 for (dest = bgp_node_get(table, p); dest;
6788 dest = bgp_route_next_until(dest, top)) {
6789 dest_p = bgp_dest_get_prefix(dest);
6790 if (dest_p->prefixlen <= p->prefixlen)
6791 continue;
6792
6793 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6794 if (BGP_PATH_HOLDDOWN(pi))
6795 continue;
6796 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6797 continue;
6798 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
6799 med_matched = false;
6800 break;
6801 }
6802 }
6803 if (!med_matched)
6804 break;
6805 }
6806 bgp_dest_unlock_node(top);
6807
6808 return med_matched;
6809}
6810
6811/**
6812 * Toggles the route suppression status for this aggregate address
6813 * configuration.
6814 */
4056a5f6
RZ
6815void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
6816 struct bgp *bgp, const struct prefix *p,
6817 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
6818{
6819 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
6820 const struct prefix *dest_p;
6821 struct bgp_dest *dest, *top;
6822 struct bgp_path_info *pi;
6823 bool toggle_suppression;
6824
6825 /* We've found a different MED we must revert any suppressed routes. */
6826 top = bgp_node_get(table, p);
6827 for (dest = bgp_node_get(table, p); dest;
6828 dest = bgp_route_next_until(dest, top)) {
6829 dest_p = bgp_dest_get_prefix(dest);
6830 if (dest_p->prefixlen <= p->prefixlen)
6831 continue;
6832
6833 toggle_suppression = false;
6834 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
6835 if (BGP_PATH_HOLDDOWN(pi))
6836 continue;
6837 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
6838 continue;
6839
6aabb15d
RZ
6840 /* We are toggling suppression back. */
6841 if (suppress) {
6aabb15d 6842 /* Suppress route if not suppressed already. */
4056a5f6
RZ
6843 if (aggr_suppress_path(aggregate, pi))
6844 toggle_suppression = true;
6aabb15d
RZ
6845 continue;
6846 }
6847
6aabb15d 6848 /* Install route if there is no more suppression. */
4056a5f6 6849 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 6850 toggle_suppression = true;
6aabb15d
RZ
6851 }
6852
6853 if (toggle_suppression)
6854 bgp_process(bgp, dest, afi, safi);
6855 }
6856 bgp_dest_unlock_node(top);
6857}
6858
6859/**
6860 * Aggregate address MED matching incremental test: this function is called
6861 * when the initial aggregation occurred and we are only testing a single
6862 * new path.
6863 *
6864 * In addition to testing and setting the MED validity it also installs back
6865 * suppressed routes (if summary is configured).
6866 *
6867 * Must not be called in `bgp_aggregate_route`.
6868 */
6869static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
6870 struct bgp *bgp, const struct prefix *p,
6871 afi_t afi, safi_t safi,
6872 struct bgp_path_info *pi, bool is_adding)
6873{
6874 /* MED matching disabled. */
6875 if (!aggregate->match_med)
6876 return;
6877
6878 /* Aggregation with different MED, nothing to do. */
6879 if (aggregate->med_mismatched)
6880 return;
6881
6882 /*
6883 * Test the current entry:
6884 *
6885 * is_adding == true: if the new entry doesn't match then we must
6886 * install all suppressed routes.
6887 *
6888 * is_adding == false: if the entry being removed was the last
6889 * unmatching entry then we can suppress all routes.
6890 */
6891 if (!is_adding) {
6892 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
6893 && aggregate->summary_only)
6894 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
6895 safi, true);
6896 } else
6897 bgp_aggregate_med_match(aggregate, bgp, pi);
6898
6899 /* No mismatches, just quit. */
6900 if (!aggregate->med_mismatched)
6901 return;
6902
6903 /* Route summarization is disabled. */
6904 if (!aggregate->summary_only)
6905 return;
6906
6907 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
6908}
6909
b5d58c32 6910/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
6911void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
6912 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 6913{
6914 struct bgp_table *table;
9bcb3eef
DS
6915 struct bgp_dest *top;
6916 struct bgp_dest *dest;
d7c0a89a 6917 uint8_t origin;
d62a17ae 6918 struct aspath *aspath = NULL;
d62a17ae 6919 struct community *community = NULL;
3da2cc32 6920 struct ecommunity *ecommunity = NULL;
dd18c5a9 6921 struct lcommunity *lcommunity = NULL;
40381db7 6922 struct bgp_path_info *pi;
d62a17ae 6923 unsigned long match = 0;
d7c0a89a 6924 uint8_t atomic_aggregate = 0;
d62a17ae 6925
9f822fa2
S
6926 /* If the bgp instance is being deleted or self peer is deleted
6927 * then do not create aggregate route
6928 */
892fedb6
DA
6929 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6930 || (bgp->peer_self == NULL))
9f822fa2
S
6931 return;
6932
6aabb15d
RZ
6933 /* Initialize and test routes for MED difference. */
6934 if (aggregate->match_med)
6935 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
6936
4056a5f6
RZ
6937 /*
6938 * Reset aggregate count: we might've been called from route map
6939 * update so in that case we must retest all more specific routes.
6940 *
6941 * \see `bgp_route_map_process_update`.
6942 */
6943 aggregate->count = 0;
6944 aggregate->incomplete_origin_count = 0;
6945 aggregate->incomplete_origin_count = 0;
6946 aggregate->egp_origin_count = 0;
6947
d62a17ae 6948 /* ORIGIN attribute: If at least one route among routes that are
6949 aggregated has ORIGIN with the value INCOMPLETE, then the
6950 aggregated route must have the ORIGIN attribute with the value
6951 INCOMPLETE. Otherwise, if at least one route among routes that
6952 are aggregated has ORIGIN with the value EGP, then the aggregated
6953 route must have the origin attribute with the value EGP. In all
6954 other case the value of the ORIGIN attribute of the aggregated
6955 route is INTERNAL. */
6956 origin = BGP_ORIGIN_IGP;
718e3744 6957
d62a17ae 6958 table = bgp->rib[afi][safi];
718e3744 6959
d62a17ae 6960 top = bgp_node_get(table, p);
9bcb3eef
DS
6961 for (dest = bgp_node_get(table, p); dest;
6962 dest = bgp_route_next_until(dest, top)) {
6963 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 6964
9bcb3eef 6965 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 6966 continue;
d62a17ae 6967
a77e2f4b
S
6968 /* If suppress fib is enabled and route not installed
6969 * in FIB, skip the route
6970 */
6971 if (!bgp_check_advertise(bgp, dest))
6972 continue;
6973
c2ff8b3e 6974 match = 0;
d62a17ae 6975
9bcb3eef 6976 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 6977 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 6978 continue;
718e3744 6979
40381db7 6980 if (pi->attr->flag
c2ff8b3e
DS
6981 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
6982 atomic_aggregate = 1;
d62a17ae 6983
40381db7 6984 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 6985 continue;
d62a17ae 6986
f273fef1
DS
6987 /*
6988 * summary-only aggregate route suppress
6989 * aggregated route announcements.
6aabb15d
RZ
6990 *
6991 * MED matching:
6992 * Don't create summaries if MED didn't match
6993 * otherwise neither the specific routes and the
6994 * aggregation will be announced.
f273fef1 6995 */
6aabb15d
RZ
6996 if (aggregate->summary_only
6997 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
6998 if (aggr_suppress_path(aggregate, pi))
6999 match++;
d62a17ae 7000 }
c2ff8b3e 7001
365ab2e7
RZ
7002 /*
7003 * Suppress more specific routes that match the route
7004 * map results.
7005 *
7006 * MED matching:
7007 * Don't suppress routes if MED matching is enabled and
7008 * it mismatched otherwise we might end up with no
7009 * routes for this path.
7010 */
7011 if (aggregate->suppress_map_name
7012 && AGGREGATE_MED_VALID(aggregate)
7013 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7014 if (aggr_suppress_path(aggregate, pi))
7015 match++;
d62a17ae 7016 }
c2ff8b3e
DS
7017
7018 aggregate->count++;
7019
f273fef1
DS
7020 /*
7021 * If at least one route among routes that are
7022 * aggregated has ORIGIN with the value INCOMPLETE,
7023 * then the aggregated route MUST have the ORIGIN
7024 * attribute with the value INCOMPLETE. Otherwise, if
7025 * at least one route among routes that are aggregated
7026 * has ORIGIN with the value EGP, then the aggregated
7027 * route MUST have the ORIGIN attribute with the value
7028 * EGP.
7029 */
fc968841
NT
7030 switch (pi->attr->origin) {
7031 case BGP_ORIGIN_INCOMPLETE:
7032 aggregate->incomplete_origin_count++;
7033 break;
7034 case BGP_ORIGIN_EGP:
7035 aggregate->egp_origin_count++;
7036 break;
7037 default:
7038 /*Do nothing.
7039 */
7040 break;
7041 }
c2ff8b3e
DS
7042
7043 if (!aggregate->as_set)
7044 continue;
7045
f273fef1
DS
7046 /*
7047 * as-set aggregate route generate origin, as path,
7048 * and community aggregation.
7049 */
fc968841
NT
7050 /* Compute aggregate route's as-path.
7051 */
ef51a7d8 7052 bgp_compute_aggregate_aspath_hash(aggregate,
7053 pi->attr->aspath);
c2ff8b3e 7054
fc968841
NT
7055 /* Compute aggregate route's community.
7056 */
7057 if (pi->attr->community)
21fec674 7058 bgp_compute_aggregate_community_hash(
fc968841
NT
7059 aggregate,
7060 pi->attr->community);
dd18c5a9 7061
fc968841
NT
7062 /* Compute aggregate route's extended community.
7063 */
7064 if (pi->attr->ecommunity)
4edd83f9 7065 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7066 aggregate,
7067 pi->attr->ecommunity);
7068
7069 /* Compute aggregate route's large community.
7070 */
7071 if (pi->attr->lcommunity)
f1eb1f05 7072 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7073 aggregate,
7074 pi->attr->lcommunity);
d62a17ae 7075 }
c2ff8b3e 7076 if (match)
9bcb3eef 7077 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7078 }
21fec674 7079 if (aggregate->as_set) {
ef51a7d8 7080 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7081 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7082 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7083 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7084 }
7085
f1eb1f05 7086
9bcb3eef 7087 bgp_dest_unlock_node(top);
718e3744 7088
718e3744 7089
fc968841
NT
7090 if (aggregate->incomplete_origin_count > 0)
7091 origin = BGP_ORIGIN_INCOMPLETE;
7092 else if (aggregate->egp_origin_count > 0)
7093 origin = BGP_ORIGIN_EGP;
d62a17ae 7094
229757f1
DA
7095 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7096 origin = aggregate->origin;
7097
fc968841
NT
7098 if (aggregate->as_set) {
7099 if (aggregate->aspath)
7100 /* Retrieve aggregate route's as-path.
7101 */
7102 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7103
fc968841
NT
7104 if (aggregate->community)
7105 /* Retrieve aggregate route's community.
7106 */
7107 community = community_dup(aggregate->community);
3da2cc32 7108
fc968841
NT
7109 if (aggregate->ecommunity)
7110 /* Retrieve aggregate route's ecommunity.
7111 */
7112 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7113
fc968841
NT
7114 if (aggregate->lcommunity)
7115 /* Retrieve aggregate route's lcommunity.
7116 */
7117 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7118 }
718e3744 7119
c701010e 7120 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7121 ecommunity, lcommunity, atomic_aggregate,
7122 aggregate);
718e3744 7123}
7124
5f040085
DS
7125void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7126 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7127{
7128 struct bgp_table *table;
9bcb3eef
DS
7129 struct bgp_dest *top;
7130 struct bgp_dest *dest;
40381db7 7131 struct bgp_path_info *pi;
3b7db173
DS
7132 unsigned long match;
7133
7134 table = bgp->rib[afi][safi];
7135
7136 /* If routes exists below this node, generate aggregate routes. */
7137 top = bgp_node_get(table, p);
9bcb3eef
DS
7138 for (dest = bgp_node_get(table, p); dest;
7139 dest = bgp_route_next_until(dest, top)) {
7140 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7141
9bcb3eef 7142 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7143 continue;
7144 match = 0;
7145
9bcb3eef 7146 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7147 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7148 continue;
7149
40381db7 7150 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7151 continue;
7152
6aabb15d
RZ
7153 if (aggregate->summary_only && pi->extra
7154 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7155 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7156 match++;
3b7db173 7157 }
3b7db173 7158
365ab2e7
RZ
7159 if (aggregate->suppress_map_name
7160 && AGGREGATE_MED_VALID(aggregate)
7161 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7162 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7163 match++;
3b7db173 7164 }
365ab2e7 7165
3b7db173 7166 aggregate->count--;
fc968841
NT
7167
7168 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7169 aggregate->incomplete_origin_count--;
7170 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7171 aggregate->egp_origin_count--;
7172
7173 if (aggregate->as_set) {
7174 /* Remove as-path from aggregate.
7175 */
ef51a7d8 7176 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7177 aggregate,
7178 pi->attr->aspath);
7179
7180 if (pi->attr->community)
7181 /* Remove community from aggregate.
7182 */
21fec674 7183 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7184 aggregate,
7185 pi->attr->community);
7186
7187 if (pi->attr->ecommunity)
7188 /* Remove ecommunity from aggregate.
7189 */
4edd83f9 7190 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7191 aggregate,
7192 pi->attr->ecommunity);
7193
7194 if (pi->attr->lcommunity)
7195 /* Remove lcommunity from aggregate.
7196 */
f1eb1f05 7197 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7198 aggregate,
7199 pi->attr->lcommunity);
7200 }
3b7db173
DS
7201 }
7202
7203 /* If this node was suppressed, process the change. */
7204 if (match)
9bcb3eef 7205 bgp_process(bgp, dest, afi, safi);
3b7db173 7206 }
f1eb1f05 7207 if (aggregate->as_set) {
ef51a7d8 7208 aspath_free(aggregate->aspath);
7209 aggregate->aspath = NULL;
21fec674 7210 if (aggregate->community)
7211 community_free(&aggregate->community);
4edd83f9 7212 if (aggregate->ecommunity)
7213 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7214 if (aggregate->lcommunity)
7215 lcommunity_free(&aggregate->lcommunity);
7216 }
7217
9bcb3eef 7218 bgp_dest_unlock_node(top);
3b7db173 7219}
718e3744 7220
5f040085
DS
7221static void bgp_add_route_to_aggregate(struct bgp *bgp,
7222 const struct prefix *aggr_p,
fc968841
NT
7223 struct bgp_path_info *pinew, afi_t afi,
7224 safi_t safi,
7225 struct bgp_aggregate *aggregate)
7226{
7227 uint8_t origin;
7228 struct aspath *aspath = NULL;
7229 uint8_t atomic_aggregate = 0;
7230 struct community *community = NULL;
7231 struct ecommunity *ecommunity = NULL;
7232 struct lcommunity *lcommunity = NULL;
7233
a4559740 7234 /* If the bgp instance is being deleted or self peer is deleted
7235 * then do not create aggregate route
7236 */
7237 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7238 || (bgp->peer_self == NULL))
7239 return;
7240
fc968841
NT
7241 /* ORIGIN attribute: If at least one route among routes that are
7242 * aggregated has ORIGIN with the value INCOMPLETE, then the
7243 * aggregated route must have the ORIGIN attribute with the value
7244 * INCOMPLETE. Otherwise, if at least one route among routes that
7245 * are aggregated has ORIGIN with the value EGP, then the aggregated
7246 * route must have the origin attribute with the value EGP. In all
7247 * other case the value of the ORIGIN attribute of the aggregated
7248 * route is INTERNAL.
7249 */
7250 origin = BGP_ORIGIN_IGP;
7251
7252 aggregate->count++;
7253
6aabb15d
RZ
7254 /*
7255 * This must be called before `summary` check to avoid
7256 * "suppressing" twice.
7257 */
7258 if (aggregate->match_med)
7259 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7260 pinew, true);
7261
7262 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7263 aggr_suppress_path(aggregate, pinew);
fc968841 7264
365ab2e7
RZ
7265 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7266 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7267 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7268
7269 switch (pinew->attr->origin) {
7270 case BGP_ORIGIN_INCOMPLETE:
7271 aggregate->incomplete_origin_count++;
7272 break;
7273 case BGP_ORIGIN_EGP:
7274 aggregate->egp_origin_count++;
7275 break;
7276 default:
7277 /* Do nothing.
7278 */
7279 break;
7280 }
7281
7282 if (aggregate->incomplete_origin_count > 0)
7283 origin = BGP_ORIGIN_INCOMPLETE;
7284 else if (aggregate->egp_origin_count > 0)
7285 origin = BGP_ORIGIN_EGP;
7286
229757f1
DA
7287 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7288 origin = aggregate->origin;
7289
fc968841
NT
7290 if (aggregate->as_set) {
7291 /* Compute aggregate route's as-path.
7292 */
7293 bgp_compute_aggregate_aspath(aggregate,
7294 pinew->attr->aspath);
7295
7296 /* Compute aggregate route's community.
7297 */
7298 if (pinew->attr->community)
7299 bgp_compute_aggregate_community(
7300 aggregate,
7301 pinew->attr->community);
7302
7303 /* Compute aggregate route's extended community.
7304 */
7305 if (pinew->attr->ecommunity)
7306 bgp_compute_aggregate_ecommunity(
7307 aggregate,
7308 pinew->attr->ecommunity);
7309
7310 /* Compute aggregate route's large community.
7311 */
7312 if (pinew->attr->lcommunity)
7313 bgp_compute_aggregate_lcommunity(
7314 aggregate,
7315 pinew->attr->lcommunity);
7316
7317 /* Retrieve aggregate route's as-path.
7318 */
7319 if (aggregate->aspath)
7320 aspath = aspath_dup(aggregate->aspath);
7321
7322 /* Retrieve aggregate route's community.
7323 */
7324 if (aggregate->community)
7325 community = community_dup(aggregate->community);
7326
7327 /* Retrieve aggregate route's ecommunity.
7328 */
7329 if (aggregate->ecommunity)
7330 ecommunity = ecommunity_dup(aggregate->ecommunity);
7331
7332 /* Retrieve aggregate route's lcommunity.
7333 */
7334 if (aggregate->lcommunity)
7335 lcommunity = lcommunity_dup(aggregate->lcommunity);
7336 }
7337
7338 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7339 aspath, community, ecommunity,
7340 lcommunity, atomic_aggregate, aggregate);
7341}
7342
7343static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7344 safi_t safi,
7345 struct bgp_path_info *pi,
7346 struct bgp_aggregate *aggregate,
5f040085 7347 const struct prefix *aggr_p)
fc968841
NT
7348{
7349 uint8_t origin;
7350 struct aspath *aspath = NULL;
7351 uint8_t atomic_aggregate = 0;
7352 struct community *community = NULL;
7353 struct ecommunity *ecommunity = NULL;
7354 struct lcommunity *lcommunity = NULL;
7355 unsigned long match = 0;
7356
a4559740 7357 /* If the bgp instance is being deleted or self peer is deleted
7358 * then do not create aggregate route
7359 */
7360 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7361 || (bgp->peer_self == NULL))
7362 return;
7363
fc968841
NT
7364 if (BGP_PATH_HOLDDOWN(pi))
7365 return;
7366
7367 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7368 return;
7369
4056a5f6
RZ
7370 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7371 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7372 match++;
fc968841 7373
365ab2e7 7374 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7375 && aggr_suppress_map_test(bgp, aggregate, pi))
7376 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7377 match++;
fc968841 7378
6aabb15d 7379 /*
365ab2e7 7380 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7381 * "unsuppressing" twice.
7382 */
7383 if (aggregate->match_med)
7384 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7385 true);
7386
fc968841
NT
7387 if (aggregate->count > 0)
7388 aggregate->count--;
7389
7390 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7391 aggregate->incomplete_origin_count--;
7392 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7393 aggregate->egp_origin_count--;
7394
7395 if (aggregate->as_set) {
7396 /* Remove as-path from aggregate.
7397 */
7398 bgp_remove_aspath_from_aggregate(aggregate,
7399 pi->attr->aspath);
7400
7401 if (pi->attr->community)
7402 /* Remove community from aggregate.
7403 */
7404 bgp_remove_community_from_aggregate(
7405 aggregate,
7406 pi->attr->community);
7407
7408 if (pi->attr->ecommunity)
7409 /* Remove ecommunity from aggregate.
7410 */
7411 bgp_remove_ecommunity_from_aggregate(
7412 aggregate,
7413 pi->attr->ecommunity);
7414
7415 if (pi->attr->lcommunity)
7416 /* Remove lcommunity from aggregate.
7417 */
7418 bgp_remove_lcommunity_from_aggregate(
7419 aggregate,
7420 pi->attr->lcommunity);
7421 }
7422
7423 /* If this node was suppressed, process the change. */
7424 if (match)
7425 bgp_process(bgp, pi->net, afi, safi);
7426
7427 origin = BGP_ORIGIN_IGP;
7428 if (aggregate->incomplete_origin_count > 0)
7429 origin = BGP_ORIGIN_INCOMPLETE;
7430 else if (aggregate->egp_origin_count > 0)
7431 origin = BGP_ORIGIN_EGP;
7432
229757f1
DA
7433 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7434 origin = aggregate->origin;
7435
fc968841
NT
7436 if (aggregate->as_set) {
7437 /* Retrieve aggregate route's as-path.
7438 */
7439 if (aggregate->aspath)
7440 aspath = aspath_dup(aggregate->aspath);
7441
7442 /* Retrieve aggregate route's community.
7443 */
7444 if (aggregate->community)
7445 community = community_dup(aggregate->community);
7446
7447 /* Retrieve aggregate route's ecommunity.
7448 */
7449 if (aggregate->ecommunity)
7450 ecommunity = ecommunity_dup(aggregate->ecommunity);
7451
7452 /* Retrieve aggregate route's lcommunity.
7453 */
7454 if (aggregate->lcommunity)
7455 lcommunity = lcommunity_dup(aggregate->lcommunity);
7456 }
7457
7458 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7459 aspath, community, ecommunity,
7460 lcommunity, atomic_aggregate, aggregate);
7461}
7462
5a1ae2c2 7463void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7464 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7465{
9bcb3eef
DS
7466 struct bgp_dest *child;
7467 struct bgp_dest *dest;
d62a17ae 7468 struct bgp_aggregate *aggregate;
7469 struct bgp_table *table;
718e3744 7470
d62a17ae 7471 table = bgp->aggregate[afi][safi];
f018db83 7472
d62a17ae 7473 /* No aggregates configured. */
7474 if (bgp_table_top_nolock(table) == NULL)
7475 return;
f018db83 7476
d62a17ae 7477 if (p->prefixlen == 0)
7478 return;
718e3744 7479
40381db7 7480 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7481 return;
718e3744 7482
a77e2f4b
S
7483 /* If suppress fib is enabled and route not installed
7484 * in FIB, do not update the aggregate route
7485 */
7486 if (!bgp_check_advertise(bgp, pi->net))
7487 return;
7488
d62a17ae 7489 child = bgp_node_get(table, p);
718e3744 7490
d62a17ae 7491 /* Aggregate address configuration check. */
9bcb3eef
DS
7492 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7493 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7494
9bcb3eef
DS
7495 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7496 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7497 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7498 aggregate);
d62a17ae 7499 }
b1e62edd 7500 }
9bcb3eef 7501 bgp_dest_unlock_node(child);
718e3744 7502}
7503
5a1ae2c2 7504void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7505 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7506{
9bcb3eef
DS
7507 struct bgp_dest *child;
7508 struct bgp_dest *dest;
d62a17ae 7509 struct bgp_aggregate *aggregate;
7510 struct bgp_table *table;
718e3744 7511
d62a17ae 7512 table = bgp->aggregate[afi][safi];
718e3744 7513
d62a17ae 7514 /* No aggregates configured. */
7515 if (bgp_table_top_nolock(table) == NULL)
7516 return;
718e3744 7517
d62a17ae 7518 if (p->prefixlen == 0)
7519 return;
718e3744 7520
d62a17ae 7521 child = bgp_node_get(table, p);
718e3744 7522
d62a17ae 7523 /* Aggregate address configuration check. */
9bcb3eef
DS
7524 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7525 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7526
9bcb3eef
DS
7527 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7528 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7529 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7530 aggregate, dest_p);
d62a17ae 7531 }
b1e62edd 7532 }
9bcb3eef 7533 bgp_dest_unlock_node(child);
d62a17ae 7534}
718e3744 7535
718e3744 7536/* Aggregate route attribute. */
7537#define AGGREGATE_SUMMARY_ONLY 1
7538#define AGGREGATE_AS_SET 1
fb29348a 7539#define AGGREGATE_AS_UNSET 0
718e3744 7540
229757f1
DA
7541static const char *bgp_origin2str(uint8_t origin)
7542{
7543 switch (origin) {
7544 case BGP_ORIGIN_IGP:
7545 return "igp";
7546 case BGP_ORIGIN_EGP:
7547 return "egp";
7548 case BGP_ORIGIN_INCOMPLETE:
7549 return "incomplete";
7550 }
7551 return "n/a";
7552}
7553
b5b99af8
DS
7554static const char *bgp_rpki_validation2str(int v_state)
7555{
7556 switch (v_state) {
7557 case 1:
7558 return "valid";
7559 case 2:
7560 return "not found";
7561 case 3:
7562 return "invalid";
7563 default:
7564 break;
7565 }
7566 return "ERROR";
7567}
7568
37a87b8f
CS
7569int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7570 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7571{
9bcb3eef 7572 struct bgp_dest *dest;
d62a17ae 7573 struct bgp_aggregate *aggregate;
718e3744 7574
a4559740 7575 /* If the bgp instance is being deleted or self peer is deleted
7576 * then do not create aggregate route
7577 */
7578 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7579 || (bgp->peer_self == NULL))
7580 return 0;
7581
37a87b8f 7582 apply_mask(prefix);
d62a17ae 7583 /* Old configuration check. */
37a87b8f 7584 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7585 if (!dest) {
37a87b8f
CS
7586 snprintf(errmsg, errmsg_len,
7587 "There is no aggregate-address configuration.\n");
7588 return -1;
d62a17ae 7589 }
f6269b4f 7590
9bcb3eef 7591 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7592 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7593 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7594 0, aggregate);
d62a17ae 7595
7596 /* Unlock aggregate address configuration. */
9bcb3eef 7597 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7598
7599 if (aggregate->community)
7600 community_free(&aggregate->community);
7601
7602 if (aggregate->community_hash) {
7603 /* Delete all communities in the hash.
7604 */
7605 hash_clean(aggregate->community_hash,
7606 bgp_aggr_community_remove);
7607 /* Free up the community_hash.
7608 */
7609 hash_free(aggregate->community_hash);
7610 }
7611
7612 if (aggregate->ecommunity)
7613 ecommunity_free(&aggregate->ecommunity);
7614
7615 if (aggregate->ecommunity_hash) {
7616 /* Delete all ecommunities in the hash.
7617 */
7618 hash_clean(aggregate->ecommunity_hash,
7619 bgp_aggr_ecommunity_remove);
7620 /* Free up the ecommunity_hash.
7621 */
7622 hash_free(aggregate->ecommunity_hash);
7623 }
7624
7625 if (aggregate->lcommunity)
7626 lcommunity_free(&aggregate->lcommunity);
7627
7628 if (aggregate->lcommunity_hash) {
7629 /* Delete all lcommunities in the hash.
7630 */
7631 hash_clean(aggregate->lcommunity_hash,
7632 bgp_aggr_lcommunity_remove);
7633 /* Free up the lcommunity_hash.
7634 */
7635 hash_free(aggregate->lcommunity_hash);
7636 }
7637
7638 if (aggregate->aspath)
7639 aspath_free(aggregate->aspath);
7640
7641 if (aggregate->aspath_hash) {
7642 /* Delete all as-paths in the hash.
7643 */
7644 hash_clean(aggregate->aspath_hash,
7645 bgp_aggr_aspath_remove);
7646 /* Free up the aspath_hash.
7647 */
7648 hash_free(aggregate->aspath_hash);
7649 }
7650
d62a17ae 7651 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7652 bgp_dest_unlock_node(dest);
7653 bgp_dest_unlock_node(dest);
d62a17ae 7654
37a87b8f 7655 return 0;
d62a17ae 7656}
7657
37a87b8f
CS
7658int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7659 safi_t safi, const char *rmap, uint8_t summary_only,
7660 uint8_t as_set, uint8_t origin, bool match_med,
7661 const char *suppress_map,
7662 char *errmsg, size_t errmsg_len)
d62a17ae 7663{
d62a17ae 7664 int ret;
9bcb3eef 7665 struct bgp_dest *dest;
d62a17ae 7666 struct bgp_aggregate *aggregate;
fb29348a 7667 uint8_t as_set_new = as_set;
37a87b8f 7668 char buf[PREFIX2STR_BUFFER];
d62a17ae 7669
365ab2e7 7670 if (suppress_map && summary_only) {
37a87b8f 7671 snprintf(errmsg, errmsg_len,
365ab2e7 7672 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7673 return -1;
365ab2e7
RZ
7674 }
7675
37a87b8f 7676 apply_mask(prefix);
d62a17ae 7677
37a87b8f
CS
7678 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7679 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7680 snprintf(
7681 errmsg, errmsg_len,
7682 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7683 prefix2str(prefix, buf, PREFIX_STRLEN));
7684 return -1;
3624ac81
DS
7685 }
7686
d62a17ae 7687 /* Old configuration check. */
37a87b8f 7688 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7689 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7690
20894f50 7691 if (aggregate) {
37a87b8f
CS
7692 snprintf(errmsg, errmsg_len,
7693 "There is already same aggregate network.\n");
d62a17ae 7694 /* try to remove the old entry */
37a87b8f
CS
7695 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7696 errmsg_len);
d62a17ae 7697 if (ret) {
37a87b8f
CS
7698 snprintf(errmsg, errmsg_len,
7699 "Error deleting aggregate.\n");
9bcb3eef 7700 bgp_dest_unlock_node(dest);
37a87b8f 7701 return -1;
d62a17ae 7702 }
7703 }
718e3744 7704
d62a17ae 7705 /* Make aggregate address structure. */
7706 aggregate = bgp_aggregate_new();
7707 aggregate->summary_only = summary_only;
6aabb15d 7708 aggregate->match_med = match_med;
fb29348a
DA
7709
7710 /* Network operators MUST NOT locally generate any new
7711 * announcements containing AS_SET or AS_CONFED_SET. If they have
7712 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7713 * SHOULD withdraw those routes and re-announce routes for the
7714 * aggregate or component prefixes (i.e., the more-specific routes
7715 * subsumed by the previously aggregated route) without AS_SET
7716 * or AS_CONFED_SET in the updates.
7717 */
7f972cd8 7718 if (bgp->reject_as_sets) {
fb29348a
DA
7719 if (as_set == AGGREGATE_AS_SET) {
7720 as_set_new = AGGREGATE_AS_UNSET;
7721 zlog_warn(
63efca0e 7722 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7723 __func__);
37a87b8f
CS
7724 snprintf(
7725 errmsg, errmsg_len,
fb29348a
DA
7726 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7727 }
7728 }
7729
7730 aggregate->as_set = as_set_new;
d62a17ae 7731 aggregate->safi = safi;
229757f1
DA
7732 /* Override ORIGIN attribute if defined.
7733 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7734 * to IGP which is not what rfc4271 says.
7735 * This enables the same behavior, optionally.
7736 */
7737 aggregate->origin = origin;
20894f50
DA
7738
7739 if (rmap) {
7740 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7741 route_map_counter_decrement(aggregate->rmap.map);
7742 aggregate->rmap.name =
7743 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7744 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7745 route_map_counter_increment(aggregate->rmap.map);
7746 }
365ab2e7
RZ
7747
7748 if (suppress_map) {
7749 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
7750 route_map_counter_decrement(aggregate->suppress_map);
7751
7752 aggregate->suppress_map_name =
7753 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
7754 aggregate->suppress_map =
7755 route_map_lookup_by_name(aggregate->suppress_map_name);
7756 route_map_counter_increment(aggregate->suppress_map);
7757 }
7758
9bcb3eef 7759 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 7760
d62a17ae 7761 /* Aggregate address insert into BGP routing table. */
37a87b8f 7762 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 7763
37a87b8f 7764 return 0;
718e3744 7765}
7766
37a87b8f
CS
7767DEFPY_YANG(
7768 aggregate_addressv4, aggregate_addressv4_cmd,
7769 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> {"
7770 "as-set$as_set_s"
7771 "|summary-only$summary_only"
7772 "|route-map WORD$rmap_name"
7773 "|origin <egp|igp|incomplete>$origin_s"
7774 "|matching-MED-only$match_med"
90e21f35 7775 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7776 "}",
7777 NO_STR
7778 "Configure BGP aggregate entries\n"
7779 "Aggregate prefix\n"
7780 "Aggregate address\n"
7781 "Aggregate mask\n"
7782 "Generate AS set path information\n"
7783 "Filter more specific routes from updates\n"
7784 "Apply route map to aggregate network\n"
7785 "Route map name\n"
7786 "BGP origin code\n"
7787 "Remote EGP\n"
7788 "Local IGP\n"
7789 "Unknown heritage\n"
7790 "Only aggregate routes with matching MED\n"
90e21f35
CS
7791 "Suppress the selected more specific routes\n"
7792 "Route map with the route selectors\n")
37a87b8f
CS
7793{
7794 char base_xpath[XPATH_MAXLEN];
554b3b10 7795 safi_t safi = bgp_node_safi(vty);
554b3b10 7796 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 7797
554b3b10 7798 if (addr_str) {
7533cad7
QY
7799 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
7800 sizeof(prefix_buf))
554b3b10
RZ
7801 == 0) {
7802 vty_out(vty, "%% Inconsistent address and mask\n");
7803 return CMD_WARNING_CONFIG_FAILED;
7804 }
37a87b8f
CS
7805 } else {
7806 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
7807 }
7808
37a87b8f
CS
7809 if (!no && origin_s)
7810 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7811
7812 if (!no && as_set_s)
7813 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7814 else
7815 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7816
7817 if (!no && summary_only)
7818 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7819 "true");
7820 else
7821 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7822 "false");
7823
fa423774
CS
7824 if (!no && match_med)
7825 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7826 else
7827 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7828 "false");
7829
37a87b8f
CS
7830 if (rmap_name)
7831 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7832 rmap_name);
7833 else
7834 nb_cli_enqueue_change(vty, "./rmap-policy-export",
7835 NB_OP_DESTROY, NULL);
7836
90e21f35
CS
7837 if (suppress_map)
7838 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7839 suppress_map);
7840 else
7841 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7842 NULL);
7843
37a87b8f
CS
7844 snprintf(
7845 base_xpath, sizeof(base_xpath),
7846 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7847 yang_afi_safi_value2identity(AFI_IP, safi),
7848 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 7849
554b3b10 7850 if (no)
37a87b8f
CS
7851 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7852 else
7853 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
7854
7855 return nb_cli_apply_changes(vty, base_xpath);
7856}
7857
7858DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
7859 "[no] aggregate-address X:X::X:X/M$prefix {"
7860 "as-set$as_set_s"
7861 "|summary-only$summary_only"
7862 "|route-map WORD$rmap_name"
7863 "|origin <egp|igp|incomplete>$origin_s"
7864 "|matching-MED-only$match_med"
90e21f35 7865 "|suppress-map WORD$suppress_map"
37a87b8f
CS
7866 "}",
7867 NO_STR
7868 "Configure BGP aggregate entries\n"
7869 "Aggregate prefix\n"
7870 "Generate AS set path information\n"
7871 "Filter more specific routes from updates\n"
7872 "Apply route map to aggregate network\n"
7873 "Route map name\n"
7874 "BGP origin code\n"
7875 "Remote EGP\n"
7876 "Local IGP\n"
7877 "Unknown heritage\n"
7878 "Only aggregate routes with matching MED\n"
7879 "Suppress the selected more specific routes\n"
90e21f35 7880 "Route map with the route selectors\n")
37a87b8f
CS
7881{
7882 char base_xpath[XPATH_MAXLEN];
7883 safi_t safi = bgp_node_safi(vty);
7884
7885 if (!no && origin_s)
7886 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
7887
7888 if (!no && as_set_s)
7889 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
7890 else
7891 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
7892
7893 if (!no && summary_only)
7894 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7895 "true");
7896 else
7897 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
7898 "false");
7899
fa423774
CS
7900 if (!no && match_med)
7901 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
7902 else
7903 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
7904 "false");
7905
37a87b8f
CS
7906 if (rmap_name)
7907 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
7908 rmap_name);
7909
90e21f35
CS
7910 if (suppress_map)
7911 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
7912 suppress_map);
7913 else
7914 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
7915 NULL);
7916
37a87b8f
CS
7917 snprintf(
7918 base_xpath, sizeof(base_xpath),
7919 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
7920 yang_afi_safi_value2identity(AFI_IP6, safi),
7921 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
7922
554b3b10 7923 if (no)
37a87b8f
CS
7924 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
7925 else
7926 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 7927
37a87b8f
CS
7928 return nb_cli_apply_changes(vty, base_xpath);
7929}
7930
7931void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
7932 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
7933{
7934 uint8_t origin;
7935
7936 vty_out(vty, " aggregate-address %s",
7937 yang_dnode_get_string(dnode, "./prefix"));
7938
7939 if (yang_dnode_get_bool(dnode, "./as-set"))
7940 vty_out(vty, " as-set");
7941
7942 if (yang_dnode_get_bool(dnode, "./summary-only"))
7943 vty_out(vty, " summary-only");
7944
7945 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
7946 vty_out(vty, " route-map %s",
7947 yang_dnode_get_string(dnode, "./rmap-policy-export"));
7948
7949 origin = yang_dnode_get_enum(dnode, "./origin");
7950 if (origin != BGP_ORIGIN_UNSPECIFIED)
7951 vty_out(vty, " origin %s", bgp_origin2str(origin));
7952
fa423774
CS
7953 if (yang_dnode_get_bool(dnode, "./match-med"))
7954 vty_out(vty, " matching-MED-only");
7955
37a87b8f 7956 vty_out(vty, "\n");
718e3744 7957}
7958
718e3744 7959/* Redistribute route treatment. */
d62a17ae 7960void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
7961 const union g_addr *nexthop, ifindex_t ifindex,
7962 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
7963 uint8_t type, unsigned short instance,
7964 route_tag_t tag)
d62a17ae 7965{
4b7e6066 7966 struct bgp_path_info *new;
40381db7
DS
7967 struct bgp_path_info *bpi;
7968 struct bgp_path_info rmap_path;
9bcb3eef 7969 struct bgp_dest *bn;
d62a17ae 7970 struct attr attr;
7971 struct attr *new_attr;
7972 afi_t afi;
b68885f9 7973 route_map_result_t ret;
d62a17ae 7974 struct bgp_redist *red;
7975
7976 /* Make default attribute. */
7977 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
7978 /*
7979 * This must not be NULL to satisfy Coverity SA
7980 */
7981 assert(attr.aspath);
9de1f7ff 7982
a4d82a8a 7983 switch (nhtype) {
9de1f7ff
DS
7984 case NEXTHOP_TYPE_IFINDEX:
7985 break;
7986 case NEXTHOP_TYPE_IPV4:
7987 case NEXTHOP_TYPE_IPV4_IFINDEX:
7988 attr.nexthop = nexthop->ipv4;
7989 break;
7990 case NEXTHOP_TYPE_IPV6:
7991 case NEXTHOP_TYPE_IPV6_IFINDEX:
7992 attr.mp_nexthop_global = nexthop->ipv6;
7993 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
7994 break;
7995 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
7996 switch (p->family) {
7997 case AF_INET:
9de1f7ff 7998 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
7999 break;
8000 case AF_INET6:
9de1f7ff
DS
8001 memset(&attr.mp_nexthop_global, 0,
8002 sizeof(attr.mp_nexthop_global));
74489921 8003 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8004 break;
74489921 8005 }
9de1f7ff 8006 break;
d62a17ae 8007 }
74489921 8008 attr.nh_ifindex = ifindex;
f04a80a5 8009
d62a17ae 8010 attr.med = metric;
8011 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8012 attr.tag = tag;
718e3744 8013
d62a17ae 8014 afi = family2afi(p->family);
6aeb9e78 8015
d62a17ae 8016 red = bgp_redist_lookup(bgp, afi, type, instance);
8017 if (red) {
8018 struct attr attr_new;
718e3744 8019
d62a17ae 8020 /* Copy attribute for modification. */
6f4f49b2 8021 attr_new = attr;
718e3744 8022
d62a17ae 8023 if (red->redist_metric_flag)
8024 attr_new.med = red->redist_metric;
718e3744 8025
d62a17ae 8026 /* Apply route-map. */
8027 if (red->rmap.name) {
40381db7
DS
8028 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8029 rmap_path.peer = bgp->peer_self;
8030 rmap_path.attr = &attr_new;
718e3744 8031
d62a17ae 8032 SET_FLAG(bgp->peer_self->rmap_type,
8033 PEER_RMAP_TYPE_REDISTRIBUTE);
8034
1782514f 8035 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8036
8037 bgp->peer_self->rmap_type = 0;
8038
8039 if (ret == RMAP_DENYMATCH) {
8040 /* Free uninterned attribute. */
8041 bgp_attr_flush(&attr_new);
8042
8043 /* Unintern original. */
8044 aspath_unintern(&attr.aspath);
8045 bgp_redistribute_delete(bgp, p, type, instance);
8046 return;
8047 }
8048 }
8049
637e5ba4 8050 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8051 bgp_attr_add_gshut_community(&attr_new);
8052
d62a17ae 8053 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8054 SAFI_UNICAST, p, NULL);
8055
8056 new_attr = bgp_attr_intern(&attr_new);
8057
9bcb3eef 8058 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8059 if (bpi->peer == bgp->peer_self
8060 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8061 break;
8062
40381db7 8063 if (bpi) {
d62a17ae 8064 /* Ensure the (source route) type is updated. */
40381db7
DS
8065 bpi->type = type;
8066 if (attrhash_cmp(bpi->attr, new_attr)
8067 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8068 bgp_attr_unintern(&new_attr);
8069 aspath_unintern(&attr.aspath);
9bcb3eef 8070 bgp_dest_unlock_node(bn);
d62a17ae 8071 return;
8072 } else {
8073 /* The attribute is changed. */
40381db7 8074 bgp_path_info_set_flag(bn, bpi,
18ee8310 8075 BGP_PATH_ATTR_CHANGED);
d62a17ae 8076
8077 /* Rewrite BGP route information. */
40381db7
DS
8078 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8079 bgp_path_info_restore(bn, bpi);
d62a17ae 8080 else
40381db7
DS
8081 bgp_aggregate_decrement(
8082 bgp, p, bpi, afi, SAFI_UNICAST);
8083 bgp_attr_unintern(&bpi->attr);
8084 bpi->attr = new_attr;
8085 bpi->uptime = bgp_clock();
d62a17ae 8086
8087 /* Process change. */
40381db7 8088 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8089 SAFI_UNICAST);
8090 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8091 bgp_dest_unlock_node(bn);
d62a17ae 8092 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8093
8094 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8095 || (bgp->inst_type
8096 == BGP_INSTANCE_TYPE_DEFAULT)) {
8097
8098 vpn_leak_from_vrf_update(
40381db7 8099 bgp_get_default(), bgp, bpi);
ddb5b488 8100 }
d62a17ae 8101 return;
8102 }
8103 }
8104
8105 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8106 bgp->peer_self, new_attr, bn);
1defdda8 8107 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8108
8109 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8110 bgp_path_info_add(bn, new);
9bcb3eef 8111 bgp_dest_unlock_node(bn);
d62a17ae 8112 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8113
8114 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8115 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8116
8117 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8118 }
d62a17ae 8119 }
8120
8121 /* Unintern original. */
8122 aspath_unintern(&attr.aspath);
718e3744 8123}
8124
d7c0a89a
QY
8125void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8126 unsigned short instance)
718e3744 8127{
d62a17ae 8128 afi_t afi;
9bcb3eef 8129 struct bgp_dest *dest;
40381db7 8130 struct bgp_path_info *pi;
d62a17ae 8131 struct bgp_redist *red;
718e3744 8132
d62a17ae 8133 afi = family2afi(p->family);
718e3744 8134
d62a17ae 8135 red = bgp_redist_lookup(bgp, afi, type, instance);
8136 if (red) {
9bcb3eef
DS
8137 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8138 SAFI_UNICAST, p, NULL);
d62a17ae 8139
9bcb3eef 8140 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8141 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8142 break;
8143
40381db7 8144 if (pi) {
ddb5b488
PZ
8145 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8146 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8147
8148 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8149 bgp, pi);
ddb5b488 8150 }
40381db7 8151 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8152 bgp_path_info_delete(dest, pi);
8153 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8154 }
9bcb3eef 8155 bgp_dest_unlock_node(dest);
d62a17ae 8156 }
8157}
8158
8159/* Withdraw specified route type's route. */
8160void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8161 unsigned short instance)
d62a17ae 8162{
9bcb3eef 8163 struct bgp_dest *dest;
40381db7 8164 struct bgp_path_info *pi;
d62a17ae 8165 struct bgp_table *table;
8166
8167 table = bgp->rib[afi][SAFI_UNICAST];
8168
9bcb3eef
DS
8169 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8170 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8171 if (pi->peer == bgp->peer_self && pi->type == type
8172 && pi->instance == instance)
d62a17ae 8173 break;
8174
40381db7 8175 if (pi) {
ddb5b488
PZ
8176 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8177 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8178
8179 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8180 bgp, pi);
ddb5b488 8181 }
9bcb3eef 8182 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8183 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8184 bgp_path_info_delete(dest, pi);
8185 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8186 }
718e3744 8187 }
718e3744 8188}
6b0655a2 8189
718e3744 8190/* Static function to display route. */
bd494ec5 8191static void route_vty_out_route(const struct prefix *p, struct vty *vty,
ae248832 8192 json_object *json, bool wide)
718e3744 8193{
be054588 8194 int len = 0;
d62a17ae 8195 char buf[BUFSIZ];
50e05855 8196 char buf2[BUFSIZ];
718e3744 8197
d62a17ae 8198 if (p->family == AF_INET) {
c6462ff4 8199 if (!json) {
8228a9a7 8200 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8201 } else {
8202 json_object_string_add(json, "prefix",
8203 inet_ntop(p->family,
8204 &p->u.prefix, buf,
8205 BUFSIZ));
8206 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8207 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8208 json_object_string_add(json, "network", buf2);
c6462ff4 8209 }
d62a17ae 8210 } else if (p->family == AF_ETHERNET) {
8228a9a7 8211 len = vty_out(vty, "%pFX", p);
b03b8898 8212 } else if (p->family == AF_EVPN) {
57f7feb6 8213 if (!json)
2dbe669b 8214 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8215 else
60466a63 8216 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8217 } else if (p->family == AF_FLOWSPEC) {
8218 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8219 json ?
8220 NLRI_STRING_FORMAT_JSON_SIMPLE :
8221 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8222 } else {
c6462ff4 8223 if (!json)
8228a9a7 8224 len = vty_out(vty, "%pFX", p);
50e05855
AD
8225 else {
8226 json_object_string_add(json, "prefix",
8227 inet_ntop(p->family,
8228 &p->u.prefix, buf,
8229 BUFSIZ));
8230 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8231 prefix2str(p, buf2, PREFIX_STRLEN);
8232 json_object_string_add(json, "network", buf2);
8233 }
9c92b5f7 8234 }
d62a17ae 8235
9c92b5f7 8236 if (!json) {
ae248832 8237 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8238 if (len < 1)
8239 vty_out(vty, "\n%*s", 20, " ");
8240 else
8241 vty_out(vty, "%*s", len, " ");
8242 }
718e3744 8243}
8244
d62a17ae 8245enum bgp_display_type {
8246 normal_list,
718e3744 8247};
8248
bbb46eb5
DA
8249static const char *
8250bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8251{
8252 switch (reason) {
8253 case bgp_path_selection_none:
8254 return "Nothing to Select";
8255 case bgp_path_selection_first:
8256 return "First path received";
8257 case bgp_path_selection_evpn_sticky_mac:
8258 return "EVPN Sticky Mac";
8259 case bgp_path_selection_evpn_seq:
8260 return "EVPN sequence number";
8261 case bgp_path_selection_evpn_lower_ip:
8262 return "EVPN lower IP";
8263 case bgp_path_selection_evpn_local_path:
8264 return "EVPN local ES path";
8265 case bgp_path_selection_evpn_non_proxy:
8266 return "EVPN non proxy";
8267 case bgp_path_selection_weight:
8268 return "Weight";
8269 case bgp_path_selection_local_pref:
8270 return "Local Pref";
8271 case bgp_path_selection_local_route:
8272 return "Local Route";
8273 case bgp_path_selection_confed_as_path:
8274 return "Confederation based AS Path";
8275 case bgp_path_selection_as_path:
8276 return "AS Path";
8277 case bgp_path_selection_origin:
8278 return "Origin";
8279 case bgp_path_selection_med:
8280 return "MED";
8281 case bgp_path_selection_peer:
8282 return "Peer Type";
8283 case bgp_path_selection_confed:
8284 return "Confed Peer Type";
8285 case bgp_path_selection_igp_metric:
8286 return "IGP Metric";
8287 case bgp_path_selection_older:
8288 return "Older Path";
8289 case bgp_path_selection_router_id:
8290 return "Router ID";
8291 case bgp_path_selection_cluster_length:
bcab253c 8292 return "Cluster length";
bbb46eb5
DA
8293 case bgp_path_selection_stale:
8294 return "Path Staleness";
8295 case bgp_path_selection_local_configured:
8296 return "Locally configured route";
8297 case bgp_path_selection_neighbor_ip:
8298 return "Neighbor IP";
8299 case bgp_path_selection_default:
8300 return "Nothing left to compare";
8301 }
8302 return "Invalid (internal error)";
8303}
8304
18ee8310 8305/* Print the short form route status for a bgp_path_info */
4b7e6066 8306static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8307 struct bgp_path_info *path,
d62a17ae 8308 json_object *json_path)
718e3744 8309{
d62a17ae 8310 if (json_path) {
b05a1c8b 8311
d62a17ae 8312 /* Route status display. */
9b6d8fcf 8313 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8314 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8315
9b6d8fcf 8316 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8317 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8318
4056a5f6 8319 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8320 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8321
9b6d8fcf
DS
8322 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8323 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8324 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8325
d62a17ae 8326 /* Selected */
9b6d8fcf 8327 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8328 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8329
9b6d8fcf 8330 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8331 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8332
bbb46eb5 8333 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8334 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8335 json_object_string_add(json_path, "selectionReason",
8336 bgp_path_selection_reason2str(
8337 path->net->reason));
8338 }
b05a1c8b 8339
9b6d8fcf 8340 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8341 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8342
d62a17ae 8343 /* Internal route. */
9b6d8fcf
DS
8344 if ((path->peer->as)
8345 && (path->peer->as == path->peer->local_as))
d62a17ae 8346 json_object_string_add(json_path, "pathFrom",
8347 "internal");
8348 else
8349 json_object_string_add(json_path, "pathFrom",
8350 "external");
b05a1c8b 8351
d62a17ae 8352 return;
8353 }
b05a1c8b 8354
d62a17ae 8355 /* Route status display. */
9b6d8fcf 8356 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8357 vty_out(vty, "R");
9b6d8fcf 8358 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8359 vty_out(vty, "S");
4056a5f6 8360 else if (bgp_path_suppressed(path))
d62a17ae 8361 vty_out(vty, "s");
9b6d8fcf
DS
8362 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8363 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8364 vty_out(vty, "*");
8365 else
8366 vty_out(vty, " ");
8367
8368 /* Selected */
9b6d8fcf 8369 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8370 vty_out(vty, "h");
9b6d8fcf 8371 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8372 vty_out(vty, "d");
9b6d8fcf 8373 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8374 vty_out(vty, ">");
9b6d8fcf 8375 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8376 vty_out(vty, "=");
8377 else
8378 vty_out(vty, " ");
718e3744 8379
d62a17ae 8380 /* Internal route. */
9b6d8fcf
DS
8381 if (path->peer && (path->peer->as)
8382 && (path->peer->as == path->peer->local_as))
d62a17ae 8383 vty_out(vty, "i");
8384 else
8385 vty_out(vty, " ");
b40d939b 8386}
8387
2ba93fd6
DA
8388static char *bgp_nexthop_hostname(struct peer *peer,
8389 struct bgp_nexthop_cache *bnc)
25b5da8d 8390{
892fedb6 8391 if (peer->hostname
aef999a2 8392 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8393 return peer->hostname;
8394 return NULL;
8395}
8396
b40d939b 8397/* called from terminal list command */
bd494ec5 8398void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8399 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8400 json_object *json_paths, bool wide)
d62a17ae 8401{
aef999a2 8402 int len;
515c2602 8403 struct attr *attr = path->attr;
d62a17ae 8404 json_object *json_path = NULL;
8405 json_object *json_nexthops = NULL;
8406 json_object *json_nexthop_global = NULL;
8407 json_object *json_nexthop_ll = NULL;
6f214dd3 8408 json_object *json_ext_community = NULL;
9df8b37c 8409 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8410 bool nexthop_self =
9b6d8fcf 8411 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8412 bool nexthop_othervrf = false;
43089216 8413 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8414 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8415 char *nexthop_hostname =
8416 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8417 char esi_buf[ESI_STR_LEN];
d62a17ae 8418
8419 if (json_paths)
8420 json_path = json_object_new_object();
8421
8422 /* short status lead text */
9b6d8fcf 8423 route_vty_short_status_out(vty, path, json_path);
d62a17ae 8424
8425 if (!json_paths) {
8426 /* print prefix and mask */
8427 if (!display)
ae248832 8428 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8429 else
ae248832 8430 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8431 } else {
ae248832 8432 route_vty_out_route(p, vty, json_path, wide);
d62a17ae 8433 }
47fc97cc 8434
9df8b37c
PZ
8435 /*
8436 * If vrf id of nexthop is different from that of prefix,
8437 * set up printable string to append
8438 */
9b6d8fcf 8439 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8440 const char *self = "";
8441
8442 if (nexthop_self)
8443 self = "<";
8444
8445 nexthop_othervrf = true;
9b6d8fcf 8446 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8447
9b6d8fcf 8448 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8449 snprintf(vrf_id_str, sizeof(vrf_id_str),
8450 "@%s%s", VRFID_NONE_STR, self);
8451 else
8452 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8453 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8454
9b6d8fcf
DS
8455 if (path->extra->bgp_orig->inst_type
8456 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8457
9b6d8fcf 8458 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8459 } else {
8460 const char *self = "";
8461
8462 if (nexthop_self)
8463 self = "<";
8464
8465 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8466 }
8467
445c2480
DS
8468 /*
8469 * For ENCAP and EVPN routes, nexthop address family is not
8470 * neccessarily the same as the prefix address family.
8471 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8472 * EVPN routes are also exchanged with a MP nexthop. Currently,
8473 * this
8474 * is only IPv4, the value will be present in either
8475 * attr->nexthop or
8476 * attr->mp_nexthop_global_in
8477 */
8478 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8479 char buf[BUFSIZ];
8480 char nexthop[128];
8481 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8482
8483 switch (af) {
8484 case AF_INET:
772270f3
QY
8485 snprintf(nexthop, sizeof(nexthop), "%s",
8486 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8487 BUFSIZ));
445c2480
DS
8488 break;
8489 case AF_INET6:
772270f3
QY
8490 snprintf(nexthop, sizeof(nexthop), "%s",
8491 inet_ntop(af, &attr->mp_nexthop_global, buf,
8492 BUFSIZ));
445c2480
DS
8493 break;
8494 default:
772270f3 8495 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8496 break;
d62a17ae 8497 }
d62a17ae 8498
445c2480
DS
8499 if (json_paths) {
8500 json_nexthop_global = json_object_new_object();
8501
515c2602
DA
8502 json_object_string_add(json_nexthop_global, "ip",
8503 nexthop);
8504
939a97f4 8505 if (path->peer->hostname)
515c2602
DA
8506 json_object_string_add(json_nexthop_global,
8507 "hostname",
939a97f4 8508 path->peer->hostname);
515c2602
DA
8509
8510 json_object_string_add(json_nexthop_global, "afi",
8511 (af == AF_INET) ? "ipv4"
8512 : "ipv6");
445c2480
DS
8513 json_object_boolean_true_add(json_nexthop_global,
8514 "used");
aef999a2
DA
8515 } else {
8516 if (nexthop_hostname)
8517 len = vty_out(vty, "%s(%s)%s", nexthop,
8518 nexthop_hostname, vrf_id_str);
8519 else
8520 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8521
ae248832 8522 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8523 if (len < 1)
8524 vty_out(vty, "\n%*s", 36, " ");
8525 else
8526 vty_out(vty, "%*s", len, " ");
8527 }
445c2480
DS
8528 } else if (safi == SAFI_EVPN) {
8529 if (json_paths) {
23d0a753
DA
8530 char buf[BUFSIZ] = {0};
8531
445c2480
DS
8532 json_nexthop_global = json_object_new_object();
8533
515c2602 8534 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8535 inet_ntop(AF_INET,
8536 &attr->nexthop, buf,
8537 sizeof(buf)));
515c2602 8538
939a97f4 8539 if (path->peer->hostname)
515c2602
DA
8540 json_object_string_add(json_nexthop_global,
8541 "hostname",
939a97f4 8542 path->peer->hostname);
515c2602 8543
a4d82a8a
PZ
8544 json_object_string_add(json_nexthop_global, "afi",
8545 "ipv4");
445c2480
DS
8546 json_object_boolean_true_add(json_nexthop_global,
8547 "used");
aef999a2
DA
8548 } else {
8549 if (nexthop_hostname)
8550 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8551 nexthop_hostname, vrf_id_str);
8552 else
8553 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8554 vrf_id_str);
8555
ae248832 8556 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8557 if (len < 1)
8558 vty_out(vty, "\n%*s", 36, " ");
8559 else
8560 vty_out(vty, "%*s", len, " ");
8561 }
d33fc23b 8562 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8563 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8564 if (json_paths) {
23d0a753
DA
8565 char buf[BUFSIZ] = {0};
8566
026b914a 8567 json_nexthop_global = json_object_new_object();
515c2602 8568
026b914a
PG
8569 json_object_string_add(json_nexthop_global,
8570 "afi", "ipv4");
515c2602
DA
8571 json_object_string_add(
8572 json_nexthop_global, "ip",
23d0a753
DA
8573 inet_ntop(AF_INET, &attr->nexthop, buf,
8574 sizeof(buf)));
515c2602 8575
939a97f4 8576 if (path->peer->hostname)
515c2602
DA
8577 json_object_string_add(
8578 json_nexthop_global, "hostname",
939a97f4 8579 path->peer->hostname);
515c2602 8580
50e05855
AD
8581 json_object_boolean_true_add(
8582 json_nexthop_global,
026b914a
PG
8583 "used");
8584 } else {
aef999a2
DA
8585 if (nexthop_hostname)
8586 len = vty_out(vty, "%pI4(%s)%s",
8587 &attr->nexthop,
8588 nexthop_hostname,
8589 vrf_id_str);
8590 else
8591 len = vty_out(vty, "%pI4%s",
8592 &attr->nexthop,
8593 vrf_id_str);
8594
ae248832 8595 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8596 if (len < 1)
8597 vty_out(vty, "\n%*s", 36, " ");
8598 else
8599 vty_out(vty, "%*s", len, " ");
026b914a
PG
8600 }
8601 }
d33fc23b 8602 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8603 if (json_paths) {
23d0a753
DA
8604 char buf[BUFSIZ] = {0};
8605
445c2480 8606 json_nexthop_global = json_object_new_object();
d62a17ae 8607
515c2602 8608 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8609 inet_ntop(AF_INET,
8610 &attr->nexthop, buf,
8611 sizeof(buf)));
515c2602 8612
939a97f4 8613 if (path->peer->hostname)
515c2602
DA
8614 json_object_string_add(json_nexthop_global,
8615 "hostname",
939a97f4 8616 path->peer->hostname);
445c2480 8617
a4d82a8a
PZ
8618 json_object_string_add(json_nexthop_global, "afi",
8619 "ipv4");
445c2480
DS
8620 json_object_boolean_true_add(json_nexthop_global,
8621 "used");
8622 } else {
aef999a2
DA
8623 if (nexthop_hostname)
8624 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8625 nexthop_hostname, vrf_id_str);
8626 else
8627 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8628 vrf_id_str);
9df8b37c 8629
ae248832 8630 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8631 if (len < 1)
8632 vty_out(vty, "\n%*s", 36, " ");
8633 else
8634 vty_out(vty, "%*s", len, " ");
d62a17ae 8635 }
445c2480 8636 }
b05a1c8b 8637
445c2480 8638 /* IPv6 Next Hop */
a4d82a8a 8639 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8640 char buf[BUFSIZ];
d62a17ae 8641
445c2480
DS
8642 if (json_paths) {
8643 json_nexthop_global = json_object_new_object();
a4d82a8a 8644 json_object_string_add(
515c2602
DA
8645 json_nexthop_global, "ip",
8646 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8647 buf, BUFSIZ));
8648
939a97f4 8649 if (path->peer->hostname)
515c2602
DA
8650 json_object_string_add(json_nexthop_global,
8651 "hostname",
939a97f4 8652 path->peer->hostname);
515c2602 8653
a4d82a8a
PZ
8654 json_object_string_add(json_nexthop_global, "afi",
8655 "ipv6");
8656 json_object_string_add(json_nexthop_global, "scope",
8657 "global");
445c2480
DS
8658
8659 /* We display both LL & GL if both have been
8660 * received */
0606039c
DA
8661 if ((attr->mp_nexthop_len
8662 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8663 || (path->peer->conf_if)) {
a4d82a8a 8664 json_nexthop_ll = json_object_new_object();
d62a17ae 8665 json_object_string_add(
515c2602
DA
8666 json_nexthop_ll, "ip",
8667 inet_ntop(AF_INET6,
8668 &attr->mp_nexthop_local, buf,
8669 BUFSIZ));
8670
939a97f4 8671 if (path->peer->hostname)
515c2602
DA
8672 json_object_string_add(
8673 json_nexthop_ll, "hostname",
939a97f4 8674 path->peer->hostname);
515c2602 8675
a4d82a8a
PZ
8676 json_object_string_add(json_nexthop_ll, "afi",
8677 "ipv6");
8678 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8679 "link-local");
d62a17ae 8680
a4d82a8a
PZ
8681 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8682 &attr->mp_nexthop_local)
445c2480
DS
8683 != 0)
8684 && !attr->mp_nexthop_prefer_global)
d62a17ae 8685 json_object_boolean_true_add(
a4d82a8a 8686 json_nexthop_ll, "used");
445c2480
DS
8687 else
8688 json_object_boolean_true_add(
a4d82a8a 8689 json_nexthop_global, "used");
445c2480
DS
8690 } else
8691 json_object_boolean_true_add(
8692 json_nexthop_global, "used");
8693 } else {
8694 /* Display LL if LL/Global both in table unless
8695 * prefer-global is set */
0606039c
DA
8696 if (((attr->mp_nexthop_len
8697 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8698 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8699 || (path->peer->conf_if)) {
8700 if (path->peer->conf_if) {
a4d82a8a 8701 len = vty_out(vty, "%s",
9b6d8fcf 8702 path->peer->conf_if);
ae248832
MK
8703 /* len of IPv6 addr + max len of def
8704 * ifname */
8705 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8706
8707 if (len < 1)
a4d82a8a 8708 vty_out(vty, "\n%*s", 36, " ");
445c2480 8709 else
a4d82a8a 8710 vty_out(vty, "%*s", len, " ");
d62a17ae 8711 } else {
aef999a2
DA
8712 if (nexthop_hostname)
8713 len = vty_out(
8714 vty, "%pI6(%s)%s",
8715 &attr->mp_nexthop_local,
8716 nexthop_hostname,
8717 vrf_id_str);
8718 else
8719 len = vty_out(
8720 vty, "%pI6%s",
8721 &attr->mp_nexthop_local,
8722 vrf_id_str);
8723
ae248832 8724 len = wide ? (41 - len) : (16 - len);
d62a17ae 8725
8726 if (len < 1)
a4d82a8a 8727 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8728 else
a4d82a8a 8729 vty_out(vty, "%*s", len, " ");
d62a17ae 8730 }
445c2480 8731 } else {
aef999a2
DA
8732 if (nexthop_hostname)
8733 len = vty_out(vty, "%pI6(%s)%s",
8734 &attr->mp_nexthop_global,
8735 nexthop_hostname,
8736 vrf_id_str);
8737 else
8738 len = vty_out(vty, "%pI6%s",
8739 &attr->mp_nexthop_global,
8740 vrf_id_str);
8741
ae248832 8742 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8743
8744 if (len < 1)
8745 vty_out(vty, "\n%*s", 36, " ");
8746 else
8747 vty_out(vty, "%*s", len, " ");
d62a17ae 8748 }
8749 }
445c2480 8750 }
718e3744 8751
445c2480
DS
8752 /* MED/Metric */
8753 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8754 if (json_paths)
50e05855 8755 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8756 else if (wide)
8757 vty_out(vty, "%7u", attr->med);
0fbac0b4 8758 else
445c2480 8759 vty_out(vty, "%10u", attr->med);
ae248832
MK
8760 else if (!json_paths) {
8761 if (wide)
8762 vty_out(vty, "%*s", 7, " ");
8763 else
8764 vty_out(vty, "%*s", 10, " ");
8765 }
d62a17ae 8766
445c2480
DS
8767 /* Local Pref */
8768 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8769 if (json_paths)
50e05855 8770 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8771 attr->local_pref);
8772 else
445c2480
DS
8773 vty_out(vty, "%7u", attr->local_pref);
8774 else if (!json_paths)
8775 vty_out(vty, " ");
d62a17ae 8776
445c2480
DS
8777 if (json_paths)
8778 json_object_int_add(json_path, "weight", attr->weight);
8779 else
8780 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8781
445c2480
DS
8782 if (json_paths) {
8783 char buf[BUFSIZ];
a4d82a8a
PZ
8784 json_object_string_add(
8785 json_path, "peerId",
9b6d8fcf 8786 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8787 }
b05a1c8b 8788
445c2480
DS
8789 /* Print aspath */
8790 if (attr->aspath) {
0fbac0b4 8791 if (json_paths)
50e05855 8792 json_object_string_add(json_path, "path",
0fbac0b4
DA
8793 attr->aspath->str);
8794 else
445c2480 8795 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 8796 }
f1aa5d8a 8797
445c2480
DS
8798 /* Print origin */
8799 if (json_paths)
a4d82a8a
PZ
8800 json_object_string_add(json_path, "origin",
8801 bgp_origin_long_str[attr->origin]);
445c2480
DS
8802 else
8803 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
8804
9df8b37c 8805 if (json_paths) {
d071f237 8806 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
8807 json_object_string_add(json_path, "esi",
8808 esi_to_str(&attr->esi,
8809 esi_buf, sizeof(esi_buf)));
8810 }
6f214dd3
CS
8811 if (safi == SAFI_EVPN &&
8812 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8813 json_ext_community = json_object_new_object();
8814 json_object_string_add(json_ext_community,
8815 "string",
8816 attr->ecommunity->str);
8817 json_object_object_add(json_path,
8818 "extendedCommunity",
8819 json_ext_community);
8820 }
8821
9df8b37c
PZ
8822 if (nexthop_self)
8823 json_object_boolean_true_add(json_path,
8824 "announceNexthopSelf");
8825 if (nexthop_othervrf) {
8826 json_object_string_add(json_path, "nhVrfName",
8827 nexthop_vrfname);
8828
8829 json_object_int_add(json_path, "nhVrfId",
8830 ((nexthop_vrfid == VRF_UNKNOWN)
8831 ? -1
8832 : (int)nexthop_vrfid));
8833 }
8834 }
8835
d62a17ae 8836 if (json_paths) {
8837 if (json_nexthop_global || json_nexthop_ll) {
8838 json_nexthops = json_object_new_array();
f1aa5d8a 8839
d62a17ae 8840 if (json_nexthop_global)
8841 json_object_array_add(json_nexthops,
8842 json_nexthop_global);
f1aa5d8a 8843
d62a17ae 8844 if (json_nexthop_ll)
8845 json_object_array_add(json_nexthops,
8846 json_nexthop_ll);
f1aa5d8a 8847
d62a17ae 8848 json_object_object_add(json_path, "nexthops",
8849 json_nexthops);
8850 }
8851
8852 json_object_array_add(json_paths, json_path);
8853 } else {
8854 vty_out(vty, "\n");
6f214dd3 8855
b5e140c8 8856 if (safi == SAFI_EVPN) {
229587fb
AK
8857 struct bgp_path_es_info *path_es_info = NULL;
8858
8859 if (path->extra)
8860 path_es_info = path->extra->es_info;
8861
d071f237 8862 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 8863 /* XXX - add these params to the json out */
b5e140c8 8864 vty_out(vty, "%*s", 20, " ");
229587fb
AK
8865 vty_out(vty, "ESI:%s",
8866 esi_to_str(&attr->esi, esi_buf,
8867 sizeof(esi_buf)));
8868 if (path_es_info && path_es_info->es)
8869 vty_out(vty, " VNI: %u",
8870 path_es_info->vni);
8871 vty_out(vty, "\n");
b5e140c8
AK
8872 }
8873 if (attr->flag &
8874 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
8875 vty_out(vty, "%*s", 20, " ");
8876 vty_out(vty, "%s\n", attr->ecommunity->str);
8877 }
6f214dd3
CS
8878 }
8879
49e5a4a0 8880#ifdef ENABLE_BGP_VNC
d62a17ae 8881 /* prints an additional line, indented, with VNC info, if
8882 * present */
8883 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 8884 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 8885#endif
d62a17ae 8886 }
8887}
718e3744 8888
8889/* called from terminal list command */
5f040085
DS
8890void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
8891 struct attr *attr, safi_t safi, bool use_json,
ae248832 8892 json_object *json_ar, bool wide)
d62a17ae 8893{
8894 json_object *json_status = NULL;
8895 json_object *json_net = NULL;
aef999a2 8896 int len;
d62a17ae 8897 char buff[BUFSIZ];
dc387b0f 8898
d62a17ae 8899 /* Route status display. */
8900 if (use_json) {
8901 json_status = json_object_new_object();
8902 json_net = json_object_new_object();
8903 } else {
8904 vty_out(vty, "*");
8905 vty_out(vty, ">");
8906 vty_out(vty, " ");
8907 }
718e3744 8908
d62a17ae 8909 /* print prefix and mask */
50e05855 8910 if (use_json) {
dc387b0f
LK
8911 if (safi == SAFI_EVPN)
8912 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
8913 else if (p->family == AF_INET || p->family == AF_INET6) {
8914 json_object_string_add(
8915 json_net, "addrPrefix",
8916 inet_ntop(p->family, &p->u.prefix, buff,
8917 BUFSIZ));
8918 json_object_int_add(json_net, "prefixLen",
8919 p->prefixlen);
8920 prefix2str(p, buff, PREFIX_STRLEN);
8921 json_object_string_add(json_net, "network", buff);
8922 }
50e05855 8923 } else
ae248832 8924 route_vty_out_route(p, vty, NULL, wide);
d62a17ae 8925
8926 /* Print attribute */
8927 if (attr) {
8928 if (use_json) {
23d0a753
DA
8929 char buf[BUFSIZ] = {0};
8930
d62a17ae 8931 if (p->family == AF_INET
8932 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 8933 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 8934 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 8935 json_object_string_add(
8936 json_net, "nextHop",
23d0a753
DA
8937 inet_ntop(
8938 AF_INET,
8939 &attr->mp_nexthop_global_in,
8940 buf, sizeof(buf)));
d62a17ae 8941 else
8942 json_object_string_add(
8943 json_net, "nextHop",
23d0a753
DA
8944 inet_ntop(AF_INET,
8945 &attr->nexthop, buf,
8946 sizeof(buf)));
d62a17ae 8947 } else if (p->family == AF_INET6
8948 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8949 char buf[BUFSIZ];
8950
8951 json_object_string_add(
aa0a10fc 8952 json_net, "nextHopGlobal",
d62a17ae 8953 inet_ntop(AF_INET6,
8954 &attr->mp_nexthop_global, buf,
8955 BUFSIZ));
23d0a753
DA
8956 } else if (p->family == AF_EVPN
8957 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
8958 char buf[BUFSIZ] = {0};
8959
8960 json_object_string_add(
8961 json_net, "nextHop",
8962 inet_ntop(AF_INET,
8963 &attr->mp_nexthop_global_in,
8964 buf, sizeof(buf)));
8965 }
d62a17ae 8966
8967 if (attr->flag
8968 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
8969 json_object_int_add(json_net, "metric",
8970 attr->med);
8971
0fbac0b4 8972 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 8973 json_object_int_add(json_net, "locPrf",
0fbac0b4 8974 attr->local_pref);
d62a17ae 8975
8976 json_object_int_add(json_net, "weight", attr->weight);
8977
8978 /* Print aspath */
0fbac0b4 8979 if (attr->aspath)
50e05855 8980 json_object_string_add(json_net, "path",
0fbac0b4 8981 attr->aspath->str);
d62a17ae 8982
8983 /* Print origin */
8984 json_object_string_add(json_net, "bgpOriginCode",
8985 bgp_origin_str[attr->origin]);
8986 } else {
8987 if (p->family == AF_INET
8988 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8989 || safi == SAFI_EVPN
8990 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
8991 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
8992 || safi == SAFI_EVPN)
23d0a753
DA
8993 vty_out(vty, "%-16pI4",
8994 &attr->mp_nexthop_global_in);
ae248832 8995 else if (wide)
23d0a753 8996 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 8997 else
23d0a753 8998 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 8999 } else if (p->family == AF_INET6
9000 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9001 char buf[BUFSIZ];
9002
9003 len = vty_out(
9004 vty, "%s",
9005 inet_ntop(AF_INET6,
9006 &attr->mp_nexthop_global, buf,
9007 BUFSIZ));
ae248832 9008 len = wide ? (41 - len) : (16 - len);
d62a17ae 9009 if (len < 1)
9010 vty_out(vty, "\n%*s", 36, " ");
9011 else
9012 vty_out(vty, "%*s", len, " ");
9013 }
9014 if (attr->flag
9015 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9016 if (wide)
9017 vty_out(vty, "%7u", attr->med);
9018 else
9019 vty_out(vty, "%10u", attr->med);
9020 else if (wide)
9021 vty_out(vty, " ");
d62a17ae 9022 else
9023 vty_out(vty, " ");
718e3744 9024
d62a17ae 9025 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9026 vty_out(vty, "%7u", attr->local_pref);
9027 else
9028 vty_out(vty, " ");
9029
9030 vty_out(vty, "%7u ", attr->weight);
9031
9032 /* Print aspath */
9033 if (attr->aspath)
9034 aspath_print_vty(vty, "%s", attr->aspath, " ");
9035
9036 /* Print origin */
9037 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9038 }
9039 }
9040 if (use_json) {
9041 json_object_boolean_true_add(json_status, "*");
9042 json_object_boolean_true_add(json_status, ">");
9043 json_object_object_add(json_net, "appliedStatusSymbols",
9044 json_status);
1608ff77 9045
dc387b0f
LK
9046 prefix2str(p, buff, PREFIX_STRLEN);
9047 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9048 } else
9049 vty_out(vty, "\n");
9050}
9051
bd494ec5 9052void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9053 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9054 json_object *json)
9055{
9056 json_object *json_out = NULL;
9057 struct attr *attr;
9058 mpls_label_t label = MPLS_INVALID_LABEL;
9059
9b6d8fcf 9060 if (!path->extra)
d62a17ae 9061 return;
9062
9063 if (json)
9064 json_out = json_object_new_object();
9065
9066 /* short status lead text */
9b6d8fcf 9067 route_vty_short_status_out(vty, path, json_out);
d62a17ae 9068
9069 /* print prefix and mask */
9070 if (json == NULL) {
9071 if (!display)
ae248832 9072 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9073 else
9074 vty_out(vty, "%*s", 17, " ");
9075 }
9076
9077 /* Print attribute */
9b6d8fcf 9078 attr = path->attr;
05864da7
DS
9079 if (((p->family == AF_INET)
9080 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9081 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9082 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9083 char buf[BUFSIZ] = {0};
9084
05864da7
DS
9085 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9086 || safi == SAFI_EVPN) {
9087 if (json)
9088 json_object_string_add(
9089 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9090 inet_ntop(AF_INET,
9091 &attr->mp_nexthop_global_in,
9092 buf, sizeof(buf)));
05864da7 9093 else
23d0a753
DA
9094 vty_out(vty, "%-16pI4",
9095 &attr->mp_nexthop_global_in);
05864da7
DS
9096 } else {
9097 if (json)
9098 json_object_string_add(
9099 json_out, "nexthop",
23d0a753
DA
9100 inet_ntop(AF_INET, &attr->nexthop, buf,
9101 sizeof(buf)));
05864da7 9102 else
23d0a753 9103 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9104 }
9105 } else if (((p->family == AF_INET6)
9106 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9107 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9108 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9109 char buf_a[512];
9110
9111 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9112 if (json)
9113 json_object_string_add(
9114 json_out, "mpNexthopGlobalIn",
9115 inet_ntop(AF_INET6,
9116 &attr->mp_nexthop_global,
9117 buf_a, sizeof(buf_a)));
9118 else
9119 vty_out(vty, "%s",
9120 inet_ntop(AF_INET6,
9121 &attr->mp_nexthop_global,
9122 buf_a, sizeof(buf_a)));
9123 } else if (attr->mp_nexthop_len
9124 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9125 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9126 &attr->mp_nexthop_global,
9127 &attr->mp_nexthop_local);
9128 if (json)
9129 json_object_string_add(json_out,
9130 "mpNexthopGlobalLocal",
9131 buf_a);
9132 else
9133 vty_out(vty, "%s", buf_a);
d62a17ae 9134 }
9135 }
9136
9b6d8fcf 9137 label = decode_label(&path->extra->label[0]);
d62a17ae 9138
9139 if (bgp_is_valid_label(&label)) {
9140 if (json) {
9141 json_object_int_add(json_out, "notag", label);
9142 json_object_array_add(json, json_out);
9143 } else {
9144 vty_out(vty, "notag/%d", label);
9145 vty_out(vty, "\n");
9146 }
9147 }
9148}
718e3744 9149
bd494ec5 9150void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9151 struct bgp_path_info *path, int display,
d62a17ae 9152 json_object *json_paths)
718e3744 9153{
d62a17ae 9154 struct attr *attr;
14f51eba 9155 char buf[BUFSIZ] = {0};
d62a17ae 9156 json_object *json_path = NULL;
14f51eba
LK
9157 json_object *json_nexthop = NULL;
9158 json_object *json_overlay = NULL;
856ca177 9159
9b6d8fcf 9160 if (!path->extra)
d62a17ae 9161 return;
718e3744 9162
14f51eba
LK
9163 if (json_paths) {
9164 json_path = json_object_new_object();
9165 json_overlay = json_object_new_object();
9166 json_nexthop = json_object_new_object();
9167 }
9168
d62a17ae 9169 /* short status lead text */
9b6d8fcf 9170 route_vty_short_status_out(vty, path, json_path);
856ca177 9171
d62a17ae 9172 /* print prefix and mask */
9173 if (!display)
ae248832 9174 route_vty_out_route(p, vty, json_path, false);
d62a17ae 9175 else
9176 vty_out(vty, "%*s", 17, " ");
9177
9178 /* Print attribute */
9b6d8fcf 9179 attr = path->attr;
05864da7
DS
9180 char buf1[BUFSIZ];
9181 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9182
05864da7
DS
9183 switch (af) {
9184 case AF_INET:
9185 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9186 if (!json_path) {
9187 vty_out(vty, "%-16s", buf);
9188 } else {
9189 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9190
05864da7 9191 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9192
05864da7
DS
9193 json_object_object_add(json_path, "nexthop",
9194 json_nexthop);
9195 }
9196 break;
9197 case AF_INET6:
9198 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9199 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9200 if (!json_path) {
9201 vty_out(vty, "%s(%s)", buf, buf1);
9202 } else {
9203 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9204
05864da7
DS
9205 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9206 buf1);
14f51eba 9207
05864da7 9208 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9209
05864da7
DS
9210 json_object_object_add(json_path, "nexthop",
9211 json_nexthop);
9212 }
9213 break;
9214 default:
9215 if (!json_path) {
9216 vty_out(vty, "?");
9217 } else {
9218 json_object_string_add(json_nexthop, "Error",
9219 "Unsupported address-family");
d62a17ae 9220 }
05864da7 9221 }
988258b4 9222
6c924775
DS
9223 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9224
9225 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9226 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9227 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9228 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9229
05864da7
DS
9230 if (!json_path)
9231 vty_out(vty, "/%s", buf);
9232 else
9233 json_object_string_add(json_overlay, "gw", buf);
9234
9235 if (attr->ecommunity) {
9236 char *mac = NULL;
9237 struct ecommunity_val *routermac = ecommunity_lookup(
9238 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9239 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9240
9241 if (routermac)
9242 mac = ecom_mac2str((char *)routermac->val);
9243 if (mac) {
9244 if (!json_path) {
c4efd0f4 9245 vty_out(vty, "/%s", mac);
05864da7
DS
9246 } else {
9247 json_object_string_add(json_overlay, "rmac",
9248 mac);
988258b4 9249 }
05864da7 9250 XFREE(MTYPE_TMP, mac);
988258b4 9251 }
05864da7 9252 }
718e3744 9253
05864da7
DS
9254 if (!json_path) {
9255 vty_out(vty, "\n");
9256 } else {
9257 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9258
05864da7 9259 json_object_array_add(json_paths, json_path);
14f51eba 9260 }
d62a17ae 9261}
718e3744 9262
d62a17ae 9263/* dampening route */
5f040085
DS
9264static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9265 struct bgp_path_info *path, int display,
9266 afi_t afi, safi_t safi, bool use_json,
9267 json_object *json)
d62a17ae 9268{
9269 struct attr *attr;
9270 int len;
9271 char timebuf[BGP_UPTIME_LEN];
9272
9273 /* short status lead text */
9b6d8fcf 9274 route_vty_short_status_out(vty, path, json);
d62a17ae 9275
9276 /* print prefix and mask */
9277 if (!use_json) {
9278 if (!display)
ae248832 9279 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9280 else
9281 vty_out(vty, "%*s", 17, " ");
9282 }
9283
9b6d8fcf 9284 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9285 len = 17 - len;
9286 if (len < 1) {
9287 if (!use_json)
9288 vty_out(vty, "\n%*s", 34, " ");
9289 } else {
9290 if (use_json)
9291 json_object_int_add(json, "peerHost", len);
9292 else
9293 vty_out(vty, "%*s", len, " ");
9294 }
9295
9296 if (use_json)
a935f597
DA
9297 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9298 safi, use_json, json);
d62a17ae 9299 else
9b6d8fcf
DS
9300 vty_out(vty, "%s ",
9301 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9302 BGP_UPTIME_LEN, afi, safi,
9303 use_json, json));
d62a17ae 9304
9305 /* Print attribute */
9b6d8fcf 9306 attr = path->attr;
d62a17ae 9307
05864da7
DS
9308 /* Print aspath */
9309 if (attr->aspath) {
d62a17ae 9310 if (use_json)
05864da7
DS
9311 json_object_string_add(json, "asPath",
9312 attr->aspath->str);
d62a17ae 9313 else
05864da7 9314 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9315 }
05864da7
DS
9316
9317 /* Print origin */
9318 if (use_json)
9319 json_object_string_add(json, "origin",
9320 bgp_origin_str[attr->origin]);
9321 else
9322 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9323
d62a17ae 9324 if (!use_json)
9325 vty_out(vty, "\n");
9326}
718e3744 9327
d62a17ae 9328/* flap route */
5f040085
DS
9329static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9330 struct bgp_path_info *path, int display,
9331 afi_t afi, safi_t safi, bool use_json,
9332 json_object *json)
784d3a42 9333{
d62a17ae 9334 struct attr *attr;
9335 struct bgp_damp_info *bdi;
9336 char timebuf[BGP_UPTIME_LEN];
9337 int len;
784d3a42 9338
9b6d8fcf 9339 if (!path->extra)
d62a17ae 9340 return;
784d3a42 9341
9b6d8fcf 9342 bdi = path->extra->damp_info;
784d3a42 9343
d62a17ae 9344 /* short status lead text */
9b6d8fcf 9345 route_vty_short_status_out(vty, path, json);
784d3a42 9346
d62a17ae 9347 /* print prefix and mask */
9348 if (!use_json) {
9349 if (!display)
ae248832 9350 route_vty_out_route(p, vty, NULL, false);
d62a17ae 9351 else
9352 vty_out(vty, "%*s", 17, " ");
9353 }
784d3a42 9354
9b6d8fcf 9355 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9356 len = 16 - len;
9357 if (len < 1) {
9358 if (!use_json)
9359 vty_out(vty, "\n%*s", 33, " ");
9360 } else {
9361 if (use_json)
9362 json_object_int_add(json, "peerHost", len);
9363 else
9364 vty_out(vty, "%*s", len, " ");
9365 }
784d3a42 9366
d62a17ae 9367 len = vty_out(vty, "%d", bdi->flap);
9368 len = 5 - len;
9369 if (len < 1) {
9370 if (!use_json)
9371 vty_out(vty, " ");
9372 } else {
9373 if (use_json)
9374 json_object_int_add(json, "bdiFlap", len);
9375 else
9376 vty_out(vty, "%*s", len, " ");
9377 }
9378
9379 if (use_json)
9380 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9381 json);
9382 else
996c9314
LB
9383 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9384 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9385
9b6d8fcf
DS
9386 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9387 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9388 if (use_json)
9b6d8fcf 9389 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9390 BGP_UPTIME_LEN, afi, safi,
9391 use_json, json);
d62a17ae 9392 else
9393 vty_out(vty, "%s ",
9b6d8fcf 9394 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9395 BGP_UPTIME_LEN, afi,
9396 safi, use_json, json));
d62a17ae 9397 } else {
9398 if (!use_json)
9399 vty_out(vty, "%*s ", 8, " ");
9400 }
9401
9402 /* Print attribute */
9b6d8fcf 9403 attr = path->attr;
d62a17ae 9404
05864da7
DS
9405 /* Print aspath */
9406 if (attr->aspath) {
d62a17ae 9407 if (use_json)
05864da7
DS
9408 json_object_string_add(json, "asPath",
9409 attr->aspath->str);
d62a17ae 9410 else
05864da7 9411 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9412 }
05864da7
DS
9413
9414 /* Print origin */
9415 if (use_json)
9416 json_object_string_add(json, "origin",
9417 bgp_origin_str[attr->origin]);
9418 else
9419 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9420
d62a17ae 9421 if (!use_json)
9422 vty_out(vty, "\n");
9423}
9424
9425static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9426 int *first, const char *header,
9427 json_object *json_adv_to)
9428{
9429 char buf1[INET6_ADDRSTRLEN];
9430 json_object *json_peer = NULL;
9431
9432 if (json_adv_to) {
9433 /* 'advertised-to' is a dictionary of peers we have advertised
9434 * this
9435 * prefix too. The key is the peer's IP or swpX, the value is
9436 * the
9437 * hostname if we know it and "" if not.
9438 */
9439 json_peer = json_object_new_object();
9440
9441 if (peer->hostname)
9442 json_object_string_add(json_peer, "hostname",
9443 peer->hostname);
9444
9445 if (peer->conf_if)
9446 json_object_object_add(json_adv_to, peer->conf_if,
9447 json_peer);
9448 else
9449 json_object_object_add(
9450 json_adv_to,
9451 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9452 json_peer);
9453 } else {
9454 if (*first) {
9455 vty_out(vty, "%s", header);
9456 *first = 0;
9457 }
9458
9459 if (peer->hostname
892fedb6 9460 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9461 if (peer->conf_if)
9462 vty_out(vty, " %s(%s)", peer->hostname,
9463 peer->conf_if);
9464 else
9465 vty_out(vty, " %s(%s)", peer->hostname,
9466 sockunion2str(&peer->su, buf1,
9467 SU_ADDRSTRLEN));
9468 } else {
9469 if (peer->conf_if)
9470 vty_out(vty, " %s", peer->conf_if);
9471 else
9472 vty_out(vty, " %s",
9473 sockunion2str(&peer->su, buf1,
9474 SU_ADDRSTRLEN));
9475 }
9476 }
784d3a42
PG
9477}
9478
dcc68b5e
MS
9479static void route_vty_out_tx_ids(struct vty *vty,
9480 struct bgp_addpath_info_data *d)
9481{
9482 int i;
9483
9484 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9485 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9486 d->addpath_tx_id[i],
9487 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9488 }
9489}
9490
5e4d4c8a 9491static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9492 struct bgp_path_info *pi,
9493 struct attr *attr,
9494 json_object *json_path)
5e4d4c8a
AK
9495{
9496 char esi_buf[ESI_STR_LEN];
9497 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9498 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9499 ATTR_ES_PEER_ROUTER);
9500 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9501 ATTR_ES_PEER_ACTIVE);
9502 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9503 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9504 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9505 if (json_path) {
9506 json_object *json_es_info = NULL;
9507
9508 json_object_string_add(
9509 json_path, "esi",
9510 esi_buf);
9511 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9512 json_es_info = json_object_new_object();
9513 if (es_local)
9514 json_object_boolean_true_add(
9515 json_es_info, "localEs");
9516 if (peer_active)
9517 json_object_boolean_true_add(
9518 json_es_info, "peerActive");
9519 if (peer_proxy)
9520 json_object_boolean_true_add(
9521 json_es_info, "peerProxy");
9522 if (peer_router)
9523 json_object_boolean_true_add(
9524 json_es_info, "peerRouter");
9525 if (attr->mm_sync_seqnum)
9526 json_object_int_add(
9527 json_es_info, "peerSeq",
9528 attr->mm_sync_seqnum);
9529 json_object_object_add(
9530 json_path, "es_info",
9531 json_es_info);
9532 }
9533 } else {
9534 if (bgp_evpn_attr_is_sync(attr))
9535 vty_out(vty,
9536 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9537 esi_buf,
9538 es_local ? "local-es":"",
9539 peer_proxy ? "proxy " : "",
9540 peer_active ? "active ":"",
9541 peer_router ? "router ":"",
9542 attr->mm_sync_seqnum);
9543 else
9544 vty_out(vty, " ESI %s %s\n",
9545 esi_buf,
9546 es_local ? "local-es":"");
9547 }
9548}
9549
9550void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
9551 struct bgp_dest *bn, struct bgp_path_info *path,
9552 afi_t afi, safi_t safi, json_object *json_paths)
d62a17ae 9553{
9554 char buf[INET6_ADDRSTRLEN];
9555 char buf1[BUFSIZ];
515c2602 9556 struct attr *attr = path->attr;
d62a17ae 9557 int sockunion_vty_out(struct vty *, union sockunion *);
9558 time_t tbuf;
9559 json_object *json_bestpath = NULL;
9560 json_object *json_cluster_list = NULL;
9561 json_object *json_cluster_list_list = NULL;
9562 json_object *json_ext_community = NULL;
9563 json_object *json_last_update = NULL;
7fd077aa 9564 json_object *json_pmsi = NULL;
d62a17ae 9565 json_object *json_nexthop_global = NULL;
9566 json_object *json_nexthop_ll = NULL;
9567 json_object *json_nexthops = NULL;
9568 json_object *json_path = NULL;
9569 json_object *json_peer = NULL;
9570 json_object *json_string = NULL;
9571 json_object *json_adv_to = NULL;
9572 int first = 0;
9573 struct listnode *node, *nnode;
9574 struct peer *peer;
9575 int addpath_capable;
9576 int has_adj;
9577 unsigned int first_as;
1defdda8 9578 bool nexthop_self =
9b6d8fcf 9579 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9580 int i;
2ba93fd6
DA
9581 char *nexthop_hostname =
9582 bgp_nexthop_hostname(path->peer, path->nexthop);
b5b99af8 9583 int rpki_validation_state = 0;
d62a17ae 9584
9585 if (json_paths) {
9586 json_path = json_object_new_object();
9587 json_peer = json_object_new_object();
9588 json_nexthop_global = json_object_new_object();
9589 }
9590
44c69747 9591 if (path->extra) {
b57ba6d2 9592 char tag_buf[30];
d62a17ae 9593
d62a17ae 9594 tag_buf[0] = '\0';
9b6d8fcf
DS
9595 if (path->extra && path->extra->num_labels) {
9596 bgp_evpn_label2str(path->extra->label,
9597 path->extra->num_labels, tag_buf,
a4d82a8a 9598 sizeof(tag_buf));
d62a17ae 9599 }
d7325ee7 9600 if (safi == SAFI_EVPN) {
44c69747 9601 if (!json_paths) {
2dbe669b
DA
9602 vty_out(vty, " Route %pFX",
9603 (struct prefix_evpn *)
9604 bgp_dest_get_prefix(bn));
44c69747
LK
9605 if (tag_buf[0] != '\0')
9606 vty_out(vty, " VNI %s", tag_buf);
9607 vty_out(vty, "\n");
9608 } else {
9609 if (tag_buf[0])
9610 json_object_string_add(json_path, "VNI",
9611 tag_buf);
9612 }
d7325ee7
DD
9613 }
9614
44c69747 9615 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9616 struct bgp_path_info *parent_ri;
9bcb3eef 9617 struct bgp_dest *dest, *pdest;
d62a17ae 9618
9b6d8fcf 9619 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9620 dest = parent_ri->net;
9621 if (dest && dest->pdest) {
9622 pdest = dest->pdest;
9623 prefix_rd2str(
9624 (struct prefix_rd *)bgp_dest_get_prefix(
9625 pdest),
9626 buf1, sizeof(buf1));
d7325ee7 9627 if (is_pi_family_evpn(parent_ri)) {
2dbe669b
DA
9628 vty_out(vty,
9629 " Imported from %s:%pFX, VNI %s\n",
9630 buf1,
9631 (struct prefix_evpn *)
9632 bgp_dest_get_prefix(
9633 dest),
9634 tag_buf);
d7325ee7 9635 } else
2dbe669b
DA
9636 vty_out(vty,
9637 " Imported from %s:%pFX\n",
9638 buf1,
9639 (struct prefix_evpn *)
9640 bgp_dest_get_prefix(
9641 dest));
d62a17ae 9642 }
9643 }
9644 }
d62a17ae 9645
05864da7
DS
9646 /* Line1 display AS-path, Aggregator */
9647 if (attr->aspath) {
9648 if (json_paths) {
9649 if (!attr->aspath->json)
9650 aspath_str_update(attr->aspath, true);
9651 json_object_lock(attr->aspath->json);
9652 json_object_object_add(json_path, "aspath",
9653 attr->aspath->json);
9654 } else {
9655 if (attr->aspath->segments)
9656 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9657 else
05864da7 9658 vty_out(vty, " Local");
d62a17ae 9659 }
05864da7 9660 }
d62a17ae 9661
05864da7
DS
9662 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9663 if (json_paths)
9664 json_object_boolean_true_add(json_path, "removed");
9665 else
9666 vty_out(vty, ", (removed)");
9667 }
d62a17ae 9668
05864da7
DS
9669 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9670 if (json_paths)
9671 json_object_boolean_true_add(json_path, "stale");
9672 else
9673 vty_out(vty, ", (stale)");
9674 }
d62a17ae 9675
05864da7
DS
9676 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9677 if (json_paths) {
23d0a753
DA
9678 char buf[BUFSIZ] = {0};
9679
05864da7
DS
9680 json_object_int_add(json_path, "aggregatorAs",
9681 attr->aggregator_as);
23d0a753
DA
9682 json_object_string_add(json_path, "aggregatorId",
9683 inet_ntop(AF_INET,
9684 &attr->aggregator_addr,
9685 buf, sizeof(buf)));
05864da7 9686 } else {
88d495a9
DA
9687 vty_out(vty, ", (aggregated by %u %pI4)",
9688 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9689 }
05864da7 9690 }
d62a17ae 9691
05864da7
DS
9692 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9693 PEER_FLAG_REFLECTOR_CLIENT)) {
9694 if (json_paths)
9695 json_object_boolean_true_add(json_path,
9696 "rxedFromRrClient");
9697 else
9698 vty_out(vty, ", (Received from a RR-client)");
9699 }
d62a17ae 9700
05864da7
DS
9701 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9702 PEER_FLAG_RSERVER_CLIENT)) {
9703 if (json_paths)
9704 json_object_boolean_true_add(json_path,
9705 "rxedFromRsClient");
9706 else
9707 vty_out(vty, ", (Received from a RS-client)");
9708 }
d62a17ae 9709
05864da7
DS
9710 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9711 if (json_paths)
9712 json_object_boolean_true_add(json_path,
9713 "dampeningHistoryEntry");
9714 else
9715 vty_out(vty, ", (history entry)");
9716 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9717 if (json_paths)
9718 json_object_boolean_true_add(json_path,
9719 "dampeningSuppressed");
9720 else
9721 vty_out(vty, ", (suppressed due to dampening)");
9722 }
d62a17ae 9723
05864da7
DS
9724 if (!json_paths)
9725 vty_out(vty, "\n");
d62a17ae 9726
05864da7
DS
9727 /* Line2 display Next-hop, Neighbor, Router-id */
9728 /* Display the nexthop */
9bcb3eef 9729 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9730
9731 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9732 || bn_p->family == AF_EVPN)
05864da7
DS
9733 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9734 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9735 char buf[BUFSIZ] = {0};
9736
05864da7
DS
9737 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9738 || safi == SAFI_EVPN) {
515c2602 9739 if (json_paths) {
d62a17ae 9740 json_object_string_add(
515c2602 9741 json_nexthop_global, "ip",
23d0a753
DA
9742 inet_ntop(AF_INET,
9743 &attr->mp_nexthop_global_in,
9744 buf, sizeof(buf)));
515c2602 9745
939a97f4 9746 if (path->peer->hostname)
515c2602
DA
9747 json_object_string_add(
9748 json_nexthop_global, "hostname",
939a97f4 9749 path->peer->hostname);
aef999a2
DA
9750 } else {
9751 if (nexthop_hostname)
9752 vty_out(vty, " %pI4(%s)",
9753 &attr->mp_nexthop_global_in,
9754 nexthop_hostname);
9755 else
9756 vty_out(vty, " %pI4",
9757 &attr->mp_nexthop_global_in);
9758 }
d62a17ae 9759 } else {
515c2602 9760 if (json_paths) {
05864da7 9761 json_object_string_add(
515c2602 9762 json_nexthop_global, "ip",
23d0a753
DA
9763 inet_ntop(AF_INET, &attr->nexthop, buf,
9764 sizeof(buf)));
515c2602 9765
939a97f4 9766 if (path->peer->hostname)
515c2602
DA
9767 json_object_string_add(
9768 json_nexthop_global, "hostname",
939a97f4 9769 path->peer->hostname);
aef999a2
DA
9770 } else {
9771 if (nexthop_hostname)
9772 vty_out(vty, " %pI4(%s)",
9773 &attr->nexthop,
9774 nexthop_hostname);
9775 else
9776 vty_out(vty, " %pI4",
9777 &attr->nexthop);
9778 }
d62a17ae 9779 }
9780
05864da7
DS
9781 if (json_paths)
9782 json_object_string_add(json_nexthop_global, "afi",
9783 "ipv4");
9784 } else {
9785 if (json_paths) {
9786 json_object_string_add(
515c2602
DA
9787 json_nexthop_global, "ip",
9788 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
9789 buf, INET6_ADDRSTRLEN));
9790
939a97f4 9791 if (path->peer->hostname)
515c2602
DA
9792 json_object_string_add(json_nexthop_global,
9793 "hostname",
939a97f4 9794 path->peer->hostname);
515c2602 9795
05864da7
DS
9796 json_object_string_add(json_nexthop_global, "afi",
9797 "ipv6");
9798 json_object_string_add(json_nexthop_global, "scope",
9799 "global");
9800 } else {
aef999a2
DA
9801 if (nexthop_hostname)
9802 vty_out(vty, " %pI6(%s)",
9803 &attr->mp_nexthop_global,
9804 nexthop_hostname);
9805 else
9806 vty_out(vty, " %pI6",
9807 &attr->mp_nexthop_global);
d62a17ae 9808 }
05864da7 9809 }
d62a17ae 9810
05864da7
DS
9811 /* Display the IGP cost or 'inaccessible' */
9812 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
9813 if (json_paths)
9814 json_object_boolean_false_add(json_nexthop_global,
9815 "accessible");
9816 else
9817 vty_out(vty, " (inaccessible)");
9818 } else {
9819 if (path->extra && path->extra->igpmetric) {
d62a17ae 9820 if (json_paths)
05864da7
DS
9821 json_object_int_add(json_nexthop_global,
9822 "metric",
9823 path->extra->igpmetric);
d62a17ae 9824 else
05864da7
DS
9825 vty_out(vty, " (metric %u)",
9826 path->extra->igpmetric);
d62a17ae 9827 }
9828
05864da7 9829 /* IGP cost is 0, display this only for json */
d62a17ae 9830 else {
d62a17ae 9831 if (json_paths)
05864da7
DS
9832 json_object_int_add(json_nexthop_global,
9833 "metric", 0);
d62a17ae 9834 }
d62a17ae 9835
05864da7
DS
9836 if (json_paths)
9837 json_object_boolean_true_add(json_nexthop_global,
9838 "accessible");
9839 }
d62a17ae 9840
05864da7
DS
9841 /* Display peer "from" output */
9842 /* This path was originated locally */
9843 if (path->peer == bgp->peer_self) {
d62a17ae 9844
05864da7 9845 if (safi == SAFI_EVPN
b54892e0 9846 || (bn_p->family == AF_INET
05864da7 9847 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 9848 if (json_paths)
05864da7
DS
9849 json_object_string_add(json_peer, "peerId",
9850 "0.0.0.0");
d62a17ae 9851 else
05864da7
DS
9852 vty_out(vty, " from 0.0.0.0 ");
9853 } else {
d62a17ae 9854 if (json_paths)
05864da7
DS
9855 json_object_string_add(json_peer, "peerId",
9856 "::");
d62a17ae 9857 else
05864da7 9858 vty_out(vty, " from :: ");
d62a17ae 9859 }
d62a17ae 9860
23d0a753
DA
9861 if (json_paths) {
9862 char buf[BUFSIZ] = {0};
9863
05864da7 9864 json_object_string_add(json_peer, "routerId",
23d0a753
DA
9865 inet_ntop(AF_INET,
9866 &bgp->router_id, buf,
9867 sizeof(buf)));
9868 } else {
9869 vty_out(vty, "(%pI4)", &bgp->router_id);
9870 }
05864da7 9871 }
d62a17ae 9872
05864da7
DS
9873 /* We RXed this path from one of our peers */
9874 else {
9875
9876 if (json_paths) {
9877 json_object_string_add(json_peer, "peerId",
9878 sockunion2str(&path->peer->su,
9879 buf,
9880 SU_ADDRSTRLEN));
9881 json_object_string_add(json_peer, "routerId",
9882 inet_ntop(AF_INET,
9883 &path->peer->remote_id,
9884 buf1, sizeof(buf1)));
9885
9886 if (path->peer->hostname)
9887 json_object_string_add(json_peer, "hostname",
9888 path->peer->hostname);
9889
9890 if (path->peer->domainname)
9891 json_object_string_add(json_peer, "domainname",
9892 path->peer->domainname);
9893
9894 if (path->peer->conf_if)
9895 json_object_string_add(json_peer, "interface",
9896 path->peer->conf_if);
9897 } else {
9898 if (path->peer->conf_if) {
9899 if (path->peer->hostname
892fedb6
DA
9900 && CHECK_FLAG(path->peer->bgp->flags,
9901 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9902 vty_out(vty, " from %s(%s)",
9903 path->peer->hostname,
9904 path->peer->conf_if);
d62a17ae 9905 else
05864da7 9906 vty_out(vty, " from %s",
9b6d8fcf 9907 path->peer->conf_if);
d62a17ae 9908 } else {
05864da7 9909 if (path->peer->hostname
892fedb6
DA
9910 && CHECK_FLAG(path->peer->bgp->flags,
9911 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
9912 vty_out(vty, " from %s(%s)",
9913 path->peer->hostname,
9914 path->peer->host);
d62a17ae 9915 else
05864da7
DS
9916 vty_out(vty, " from %s",
9917 sockunion2str(&path->peer->su,
9918 buf,
9919 SU_ADDRSTRLEN));
d62a17ae 9920 }
d62a17ae 9921
05864da7 9922 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 9923 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
9924 else
9925 vty_out(vty, " (%s)",
9926 inet_ntop(AF_INET,
9927 &path->peer->remote_id, buf1,
9928 sizeof(buf1)));
d62a17ae 9929 }
05864da7 9930 }
9df8b37c 9931
05864da7
DS
9932 /*
9933 * Note when vrfid of nexthop is different from that of prefix
9934 */
9935 if (path->extra && path->extra->bgp_orig) {
9936 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 9937
05864da7
DS
9938 if (json_paths) {
9939 const char *vn;
9df8b37c 9940
05864da7
DS
9941 if (path->extra->bgp_orig->inst_type
9942 == BGP_INSTANCE_TYPE_DEFAULT)
9943 vn = VRF_DEFAULT_NAME;
9944 else
9945 vn = path->extra->bgp_orig->name;
9df8b37c 9946
05864da7 9947 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 9948
05864da7
DS
9949 if (nexthop_vrfid == VRF_UNKNOWN) {
9950 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 9951 } else {
05864da7
DS
9952 json_object_int_add(json_path, "nhVrfId",
9953 (int)nexthop_vrfid);
9df8b37c 9954 }
05864da7
DS
9955 } else {
9956 if (nexthop_vrfid == VRF_UNKNOWN)
9957 vty_out(vty, " vrf ?");
137147c6
DS
9958 else {
9959 struct vrf *vrf;
9960
9961 vrf = vrf_lookup_by_id(nexthop_vrfid);
9962 vty_out(vty, " vrf %s(%u)",
9963 VRF_LOGNAME(vrf), nexthop_vrfid);
9964 }
9df8b37c 9965 }
05864da7 9966 }
9df8b37c 9967
05864da7
DS
9968 if (nexthop_self) {
9969 if (json_paths) {
9970 json_object_boolean_true_add(json_path,
9971 "announceNexthopSelf");
9972 } else {
9973 vty_out(vty, " announce-nh-self");
9df8b37c 9974 }
05864da7 9975 }
9df8b37c 9976
05864da7
DS
9977 if (!json_paths)
9978 vty_out(vty, "\n");
d62a17ae 9979
05864da7
DS
9980 /* display the link-local nexthop */
9981 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9982 if (json_paths) {
9983 json_nexthop_ll = json_object_new_object();
9984 json_object_string_add(
515c2602
DA
9985 json_nexthop_ll, "ip",
9986 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
9987 buf, INET6_ADDRSTRLEN));
9988
939a97f4 9989 if (path->peer->hostname)
515c2602
DA
9990 json_object_string_add(json_nexthop_ll,
9991 "hostname",
939a97f4 9992 path->peer->hostname);
515c2602 9993
05864da7
DS
9994 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
9995 json_object_string_add(json_nexthop_ll, "scope",
9996 "link-local");
d62a17ae 9997
05864da7
DS
9998 json_object_boolean_true_add(json_nexthop_ll,
9999 "accessible");
d62a17ae 10000
05864da7 10001 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10002 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10003 "used");
10004 else
10005 json_object_boolean_true_add(
10006 json_nexthop_global, "used");
10007 } else {
10008 vty_out(vty, " (%s) %s\n",
10009 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10010 buf, INET6_ADDRSTRLEN),
10011 attr->mp_nexthop_prefer_global
10012 ? "(prefer-global)"
10013 : "(used)");
d62a17ae 10014 }
05864da7
DS
10015 }
10016 /* If we do not have a link-local nexthop then we must flag the
10017 global as "used" */
10018 else {
10019 if (json_paths)
10020 json_object_boolean_true_add(json_nexthop_global,
10021 "used");
10022 }
d62a17ae 10023
b5e140c8 10024 if (safi == SAFI_EVPN &&
5e4d4c8a 10025 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10026 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10027 }
10028
05864da7
DS
10029 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10030 * Int/Ext/Local, Atomic, best */
10031 if (json_paths)
10032 json_object_string_add(json_path, "origin",
10033 bgp_origin_long_str[attr->origin]);
10034 else
10035 vty_out(vty, " Origin %s",
10036 bgp_origin_long_str[attr->origin]);
9df8b37c 10037
05864da7 10038 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10039 if (json_paths)
05864da7 10040 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10041 else
05864da7
DS
10042 vty_out(vty, ", metric %u", attr->med);
10043 }
9df8b37c 10044
05864da7
DS
10045 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10046 if (json_paths)
0fbac0b4 10047 json_object_int_add(json_path, "locPrf",
05864da7
DS
10048 attr->local_pref);
10049 else
10050 vty_out(vty, ", localpref %u", attr->local_pref);
10051 }
9df8b37c 10052
05864da7
DS
10053 if (attr->weight != 0) {
10054 if (json_paths)
10055 json_object_int_add(json_path, "weight", attr->weight);
10056 else
10057 vty_out(vty, ", weight %u", attr->weight);
10058 }
9df8b37c 10059
05864da7
DS
10060 if (attr->tag != 0) {
10061 if (json_paths)
10062 json_object_int_add(json_path, "tag", attr->tag);
10063 else
10064 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10065 }
9df8b37c 10066
05864da7
DS
10067 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10068 if (json_paths)
10069 json_object_boolean_false_add(json_path, "valid");
10070 else
10071 vty_out(vty, ", invalid");
10072 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10073 if (json_paths)
10074 json_object_boolean_true_add(json_path, "valid");
10075 else
10076 vty_out(vty, ", valid");
10077 }
9df8b37c 10078
05864da7
DS
10079 if (path->peer != bgp->peer_self) {
10080 if (path->peer->as == path->peer->local_as) {
10081 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10082 if (json_paths)
10083 json_object_string_add(
10084 json_peer, "type",
10085 "confed-internal");
d62a17ae 10086 else
05864da7 10087 vty_out(vty, ", confed-internal");
d62a17ae 10088 } else {
05864da7
DS
10089 if (json_paths)
10090 json_object_string_add(
10091 json_peer, "type", "internal");
10092 else
10093 vty_out(vty, ", internal");
9df8b37c 10094 }
05864da7
DS
10095 } else {
10096 if (bgp_confederation_peers_check(bgp,
10097 path->peer->as)) {
10098 if (json_paths)
10099 json_object_string_add(
10100 json_peer, "type",
10101 "confed-external");
d62a17ae 10102 else
05864da7 10103 vty_out(vty, ", confed-external");
d62a17ae 10104 } else {
05864da7
DS
10105 if (json_paths)
10106 json_object_string_add(
10107 json_peer, "type", "external");
10108 else
10109 vty_out(vty, ", external");
d62a17ae 10110 }
10111 }
05864da7
DS
10112 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10113 if (json_paths) {
10114 json_object_boolean_true_add(json_path, "aggregated");
10115 json_object_boolean_true_add(json_path, "local");
10116 } else {
10117 vty_out(vty, ", aggregated, local");
10118 }
10119 } else if (path->type != ZEBRA_ROUTE_BGP) {
10120 if (json_paths)
10121 json_object_boolean_true_add(json_path, "sourced");
10122 else
10123 vty_out(vty, ", sourced");
10124 } else {
10125 if (json_paths) {
10126 json_object_boolean_true_add(json_path, "sourced");
10127 json_object_boolean_true_add(json_path, "local");
10128 } else {
10129 vty_out(vty, ", sourced, local");
d62a17ae 10130 }
05864da7 10131 }
718e3744 10132
05864da7 10133 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10134 if (json_paths)
05864da7
DS
10135 json_object_boolean_true_add(json_path,
10136 "atomicAggregate");
d62a17ae 10137 else
05864da7
DS
10138 vty_out(vty, ", atomic-aggregate");
10139 }
d62a17ae 10140
05864da7
DS
10141 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10142 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10143 && bgp_path_info_mpath_count(path))) {
10144 if (json_paths)
10145 json_object_boolean_true_add(json_path, "multipath");
10146 else
10147 vty_out(vty, ", multipath");
10148 }
50e05855 10149
05864da7
DS
10150 // Mark the bestpath(s)
10151 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10152 first_as = aspath_get_first_as(attr->aspath);
718e3744 10153
05864da7
DS
10154 if (json_paths) {
10155 if (!json_bestpath)
10156 json_bestpath = json_object_new_object();
10157 json_object_int_add(json_bestpath, "bestpathFromAs",
10158 first_as);
10159 } else {
10160 if (first_as)
10161 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10162 else
05864da7 10163 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10164 }
05864da7 10165 }
718e3744 10166
05864da7
DS
10167 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10168 if (json_paths) {
10169 if (!json_bestpath)
10170 json_bestpath = json_object_new_object();
10171 json_object_boolean_true_add(json_bestpath, "overall");
10172 json_object_string_add(
10173 json_bestpath, "selectionReason",
10174 bgp_path_selection_reason2str(bn->reason));
10175 } else {
10176 vty_out(vty, ", best");
10177 vty_out(vty, " (%s)",
10178 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10179 }
05864da7 10180 }
718e3744 10181
b5b99af8
DS
10182 const struct prefix *p = bgp_dest_get_prefix(bn);
10183 if (p->family == AF_INET || p->family == AF_INET6)
10184 rpki_validation_state = hook_call(bgp_rpki_prefix_status,
10185 path->peer, path->attr, p);
10186 if (rpki_validation_state) {
10187 if (json_paths)
10188 json_object_string_add(
10189 json_path, "rpkiValidationState",
10190 bgp_rpki_validation2str(rpki_validation_state));
10191 else
10192 vty_out(vty, ", validation-state: %s",
10193 bgp_rpki_validation2str(rpki_validation_state));
10194 }
10195
05864da7
DS
10196 if (json_bestpath)
10197 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10198
05864da7
DS
10199 if (!json_paths)
10200 vty_out(vty, "\n");
10201
10202 /* Line 4 display Community */
10203 if (attr->community) {
10204 if (json_paths) {
10205 if (!attr->community->json)
10206 community_str(attr->community, true);
10207 json_object_lock(attr->community->json);
10208 json_object_object_add(json_path, "community",
10209 attr->community->json);
10210 } else {
10211 vty_out(vty, " Community: %s\n",
10212 attr->community->str);
d62a17ae 10213 }
05864da7 10214 }
718e3744 10215
05864da7
DS
10216 /* Line 5 display Extended-community */
10217 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10218 if (json_paths) {
10219 json_ext_community = json_object_new_object();
10220 json_object_string_add(json_ext_community, "string",
10221 attr->ecommunity->str);
10222 json_object_object_add(json_path, "extendedCommunity",
10223 json_ext_community);
d62a17ae 10224 } else {
05864da7
DS
10225 vty_out(vty, " Extended Community: %s\n",
10226 attr->ecommunity->str);
d62a17ae 10227 }
05864da7 10228 }
718e3744 10229
05864da7
DS
10230 /* Line 6 display Large community */
10231 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10232 if (json_paths) {
10233 if (!attr->lcommunity->json)
10234 lcommunity_str(attr->lcommunity, true);
10235 json_object_lock(attr->lcommunity->json);
10236 json_object_object_add(json_path, "largeCommunity",
10237 attr->lcommunity->json);
10238 } else {
10239 vty_out(vty, " Large Community: %s\n",
10240 attr->lcommunity->str);
d62a17ae 10241 }
05864da7 10242 }
718e3744 10243
05864da7
DS
10244 /* Line 7 display Originator, Cluster-id */
10245 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10246 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10247 char buf[BUFSIZ] = {0};
10248
05864da7 10249 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10250 if (json_paths)
05864da7
DS
10251 json_object_string_add(
10252 json_path, "originatorId",
23d0a753
DA
10253 inet_ntop(AF_INET, &attr->originator_id,
10254 buf, sizeof(buf)));
d62a17ae 10255 else
23d0a753
DA
10256 vty_out(vty, " Originator: %pI4",
10257 &attr->originator_id);
d62a17ae 10258 }
856ca177 10259
05864da7 10260 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10261 struct cluster_list *cluster =
10262 bgp_attr_get_cluster(attr);
05864da7 10263 int i;
d62a17ae 10264
10265 if (json_paths) {
05864da7
DS
10266 json_cluster_list = json_object_new_object();
10267 json_cluster_list_list =
10268 json_object_new_array();
10269
779fee93 10270 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10271 json_string = json_object_new_string(
779fee93
DS
10272 inet_ntop(AF_INET,
10273 &cluster->list[i],
10274 buf, sizeof(buf)));
05864da7
DS
10275 json_object_array_add(
10276 json_cluster_list_list,
10277 json_string);
10278 }
718e3744 10279
05864da7
DS
10280 /*
10281 * struct cluster_list does not have
10282 * "str" variable like aspath and community
10283 * do. Add this someday if someone asks
10284 * for it.
10285 * json_object_string_add(json_cluster_list,
779fee93 10286 * "string", cluster->str);
05864da7
DS
10287 */
10288 json_object_object_add(json_cluster_list,
10289 "list",
10290 json_cluster_list_list);
10291 json_object_object_add(json_path, "clusterList",
10292 json_cluster_list);
0dc8ee70 10293 } else {
05864da7
DS
10294 vty_out(vty, ", Cluster list: ");
10295
779fee93 10296 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10297 vty_out(vty, "%pI4 ",
779fee93 10298 &cluster->list[i]);
05864da7 10299 }
0dc8ee70 10300 }
d62a17ae 10301 }
718e3744 10302
d62a17ae 10303 if (!json_paths)
10304 vty_out(vty, "\n");
05864da7 10305 }
d62a17ae 10306
05864da7 10307 if (path->extra && path->extra->damp_info)
40ec3340 10308 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10309
05864da7
DS
10310 /* Remote Label */
10311 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10312 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10313 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10314
05864da7
DS
10315 if (json_paths)
10316 json_object_int_add(json_path, "remoteLabel", label);
10317 else
10318 vty_out(vty, " Remote label: %d\n", label);
10319 }
d62a17ae 10320
e496b420
HS
10321 /* Remote SID */
10322 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10323 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10324 if (json_paths)
10325 json_object_string_add(json_path, "remoteSid", buf);
10326 else
10327 vty_out(vty, " Remote SID: %s\n", buf);
10328 }
10329
05864da7
DS
10330 /* Label Index */
10331 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10332 if (json_paths)
10333 json_object_int_add(json_path, "labelIndex",
10334 attr->label_index);
10335 else
10336 vty_out(vty, " Label Index: %d\n",
10337 attr->label_index);
10338 }
d62a17ae 10339
05864da7
DS
10340 /* Line 8 display Addpath IDs */
10341 if (path->addpath_rx_id
10342 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10343 if (json_paths) {
10344 json_object_int_add(json_path, "addpathRxId",
10345 path->addpath_rx_id);
d62a17ae 10346
05864da7
DS
10347 /* Keep backwards compatibility with the old API
10348 * by putting TX All's ID in the old field
10349 */
10350 json_object_int_add(
10351 json_path, "addpathTxId",
10352 path->tx_addpath
10353 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10354
05864da7
DS
10355 /* ... but create a specific field for each
10356 * strategy
10357 */
10358 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10359 json_object_int_add(
10360 json_path,
10361 bgp_addpath_names(i)->id_json_name,
10362 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10363 }
05864da7
DS
10364 } else {
10365 vty_out(vty, " AddPath ID: RX %u, ",
10366 path->addpath_rx_id);
d62a17ae 10367
05864da7 10368 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10369 }
05864da7 10370 }
520d5d76 10371
05864da7
DS
10372 /* If we used addpath to TX a non-bestpath we need to display
10373 * "Advertised to" on a path-by-path basis
10374 */
10375 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10376 first = 1;
dcc68b5e 10377
05864da7
DS
10378 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10379 addpath_capable =
10380 bgp_addpath_encode_tx(peer, afi, safi);
10381 has_adj = bgp_adj_out_lookup(
10382 peer, path->net,
10383 bgp_addpath_id_for_peer(peer, afi, safi,
10384 &path->tx_addpath));
10385
10386 if ((addpath_capable && has_adj)
10387 || (!addpath_capable && has_adj
10388 && CHECK_FLAG(path->flags,
10389 BGP_PATH_SELECTED))) {
10390 if (json_path && !json_adv_to)
10391 json_adv_to = json_object_new_object();
dcc68b5e 10392
05864da7
DS
10393 route_vty_out_advertised_to(
10394 vty, peer, &first,
10395 " Advertised to:", json_adv_to);
d62a17ae 10396 }
10397 }
718e3744 10398
05864da7
DS
10399 if (json_path) {
10400 if (json_adv_to) {
10401 json_object_object_add(
10402 json_path, "advertisedTo", json_adv_to);
d62a17ae 10403 }
05864da7
DS
10404 } else {
10405 if (!first) {
10406 vty_out(vty, "\n");
d62a17ae 10407 }
10408 }
05864da7 10409 }
b05a1c8b 10410
05864da7
DS
10411 /* Line 9 display Uptime */
10412 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10413 if (json_paths) {
10414 json_last_update = json_object_new_object();
10415 json_object_int_add(json_last_update, "epoch", tbuf);
10416 json_object_string_add(json_last_update, "string",
10417 ctime(&tbuf));
10418 json_object_object_add(json_path, "lastUpdate",
10419 json_last_update);
10420 } else
10421 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10422
05864da7
DS
10423 /* Line 10 display PMSI tunnel attribute, if present */
10424 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10425 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10426 bgp_attr_get_pmsi_tnl_type(attr),
10427 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10428
05864da7
DS
10429 if (json_paths) {
10430 json_pmsi = json_object_new_object();
10431 json_object_string_add(json_pmsi, "tunnelType", str);
10432 json_object_int_add(json_pmsi, "label",
10433 label2vni(&attr->label));
10434 json_object_object_add(json_path, "pmsi", json_pmsi);
10435 } else
10436 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10437 str, label2vni(&attr->label));
d62a17ae 10438 }
f1aa5d8a 10439
92269aa2
DS
10440 /* Output some debug about internal state of the dest flags */
10441 if (json_paths) {
10442 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10443 json_object_boolean_true_add(json_path, "processScheduled");
10444 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10445 json_object_boolean_true_add(json_path, "userCleared");
10446 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10447 json_object_boolean_true_add(json_path, "labelChanged");
10448 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10449 json_object_boolean_true_add(json_path, "registeredForLabel");
10450 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10451 json_object_boolean_true_add(json_path, "selectDefered");
10452 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10453 json_object_boolean_true_add(json_path, "fibInstalled");
10454 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10455 json_object_boolean_true_add(json_path, "fibPending");
10456 }
10457
d62a17ae 10458 /* We've constructed the json object for this path, add it to the json
10459 * array of paths
10460 */
10461 if (json_paths) {
10462 if (json_nexthop_global || json_nexthop_ll) {
10463 json_nexthops = json_object_new_array();
f1aa5d8a 10464
d62a17ae 10465 if (json_nexthop_global)
10466 json_object_array_add(json_nexthops,
10467 json_nexthop_global);
f1aa5d8a 10468
d62a17ae 10469 if (json_nexthop_ll)
10470 json_object_array_add(json_nexthops,
10471 json_nexthop_ll);
f1aa5d8a 10472
d62a17ae 10473 json_object_object_add(json_path, "nexthops",
10474 json_nexthops);
10475 }
10476
10477 json_object_object_add(json_path, "peer", json_peer);
10478 json_object_array_add(json_paths, json_path);
05864da7 10479 }
b366b518
BB
10480}
10481
96ade3ed 10482#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10483#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10484#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10485
d62a17ae 10486static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10487 const char *prefix_list_str, afi_t afi,
10488 safi_t safi, enum bgp_show_type type);
10489static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10490 const char *filter, afi_t afi, safi_t safi,
10491 enum bgp_show_type type);
10492static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10493 const char *rmap_str, afi_t afi, safi_t safi,
10494 enum bgp_show_type type);
10495static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10496 const char *com, int exact, afi_t afi,
10497 safi_t safi);
10498static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10499 const char *prefix, afi_t afi, safi_t safi,
10500 enum bgp_show_type type);
a4d82a8a 10501static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10502 afi_t afi, safi_t safi, enum bgp_show_type type,
10503 bool use_json);
7f323236
DW
10504static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10505 const char *comstr, int exact, afi_t afi,
96f3485c 10506 safi_t safi, uint8_t show_flags);
d62a17ae 10507
1ae44dfc
LB
10508
10509static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10510 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10511 void *output_arg, char *rd, int is_last,
10512 unsigned long *output_cum, unsigned long *total_cum,
10513 unsigned long *json_header_depth, uint8_t show_flags)
d62a17ae 10514{
40381db7 10515 struct bgp_path_info *pi;
9bcb3eef 10516 struct bgp_dest *dest;
d62a17ae 10517 int header = 1;
10518 int display;
1ae44dfc
LB
10519 unsigned long output_count = 0;
10520 unsigned long total_count = 0;
d62a17ae 10521 struct prefix *p;
d62a17ae 10522 json_object *json_paths = NULL;
10523 int first = 1;
96f3485c
MK
10524 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10525 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10526 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10527
1ae44dfc
LB
10528 if (output_cum && *output_cum != 0)
10529 header = 0;
10530
9386b588 10531 if (use_json && !*json_header_depth) {
96f3485c
MK
10532 if (all)
10533 *json_header_depth = 1;
10534 else {
10535 vty_out(vty, "{\n");
10536 *json_header_depth = 2;
10537 }
10538
d62a17ae 10539 vty_out(vty,
23d0a753
DA
10540 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10541 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10542 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10543 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10544 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10545 ? VRF_DEFAULT_NAME
10546 : bgp->name,
10547 table->version, &bgp->router_id,
01eced22 10548 bgp->default_local_pref, bgp->as);
9386b588 10549 if (rd) {
445c2480 10550 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10551 ++*json_header_depth;
10552 }
d62a17ae 10553 }
718e3744 10554
445c2480
DS
10555 if (use_json && rd) {
10556 vty_out(vty, " \"%s\" : { ", rd);
10557 }
10558
d62a17ae 10559 /* Start processing of routes. */
9bcb3eef
DS
10560 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10561 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10562
9bcb3eef 10563 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10564 if (pi == NULL)
98ce9a06 10565 continue;
d62a17ae 10566
98ce9a06 10567 display = 0;
98ce9a06
DS
10568 if (use_json)
10569 json_paths = json_object_new_array();
10570 else
10571 json_paths = NULL;
d62a17ae 10572
6f94b685 10573 for (; pi; pi = pi->next) {
98ce9a06
DS
10574 total_count++;
10575 if (type == bgp_show_type_flap_statistics
10576 || type == bgp_show_type_flap_neighbor
10577 || type == bgp_show_type_dampend_paths
10578 || type == bgp_show_type_damp_neighbor) {
40381db7 10579 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10580 continue;
10581 }
10582 if (type == bgp_show_type_regexp) {
10583 regex_t *regex = output_arg;
d62a17ae 10584
40381db7 10585 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10586 == REG_NOMATCH)
10587 continue;
10588 }
10589 if (type == bgp_show_type_prefix_list) {
10590 struct prefix_list *plist = output_arg;
d62a17ae 10591
9bcb3eef 10592 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10593 != PREFIX_PERMIT)
10594 continue;
10595 }
10596 if (type == bgp_show_type_filter_list) {
10597 struct as_list *as_list = output_arg;
d62a17ae 10598
40381db7 10599 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10600 != AS_FILTER_PERMIT)
10601 continue;
10602 }
10603 if (type == bgp_show_type_route_map) {
10604 struct route_map *rmap = output_arg;
9b6d8fcf 10605 struct bgp_path_info path;
98ce9a06 10606 struct attr dummy_attr;
b68885f9 10607 route_map_result_t ret;
d62a17ae 10608
6f4f49b2 10609 dummy_attr = *pi->attr;
d62a17ae 10610
40381db7 10611 path.peer = pi->peer;
9b6d8fcf 10612 path.attr = &dummy_attr;
d62a17ae 10613
1782514f 10614 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10615 if (ret == RMAP_DENYMATCH)
10616 continue;
10617 }
10618 if (type == bgp_show_type_neighbor
10619 || type == bgp_show_type_flap_neighbor
10620 || type == bgp_show_type_damp_neighbor) {
10621 union sockunion *su = output_arg;
10622
40381db7
DS
10623 if (pi->peer == NULL
10624 || pi->peer->su_remote == NULL
10625 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10626 continue;
10627 }
10628 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10629 uint32_t destination;
d62a17ae 10630
9bcb3eef 10631 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10632 if (IN_CLASSC(destination)
9bcb3eef 10633 && dest_p->prefixlen == 24)
98ce9a06
DS
10634 continue;
10635 if (IN_CLASSB(destination)
9bcb3eef 10636 && dest_p->prefixlen == 16)
98ce9a06
DS
10637 continue;
10638 if (IN_CLASSA(destination)
9bcb3eef 10639 && dest_p->prefixlen == 8)
98ce9a06
DS
10640 continue;
10641 }
10642 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10643 p = output_arg;
9bcb3eef 10644 if (!prefix_match(p, dest_p))
98ce9a06
DS
10645 continue;
10646 }
10647 if (type == bgp_show_type_community_all) {
40381db7 10648 if (!pi->attr->community)
98ce9a06
DS
10649 continue;
10650 }
10651 if (type == bgp_show_type_community) {
10652 struct community *com = output_arg;
d62a17ae 10653
40381db7
DS
10654 if (!pi->attr->community
10655 || !community_match(pi->attr->community,
98ce9a06
DS
10656 com))
10657 continue;
10658 }
10659 if (type == bgp_show_type_community_exact) {
10660 struct community *com = output_arg;
d62a17ae 10661
40381db7
DS
10662 if (!pi->attr->community
10663 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10664 continue;
10665 }
10666 if (type == bgp_show_type_community_list) {
10667 struct community_list *list = output_arg;
d62a17ae 10668
40381db7 10669 if (!community_list_match(pi->attr->community,
a4d82a8a 10670 list))
98ce9a06
DS
10671 continue;
10672 }
a4d82a8a 10673 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10674 struct community_list *list = output_arg;
d62a17ae 10675
98ce9a06 10676 if (!community_list_exact_match(
40381db7 10677 pi->attr->community, list))
98ce9a06
DS
10678 continue;
10679 }
10680 if (type == bgp_show_type_lcommunity) {
10681 struct lcommunity *lcom = output_arg;
d62a17ae 10682
40381db7
DS
10683 if (!pi->attr->lcommunity
10684 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10685 lcom))
10686 continue;
10687 }
36a206db 10688
10689 if (type == bgp_show_type_lcommunity_exact) {
10690 struct lcommunity *lcom = output_arg;
10691
10692 if (!pi->attr->lcommunity
10693 || !lcommunity_cmp(pi->attr->lcommunity,
10694 lcom))
10695 continue;
10696 }
98ce9a06
DS
10697 if (type == bgp_show_type_lcommunity_list) {
10698 struct community_list *list = output_arg;
d62a17ae 10699
40381db7 10700 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10701 list))
98ce9a06
DS
10702 continue;
10703 }
36a206db 10704 if (type
10705 == bgp_show_type_lcommunity_list_exact) {
10706 struct community_list *list = output_arg;
10707
10708 if (!lcommunity_list_exact_match(
10709 pi->attr->lcommunity, list))
10710 continue;
10711 }
98ce9a06 10712 if (type == bgp_show_type_lcommunity_all) {
40381db7 10713 if (!pi->attr->lcommunity)
98ce9a06
DS
10714 continue;
10715 }
10716 if (type == bgp_show_type_dampend_paths
10717 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
10718 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
10719 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
10720 continue;
10721 }
10722
10723 if (!use_json && header) {
23d0a753
DA
10724 vty_out(vty,
10725 "BGP table version is %" PRIu64
10726 ", local router ID is %pI4, vrf id ",
10727 table->version, &bgp->router_id);
9df8b37c
PZ
10728 if (bgp->vrf_id == VRF_UNKNOWN)
10729 vty_out(vty, "%s", VRFID_NONE_STR);
10730 else
10731 vty_out(vty, "%u", bgp->vrf_id);
10732 vty_out(vty, "\n");
01eced22
AD
10733 vty_out(vty, "Default local pref %u, ",
10734 bgp->default_local_pref);
10735 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 10736 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 10737 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 10738 vty_out(vty, BGP_SHOW_OCODE_HEADER);
d62a17ae 10739 if (type == bgp_show_type_dampend_paths
10740 || type == bgp_show_type_damp_neighbor)
98ce9a06 10741 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
10742 else if (type == bgp_show_type_flap_statistics
10743 || type == bgp_show_type_flap_neighbor)
98ce9a06 10744 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 10745 else
ae248832
MK
10746 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
10747 : BGP_SHOW_HEADER));
98ce9a06 10748 header = 0;
d62a17ae 10749 }
98ce9a06
DS
10750 if (rd != NULL && !display && !output_count) {
10751 if (!use_json)
10752 vty_out(vty,
10753 "Route Distinguisher: %s\n",
10754 rd);
d62a17ae 10755 }
98ce9a06
DS
10756 if (type == bgp_show_type_dampend_paths
10757 || type == bgp_show_type_damp_neighbor)
9bcb3eef 10758 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10759 AFI_IP, safi, use_json,
10760 json_paths);
98ce9a06
DS
10761 else if (type == bgp_show_type_flap_statistics
10762 || type == bgp_show_type_flap_neighbor)
9bcb3eef 10763 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
10764 AFI_IP, safi, use_json,
10765 json_paths);
98ce9a06 10766 else
9bcb3eef 10767 route_vty_out(vty, dest_p, pi, display, safi,
ae248832 10768 json_paths, wide);
98ce9a06 10769 display++;
d62a17ae 10770 }
10771
98ce9a06
DS
10772 if (display) {
10773 output_count++;
10774 if (!use_json)
10775 continue;
10776
625d2931 10777 /* encode prefix */
9bcb3eef 10778 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
10779 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
10780
1840384b 10781
b54892e0
DS
10782 bgp_fs_nlri_get_string(
10783 (unsigned char *)
9bcb3eef
DS
10784 dest_p->u.prefix_flowspec.ptr,
10785 dest_p->u.prefix_flowspec.prefixlen,
1840384b 10786 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
10787 family2afi(dest_p->u
10788 .prefix_flowspec.family));
625d2931 10789 if (first)
b54892e0 10790 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 10791 dest_p->u.prefix_flowspec
b54892e0 10792 .prefixlen);
625d2931 10793 else
b54892e0 10794 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 10795 dest_p->u.prefix_flowspec
b54892e0 10796 .prefixlen);
625d2931 10797 } else {
625d2931 10798 if (first)
1b78780b 10799 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 10800 else
1b78780b 10801 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 10802 }
98ce9a06 10803 vty_out(vty, "%s",
f4ec52f7
DA
10804 json_object_to_json_string_ext(
10805 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 10806 json_object_free(json_paths);
449feb8e 10807 json_paths = NULL;
98ce9a06 10808 first = 0;
1f83ed02
DS
10809 } else
10810 json_object_free(json_paths);
98ce9a06
DS
10811 }
10812
1ae44dfc
LB
10813 if (output_cum) {
10814 output_count += *output_cum;
10815 *output_cum = output_count;
10816 }
10817 if (total_cum) {
10818 total_count += *total_cum;
10819 *total_cum = total_count;
10820 }
d62a17ae 10821 if (use_json) {
9386b588 10822 if (rd) {
a4d82a8a 10823 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
10824 }
10825 if (is_last) {
a4d82a8a
PZ
10826 unsigned long i;
10827 for (i = 0; i < *json_header_depth; ++i)
10828 vty_out(vty, " } ");
96f3485c
MK
10829 if (!all)
10830 vty_out(vty, "\n");
9386b588 10831 }
d62a17ae 10832 } else {
1ae44dfc
LB
10833 if (is_last) {
10834 /* No route is displayed */
10835 if (output_count == 0) {
10836 if (type == bgp_show_type_normal)
10837 vty_out(vty,
10838 "No BGP prefixes displayed, %ld exist\n",
10839 total_count);
10840 } else
d62a17ae 10841 vty_out(vty,
1ae44dfc
LB
10842 "\nDisplayed %ld routes and %ld total paths\n",
10843 output_count, total_count);
10844 }
d62a17ae 10845 }
718e3744 10846
d62a17ae 10847 return CMD_SUCCESS;
718e3744 10848}
10849
1ae44dfc
LB
10850int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
10851 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 10852 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 10853{
9bcb3eef 10854 struct bgp_dest *dest, *next;
1ae44dfc
LB
10855 unsigned long output_cum = 0;
10856 unsigned long total_cum = 0;
9386b588 10857 unsigned long json_header_depth = 0;
67009e22 10858 struct bgp_table *itable;
0136788c 10859 bool show_msg;
96f3485c 10860 uint8_t show_flags = 0;
0136788c
LB
10861
10862 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 10863
96f3485c
MK
10864 if (use_json)
10865 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10866
9bcb3eef
DS
10867 for (dest = bgp_table_top(table); dest; dest = next) {
10868 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 10869
9bcb3eef
DS
10870 next = bgp_route_next(dest);
10871 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 10872 continue;
67009e22 10873
9bcb3eef 10874 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 10875 if (itable != NULL) {
1ae44dfc 10876 struct prefix_rd prd;
06b9f471 10877 char rd[RD_ADDRSTRLEN];
1ae44dfc 10878
9bcb3eef 10879 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 10880 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 10881 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
10882 rd, next == NULL, &output_cum,
10883 &total_cum, &json_header_depth,
10884 show_flags);
0136788c
LB
10885 if (next == NULL)
10886 show_msg = false;
1ae44dfc
LB
10887 }
10888 }
0136788c
LB
10889 if (show_msg) {
10890 if (output_cum == 0)
10891 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
10892 total_cum);
10893 else
10894 vty_out(vty,
10895 "\nDisplayed %ld routes and %ld total paths\n",
10896 output_cum, total_cum);
10897 }
1ae44dfc
LB
10898 return CMD_SUCCESS;
10899}
d62a17ae 10900static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c
MK
10901 enum bgp_show_type type, void *output_arg,
10902 uint8_t show_flags)
fee0f4c6 10903{
d62a17ae 10904 struct bgp_table *table;
9386b588 10905 unsigned long json_header_depth = 0;
96f3485c 10906 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 10907
d62a17ae 10908 if (bgp == NULL) {
10909 bgp = bgp_get_default();
10910 }
fee0f4c6 10911
d62a17ae 10912 if (bgp == NULL) {
10913 if (!use_json)
10914 vty_out(vty, "No BGP process is configured\n");
16307668
RW
10915 else
10916 vty_out(vty, "{}\n");
d62a17ae 10917 return CMD_WARNING;
10918 }
4dd6177e 10919
1ae44dfc 10920 table = bgp->rib[afi][safi];
d62a17ae 10921 /* use MPLS and ENCAP specific shows until they are merged */
10922 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
10923 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
10924 output_arg, use_json);
d62a17ae 10925 }
dba3c1d3
PG
10926
10927 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
10928 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
10929 output_arg, use_json,
10930 1, NULL, NULL);
10931 }
d62a17ae 10932 /* labeled-unicast routes live in the unicast table */
10933 else if (safi == SAFI_LABELED_UNICAST)
10934 safi = SAFI_UNICAST;
fee0f4c6 10935
96f3485c
MK
10936 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
10937 NULL, NULL, &json_header_depth, show_flags);
fee0f4c6 10938}
10939
d62a17ae 10940static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96f3485c 10941 safi_t safi, uint8_t show_flags)
f186de26 10942{
d62a17ae 10943 struct listnode *node, *nnode;
10944 struct bgp *bgp;
10945 int is_first = 1;
9f049418 10946 bool route_output = false;
96f3485c 10947 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 10948
d62a17ae 10949 if (use_json)
10950 vty_out(vty, "{\n");
9f689658 10951
d62a17ae 10952 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 10953 route_output = true;
d62a17ae 10954 if (use_json) {
10955 if (!is_first)
10956 vty_out(vty, ",\n");
10957 else
10958 is_first = 0;
10959
10960 vty_out(vty, "\"%s\":",
10961 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10962 ? VRF_DEFAULT_NAME
d62a17ae 10963 : bgp->name);
10964 } else {
10965 vty_out(vty, "\nInstance %s:\n",
10966 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 10967 ? VRF_DEFAULT_NAME
d62a17ae 10968 : bgp->name);
10969 }
10970 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
96f3485c 10971 show_flags);
d62a17ae 10972 }
9f689658 10973
d62a17ae 10974 if (use_json)
10975 vty_out(vty, "}\n");
9f049418
DS
10976 else if (!route_output)
10977 vty_out(vty, "%% BGP instance not found\n");
f186de26 10978}
10979
718e3744 10980/* Header of detailed BGP route information */
d62a17ae 10981void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 10982 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 10983 afi_t afi, safi_t safi, json_object *json)
10984{
40381db7 10985 struct bgp_path_info *pi;
b54892e0 10986 const struct prefix *p;
d62a17ae 10987 struct peer *peer;
10988 struct listnode *node, *nnode;
06b9f471 10989 char buf1[RD_ADDRSTRLEN];
0291c246 10990 char prefix_str[BUFSIZ];
d62a17ae 10991 int count = 0;
10992 int best = 0;
10993 int suppress = 0;
c5f1e1b2
C
10994 int accept_own = 0;
10995 int route_filter_translated_v4 = 0;
10996 int route_filter_v4 = 0;
10997 int route_filter_translated_v6 = 0;
10998 int route_filter_v6 = 0;
10999 int llgr_stale = 0;
11000 int no_llgr = 0;
11001 int accept_own_nexthop = 0;
11002 int blackhole = 0;
d62a17ae 11003 int no_export = 0;
11004 int no_advertise = 0;
11005 int local_as = 0;
c5f1e1b2 11006 int no_peer = 0;
d62a17ae 11007 int first = 1;
11008 int has_valid_label = 0;
11009 mpls_label_t label = 0;
11010 json_object *json_adv_to = NULL;
9bedbb1e 11011
9bcb3eef
DS
11012 p = bgp_dest_get_prefix(dest);
11013 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11014
11015 if (has_valid_label)
9bcb3eef 11016 label = label_pton(&dest->local_label);
d62a17ae 11017
44c69747 11018 if (safi == SAFI_EVPN) {
d62a17ae 11019
44c69747 11020 if (!json) {
2dbe669b 11021 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11022 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11023 : "",
2dbe669b 11024 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11025 } else {
11026 json_object_string_add(json, "rd",
11027 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11028 "");
11029 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11030 }
11031 } else {
11032 if (!json) {
8228a9a7 11033 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
d62a17ae 11034 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11035 ? prefix_rd2str(prd, buf1,
11036 sizeof(buf1))
11037 : ""),
11038 safi == SAFI_MPLS_VPN ? ":" : "", p);
cd1964ff 11039
44c69747
LK
11040 } else
11041 json_object_string_add(json, "prefix",
11042 prefix2str(p, prefix_str, sizeof(prefix_str)));
11043 }
11044
11045 if (has_valid_label) {
11046 if (json)
11047 json_object_int_add(json, "localLabel", label);
11048 else
d62a17ae 11049 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11050 }
11051
11052 if (!json)
d62a17ae 11053 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11054 vty_out(vty, "not allocated\n");
718e3744 11055
9bcb3eef 11056 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11057 count++;
40381db7 11058 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11059 best = count;
4056a5f6 11060 if (bgp_path_suppressed(pi))
d62a17ae 11061 suppress = 1;
cee9c031 11062
40381db7 11063 if (pi->attr->community == NULL)
cee9c031
QY
11064 continue;
11065
11066 no_advertise += community_include(
40381db7
DS
11067 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11068 no_export += community_include(pi->attr->community,
cee9c031 11069 COMMUNITY_NO_EXPORT);
40381db7 11070 local_as += community_include(pi->attr->community,
cee9c031 11071 COMMUNITY_LOCAL_AS);
40381db7 11072 accept_own += community_include(pi->attr->community,
cee9c031
QY
11073 COMMUNITY_ACCEPT_OWN);
11074 route_filter_translated_v4 += community_include(
40381db7 11075 pi->attr->community,
cee9c031
QY
11076 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11077 route_filter_translated_v6 += community_include(
40381db7 11078 pi->attr->community,
cee9c031
QY
11079 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11080 route_filter_v4 += community_include(
40381db7 11081 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11082 route_filter_v6 += community_include(
40381db7
DS
11083 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11084 llgr_stale += community_include(pi->attr->community,
cee9c031 11085 COMMUNITY_LLGR_STALE);
40381db7 11086 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11087 COMMUNITY_NO_LLGR);
11088 accept_own_nexthop +=
40381db7 11089 community_include(pi->attr->community,
cee9c031 11090 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11091 blackhole += community_include(pi->attr->community,
cee9c031 11092 COMMUNITY_BLACKHOLE);
40381db7 11093 no_peer += community_include(pi->attr->community,
cee9c031 11094 COMMUNITY_NO_PEER);
d62a17ae 11095 }
718e3744 11096 }
718e3744 11097
d62a17ae 11098 if (!json) {
11099 vty_out(vty, "Paths: (%d available", count);
11100 if (best) {
11101 vty_out(vty, ", best #%d", best);
b84060bb
PG
11102 if (safi == SAFI_UNICAST) {
11103 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11104 vty_out(vty, ", table %s",
11105 VRF_DEFAULT_NAME);
11106 else
11107 vty_out(vty, ", vrf %s",
11108 bgp->name);
11109 }
d62a17ae 11110 } else
11111 vty_out(vty, ", no best path");
11112
c5f1e1b2
C
11113 if (accept_own)
11114 vty_out(vty,
11115 ", accept own local route exported and imported in different VRF");
11116 else if (route_filter_translated_v4)
11117 vty_out(vty,
11118 ", mark translated RTs for VPNv4 route filtering");
11119 else if (route_filter_v4)
11120 vty_out(vty,
11121 ", attach RT as-is for VPNv4 route filtering");
11122 else if (route_filter_translated_v6)
11123 vty_out(vty,
11124 ", mark translated RTs for VPNv6 route filtering");
11125 else if (route_filter_v6)
11126 vty_out(vty,
11127 ", attach RT as-is for VPNv6 route filtering");
11128 else if (llgr_stale)
11129 vty_out(vty,
11130 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11131 else if (no_llgr)
11132 vty_out(vty,
11133 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11134 else if (accept_own_nexthop)
11135 vty_out(vty,
11136 ", accept local nexthop");
11137 else if (blackhole)
11138 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11139 else if (no_export)
11140 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11141 else if (no_advertise)
11142 vty_out(vty, ", not advertised to any peer");
d62a17ae 11143 else if (local_as)
11144 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11145 else if (no_peer)
11146 vty_out(vty,
11147 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11148
11149 if (suppress)
11150 vty_out(vty,
11151 ", Advertisements suppressed by an aggregate.");
11152 vty_out(vty, ")\n");
11153 }
718e3744 11154
d62a17ae 11155 /* If we are not using addpath then we can display Advertised to and
11156 * that will
11157 * show what peers we advertised the bestpath to. If we are using
11158 * addpath
11159 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11160 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11161 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11162 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11163 if (json && !json_adv_to)
11164 json_adv_to = json_object_new_object();
11165
11166 route_vty_out_advertised_to(
11167 vty, peer, &first,
11168 " Advertised to non peer-group peers:\n ",
11169 json_adv_to);
11170 }
11171 }
11172
11173 if (json) {
11174 if (json_adv_to) {
11175 json_object_object_add(json, "advertisedTo",
11176 json_adv_to);
11177 }
11178 } else {
11179 if (first)
11180 vty_out(vty, " Not advertised to any peer");
11181 vty_out(vty, "\n");
11182 }
11183 }
718e3744 11184}
11185
44c69747 11186static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11187 struct bgp_dest *bgp_node, struct vty *vty,
11188 struct bgp *bgp, afi_t afi, safi_t safi,
11189 json_object *json, enum bgp_path_type pathtype,
11190 int *display)
44c69747
LK
11191{
11192 struct bgp_path_info *pi;
11193 int header = 1;
11194 char rdbuf[RD_ADDRSTRLEN];
11195 json_object *json_header = NULL;
11196 json_object *json_paths = NULL;
11197
9bcb3eef 11198 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
44c69747
LK
11199
11200 if (json && !json_paths) {
11201 /* Instantiate json_paths only if path is valid */
11202 json_paths = json_object_new_array();
11203 if (pfx_rd) {
11204 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11205 json_header = json_object_new_object();
11206 } else
11207 json_header = json;
11208 }
11209
11210 if (header) {
11211 route_vty_out_detail_header(
11212 vty, bgp, bgp_node, pfx_rd,
11213 AFI_IP, safi, json_header);
11214 header = 0;
11215 }
11216 (*display)++;
11217
11218 if (pathtype == BGP_PATH_SHOW_ALL
11219 || (pathtype == BGP_PATH_SHOW_BESTPATH
11220 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11221 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11222 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11223 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
11224 route_vty_out_detail(vty, bgp, bgp_node,
11225 pi, AFI_IP, safi,
11226 json_paths);
11227 }
11228
11229 if (json && json_paths) {
11230 json_object_object_add(json_header, "paths", json_paths);
11231
11232 if (pfx_rd)
11233 json_object_object_add(json, rdbuf, json_header);
11234 }
11235}
11236
718e3744 11237/* Display specified route of BGP table. */
d62a17ae 11238static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11239 struct bgp_table *rib, const char *ip_str,
11240 afi_t afi, safi_t safi,
11241 struct prefix_rd *prd, int prefix_check,
9f049418 11242 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11243{
11244 int ret;
d62a17ae 11245 int display = 0;
11246 struct prefix match;
9bcb3eef
DS
11247 struct bgp_dest *dest;
11248 struct bgp_dest *rm;
d62a17ae 11249 struct bgp_table *table;
11250 json_object *json = NULL;
11251 json_object *json_paths = NULL;
11252
11253 /* Check IP address argument. */
11254 ret = str2prefix(ip_str, &match);
11255 if (!ret) {
11256 vty_out(vty, "address is malformed\n");
11257 return CMD_WARNING;
11258 }
718e3744 11259
d62a17ae 11260 match.family = afi2family(afi);
b05a1c8b 11261
44c69747 11262 if (use_json)
d62a17ae 11263 json = json_object_new_object();
718e3744 11264
44c69747 11265 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11266 for (dest = bgp_table_top(rib); dest;
11267 dest = bgp_route_next(dest)) {
11268 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11269
9bcb3eef 11270 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11271 continue;
9bcb3eef 11272 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11273 if (!table)
ea47320b 11274 continue;
d62a17ae 11275
ea47320b
DL
11276 if ((rm = bgp_node_match(table, &match)) == NULL)
11277 continue;
d62a17ae 11278
9bcb3eef 11279 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11280 if (prefix_check
b54892e0 11281 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11282 bgp_dest_unlock_node(rm);
ea47320b
DL
11283 continue;
11284 }
d62a17ae 11285
9bcb3eef 11286 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11287 bgp, afi, safi, json, pathtype,
11288 &display);
44c69747 11289
9bcb3eef 11290 bgp_dest_unlock_node(rm);
44c69747
LK
11291 }
11292 } else if (safi == SAFI_EVPN) {
9bcb3eef 11293 struct bgp_dest *longest_pfx;
cded3b72 11294 bool is_exact_pfxlen_match = false;
44c69747 11295
9bcb3eef
DS
11296 for (dest = bgp_table_top(rib); dest;
11297 dest = bgp_route_next(dest)) {
11298 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11299
9bcb3eef 11300 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11301 continue;
9bcb3eef 11302 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11303 if (!table)
11304 continue;
11305
11306 longest_pfx = NULL;
cded3b72 11307 is_exact_pfxlen_match = false;
44c69747
LK
11308 /*
11309 * Search through all the prefixes for a match. The
11310 * pfx's are enumerated in ascending order of pfxlens.
11311 * So, the last pfx match is the longest match. Set
11312 * is_exact_pfxlen_match when we get exact pfxlen match
11313 */
11314 for (rm = bgp_table_top(table); rm;
11315 rm = bgp_route_next(rm)) {
b54892e0 11316 const struct prefix *rm_p =
9bcb3eef 11317 bgp_dest_get_prefix(rm);
44c69747
LK
11318 /*
11319 * Get prefixlen of the ip-prefix within type5
11320 * evpn route
11321 */
b54892e0
DS
11322 if (evpn_type5_prefix_match(rm_p, &match)
11323 && rm->info) {
44c69747
LK
11324 longest_pfx = rm;
11325 int type5_pfxlen =
b54892e0
DS
11326 bgp_evpn_get_type5_prefixlen(
11327 rm_p);
44c69747 11328 if (type5_pfxlen == match.prefixlen) {
cded3b72 11329 is_exact_pfxlen_match = true;
9bcb3eef 11330 bgp_dest_unlock_node(rm);
44c69747
LK
11331 break;
11332 }
d62a17ae 11333 }
11334 }
ea47320b 11335
44c69747
LK
11336 if (!longest_pfx)
11337 continue;
11338
11339 if (prefix_check && !is_exact_pfxlen_match)
11340 continue;
11341
11342 rm = longest_pfx;
9bcb3eef 11343 bgp_dest_lock_node(rm);
44c69747 11344
9bcb3eef 11345 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0
DS
11346 bgp, afi, safi, json, pathtype,
11347 &display);
44c69747 11348
9bcb3eef 11349 bgp_dest_unlock_node(rm);
d62a17ae 11350 }
98a9dbc7 11351 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11352 if (use_json)
11353 json_paths = json_object_new_array();
11354
63a0b7a9
PG
11355 display = bgp_flowspec_display_match_per_ip(afi, rib,
11356 &match, prefix_check,
11357 vty,
11358 use_json,
11359 json_paths);
d5f20468
SP
11360 if (use_json) {
11361 if (display)
11362 json_object_object_add(json, "paths",
11363 json_paths);
11364 else
11365 json_object_free(json_paths);
11366 }
d62a17ae 11367 } else {
9bcb3eef
DS
11368 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11369 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11370 if (!prefix_check
9bcb3eef
DS
11371 || dest_p->prefixlen == match.prefixlen) {
11372 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11373 safi, json, pathtype,
11374 &display);
d62a17ae 11375 }
11376
9bcb3eef 11377 bgp_dest_unlock_node(dest);
d62a17ae 11378 }
11379 }
e5eee9af 11380
d62a17ae 11381 if (use_json) {
996c9314 11382 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11383 json, JSON_C_TO_STRING_PRETTY |
11384 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11385 json_object_free(json);
11386 } else {
11387 if (!display) {
11388 vty_out(vty, "%% Network not in table\n");
11389 return CMD_WARNING;
11390 }
11391 }
b05a1c8b 11392
d62a17ae 11393 return CMD_SUCCESS;
718e3744 11394}
11395
fee0f4c6 11396/* Display specified route of Main RIB */
d62a17ae 11397static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11398 afi_t afi, safi_t safi, struct prefix_rd *prd,
11399 int prefix_check, enum bgp_path_type pathtype,
9f049418 11400 bool use_json)
d62a17ae 11401{
9b86009a 11402 if (!bgp) {
d62a17ae 11403 bgp = bgp_get_default();
9b86009a
RW
11404 if (!bgp) {
11405 if (!use_json)
11406 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11407 else
11408 vty_out(vty, "{}\n");
9b86009a
RW
11409 return CMD_WARNING;
11410 }
11411 }
d62a17ae 11412
11413 /* labeled-unicast routes live in the unicast table */
11414 if (safi == SAFI_LABELED_UNICAST)
11415 safi = SAFI_UNICAST;
11416
11417 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
11418 afi, safi, prd, prefix_check, pathtype,
11419 use_json);
11420}
11421
11422static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11423 struct cmd_token **argv, bool exact, afi_t afi,
11424 safi_t safi, bool uj)
d62a17ae 11425{
11426 struct lcommunity *lcom;
11427 struct buffer *b;
11428 int i;
11429 char *str;
11430 int first = 0;
96f3485c 11431 uint8_t show_flags = 0;
4f28b2b5 11432 int ret;
96f3485c
MK
11433
11434 if (uj)
11435 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11436
11437 b = buffer_new(1024);
11438 for (i = 0; i < argc; i++) {
11439 if (first)
11440 buffer_putc(b, ' ');
11441 else {
11442 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11443 first = 1;
11444 buffer_putstr(b, argv[i]->arg);
11445 }
11446 }
11447 }
11448 buffer_putc(b, '\0');
57d187bc 11449
d62a17ae 11450 str = buffer_getstr(b);
11451 buffer_free(b);
57d187bc 11452
d62a17ae 11453 lcom = lcommunity_str2com(str);
11454 XFREE(MTYPE_TMP, str);
11455 if (!lcom) {
11456 vty_out(vty, "%% Large-community malformed\n");
11457 return CMD_WARNING;
11458 }
57d187bc 11459
4f28b2b5 11460 ret = bgp_show(vty, bgp, afi, safi,
36a206db 11461 (exact ? bgp_show_type_lcommunity_exact
ae248832 11462 : bgp_show_type_lcommunity),
96f3485c 11463 lcom, show_flags);
4f28b2b5
DS
11464
11465 lcommunity_free(&lcom);
11466 return ret;
57d187bc
JS
11467}
11468
d62a17ae 11469static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11470 const char *lcom, bool exact, afi_t afi,
11471 safi_t safi, bool uj)
57d187bc 11472{
d62a17ae 11473 struct community_list *list;
96f3485c
MK
11474 uint8_t show_flags = 0;
11475
11476 if (uj)
11477 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11478
57d187bc 11479
e237b0d2 11480 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11481 LARGE_COMMUNITY_LIST_MASTER);
11482 if (list == NULL) {
11483 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11484 lcom);
11485 return CMD_WARNING;
11486 }
57d187bc 11487
36a206db 11488 return bgp_show(vty, bgp, afi, safi,
11489 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11490 : bgp_show_type_lcommunity_list),
96f3485c 11491 list, show_flags);
fee0f4c6 11492}
11493
52951b63
DS
11494DEFUN (show_ip_bgp_large_community_list,
11495 show_ip_bgp_large_community_list_cmd,
36a206db 11496 "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
11497 SHOW_STR
11498 IP_STR
11499 BGP_STR
11500 BGP_INSTANCE_HELP_STR
9bedbb1e 11501 BGP_AFI_HELP_STR
4dd6177e 11502 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11503 "Display routes matching the large-community-list\n"
11504 "large-community-list number\n"
11505 "large-community-list name\n"
36a206db 11506 "Exact match of the large-communities\n"
52951b63
DS
11507 JSON_STR)
11508{
d62a17ae 11509 afi_t afi = AFI_IP6;
11510 safi_t safi = SAFI_UNICAST;
11511 int idx = 0;
36a206db 11512 bool exact_match = 0;
4d678463 11513 struct bgp *bgp = NULL;
9f049418 11514 bool uj = use_json(argc, argv);
d62a17ae 11515
4d678463
KA
11516 if (uj)
11517 argc--;
11518
11519 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11520 &bgp, uj);
11521 if (!idx)
11522 return CMD_WARNING;
d62a17ae 11523
11524 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11525
11526 const char *clist_number_or_name = argv[++idx]->arg;
11527
11528 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11529 exact_match = 1;
11530
11531 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11532 exact_match, afi, safi, uj);
52951b63
DS
11533}
11534DEFUN (show_ip_bgp_large_community,
11535 show_ip_bgp_large_community_cmd,
36a206db 11536 "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
11537 SHOW_STR
11538 IP_STR
11539 BGP_STR
11540 BGP_INSTANCE_HELP_STR
9bedbb1e 11541 BGP_AFI_HELP_STR
4dd6177e 11542 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11543 "Display routes matching the large-communities\n"
11544 "List of large-community numbers\n"
36a206db 11545 "Exact match of the large-communities\n"
52951b63
DS
11546 JSON_STR)
11547{
d62a17ae 11548 afi_t afi = AFI_IP6;
11549 safi_t safi = SAFI_UNICAST;
11550 int idx = 0;
36a206db 11551 bool exact_match = 0;
4d678463 11552 struct bgp *bgp = NULL;
9f049418 11553 bool uj = use_json(argc, argv);
96f3485c 11554 uint8_t show_flags = 0;
d62a17ae 11555
96f3485c
MK
11556 if (uj) {
11557 argc--;
11558 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11559 }
4d678463 11560
96f3485c
MK
11561 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11562 &bgp, uj);
11563 if (!idx)
11564 return CMD_WARNING;
d62a17ae 11565
36a206db 11566 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11567 if (argv_find(argv, argc, "exact-match", &idx))
11568 exact_match = 1;
11569 return bgp_show_lcommunity(vty, bgp, argc, argv,
11570 exact_match, afi, safi, uj);
11571 } else
d62a17ae 11572 return bgp_show(vty, bgp, afi, safi,
96f3485c 11573 bgp_show_type_lcommunity_all, NULL, show_flags);
52951b63
DS
11574}
11575
71f1613a
DA
11576static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11577 safi_t safi, struct json_object *json_array);
d62a17ae 11578static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11579 safi_t safi, struct json_object *json);
e01ca200 11580
7b2ff250 11581
9ab0cf58
PG
11582DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11583 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11584 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11585 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11586{
11587 bool uj = use_json(argc, argv);
11588 struct bgp *bgp = NULL;
ec76a1d1
DA
11589 safi_t safi = SAFI_UNICAST;
11590 afi_t afi = AFI_IP6;
4265b261 11591 int idx = 0;
6c9d22e2
PG
11592 struct json_object *json_all = NULL;
11593 struct json_object *json_afi_safi = NULL;
4265b261
PG
11594
11595 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11596 &bgp, false);
71f1613a 11597 if (!idx)
4265b261 11598 return CMD_WARNING;
6c9d22e2 11599
4265b261 11600 if (uj)
6c9d22e2 11601 json_all = json_object_new_object();
4265b261 11602
9ab0cf58
PG
11603 FOREACH_AFI_SAFI (afi, safi) {
11604 /*
11605 * So limit output to those afi/safi pairs that
11606 * actually have something interesting in them
11607 */
11608 if (strmatch(get_afi_safi_str(afi, safi, true),
11609 "Unknown")) {
11610 continue;
11611 }
11612 if (uj) {
11613 json_afi_safi = json_object_new_array();
11614 json_object_object_add(
11615 json_all,
11616 get_afi_safi_str(afi, safi, true),
11617 json_afi_safi);
11618 } else {
11619 json_afi_safi = NULL;
6c9d22e2 11620 }
9ab0cf58
PG
11621
11622 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11623 }
6c9d22e2
PG
11624
11625 if (uj) {
9ab0cf58
PG
11626 vty_out(vty, "%s",
11627 json_object_to_json_string_ext(
11628 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11629 json_object_free(json_all);
4265b261 11630 }
6c9d22e2 11631
4265b261
PG
11632 return CMD_SUCCESS;
11633}
11634
7b2ff250 11635/* BGP route print out function without JSON */
14718643
PG
11636DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11637 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11638 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11639 SHOW_STR
11640 IP_STR
11641 BGP_STR
11642 BGP_INSTANCE_HELP_STR
11643 L2VPN_HELP_STR
11644 EVPN_HELP_STR
11645 "BGP RIB advertisement statistics\n"
11646 JSON_STR)
11647{
ec76a1d1
DA
11648 afi_t afi = AFI_IP6;
11649 safi_t safi = SAFI_UNICAST;
14718643
PG
11650 struct bgp *bgp = NULL;
11651 int idx = 0, ret;
11652 bool uj = use_json(argc, argv);
11653 struct json_object *json_afi_safi = NULL, *json = NULL;
11654
11655 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11656 &bgp, false);
11657 if (!idx)
11658 return CMD_WARNING;
11659
11660 if (uj)
11661 json_afi_safi = json_object_new_array();
11662 else
11663 json_afi_safi = NULL;
11664
11665 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11666
11667 if (uj) {
11668 json = json_object_new_object();
11669 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11670 json_afi_safi);
11671 vty_out(vty, "%s", json_object_to_json_string_ext(
11672 json, JSON_C_TO_STRING_PRETTY));
11673 json_object_free(json);
11674 }
11675 return ret;
11676}
11677
893cccd0 11678/* BGP route print out function without JSON */
9ab0cf58
PG
11679DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
11680 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11681 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11682 "]]\
893cccd0 11683 statistics [json]",
9ab0cf58
PG
11684 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11685 BGP_SAFI_WITH_LABEL_HELP_STR
11686 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 11687{
ec76a1d1
DA
11688 afi_t afi = AFI_IP6;
11689 safi_t safi = SAFI_UNICAST;
893cccd0
PG
11690 struct bgp *bgp = NULL;
11691 int idx = 0, ret;
11692 bool uj = use_json(argc, argv);
6c9d22e2 11693 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
11694
11695 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11696 &bgp, false);
11697 if (!idx)
11698 return CMD_WARNING;
6c9d22e2 11699
893cccd0 11700 if (uj)
6c9d22e2
PG
11701 json_afi_safi = json_object_new_array();
11702 else
11703 json_afi_safi = NULL;
11704
11705 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
11706
11707 if (uj) {
11708 json = json_object_new_object();
11709 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
11710 json_afi_safi);
9ab0cf58
PG
11711 vty_out(vty, "%s",
11712 json_object_to_json_string_ext(
11713 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
11714 json_object_free(json);
11715 }
11716 return ret;
893cccd0 11717}
7b2ff250
DW
11718
11719/* BGP route print out function without JSON */
96f3485c 11720DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
11721 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
11722 " [" BGP_SAFI_WITH_LABEL_CMD_STR
11723 "]]\
96f3485c 11724 <[all$all] dampening <parameters>\
7b2ff250
DW
11725 |route-map WORD\
11726 |prefix-list WORD\
11727 |filter-list WORD\
7b2ff250
DW
11728 |community-list <(1-500)|WORD> [exact-match]\
11729 |A.B.C.D/M longer-prefixes\
11730 |X:X::X:X/M longer-prefixes\
893cccd0 11731 >",
9ab0cf58
PG
11732 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
11733 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11734 "Display the entries for all address families\n"
9ab0cf58
PG
11735 "Display detailed information about dampening\n"
11736 "Display detail of configured dampening parameters\n"
11737 "Display routes matching the route-map\n"
11738 "A route-map to match on\n"
11739 "Display routes conforming to the prefix-list\n"
11740 "Prefix-list name\n"
11741 "Display routes conforming to the filter-list\n"
11742 "Regular expression access list name\n"
11743 "Display routes matching the community-list\n"
11744 "community-list number\n"
11745 "community-list name\n"
11746 "Exact match of the communities\n"
11747 "IPv4 prefix\n"
11748 "Display route and more specific routes\n"
11749 "IPv6 prefix\n"
11750 "Display route and more specific routes\n")
718e3744 11751{
d62a17ae 11752 afi_t afi = AFI_IP6;
11753 safi_t safi = SAFI_UNICAST;
11754 int exact_match = 0;
d62a17ae 11755 struct bgp *bgp = NULL;
11756 int idx = 0;
96f3485c
MK
11757 uint8_t show_flags = 0;
11758
11759 /* [<ipv4|ipv6> [all]] */
11760 if (all) {
11761 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11762 if (argv_find(argv, argc, "ipv4", &idx))
11763 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11764
11765 if (argv_find(argv, argc, "ipv6", &idx))
11766 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11767 }
d62a17ae 11768
11769 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11770 &bgp, false);
d62a17ae 11771 if (!idx)
11772 return CMD_WARNING;
11773
d62a17ae 11774 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 11775 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
11776 return bgp_show_dampening_parameters(vty, afi, safi,
11777 show_flags);
d62a17ae 11778 }
c016b6c7 11779
d62a17ae 11780 if (argv_find(argv, argc, "prefix-list", &idx))
11781 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
11782 safi, bgp_show_type_prefix_list);
11783
11784 if (argv_find(argv, argc, "filter-list", &idx))
11785 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
11786 safi, bgp_show_type_filter_list);
11787
d62a17ae 11788 if (argv_find(argv, argc, "route-map", &idx))
11789 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
11790 safi, bgp_show_type_route_map);
11791
d62a17ae 11792 if (argv_find(argv, argc, "community-list", &idx)) {
11793 const char *clist_number_or_name = argv[++idx]->arg;
11794 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11795 exact_match = 1;
11796 return bgp_show_community_list(vty, bgp, clist_number_or_name,
11797 exact_match, afi, safi);
11798 }
11799 /* prefix-longer */
11800 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
11801 || argv_find(argv, argc, "X:X::X:X/M", &idx))
11802 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
11803 safi,
11804 bgp_show_type_prefix_longer);
11805
7b2ff250
DW
11806 return CMD_WARNING;
11807}
11808
11809/* BGP route print out function with JSON */
ae248832 11810DEFPY (show_ip_bgp_json,
7b2ff250
DW
11811 show_ip_bgp_json_cmd,
11812 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
96f3485c 11813 [all$all]\
cf4898bc
QY
11814 [cidr-only\
11815 |dampening <flap-statistics|dampened-paths>\
11816 |community [AA:NN|local-AS|no-advertise|no-export\
11817 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
11818 |accept-own|accept-own-nexthop|route-filter-v6\
11819 |route-filter-v4|route-filter-translated-v6\
11820 |route-filter-translated-v4] [exact-match]\
ae248832 11821 ] [json$uj | wide$wide]",
7b2ff250
DW
11822 SHOW_STR
11823 IP_STR
11824 BGP_STR
11825 BGP_INSTANCE_HELP_STR
11826 BGP_AFI_HELP_STR
11827 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 11828 "Display the entries for all address families\n"
7b2ff250
DW
11829 "Display only routes with non-natural netmasks\n"
11830 "Display detailed information about dampening\n"
11831 "Display flap statistics of routes\n"
11832 "Display paths suppressed due to dampening\n"
11833 "Display routes matching the communities\n"
d0086e8e
AD
11834 COMMUNITY_AANN_STR
11835 "Do not send outside local AS (well-known community)\n"
11836 "Do not advertise to any peer (well-known community)\n"
11837 "Do not export to next AS (well-known community)\n"
11838 "Graceful shutdown (well-known community)\n"
cf4898bc
QY
11839 "Do not export to any peer (well-known community)\n"
11840 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
11841 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
11842 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
11843 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
11844 "Should accept VPN route with local nexthop (well-known community)\n"
11845 "RT VPNv6 route filtering (well-known community)\n"
11846 "RT VPNv4 route filtering (well-known community)\n"
11847 "RT translated VPNv6 route filtering (well-known community)\n"
11848 "RT translated VPNv4 route filtering (well-known community)\n"
d0086e8e 11849 "Exact match of the communities\n"
ae248832
MK
11850 JSON_STR
11851 "Increase table width for longer prefixes\n")
7b2ff250
DW
11852{
11853 afi_t afi = AFI_IP6;
11854 safi_t safi = SAFI_UNICAST;
11855 enum bgp_show_type sh_type = bgp_show_type_normal;
11856 struct bgp *bgp = NULL;
11857 int idx = 0;
d0086e8e 11858 int exact_match = 0;
96f3485c
MK
11859 char *community = NULL;
11860 bool first = true;
11861 uint8_t show_flags = 0;
9f049418 11862
96f3485c
MK
11863
11864 if (uj) {
9f049418 11865 argc--;
96f3485c
MK
11866 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11867 }
11868
11869 /* [<ipv4|ipv6> [all]] */
11870 if (all) {
11871 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
11872
11873 if (argv_find(argv, argc, "ipv4", &idx))
11874 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
11875
11876 if (argv_find(argv, argc, "ipv6", &idx))
11877 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
11878 }
11879
11880 if (wide)
11881 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
11882
11883 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 11884 &bgp, uj);
7b2ff250
DW
11885 if (!idx)
11886 return CMD_WARNING;
11887
7b2ff250 11888 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 11889 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
11890
11891 if (argv_find(argv, argc, "dampening", &idx)) {
11892 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 11893 sh_type = bgp_show_type_dampend_paths;
7b2ff250 11894 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 11895 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
11896 }
11897
11898 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 11899 char *maybecomm = NULL;
d0086e8e 11900
79bc257a
RW
11901 if (idx + 1 < argc) {
11902 if (argv[idx + 1]->type == VARIABLE_TKN)
11903 maybecomm = argv[idx + 1]->arg;
11904 else
11905 maybecomm = argv[idx + 1]->text;
11906 }
11907
cf4898bc
QY
11908 if (maybecomm && !strmatch(maybecomm, "json")
11909 && !strmatch(maybecomm, "exact-match"))
11910 community = maybecomm;
d0086e8e 11911
cf4898bc
QY
11912 if (argv_find(argv, argc, "exact-match", &idx))
11913 exact_match = 1;
d0086e8e 11914
96f3485c
MK
11915 if (!community)
11916 sh_type = bgp_show_type_community_all;
11917 }
11918
11919 if (!all) {
11920 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
11921 if (community)
11922 return bgp_show_community(vty, bgp, community,
96f3485c
MK
11923 exact_match, afi, safi,
11924 show_flags);
cf4898bc 11925 else
96f3485c
MK
11926 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
11927 show_flags);
11928 } else {
11929 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
11930 * AFI_IP6 */
11931
11932 if (uj)
11933 vty_out(vty, "{\n");
11934
11935 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11936 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
11937 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
11938 ? AFI_IP
11939 : AFI_IP6;
11940 FOREACH_SAFI (safi) {
96f3485c
MK
11941 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11942 continue;
11943
11944 if (uj) {
11945 if (first)
11946 first = false;
11947 else
11948 vty_out(vty, ",\n");
11949 vty_out(vty, "\"%s\":{\n",
11950 get_afi_safi_str(afi, safi,
11951 true));
11952 } else
11953 vty_out(vty,
11954 "\nFor address family: %s\n",
11955 get_afi_safi_str(afi, safi,
11956 false));
11957
11958 if (community)
11959 bgp_show_community(vty, bgp, community,
11960 exact_match, afi,
11961 safi, show_flags);
11962 else
11963 bgp_show(vty, bgp, afi, safi, sh_type,
11964 NULL, show_flags);
11965 if (uj)
11966 vty_out(vty, "}\n");
11967 }
11968 } else {
11969 /* show <ip> bgp all: for each AFI and SAFI*/
11970 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
11971 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
11972 continue;
11973
11974 if (uj) {
11975 if (first)
11976 first = false;
11977 else
11978 vty_out(vty, ",\n");
d0086e8e 11979
96f3485c
MK
11980 vty_out(vty, "\"%s\":{\n",
11981 get_afi_safi_str(afi, safi,
11982 true));
11983 } else
11984 vty_out(vty,
11985 "\nFor address family: %s\n",
11986 get_afi_safi_str(afi, safi,
11987 false));
11988
11989 if (community)
11990 bgp_show_community(vty, bgp, community,
11991 exact_match, afi,
11992 safi, show_flags);
11993 else
11994 bgp_show(vty, bgp, afi, safi, sh_type,
11995 NULL, show_flags);
11996 if (uj)
11997 vty_out(vty, "}\n");
11998 }
11999 }
12000 if (uj)
12001 vty_out(vty, "}\n");
12002 }
12003 return CMD_SUCCESS;
a636c635 12004}
47fc97cc 12005
718e3744 12006DEFUN (show_ip_bgp_route,
12007 show_ip_bgp_route_cmd,
3efd0893 12008 "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 12009 SHOW_STR
12010 IP_STR
12011 BGP_STR
a636c635 12012 BGP_INSTANCE_HELP_STR
4f280b15 12013 BGP_AFI_HELP_STR
4dd6177e 12014 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12015 "Network in the BGP routing table to display\n"
0c7b1b01 12016 "IPv4 prefix\n"
8c3deaae 12017 "Network in the BGP routing table to display\n"
0c7b1b01 12018 "IPv6 prefix\n"
4092b06c 12019 "Display only the bestpath\n"
b05a1c8b 12020 "Display only multipaths\n"
9973d184 12021 JSON_STR)
4092b06c 12022{
d62a17ae 12023 int prefix_check = 0;
ae19d7dd 12024
d62a17ae 12025 afi_t afi = AFI_IP6;
12026 safi_t safi = SAFI_UNICAST;
12027 char *prefix = NULL;
12028 struct bgp *bgp = NULL;
12029 enum bgp_path_type path_type;
9f049418 12030 bool uj = use_json(argc, argv);
b05a1c8b 12031
d62a17ae 12032 int idx = 0;
ae19d7dd 12033
d62a17ae 12034 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12035 &bgp, uj);
d62a17ae 12036 if (!idx)
12037 return CMD_WARNING;
c41247f5 12038
d62a17ae 12039 if (!bgp) {
12040 vty_out(vty,
12041 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12042 return CMD_WARNING;
12043 }
a636c635 12044
d62a17ae 12045 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12046 if (argv_find(argv, argc, "A.B.C.D", &idx)
12047 || argv_find(argv, argc, "X:X::X:X", &idx))
12048 prefix_check = 0;
12049 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12050 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12051 prefix_check = 1;
12052
12053 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12054 && afi != AFI_IP6) {
12055 vty_out(vty,
12056 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12057 return CMD_WARNING;
12058 }
12059 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12060 && afi != AFI_IP) {
12061 vty_out(vty,
12062 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12063 return CMD_WARNING;
12064 }
12065
12066 prefix = argv[idx]->arg;
12067
12068 /* [<bestpath|multipath>] */
12069 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12070 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12071 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12072 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12073 else
360660c6 12074 path_type = BGP_PATH_SHOW_ALL;
a636c635 12075
d62a17ae 12076 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
12077 path_type, uj);
4092b06c
DS
12078}
12079
8c3deaae
QY
12080DEFUN (show_ip_bgp_regexp,
12081 show_ip_bgp_regexp_cmd,
3e5b31b3 12082 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12083 SHOW_STR
12084 IP_STR
12085 BGP_STR
b00b230a 12086 BGP_INSTANCE_HELP_STR
4f280b15 12087 BGP_AFI_HELP_STR
4dd6177e 12088 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12089 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12090 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12091 JSON_STR)
8c3deaae 12092{
d62a17ae 12093 afi_t afi = AFI_IP6;
12094 safi_t safi = SAFI_UNICAST;
12095 struct bgp *bgp = NULL;
3e5b31b3
DA
12096 bool uj = use_json(argc, argv);
12097 char *regstr = NULL;
8c3deaae 12098
d62a17ae 12099 int idx = 0;
12100 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12101 &bgp, false);
d62a17ae 12102 if (!idx)
12103 return CMD_WARNING;
8c3deaae 12104
d62a17ae 12105 // get index of regex
3e5b31b3
DA
12106 if (argv_find(argv, argc, "REGEX", &idx))
12107 regstr = argv[idx]->arg;
8c3deaae 12108
5f71d11c 12109 assert(regstr);
3e5b31b3
DA
12110 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12111 bgp_show_type_regexp, uj);
8c3deaae
QY
12112}
12113
ae248832 12114DEFPY (show_ip_bgp_instance_all,
a636c635 12115 show_ip_bgp_instance_all_cmd,
ae248832 12116 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12117 SHOW_STR
a636c635 12118 IP_STR
4092b06c 12119 BGP_STR
a636c635 12120 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12121 BGP_AFI_HELP_STR
4dd6177e 12122 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12123 JSON_STR
12124 "Increase table width for longer prefixes\n")
4092b06c 12125{
d62a17ae 12126 afi_t afi = AFI_IP;
12127 safi_t safi = SAFI_UNICAST;
12128 struct bgp *bgp = NULL;
d62a17ae 12129 int idx = 0;
96f3485c 12130 uint8_t show_flags = 0;
ae19d7dd 12131
96f3485c 12132 if (uj) {
d62a17ae 12133 argc--;
96f3485c
MK
12134 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12135 }
12136
12137 if (wide)
12138 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12139
9f049418
DS
12140 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12141 &bgp, uj);
12142 if (!idx)
12143 return CMD_WARNING;
12144
96f3485c 12145 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12146 return CMD_SUCCESS;
e3e29b32
LB
12147}
12148
a4d82a8a 12149static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12150 afi_t afi, safi_t safi, enum bgp_show_type type,
12151 bool use_json)
718e3744 12152{
d62a17ae 12153 regex_t *regex;
12154 int rc;
96f3485c
MK
12155 uint8_t show_flags = 0;
12156
12157 if (use_json)
12158 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12159
c3900853 12160 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12161 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12162 regstr);
12163 return CMD_WARNING_CONFIG_FAILED;
12164 }
12165
d62a17ae 12166 regex = bgp_regcomp(regstr);
12167 if (!regex) {
12168 vty_out(vty, "Can't compile regexp %s\n", regstr);
12169 return CMD_WARNING;
12170 }
a636c635 12171
96f3485c 12172 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags);
d62a17ae 12173 bgp_regex_free(regex);
12174 return rc;
e3e29b32
LB
12175}
12176
d62a17ae 12177static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12178 const char *prefix_list_str, afi_t afi,
12179 safi_t safi, enum bgp_show_type type)
e3e29b32 12180{
d62a17ae 12181 struct prefix_list *plist;
96f3485c 12182 uint8_t show_flags = 0;
718e3744 12183
d62a17ae 12184 plist = prefix_list_lookup(afi, prefix_list_str);
12185 if (plist == NULL) {
12186 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12187 prefix_list_str);
12188 return CMD_WARNING;
12189 }
718e3744 12190
96f3485c 12191 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags);
4092b06c
DS
12192}
12193
d62a17ae 12194static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12195 const char *filter, afi_t afi, safi_t safi,
12196 enum bgp_show_type type)
4092b06c 12197{
d62a17ae 12198 struct as_list *as_list;
96f3485c 12199 uint8_t show_flags = 0;
718e3744 12200
d62a17ae 12201 as_list = as_list_lookup(filter);
12202 if (as_list == NULL) {
12203 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12204 filter);
12205 return CMD_WARNING;
12206 }
a636c635 12207
96f3485c 12208 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags);
718e3744 12209}
12210
d62a17ae 12211static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12212 const char *rmap_str, afi_t afi, safi_t safi,
12213 enum bgp_show_type type)
718e3744 12214{
d62a17ae 12215 struct route_map *rmap;
96f3485c 12216 uint8_t show_flags = 0;
bb46e94f 12217
d62a17ae 12218 rmap = route_map_lookup_by_name(rmap_str);
12219 if (!rmap) {
12220 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12221 return CMD_WARNING;
12222 }
12223
96f3485c 12224 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags);
d62a17ae 12225}
12226
7f323236
DW
12227static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12228 const char *comstr, int exact, afi_t afi,
96f3485c 12229 safi_t safi, uint8_t show_flags)
d62a17ae 12230{
12231 struct community *com;
d62a17ae 12232 int ret = 0;
12233
7f323236 12234 com = community_str2com(comstr);
d62a17ae 12235 if (!com) {
7f323236 12236 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12237 return CMD_WARNING;
12238 }
12239
12240 ret = bgp_show(vty, bgp, afi, safi,
12241 (exact ? bgp_show_type_community_exact
12242 : bgp_show_type_community),
96f3485c 12243 com, show_flags);
3c1f53de 12244 community_free(&com);
46c3ce83 12245
d62a17ae 12246 return ret;
718e3744 12247}
12248
d62a17ae 12249static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12250 const char *com, int exact, afi_t afi,
12251 safi_t safi)
50ef26d4 12252{
d62a17ae 12253 struct community_list *list;
96f3485c 12254 uint8_t show_flags = 0;
50ef26d4 12255
e237b0d2 12256 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12257 if (list == NULL) {
12258 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12259 return CMD_WARNING;
12260 }
718e3744 12261
d62a17ae 12262 return bgp_show(vty, bgp, afi, safi,
12263 (exact ? bgp_show_type_community_list_exact
12264 : bgp_show_type_community_list),
96f3485c 12265 list, show_flags);
50ef26d4 12266}
12267
d62a17ae 12268static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12269 const char *prefix, afi_t afi, safi_t safi,
12270 enum bgp_show_type type)
718e3744 12271{
d62a17ae 12272 int ret;
12273 struct prefix *p;
96f3485c 12274 uint8_t show_flags = 0;
47fc97cc 12275
d62a17ae 12276 p = prefix_new();
95cbbd2a 12277
d62a17ae 12278 ret = str2prefix(prefix, p);
12279 if (!ret) {
12280 vty_out(vty, "%% Malformed Prefix\n");
12281 return CMD_WARNING;
12282 }
47e9b292 12283
96f3485c 12284 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags);
63265b5c 12285 prefix_free(&p);
d62a17ae 12286 return ret;
12287}
12288
d62a17ae 12289enum bgp_stats {
12290 BGP_STATS_MAXBITLEN = 0,
12291 BGP_STATS_RIB,
12292 BGP_STATS_PREFIXES,
12293 BGP_STATS_TOTPLEN,
12294 BGP_STATS_UNAGGREGATEABLE,
12295 BGP_STATS_MAX_AGGREGATEABLE,
12296 BGP_STATS_AGGREGATES,
12297 BGP_STATS_SPACE,
12298 BGP_STATS_ASPATH_COUNT,
12299 BGP_STATS_ASPATH_MAXHOPS,
12300 BGP_STATS_ASPATH_TOTHOPS,
12301 BGP_STATS_ASPATH_MAXSIZE,
12302 BGP_STATS_ASPATH_TOTSIZE,
12303 BGP_STATS_ASN_HIGHEST,
12304 BGP_STATS_MAX,
a636c635 12305};
2815e61f 12306
9ab0cf58 12307#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12308#define TABLE_STATS_IDX_JSON 1
12309
12310static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12311 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12312 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12313 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12314 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12315 "unaggregateablePrefixes"},
12316 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12317 "maximumAggregateablePrefixes"},
12318 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12319 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12320 [BGP_STATS_SPACE] = {"Address space advertised",
12321 "addressSpaceAdvertised"},
9ab0cf58
PG
12322 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12323 "advertisementsWithPaths"},
12324 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12325 "longestAsPath"},
12326 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12327 "largestAsPath"},
12328 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12329 "averageAsPathLengthHops"},
12330 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12331 "averageAsPathSizeBytes"},
12332 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12333 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12334};
2815e61f 12335
d62a17ae 12336struct bgp_table_stats {
12337 struct bgp_table *table;
12338 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12339 double total_space;
ff7924f6
PJ
12340};
12341
9bcb3eef 12342static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12343 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12344{
9bcb3eef 12345 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12346 struct bgp_path_info *pi;
b54892e0 12347 const struct prefix *rn_p;
d62a17ae 12348
9bcb3eef 12349 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12350 return;
d62a17ae 12351
9bcb3eef 12352 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12353 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12354 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12355
9c14ec72 12356 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12357 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12358 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12359
9bcb3eef 12360 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12361 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12362 /* announced address space */
12363 if (space)
b54892e0 12364 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12365 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12366 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12367
9c14ec72 12368
9bcb3eef 12369 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12370 ts->counts[BGP_STATS_RIB]++;
12371
05864da7
DS
12372 if (CHECK_FLAG(pi->attr->flag,
12373 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12374 ts->counts[BGP_STATS_AGGREGATES]++;
12375
12376 /* as-path stats */
05864da7 12377 if (pi->attr->aspath) {
9c14ec72
RW
12378 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12379 unsigned int size = aspath_size(pi->attr->aspath);
12380 as_t highest = aspath_highest(pi->attr->aspath);
12381
12382 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12383
12384 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12385 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12386
12387 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12388 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12389
12390 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12391 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12392 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12393 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12394 }
12395 }
12396}
12397
12398static int bgp_table_stats_walker(struct thread *t)
12399{
9bcb3eef
DS
12400 struct bgp_dest *dest, *ndest;
12401 struct bgp_dest *top;
9c14ec72
RW
12402 struct bgp_table_stats *ts = THREAD_ARG(t);
12403 unsigned int space = 0;
12404
12405 if (!(top = bgp_table_top(ts->table)))
12406 return 0;
12407
12408 switch (ts->table->afi) {
12409 case AFI_IP:
12410 space = IPV4_MAX_BITLEN;
12411 break;
12412 case AFI_IP6:
12413 space = IPV6_MAX_BITLEN;
12414 break;
3ba7b4af
TA
12415 case AFI_L2VPN:
12416 space = EVPN_ROUTE_PREFIXLEN;
12417 break;
9c14ec72
RW
12418 default:
12419 return 0;
12420 }
12421
12422 ts->counts[BGP_STATS_MAXBITLEN] = space;
12423
9bcb3eef 12424 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12425 if (ts->table->safi == SAFI_MPLS_VPN
12426 || ts->table->safi == SAFI_ENCAP
12427 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12428 struct bgp_table *table;
12429
9bcb3eef 12430 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12431 if (!table)
12432 continue;
12433
12434 top = bgp_table_top(table);
9bcb3eef
DS
12435 for (ndest = bgp_table_top(table); ndest;
12436 ndest = bgp_route_next(ndest))
12437 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12438 } else {
9bcb3eef 12439 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12440 }
12441 }
9c14ec72 12442
d62a17ae 12443 return 0;
2815e61f 12444}
ff7924f6 12445
71f1613a
DA
12446static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12447 struct json_object *json_array)
12448{
12449 struct listnode *node, *nnode;
12450 struct bgp *bgp;
12451
12452 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12453 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12454}
12455
12456static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12457 safi_t safi, struct json_object *json_array)
2815e61f 12458{
d62a17ae 12459 struct bgp_table_stats ts;
12460 unsigned int i;
893cccd0
PG
12461 int ret = CMD_SUCCESS;
12462 char temp_buf[20];
6c9d22e2
PG
12463 struct json_object *json = NULL;
12464
12465 if (json_array)
12466 json = json_object_new_object();
019386c2 12467
d62a17ae 12468 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12469 char warning_msg[50];
12470
12471 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12472 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12473 safi);
6c9d22e2
PG
12474
12475 if (!json)
893cccd0
PG
12476 vty_out(vty, "%s\n", warning_msg);
12477 else
9ab0cf58 12478 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12479
893cccd0
PG
12480 ret = CMD_WARNING;
12481 goto end_table_stats;
d62a17ae 12482 }
019386c2 12483
893cccd0 12484 if (!json)
5290ceab
DA
12485 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12486 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12487 else
12488 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12489
d62a17ae 12490 /* labeled-unicast routes live in the unicast table */
12491 if (safi == SAFI_LABELED_UNICAST)
12492 safi = SAFI_UNICAST;
019386c2 12493
d62a17ae 12494 memset(&ts, 0, sizeof(ts));
12495 ts.table = bgp->rib[afi][safi];
12496 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12497
d62a17ae 12498 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12499 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12500 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12501 continue;
12502
12503 switch (i) {
d62a17ae 12504 case BGP_STATS_ASPATH_TOTHOPS:
12505 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12506 if (!json) {
9ab0cf58
PG
12507 snprintf(
12508 temp_buf, sizeof(temp_buf), "%12.2f",
12509 ts.counts[i]
12510 ? (float)ts.counts[i]
12511 / (float)ts.counts
12512 [BGP_STATS_ASPATH_COUNT]
12513 : 0);
893cccd0 12514 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12515 table_stats_strs[i]
12516 [TABLE_STATS_IDX_VTY],
893cccd0 12517 temp_buf);
9ab0cf58
PG
12518 } else {
12519 json_object_double_add(
12520 json,
12521 table_stats_strs[i]
12522 [TABLE_STATS_IDX_JSON],
12523 ts.counts[i]
12524 ? (double)ts.counts[i]
12525 / (double)ts.counts
d62a17ae 12526 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12527 : 0);
12528 }
d62a17ae 12529 break;
12530 case BGP_STATS_TOTPLEN:
6c9d22e2 12531 if (!json) {
9ab0cf58
PG
12532 snprintf(
12533 temp_buf, sizeof(temp_buf), "%12.2f",
12534 ts.counts[i]
12535 ? (float)ts.counts[i]
12536 / (float)ts.counts
12537 [BGP_STATS_PREFIXES]
12538 : 0);
893cccd0 12539 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12540 table_stats_strs[i]
12541 [TABLE_STATS_IDX_VTY],
893cccd0 12542 temp_buf);
9ab0cf58
PG
12543 } else {
12544 json_object_double_add(
12545 json,
12546 table_stats_strs[i]
12547 [TABLE_STATS_IDX_JSON],
12548 ts.counts[i]
12549 ? (double)ts.counts[i]
12550 / (double)ts.counts
d62a17ae 12551 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12552 : 0);
12553 }
d62a17ae 12554 break;
12555 case BGP_STATS_SPACE:
6c9d22e2
PG
12556 if (!json) {
12557 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12558 ts.total_space);
893cccd0 12559 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12560 table_stats_strs[i]
12561 [TABLE_STATS_IDX_VTY],
893cccd0 12562 temp_buf);
9ab0cf58
PG
12563 } else {
12564 json_object_double_add(
12565 json,
12566 table_stats_strs[i]
12567 [TABLE_STATS_IDX_JSON],
12568 (double)ts.total_space);
12569 }
8d0ab76d 12570 if (afi == AFI_IP6) {
6c9d22e2
PG
12571 if (!json) {
12572 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12573 "%12g",
12574 ts.total_space
12575 * pow(2.0, -128 + 32));
6c9d22e2
PG
12576 vty_out(vty, "%30s: %s\n",
12577 "/32 equivalent %s\n",
12578 temp_buf);
9ab0cf58
PG
12579 } else {
12580 json_object_double_add(
12581 json, "/32equivalent",
12582 (double)(ts.total_space
12583 * pow(2.0,
12584 -128 + 32)));
12585 }
6c9d22e2
PG
12586 if (!json) {
12587 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12588 "%12g",
12589 ts.total_space
12590 * pow(2.0, -128 + 48));
6c9d22e2
PG
12591 vty_out(vty, "%30s: %s\n",
12592 "/48 equivalent %s\n",
12593 temp_buf);
9ab0cf58
PG
12594 } else {
12595 json_object_double_add(
12596 json, "/48equivalent",
12597 (double)(ts.total_space
12598 * pow(2.0,
12599 -128 + 48)));
12600 }
8d0ab76d 12601 } else {
6c9d22e2
PG
12602 if (!json) {
12603 snprintf(temp_buf, sizeof(temp_buf),
12604 "%12.2f",
9ab0cf58
PG
12605 ts.total_space * 100.
12606 * pow(2.0, -32));
6c9d22e2 12607 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12608 "% announced ", temp_buf);
12609 } else {
12610 json_object_double_add(
12611 json, "%announced",
12612 (double)(ts.total_space * 100.
12613 * pow(2.0, -32)));
12614 }
6c9d22e2
PG
12615 if (!json) {
12616 snprintf(temp_buf, sizeof(temp_buf),
12617 "%12.2f",
9ab0cf58
PG
12618 ts.total_space
12619 * pow(2.0, -32 + 8));
6c9d22e2
PG
12620 vty_out(vty, "%30s: %s\n",
12621 "/8 equivalent ", temp_buf);
9ab0cf58
PG
12622 } else {
12623 json_object_double_add(
12624 json, "/8equivalent",
12625 (double)(ts.total_space
12626 * pow(2.0, -32 + 8)));
12627 }
6c9d22e2
PG
12628 if (!json) {
12629 snprintf(temp_buf, sizeof(temp_buf),
12630 "%12.2f",
9ab0cf58
PG
12631 ts.total_space
12632 * pow(2.0, -32 + 24));
6c9d22e2 12633 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
12634 "/24 equivalent ", temp_buf);
12635 } else {
12636 json_object_double_add(
12637 json, "/24equivalent",
12638 (double)(ts.total_space
12639 * pow(2.0, -32 + 24)));
12640 }
8d0ab76d 12641 }
d62a17ae 12642 break;
12643 default:
6c9d22e2
PG
12644 if (!json) {
12645 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
12646 ts.counts[i]);
893cccd0 12647 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12648 table_stats_strs[i]
12649 [TABLE_STATS_IDX_VTY],
12650 temp_buf);
12651 } else {
12652 json_object_int_add(
12653 json,
12654 table_stats_strs[i]
12655 [TABLE_STATS_IDX_JSON],
12656 ts.counts[i]);
12657 }
d62a17ae 12658 }
893cccd0
PG
12659 if (!json)
12660 vty_out(vty, "\n");
d62a17ae 12661 }
9ab0cf58 12662end_table_stats:
6c9d22e2
PG
12663 if (json)
12664 json_object_array_add(json_array, json);
893cccd0 12665 return ret;
d62a17ae 12666}
12667
71f1613a
DA
12668static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
12669 safi_t safi, struct json_object *json_array)
12670{
12671 if (!bgp) {
12672 bgp_table_stats_all(vty, afi, safi, json_array);
12673 return CMD_SUCCESS;
12674 }
12675
12676 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12677}
12678
d62a17ae 12679enum bgp_pcounts {
12680 PCOUNT_ADJ_IN = 0,
12681 PCOUNT_DAMPED,
12682 PCOUNT_REMOVED,
12683 PCOUNT_HISTORY,
12684 PCOUNT_STALE,
12685 PCOUNT_VALID,
12686 PCOUNT_ALL,
12687 PCOUNT_COUNTED,
7e3d9632 12688 PCOUNT_BPATH_SELECTED,
d62a17ae 12689 PCOUNT_PFCNT, /* the figure we display to users */
12690 PCOUNT_MAX,
a636c635 12691};
718e3744 12692
2b64873d 12693static const char *const pcount_strs[] = {
9d303b37
DL
12694 [PCOUNT_ADJ_IN] = "Adj-in",
12695 [PCOUNT_DAMPED] = "Damped",
12696 [PCOUNT_REMOVED] = "Removed",
12697 [PCOUNT_HISTORY] = "History",
12698 [PCOUNT_STALE] = "Stale",
12699 [PCOUNT_VALID] = "Valid",
12700 [PCOUNT_ALL] = "All RIB",
12701 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 12702 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
12703 [PCOUNT_PFCNT] = "Useable",
12704 [PCOUNT_MAX] = NULL,
a636c635 12705};
718e3744 12706
d62a17ae 12707struct peer_pcounts {
12708 unsigned int count[PCOUNT_MAX];
12709 const struct peer *peer;
12710 const struct bgp_table *table;
54317cba 12711 safi_t safi;
a636c635 12712};
47fc97cc 12713
9bcb3eef 12714static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 12715{
54317cba
JW
12716 const struct bgp_adj_in *ain;
12717 const struct bgp_path_info *pi;
d62a17ae 12718 const struct peer *peer = pc->peer;
12719
54317cba
JW
12720 for (ain = rn->adj_in; ain; ain = ain->next)
12721 if (ain->peer == peer)
12722 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 12723
9bcb3eef 12724 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 12725
54317cba
JW
12726 if (pi->peer != peer)
12727 continue;
d62a17ae 12728
54317cba 12729 pc->count[PCOUNT_ALL]++;
d62a17ae 12730
54317cba
JW
12731 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
12732 pc->count[PCOUNT_DAMPED]++;
12733 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
12734 pc->count[PCOUNT_HISTORY]++;
12735 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
12736 pc->count[PCOUNT_REMOVED]++;
12737 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
12738 pc->count[PCOUNT_STALE]++;
12739 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
12740 pc->count[PCOUNT_VALID]++;
12741 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12742 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
12743 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
12744 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
12745
12746 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
12747 pc->count[PCOUNT_COUNTED]++;
12748 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
12749 flog_err(
12750 EC_LIB_DEVELOPMENT,
12751 "Attempting to count but flags say it is unusable");
12752 } else {
40381db7 12753 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
12754 flog_err(
12755 EC_LIB_DEVELOPMENT,
12756 "Not counted but flags say we should");
d62a17ae 12757 }
12758 }
54317cba
JW
12759}
12760
12761static int bgp_peer_count_walker(struct thread *t)
12762{
9bcb3eef 12763 struct bgp_dest *rn, *rm;
54317cba
JW
12764 const struct bgp_table *table;
12765 struct peer_pcounts *pc = THREAD_ARG(t);
12766
12767 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
12768 || pc->safi == SAFI_EVPN) {
12769 /* Special handling for 2-level routing tables. */
12770 for (rn = bgp_table_top(pc->table); rn;
12771 rn = bgp_route_next(rn)) {
9bcb3eef 12772 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
12773 if (table != NULL)
12774 for (rm = bgp_table_top(table); rm;
12775 rm = bgp_route_next(rm))
12776 bgp_peer_count_proc(rm, pc);
12777 }
12778 } else
12779 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
12780 bgp_peer_count_proc(rn, pc);
12781
d62a17ae 12782 return 0;
718e3744 12783}
12784
d62a17ae 12785static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 12786 safi_t safi, bool use_json)
856ca177 12787{
d62a17ae 12788 struct peer_pcounts pcounts = {.peer = peer};
12789 unsigned int i;
12790 json_object *json = NULL;
12791 json_object *json_loop = NULL;
856ca177 12792
d62a17ae 12793 if (use_json) {
12794 json = json_object_new_object();
12795 json_loop = json_object_new_object();
12796 }
718e3744 12797
d62a17ae 12798 if (!peer || !peer->bgp || !peer->afc[afi][safi]
12799 || !peer->bgp->rib[afi][safi]) {
12800 if (use_json) {
12801 json_object_string_add(
12802 json, "warning",
12803 "No such neighbor or address family");
12804 vty_out(vty, "%s\n", json_object_to_json_string(json));
12805 json_object_free(json);
d5f20468 12806 json_object_free(json_loop);
d62a17ae 12807 } else
12808 vty_out(vty, "%% No such neighbor or address family\n");
12809
12810 return CMD_WARNING;
12811 }
2a71e9ce 12812
d62a17ae 12813 memset(&pcounts, 0, sizeof(pcounts));
12814 pcounts.peer = peer;
12815 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 12816 pcounts.safi = safi;
d62a17ae 12817
12818 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
12819 * stats for the thread-walk (i.e. ensure this can't be blamed on
12820 * on just vty_read()).
12821 */
d62a17ae 12822 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
12823
12824 if (use_json) {
12825 json_object_string_add(json, "prefixCountsFor", peer->host);
12826 json_object_string_add(json, "multiProtocol",
5cb5f4d0 12827 get_afi_safi_str(afi, safi, true));
d62a17ae 12828 json_object_int_add(json, "pfxCounter",
12829 peer->pcount[afi][safi]);
12830
12831 for (i = 0; i < PCOUNT_MAX; i++)
12832 json_object_int_add(json_loop, pcount_strs[i],
12833 pcounts.count[i]);
12834
12835 json_object_object_add(json, "ribTableWalkCounters", json_loop);
12836
12837 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12838 json_object_string_add(json, "pfxctDriftFor",
12839 peer->host);
12840 json_object_string_add(
12841 json, "recommended",
12842 "Please report this bug, with the above command output");
12843 }
996c9314
LB
12844 vty_out(vty, "%s\n", json_object_to_json_string_ext(
12845 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 12846 json_object_free(json);
12847 } else {
12848
12849 if (peer->hostname
892fedb6 12850 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 12851 vty_out(vty, "Prefix counts for %s/%s, %s\n",
12852 peer->hostname, peer->host,
5cb5f4d0 12853 get_afi_safi_str(afi, safi, false));
d62a17ae 12854 } else {
12855 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 12856 get_afi_safi_str(afi, safi, false));
d62a17ae 12857 }
12858
6cde4b45 12859 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 12860 vty_out(vty, "\nCounts from RIB table walk:\n\n");
12861
12862 for (i = 0; i < PCOUNT_MAX; i++)
12863 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
12864 pcounts.count[i]);
12865
12866 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
12867 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
12868 vty_out(vty,
12869 "Please report this bug, with the above command output\n");
12870 }
12871 }
12872
12873 return CMD_SUCCESS;
718e3744 12874}
12875
a636c635
DW
12876DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
12877 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 12878 "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 12879 SHOW_STR
12880 IP_STR
12881 BGP_STR
8386ac43 12882 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
12883 BGP_AFI_HELP_STR
12884 BGP_SAFI_HELP_STR
0b16f239
DS
12885 "Detailed information on TCP and BGP neighbor connections\n"
12886 "Neighbor to display information about\n"
12887 "Neighbor to display information about\n"
91d37724 12888 "Neighbor on BGP configured interface\n"
a636c635 12889 "Display detailed prefix count information\n"
9973d184 12890 JSON_STR)
0b16f239 12891{
d62a17ae 12892 afi_t afi = AFI_IP6;
12893 safi_t safi = SAFI_UNICAST;
12894 struct peer *peer;
12895 int idx = 0;
12896 struct bgp *bgp = NULL;
9f049418
DS
12897 bool uj = use_json(argc, argv);
12898
12899 if (uj)
12900 argc--;
856ca177 12901
d62a17ae 12902 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12903 &bgp, uj);
d62a17ae 12904 if (!idx)
12905 return CMD_WARNING;
0b16f239 12906
d62a17ae 12907 argv_find(argv, argc, "neighbors", &idx);
12908 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
12909 if (!peer)
12910 return CMD_WARNING;
bb46e94f 12911
29c8d9da 12912 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 12913}
0b16f239 12914
d6902373
PG
12915#ifdef KEEP_OLD_VPN_COMMANDS
12916DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
12917 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
12918 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
12919 SHOW_STR
12920 IP_STR
12921 BGP_STR
d6902373 12922 BGP_VPNVX_HELP_STR
91d37724 12923 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
12924 "Detailed information on TCP and BGP neighbor connections\n"
12925 "Neighbor to display information about\n"
12926 "Neighbor to display information about\n"
91d37724 12927 "Neighbor on BGP configured interface\n"
a636c635 12928 "Display detailed prefix count information\n"
9973d184 12929 JSON_STR)
a636c635 12930{
d62a17ae 12931 int idx_peer = 6;
12932 struct peer *peer;
9f049418 12933 bool uj = use_json(argc, argv);
a636c635 12934
d62a17ae 12935 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
12936 if (!peer)
12937 return CMD_WARNING;
12938
12939 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
12940}
12941
d6902373
PG
12942DEFUN (show_ip_bgp_vpn_all_route_prefix,
12943 show_ip_bgp_vpn_all_route_prefix_cmd,
12944 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
12945 SHOW_STR
12946 IP_STR
12947 BGP_STR
d6902373 12948 BGP_VPNVX_HELP_STR
91d37724
QY
12949 "Display information about all VPNv4 NLRIs\n"
12950 "Network in the BGP routing table to display\n"
3a2d747c 12951 "Network in the BGP routing table to display\n"
9973d184 12952 JSON_STR)
91d37724 12953{
d62a17ae 12954 int idx = 0;
12955 char *network = NULL;
12956 struct bgp *bgp = bgp_get_default();
12957 if (!bgp) {
12958 vty_out(vty, "Can't find default instance\n");
12959 return CMD_WARNING;
12960 }
87e34b58 12961
d62a17ae 12962 if (argv_find(argv, argc, "A.B.C.D", &idx))
12963 network = argv[idx]->arg;
12964 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
12965 network = argv[idx]->arg;
12966 else {
12967 vty_out(vty, "Unable to figure out Network\n");
12968 return CMD_WARNING;
12969 }
87e34b58 12970
d62a17ae 12971 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
360660c6 12972 BGP_PATH_SHOW_ALL, use_json(argc, argv));
91d37724 12973}
d6902373 12974#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 12975
44c69747
LK
12976DEFUN (show_bgp_l2vpn_evpn_route_prefix,
12977 show_bgp_l2vpn_evpn_route_prefix_cmd,
12978 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 12979 SHOW_STR
4c63a661
PG
12980 BGP_STR
12981 L2VPN_HELP_STR
12982 EVPN_HELP_STR
44c69747
LK
12983 "Network in the BGP routing table to display\n"
12984 "Network in the BGP routing table to display\n"
4c63a661
PG
12985 "Network in the BGP routing table to display\n"
12986 "Network in the BGP routing table to display\n"
12987 JSON_STR)
12988{
d62a17ae 12989 int idx = 0;
12990 char *network = NULL;
44c69747 12991 int prefix_check = 0;
a636c635 12992
44c69747
LK
12993 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
12994 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 12995 network = argv[idx]->arg;
44c69747 12996 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 12997 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 12998 network = argv[idx]->arg;
44c69747
LK
12999 prefix_check = 1;
13000 } else {
d62a17ae 13001 vty_out(vty, "Unable to figure out Network\n");
13002 return CMD_WARNING;
13003 }
44c69747
LK
13004 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13005 prefix_check, BGP_PATH_SHOW_ALL,
13006 use_json(argc, argv));
d62a17ae 13007}
13008
2f9bc755
DS
13009static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13010 struct bgp_table *table, int *header1,
13011 int *header2, json_object *json,
13012 json_object *json_scode,
13013 json_object *json_ocode, bool wide)
13014{
13015 uint64_t version = table ? table->version : 0;
23d0a753 13016 char buf[BUFSIZ] = {0};
2f9bc755
DS
13017
13018 if (*header1) {
13019 if (json) {
13020 json_object_int_add(json, "bgpTableVersion", version);
13021 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13022 inet_ntop(AF_INET,
13023 &bgp->router_id, buf,
13024 sizeof(buf)));
2f9bc755
DS
13025 json_object_int_add(json, "defaultLocPrf",
13026 bgp->default_local_pref);
13027 json_object_int_add(json, "localAS", bgp->as);
13028 json_object_object_add(json, "bgpStatusCodes",
13029 json_scode);
13030 json_object_object_add(json, "bgpOriginCodes",
13031 json_ocode);
13032 } else {
13033 vty_out(vty,
23d0a753
DA
13034 "BGP table version is %" PRIu64
13035 ", local router ID is %pI4, vrf id ",
13036 version, &bgp->router_id);
2f9bc755
DS
13037 if (bgp->vrf_id == VRF_UNKNOWN)
13038 vty_out(vty, "%s", VRFID_NONE_STR);
13039 else
13040 vty_out(vty, "%u", bgp->vrf_id);
13041 vty_out(vty, "\n");
13042 vty_out(vty, "Default local pref %u, ",
13043 bgp->default_local_pref);
13044 vty_out(vty, "local AS %u\n", bgp->as);
13045 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13046 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13047 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13048 }
13049 *header1 = 0;
13050 }
13051 if (*header2) {
13052 if (!json)
13053 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13054 : BGP_SHOW_HEADER));
13055 *header2 = 0;
13056 }
13057}
13058
d9478df0
TA
13059static void
13060show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13061 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13062 const char *rmap_name, json_object *json, json_object *json_ar,
13063 json_object *json_scode, json_object *json_ocode,
13064 uint8_t show_flags, int *header1, int *header2, char *rd_str,
13065 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13066{
d62a17ae 13067 struct bgp_adj_in *ain;
13068 struct bgp_adj_out *adj;
9bcb3eef 13069 struct bgp_dest *dest;
d62a17ae 13070 struct bgp *bgp;
d62a17ae 13071 struct attr attr;
13072 int ret;
13073 struct update_subgroup *subgrp;
d62a17ae 13074 struct peer_af *paf;
f99def61 13075 bool route_filtered;
96f3485c
MK
13076 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13077 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13078 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13079 || (safi == SAFI_EVPN))
13080 ? true
13081 : false;
a636c635 13082
d62a17ae 13083 bgp = peer->bgp;
a636c635 13084
d62a17ae 13085 if (!bgp) {
13086 if (use_json) {
13087 json_object_string_add(json, "alert", "no BGP");
13088 vty_out(vty, "%s\n", json_object_to_json_string(json));
13089 json_object_free(json);
13090 } else
13091 vty_out(vty, "%% No bgp\n");
13092 return;
13093 }
a636c635 13094
d62a17ae 13095 subgrp = peer_subgroup(peer, afi, safi);
13096
6392aaa6 13097 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13098 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13099 char buf[BUFSIZ] = {0};
13100
d62a17ae 13101 if (use_json) {
13102 json_object_int_add(json, "bgpTableVersion",
13103 table->version);
13104 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13105 inet_ntop(AF_INET,
13106 &bgp->router_id, buf,
13107 sizeof(buf)));
01eced22
AD
13108 json_object_int_add(json, "defaultLocPrf",
13109 bgp->default_local_pref);
13110 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13111 json_object_object_add(json, "bgpStatusCodes",
13112 json_scode);
13113 json_object_object_add(json, "bgpOriginCodes",
13114 json_ocode);
07d0c4ed
DA
13115 json_object_string_add(
13116 json, "bgpOriginatingDefaultNetwork",
13117 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13118 } else {
23d0a753
DA
13119 vty_out(vty,
13120 "BGP table version is %" PRIu64
13121 ", local router ID is %pI4, vrf id ",
13122 table->version, &bgp->router_id);
9df8b37c
PZ
13123 if (bgp->vrf_id == VRF_UNKNOWN)
13124 vty_out(vty, "%s", VRFID_NONE_STR);
13125 else
13126 vty_out(vty, "%u", bgp->vrf_id);
13127 vty_out(vty, "\n");
01eced22
AD
13128 vty_out(vty, "Default local pref %u, ",
13129 bgp->default_local_pref);
13130 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13131 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13132 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13133 vty_out(vty, BGP_SHOW_OCODE_HEADER);
13134
07d0c4ed
DA
13135 vty_out(vty, "Originating default network %s\n\n",
13136 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13137 }
d9478df0 13138 *header1 = 0;
d62a17ae 13139 }
a636c635 13140
9bcb3eef 13141 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13142 if (type == bgp_show_adj_route_received
13143 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13144 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13145 if (ain->peer != peer)
ea47320b 13146 continue;
6392aaa6 13147
d9478df0
TA
13148 show_adj_route_header(vty, bgp, table, header1,
13149 header2, json, json_scode,
13150 json_ocode, wide);
13151
13152 if ((safi == SAFI_MPLS_VPN)
13153 || (safi == SAFI_ENCAP)
13154 || (safi == SAFI_EVPN)) {
13155 if (use_json)
13156 json_object_string_add(
13157 json_ar, "rd", rd_str);
13158 else if (show_rd && rd_str) {
13159 vty_out(vty,
13160 "Route Distinguisher: %s\n",
13161 rd_str);
13162 show_rd = false;
13163 }
13164 }
6392aaa6 13165
6f4f49b2 13166 attr = *ain->attr;
f99def61
AD
13167 route_filtered = false;
13168
13169 /* Filter prefix using distribute list,
13170 * filter list or prefix list
13171 */
b54892e0 13172 const struct prefix *rn_p =
9bcb3eef 13173 bgp_dest_get_prefix(dest);
b54892e0
DS
13174 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13175 safi))
13176 == FILTER_DENY)
f99def61
AD
13177 route_filtered = true;
13178
13179 /* Filter prefix using route-map */
b54892e0
DS
13180 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13181 safi, rmap_name, NULL,
13182 0, NULL);
6392aaa6 13183
13c8e163
AD
13184 if (type == bgp_show_adj_route_filtered &&
13185 !route_filtered && ret != RMAP_DENY) {
b755861b 13186 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13187 continue;
d62a17ae 13188 }
6392aaa6 13189
d9478df0
TA
13190 if (type == bgp_show_adj_route_received
13191 && (route_filtered || ret == RMAP_DENY))
13192 (*filtered_count)++;
6392aaa6 13193
b54892e0 13194 route_vty_out_tmp(vty, rn_p, &attr, safi,
ae248832 13195 use_json, json_ar, wide);
b755861b 13196 bgp_attr_undup(&attr, ain->attr);
d9478df0 13197 (*output_count)++;
d62a17ae 13198 }
6392aaa6 13199 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13200 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13201 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13202 if (paf->peer != peer || !adj->attr)
924c3f6a 13203 continue;
d62a17ae 13204
d9478df0
TA
13205 show_adj_route_header(vty, bgp, table,
13206 header1, header2,
13207 json, json_scode,
13208 json_ocode, wide);
d62a17ae 13209
b54892e0 13210 const struct prefix *rn_p =
9bcb3eef 13211 bgp_dest_get_prefix(dest);
b54892e0 13212
6f4f49b2 13213 attr = *adj->attr;
b755861b 13214 ret = bgp_output_modifier(
b54892e0 13215 peer, rn_p, &attr, afi, safi,
b755861b 13216 rmap_name);
f46d8e1e 13217
b755861b 13218 if (ret != RMAP_DENY) {
d9478df0
TA
13219 if ((safi == SAFI_MPLS_VPN)
13220 || (safi == SAFI_ENCAP)
13221 || (safi == SAFI_EVPN)) {
13222 if (use_json)
13223 json_object_string_add(
13224 json_ar,
13225 "rd",
13226 rd_str);
13227 else if (show_rd
13228 && rd_str) {
13229 vty_out(vty,
13230 "Route Distinguisher: %s\n",
13231 rd_str);
13232 show_rd = false;
13233 }
13234 }
b54892e0
DS
13235 route_vty_out_tmp(
13236 vty, rn_p, &attr, safi,
ae248832
MK
13237 use_json, json_ar,
13238 wide);
d9478df0 13239 (*output_count)++;
b755861b 13240 } else {
d9478df0 13241 (*filtered_count)++;
a2addae8 13242 }
b755861b
PM
13243
13244 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13245 }
f20ce998
DS
13246 } else if (type == bgp_show_adj_route_bestpath) {
13247 struct bgp_path_info *pi;
13248
d9478df0
TA
13249 show_adj_route_header(vty, bgp, table, header1, header2,
13250 json, json_scode, json_ocode,
13251 wide);
f20ce998
DS
13252
13253 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13254 pi = pi->next) {
13255 if (pi->peer != peer)
13256 continue;
13257
13258 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13259 continue;
13260
13261 route_vty_out_tmp(vty,
13262 bgp_dest_get_prefix(dest),
13263 pi->attr, safi, use_json,
13264 json_ar, wide);
d9478df0 13265 (*output_count)++;
f20ce998 13266 }
d62a17ae 13267 }
13268 }
a636c635 13269}
2a71e9ce 13270
d62a17ae 13271static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13272 safi_t safi, enum bgp_show_adj_route_type type,
96f3485c 13273 const char *rmap_name, uint8_t show_flags)
0b16f239 13274{
d9478df0
TA
13275 struct bgp *bgp;
13276 struct bgp_table *table;
d62a17ae 13277 json_object *json = NULL;
d9478df0
TA
13278 json_object *json_scode = NULL;
13279 json_object *json_ocode = NULL;
13280 json_object *json_ar = NULL;
96f3485c 13281 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13282
d9478df0
TA
13283 /* Init BGP headers here so they're only displayed once
13284 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13285 */
13286 int header1 = 1;
13287 int header2 = 1;
13288
13289 /*
13290 * Initialize variables for each RD
13291 * All prefixes under an RD is aggregated within "json_routes"
13292 */
13293 char rd_str[BUFSIZ] = {0};
13294 json_object *json_routes = NULL;
13295
13296
13297 /* For 2-tier tables, prefix counts need to be
13298 * maintained across multiple runs of show_adj_route()
13299 */
13300 unsigned long output_count_per_rd;
13301 unsigned long filtered_count_per_rd;
13302 unsigned long output_count = 0;
13303 unsigned long filtered_count = 0;
13304
13305 if (use_json) {
d62a17ae 13306 json = json_object_new_object();
d9478df0
TA
13307 json_ar = json_object_new_object();
13308 json_scode = json_object_new_object();
13309 json_ocode = json_object_new_object();
13310
13311 json_object_string_add(json_scode, "suppressed", "s");
13312 json_object_string_add(json_scode, "damped", "d");
13313 json_object_string_add(json_scode, "history", "h");
13314 json_object_string_add(json_scode, "valid", "*");
13315 json_object_string_add(json_scode, "best", ">");
13316 json_object_string_add(json_scode, "multipath", "=");
13317 json_object_string_add(json_scode, "internal", "i");
13318 json_object_string_add(json_scode, "ribFailure", "r");
13319 json_object_string_add(json_scode, "stale", "S");
13320 json_object_string_add(json_scode, "removed", "R");
13321
13322 json_object_string_add(json_ocode, "igp", "i");
13323 json_object_string_add(json_ocode, "egp", "e");
13324 json_object_string_add(json_ocode, "incomplete", "?");
13325 }
0b16f239 13326
d62a17ae 13327 if (!peer || !peer->afc[afi][safi]) {
13328 if (use_json) {
13329 json_object_string_add(
13330 json, "warning",
13331 "No such neighbor or address family");
13332 vty_out(vty, "%s\n", json_object_to_json_string(json));
13333 json_object_free(json);
13334 } else
13335 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13336
d62a17ae 13337 return CMD_WARNING;
13338 }
13339
6392aaa6
PM
13340 if ((type == bgp_show_adj_route_received
13341 || type == bgp_show_adj_route_filtered)
d62a17ae 13342 && !CHECK_FLAG(peer->af_flags[afi][safi],
13343 PEER_FLAG_SOFT_RECONFIG)) {
13344 if (use_json) {
13345 json_object_string_add(
13346 json, "warning",
13347 "Inbound soft reconfiguration not enabled");
13348 vty_out(vty, "%s\n", json_object_to_json_string(json));
13349 json_object_free(json);
13350 } else
13351 vty_out(vty,
13352 "%% Inbound soft reconfiguration not enabled\n");
13353
13354 return CMD_WARNING;
13355 }
0b16f239 13356
d9478df0
TA
13357 bgp = peer->bgp;
13358
13359 /* labeled-unicast routes live in the unicast table */
13360 if (safi == SAFI_LABELED_UNICAST)
13361 table = bgp->rib[afi][SAFI_UNICAST];
13362 else
13363 table = bgp->rib[afi][safi];
13364
13365 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13366 || (safi == SAFI_EVPN)) {
13367
13368 struct bgp_dest *dest;
13369
13370 for (dest = bgp_table_top(table); dest;
13371 dest = bgp_route_next(dest)) {
13372 table = bgp_dest_get_bgp_table_info(dest);
13373 if (!table)
13374 continue;
13375
13376 output_count_per_rd = 0;
13377 filtered_count_per_rd = 0;
13378
13379 if (use_json)
13380 json_routes = json_object_new_object();
13381
13382 const struct prefix_rd *prd;
13383 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13384 dest);
13385
13386 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13387
13388 show_adj_route(vty, peer, table, afi, safi, type,
13389 rmap_name, json, json_routes, json_scode,
13390 json_ocode, show_flags, &header1,
13391 &header2, rd_str, &output_count_per_rd,
13392 &filtered_count_per_rd);
13393
13394 /* Don't include an empty RD in the output! */
13395 if (json_routes && (output_count_per_rd > 0))
13396 json_object_object_add(json_ar, rd_str,
13397 json_routes);
13398
13399 output_count += output_count_per_rd;
13400 filtered_count += filtered_count_per_rd;
13401 }
13402 } else
13403 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13404 json, json_ar, json_scode, json_ocode,
13405 show_flags, &header1, &header2, rd_str,
13406 &output_count, &filtered_count);
13407
13408 if (use_json) {
13409 json_object_object_add(json, "advertisedRoutes", json_ar);
13410 json_object_int_add(json, "totalPrefixCounter", output_count);
13411 json_object_int_add(json, "filteredPrefixCounter",
13412 filtered_count);
13413
13414 vty_out(vty, "%s\n",
13415 json_object_to_json_string_ext(
13416 json, JSON_C_TO_STRING_PRETTY));
13417
13418 if (!output_count && !filtered_count) {
13419 json_object_free(json_scode);
13420 json_object_free(json_ocode);
13421 }
13422
13423 if (json)
13424 json_object_free(json);
13425
13426 } else if (output_count > 0) {
13427 if (filtered_count > 0)
13428 vty_out(vty,
13429 "\nTotal number of prefixes %ld (%ld filtered)\n",
13430 output_count, filtered_count);
13431 else
13432 vty_out(vty, "\nTotal number of prefixes %ld\n",
13433 output_count);
13434 }
0b16f239 13435
d62a17ae 13436 return CMD_SUCCESS;
a636c635 13437}
50ef26d4 13438
f20ce998
DS
13439DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13440 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13441 "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]",
13442 SHOW_STR
13443 IP_STR
13444 BGP_STR
13445 BGP_INSTANCE_HELP_STR
13446 BGP_AFI_HELP_STR
13447 BGP_SAFI_WITH_LABEL_HELP_STR
13448 "Detailed information on TCP and BGP neighbor connections\n"
13449 "Neighbor to display information about\n"
13450 "Neighbor to display information about\n"
13451 "Neighbor on BGP configured interface\n"
13452 "Display the routes selected by best path\n"
13453 JSON_STR
13454 "Increase table width for longer prefixes\n")
13455{
13456 afi_t afi = AFI_IP6;
13457 safi_t safi = SAFI_UNICAST;
13458 char *rmap_name = NULL;
13459 char *peerstr = NULL;
13460 struct bgp *bgp = NULL;
13461 struct peer *peer;
13462 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13463 int idx = 0;
96f3485c
MK
13464 uint8_t show_flags = 0;
13465
13466 if (uj)
13467 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13468
13469 if (wide)
13470 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13471
13472 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13473 &bgp, uj);
13474
13475 if (!idx)
13476 return CMD_WARNING;
13477
13478 argv_find(argv, argc, "neighbors", &idx);
13479 peerstr = argv[++idx]->arg;
13480
13481 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13482 if (!peer)
13483 return CMD_WARNING;
13484
96f3485c
MK
13485 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13486 show_flags);
f20ce998
DS
13487}
13488
ae248832 13489DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13490 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13491 "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 13492 SHOW_STR
13493 IP_STR
13494 BGP_STR
a636c635 13495 BGP_INSTANCE_HELP_STR
7395a2c9 13496 BGP_AFI_HELP_STR
4dd6177e 13497 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13498 "Display the entries for all address families\n"
718e3744 13499 "Detailed information on TCP and BGP neighbor connections\n"
13500 "Neighbor to display information about\n"
13501 "Neighbor to display information about\n"
91d37724 13502 "Neighbor on BGP configured interface\n"
a636c635 13503 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13504 "Display the received routes from neighbor\n"
13505 "Display the filtered routes received from neighbor\n"
a636c635
DW
13506 "Route-map to modify the attributes\n"
13507 "Name of the route map\n"
ae248832
MK
13508 JSON_STR
13509 "Increase table width for longer prefixes\n")
718e3744 13510{
d62a17ae 13511 afi_t afi = AFI_IP6;
13512 safi_t safi = SAFI_UNICAST;
13513 char *rmap_name = NULL;
13514 char *peerstr = NULL;
d62a17ae 13515 struct bgp *bgp = NULL;
13516 struct peer *peer;
6392aaa6 13517 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13518 int idx = 0;
96f3485c
MK
13519 bool first = true;
13520 uint8_t show_flags = 0;
6392aaa6 13521
96f3485c 13522 if (uj) {
d62a17ae 13523 argc--;
96f3485c
MK
13524 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13525 }
13526
13527 if (all) {
13528 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13529 if (argv_find(argv, argc, "ipv4", &idx))
13530 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13531
13532 if (argv_find(argv, argc, "ipv6", &idx))
13533 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13534 }
13535
13536 if (wide)
13537 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13538
9f049418
DS
13539 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13540 &bgp, uj);
13541 if (!idx)
13542 return CMD_WARNING;
13543
d62a17ae 13544 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13545 argv_find(argv, argc, "neighbors", &idx);
13546 peerstr = argv[++idx]->arg;
8c3deaae 13547
d62a17ae 13548 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13549 if (!peer)
13550 return CMD_WARNING;
856ca177 13551
d62a17ae 13552 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13553 type = bgp_show_adj_route_advertised;
13554 else if (argv_find(argv, argc, "received-routes", &idx))
13555 type = bgp_show_adj_route_received;
13556 else if (argv_find(argv, argc, "filtered-routes", &idx))
13557 type = bgp_show_adj_route_filtered;
13558
d62a17ae 13559 if (argv_find(argv, argc, "route-map", &idx))
13560 rmap_name = argv[++idx]->arg;
95cbbd2a 13561
96f3485c
MK
13562 if (!all)
13563 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13564 show_flags);
13565 if (uj)
13566 vty_out(vty, "{\n");
13567
13568 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13569 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13570 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13571 : AFI_IP6;
13572 FOREACH_SAFI (safi) {
96f3485c
MK
13573 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13574 continue;
13575
13576 if (uj) {
13577 if (first)
13578 first = false;
13579 else
13580 vty_out(vty, ",\n");
13581 vty_out(vty, "\"%s\":",
13582 get_afi_safi_str(afi, safi, true));
13583 } else
13584 vty_out(vty, "\nFor address family: %s\n",
13585 get_afi_safi_str(afi, safi, false));
13586
13587 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13588 show_flags);
13589 }
13590 } else {
13591 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
13592 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13593 continue;
13594
13595 if (uj) {
13596 if (first)
13597 first = false;
13598 else
13599 vty_out(vty, ",\n");
13600 vty_out(vty, "\"%s\":",
13601 get_afi_safi_str(afi, safi, true));
13602 } else
13603 vty_out(vty, "\nFor address family: %s\n",
13604 get_afi_safi_str(afi, safi, false));
13605
13606 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13607 show_flags);
13608 }
13609 }
13610 if (uj)
13611 vty_out(vty, "}\n");
13612
13613 return CMD_SUCCESS;
95cbbd2a
ML
13614}
13615
718e3744 13616DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
13617 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 13618 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 13619 SHOW_STR
13620 IP_STR
13621 BGP_STR
8c3deaae
QY
13622 "Address Family\n"
13623 "Address Family\n"
718e3744 13624 "Address Family modifier\n"
13625 "Detailed information on TCP and BGP neighbor connections\n"
13626 "Neighbor to display information about\n"
13627 "Neighbor to display information about\n"
91d37724 13628 "Neighbor on BGP configured interface\n"
718e3744 13629 "Display information received from a BGP neighbor\n"
856ca177 13630 "Display the prefixlist filter\n"
9973d184 13631 JSON_STR)
718e3744 13632{
d62a17ae 13633 afi_t afi = AFI_IP6;
13634 safi_t safi = SAFI_UNICAST;
13635 char *peerstr = NULL;
13636
13637 char name[BUFSIZ];
13638 union sockunion su;
13639 struct peer *peer;
13640 int count, ret;
13641
13642 int idx = 0;
13643
13644 /* show [ip] bgp */
13645 if (argv_find(argv, argc, "ip", &idx))
13646 afi = AFI_IP;
13647 /* [<ipv4|ipv6> [unicast]] */
13648 if (argv_find(argv, argc, "ipv4", &idx))
13649 afi = AFI_IP;
13650 if (argv_find(argv, argc, "ipv6", &idx))
13651 afi = AFI_IP6;
13652 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13653 argv_find(argv, argc, "neighbors", &idx);
13654 peerstr = argv[++idx]->arg;
13655
9f049418 13656 bool uj = use_json(argc, argv);
d62a17ae 13657
13658 ret = str2sockunion(peerstr, &su);
13659 if (ret < 0) {
13660 peer = peer_lookup_by_conf_if(NULL, peerstr);
13661 if (!peer) {
13662 if (uj)
13663 vty_out(vty, "{}\n");
13664 else
13665 vty_out(vty,
13666 "%% Malformed address or name: %s\n",
13667 peerstr);
13668 return CMD_WARNING;
13669 }
13670 } else {
13671 peer = peer_lookup(NULL, &su);
13672 if (!peer) {
13673 if (uj)
13674 vty_out(vty, "{}\n");
13675 else
13676 vty_out(vty, "No peer\n");
13677 return CMD_WARNING;
13678 }
13679 }
718e3744 13680
4ced1a2c 13681 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 13682 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
13683 if (count) {
13684 if (!uj)
13685 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 13686 get_afi_safi_str(afi, safi, false));
d62a17ae 13687 prefix_bgp_show_prefix_list(vty, afi, name, uj);
13688 } else {
13689 if (uj)
13690 vty_out(vty, "{}\n");
13691 else
13692 vty_out(vty, "No functional output\n");
13693 }
718e3744 13694
d62a17ae 13695 return CMD_SUCCESS;
13696}
13697
13698static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
13699 afi_t afi, safi_t safi,
9f049418 13700 enum bgp_show_type type, bool use_json)
d62a17ae 13701{
96f3485c
MK
13702 uint8_t show_flags = 0;
13703
13704 if (use_json)
13705 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13706
d62a17ae 13707 if (!peer || !peer->afc[afi][safi]) {
13708 if (use_json) {
13709 json_object *json_no = NULL;
13710 json_no = json_object_new_object();
13711 json_object_string_add(
13712 json_no, "warning",
13713 "No such neighbor or address family");
13714 vty_out(vty, "%s\n",
13715 json_object_to_json_string(json_no));
13716 json_object_free(json_no);
13717 } else
13718 vty_out(vty, "%% No such neighbor or address family\n");
13719 return CMD_WARNING;
13720 }
47fc97cc 13721
7daf25a3
TA
13722 /* labeled-unicast routes live in the unicast table */
13723 if (safi == SAFI_LABELED_UNICAST)
13724 safi = SAFI_UNICAST;
13725
96f3485c 13726 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags);
718e3744 13727}
13728
dba3c1d3
PG
13729DEFUN (show_ip_bgp_flowspec_routes_detailed,
13730 show_ip_bgp_flowspec_routes_detailed_cmd,
13731 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
13732 SHOW_STR
13733 IP_STR
13734 BGP_STR
13735 BGP_INSTANCE_HELP_STR
13736 BGP_AFI_HELP_STR
13737 "SAFI Flowspec\n"
13738 "Detailed information on flowspec entries\n"
13739 JSON_STR)
13740{
13741 afi_t afi = AFI_IP;
13742 safi_t safi = SAFI_UNICAST;
13743 struct bgp *bgp = NULL;
13744 int idx = 0;
9f049418 13745 bool uj = use_json(argc, argv);
96f3485c 13746 uint8_t show_flags = 0;
9f049418 13747
96f3485c 13748 if (uj) {
9f049418 13749 argc--;
96f3485c
MK
13750 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13751 }
dba3c1d3
PG
13752
13753 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13754 &bgp, uj);
dba3c1d3
PG
13755 if (!idx)
13756 return CMD_WARNING;
13757
96f3485c
MK
13758 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
13759 show_flags);
dba3c1d3
PG
13760}
13761
718e3744 13762DEFUN (show_ip_bgp_neighbor_routes,
13763 show_ip_bgp_neighbor_routes_cmd,
3efd0893 13764 "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 13765 SHOW_STR
13766 IP_STR
13767 BGP_STR
8386ac43 13768 BGP_INSTANCE_HELP_STR
4f280b15 13769 BGP_AFI_HELP_STR
4dd6177e 13770 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 13771 "Detailed information on TCP and BGP neighbor connections\n"
13772 "Neighbor to display information about\n"
13773 "Neighbor to display information about\n"
91d37724 13774 "Neighbor on BGP configured interface\n"
2525cf39 13775 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
13776 "Display the dampened routes received from neighbor\n"
13777 "Display routes learned from neighbor\n"
9973d184 13778 JSON_STR)
718e3744 13779{
d62a17ae 13780 char *peerstr = NULL;
13781 struct bgp *bgp = NULL;
13782 afi_t afi = AFI_IP6;
13783 safi_t safi = SAFI_UNICAST;
13784 struct peer *peer;
13785 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 13786 int idx = 0;
9f049418
DS
13787 bool uj = use_json(argc, argv);
13788
13789 if (uj)
13790 argc--;
bb46e94f 13791
d62a17ae 13792 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13793 &bgp, uj);
d62a17ae 13794 if (!idx)
13795 return CMD_WARNING;
c493f2d8 13796
d62a17ae 13797 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13798 argv_find(argv, argc, "neighbors", &idx);
13799 peerstr = argv[++idx]->arg;
8c3deaae 13800
d62a17ae 13801 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 13802 if (!peer)
d62a17ae 13803 return CMD_WARNING;
bb46e94f 13804
d62a17ae 13805 if (argv_find(argv, argc, "flap-statistics", &idx))
13806 sh_type = bgp_show_type_flap_neighbor;
13807 else if (argv_find(argv, argc, "dampened-routes", &idx))
13808 sh_type = bgp_show_type_damp_neighbor;
13809 else if (argv_find(argv, argc, "routes", &idx))
13810 sh_type = bgp_show_type_neighbor;
2525cf39 13811
d62a17ae 13812 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 13813}
6b0655a2 13814
734b349e 13815struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 13816
d62a17ae 13817struct bgp_distance {
13818 /* Distance value for the IP source prefix. */
d7c0a89a 13819 uint8_t distance;
718e3744 13820
d62a17ae 13821 /* Name of the access-list to be matched. */
13822 char *access_list;
718e3744 13823};
13824
4f280b15
LB
13825DEFUN (show_bgp_afi_vpn_rd_route,
13826 show_bgp_afi_vpn_rd_route_cmd,
d114b977 13827 "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
13828 SHOW_STR
13829 BGP_STR
13830 BGP_AFI_HELP_STR
13831 "Address Family modifier\n"
13832 "Display information for a route distinguisher\n"
13833 "Route Distinguisher\n"
7395a2c9
DS
13834 "Network in the BGP routing table to display\n"
13835 "Network in the BGP routing table to display\n"
13836 JSON_STR)
4f280b15 13837{
d62a17ae 13838 int ret;
13839 struct prefix_rd prd;
13840 afi_t afi = AFI_MAX;
13841 int idx = 0;
4f280b15 13842
ff6566f3
DS
13843 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
13844 vty_out(vty, "%% Malformed Address Family\n");
13845 return CMD_WARNING;
13846 }
13847
d62a17ae 13848 ret = str2prefix_rd(argv[5]->arg, &prd);
13849 if (!ret) {
13850 vty_out(vty, "%% Malformed Route Distinguisher\n");
13851 return CMD_WARNING;
13852 }
ff6566f3 13853
d62a17ae 13854 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
360660c6 13855 0, BGP_PATH_SHOW_ALL, use_json(argc, argv));
4f280b15
LB
13856}
13857
d62a17ae 13858static struct bgp_distance *bgp_distance_new(void)
718e3744 13859{
d62a17ae 13860 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 13861}
13862
d62a17ae 13863static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 13864{
d62a17ae 13865 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 13866}
13867
37a87b8f
CS
13868int bgp_distance_set(uint8_t distance, const char *ip_str,
13869 const char *access_list_str, afi_t afi, safi_t safi,
13870 char *errmsg, size_t errmsg_len)
718e3744 13871{
d62a17ae 13872 int ret;
d62a17ae 13873 struct prefix p;
9bcb3eef 13874 struct bgp_dest *dest;
d62a17ae 13875 struct bgp_distance *bdistance;
718e3744 13876
d62a17ae 13877 ret = str2prefix(ip_str, &p);
13878 if (ret == 0) {
37a87b8f 13879 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13880 return CMD_WARNING_CONFIG_FAILED;
13881 }
718e3744 13882
d62a17ae 13883 /* Get BGP distance node. */
9bcb3eef
DS
13884 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
13885 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 13886 if (bdistance)
9bcb3eef 13887 bgp_dest_unlock_node(dest);
ca2e160d 13888 else {
d62a17ae 13889 bdistance = bgp_distance_new();
9bcb3eef 13890 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 13891 }
718e3744 13892
d62a17ae 13893 /* Set distance value. */
13894 bdistance->distance = distance;
718e3744 13895
d62a17ae 13896 /* Reset access-list configuration. */
e1b36e13 13897 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13898 if (access_list_str)
13899 bdistance->access_list =
13900 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 13901
d62a17ae 13902 return CMD_SUCCESS;
718e3744 13903}
13904
37a87b8f
CS
13905int bgp_distance_unset(uint8_t distance, const char *ip_str,
13906 const char *access_list_str, afi_t afi, safi_t safi,
13907 char *errmsg, size_t errmsg_len)
718e3744 13908{
d62a17ae 13909 int ret;
d62a17ae 13910 struct prefix p;
9bcb3eef 13911 struct bgp_dest *dest;
d62a17ae 13912 struct bgp_distance *bdistance;
718e3744 13913
d62a17ae 13914 ret = str2prefix(ip_str, &p);
13915 if (ret == 0) {
37a87b8f 13916 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 13917 return CMD_WARNING_CONFIG_FAILED;
13918 }
718e3744 13919
9bcb3eef
DS
13920 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
13921 if (!dest) {
37a87b8f 13922 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 13923 return CMD_WARNING_CONFIG_FAILED;
13924 }
718e3744 13925
9bcb3eef 13926 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 13927
d62a17ae 13928 if (bdistance->distance != distance) {
37a87b8f
CS
13929 snprintf(errmsg, errmsg_len,
13930 "Distance does not match configured\n");
d62a17ae 13931 return CMD_WARNING_CONFIG_FAILED;
13932 }
718e3744 13933
0a22ddfb 13934 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 13935 bgp_distance_free(bdistance);
718e3744 13936
9bcb3eef
DS
13937 bgp_dest_set_bgp_path_info(dest, NULL);
13938 bgp_dest_unlock_node(dest);
13939 bgp_dest_unlock_node(dest);
718e3744 13940
d62a17ae 13941 return CMD_SUCCESS;
718e3744 13942}
13943
718e3744 13944/* Apply BGP information to distance method. */
b8685f9b 13945uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 13946 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 13947{
9bcb3eef 13948 struct bgp_dest *dest;
801bb996 13949 struct prefix q = {0};
d62a17ae 13950 struct peer *peer;
13951 struct bgp_distance *bdistance;
13952 struct access_list *alist;
13953 struct bgp_static *bgp_static;
13954
13955 if (!bgp)
13956 return 0;
13957
40381db7 13958 peer = pinfo->peer;
d62a17ae 13959
7b7d48e5
DS
13960 if (pinfo->attr->distance)
13961 return pinfo->attr->distance;
13962
801bb996
CS
13963 /* Check source address.
13964 * Note: for aggregate route, peer can have unspec af type.
13965 */
13966 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
13967 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
13968 return 0;
13969
9bcb3eef
DS
13970 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
13971 if (dest) {
13972 bdistance = bgp_dest_get_bgp_distance_info(dest);
13973 bgp_dest_unlock_node(dest);
d62a17ae 13974
13975 if (bdistance->access_list) {
13976 alist = access_list_lookup(afi, bdistance->access_list);
13977 if (alist
13978 && access_list_apply(alist, p) == FILTER_PERMIT)
13979 return bdistance->distance;
13980 } else
13981 return bdistance->distance;
718e3744 13982 }
718e3744 13983
d62a17ae 13984 /* Backdoor check. */
9bcb3eef
DS
13985 dest = bgp_node_lookup(bgp->route[afi][safi], p);
13986 if (dest) {
13987 bgp_static = bgp_dest_get_bgp_static_info(dest);
13988 bgp_dest_unlock_node(dest);
718e3744 13989
d62a17ae 13990 if (bgp_static->backdoor) {
13991 if (bgp->distance_local[afi][safi])
13992 return bgp->distance_local[afi][safi];
13993 else
13994 return ZEBRA_IBGP_DISTANCE_DEFAULT;
13995 }
718e3744 13996 }
718e3744 13997
d62a17ae 13998 if (peer->sort == BGP_PEER_EBGP) {
13999 if (bgp->distance_ebgp[afi][safi])
14000 return bgp->distance_ebgp[afi][safi];
14001 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14002 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14003 if (bgp->distance_ibgp[afi][safi])
14004 return bgp->distance_ibgp[afi][safi];
14005 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14006 } else {
14007 if (bgp->distance_local[afi][safi])
14008 return bgp->distance_local[afi][safi];
14009 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14010 }
718e3744 14011}
14012
a612fb77
DA
14013/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14014 * we should tell ZEBRA update the routes for a specific
14015 * AFI/SAFI to reflect changes in RIB.
14016 */
37a87b8f
CS
14017void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14018 safi_t update_safi)
a612fb77
DA
14019{
14020 afi_t afi;
14021 safi_t safi;
14022
14023 FOREACH_AFI_SAFI (afi, safi) {
14024 if (!bgp_fibupd_safi(safi))
14025 continue;
14026
8b54bc30
DA
14027 if (afi != update_afi && safi != update_safi)
14028 continue;
14029
14030 if (BGP_DEBUG(zebra, ZEBRA))
14031 zlog_debug(
14032 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14033 __func__, afi, safi);
14034 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14035 }
14036}
14037
37a87b8f
CS
14038DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14039 "distance bgp (1-255) (1-255) (1-255)",
14040 "Define an administrative distance\n"
14041 "BGP distance\n"
14042 "Distance for routes external to the AS\n"
14043 "Distance for routes internal to the AS\n"
14044 "Distance for local routes\n")
718e3744 14045{
d62a17ae 14046 int idx_number = 2;
14047 int idx_number_2 = 3;
14048 int idx_number_3 = 4;
14049 afi_t afi;
14050 safi_t safi;
37a87b8f 14051 char xpath[XPATH_MAXLEN];
718e3744 14052
d62a17ae 14053 afi = bgp_node_afi(vty);
14054 safi = bgp_node_safi(vty);
718e3744 14055
37a87b8f
CS
14056 snprintf(
14057 xpath, sizeof(xpath),
14058 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14059 yang_afi_safi_value2identity(afi, safi),
14060 bgp_afi_safi_get_container_str(afi, safi));
14061 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14062 snprintf(
14063 xpath, sizeof(xpath),
14064 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14065 yang_afi_safi_value2identity(afi, safi),
14066 bgp_afi_safi_get_container_str(afi, safi));
14067 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14068 argv[idx_number_2]->arg);
14069 snprintf(
14070 xpath, sizeof(xpath),
14071 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14072 yang_afi_safi_value2identity(afi, safi),
14073 bgp_afi_safi_get_container_str(afi, safi));
14074
14075 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14076 argv[idx_number_3]->arg);
14077
14078 return nb_cli_apply_changes(vty, NULL);
14079}
14080
14081DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14082 "no distance bgp [(1-255) (1-255) (1-255)]",
14083 NO_STR
14084 "Define an administrative distance\n"
14085 "BGP distance\n"
14086 "Distance for routes external to the AS\n"
14087 "Distance for routes internal to the AS\n"
14088 "Distance for local routes\n")
14089{
14090 afi_t afi;
14091 safi_t safi;
14092 char xpath[XPATH_MAXLEN];
14093
14094 afi = bgp_node_afi(vty);
14095 safi = bgp_node_safi(vty);
14096
14097 snprintf(
14098 xpath, sizeof(xpath),
14099 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14100 yang_afi_safi_value2identity(afi, safi),
14101 bgp_afi_safi_get_container_str(afi, safi));
14102 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14103 snprintf(
14104 xpath, sizeof(xpath),
14105 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14106 yang_afi_safi_value2identity(afi, safi),
14107 bgp_afi_safi_get_container_str(afi, safi));
14108 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14109 snprintf(
14110 xpath, sizeof(xpath),
14111 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14112 yang_afi_safi_value2identity(afi, safi),
14113 bgp_afi_safi_get_container_str(afi, safi));
14114
14115 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14116
14117 return nb_cli_apply_changes(vty, NULL);
718e3744 14118}
14119
37a87b8f
CS
14120void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14121 struct lyd_node *dnode,
14122 bool show_defaults)
718e3744 14123{
37a87b8f
CS
14124 uint8_t distance_ebgp, distance_ibgp, distance_local;
14125
14126 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14127 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14128 distance_local = yang_dnode_get_uint8(dnode, "./local");
14129
14130 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14131 distance_local);
14132}
14133
8cc7152a
CS
14134DEFPY_YANG(bgp_distance_source,
14135 bgp_distance_source_cmd,
14136 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14137 NO_STR
14138 "Define an administrative distance\n"
8cc7152a 14139 "Distance value\n"
e12affc1
SW
14140 "IPv4 source prefix\n"
14141 "IPv6 source prefix\n"
37a87b8f 14142 "Access list name\n")
718e3744 14143{
37a87b8f
CS
14144 afi_t afi;
14145 safi_t safi;
14146 char xpath[XPATH_MAXLEN];
14147
14148 afi = bgp_node_afi(vty);
14149 safi = bgp_node_safi(vty);
14150
8cc7152a
CS
14151 if (!no) {
14152 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14153 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14154 distance_str);
14155 if (acl)
14156 nb_cli_enqueue_change(vty,
14157 "./access-list-policy-export",
14158 NB_OP_CREATE, acl);
14159 else
14160 nb_cli_enqueue_change(vty,
14161 "./access-list-policy-export",
14162 NB_OP_DESTROY, NULL);
14163 } else {
14164 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14165 }
37a87b8f
CS
14166
14167 snprintf(
14168 xpath, sizeof(xpath),
14169 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14170 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14171 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14172
14173 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14174}
14175
37a87b8f
CS
14176void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14177 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14178{
14179 vty_out(vty, " distance %d %s %s\n",
14180 yang_dnode_get_uint8(dnode, "./distance"),
14181 yang_dnode_get_string(dnode, "./prefix"),
14182 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14183 ? yang_dnode_get_string(dnode,
14184 "./access-list-policy-export")
14185 : "");
14186}
14187
7c98d487
DA
14188DEFPY_YANG(
14189 bgp_dampening, bgp_dampening_cmd,
14190 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14191 NO_STR
14192 "BGP Specific commands\n"
14193 "Enable route-flap dampening\n"
14194 "Half-life time for the penalty\n"
14195 "Value to start reusing a route\n"
14196 "Value to start suppressing a route\n"
14197 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14198{
14199 afi_t afi;
14200 safi_t safi;
14201 char xpath[XPATH_MAXLEN];
718e3744 14202
37a87b8f
CS
14203 afi = bgp_node_afi(vty);
14204 safi = bgp_node_safi(vty);
14205
d9ce5113
CS
14206 if (!no) {
14207 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14208 if (argc == 6) {
14209 nb_cli_enqueue_change(vty, "./reach-decay",
14210 NB_OP_MODIFY, halflife_str);
14211 nb_cli_enqueue_change(vty, "./reuse-above",
14212 NB_OP_MODIFY, reuse_str);
14213 nb_cli_enqueue_change(vty, "./suppress-above",
14214 NB_OP_MODIFY, suppress_str);
14215 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14216 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14217 } if (argc == 3) {
14218 nb_cli_enqueue_change(vty, "./reach-decay",
14219 NB_OP_MODIFY, halflife_str);
14220 }
14221 } else {
14222 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14223 }
7ebe9748 14224
37a87b8f
CS
14225 snprintf(
14226 xpath, sizeof(xpath),
14227 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14228 yang_afi_safi_value2identity(afi, safi),
14229 bgp_afi_safi_get_container_str(afi, safi));
14230
14231 return nb_cli_apply_changes(vty, xpath);
718e3744 14232}
14233
37a87b8f
CS
14234void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14235 struct lyd_node *dnode,
14236 bool show_defaults)
718e3744 14237{
37a87b8f
CS
14238 if (!yang_dnode_get_bool(dnode, "./enable"))
14239 return;
14240
14241 int half = DEFAULT_HALF_LIFE * 60;
14242 int reuse = DEFAULT_REUSE;
14243 int suppress = DEFAULT_SUPPRESS;
14244 int max;
14245
14246 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14247 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14248 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14249 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14250
14251 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14252 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14253 vty_out(vty, " bgp dampening\n");
14254 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14255 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14256 vty_out(vty, " bgp dampening %u\n", half);
14257 else
14258 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14259 suppress, max);
718e3744 14260}
14261
718e3744 14262/* Display specified route of BGP table. */
d62a17ae 14263static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14264 const char *ip_str, afi_t afi, safi_t safi,
14265 struct prefix_rd *prd, int prefix_check)
14266{
14267 int ret;
14268 struct prefix match;
9bcb3eef
DS
14269 struct bgp_dest *dest;
14270 struct bgp_dest *rm;
40381db7
DS
14271 struct bgp_path_info *pi;
14272 struct bgp_path_info *pi_temp;
d62a17ae 14273 struct bgp *bgp;
14274 struct bgp_table *table;
14275
14276 /* BGP structure lookup. */
14277 if (view_name) {
14278 bgp = bgp_lookup_by_name(view_name);
14279 if (bgp == NULL) {
14280 vty_out(vty, "%% Can't find BGP instance %s\n",
14281 view_name);
14282 return CMD_WARNING;
14283 }
14284 } else {
14285 bgp = bgp_get_default();
14286 if (bgp == NULL) {
14287 vty_out(vty, "%% No BGP process is configured\n");
14288 return CMD_WARNING;
14289 }
718e3744 14290 }
718e3744 14291
d62a17ae 14292 /* Check IP address argument. */
14293 ret = str2prefix(ip_str, &match);
14294 if (!ret) {
14295 vty_out(vty, "%% address is malformed\n");
14296 return CMD_WARNING;
14297 }
718e3744 14298
d62a17ae 14299 match.family = afi2family(afi);
14300
14301 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14302 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14303 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14304 dest = bgp_route_next(dest)) {
14305 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14306
9bcb3eef 14307 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14308 continue;
9bcb3eef 14309 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14310 if (!table)
ea47320b
DL
14311 continue;
14312 if ((rm = bgp_node_match(table, &match)) == NULL)
14313 continue;
d62a17ae 14314
9bcb3eef 14315 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14316
ea47320b 14317 if (!prefix_check
b54892e0 14318 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14319 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14320 while (pi) {
14321 if (pi->extra && pi->extra->damp_info) {
14322 pi_temp = pi->next;
ea47320b 14323 bgp_damp_info_free(
40ec3340
DS
14324 &pi->extra->damp_info,
14325 &bgp->damp[afi][safi],
a935f597 14326 1, afi, safi);
40381db7 14327 pi = pi_temp;
ea47320b 14328 } else
40381db7 14329 pi = pi->next;
d62a17ae 14330 }
ea47320b
DL
14331 }
14332
9bcb3eef 14333 bgp_dest_unlock_node(rm);
d62a17ae 14334 }
14335 } else {
9bcb3eef 14336 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14337 != NULL) {
9bcb3eef 14338 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14339
d62a17ae 14340 if (!prefix_check
9bcb3eef
DS
14341 || dest_p->prefixlen == match.prefixlen) {
14342 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14343 while (pi) {
14344 if (pi->extra && pi->extra->damp_info) {
14345 pi_temp = pi->next;
c8ddbd48 14346 struct bgp_damp_info *bdi =
14347 pi->extra->damp_info;
14348 if (bdi->lastrecord
14349 == BGP_RECORD_UPDATE) {
14350 bgp_aggregate_increment(
14351 bgp,
14352 &bdi->dest->p,
14353 bdi->path,
14354 bdi->afi,
14355 bdi->safi);
14356 bgp_process(bgp,
14357 bdi->dest,
14358 bdi->afi,
14359 bdi->safi);
14360 }
d62a17ae 14361 bgp_damp_info_free(
40ec3340
DS
14362 &pi->extra->damp_info,
14363 &bgp->damp[afi][safi],
a935f597 14364 1, afi, safi);
40381db7 14365 pi = pi_temp;
d62a17ae 14366 } else
40381db7 14367 pi = pi->next;
d62a17ae 14368 }
14369 }
14370
9bcb3eef 14371 bgp_dest_unlock_node(dest);
d62a17ae 14372 }
14373 }
718e3744 14374
d62a17ae 14375 return CMD_SUCCESS;
718e3744 14376}
14377
14378DEFUN (clear_ip_bgp_dampening,
14379 clear_ip_bgp_dampening_cmd,
14380 "clear ip bgp dampening",
14381 CLEAR_STR
14382 IP_STR
14383 BGP_STR
14384 "Clear route flap dampening information\n")
14385{
40ec3340 14386 VTY_DECLVAR_CONTEXT(bgp, bgp);
c8ddbd48 14387 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
40ec3340 14388 SAFI_UNICAST);
d62a17ae 14389 return CMD_SUCCESS;
718e3744 14390}
14391
14392DEFUN (clear_ip_bgp_dampening_prefix,
14393 clear_ip_bgp_dampening_prefix_cmd,
14394 "clear ip bgp dampening A.B.C.D/M",
14395 CLEAR_STR
14396 IP_STR
14397 BGP_STR
14398 "Clear route flap dampening information\n"
0c7b1b01 14399 "IPv4 prefix\n")
718e3744 14400{
d62a17ae 14401 int idx_ipv4_prefixlen = 4;
14402 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14403 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14404}
14405
14406DEFUN (clear_ip_bgp_dampening_address,
14407 clear_ip_bgp_dampening_address_cmd,
14408 "clear ip bgp dampening A.B.C.D",
14409 CLEAR_STR
14410 IP_STR
14411 BGP_STR
14412 "Clear route flap dampening information\n"
14413 "Network to clear damping information\n")
14414{
d62a17ae 14415 int idx_ipv4 = 4;
14416 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14417 SAFI_UNICAST, NULL, 0);
718e3744 14418}
14419
14420DEFUN (clear_ip_bgp_dampening_address_mask,
14421 clear_ip_bgp_dampening_address_mask_cmd,
14422 "clear ip bgp dampening A.B.C.D A.B.C.D",
14423 CLEAR_STR
14424 IP_STR
14425 BGP_STR
14426 "Clear route flap dampening information\n"
14427 "Network to clear damping information\n"
14428 "Network mask\n")
14429{
d62a17ae 14430 int idx_ipv4 = 4;
14431 int idx_ipv4_2 = 5;
14432 int ret;
14433 char prefix_str[BUFSIZ];
718e3744 14434
d62a17ae 14435 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14436 prefix_str, sizeof(prefix_str));
d62a17ae 14437 if (!ret) {
14438 vty_out(vty, "%% Inconsistent address and mask\n");
14439 return CMD_WARNING;
14440 }
718e3744 14441
d62a17ae 14442 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14443 NULL, 0);
718e3744 14444}
6b0655a2 14445
e3b78da8 14446static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14447{
14448 struct vty *vty = arg;
e3b78da8 14449 struct peer *peer = bucket->data;
825d9834
DS
14450 char buf[SU_ADDRSTRLEN];
14451
14452 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14453 sockunion2str(&peer->su, buf, sizeof(buf)));
14454}
14455
2a0e69ae
DS
14456DEFUN (show_bgp_listeners,
14457 show_bgp_listeners_cmd,
14458 "show bgp listeners",
14459 SHOW_STR
14460 BGP_STR
14461 "Display Listen Sockets and who created them\n")
14462{
14463 bgp_dump_listener_info(vty);
14464
14465 return CMD_SUCCESS;
14466}
14467
825d9834
DS
14468DEFUN (show_bgp_peerhash,
14469 show_bgp_peerhash_cmd,
14470 "show bgp peerhash",
14471 SHOW_STR
14472 BGP_STR
14473 "Display information about the BGP peerhash\n")
14474{
14475 struct list *instances = bm->bgp;
14476 struct listnode *node;
14477 struct bgp *bgp;
14478
14479 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14480 vty_out(vty, "BGP: %s\n", bgp->name);
14481 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14482 vty);
14483 }
14484
14485 return CMD_SUCCESS;
14486}
14487
587ff0fd 14488/* also used for encap safi */
2b791107
DL
14489static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14490 afi_t afi, safi_t safi)
d62a17ae 14491{
9bcb3eef
DS
14492 struct bgp_dest *pdest;
14493 struct bgp_dest *dest;
d62a17ae 14494 struct bgp_table *table;
b54892e0
DS
14495 const struct prefix *p;
14496 const struct prefix_rd *prd;
d62a17ae 14497 struct bgp_static *bgp_static;
14498 mpls_label_t label;
d62a17ae 14499 char rdbuf[RD_ADDRSTRLEN];
14500
14501 /* Network configuration. */
9bcb3eef
DS
14502 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14503 pdest = bgp_route_next(pdest)) {
14504 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14505 if (!table)
ea47320b 14506 continue;
d62a17ae 14507
9bcb3eef
DS
14508 for (dest = bgp_table_top(table); dest;
14509 dest = bgp_route_next(dest)) {
14510 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14511 if (bgp_static == NULL)
ea47320b 14512 continue;
d62a17ae 14513
9bcb3eef
DS
14514 p = bgp_dest_get_prefix(dest);
14515 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14516 pdest);
d62a17ae 14517
ea47320b 14518 /* "network" configuration display. */
06b9f471 14519 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14520 label = decode_label(&bgp_static->label);
14521
8228a9a7 14522 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14523 if (safi == SAFI_MPLS_VPN)
14524 vty_out(vty, " label %u", label);
14525
14526 if (bgp_static->rmap.name)
14527 vty_out(vty, " route-map %s",
14528 bgp_static->rmap.name);
e2a86ad9
DS
14529
14530 if (bgp_static->backdoor)
14531 vty_out(vty, " backdoor");
14532
ea47320b
DL
14533 vty_out(vty, "\n");
14534 }
14535 }
d62a17ae 14536}
14537
2b791107
DL
14538static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14539 afi_t afi, safi_t safi)
d62a17ae 14540{
9bcb3eef
DS
14541 struct bgp_dest *pdest;
14542 struct bgp_dest *dest;
d62a17ae 14543 struct bgp_table *table;
b54892e0
DS
14544 const struct prefix *p;
14545 const struct prefix_rd *prd;
d62a17ae 14546 struct bgp_static *bgp_static;
ff44f570 14547 char buf[PREFIX_STRLEN * 2];
d62a17ae 14548 char buf2[SU_ADDRSTRLEN];
14549 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14550 char esi_buf[ESI_BYTES];
d62a17ae 14551
14552 /* Network configuration. */
9bcb3eef
DS
14553 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14554 pdest = bgp_route_next(pdest)) {
14555 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14556 if (!table)
ea47320b 14557 continue;
d62a17ae 14558
9bcb3eef
DS
14559 for (dest = bgp_table_top(table); dest;
14560 dest = bgp_route_next(dest)) {
14561 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14562 if (bgp_static == NULL)
ea47320b 14563 continue;
d62a17ae 14564
ea47320b 14565 char *macrouter = NULL;
d62a17ae 14566
ea47320b
DL
14567 if (bgp_static->router_mac)
14568 macrouter = prefix_mac2str(
14569 bgp_static->router_mac, NULL, 0);
14570 if (bgp_static->eth_s_id)
0a50c248
AK
14571 esi_to_str(bgp_static->eth_s_id,
14572 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14573 p = bgp_dest_get_prefix(dest);
14574 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14575
ea47320b 14576 /* "network" configuration display. */
06b9f471 14577 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14578 if (p->u.prefix_evpn.route_type == 5) {
14579 char local_buf[PREFIX_STRLEN];
3714a385 14580 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14581 struct prefix_evpn *)p)
14582 ? AF_INET
14583 : AF_INET6;
3714a385 14584 inet_ntop(family,
14585 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 14586 local_buf, PREFIX_STRLEN);
772270f3
QY
14587 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
14588 p->u.prefix_evpn.prefix_addr
14589 .ip_prefix_length);
197cb530
PG
14590 } else {
14591 prefix2str(p, buf, sizeof(buf));
14592 }
ea47320b 14593
a4d82a8a
PZ
14594 if (bgp_static->gatewayIp.family == AF_INET
14595 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
14596 inet_ntop(bgp_static->gatewayIp.family,
14597 &bgp_static->gatewayIp.u.prefix, buf2,
14598 sizeof(buf2));
ea47320b 14599 vty_out(vty,
7bcc8dac 14600 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 14601 buf, rdbuf,
14602 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 14603 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
14604 macrouter);
14605
0a22ddfb 14606 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
14607 }
14608 }
3da6fcd5
PG
14609}
14610
718e3744 14611/* Configuration of static route announcement and aggregate
14612 information. */
2b791107
DL
14613void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
14614 safi_t safi)
d62a17ae 14615{
9bcb3eef 14616 struct bgp_dest *dest;
b54892e0 14617 const struct prefix *p;
d62a17ae 14618 struct bgp_static *bgp_static;
14619 struct bgp_aggregate *bgp_aggregate;
d62a17ae 14620
2b791107
DL
14621 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
14622 bgp_config_write_network_vpn(vty, bgp, afi, safi);
14623 return;
14624 }
d62a17ae 14625
2b791107
DL
14626 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
14627 bgp_config_write_network_evpn(vty, bgp, afi, safi);
14628 return;
14629 }
d62a17ae 14630
14631 /* Network configuration. */
9bcb3eef
DS
14632 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
14633 dest = bgp_route_next(dest)) {
14634 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14635 if (bgp_static == NULL)
ea47320b 14636 continue;
d62a17ae 14637
9bcb3eef 14638 p = bgp_dest_get_prefix(dest);
d62a17ae 14639
8228a9a7 14640 vty_out(vty, " network %pFX", p);
d62a17ae 14641
ea47320b
DL
14642 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
14643 vty_out(vty, " label-index %u",
14644 bgp_static->label_index);
d62a17ae 14645
ea47320b
DL
14646 if (bgp_static->rmap.name)
14647 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
14648
14649 if (bgp_static->backdoor)
14650 vty_out(vty, " backdoor");
718e3744 14651
ea47320b
DL
14652 vty_out(vty, "\n");
14653 }
14654
d62a17ae 14655 /* Aggregate-address configuration. */
9bcb3eef
DS
14656 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
14657 dest = bgp_route_next(dest)) {
14658 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 14659 if (bgp_aggregate == NULL)
ea47320b 14660 continue;
d62a17ae 14661
9bcb3eef 14662 p = bgp_dest_get_prefix(dest);
d62a17ae 14663
8228a9a7 14664 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 14665
ea47320b
DL
14666 if (bgp_aggregate->as_set)
14667 vty_out(vty, " as-set");
d62a17ae 14668
ea47320b
DL
14669 if (bgp_aggregate->summary_only)
14670 vty_out(vty, " summary-only");
718e3744 14671
20894f50
DA
14672 if (bgp_aggregate->rmap.name)
14673 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
14674
229757f1
DA
14675 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
14676 vty_out(vty, " origin %s",
14677 bgp_origin2str(bgp_aggregate->origin));
14678
6aabb15d
RZ
14679 if (bgp_aggregate->match_med)
14680 vty_out(vty, " matching-MED-only");
14681
365ab2e7
RZ
14682 if (bgp_aggregate->suppress_map_name)
14683 vty_out(vty, " suppress-map %s",
14684 bgp_aggregate->suppress_map_name);
14685
ea47320b
DL
14686 vty_out(vty, "\n");
14687 }
d62a17ae 14688}
734b349e 14689
2b791107 14690void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 14691 safi_t safi)
d62a17ae 14692{
9bcb3eef 14693 struct bgp_dest *dest;
d62a17ae 14694 struct bgp_distance *bdistance;
14695
14696 /* Distance configuration. */
14697 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
14698 && bgp->distance_local[afi][safi]
14699 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
14700 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
14701 || bgp->distance_local[afi][safi]
14702 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 14703 vty_out(vty, " distance bgp %d %d %d\n",
14704 bgp->distance_ebgp[afi][safi],
14705 bgp->distance_ibgp[afi][safi],
14706 bgp->distance_local[afi][safi]);
14707 }
734b349e 14708
9bcb3eef
DS
14709 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
14710 dest = bgp_route_next(dest)) {
14711 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 14712 if (bdistance != NULL)
56ca3b5b 14713 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 14714 bdistance->distance, dest,
d62a17ae 14715 bdistance->access_list ? bdistance->access_list
14716 : "");
ca2e160d 14717 }
718e3744 14718}
14719
14720/* Allocate routing table structure and install commands. */
d62a17ae 14721void bgp_route_init(void)
14722{
14723 afi_t afi;
14724 safi_t safi;
14725
14726 /* Init BGP distance table. */
05c7a1cc 14727 FOREACH_AFI_SAFI (afi, safi)
960035b2 14728 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 14729
14730 /* IPv4 BGP commands. */
14731 install_element(BGP_NODE, &bgp_table_map_cmd);
14732 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 14733 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 14734
554b3b10 14735 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 14736
14737 /* IPv4 unicast configuration. */
14738 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
14739 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 14740 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 14741
554b3b10 14742 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 14743
14744 /* IPv4 multicast configuration. */
14745 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
14746 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 14747 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 14748 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 14749
14750 /* IPv4 labeled-unicast configuration. */
fb985e0c 14751 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 14752 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 14753
d62a17ae 14754 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
14755 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 14756 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 14757 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 14758 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 14759 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
14760 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 14761 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 14762
14763 install_element(VIEW_NODE,
14764 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
14765 install_element(VIEW_NODE,
14766 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 14767 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
14768 install_element(VIEW_NODE,
14769 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 14770#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14771 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 14772#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 14773 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
14774 install_element(VIEW_NODE,
44c69747 14775 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 14776
d62a17ae 14777 /* BGP dampening clear commands */
14778 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
14779 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 14780
d62a17ae 14781 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
14782 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
14783
14784 /* prefix count */
14785 install_element(ENABLE_NODE,
14786 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 14787#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 14788 install_element(ENABLE_NODE,
14789 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 14790#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 14791
d62a17ae 14792 /* New config IPv6 BGP commands. */
14793 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
14794 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14795 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 14796
554b3b10 14797 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 14798
14799 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 14800
fb985e0c
DA
14801 /* IPv6 labeled unicast address family. */
14802 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 14803 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 14804
d62a17ae 14805 install_element(BGP_NODE, &bgp_distance_cmd);
14806 install_element(BGP_NODE, &no_bgp_distance_cmd);
14807 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 14808 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
14809 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
14810 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 14811 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
14812 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
14813 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 14814 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
14815 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 14816 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 14817 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
14818 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 14819 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 14820
ef5f4b23 14821 /* BGP dampening */
d9ce5113
CS
14822 install_element(BGP_NODE, &bgp_dampening_cmd);
14823 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
14824 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
14825 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
14826 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
14827 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
14828 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 14829
14830 /* Large Communities */
14831 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
14832 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
14833
14834 /* show bgp ipv4 flowspec detailed */
14835 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
14836
2a0e69ae 14837 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 14838 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 14839}
14840
14841void bgp_route_finish(void)
14842{
14843 afi_t afi;
14844 safi_t safi;
14845
05c7a1cc
QY
14846 FOREACH_AFI_SAFI (afi, safi) {
14847 bgp_table_unlock(bgp_distance_table[afi][safi]);
14848 bgp_distance_table[afi][safi] = NULL;
14849 }
228da428 14850}