]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #9302 from ton31337/fix/comments
[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"
a70a28a5 26#include "frrstr.h"
718e3744 27#include "prefix.h"
28#include "linklist.h"
29#include "memory.h"
30#include "command.h"
31#include "stream.h"
32#include "filter.h"
718e3744 33#include "log.h"
34#include "routemap.h"
35#include "buffer.h"
36#include "sockunion.h"
37#include "plist.h"
38#include "thread.h"
200df115 39#include "workqueue.h"
3f9c7369 40#include "queue.h"
6e919709 41#include "memory.h"
e496b420 42#include "srv6.h"
4dcadbef 43#include "lib/json.h"
d8d084d9 44#include "lib_errors.h"
8c48b3b6 45#include "zclient.h"
718e3744 46#include "bgpd/bgpd.h"
47#include "bgpd/bgp_table.h"
48#include "bgpd/bgp_route.h"
49#include "bgpd/bgp_attr.h"
50#include "bgpd/bgp_debug.h"
14454c9f 51#include "bgpd/bgp_errors.h"
718e3744 52#include "bgpd/bgp_aspath.h"
53#include "bgpd/bgp_regex.h"
54#include "bgpd/bgp_community.h"
ed0e57e3 55#include "bgpd/bgp_community_alias.h"
718e3744 56#include "bgpd/bgp_ecommunity.h"
57d187bc 57#include "bgpd/bgp_lcommunity.h"
718e3744 58#include "bgpd/bgp_clist.h"
59#include "bgpd/bgp_packet.h"
60#include "bgpd/bgp_filter.h"
61#include "bgpd/bgp_fsm.h"
62#include "bgpd/bgp_mplsvpn.h"
63#include "bgpd/bgp_nexthop.h"
64#include "bgpd/bgp_damp.h"
65#include "bgpd/bgp_advertise.h"
66#include "bgpd/bgp_zebra.h"
0a486e5f 67#include "bgpd/bgp_vty.h"
96450faf 68#include "bgpd/bgp_mpath.h"
fc9a856f 69#include "bgpd/bgp_nht.h"
3f9c7369 70#include "bgpd/bgp_updgrp.h"
cd1964ff 71#include "bgpd/bgp_label.h"
dcc68b5e 72#include "bgpd/bgp_addpath.h"
4e802e66 73#include "bgpd/bgp_mac.h"
2a0e69ae 74#include "bgpd/bgp_network.h"
6401252f 75#include "bgpd/bgp_trace.h"
fdeb5a81 76#include "bgpd/bgp_rpki.h"
718e3744 77
49e5a4a0 78#ifdef ENABLE_BGP_VNC
f8b6f499
LB
79#include "bgpd/rfapi/rfapi_backend.h"
80#include "bgpd/rfapi/vnc_import_bgp.h"
81#include "bgpd/rfapi/vnc_export_bgp.h"
65efcfce 82#endif
aee875b5
PG
83#include "bgpd/bgp_encap_types.h"
84#include "bgpd/bgp_encap_tlv.h"
684a7227 85#include "bgpd/bgp_evpn.h"
0a50c248 86#include "bgpd/bgp_evpn_mh.h"
3da6fcd5 87#include "bgpd/bgp_evpn_vty.h"
dba3c1d3 88#include "bgpd/bgp_flowspec.h"
98a9dbc7 89#include "bgpd/bgp_flowspec_util.h"
45918cfb 90#include "bgpd/bgp_pbr.h"
37a87b8f
CS
91#include "northbound.h"
92#include "northbound_cli.h"
93#include "bgpd/bgp_nb.h"
65efcfce 94
e2a86ad9
DS
95#ifndef VTYSH_EXTRACT_PL
96#include "bgpd/bgp_route_clippy.c"
97#endif
aee875b5 98
7fd28dd2
PR
99DEFINE_HOOK(bgp_snmp_update_stats,
100 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 101 (rn, pi, added));
7fd28dd2 102
b5b99af8
DS
103DEFINE_HOOK(bgp_rpki_prefix_status,
104 (struct peer *peer, struct attr *attr,
105 const struct prefix *prefix),
8451921b 106 (peer, attr, prefix));
b5b99af8 107
718e3744 108/* Extern from bgp_dump.c */
dde72586
SH
109extern const char *bgp_origin_str[];
110extern const char *bgp_origin_long_str[];
3742de8d 111
b7d08f5a 112/* PMSI strings. */
113#define PMSI_TNLTYPE_STR_NO_INFO "No info"
114#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
115static const struct message bgp_pmsi_tnltype_str[] = {
116 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
117 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
118 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
119 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
120 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
121 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
122 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
123 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 124 {0}
125};
b7d08f5a 126
9df8b37c 127#define VRFID_NONE_STR "-"
46aeabed 128#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 129
4a11bf2c 130DEFINE_HOOK(bgp_process,
9bcb3eef
DS
131 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
132 struct peer *peer, bool withdraw),
8451921b 133 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 134
4056a5f6
RZ
135/** Test if path is suppressed. */
136static bool bgp_path_suppressed(struct bgp_path_info *pi)
137{
138 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
139 return false;
140
141 return listcount(pi->extra->aggr_suppressors) > 0;
142}
4a11bf2c 143
9bcb3eef 144struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 145 safi_t safi, const struct prefix *p,
d62a17ae 146 struct prefix_rd *prd)
147{
9bcb3eef
DS
148 struct bgp_dest *dest;
149 struct bgp_dest *pdest = NULL;
d62a17ae 150
151 assert(table);
d62a17ae 152
153 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
154 || (safi == SAFI_EVPN)) {
9bcb3eef 155 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 156
9bcb3eef
DS
157 if (!bgp_dest_has_bgp_path_info_data(pdest))
158 bgp_dest_set_bgp_table_info(
159 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 160 else
9bcb3eef
DS
161 bgp_dest_unlock_node(pdest);
162 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 163 }
718e3744 164
9bcb3eef 165 dest = bgp_node_get(table, p);
718e3744 166
d62a17ae 167 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
168 || (safi == SAFI_EVPN))
9bcb3eef 169 dest->pdest = pdest;
718e3744 170
9bcb3eef 171 return dest;
718e3744 172}
6b0655a2 173
9bcb3eef 174struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 175 safi_t safi, const struct prefix *p,
d62a17ae 176 struct prefix_rd *prd)
128ea8ab 177{
9bcb3eef
DS
178 struct bgp_dest *dest;
179 struct bgp_dest *pdest = NULL;
128ea8ab 180
d62a17ae 181 if (!table)
182 return NULL;
128ea8ab 183
d62a17ae 184 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
185 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
186 pdest = bgp_node_lookup(table, (struct prefix *)prd);
187 if (!pdest)
d62a17ae 188 return NULL;
128ea8ab 189
9bcb3eef
DS
190 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
191 bgp_dest_unlock_node(pdest);
d62a17ae 192 return NULL;
193 }
128ea8ab 194
9bcb3eef 195 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 196 }
128ea8ab 197
9bcb3eef 198 dest = bgp_node_lookup(table, p);
128ea8ab 199
9bcb3eef 200 return dest;
128ea8ab 201}
202
18ee8310
DS
203/* Allocate bgp_path_info_extra */
204static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 205{
4b7e6066
DS
206 struct bgp_path_info_extra *new;
207 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
208 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
209 new->label[0] = MPLS_INVALID_LABEL;
210 new->num_labels = 0;
3e3708cb
PG
211 new->bgp_fs_pbr = NULL;
212 new->bgp_fs_iprule = NULL;
d62a17ae 213 return new;
fb982c25
PJ
214}
215
a2e219fe 216void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 217{
4b7e6066 218 struct bgp_path_info_extra *e;
d62a17ae 219
c93a3b77
DS
220 if (!extra || !*extra)
221 return;
d62a17ae 222
c93a3b77 223 e = *extra;
d62a17ae 224
4538f895
IR
225 if (e->damp_info)
226 bgp_damp_info_free(e->damp_info, 0);
c93a3b77 227 e->damp_info = NULL;
4538f895 228
c93a3b77 229 if (e->parent) {
40381db7 230 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 231
40381db7 232 if (bpi->net) {
0e70e6c8
DL
233 /* FIXME: since multiple e may have the same e->parent
234 * and e->parent->net is holding a refcount for each
235 * of them, we need to do some fudging here.
236 *
40381db7
DS
237 * WARNING: if bpi->net->lock drops to 0, bpi may be
238 * freed as well (because bpi->net was holding the
239 * last reference to bpi) => write after free!
0e70e6c8
DL
240 */
241 unsigned refcount;
242
40381db7 243 bpi = bgp_path_info_lock(bpi);
c10e14e9 244 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 245 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 246 if (!refcount)
40381db7
DS
247 bpi->net = NULL;
248 bgp_path_info_unlock(bpi);
0e70e6c8 249 }
18ee8310 250 bgp_path_info_unlock(e->parent);
c93a3b77 251 e->parent = NULL;
d62a17ae 252 }
c93a3b77
DS
253
254 if (e->bgp_orig)
255 bgp_unlock(e->bgp_orig);
c26edcda 256
ff3bf9a4
DS
257 if (e->aggr_suppressors)
258 list_delete(&e->aggr_suppressors);
259
60605cbc
AK
260 if (e->mh_info)
261 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 262
ce3c0614
PG
263 if ((*extra)->bgp_fs_iprule)
264 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 265 if ((*extra)->bgp_fs_pbr)
6a154c88 266 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 267 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
268}
269
18ee8310
DS
270/* Get bgp_path_info extra information for the given bgp_path_info, lazy
271 * allocated if required.
fb982c25 272 */
40381db7 273struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 274{
40381db7
DS
275 if (!pi->extra)
276 pi->extra = bgp_path_info_extra_new();
277 return pi->extra;
fb982c25
PJ
278}
279
718e3744 280/* Free bgp route information. */
9b6d8fcf 281static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 282{
05864da7 283 bgp_attr_unintern(&path->attr);
fb018d25 284
9b6d8fcf
DS
285 bgp_unlink_nexthop(path);
286 bgp_path_info_extra_free(&path->extra);
287 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
288 if (path->net)
289 bgp_addpath_free_info_data(&path->tx_addpath,
290 &path->net->tx_addpath);
718e3744 291
9b6d8fcf 292 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 293
9b6d8fcf 294 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 295}
296
9b6d8fcf 297struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 298{
9b6d8fcf
DS
299 path->lock++;
300 return path;
200df115 301}
302
9b6d8fcf 303struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 304{
9b6d8fcf
DS
305 assert(path && path->lock > 0);
306 path->lock--;
d62a17ae 307
9b6d8fcf 308 if (path->lock == 0) {
200df115 309#if 0
310 zlog_debug ("%s: unlocked and freeing", __func__);
311 zlog_backtrace (LOG_DEBUG);
312#endif
9b6d8fcf 313 bgp_path_info_free(path);
d62a17ae 314 return NULL;
315 }
200df115 316
317#if 0
9b6d8fcf 318 if (path->lock == 1)
200df115 319 {
320 zlog_debug ("%s: unlocked to 1", __func__);
321 zlog_backtrace (LOG_DEBUG);
322 }
323#endif
d62a17ae 324
9b6d8fcf 325 return path;
200df115 326}
327
f009ff26 328/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 329static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 330{
331 struct peer *peer;
332 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 333 bool set_flag = false;
f009ff26 334 struct bgp *bgp = NULL;
335 struct bgp_table *table = NULL;
336 afi_t afi = 0;
337 safi_t safi = 0;
f009ff26 338
339 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
340 * then the route selection is deferred
341 */
9bcb3eef 342 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 343 return 0;
344
9bcb3eef 345 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 346 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 347 zlog_debug(
56ca3b5b
DL
348 "Route %pBD is in workqueue and being processed, not deferred.",
349 dest);
b54892e0 350
5f9c1aa2 351 return 0;
352 }
353
9bcb3eef 354 table = bgp_dest_table(dest);
f009ff26 355 if (table) {
356 bgp = table->bgp;
357 afi = table->afi;
358 safi = table->safi;
359 }
360
9bcb3eef 361 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 362 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
363 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
364 continue;
365
366 /* Route selection is deferred if there is a stale path which
367 * which indicates peer is in restart mode
368 */
36235319
QY
369 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
370 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 371 set_flag = true;
f009ff26 372 } else {
373 /* If the peer is graceful restart capable and peer is
374 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
375 */
376 peer = old_pi->peer;
36235319
QY
377 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
378 && BGP_PEER_RESTARTING_MODE(peer)
379 && (old_pi
380 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 381 set_flag = true;
f009ff26 382 }
383 }
384 if (set_flag)
385 break;
386 }
387
388 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
389 * is active
390 */
2ba1fe69 391 if (set_flag && table) {
f009ff26 392 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
393 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
394 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 395 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 396 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
397 zlog_debug("DEFER route %pBD, dest %p", dest,
398 dest);
f009ff26 399 return 0;
400 }
401 }
402 return -1;
403}
404
9bcb3eef 405void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 406{
4b7e6066 407 struct bgp_path_info *top;
718e3744 408
9bcb3eef 409 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 410
6f94b685 411 pi->next = top;
40381db7 412 pi->prev = NULL;
d62a17ae 413 if (top)
40381db7 414 top->prev = pi;
9bcb3eef 415 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 416
40381db7 417 bgp_path_info_lock(pi);
9bcb3eef 418 bgp_dest_lock_node(dest);
40381db7 419 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 420 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 421 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 422}
423
d62a17ae 424/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 425 completion callback *only* */
9bcb3eef 426void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 427{
40381db7
DS
428 if (pi->next)
429 pi->next->prev = pi->prev;
430 if (pi->prev)
431 pi->prev->next = pi->next;
d62a17ae 432 else
9bcb3eef 433 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 434
40381db7
DS
435 bgp_path_info_mpath_dequeue(pi);
436 bgp_path_info_unlock(pi);
7fd28dd2 437 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 438 bgp_dest_unlock_node(dest);
718e3744 439}
440
9bcb3eef 441void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 442{
9bcb3eef 443 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 444 /* set of previous already took care of pcount */
40381db7 445 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 446}
447
18ee8310 448/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
449 called when a route is deleted and then quickly re-added before the
450 deletion has been processed */
9bcb3eef 451void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 452{
9bcb3eef 453 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 454 /* unset of previous already took care of pcount */
40381db7 455 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
456}
457
d62a17ae 458/* Adjust pcount as required */
9bcb3eef 459static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 460{
d62a17ae 461 struct bgp_table *table;
67174041 462
9bcb3eef 463 assert(dest && bgp_dest_table(dest));
40381db7 464 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 465
9bcb3eef 466 table = bgp_dest_table(dest);
67174041 467
40381db7 468 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 469 return;
470
40381db7
DS
471 if (!BGP_PATH_COUNTABLE(pi)
472 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 473
40381db7 474 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 475
476 /* slight hack, but more robust against errors. */
40381db7
DS
477 if (pi->peer->pcount[table->afi][table->safi])
478 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 479 else
450971aa 480 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 481 "Asked to decrement 0 prefix count for peer");
40381db7
DS
482 } else if (BGP_PATH_COUNTABLE(pi)
483 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
484 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
485 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 486 }
1a392d46
PJ
487}
488
40381db7
DS
489static int bgp_label_index_differs(struct bgp_path_info *pi1,
490 struct bgp_path_info *pi2)
28d58fd7 491{
40381db7 492 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 493}
1a392d46 494
18ee8310 495/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
496 * This is here primarily to keep prefix-count in check.
497 */
9bcb3eef 498void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 499 uint32_t flag)
1a392d46 500{
40381db7 501 SET_FLAG(pi->flags, flag);
d62a17ae 502
503 /* early bath if we know it's not a flag that changes countability state
504 */
505 if (!CHECK_FLAG(flag,
1defdda8 506 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 507 return;
508
9bcb3eef 509 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
510}
511
9bcb3eef 512void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 513 uint32_t flag)
1a392d46 514{
40381db7 515 UNSET_FLAG(pi->flags, flag);
d62a17ae 516
517 /* early bath if we know it's not a flag that changes countability state
518 */
519 if (!CHECK_FLAG(flag,
1defdda8 520 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 521 return;
522
9bcb3eef 523 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
524}
525
718e3744 526/* Get MED value. If MED value is missing and "bgp bestpath
527 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 528static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 529{
530 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
531 return attr->med;
532 else {
892fedb6 533 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 534 return BGP_MED_MAX;
535 else
536 return 0;
537 }
718e3744 538}
539
7533cad7
QY
540void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
541 size_t buf_len)
2ec1e66f 542{
40381db7 543 if (pi->addpath_rx_id)
7533cad7
QY
544 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
545 pi->peer->host, pi->addpath_rx_id);
d62a17ae 546 else
7533cad7 547 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 548}
9fbdd100 549
d62a17ae 550/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
551 */
18ee8310
DS
552static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
553 struct bgp_path_info *exist, int *paths_eq,
554 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
555 char *pfx_buf, afi_t afi, safi_t safi,
556 enum bgp_path_selection_reason *reason)
d62a17ae 557{
5df26422 558 const struct prefix *new_p;
d62a17ae 559 struct attr *newattr, *existattr;
560 bgp_peer_sort_t new_sort;
561 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
562 uint32_t new_pref;
563 uint32_t exist_pref;
564 uint32_t new_med;
565 uint32_t exist_med;
566 uint32_t new_weight;
567 uint32_t exist_weight;
d62a17ae 568 uint32_t newm, existm;
569 struct in_addr new_id;
570 struct in_addr exist_id;
571 int new_cluster;
572 int exist_cluster;
573 int internal_as_route;
574 int confed_as_route;
04d14c8b 575 int ret = 0;
ee88563a
JM
576 int igp_metric_ret = 0;
577 int peer_sort_ret = -1;
d62a17ae 578 char new_buf[PATH_ADDPATH_STR_BUFFER];
579 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
580 uint32_t new_mm_seq;
581 uint32_t exist_mm_seq;
6d8c603a 582 int nh_cmp;
d071f237
AK
583 esi_t *exist_esi;
584 esi_t *new_esi;
585 bool same_esi;
586 bool old_proxy;
587 bool new_proxy;
33c6e933 588 bool new_origin, exist_origin;
d62a17ae 589
590 *paths_eq = 0;
591
592 /* 0. Null check. */
593 if (new == NULL) {
fdf81fa0 594 *reason = bgp_path_selection_none;
d62a17ae 595 if (debug)
596 zlog_debug("%s: new is NULL", pfx_buf);
597 return 0;
598 }
2ec1e66f 599
d62a17ae 600 if (debug)
7533cad7
QY
601 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
602 sizeof(new_buf));
718e3744 603
d62a17ae 604 if (exist == NULL) {
fdf81fa0 605 *reason = bgp_path_selection_first;
d62a17ae 606 if (debug)
607 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
608 new_buf);
609 return 1;
610 }
2ec1e66f 611
d62a17ae 612 if (debug) {
7533cad7
QY
613 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
614 sizeof(exist_buf));
d62a17ae 615 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
616 pfx_buf, new_buf, new->flags, exist_buf,
617 exist->flags);
618 }
8ff56318 619
d62a17ae 620 newattr = new->attr;
621 existattr = exist->attr;
622
5df26422
NS
623 new_p = bgp_dest_get_prefix(new->net);
624
d62a17ae 625 /* For EVPN routes, we cannot just go by local vs remote, we have to
626 * look at the MAC mobility sequence number, if present.
627 */
5df26422
NS
628 if ((safi == SAFI_EVPN)
629 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 630 /* This is an error condition described in RFC 7432 Section
631 * 15.2. The RFC
632 * states that in this scenario "the PE MUST alert the operator"
633 * but it
634 * does not state what other action to take. In order to provide
635 * some
636 * consistency in this scenario we are going to prefer the path
637 * with the
638 * sticky flag.
639 */
640 if (newattr->sticky != existattr->sticky) {
641 if (!debug) {
5df26422
NS
642 prefix2str(new_p, pfx_buf,
643 sizeof(*pfx_buf)
644 * PREFIX2STR_BUFFER);
18ee8310 645 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
646 new, new_buf, sizeof(new_buf));
647 bgp_path_info_path_with_addpath_rx_str(
648 exist, exist_buf, sizeof(exist_buf));
d62a17ae 649 }
650
651 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 652 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
653 if (debug)
654 zlog_debug(
655 "%s: %s wins over %s due to sticky MAC flag",
656 pfx_buf, new_buf, exist_buf);
d62a17ae 657 return 1;
658 }
659
660 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 661 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
662 if (debug)
663 zlog_debug(
664 "%s: %s loses to %s due to sticky MAC flag",
665 pfx_buf, new_buf, exist_buf);
d62a17ae 666 return 0;
667 }
668 }
128ea8ab 669
d071f237
AK
670 new_esi = bgp_evpn_attr_get_esi(newattr);
671 exist_esi = bgp_evpn_attr_get_esi(existattr);
672 if (bgp_evpn_is_esi_valid(new_esi) &&
673 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
674 same_esi = true;
675 } else {
676 same_esi = false;
677 }
678
679 /* If both paths have the same non-zero ES and
680 * one path is local it wins.
681 * PS: Note the local path wins even if the remote
682 * has the higher MM seq. The local path's
683 * MM seq will be fixed up to match the highest
684 * rem seq, subsequently.
685 */
686 if (same_esi) {
687 char esi_buf[ESI_STR_LEN];
688
689 if (bgp_evpn_is_path_local(bgp, new)) {
690 *reason = bgp_path_selection_evpn_local_path;
691 if (debug)
692 zlog_debug(
693 "%s: %s wins over %s as ES %s is same and local",
694 pfx_buf, new_buf, exist_buf,
695 esi_to_str(new_esi, esi_buf,
696 sizeof(esi_buf)));
697 return 1;
698 }
699 if (bgp_evpn_is_path_local(bgp, exist)) {
700 *reason = bgp_path_selection_evpn_local_path;
701 if (debug)
702 zlog_debug(
703 "%s: %s loses to %s as ES %s is same and local",
704 pfx_buf, new_buf, exist_buf,
705 esi_to_str(new_esi, esi_buf,
706 sizeof(esi_buf)));
707 return 0;
708 }
709 }
710
d62a17ae 711 new_mm_seq = mac_mobility_seqnum(newattr);
712 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 713
d62a17ae 714 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 715 *reason = bgp_path_selection_evpn_seq;
d62a17ae 716 if (debug)
717 zlog_debug(
718 "%s: %s wins over %s due to MM seq %u > %u",
719 pfx_buf, new_buf, exist_buf, new_mm_seq,
720 exist_mm_seq);
721 return 1;
722 }
8ff56318 723
d62a17ae 724 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 725 *reason = bgp_path_selection_evpn_seq;
d62a17ae 726 if (debug)
727 zlog_debug(
728 "%s: %s loses to %s due to MM seq %u < %u",
729 pfx_buf, new_buf, exist_buf, new_mm_seq,
730 exist_mm_seq);
731 return 0;
732 }
6d8c603a 733
d071f237
AK
734 /* if the sequence numbers and ESI are the same and one path
735 * is non-proxy it wins (over proxy)
736 */
737 new_proxy = bgp_evpn_attr_is_proxy(newattr);
738 old_proxy = bgp_evpn_attr_is_proxy(existattr);
739 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
740 old_proxy != new_proxy) {
741 if (!new_proxy) {
742 *reason = bgp_path_selection_evpn_non_proxy;
743 if (debug)
744 zlog_debug(
745 "%s: %s wins over %s, same seq/es and non-proxy",
746 pfx_buf, new_buf, exist_buf);
747 return 1;
748 }
749
750 *reason = bgp_path_selection_evpn_non_proxy;
751 if (debug)
752 zlog_debug(
753 "%s: %s loses to %s, same seq/es and non-proxy",
754 pfx_buf, new_buf, exist_buf);
755 return 0;
756 }
757
6d8c603a
AK
758 /*
759 * if sequence numbers are the same path with the lowest IP
760 * wins
761 */
762 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
763 if (nh_cmp < 0) {
fdf81fa0 764 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
765 if (debug)
766 zlog_debug(
23d0a753 767 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 768 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 769 &new->attr->nexthop);
6d8c603a
AK
770 return 1;
771 }
772 if (nh_cmp > 0) {
fdf81fa0 773 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
774 if (debug)
775 zlog_debug(
23d0a753 776 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 777 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 778 &new->attr->nexthop);
6d8c603a
AK
779 return 0;
780 }
d62a17ae 781 }
9fbdd100 782
d62a17ae 783 /* 1. Weight check. */
d62a17ae 784 new_weight = newattr->weight;
785 exist_weight = existattr->weight;
8ff56318 786
d62a17ae 787 if (new_weight > exist_weight) {
fdf81fa0 788 *reason = bgp_path_selection_weight;
d62a17ae 789 if (debug)
790 zlog_debug("%s: %s wins over %s due to weight %d > %d",
791 pfx_buf, new_buf, exist_buf, new_weight,
792 exist_weight);
793 return 1;
794 }
718e3744 795
d62a17ae 796 if (new_weight < exist_weight) {
fdf81fa0 797 *reason = bgp_path_selection_weight;
d62a17ae 798 if (debug)
799 zlog_debug("%s: %s loses to %s due to weight %d < %d",
800 pfx_buf, new_buf, exist_buf, new_weight,
801 exist_weight);
802 return 0;
803 }
9fbdd100 804
d62a17ae 805 /* 2. Local preference check. */
806 new_pref = exist_pref = bgp->default_local_pref;
807
808 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
809 new_pref = newattr->local_pref;
810 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
811 exist_pref = existattr->local_pref;
812
813 if (new_pref > exist_pref) {
fdf81fa0 814 *reason = bgp_path_selection_local_pref;
d62a17ae 815 if (debug)
816 zlog_debug(
817 "%s: %s wins over %s due to localpref %d > %d",
818 pfx_buf, new_buf, exist_buf, new_pref,
819 exist_pref);
820 return 1;
821 }
718e3744 822
d62a17ae 823 if (new_pref < exist_pref) {
fdf81fa0 824 *reason = bgp_path_selection_local_pref;
d62a17ae 825 if (debug)
826 zlog_debug(
827 "%s: %s loses to %s due to localpref %d < %d",
828 pfx_buf, new_buf, exist_buf, new_pref,
829 exist_pref);
830 return 0;
831 }
9fbdd100 832
d62a17ae 833 /* 3. Local route check. We prefer:
834 * - BGP_ROUTE_STATIC
835 * - BGP_ROUTE_AGGREGATE
836 * - BGP_ROUTE_REDISTRIBUTE
837 */
33c6e933
DS
838 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
839 new->sub_type == BGP_ROUTE_IMPORTED);
840 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
841 exist->sub_type == BGP_ROUTE_IMPORTED);
842
843 if (new_origin && !exist_origin) {
fdf81fa0 844 *reason = bgp_path_selection_local_route;
d62a17ae 845 if (debug)
846 zlog_debug(
847 "%s: %s wins over %s due to preferred BGP_ROUTE type",
848 pfx_buf, new_buf, exist_buf);
849 return 1;
850 }
718e3744 851
33c6e933 852 if (!new_origin && exist_origin) {
fdf81fa0 853 *reason = bgp_path_selection_local_route;
d62a17ae 854 if (debug)
855 zlog_debug(
856 "%s: %s loses to %s due to preferred BGP_ROUTE type",
857 pfx_buf, new_buf, exist_buf);
858 return 0;
6811845b 859 }
718e3744 860
d62a17ae 861 /* 4. AS path length check. */
892fedb6 862 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 863 int exist_hops = aspath_count_hops(existattr->aspath);
864 int exist_confeds = aspath_count_confeds(existattr->aspath);
865
892fedb6 866 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 867 int aspath_hops;
868
869 aspath_hops = aspath_count_hops(newattr->aspath);
870 aspath_hops += aspath_count_confeds(newattr->aspath);
871
872 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 873 *reason = bgp_path_selection_confed_as_path;
d62a17ae 874 if (debug)
875 zlog_debug(
876 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
877 pfx_buf, new_buf, exist_buf,
878 aspath_hops,
879 (exist_hops + exist_confeds));
880 return 1;
881 }
882
883 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 884 *reason = bgp_path_selection_confed_as_path;
d62a17ae 885 if (debug)
886 zlog_debug(
887 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
888 pfx_buf, new_buf, exist_buf,
889 aspath_hops,
890 (exist_hops + exist_confeds));
891 return 0;
892 }
893 } else {
894 int newhops = aspath_count_hops(newattr->aspath);
895
896 if (newhops < exist_hops) {
fdf81fa0 897 *reason = bgp_path_selection_as_path;
d62a17ae 898 if (debug)
899 zlog_debug(
900 "%s: %s wins over %s due to aspath hopcount %d < %d",
901 pfx_buf, new_buf, exist_buf,
902 newhops, exist_hops);
903 return 1;
904 }
905
906 if (newhops > exist_hops) {
fdf81fa0 907 *reason = bgp_path_selection_as_path;
d62a17ae 908 if (debug)
909 zlog_debug(
910 "%s: %s loses to %s due to aspath hopcount %d > %d",
911 pfx_buf, new_buf, exist_buf,
912 newhops, exist_hops);
913 return 0;
914 }
915 }
916 }
9fbdd100 917
d62a17ae 918 /* 5. Origin check. */
919 if (newattr->origin < existattr->origin) {
fdf81fa0 920 *reason = bgp_path_selection_origin;
d62a17ae 921 if (debug)
922 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
923 pfx_buf, new_buf, exist_buf,
924 bgp_origin_long_str[newattr->origin],
925 bgp_origin_long_str[existattr->origin]);
926 return 1;
927 }
718e3744 928
d62a17ae 929 if (newattr->origin > existattr->origin) {
fdf81fa0 930 *reason = bgp_path_selection_origin;
d62a17ae 931 if (debug)
932 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
933 pfx_buf, new_buf, exist_buf,
934 bgp_origin_long_str[newattr->origin],
935 bgp_origin_long_str[existattr->origin]);
936 return 0;
937 }
718e3744 938
d62a17ae 939 /* 6. MED check. */
940 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
941 && aspath_count_hops(existattr->aspath) == 0);
942 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
943 && aspath_count_confeds(existattr->aspath) > 0
944 && aspath_count_hops(newattr->aspath) == 0
945 && aspath_count_hops(existattr->aspath) == 0);
946
892fedb6
DA
947 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
948 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 949 || aspath_cmp_left(newattr->aspath, existattr->aspath)
950 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
951 || internal_as_route) {
952 new_med = bgp_med_value(new->attr, bgp);
953 exist_med = bgp_med_value(exist->attr, bgp);
954
955 if (new_med < exist_med) {
fdf81fa0 956 *reason = bgp_path_selection_med;
d62a17ae 957 if (debug)
958 zlog_debug(
959 "%s: %s wins over %s due to MED %d < %d",
960 pfx_buf, new_buf, exist_buf, new_med,
961 exist_med);
962 return 1;
963 }
8ff56318 964
d62a17ae 965 if (new_med > exist_med) {
fdf81fa0 966 *reason = bgp_path_selection_med;
d62a17ae 967 if (debug)
968 zlog_debug(
969 "%s: %s loses to %s due to MED %d > %d",
970 pfx_buf, new_buf, exist_buf, new_med,
971 exist_med);
972 return 0;
973 }
974 }
9fbdd100 975
d62a17ae 976 /* 7. Peer type check. */
977 new_sort = new->peer->sort;
978 exist_sort = exist->peer->sort;
979
980 if (new_sort == BGP_PEER_EBGP
981 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 982 *reason = bgp_path_selection_peer;
d62a17ae 983 if (debug)
984 zlog_debug(
985 "%s: %s wins over %s due to eBGP peer > iBGP peer",
986 pfx_buf, new_buf, exist_buf);
ee88563a
JM
987 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
988 return 1;
989 peer_sort_ret = 1;
d62a17ae 990 }
718e3744 991
d62a17ae 992 if (exist_sort == BGP_PEER_EBGP
993 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 994 *reason = bgp_path_selection_peer;
d62a17ae 995 if (debug)
996 zlog_debug(
997 "%s: %s loses to %s due to iBGP peer < eBGP peer",
998 pfx_buf, new_buf, exist_buf);
ee88563a
JM
999 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1000 return 0;
1001 peer_sort_ret = 0;
d62a17ae 1002 }
8ff56318 1003
d62a17ae 1004 /* 8. IGP metric check. */
1005 newm = existm = 0;
8ff56318 1006
d62a17ae 1007 if (new->extra)
1008 newm = new->extra->igpmetric;
1009 if (exist->extra)
1010 existm = exist->extra->igpmetric;
9fbdd100 1011
d62a17ae 1012 if (newm < existm) {
ee88563a 1013 if (debug && peer_sort_ret < 0)
d62a17ae 1014 zlog_debug(
d588b995 1015 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1016 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1017 igp_metric_ret = 1;
d62a17ae 1018 }
718e3744 1019
d62a17ae 1020 if (newm > existm) {
ee88563a 1021 if (debug && peer_sort_ret < 0)
d62a17ae 1022 zlog_debug(
d588b995 1023 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1024 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1025 igp_metric_ret = 0;
5e242b0d 1026 }
5e242b0d 1027
d62a17ae 1028 /* 9. Same IGP metric. Compare the cluster list length as
1029 representative of IGP hops metric. Rewrite the metric value
1030 pair (newm, existm) with the cluster list length. Prefer the
1031 path with smaller cluster list length. */
1032 if (newm == existm) {
bf0d28dc
DS
1033 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1034 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1035 && (mpath_cfg == NULL
1036 || CHECK_FLAG(
1037 mpath_cfg->ibgp_flags,
1038 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1039 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1040 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1041
1042 if (newm < existm) {
ee88563a 1043 if (debug && peer_sort_ret < 0)
d62a17ae 1044 zlog_debug(
d588b995 1045 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1046 pfx_buf, new_buf, exist_buf,
1047 newm, existm);
ee88563a 1048 igp_metric_ret = 1;
d62a17ae 1049 }
1050
1051 if (newm > existm) {
ee88563a 1052 if (debug && peer_sort_ret < 0)
d62a17ae 1053 zlog_debug(
d588b995 1054 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1055 pfx_buf, new_buf, exist_buf,
1056 newm, existm);
ee88563a 1057 igp_metric_ret = 0;
d62a17ae 1058 }
1059 }
1060 }
31a4638f 1061
d62a17ae 1062 /* 10. confed-external vs. confed-internal */
1063 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1064 if (new_sort == BGP_PEER_CONFED
1065 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1066 *reason = bgp_path_selection_confed;
d62a17ae 1067 if (debug)
1068 zlog_debug(
1069 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1070 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1071 if (!CHECK_FLAG(bgp->flags,
1072 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1073 return 1;
1074 peer_sort_ret = 1;
d62a17ae 1075 }
718e3744 1076
d62a17ae 1077 if (exist_sort == BGP_PEER_CONFED
1078 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1079 *reason = bgp_path_selection_confed;
d62a17ae 1080 if (debug)
1081 zlog_debug(
1082 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1083 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1084 if (!CHECK_FLAG(bgp->flags,
1085 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1086 return 0;
1087 peer_sort_ret = 0;
d62a17ae 1088 }
1089 }
718e3744 1090
d62a17ae 1091 /* 11. Maximum path check. */
1092 if (newm == existm) {
1093 /* If one path has a label but the other does not, do not treat
1094 * them as equals for multipath
1095 */
a4d82a8a 1096 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1097 != (exist->extra
b57ba6d2 1098 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1099 if (debug)
1100 zlog_debug(
1101 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1102 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1103 } else if (CHECK_FLAG(bgp->flags,
1104 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1105
1106 /*
1107 * For the two paths, all comparison steps till IGP
1108 * metric
1109 * have succeeded - including AS_PATH hop count. Since
1110 * 'bgp
1111 * bestpath as-path multipath-relax' knob is on, we
1112 * don't need
1113 * an exact match of AS_PATH. Thus, mark the paths are
1114 * equal.
1115 * That will trigger both these paths to get into the
1116 * multipath
1117 * array.
1118 */
1119 *paths_eq = 1;
1120
1121 if (debug)
1122 zlog_debug(
1123 "%s: %s and %s are equal via multipath-relax",
1124 pfx_buf, new_buf, exist_buf);
1125 } else if (new->peer->sort == BGP_PEER_IBGP) {
1126 if (aspath_cmp(new->attr->aspath,
1127 exist->attr->aspath)) {
1128 *paths_eq = 1;
1129
1130 if (debug)
1131 zlog_debug(
1132 "%s: %s and %s are equal via matching aspaths",
1133 pfx_buf, new_buf, exist_buf);
1134 }
1135 } else if (new->peer->as == exist->peer->as) {
1136 *paths_eq = 1;
1137
1138 if (debug)
1139 zlog_debug(
1140 "%s: %s and %s are equal via same remote-as",
1141 pfx_buf, new_buf, exist_buf);
1142 }
1143 } else {
1144 /*
1145 * TODO: If unequal cost ibgp multipath is enabled we can
1146 * mark the paths as equal here instead of returning
1147 */
ee88563a
JM
1148
1149 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1150 * if either step 7 or 10 (peer type checks) yielded a winner,
1151 * that result was returned immediately. Returning from step 10
1152 * ignored the return value computed in steps 8 and 9 (IGP
1153 * metric checks). In order to preserve that behavior, if
1154 * peer_sort_ret is set, return that rather than igp_metric_ret.
1155 */
1156 ret = peer_sort_ret;
1157 if (peer_sort_ret < 0) {
1158 ret = igp_metric_ret;
1159 if (debug) {
1160 if (ret == 1)
1161 zlog_debug(
1162 "%s: %s wins over %s after IGP metric comparison",
1163 pfx_buf, new_buf, exist_buf);
1164 else
1165 zlog_debug(
1166 "%s: %s loses to %s after IGP metric comparison",
1167 pfx_buf, new_buf, exist_buf);
1168 }
1169 *reason = bgp_path_selection_igp_metric;
d62a17ae 1170 }
1171 return ret;
1172 }
718e3744 1173
ee88563a
JM
1174 /*
1175 * At this point, the decision whether to set *paths_eq = 1 has been
1176 * completed. If we deferred returning because of bestpath peer-type
1177 * relax configuration, return now.
1178 */
1179 if (peer_sort_ret >= 0)
1180 return peer_sort_ret;
1181
d62a17ae 1182 /* 12. If both paths are external, prefer the path that was received
1183 first (the oldest one). This step minimizes route-flap, since a
1184 newer path won't displace an older one, even if it was the
1185 preferred route based on the additional decision criteria below. */
892fedb6 1186 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1187 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1188 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1189 *reason = bgp_path_selection_older;
d62a17ae 1190 if (debug)
1191 zlog_debug(
1192 "%s: %s wins over %s due to oldest external",
1193 pfx_buf, new_buf, exist_buf);
1194 return 1;
1195 }
9fbdd100 1196
1defdda8 1197 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1198 *reason = bgp_path_selection_older;
d62a17ae 1199 if (debug)
1200 zlog_debug(
1201 "%s: %s loses to %s due to oldest external",
1202 pfx_buf, new_buf, exist_buf);
1203 return 0;
1204 }
1205 }
718e3744 1206
d62a17ae 1207 /* 13. Router-ID comparision. */
1208 /* If one of the paths is "stale", the corresponding peer router-id will
1209 * be 0 and would always win over the other path. If originator id is
1210 * used for the comparision, it will decide which path is better.
1211 */
1212 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1213 new_id.s_addr = newattr->originator_id.s_addr;
1214 else
1215 new_id.s_addr = new->peer->remote_id.s_addr;
1216 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1217 exist_id.s_addr = existattr->originator_id.s_addr;
1218 else
1219 exist_id.s_addr = exist->peer->remote_id.s_addr;
1220
1221 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1222 *reason = bgp_path_selection_router_id;
d62a17ae 1223 if (debug)
1224 zlog_debug(
1225 "%s: %s wins over %s due to Router-ID comparison",
1226 pfx_buf, new_buf, exist_buf);
1227 return 1;
1228 }
718e3744 1229
d62a17ae 1230 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1231 *reason = bgp_path_selection_router_id;
d62a17ae 1232 if (debug)
1233 zlog_debug(
1234 "%s: %s loses to %s due to Router-ID comparison",
1235 pfx_buf, new_buf, exist_buf);
1236 return 0;
1237 }
9fbdd100 1238
d62a17ae 1239 /* 14. Cluster length comparision. */
1240 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1241 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1242
1243 if (new_cluster < exist_cluster) {
fdf81fa0 1244 *reason = bgp_path_selection_cluster_length;
d62a17ae 1245 if (debug)
1246 zlog_debug(
1247 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1248 pfx_buf, new_buf, exist_buf, new_cluster,
1249 exist_cluster);
1250 return 1;
1251 }
718e3744 1252
d62a17ae 1253 if (new_cluster > exist_cluster) {
fdf81fa0 1254 *reason = bgp_path_selection_cluster_length;
d62a17ae 1255 if (debug)
1256 zlog_debug(
1257 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1258 pfx_buf, new_buf, exist_buf, new_cluster,
1259 exist_cluster);
1260 return 0;
1261 }
9fbdd100 1262
d62a17ae 1263 /* 15. Neighbor address comparision. */
1264 /* Do this only if neither path is "stale" as stale paths do not have
1265 * valid peer information (as the connection may or may not be up).
1266 */
1defdda8 1267 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1268 *reason = bgp_path_selection_stale;
d62a17ae 1269 if (debug)
1270 zlog_debug(
1271 "%s: %s wins over %s due to latter path being STALE",
1272 pfx_buf, new_buf, exist_buf);
1273 return 1;
1274 }
0de5153c 1275
1defdda8 1276 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1277 *reason = bgp_path_selection_stale;
d62a17ae 1278 if (debug)
1279 zlog_debug(
1280 "%s: %s loses to %s due to former path being STALE",
1281 pfx_buf, new_buf, exist_buf);
1282 return 0;
1283 }
718e3744 1284
d62a17ae 1285 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1286 if (new->peer->su_remote == NULL) {
1287 *reason = bgp_path_selection_local_configured;
d62a17ae 1288 return 0;
fdf81fa0
DS
1289 }
1290 if (exist->peer->su_remote == NULL) {
1291 *reason = bgp_path_selection_local_configured;
d62a17ae 1292 return 1;
fdf81fa0 1293 }
9fbdd100 1294
d62a17ae 1295 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1296
1297 if (ret == 1) {
fdf81fa0 1298 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1299 if (debug)
1300 zlog_debug(
1301 "%s: %s loses to %s due to Neighor IP comparison",
1302 pfx_buf, new_buf, exist_buf);
1303 return 0;
1304 }
1305
1306 if (ret == -1) {
fdf81fa0 1307 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1308 if (debug)
1309 zlog_debug(
1310 "%s: %s wins over %s due to Neighor IP comparison",
1311 pfx_buf, new_buf, exist_buf);
1312 return 1;
1313 }
9fbdd100 1314
fdf81fa0 1315 *reason = bgp_path_selection_default;
d62a17ae 1316 if (debug)
1317 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1318 pfx_buf, new_buf, exist_buf);
718e3744 1319
d62a17ae 1320 return 1;
718e3744 1321}
1322
d071f237
AK
1323
1324int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1325 struct bgp_path_info *exist, int *paths_eq)
1326{
1327 enum bgp_path_selection_reason reason;
1328 char pfx_buf[PREFIX2STR_BUFFER];
1329
1330 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1331 AFI_L2VPN, SAFI_EVPN, &reason);
1332}
1333
65efcfce
LB
1334/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1335 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1336 * multipath is enabled
65efcfce 1337 * This version is compatible with */
18ee8310
DS
1338int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1339 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1340 afi_t afi, safi_t safi,
1341 enum bgp_path_selection_reason *reason)
d62a17ae 1342{
1343 int paths_eq;
1344 int ret;
18ee8310 1345 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1346 afi, safi, reason);
d62a17ae 1347
1348 if (paths_eq)
1349 ret = 0;
1350 else {
1351 if (ret == 1)
1352 ret = -1;
1353 else
1354 ret = 1;
1355 }
1356 return ret;
65efcfce
LB
1357}
1358
5a1ae2c2
DS
1359static enum filter_type bgp_input_filter(struct peer *peer,
1360 const struct prefix *p,
d62a17ae 1361 struct attr *attr, afi_t afi,
1362 safi_t safi)
718e3744 1363{
d62a17ae 1364 struct bgp_filter *filter;
6401252f 1365 enum filter_type ret = FILTER_PERMIT;
718e3744 1366
d62a17ae 1367 filter = &peer->filter[afi][safi];
718e3744 1368
d62a17ae 1369#define FILTER_EXIST_WARN(F, f, filter) \
1370 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1371 zlog_debug("%s: Could not find configured input %s-list %s!", \
1372 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1373
1374 if (DISTRIBUTE_IN_NAME(filter)) {
1375 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1376
6401252f
QY
1377 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1378 == FILTER_DENY) {
1379 ret = FILTER_DENY;
1380 goto done;
1381 }
d62a17ae 1382 }
1383
1384 if (PREFIX_LIST_IN_NAME(filter)) {
1385 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1386
6401252f
QY
1387 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1388 == PREFIX_DENY) {
1389 ret = FILTER_DENY;
1390 goto done;
1391 }
d62a17ae 1392 }
1393
1394 if (FILTER_LIST_IN_NAME(filter)) {
1395 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1396
1397 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1398 == AS_FILTER_DENY) {
1399 ret = FILTER_DENY;
1400 goto done;
1401 }
d62a17ae 1402 }
1403
6401252f 1404done:
c7bb4f00 1405 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1406 char pfxprint[PREFIX2STR_BUFFER];
1407
1408 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1409 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1410 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1411 }
1412
1413 return ret;
650f76c2 1414#undef FILTER_EXIST_WARN
718e3744 1415}
1416
b8685f9b
DS
1417static enum filter_type bgp_output_filter(struct peer *peer,
1418 const struct prefix *p,
d62a17ae 1419 struct attr *attr, afi_t afi,
1420 safi_t safi)
718e3744 1421{
d62a17ae 1422 struct bgp_filter *filter;
6401252f 1423 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1424
1425 filter = &peer->filter[afi][safi];
1426
1427#define FILTER_EXIST_WARN(F, f, filter) \
1428 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1429 zlog_debug("%s: Could not find configured output %s-list %s!", \
1430 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1431
d62a17ae 1432 if (DISTRIBUTE_OUT_NAME(filter)) {
1433 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1434
6401252f
QY
1435 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1436 == FILTER_DENY) {
1437 ret = FILTER_DENY;
1438 goto done;
1439 }
d62a17ae 1440 }
1441
1442 if (PREFIX_LIST_OUT_NAME(filter)) {
1443 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1444
d62a17ae 1445 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1446 == PREFIX_DENY) {
1447 ret = FILTER_DENY;
1448 goto done;
1449 }
d62a17ae 1450 }
718e3744 1451
d62a17ae 1452 if (FILTER_LIST_OUT_NAME(filter)) {
1453 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1454
d62a17ae 1455 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1456 == AS_FILTER_DENY) {
1457 ret = FILTER_DENY;
1458 goto done;
1459 }
1460 }
1461
c7bb4f00 1462 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1463 char pfxprint[PREFIX2STR_BUFFER];
1464
1465 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1466 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1467 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1468 }
718e3744 1469
6401252f
QY
1470done:
1471 return ret;
650f76c2 1472#undef FILTER_EXIST_WARN
718e3744 1473}
1474
1475/* If community attribute includes no_export then return 1. */
3dc339cd 1476static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1477{
1478 if (attr->community) {
1479 /* NO_ADVERTISE check. */
1480 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1481 return true;
d62a17ae 1482
1483 /* NO_EXPORT check. */
1484 if (peer->sort == BGP_PEER_EBGP
1485 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1486 return true;
d62a17ae 1487
1488 /* NO_EXPORT_SUBCONFED check. */
1489 if (peer->sort == BGP_PEER_EBGP
1490 || peer->sort == BGP_PEER_CONFED)
1491 if (community_include(attr->community,
1492 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1493 return true;
d62a17ae 1494 }
3dc339cd 1495 return false;
718e3744 1496}
1497
1498/* Route reflection loop check. */
3dc339cd 1499static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1500{
d62a17ae 1501 struct in_addr cluster_id;
779fee93 1502 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1503
779fee93 1504 if (cluster) {
d62a17ae 1505 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1506 cluster_id = peer->bgp->cluster_id;
1507 else
1508 cluster_id = peer->bgp->router_id;
1509
779fee93 1510 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1511 return true;
d62a17ae 1512 }
3dc339cd 1513 return false;
718e3744 1514}
6b0655a2 1515
5a1ae2c2 1516static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1517 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1518 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1519 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1520{
d62a17ae 1521 struct bgp_filter *filter;
82b692c0
LK
1522 struct bgp_path_info rmap_path = { 0 };
1523 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1524 route_map_result_t ret;
1525 struct route_map *rmap = NULL;
718e3744 1526
d62a17ae 1527 filter = &peer->filter[afi][safi];
718e3744 1528
d62a17ae 1529 /* Apply default weight value. */
1530 if (peer->weight[afi][safi])
1531 attr->weight = peer->weight[afi][safi];
718e3744 1532
d62a17ae 1533 if (rmap_name) {
1534 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1535
d62a17ae 1536 if (rmap == NULL)
1537 return RMAP_DENY;
1538 } else {
1539 if (ROUTE_MAP_IN_NAME(filter)) {
1540 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1541
d62a17ae 1542 if (rmap == NULL)
1543 return RMAP_DENY;
1544 }
1545 }
0b16f239 1546
d62a17ae 1547 /* Route map apply. */
1548 if (rmap) {
40381db7 1549 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1550 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1551 rmap_path.peer = peer;
1552 rmap_path.attr = attr;
82b692c0 1553 rmap_path.extra = &extra;
9bcb3eef 1554 rmap_path.net = dest;
196c6b09 1555
82b692c0
LK
1556 extra.num_labels = num_labels;
1557 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1558 memcpy(extra.label, label,
1559 num_labels * sizeof(mpls_label_t));
718e3744 1560
d62a17ae 1561 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1562
d62a17ae 1563 /* Apply BGP route map to the attribute. */
1782514f 1564 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1565
d62a17ae 1566 peer->rmap_type = 0;
0b16f239 1567
1f2263be 1568 if (ret == RMAP_DENYMATCH)
d62a17ae 1569 return RMAP_DENY;
0b16f239 1570 }
d62a17ae 1571 return RMAP_PERMIT;
0b16f239
DS
1572}
1573
5f040085 1574static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1575 struct attr *attr, afi_t afi, safi_t safi,
1576 const char *rmap_name)
0b16f239 1577{
40381db7 1578 struct bgp_path_info rmap_path;
d62a17ae 1579 route_map_result_t ret;
1580 struct route_map *rmap = NULL;
d7c0a89a 1581 uint8_t rmap_type;
0b16f239 1582
b787157a
DS
1583 /*
1584 * So if we get to this point and have no rmap_name
1585 * we want to just show the output as it currently
1586 * exists.
1587 */
1588 if (!rmap_name)
1589 return RMAP_PERMIT;
0b16f239 1590
d62a17ae 1591 /* Apply default weight value. */
1592 if (peer->weight[afi][safi])
1593 attr->weight = peer->weight[afi][safi];
0b16f239 1594
b787157a 1595 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1596
b787157a
DS
1597 /*
1598 * If we have a route map name and we do not find
1599 * the routemap that means we have an implicit
1600 * deny.
1601 */
1602 if (rmap == NULL)
1603 return RMAP_DENY;
0b16f239 1604
40381db7 1605 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1606 /* Route map apply. */
b787157a 1607 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1608 rmap_path.peer = peer;
1609 rmap_path.attr = attr;
0b16f239 1610
0f672529 1611 rmap_type = peer->rmap_type;
b787157a 1612 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1613
b787157a 1614 /* Apply BGP route map to the attribute. */
1782514f 1615 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1616
0f672529 1617 peer->rmap_type = rmap_type;
b787157a
DS
1618
1619 if (ret == RMAP_DENYMATCH)
1620 /*
1621 * caller has multiple error paths with bgp_attr_flush()
1622 */
1623 return RMAP_DENY;
ac41b2a2 1624
d62a17ae 1625 return RMAP_PERMIT;
718e3744 1626}
6b0655a2 1627
5000f21c 1628/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1629static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1630 struct peer *peer, struct attr *attr)
1631{
1632 if (peer->sort == BGP_PEER_EBGP
1633 && (peer_af_flag_check(peer, afi, safi,
1634 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1635 || peer_af_flag_check(peer, afi, safi,
1636 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1637 || peer_af_flag_check(peer, afi, safi,
1638 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1639 || peer_af_flag_check(peer, afi, safi,
1640 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1641 // Take action on the entire aspath
1642 if (peer_af_flag_check(peer, afi, safi,
1643 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1644 || peer_af_flag_check(peer, afi, safi,
1645 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1646 if (peer_af_flag_check(
1647 peer, afi, safi,
1648 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1649 attr->aspath = aspath_replace_private_asns(
bf26b80e 1650 attr->aspath, bgp->as, peer->as);
d62a17ae 1651
1652 // The entire aspath consists of private ASNs so create
1653 // an empty aspath
1654 else if (aspath_private_as_check(attr->aspath))
1655 attr->aspath = aspath_empty_get();
1656
1657 // There are some public and some private ASNs, remove
1658 // the private ASNs
1659 else
1660 attr->aspath = aspath_remove_private_asns(
bf26b80e 1661 attr->aspath, peer->as);
d62a17ae 1662 }
1663
1664 // 'all' was not specified so the entire aspath must be private
1665 // ASNs
1666 // for us to do anything
1667 else if (aspath_private_as_check(attr->aspath)) {
1668 if (peer_af_flag_check(
1669 peer, afi, safi,
1670 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1671 attr->aspath = aspath_replace_private_asns(
bf26b80e 1672 attr->aspath, bgp->as, peer->as);
d62a17ae 1673 else
1674 attr->aspath = aspath_empty_get();
1675 }
1676 }
5000f21c
DS
1677}
1678
c7122e14 1679/* If this is an EBGP peer with as-override */
d62a17ae 1680static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1681 struct peer *peer, struct attr *attr)
1682{
1683 if (peer->sort == BGP_PEER_EBGP
1684 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1685 if (aspath_single_asn_check(attr->aspath, peer->as))
1686 attr->aspath = aspath_replace_specific_asn(
1687 attr->aspath, peer->as, bgp->as);
1688 }
1689}
1690
7f323236
DW
1691void bgp_attr_add_gshut_community(struct attr *attr)
1692{
1693 struct community *old;
1694 struct community *new;
1695 struct community *merge;
1696 struct community *gshut;
1697
1698 old = attr->community;
1699 gshut = community_str2com("graceful-shutdown");
1700
990f4f91 1701 assert(gshut);
1702
7f323236
DW
1703 if (old) {
1704 merge = community_merge(community_dup(old), gshut);
1705
a4d82a8a 1706 if (old->refcnt == 0)
3c1f53de 1707 community_free(&old);
7f323236
DW
1708
1709 new = community_uniq_sort(merge);
3c1f53de 1710 community_free(&merge);
7f323236
DW
1711 } else {
1712 new = community_dup(gshut);
1713 }
1714
3c1f53de 1715 community_free(&gshut);
7f323236
DW
1716 attr->community = new;
1717 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1718
1719 /* When we add the graceful-shutdown community we must also
1720 * lower the local-preference */
1721 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1722 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1723}
1724
1725
e73c112e
MK
1726/* Notify BGP Conditional advertisement scanner process. */
1727void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1728{
1729 struct peer *temp_peer;
1730 struct peer *peer = SUBGRP_PEER(subgrp);
1731 struct listnode *temp_node, *temp_nnode = NULL;
1732 afi_t afi = SUBGRP_AFI(subgrp);
1733 safi_t safi = SUBGRP_SAFI(subgrp);
1734 struct bgp *bgp = SUBGRP_INST(subgrp);
1735 struct bgp_filter *filter = &peer->filter[afi][safi];
1736
1737 if (!ADVERTISE_MAP_NAME(filter))
1738 return;
1739
1740 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1741 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1742 continue;
1743
1744 if (peer != temp_peer)
1745 continue;
1746
1747 temp_peer->advmap_table_change = true;
1748 break;
1749 }
1750}
1751
1752
f2ee6d5c 1753void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1754{
960035b2 1755 if (family == AF_INET) {
975a328e
DA
1756 attr->nexthop.s_addr = INADDR_ANY;
1757 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1758 }
d62a17ae 1759 if (family == AF_INET6)
1760 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1761 if (family == AF_EVPN)
1762 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1763}
1764
9bcb3eef 1765bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1766 struct update_subgroup *subgrp,
7f7940e6
MK
1767 const struct prefix *p, struct attr *attr,
1768 bool skip_rmap_check)
d62a17ae 1769{
1770 struct bgp_filter *filter;
1771 struct peer *from;
1772 struct peer *peer;
1773 struct peer *onlypeer;
1774 struct bgp *bgp;
40381db7 1775 struct attr *piattr;
b68885f9 1776 route_map_result_t ret;
d62a17ae 1777 int transparent;
1778 int reflect;
1779 afi_t afi;
1780 safi_t safi;
1781 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1782 bool nh_reset = false;
1783 uint64_t cum_bw;
d62a17ae 1784
1785 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1786 return false;
d62a17ae 1787
1788 afi = SUBGRP_AFI(subgrp);
1789 safi = SUBGRP_SAFI(subgrp);
1790 peer = SUBGRP_PEER(subgrp);
1791 onlypeer = NULL;
1792 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1793 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1794
40381db7 1795 from = pi->peer;
d62a17ae 1796 filter = &peer->filter[afi][safi];
1797 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1798 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1799 : pi->attr;
3f9c7369 1800
49e5a4a0 1801#ifdef ENABLE_BGP_VNC
d62a17ae 1802 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1803 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1804 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1805
1806 /*
1807 * direct and direct_ext type routes originate internally even
1808 * though they can have peer pointers that reference other
1809 * systems
1810 */
8228a9a7
DS
1811 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1812 __func__, p);
d62a17ae 1813 samepeer_safe = 1;
1814 }
65efcfce
LB
1815#endif
1816
ddb5b488
PZ
1817 if (((afi == AFI_IP) || (afi == AFI_IP6))
1818 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1819 && (pi->type == ZEBRA_ROUTE_BGP)
1820 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1821
1822 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1823
1824 samepeer_safe = 1;
1825 }
1826
d62a17ae 1827 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1828 * pi is valid */
1829 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1830 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1831 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1832 return false;
d62a17ae 1833 }
adbac85e 1834
d62a17ae 1835 /* If this is not the bestpath then check to see if there is an enabled
1836 * addpath
1837 * feature that requires us to advertise it */
40381db7 1838 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1839 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1840 return false;
d62a17ae 1841 }
1842 }
06370dac 1843
d62a17ae 1844 /* Aggregate-address suppress check. */
4056a5f6
RZ
1845 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1846 return false;
3f9c7369 1847
13b7e7f0
DS
1848 /*
1849 * If we are doing VRF 2 VRF leaking via the import
1850 * statement, we want to prevent the route going
1851 * off box as that the RT and RD created are localy
1852 * significant and globaly useless.
1853 */
40381db7
DS
1854 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1855 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1856 return false;
13b7e7f0 1857
d62a17ae 1858 /* If it's labeled safi, make sure the route has a valid label. */
1859 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1860 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1861 if (!bgp_is_valid_label(&label)) {
1862 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1863 zlog_debug("u%" PRIu64 ":s%" PRIu64
1864 " %pFX is filtered - no label (%p)",
d62a17ae 1865 subgrp->update_group->id, subgrp->id,
8228a9a7 1866 p, &label);
3dc339cd 1867 return false;
d62a17ae 1868 }
1869 }
cd1964ff 1870
d62a17ae 1871 /* Do not send back route to sender. */
1872 if (onlypeer && from == onlypeer) {
3dc339cd 1873 return false;
d62a17ae 1874 }
3f9c7369 1875
d62a17ae 1876 /* Do not send the default route in the BGP table if the neighbor is
1877 * configured for default-originate */
1878 if (CHECK_FLAG(peer->af_flags[afi][safi],
1879 PEER_FLAG_DEFAULT_ORIGINATE)) {
1880 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1881 return false;
d62a17ae 1882 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1883 return false;
d62a17ae 1884 }
4125bb67 1885
d62a17ae 1886 /* Transparency check. */
1887 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1888 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1889 transparent = 1;
1890 else
1891 transparent = 0;
1892
1893 /* If community is not disabled check the no-export and local. */
40381db7 1894 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1895 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1896 zlog_debug("%s: community filter check fail for %pFX",
1897 __func__, p);
3dc339cd 1898 return false;
d62a17ae 1899 }
3f9c7369 1900
d62a17ae 1901 /* If the attribute has originator-id and it is same as remote
1902 peer's id. */
40381db7
DS
1903 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1904 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1905 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1906 zlog_debug(
8228a9a7
DS
1907 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1908 onlypeer->host, p);
3dc339cd 1909 return false;
d62a17ae 1910 }
3f9c7369 1911
d62a17ae 1912 /* ORF prefix-list filter check */
1913 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1914 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1915 || CHECK_FLAG(peer->af_cap[afi][safi],
1916 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1917 if (peer->orf_plist[afi][safi]) {
1918 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1919 == PREFIX_DENY) {
1920 if (bgp_debug_update(NULL, p,
1921 subgrp->update_group, 0))
1922 zlog_debug(
8228a9a7
DS
1923 "%s [Update:SEND] %pFX is filtered via ORF",
1924 peer->host, p);
3dc339cd 1925 return false;
d62a17ae 1926 }
1927 }
1928
1929 /* Output filter check. */
40381db7 1930 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1931 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1932 zlog_debug("%s [Update:SEND] %pFX is filtered",
1933 peer->host, p);
3dc339cd 1934 return false;
d62a17ae 1935 }
3f9c7369 1936
d62a17ae 1937 /* AS path loop check. */
2b31007c
RZ
1938 if (onlypeer && onlypeer->as_path_loop_detection
1939 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1940 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1941 zlog_debug(
3efd0893 1942 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1943 onlypeer->host, onlypeer->as);
3dc339cd 1944 return false;
d62a17ae 1945 }
3f9c7369 1946
d62a17ae 1947 /* If we're a CONFED we need to loop check the CONFED ID too */
1948 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1949 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1950 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1951 zlog_debug(
3efd0893 1952 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1953 peer->host, bgp->confed_id);
3dc339cd 1954 return false;
d62a17ae 1955 }
3f9c7369 1956 }
3f9c7369 1957
d62a17ae 1958 /* Route-Reflect check. */
1959 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1960 reflect = 1;
1961 else
1962 reflect = 0;
1963
1964 /* IBGP reflection check. */
1965 if (reflect && !samepeer_safe) {
1966 /* A route from a Client peer. */
1967 if (CHECK_FLAG(from->af_flags[afi][safi],
1968 PEER_FLAG_REFLECTOR_CLIENT)) {
1969 /* Reflect to all the Non-Client peers and also to the
1970 Client peers other than the originator. Originator
1971 check
1972 is already done. So there is noting to do. */
1973 /* no bgp client-to-client reflection check. */
892fedb6
DA
1974 if (CHECK_FLAG(bgp->flags,
1975 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1976 if (CHECK_FLAG(peer->af_flags[afi][safi],
1977 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1978 return false;
d62a17ae 1979 } else {
1980 /* A route from a Non-client peer. Reflect to all other
1981 clients. */
1982 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1983 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1984 return false;
d62a17ae 1985 }
1986 }
3f9c7369 1987
d62a17ae 1988 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1989 *attr = *piattr;
d62a17ae 1990
1991 /* If local-preference is not set. */
1992 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1993 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1994 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1995 attr->local_pref = bgp->default_local_pref;
3f9c7369 1996 }
3f9c7369 1997
d62a17ae 1998 /* If originator-id is not set and the route is to be reflected,
1999 set the originator id */
2000 if (reflect
2001 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2002 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2003 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2004 }
3f9c7369 2005
d62a17ae 2006 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2007 */
2008 if (peer->sort == BGP_PEER_EBGP
2009 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2010 if (from != bgp->peer_self && !transparent
2011 && !CHECK_FLAG(peer->af_flags[afi][safi],
2012 PEER_FLAG_MED_UNCHANGED))
2013 attr->flag &=
2014 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2015 }
3f9c7369 2016
d62a17ae 2017 /* Since the nexthop attribute can vary per peer, it is not explicitly
2018 * set
2019 * in announce check, only certain flags and length (or number of
2020 * nexthops
2021 * -- for IPv6/MP_REACH) are set here in order to guide the update
2022 * formation
2023 * code in setting the nexthop(s) on a per peer basis in
2024 * reformat_peer().
2025 * Typically, the source nexthop in the attribute is preserved but in
2026 * the
2027 * scenarios where we know it will always be overwritten, we reset the
2028 * nexthop to "0" in an attempt to achieve better Update packing. An
2029 * example of this is when a prefix from each of 2 IBGP peers needs to
2030 * be
2031 * announced to an EBGP peer (and they have the same attributes barring
2032 * their nexthop).
2033 */
2034 if (reflect)
2035 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2036
2037#define NEXTHOP_IS_V6 \
2038 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2039 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2040 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2041 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2042
2043 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2044 * if
2045 * the peer (group) is configured to receive link-local nexthop
2046 * unchanged
c728d027
DA
2047 * and it is available in the prefix OR we're not reflecting the route,
2048 * link-local nexthop address is valid and
d62a17ae 2049 * the peer (group) to whom we're going to announce is on a shared
2050 * network
2051 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2052 * By checking if nexthop LL address is valid we are sure that
2053 * we do not announce LL address as `::`.
d62a17ae 2054 */
2055 if (NEXTHOP_IS_V6) {
2056 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2057 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2058 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2059 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2060 || (!reflect
2061 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2062 && peer->shared_network
d62a17ae 2063 && (from == bgp->peer_self
2064 || peer->sort == BGP_PEER_EBGP))) {
2065 attr->mp_nexthop_len =
2066 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2067 }
3f9c7369 2068
d62a17ae 2069 /* Clear off link-local nexthop in source, whenever it is not
2070 * needed to
2071 * ensure more prefixes share the same attribute for
2072 * announcement.
2073 */
2074 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2075 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2076 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2077 }
3f9c7369 2078
d62a17ae 2079 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2080 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2081
2082 /* Route map & unsuppress-map apply. */
7f7940e6 2083 if (!skip_rmap_check
e73c112e 2084 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2085 struct bgp_path_info rmap_path = {0};
2086 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2087 struct attr dummy_attr = {0};
d62a17ae 2088
e34291b8 2089 /* Fill temp path_info */
9bcb3eef
DS
2090 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2091 pi, peer, attr);
16f7ce2b 2092
d62a17ae 2093 /* don't confuse inbound and outbound setting */
2094 RESET_FLAG(attr->rmap_change_flags);
2095
2096 /*
2097 * The route reflector is not allowed to modify the attributes
2098 * of the reflected IBGP routes unless explicitly allowed.
2099 */
2100 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2101 && !CHECK_FLAG(bgp->flags,
2102 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2103 dummy_attr = *attr;
40381db7 2104 rmap_path.attr = &dummy_attr;
d62a17ae 2105 }
3f9c7369 2106
d62a17ae 2107 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2108
4056a5f6 2109 if (bgp_path_suppressed(pi))
d62a17ae 2110 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2111 &rmap_path);
d62a17ae 2112 else
2113 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2114 &rmap_path);
d62a17ae 2115
2116 peer->rmap_type = 0;
2117
2118 if (ret == RMAP_DENYMATCH) {
778048bf 2119 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2120 zlog_debug(
2121 "%s [Update:SEND] %pFX is filtered by route-map",
2122 peer->host, p);
778048bf 2123
d62a17ae 2124 bgp_attr_flush(attr);
3dc339cd 2125 return false;
d62a17ae 2126 }
3f9c7369 2127 }
3f9c7369 2128
9dac9fc8
DA
2129 /* RFC 8212 to prevent route leaks.
2130 * This specification intends to improve this situation by requiring the
2131 * explicit configuration of both BGP Import and Export Policies for any
2132 * External BGP (EBGP) session such as customers, peers, or
2133 * confederation boundaries for all enabled address families. Through
2134 * codification of the aforementioned requirement, operators will
2135 * benefit from consistent behavior across different BGP
2136 * implementations.
2137 */
1d3fdccf 2138 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2139 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2140 return false;
9dac9fc8 2141
fb29348a
DA
2142 /* draft-ietf-idr-deprecate-as-set-confed-set
2143 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2144 * Eventually, This document (if approved) updates RFC 4271
2145 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2146 * and obsoletes RFC 6472.
2147 */
7f972cd8 2148 if (peer->bgp->reject_as_sets)
fb29348a 2149 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2150 return false;
fb29348a 2151
33d022bc
DA
2152 /* Codification of AS 0 Processing */
2153 if (aspath_check_as_zero(attr->aspath))
e2369003 2154 return false;
33d022bc 2155
637e5ba4 2156 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2157 if (peer->sort == BGP_PEER_IBGP
2158 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2159 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2160 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2161 } else {
2162 bgp_attr_add_gshut_community(attr);
2163 }
2164 }
2165
d62a17ae 2166 /* After route-map has been applied, we check to see if the nexthop to
2167 * be carried in the attribute (that is used for the announcement) can
2168 * be cleared off or not. We do this in all cases where we would be
2169 * setting the nexthop to "ourselves". For IPv6, we only need to
2170 * consider
2171 * the global nexthop here; the link-local nexthop would have been
2172 * cleared
2173 * already, and if not, it is required by the update formation code.
2174 * Also see earlier comments in this function.
2175 */
2176 /*
2177 * If route-map has performed some operation on the nexthop or the peer
2178 * configuration says to pass it unchanged, we cannot reset the nexthop
2179 * here, so only attempt to do it if these aren't true. Note that the
2180 * route-map handler itself might have cleared the nexthop, if for
2181 * example,
2182 * it is configured as 'peer-address'.
2183 */
2184 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2185 piattr->rmap_change_flags)
d62a17ae 2186 && !transparent
2187 && !CHECK_FLAG(peer->af_flags[afi][safi],
2188 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2189 /* We can reset the nexthop, if setting (or forcing) it to
2190 * 'self' */
2191 if (CHECK_FLAG(peer->af_flags[afi][safi],
2192 PEER_FLAG_NEXTHOP_SELF)
2193 || CHECK_FLAG(peer->af_flags[afi][safi],
2194 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2195 if (!reflect
2196 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2197 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2198 subgroup_announce_reset_nhop(
2199 (peer_cap_enhe(peer, afi, safi)
2200 ? AF_INET6
2201 : p->family),
2202 attr);
7b651a32 2203 nh_reset = true;
2204 }
d62a17ae 2205 } else if (peer->sort == BGP_PEER_EBGP) {
2206 /* Can also reset the nexthop if announcing to EBGP, but
2207 * only if
2208 * no peer in the subgroup is on a shared subnet.
2209 * Note: 3rd party nexthop currently implemented for
2210 * IPv4 only.
2211 */
737af885
BS
2212 if ((p->family == AF_INET) &&
2213 (!bgp_subgrp_multiaccess_check_v4(
2214 piattr->nexthop,
7b651a32 2215 subgrp, from))) {
d62a17ae 2216 subgroup_announce_reset_nhop(
2217 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2218 ? AF_INET6
2219 : p->family),
737af885 2220 attr);
7b651a32 2221 nh_reset = true;
2222 }
737af885
BS
2223
2224 if ((p->family == AF_INET6) &&
2225 (!bgp_subgrp_multiaccess_check_v6(
2226 piattr->mp_nexthop_global,
7b651a32 2227 subgrp, from))) {
737af885
BS
2228 subgroup_announce_reset_nhop(
2229 (peer_cap_enhe(peer, afi, safi)
2230 ? AF_INET6
2231 : p->family),
2232 attr);
7b651a32 2233 nh_reset = true;
2234 }
737af885
BS
2235
2236
2237
40381db7 2238 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2239 /*
2240 * This flag is used for leaked vpn-vrf routes
2241 */
2242 int family = p->family;
2243
2244 if (peer_cap_enhe(peer, afi, safi))
2245 family = AF_INET6;
2246
2247 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2248 zlog_debug(
1defdda8 2249 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2250 __func__, family2str(family));
2251 subgroup_announce_reset_nhop(family, attr);
7b651a32 2252 nh_reset = true;
d62a17ae 2253 }
63696f1d 2254 }
960035b2 2255
63696f1d 2256 /* If IPv6/MP and nexthop does not have any override and happens
2257 * to
2258 * be a link-local address, reset it so that we don't pass along
2259 * the
2260 * source's link-local IPv6 address to recipients who may not be
2261 * on
2262 * the same interface.
2263 */
2264 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2265 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2266 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2267 nh_reset = true;
2268 }
d62a17ae 2269 }
3f9c7369 2270
7b651a32 2271 /*
2272 * When the next hop is set to ourselves, if all multipaths have
2273 * link-bandwidth announce the cumulative bandwidth as that makes
2274 * the most sense. However, don't modify if the link-bandwidth has
2275 * been explicitly set by user policy.
2276 */
2277 if (nh_reset &&
f7e1c681 2278 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2279 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2280 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2281 attr->ecommunity = ecommunity_replace_linkbw(
2282 bgp->as, attr->ecommunity, cum_bw);
2283
3dc339cd 2284 return true;
3f9c7369
DS
2285}
2286
f009ff26 2287static int bgp_route_select_timer_expire(struct thread *thread)
2288{
2289 struct afi_safi_info *info;
2290 afi_t afi;
2291 safi_t safi;
2292 struct bgp *bgp;
2293
2294 info = THREAD_ARG(thread);
2295 afi = info->afi;
2296 safi = info->safi;
2297 bgp = info->bgp;
2298
2299 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2300 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2301 safi);
f009ff26 2302
2303 bgp->gr_info[afi][safi].t_route_select = NULL;
2304
2305 XFREE(MTYPE_TMP, info);
2306
2307 /* Best path selection */
2308 return bgp_best_path_select_defer(bgp, afi, safi);
2309}
2310
9bcb3eef 2311void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2312 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2313 struct bgp_path_info_pair *result, afi_t afi,
2314 safi_t safi)
2315{
2316 struct bgp_path_info *new_select;
2317 struct bgp_path_info *old_select;
40381db7
DS
2318 struct bgp_path_info *pi;
2319 struct bgp_path_info *pi1;
2320 struct bgp_path_info *pi2;
2321 struct bgp_path_info *nextpi = NULL;
d62a17ae 2322 int paths_eq, do_mpath, debug;
2323 struct list mp_list;
2324 char pfx_buf[PREFIX2STR_BUFFER];
2325 char path_buf[PATH_ADDPATH_STR_BUFFER];
2326
2327 bgp_mp_list_init(&mp_list);
2328 do_mpath =
2329 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2330
9bcb3eef 2331 debug = bgp_debug_bestpath(dest);
d62a17ae 2332
2333 if (debug)
9bcb3eef 2334 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2335
9bcb3eef 2336 dest->reason = bgp_path_selection_none;
d62a17ae 2337 /* bgp deterministic-med */
2338 new_select = NULL;
892fedb6 2339 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2340
1defdda8 2341 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2342 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2343 pi1 = pi1->next)
9bcb3eef 2344 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2345 BGP_PATH_DMED_SELECTED);
d62a17ae 2346
9bcb3eef 2347 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2348 pi1 = pi1->next) {
40381db7 2349 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2350 continue;
40381db7 2351 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2352 continue;
ea8b2282 2353 if (pi1->peer != bgp->peer_self)
feb17238 2354 if (!peer_established(pi1->peer))
d62a17ae 2355 continue;
2356
40381db7
DS
2357 new_select = pi1;
2358 if (pi1->next) {
2359 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2360 if (CHECK_FLAG(pi2->flags,
1defdda8 2361 BGP_PATH_DMED_CHECK))
d62a17ae 2362 continue;
40381db7 2363 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2364 continue;
ea8b2282 2365 if (pi2->peer != bgp->peer_self
d62a17ae 2366 && !CHECK_FLAG(
ea8b2282
DS
2367 pi2->peer->sflags,
2368 PEER_STATUS_NSF_WAIT))
40381db7 2369 if (pi2->peer->status
d62a17ae 2370 != Established)
2371 continue;
2372
121e245d
DS
2373 if (!aspath_cmp_left(pi1->attr->aspath,
2374 pi2->attr->aspath)
2375 && !aspath_cmp_left_confed(
40381db7 2376 pi1->attr->aspath,
121e245d
DS
2377 pi2->attr->aspath))
2378 continue;
d62a17ae 2379
121e245d
DS
2380 if (bgp_path_info_cmp(
2381 bgp, pi2, new_select,
2382 &paths_eq, mpath_cfg, debug,
fdf81fa0 2383 pfx_buf, afi, safi,
9bcb3eef 2384 &dest->reason)) {
121e245d 2385 bgp_path_info_unset_flag(
9bcb3eef 2386 dest, new_select,
121e245d
DS
2387 BGP_PATH_DMED_SELECTED);
2388 new_select = pi2;
d62a17ae 2389 }
121e245d
DS
2390
2391 bgp_path_info_set_flag(
9bcb3eef 2392 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2393 }
2394 }
9bcb3eef 2395 bgp_path_info_set_flag(dest, new_select,
18ee8310 2396 BGP_PATH_DMED_CHECK);
9bcb3eef 2397 bgp_path_info_set_flag(dest, new_select,
18ee8310 2398 BGP_PATH_DMED_SELECTED);
d62a17ae 2399
2400 if (debug) {
18ee8310 2401 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2402 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2403 zlog_debug(
2404 "%pBD: %s is the bestpath from AS %u",
2405 dest, path_buf,
2406 aspath_get_first_as(
2407 new_select->attr->aspath));
d62a17ae 2408 }
2409 }
2410 }
96450faf 2411
d62a17ae 2412 /* Check old selected route and new selected route. */
2413 old_select = NULL;
2414 new_select = NULL;
9bcb3eef 2415 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2416 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2417 enum bgp_path_selection_reason reason;
2418
40381db7
DS
2419 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2420 old_select = pi;
d62a17ae 2421
40381db7 2422 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2423 /* reap REMOVED routes, if needs be
2424 * selected route must stay for a while longer though
2425 */
40381db7
DS
2426 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2427 && (pi != old_select))
9bcb3eef 2428 bgp_path_info_reap(dest, pi);
d62a17ae 2429
ddb5b488 2430 if (debug)
40381db7
DS
2431 zlog_debug("%s: pi %p in holddown", __func__,
2432 pi);
ddb5b488 2433
d62a17ae 2434 continue;
2435 }
96450faf 2436
40381db7
DS
2437 if (pi->peer && pi->peer != bgp->peer_self
2438 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2439 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2440
2441 if (debug)
2442 zlog_debug(
40381db7
DS
2443 "%s: pi %p non self peer %s not estab state",
2444 __func__, pi, pi->peer->host);
ddb5b488 2445
d62a17ae 2446 continue;
ddb5b488 2447 }
9fbdd100 2448
892fedb6 2449 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2450 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2451 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2452 if (debug)
40381db7 2453 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2454 continue;
2455 }
9fbdd100 2456
9bcb3eef 2457 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2458
9bcb3eef 2459 reason = dest->reason;
40381db7 2460 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2461 debug, pfx_buf, afi, safi,
2462 &dest->reason)) {
19ea4cec
DS
2463 if (new_select == NULL &&
2464 reason != bgp_path_selection_none)
9bcb3eef 2465 dest->reason = reason;
40381db7 2466 new_select = pi;
d62a17ae 2467 }
2468 }
718e3744 2469
d62a17ae 2470 /* Now that we know which path is the bestpath see if any of the other
2471 * paths
2472 * qualify as multipaths
2473 */
2474 if (debug) {
2475 if (new_select)
7533cad7
QY
2476 bgp_path_info_path_with_addpath_rx_str(
2477 new_select, path_buf, sizeof(path_buf));
d62a17ae 2478 else
772270f3 2479 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2480 zlog_debug(
8228a9a7
DS
2481 "%pBD: After path selection, newbest is %s oldbest was %s",
2482 dest, path_buf,
d62a17ae 2483 old_select ? old_select->peer->host : "NONE");
96450faf 2484 }
9fbdd100 2485
d62a17ae 2486 if (do_mpath && new_select) {
9bcb3eef 2487 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2488 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2489
2490 if (debug)
18ee8310 2491 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2492 pi, path_buf, sizeof(path_buf));
d62a17ae 2493
40381db7 2494 if (pi == new_select) {
d62a17ae 2495 if (debug)
2496 zlog_debug(
8228a9a7
DS
2497 "%pBD: %s is the bestpath, add to the multipath list",
2498 dest, path_buf);
40381db7 2499 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2500 continue;
2501 }
2502
40381db7 2503 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2504 continue;
2505
40381db7
DS
2506 if (pi->peer && pi->peer != bgp->peer_self
2507 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2508 PEER_STATUS_NSF_WAIT))
feb17238 2509 if (!peer_established(pi->peer))
d62a17ae 2510 continue;
2511
40381db7 2512 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2513 if (debug)
2514 zlog_debug(
8228a9a7
DS
2515 "%pBD: %s has the same nexthop as the bestpath, skip it",
2516 dest, path_buf);
d62a17ae 2517 continue;
2518 }
2519
40381db7 2520 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2521 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2522 &dest->reason);
d62a17ae 2523
2524 if (paths_eq) {
2525 if (debug)
2526 zlog_debug(
8228a9a7
DS
2527 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2528 dest, path_buf);
40381db7 2529 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2530 }
2531 }
2532 }
fee0f4c6 2533
9bcb3eef 2534 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2535 mpath_cfg);
2536 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2537 bgp_mp_list_clear(&mp_list);
96450faf 2538
9bcb3eef 2539 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2540
d62a17ae 2541 result->old = old_select;
2542 result->new = new_select;
96450faf 2543
d62a17ae 2544 return;
fee0f4c6 2545}
2546
3f9c7369
DS
2547/*
2548 * A new route/change in bestpath of an existing route. Evaluate the path
2549 * for advertisement to the subgroup.
2550 */
3dc339cd
DA
2551void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2552 struct bgp_path_info *selected,
9bcb3eef 2553 struct bgp_dest *dest,
3dc339cd 2554 uint32_t addpath_tx_id)
d62a17ae 2555{
b54892e0 2556 const struct prefix *p;
d62a17ae 2557 struct peer *onlypeer;
2558 struct attr attr;
2559 afi_t afi;
2560 safi_t safi;
a77e2f4b
S
2561 struct bgp *bgp;
2562 bool advertise;
adbac85e 2563
9bcb3eef 2564 p = bgp_dest_get_prefix(dest);
d62a17ae 2565 afi = SUBGRP_AFI(subgrp);
2566 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2567 bgp = SUBGRP_INST(subgrp);
d62a17ae 2568 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2569 : NULL);
2570
2dbe669b
DA
2571 if (BGP_DEBUG(update, UPDATE_OUT))
2572 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2573
d62a17ae 2574 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2575 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2576 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2577 return;
d62a17ae 2578
2579 memset(&attr, 0, sizeof(struct attr));
2580 /* It's initialized in bgp_announce_check() */
2581
a77e2f4b
S
2582 /* Announcement to the subgroup. If the route is filtered withdraw it.
2583 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2584 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2585 * route
d62a17ae 2586 */
a77e2f4b
S
2587 advertise = bgp_check_advertise(bgp, dest);
2588
d62a17ae 2589 if (selected) {
7f7940e6 2590 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2591 false)) {
2592 /* Route is selected, if the route is already installed
2593 * in FIB, then it is advertised
2594 */
2595 if (advertise)
2596 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2597 selected);
2598 } else
9bcb3eef 2599 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2600 addpath_tx_id);
d62a17ae 2601 }
2602
2603 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2604 else {
9bcb3eef 2605 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2606 }
200df115 2607}
fee0f4c6 2608
3064bf43 2609/*
e1072051 2610 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2611 * This is called at the end of route processing.
3064bf43 2612 */
9bcb3eef 2613void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2614{
40381db7 2615 struct bgp_path_info *pi;
3064bf43 2616
9bcb3eef 2617 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2618 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2619 continue;
40381db7
DS
2620 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2621 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2622 }
3064bf43 2623}
2624
2625/*
2626 * Has the route changed from the RIB's perspective? This is invoked only
2627 * if the route selection returns the same best route as earlier - to
2628 * determine if we need to update zebra or not.
2629 */
9bcb3eef 2630bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2631{
4b7e6066 2632 struct bgp_path_info *mpinfo;
d62a17ae 2633
2bb9eff4
DS
2634 /* If this is multipath, check all selected paths for any nexthop
2635 * change or attribute change. Some attribute changes (e.g., community)
2636 * aren't of relevance to the RIB, but we'll update zebra to ensure
2637 * we handle the case of BGP nexthop change. This is the behavior
2638 * when the best path has an attribute change anyway.
d62a17ae 2639 */
1defdda8 2640 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2641 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2642 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2643 return true;
d62a17ae 2644
2bb9eff4
DS
2645 /*
2646 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2647 */
18ee8310
DS
2648 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2649 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2650 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2651 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2652 return true;
d62a17ae 2653 }
3064bf43 2654
d62a17ae 2655 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2656 return false;
3064bf43 2657}
2658
d62a17ae 2659struct bgp_process_queue {
2660 struct bgp *bgp;
9bcb3eef 2661 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2662#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2663 unsigned int flags;
2664 unsigned int queued;
200df115 2665};
2666
3b0c17e1 2667static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2668 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2669 struct bgp_path_info *new_select,
2670 struct bgp_path_info *old_select)
2671{
9bcb3eef 2672 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2673
2674 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2675 return;
2676
2677 if (advertise_type5_routes(bgp, afi) && new_select
2678 && is_route_injectable_into_evpn(new_select)) {
2679
2680 /* apply the route-map */
2681 if (bgp->adv_cmd_rmap[afi][safi].map) {
2682 route_map_result_t ret;
2683 struct bgp_path_info rmap_path;
2684 struct bgp_path_info_extra rmap_path_extra;
2685 struct attr dummy_attr;
2686
2687 dummy_attr = *new_select->attr;
2688
2689 /* Fill temp path_info */
9bcb3eef 2690 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2691 new_select, new_select->peer,
2692 &dummy_attr);
2693
2694 RESET_FLAG(dummy_attr.rmap_change_flags);
2695
2696 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2697 p, &rmap_path);
3b0c17e1 2698
2699 if (ret == RMAP_DENYMATCH) {
2700 bgp_attr_flush(&dummy_attr);
2701 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2702 safi);
2703 } else
2704 bgp_evpn_advertise_type5_route(
2705 bgp, p, &dummy_attr, afi, safi);
2706 } else {
2707 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2708 afi, safi);
2709 }
2710 } else if (advertise_type5_routes(bgp, afi) && old_select
2711 && is_route_injectable_into_evpn(old_select))
2712 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2713}
2714
3103e8d2
DS
2715/*
2716 * old_select = The old best path
2717 * new_select = the new best path
2718 *
2719 * if (!old_select && new_select)
2720 * We are sending new information on.
2721 *
2722 * if (old_select && new_select) {
2723 * if (new_select != old_select)
2724 * We have a new best path send a change
2725 * else
2726 * We've received a update with new attributes that needs
2727 * to be passed on.
2728 * }
2729 *
2730 * if (old_select && !new_select)
2731 * We have no eligible route that we can announce or the rn
2732 * is being removed.
2733 */
9bcb3eef 2734static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2735 afi_t afi, safi_t safi)
d62a17ae 2736{
4b7e6066
DS
2737 struct bgp_path_info *new_select;
2738 struct bgp_path_info *old_select;
2739 struct bgp_path_info_pair old_and_new;
ddb5b488 2740 int debug = 0;
d62a17ae 2741
892fedb6 2742 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2743 if (dest)
2744 debug = bgp_debug_bestpath(dest);
b54892e0 2745 if (debug)
f4c713ae 2746 zlog_debug(
56ca3b5b 2747 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2748 __func__, dest);
f4c713ae
LB
2749 return;
2750 }
d62a17ae 2751 /* Is it end of initial update? (after startup) */
9bcb3eef 2752 if (!dest) {
d62a17ae 2753 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2754 sizeof(bgp->update_delay_zebra_resume_time));
2755
2756 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2757 FOREACH_AFI_SAFI (afi, safi) {
2758 if (bgp_fibupd_safi(safi))
2759 bgp_zebra_announce_table(bgp, afi, safi);
2760 }
d62a17ae 2761 bgp->main_peers_update_hold = 0;
2762
2763 bgp_start_routeadv(bgp);
aac24838 2764 return;
d62a17ae 2765 }
cb1faec9 2766
9bcb3eef 2767 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2768
9bcb3eef 2769 debug = bgp_debug_bestpath(dest);
b54892e0 2770 if (debug)
56ca3b5b 2771 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2772 afi2str(afi), safi2str(safi));
ddb5b488 2773
f009ff26 2774 /* The best path calculation for the route is deferred if
2775 * BGP_NODE_SELECT_DEFER is set
2776 */
9bcb3eef 2777 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2778 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2779 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2780 return;
2781 }
2782
d62a17ae 2783 /* Best path selection. */
9bcb3eef 2784 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2785 afi, safi);
2786 old_select = old_and_new.old;
2787 new_select = old_and_new.new;
2788
2789 /* Do we need to allocate or free labels?
2790 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2791 * necessary to do this upon changes to best path. Exceptions:
2792 * - label index has changed -> recalculate resulting label
2793 * - path_info sub_type changed -> switch to/from implicit-null
2794 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2795 */
318cac96 2796 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2797 if (new_select) {
2798 if (!old_select
2799 || bgp_label_index_differs(new_select, old_select)
57592a53 2800 || new_select->sub_type != old_select->sub_type
9bcb3eef 2801 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2802 /* Enforced penultimate hop popping:
2803 * implicit-null for local routes, aggregate
2804 * and redistributed routes
2805 */
d62a17ae 2806 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2807 || new_select->sub_type
2808 == BGP_ROUTE_AGGREGATE
2809 || new_select->sub_type
2810 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2811 if (CHECK_FLAG(
9bcb3eef 2812 dest->flags,
992dd67e
PR
2813 BGP_NODE_REGISTERED_FOR_LABEL)
2814 || CHECK_FLAG(
2815 dest->flags,
2816 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2817 bgp_unregister_for_label(dest);
70e98a7f 2818 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2819 &dest->local_label);
2820 bgp_set_valid_label(&dest->local_label);
d62a17ae 2821 } else
9bcb3eef
DS
2822 bgp_register_for_label(dest,
2823 new_select);
d62a17ae 2824 }
9bcb3eef 2825 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2826 BGP_NODE_REGISTERED_FOR_LABEL)
2827 || CHECK_FLAG(dest->flags,
2828 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2829 bgp_unregister_for_label(dest);
318cac96 2830 }
992dd67e
PR
2831 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2832 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2833 bgp_unregister_for_label(dest);
d62a17ae 2834 }
cd1964ff 2835
b54892e0 2836 if (debug)
ddb5b488 2837 zlog_debug(
56ca3b5b 2838 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2839 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2840 old_select, new_select);
ddb5b488 2841
d62a17ae 2842 /* If best route remains the same and this is not due to user-initiated
2843 * clear, see exactly what needs to be done.
2844 */
d62a17ae 2845 if (old_select && old_select == new_select
9bcb3eef 2846 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2847 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2848 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2849 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2850#ifdef ENABLE_BGP_VNC
d62a17ae 2851 vnc_import_bgp_add_route(bgp, p, old_select);
2852 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2853#endif
bb744275 2854 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2855 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2856
2857 if (new_select->type == ZEBRA_ROUTE_BGP
2858 && (new_select->sub_type == BGP_ROUTE_NORMAL
2859 || new_select->sub_type
2860 == BGP_ROUTE_IMPORTED))
2861
9bcb3eef 2862 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2863 bgp, afi, safi);
2864 }
d62a17ae 2865 }
d62a17ae 2866
2867 /* If there is a change of interest to peers, reannounce the
2868 * route. */
1defdda8 2869 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2870 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2871 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2872 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2873
2874 /* unicast routes must also be annouced to
2875 * labeled-unicast update-groups */
2876 if (safi == SAFI_UNICAST)
2877 group_announce_route(bgp, afi,
9bcb3eef 2878 SAFI_LABELED_UNICAST, dest,
d62a17ae 2879 new_select);
2880
1defdda8 2881 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2882 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2883 }
fee0f4c6 2884
3b0c17e1 2885 /* advertise/withdraw type-5 routes */
2886 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2887 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2888 bgp_process_evpn_route_injection(
9bcb3eef 2889 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2890
b1875e65 2891 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2892 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2893 bgp_zebra_clear_route_change_flags(dest);
2894 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2895 return;
d62a17ae 2896 }
8ad7271d 2897
d62a17ae 2898 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2899 */
9bcb3eef 2900 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2901
2902 /* bestpath has changed; bump version */
2903 if (old_select || new_select) {
9bcb3eef 2904 bgp_bump_version(dest);
d62a17ae 2905
2906 if (!bgp->t_rmap_def_originate_eval) {
2907 bgp_lock(bgp);
2908 thread_add_timer(
2909 bm->master,
2910 update_group_refresh_default_originate_route_map,
2911 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2912 &bgp->t_rmap_def_originate_eval);
2913 }
2914 }
3f9c7369 2915
d62a17ae 2916 if (old_select)
9bcb3eef 2917 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2918 if (new_select) {
ddb5b488
PZ
2919 if (debug)
2920 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2921 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2922 bgp_path_info_unset_flag(dest, new_select,
2923 BGP_PATH_ATTR_CHANGED);
1defdda8 2924 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2925 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2926 }
338b3424 2927
49e5a4a0 2928#ifdef ENABLE_BGP_VNC
d62a17ae 2929 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2930 if (old_select != new_select) {
2931 if (old_select) {
2932 vnc_import_bgp_exterior_del_route(bgp, p,
2933 old_select);
2934 vnc_import_bgp_del_route(bgp, p, old_select);
2935 }
2936 if (new_select) {
2937 vnc_import_bgp_exterior_add_route(bgp, p,
2938 new_select);
2939 vnc_import_bgp_add_route(bgp, p, new_select);
2940 }
2941 }
2942 }
65efcfce
LB
2943#endif
2944
9bcb3eef 2945 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2946
2947 /* unicast routes must also be annouced to labeled-unicast update-groups
2948 */
2949 if (safi == SAFI_UNICAST)
9bcb3eef 2950 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2951 new_select);
2952
2953 /* FIB update. */
2954 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2955 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2956 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2957 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2958 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2959 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2960
2961 /* if this is an evpn imported type-5 prefix,
2962 * we need to withdraw the route first to clear
2963 * the nh neigh and the RMAC entry.
2964 */
2965 if (old_select &&
2966 is_route_parent_evpn(old_select))
2967 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2968
9bcb3eef 2969 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2970 } else {
d62a17ae 2971 /* Withdraw the route from the kernel. */
2972 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2973 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2974 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2975 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2976
568e10ca 2977 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2978 }
718e3744 2979 }
3064bf43 2980
9bcb3eef 2981 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2982 old_select);
5424b7ba 2983
d62a17ae 2984 /* Clear any route change flags. */
9bcb3eef 2985 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2986
18ee8310 2987 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2988 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2989 bgp_path_info_reap(dest, old_select);
d62a17ae 2990
9bcb3eef 2991 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2992 return;
718e3744 2993}
2994
f009ff26 2995/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2996int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2997{
9bcb3eef 2998 struct bgp_dest *dest;
f009ff26 2999 int cnt = 0;
3000 struct afi_safi_info *thread_info;
f009ff26 3001
56c226e7
DS
3002 if (bgp->gr_info[afi][safi].t_route_select) {
3003 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3004
3005 thread_info = THREAD_ARG(t);
3006 XFREE(MTYPE_TMP, thread_info);
f009ff26 3007 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3008 }
f009ff26 3009
3010 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3011 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3012 get_afi_safi_str(afi, safi, false),
26742171 3013 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3014 }
3015
3016 /* Process the route list */
6338d242
DS
3017 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3018 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3019 dest = bgp_route_next(dest)) {
3020 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3021 continue;
3022
3023 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3024 bgp->gr_info[afi][safi].gr_deferred--;
3025 bgp_process_main_one(bgp, dest, afi, safi);
3026 cnt++;
3027 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3028 bgp_dest_unlock_node(dest);
3029 break;
f009ff26 3030 }
f009ff26 3031 }
3032
9e3b51a7 3033 /* Send EOR message when all routes are processed */
6338d242 3034 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3035 bgp_send_delayed_eor(bgp);
8c48b3b6 3036 /* Send route processing complete message to RIB */
3037 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3038 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3039 return 0;
9e3b51a7 3040 }
f009ff26 3041
3042 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3043
3044 thread_info->afi = afi;
3045 thread_info->safi = safi;
3046 thread_info->bgp = bgp;
3047
3048 /* If there are more routes to be processed, start the
3049 * selection timer
3050 */
3051 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3052 BGP_ROUTE_SELECT_DELAY,
3053 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3054 return 0;
3055}
3056
aac24838 3057static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3058{
aac24838
JB
3059 struct bgp_process_queue *pqnode = data;
3060 struct bgp *bgp = pqnode->bgp;
d62a17ae 3061 struct bgp_table *table;
9bcb3eef 3062 struct bgp_dest *dest;
aac24838
JB
3063
3064 /* eoiu marker */
3065 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3066 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3067 /* should always have dedicated wq call */
3068 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3069 return WQ_SUCCESS;
3070 }
3071
ac021f40 3072 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3073 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3074 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3075 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3076 table = bgp_dest_table(dest);
3077 /* note, new DESTs may be added as part of processing */
3078 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3079
9bcb3eef 3080 bgp_dest_unlock_node(dest);
d62a17ae 3081 bgp_table_unlock(table);
3082 }
aac24838
JB
3083
3084 return WQ_SUCCESS;
3085}
3086
3087static void bgp_processq_del(struct work_queue *wq, void *data)
3088{
3089 struct bgp_process_queue *pqnode = data;
3090
3091 bgp_unlock(pqnode->bgp);
3092
3093 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3094}
3095
b6c386bb 3096void bgp_process_queue_init(struct bgp *bgp)
200df115 3097{
b6c386bb
DS
3098 if (!bgp->process_queue) {
3099 char name[BUFSIZ];
3100
3101 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3102 bgp->process_queue = work_queue_new(bm->master, name);
3103 }
3104
3105 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3106 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3107 bgp->process_queue->spec.max_retries = 0;
3108 bgp->process_queue->spec.hold = 50;
d62a17ae 3109 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3110 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3111}
3112
cfe8d15a 3113static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3114{
3115 struct bgp_process_queue *pqnode;
3116
a4d82a8a
PZ
3117 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3118 sizeof(struct bgp_process_queue));
aac24838
JB
3119
3120 /* unlocked in bgp_processq_del */
3121 pqnode->bgp = bgp_lock(bgp);
3122 STAILQ_INIT(&pqnode->pqueue);
3123
aac24838
JB
3124 return pqnode;
3125}
3126
9bcb3eef 3127void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3128{
aac24838 3129#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3130 struct work_queue *wq = bgp->process_queue;
d62a17ae 3131 struct bgp_process_queue *pqnode;
cfe8d15a 3132 int pqnode_reuse = 0;
495f0b13 3133
d62a17ae 3134 /* already scheduled for processing? */
9bcb3eef 3135 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3136 return;
2e02b9b2 3137
f009ff26 3138 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3139 * the workqueue
3140 */
9bcb3eef 3141 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3142 if (BGP_DEBUG(update, UPDATE_OUT))
3143 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3144 dest);
f009ff26 3145 return;
3146 }
3147
46aeabed
LS
3148 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3149 if (BGP_DEBUG(update, UPDATE_OUT))
3150 zlog_debug(
3151 "Soft reconfigure table in progress for route %p",
3152 dest);
3153 return;
3154 }
3155
aac24838 3156 if (wq == NULL)
d62a17ae 3157 return;
3158
aac24838 3159 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3160 limit only if is from the same BGP view and it's not an EOIU marker
3161 */
aac24838
JB
3162 if (work_queue_item_count(wq)) {
3163 struct work_queue_item *item = work_queue_last_item(wq);
3164 pqnode = item->data;
228da428 3165
a4d82a8a
PZ
3166 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3167 || pqnode->bgp != bgp
3168 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3169 pqnode = bgp_processq_alloc(bgp);
3170 else
3171 pqnode_reuse = 1;
aac24838 3172 } else
cfe8d15a 3173 pqnode = bgp_processq_alloc(bgp);
aac24838 3174 /* all unlocked in bgp_process_wq */
9bcb3eef 3175 bgp_table_lock(bgp_dest_table(dest));
aac24838 3176
9bcb3eef
DS
3177 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3178 bgp_dest_lock_node(dest);
aac24838 3179
60466a63 3180 /* can't be enqueued twice */
9bcb3eef
DS
3181 assert(STAILQ_NEXT(dest, pq) == NULL);
3182 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3183 pqnode->queued++;
3184
cfe8d15a
LB
3185 if (!pqnode_reuse)
3186 work_queue_add(wq, pqnode);
3187
d62a17ae 3188 return;
fee0f4c6 3189}
0a486e5f 3190
d62a17ae 3191void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3192{
d62a17ae 3193 struct bgp_process_queue *pqnode;
cb1faec9 3194
b6c386bb 3195 if (bgp->process_queue == NULL)
d62a17ae 3196 return;
2e02b9b2 3197
cfe8d15a 3198 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3199
aac24838 3200 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3201 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3202}
3203
d62a17ae 3204static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3205{
d62a17ae 3206 struct peer *peer;
0a486e5f 3207
d62a17ae 3208 peer = THREAD_ARG(thread);
3209 peer->t_pmax_restart = NULL;
0a486e5f 3210
d62a17ae 3211 if (bgp_debug_neighbor_events(peer))
3212 zlog_debug(
3213 "%s Maximum-prefix restart timer expired, restore peering",
3214 peer->host);
0a486e5f 3215
a9bafa95 3216 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3217 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3218
d62a17ae 3219 return 0;
0a486e5f 3220}
3221
9cbd06e0
DA
3222static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3223 safi_t safi)
3224{
3225 uint32_t count = 0;
f41b0459 3226 bool filtered = false;
9cbd06e0
DA
3227 struct bgp_dest *dest;
3228 struct bgp_adj_in *ain;
40bb2ccf 3229 struct attr attr = {};
9cbd06e0
DA
3230 struct bgp_table *table = peer->bgp->rib[afi][safi];
3231
3232 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3233 for (ain = dest->adj_in; ain; ain = ain->next) {
3234 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3235
3236 attr = *ain->attr;
9cbd06e0
DA
3237
3238 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3239 == FILTER_DENY)
f41b0459
DA
3240 filtered = true;
3241
3242 if (bgp_input_modifier(
3243 peer, rn_p, &attr, afi, safi,
3244 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3245 NULL, 0, NULL)
3246 == RMAP_DENY)
3247 filtered = true;
3248
3249 if (filtered)
9cbd06e0 3250 count++;
f41b0459
DA
3251
3252 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3253 }
3254 }
3255
3256 return count;
3257}
3258
3dc339cd
DA
3259bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3260 int always)
718e3744 3261{
d62a17ae 3262 iana_afi_t pkt_afi;
5c525538 3263 iana_safi_t pkt_safi;
9cbd06e0
DA
3264 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3265 PEER_FLAG_MAX_PREFIX_FORCE))
3266 ? bgp_filtered_routes_count(peer, afi, safi)
3267 + peer->pcount[afi][safi]
3268 : peer->pcount[afi][safi];
9cabb64b 3269
d62a17ae 3270 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3271 return false;
e0701b79 3272
9cbd06e0 3273 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3274 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3275 PEER_STATUS_PREFIX_LIMIT)
3276 && !always)
3dc339cd 3277 return false;
e0701b79 3278
d62a17ae 3279 zlog_info(
6cde4b45 3280 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3281 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3282 peer->pmax[afi][safi]);
d62a17ae 3283 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3284
3285 if (CHECK_FLAG(peer->af_flags[afi][safi],
3286 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3287 return false;
d62a17ae 3288
3289 /* Convert AFI, SAFI to values for packet. */
3290 pkt_afi = afi_int2iana(afi);
3291 pkt_safi = safi_int2iana(safi);
3292 {
d7c0a89a 3293 uint8_t ndata[7];
d62a17ae 3294
3295 ndata[0] = (pkt_afi >> 8);
3296 ndata[1] = pkt_afi;
3297 ndata[2] = pkt_safi;
3298 ndata[3] = (peer->pmax[afi][safi] >> 24);
3299 ndata[4] = (peer->pmax[afi][safi] >> 16);
3300 ndata[5] = (peer->pmax[afi][safi] >> 8);
3301 ndata[6] = (peer->pmax[afi][safi]);
3302
3303 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3304 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3305 BGP_NOTIFY_CEASE_MAX_PREFIX,
3306 ndata, 7);
3307 }
3308
3309 /* Dynamic peers will just close their connection. */
3310 if (peer_dynamic_neighbor(peer))
3dc339cd 3311 return true;
d62a17ae 3312
3313 /* restart timer start */
3314 if (peer->pmax_restart[afi][safi]) {
3315 peer->v_pmax_restart =
3316 peer->pmax_restart[afi][safi] * 60;
3317
3318 if (bgp_debug_neighbor_events(peer))
3319 zlog_debug(
3320 "%s Maximum-prefix restart timer started for %d secs",
3321 peer->host, peer->v_pmax_restart);
3322
3323 BGP_TIMER_ON(peer->t_pmax_restart,
3324 bgp_maximum_prefix_restart_timer,
3325 peer->v_pmax_restart);
3326 }
3327
3dc339cd 3328 return true;
d62a17ae 3329 } else
3330 UNSET_FLAG(peer->af_sflags[afi][safi],
3331 PEER_STATUS_PREFIX_LIMIT);
3332
b1823b69
DS
3333 if (pcount
3334 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3335 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3336 PEER_STATUS_PREFIX_THRESHOLD)
3337 && !always)
3dc339cd 3338 return false;
d62a17ae 3339
3340 zlog_info(
6cde4b45 3341 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3342 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3343 peer->pmax[afi][safi]);
d62a17ae 3344 SET_FLAG(peer->af_sflags[afi][safi],
3345 PEER_STATUS_PREFIX_THRESHOLD);
3346 } else
3347 UNSET_FLAG(peer->af_sflags[afi][safi],
3348 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3349 return false;
718e3744 3350}
3351
b40d939b 3352/* Unconditionally remove the route from the RIB, without taking
3353 * damping into consideration (eg, because the session went down)
3354 */
9bcb3eef 3355void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3356 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3357{
f009ff26 3358
3359 struct bgp *bgp = NULL;
3360 bool delete_route = false;
3361
9bcb3eef
DS
3362 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3363 safi);
d62a17ae 3364
f009ff26 3365 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3366 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3367
f009ff26 3368 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3369 * flag
3370 */
3371 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3372 delete_route = true;
9bcb3eef 3373 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3374 delete_route = true;
f009ff26 3375 if (delete_route) {
9bcb3eef
DS
3376 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3377 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3378 bgp = pi->peer->bgp;
26742171 3379 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3380 }
3381 }
3382 }
4a11bf2c 3383
9bcb3eef
DS
3384 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3385 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3386}
3387
9bcb3eef 3388static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3389 struct peer *peer, afi_t afi, safi_t safi,
3390 struct prefix_rd *prd)
3391{
9bcb3eef 3392 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3393
d62a17ae 3394 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3395 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3396 */
40ec3340
DS
3397 if (peer->sort == BGP_PEER_EBGP) {
3398 if (get_active_bdc_from_pi(pi, afi, safi)) {
3399 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3400 == BGP_DAMP_SUPPRESSED) {
3401 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3402 safi);
3403 return;
3404 }
d62a17ae 3405 }
40ec3340 3406 }
d62a17ae 3407
49e5a4a0 3408#ifdef ENABLE_BGP_VNC
d62a17ae 3409 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3410 struct bgp_dest *pdest = NULL;
d62a17ae 3411 struct bgp_table *table = NULL;
3412
9bcb3eef
DS
3413 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3414 (struct prefix *)prd);
3415 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3416 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3417
3418 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3419 peer->bgp, prd, table, p, pi);
d62a17ae 3420 }
9bcb3eef 3421 bgp_dest_unlock_node(pdest);
d62a17ae 3422 }
3423 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3424 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3425
b54892e0
DS
3426 vnc_import_bgp_del_route(peer->bgp, p, pi);
3427 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3428 }
65efcfce 3429 }
d62a17ae 3430#endif
128ea8ab 3431
d62a17ae 3432 /* If this is an EVPN route, process for un-import. */
3433 if (safi == SAFI_EVPN)
b54892e0 3434 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3435
9bcb3eef 3436 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3437}
3438
4b7e6066
DS
3439struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3440 struct peer *peer, struct attr *attr,
9bcb3eef 3441 struct bgp_dest *dest)
fb018d25 3442{
4b7e6066 3443 struct bgp_path_info *new;
fb018d25 3444
d62a17ae 3445 /* Make new BGP info. */
4b7e6066 3446 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3447 new->type = type;
3448 new->instance = instance;
3449 new->sub_type = sub_type;
3450 new->peer = peer;
3451 new->attr = attr;
3452 new->uptime = bgp_clock();
9bcb3eef 3453 new->net = dest;
d62a17ae 3454 return new;
fb018d25
DS
3455}
3456
40381db7 3457static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3458 union gw_addr *gw_ip)
3459{
6c924775
DS
3460 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3461 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3462 union {
0a50c248 3463 esi_t esi;
11ebf4ed
DS
3464 union gw_addr ip;
3465 } temp;
d62a17ae 3466
3467 if (afi != AFI_L2VPN)
3468 return true;
11ebf4ed 3469
6c924775 3470 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3471
3472 if (gw_ip == NULL) {
3473 memset(&temp, 0, sizeof(temp));
40381db7 3474 path_gw_ip_remote = &temp.ip;
11ebf4ed 3475 } else
40381db7 3476 path_gw_ip_remote = gw_ip;
11ebf4ed 3477
6c924775 3478 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3479}
3480
c265ee22 3481/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3482bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3483 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3484 struct bgp_dest *dest)
d62a17ae 3485{
2dbe3fa9 3486 bool ret = false;
b099a5c8
DA
3487 bool is_bgp_static_route =
3488 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3489 : false;
d62a17ae 3490
e8442016
DS
3491 /*
3492 * Only validated for unicast and multicast currently.
3493 * Also valid for EVPN where the nexthop is an IP address.
3494 * If we are a bgp static route being checked then there is
3495 * no need to check to see if the nexthop is martian as
3496 * that it should be ok.
3497 */
3498 if (is_bgp_static_route ||
3499 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3500 return false;
d62a17ae 3501
3502 /* If NEXT_HOP is present, validate it. */
3503 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3504 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3505 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3506 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3507 return true;
d62a17ae 3508 }
c265ee22 3509
d62a17ae 3510 /* If MP_NEXTHOP is present, validate it. */
3511 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3512 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3513 * it is not an IPv6 link-local address.
0355b41d
DA
3514 *
3515 * If we receive an UPDATE with nexthop length set to 32 bytes
3516 * we shouldn't discard an UPDATE if it's set to (::).
3517 * The link-local (2st) is validated along the code path later.
d62a17ae 3518 */
3519 if (attr->mp_nexthop_len) {
3520 switch (attr->mp_nexthop_len) {
3521 case BGP_ATTR_NHLEN_IPV4:
3522 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3523 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3524 || IPV4_CLASS_DE(
3525 ntohl(attr->mp_nexthop_global_in.s_addr))
3526 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3527 dest));
d62a17ae 3528 break;
3529
3530 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3531 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3532 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3533 &attr->mp_nexthop_global)
d62a17ae 3534 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3535 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3536 &attr->mp_nexthop_global)
3537 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3538 dest));
d62a17ae 3539 break;
0355b41d
DA
3540 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3541 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3542 || IN6_IS_ADDR_MULTICAST(
3543 &attr->mp_nexthop_global)
3544 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3545 dest));
0355b41d 3546 break;
d62a17ae 3547
3548 default:
3dc339cd 3549 ret = true;
d62a17ae 3550 break;
3551 }
3552 }
c265ee22 3553
d62a17ae 3554 return ret;
3555}
3556
aade37d7 3557static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3558{
3559 struct community *old;
3560 struct community *new;
3561 struct community *merge;
aade37d7 3562 struct community *no_export;
2721dd61
DA
3563
3564 old = attr->community;
aade37d7 3565 no_export = community_str2com("no-export");
2721dd61 3566
b4efa101
DA
3567 assert(no_export);
3568
2721dd61 3569 if (old) {
aade37d7 3570 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3571
3572 if (!old->refcnt)
3573 community_free(&old);
3574
3575 new = community_uniq_sort(merge);
3576 community_free(&merge);
3577 } else {
aade37d7 3578 new = community_dup(no_export);
2721dd61
DA
3579 }
3580
aade37d7 3581 community_free(&no_export);
2721dd61
DA
3582
3583 attr->community = new;
3584 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3585}
3586
5a1ae2c2 3587int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3588 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3589 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3590 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3591 struct bgp_route_evpn *evpn)
d62a17ae 3592{
3593 int ret;
3594 int aspath_loop_count = 0;
9bcb3eef 3595 struct bgp_dest *dest;
d62a17ae 3596 struct bgp *bgp;
3597 struct attr new_attr;
3598 struct attr *attr_new;
40381db7 3599 struct bgp_path_info *pi;
4b7e6066
DS
3600 struct bgp_path_info *new;
3601 struct bgp_path_info_extra *extra;
d62a17ae 3602 const char *reason;
3603 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3604 int connected = 0;
3605 int do_loop_check = 1;
3606 int has_valid_label = 0;
7c312383 3607 afi_t nh_afi;
949b0f24 3608 uint8_t pi_type = 0;
3609 uint8_t pi_sub_type = 0;
9146341f 3610 bool force_evpn_import = false;
949b0f24 3611
c7bb4f00 3612 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3613 char pfxprint[PREFIX2STR_BUFFER];
3614
3615 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3616 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3617 afi, safi, attr);
6401252f
QY
3618 }
3619
49e5a4a0 3620#ifdef ENABLE_BGP_VNC
d62a17ae 3621 int vnc_implicit_withdraw = 0;
65efcfce 3622#endif
d62a17ae 3623 int same_attr = 0;
718e3744 3624
d62a17ae 3625 memset(&new_attr, 0, sizeof(struct attr));
3626 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3627 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3628
d62a17ae 3629 bgp = peer->bgp;
9bcb3eef 3630 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3631 /* TODO: Check to see if we can get rid of "is_valid_label" */
3632 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3633 has_valid_label = (num_labels > 0) ? 1 : 0;
3634 else
3635 has_valid_label = bgp_is_valid_label(label);
718e3744 3636
28f66de2
MS
3637 if (has_valid_label)
3638 assert(label != NULL);
3639
66ff6089
AD
3640 /* Update overlay index of the attribute */
3641 if (afi == AFI_L2VPN && evpn)
3642 memcpy(&attr->evpn_overlay, evpn,
3643 sizeof(struct bgp_route_evpn));
3644
d62a17ae 3645 /* When peer's soft reconfiguration enabled. Record input packet in
3646 Adj-RIBs-In. */
3647 if (!soft_reconfig
3648 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3649 && peer != bgp->peer_self)
9bcb3eef 3650 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3651
3652 /* Check previously received route. */
9bcb3eef 3653 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3654 if (pi->peer == peer && pi->type == type
3655 && pi->sub_type == sub_type
3656 && pi->addpath_rx_id == addpath_id)
d62a17ae 3657 break;
3658
3659 /* AS path local-as loop check. */
3660 if (peer->change_local_as) {
c4368918
DW
3661 if (peer->allowas_in[afi][safi])
3662 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3663 else if (!CHECK_FLAG(peer->flags,
3664 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3665 aspath_loop_count = 1;
3666
3667 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3668 > aspath_loop_count) {
b4d46cc9 3669 peer->stat_pfx_aspath_loop++;
692174a1 3670 reason = "as-path contains our own AS;";
d62a17ae 3671 goto filtered;
3672 }
718e3744 3673 }
718e3744 3674
d62a17ae 3675 /* If the peer is configured for "allowas-in origin" and the last ASN in
3676 * the
3677 * as-path is our ASN then we do not need to call aspath_loop_check
3678 */
3679 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3680 if (aspath_get_last_as(attr->aspath) == bgp->as)
3681 do_loop_check = 0;
3682
3683 /* AS path loop check. */
3684 if (do_loop_check) {
3685 if (aspath_loop_check(attr->aspath, bgp->as)
3686 > peer->allowas_in[afi][safi]
3687 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3688 && aspath_loop_check(attr->aspath, bgp->confed_id)
3689 > peer->allowas_in[afi][safi])) {
b4d46cc9 3690 peer->stat_pfx_aspath_loop++;
d62a17ae 3691 reason = "as-path contains our own AS;";
3692 goto filtered;
3693 }
3694 }
aac9ef6c 3695
d62a17ae 3696 /* Route reflector originator ID check. */
3697 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3698 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3699 peer->stat_pfx_originator_loop++;
d62a17ae 3700 reason = "originator is us;";
3701 goto filtered;
3702 }
718e3744 3703
d62a17ae 3704 /* Route reflector cluster ID check. */
3705 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3706 peer->stat_pfx_cluster_loop++;
d62a17ae 3707 reason = "reflected from the same cluster;";
3708 goto filtered;
3709 }
718e3744 3710
d62a17ae 3711 /* Apply incoming filter. */
3712 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3713 peer->stat_pfx_filter++;
d62a17ae 3714 reason = "filter;";
3715 goto filtered;
3716 }
718e3744 3717
a8b72dc6
DA
3718 /* RFC 8212 to prevent route leaks.
3719 * This specification intends to improve this situation by requiring the
3720 * explicit configuration of both BGP Import and Export Policies for any
3721 * External BGP (EBGP) session such as customers, peers, or
3722 * confederation boundaries for all enabled address families. Through
3723 * codification of the aforementioned requirement, operators will
3724 * benefit from consistent behavior across different BGP
3725 * implementations.
3726 */
1d3fdccf 3727 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3728 if (!bgp_inbound_policy_exists(peer,
3729 &peer->filter[afi][safi])) {
3730 reason = "inbound policy missing";
3731 goto filtered;
3732 }
3733
fb29348a
DA
3734 /* draft-ietf-idr-deprecate-as-set-confed-set
3735 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3736 * Eventually, This document (if approved) updates RFC 4271
3737 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3738 * and obsoletes RFC 6472.
3739 */
7f972cd8 3740 if (peer->bgp->reject_as_sets)
fb29348a
DA
3741 if (aspath_check_as_sets(attr->aspath)) {
3742 reason =
3743 "as-path contains AS_SET or AS_CONFED_SET type;";
3744 goto filtered;
3745 }
3746
6f4f49b2 3747 new_attr = *attr;
d62a17ae 3748
3749 /* Apply incoming route-map.
3750 * NB: new_attr may now contain newly allocated values from route-map
3751 * "set"
3752 * commands, so we need bgp_attr_flush in the error paths, until we
3753 * intern
3754 * the attr (which takes over the memory references) */
9bcb3eef
DS
3755 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3756 num_labels, dest)
3757 == RMAP_DENY) {
b4d46cc9 3758 peer->stat_pfx_filter++;
d62a17ae 3759 reason = "route-map;";
3760 bgp_attr_flush(&new_attr);
3761 goto filtered;
3762 }
718e3744 3763
05864da7 3764 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3765 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3766 /* remove from RIB previous entry */
3767 bgp_zebra_withdraw(p, pi, bgp, safi);
3768 }
3769
7f323236
DW
3770 if (peer->sort == BGP_PEER_EBGP) {
3771
2721dd61
DA
3772 /* rfc7999:
3773 * A BGP speaker receiving an announcement tagged with the
3774 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3775 * NO_EXPORT community as defined in RFC1997, or a
3776 * similar community, to prevent propagation of the
3777 * prefix outside the local AS. The community to prevent
3778 * propagation SHOULD be chosen according to the operator's
3779 * routing policy.
3780 */
3781 if (new_attr.community
3782 && community_include(new_attr.community,
3783 COMMUNITY_BLACKHOLE))
aade37d7 3784 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3785
a4d82a8a
PZ
3786 /* If we receive the graceful-shutdown community from an eBGP
3787 * peer we must lower local-preference */
3788 if (new_attr.community
3789 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3790 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3791 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3792
a4d82a8a
PZ
3793 /* If graceful-shutdown is configured then add the GSHUT
3794 * community to all paths received from eBGP peers */
637e5ba4 3795 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3796 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3797 }
3798
949b0f24 3799 if (pi) {
3800 pi_type = pi->type;
3801 pi_sub_type = pi->sub_type;
3802 }
3803
d62a17ae 3804 /* next hop check. */
a4d82a8a 3805 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3806 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3807 &new_attr, dest)) {
b4d46cc9 3808 peer->stat_pfx_nh_invalid++;
d62a17ae 3809 reason = "martian or self next-hop;";
3810 bgp_attr_flush(&new_attr);
3811 goto filtered;
3812 }
718e3744 3813
5c14a191 3814 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3815 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3816 reason = "self mac;";
3817 goto filtered;
3818 }
3819
a1b773e2
DS
3820 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3821 * condition :
3822 * Suppress fib is enabled
3823 * BGP_OPT_NO_FIB is not enabled
3824 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3825 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3826 */
3827 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3828 && (sub_type == BGP_ROUTE_NORMAL)
3829 && (!bgp_option_check(BGP_OPT_NO_FIB))
3830 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3831 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3832
d62a17ae 3833 attr_new = bgp_attr_intern(&new_attr);
3834
9cbd06e0
DA
3835 /* If maximum prefix count is configured and current prefix
3836 * count exeed it.
3837 */
3838 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3839 return -1;
3840
d62a17ae 3841 /* If the update is implicit withdraw. */
40381db7
DS
3842 if (pi) {
3843 pi->uptime = bgp_clock();
3844 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3845
9bcb3eef 3846 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3847
d62a17ae 3848 /* Same attribute comes in. */
40381db7 3849 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3850 && same_attr
d62a17ae 3851 && (!has_valid_label
40381db7 3852 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3853 num_labels * sizeof(mpls_label_t))
66ff6089 3854 == 0)) {
40ec3340 3855 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3856 && peer->sort == BGP_PEER_EBGP
40381db7 3857 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3858 if (bgp_debug_update(peer, p, NULL, 1)) {
3859 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3860 afi, safi, prd, p, label,
3861 num_labels, addpath_id ? 1 : 0,
66ff6089 3862 addpath_id, evpn, pfx_buf,
a4d82a8a 3863 sizeof(pfx_buf));
d62a17ae 3864 zlog_debug("%s rcvd %s", peer->host,
3865 pfx_buf);
3866 }
3867
9bcb3eef 3868 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3869 != BGP_DAMP_SUPPRESSED) {
40381db7 3870 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3871 safi);
9bcb3eef 3872 bgp_process(bgp, dest, afi, safi);
d62a17ae 3873 }
3874 } else /* Duplicate - odd */
3875 {
3876 if (bgp_debug_update(peer, p, NULL, 1)) {
3877 if (!peer->rcvd_attr_printed) {
3878 zlog_debug(
3879 "%s rcvd UPDATE w/ attr: %s",
3880 peer->host,
3881 peer->rcvd_attr_str);
3882 peer->rcvd_attr_printed = 1;
3883 }
3884
3885 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3886 afi, safi, prd, p, label,
3887 num_labels, addpath_id ? 1 : 0,
66ff6089 3888 addpath_id, evpn, pfx_buf,
a4d82a8a 3889 sizeof(pfx_buf));
d62a17ae 3890 zlog_debug(
3891 "%s rcvd %s...duplicate ignored",
3892 peer->host, pfx_buf);
3893 }
3894
3895 /* graceful restart STALE flag unset. */
40381db7 3896 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3897 bgp_path_info_unset_flag(
9bcb3eef
DS
3898 dest, pi, BGP_PATH_STALE);
3899 bgp_dest_set_defer_flag(dest, false);
3900 bgp_process(bgp, dest, afi, safi);
d62a17ae 3901 }
3902 }
3903
9bcb3eef 3904 bgp_dest_unlock_node(dest);
d62a17ae 3905 bgp_attr_unintern(&attr_new);
3906
3907 return 0;
3908 }
718e3744 3909
d62a17ae 3910 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3911 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3912 if (bgp_debug_update(peer, p, NULL, 1)) {
3913 bgp_debug_rdpfxpath2str(
a4d82a8a 3914 afi, safi, prd, p, label, num_labels,
66ff6089 3915 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 3916 pfx_buf, sizeof(pfx_buf));
d62a17ae 3917 zlog_debug(
3918 "%s rcvd %s, flapped quicker than processing",
3919 peer->host, pfx_buf);
3920 }
3921
9bcb3eef 3922 bgp_path_info_restore(dest, pi);
9146341f 3923
3924 /*
3925 * If the BGP_PATH_REMOVED flag is set, then EVPN
3926 * routes would have been unimported already when a
3927 * prior BGP withdraw processing happened. Such routes
3928 * need to be imported again, so flag accordingly.
3929 */
3930 force_evpn_import = true;
d62a17ae 3931 }
718e3744 3932
d62a17ae 3933 /* Received Logging. */
3934 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3935 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3936 num_labels, addpath_id ? 1 : 0,
66ff6089 3937 addpath_id, evpn, pfx_buf,
a4d82a8a 3938 sizeof(pfx_buf));
d62a17ae 3939 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3940 }
718e3744 3941
d62a17ae 3942 /* graceful restart STALE flag unset. */
f009ff26 3943 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3944 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3945 bgp_dest_set_defer_flag(dest, false);
f009ff26 3946 }
d62a17ae 3947
3948 /* The attribute is changed. */
9bcb3eef 3949 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3950
3951 /* implicit withdraw, decrement aggregate and pcount here.
3952 * only if update is accepted, they'll increment below.
3953 */
40381db7 3954 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3955
3956 /* Update bgp route dampening information. */
40ec3340 3957 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3958 && peer->sort == BGP_PEER_EBGP) {
3959 /* This is implicit withdraw so we should update
40ec3340
DS
3960 * dampening information.
3961 */
40381db7 3962 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3963 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3964 }
49e5a4a0 3965#ifdef ENABLE_BGP_VNC
d62a17ae 3966 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3967 struct bgp_dest *pdest = NULL;
d62a17ae 3968 struct bgp_table *table = NULL;
3969
9bcb3eef
DS
3970 pdest = bgp_node_get(bgp->rib[afi][safi],
3971 (struct prefix *)prd);
3972 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3973 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3974
3975 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3976 bgp, prd, table, p, pi);
d62a17ae 3977 }
9bcb3eef 3978 bgp_dest_unlock_node(pdest);
d62a17ae 3979 }
3980 if ((afi == AFI_IP || afi == AFI_IP6)
3981 && (safi == SAFI_UNICAST)) {
40381db7 3982 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3983 /*
3984 * Implicit withdraw case.
3985 */
3986 ++vnc_implicit_withdraw;
40381db7
DS
3987 vnc_import_bgp_del_route(bgp, p, pi);
3988 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3989 }
3990 }
65efcfce 3991#endif
128ea8ab 3992
d62a17ae 3993 /* Special handling for EVPN update of an existing route. If the
3994 * extended community attribute has changed, we need to
3995 * un-import
3996 * the route using its existing extended community. It will be
3997 * subsequently processed for import with the new extended
3998 * community.
3999 */
6f8c9c11
PR
4000 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4001 && !same_attr) {
40381db7 4002 if ((pi->attr->flag
d62a17ae 4003 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4004 && (attr_new->flag
4005 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4006 int cmp;
4007
40381db7 4008 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4009 attr_new->ecommunity);
4010 if (!cmp) {
4011 if (bgp_debug_update(peer, p, NULL, 1))
4012 zlog_debug(
4013 "Change in EXT-COMM, existing %s new %s",
4014 ecommunity_str(
40381db7 4015 pi->attr->ecommunity),
d62a17ae 4016 ecommunity_str(
4017 attr_new->ecommunity));
6f8c9c11
PR
4018 if (safi == SAFI_EVPN)
4019 bgp_evpn_unimport_route(
4020 bgp, afi, safi, p, pi);
4021 else /* SAFI_MPLS_VPN */
4022 vpn_leak_to_vrf_withdraw(bgp,
4023 pi);
d62a17ae 4024 }
4025 }
4026 }
718e3744 4027
d62a17ae 4028 /* Update to new attribute. */
40381db7
DS
4029 bgp_attr_unintern(&pi->attr);
4030 pi->attr = attr_new;
d62a17ae 4031
4032 /* Update MPLS label */
4033 if (has_valid_label) {
40381db7 4034 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4035 if (extra->label != label) {
4036 memcpy(&extra->label, label,
dbd587da 4037 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4038 extra->num_labels = num_labels;
4039 }
b57ba6d2
MK
4040 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4041 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4042 }
718e3744 4043
e496b420
HS
4044 /* Update SRv6 SID */
4045 if (attr->srv6_l3vpn) {
4046 extra = bgp_path_info_extra_get(pi);
4047 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4048 sid_copy(&extra->sid[0],
4049 &attr->srv6_l3vpn->sid);
4050 extra->num_sids = 1;
4051 }
4052 } else if (attr->srv6_vpn) {
4053 extra = bgp_path_info_extra_get(pi);
4054 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4055 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4056 extra->num_sids = 1;
4057 }
4058 }
4059
49e5a4a0 4060#ifdef ENABLE_BGP_VNC
d62a17ae 4061 if ((afi == AFI_IP || afi == AFI_IP6)
4062 && (safi == SAFI_UNICAST)) {
4063 if (vnc_implicit_withdraw) {
4064 /*
4065 * Add back the route with its new attributes
4066 * (e.g., nexthop).
4067 * The route is still selected, until the route
4068 * selection
4069 * queued by bgp_process actually runs. We have
4070 * to make this
4071 * update to the VNC side immediately to avoid
4072 * racing against
4073 * configuration changes (e.g., route-map
4074 * changes) which
4075 * trigger re-importation of the entire RIB.
4076 */
40381db7
DS
4077 vnc_import_bgp_add_route(bgp, p, pi);
4078 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4079 }
4080 }
65efcfce
LB
4081#endif
4082
d62a17ae 4083 /* Update bgp route dampening information. */
40ec3340 4084 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4085 && peer->sort == BGP_PEER_EBGP) {
4086 /* Now we do normal update dampening. */
9bcb3eef 4087 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4088 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4089 bgp_dest_unlock_node(dest);
d62a17ae 4090 return 0;
4091 }
4092 }
128ea8ab 4093
d62a17ae 4094 /* Nexthop reachability check - for unicast and
4095 * labeled-unicast.. */
7c312383
AD
4096 if (((afi == AFI_IP || afi == AFI_IP6)
4097 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4098 || (safi == SAFI_EVPN &&
4099 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4100 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4101 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4102 && !CHECK_FLAG(peer->flags,
4103 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4104 && !CHECK_FLAG(bgp->flags,
4105 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4106 connected = 1;
4107 else
4108 connected = 0;
4109
960035b2
PZ
4110 struct bgp *bgp_nexthop = bgp;
4111
40381db7
DS
4112 if (pi->extra && pi->extra->bgp_orig)
4113 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4114
7c312383
AD
4115 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4116
4117 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4118 safi, pi, NULL, connected,
4119 p)
a4d82a8a 4120 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4121 bgp_path_info_set_flag(dest, pi,
4122 BGP_PATH_VALID);
d62a17ae 4123 else {
4124 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4125 zlog_debug("%s(%pI4): NH unresolved",
4126 __func__,
4127 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4128 }
9bcb3eef 4129 bgp_path_info_unset_flag(dest, pi,
18ee8310 4130 BGP_PATH_VALID);
d62a17ae 4131 }
4132 } else
9bcb3eef 4133 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4134
49e5a4a0 4135#ifdef ENABLE_BGP_VNC
d62a17ae 4136 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4137 struct bgp_dest *pdest = NULL;
d62a17ae 4138 struct bgp_table *table = NULL;
4139
9bcb3eef
DS
4140 pdest = bgp_node_get(bgp->rib[afi][safi],
4141 (struct prefix *)prd);
4142 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4143 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4144
4145 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4146 bgp, prd, table, p, pi);
d62a17ae 4147 }
9bcb3eef 4148 bgp_dest_unlock_node(pdest);
d62a17ae 4149 }
4150#endif
718e3744 4151
d62a17ae 4152 /* If this is an EVPN route and some attribute has changed,
9146341f 4153 * or we are explicitly told to perform a route import, process
d62a17ae 4154 * route for import. If the extended community has changed, we
4155 * would
4156 * have done the un-import earlier and the import would result
4157 * in the
4158 * route getting injected into appropriate L2 VNIs. If it is
4159 * just
4160 * some other attribute change, the import will result in
4161 * updating
4162 * the attributes for the route in the VNI(s).
4163 */
9146341f 4164 if (safi == SAFI_EVPN &&
4165 (!same_attr || force_evpn_import) &&
7c312383 4166 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4167 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4168
4169 /* Process change. */
40381db7 4170 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4171
9bcb3eef
DS
4172 bgp_process(bgp, dest, afi, safi);
4173 bgp_dest_unlock_node(dest);
558d1fec 4174
ddb5b488
PZ
4175 if (SAFI_UNICAST == safi
4176 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4177 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4178
40381db7 4179 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4180 }
4181 if ((SAFI_MPLS_VPN == safi)
4182 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4183
40381db7 4184 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4185 }
4186
49e5a4a0 4187#ifdef ENABLE_BGP_VNC
d62a17ae 4188 if (SAFI_MPLS_VPN == safi) {
4189 mpls_label_t label_decoded = decode_label(label);
28070ee3 4190
d62a17ae 4191 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4192 type, sub_type, &label_decoded);
4193 }
4194 if (SAFI_ENCAP == safi) {
4195 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4196 type, sub_type, NULL);
4197 }
28070ee3
PZ
4198#endif
4199
d62a17ae 4200 return 0;
4201 } // End of implicit withdraw
718e3744 4202
d62a17ae 4203 /* Received Logging. */
4204 if (bgp_debug_update(peer, p, NULL, 1)) {
4205 if (!peer->rcvd_attr_printed) {
4206 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4207 peer->rcvd_attr_str);
4208 peer->rcvd_attr_printed = 1;
4209 }
718e3744 4210
a4d82a8a 4211 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4212 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4213 pfx_buf, sizeof(pfx_buf));
d62a17ae 4214 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4215 }
718e3744 4216
d62a17ae 4217 /* Make new BGP info. */
9bcb3eef 4218 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4219
d62a17ae 4220 /* Update MPLS label */
4221 if (has_valid_label) {
18ee8310 4222 extra = bgp_path_info_extra_get(new);
8ba71050 4223 if (extra->label != label) {
dbd587da
QY
4224 memcpy(&extra->label, label,
4225 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4226 extra->num_labels = num_labels;
4227 }
b57ba6d2
MK
4228 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4229 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4230 }
718e3744 4231
e496b420
HS
4232 /* Update SRv6 SID */
4233 if (safi == SAFI_MPLS_VPN) {
4234 extra = bgp_path_info_extra_get(new);
4235 if (attr->srv6_l3vpn) {
4236 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4237 extra->num_sids = 1;
4238 } else if (attr->srv6_vpn) {
4239 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4240 extra->num_sids = 1;
4241 }
4242 }
4243
d62a17ae 4244 /* Nexthop reachability check. */
7c312383
AD
4245 if (((afi == AFI_IP || afi == AFI_IP6)
4246 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4247 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4248 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4249 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4250 && !CHECK_FLAG(peer->flags,
4251 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4252 && !CHECK_FLAG(bgp->flags,
4253 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4254 connected = 1;
4255 else
4256 connected = 0;
4257
7c312383
AD
4258 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4259
4053e952 4260 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4261 connected, p)
a4d82a8a 4262 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4263 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4264 else {
4265 if (BGP_DEBUG(nht, NHT)) {
4266 char buf1[INET6_ADDRSTRLEN];
4267 inet_ntop(AF_INET,
4268 (const void *)&attr_new->nexthop,
4269 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4270 zlog_debug("%s(%s): NH unresolved", __func__,
4271 buf1);
d62a17ae 4272 }
9bcb3eef 4273 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4274 }
4275 } else
9bcb3eef 4276 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4277
d62a17ae 4278 /* Addpath ID */
4279 new->addpath_rx_id = addpath_id;
4280
4281 /* Increment prefix */
4282 bgp_aggregate_increment(bgp, p, new, afi, safi);
4283
4284 /* Register new BGP information. */
9bcb3eef 4285 bgp_path_info_add(dest, new);
d62a17ae 4286
4287 /* route_node_get lock */
9bcb3eef 4288 bgp_dest_unlock_node(dest);
558d1fec 4289
49e5a4a0 4290#ifdef ENABLE_BGP_VNC
d62a17ae 4291 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4292 struct bgp_dest *pdest = NULL;
d62a17ae 4293 struct bgp_table *table = NULL;
4294
9bcb3eef
DS
4295 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4296 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4297 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4298
4299 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4300 bgp, prd, table, p, new);
4301 }
9bcb3eef 4302 bgp_dest_unlock_node(pdest);
d62a17ae 4303 }
65efcfce
LB
4304#endif
4305
d62a17ae 4306 /* If this is an EVPN route, process for import. */
7c312383 4307 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4308 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4309
9bcb3eef 4310 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4311
d62a17ae 4312 /* Process change. */
9bcb3eef 4313 bgp_process(bgp, dest, afi, safi);
718e3744 4314
ddb5b488
PZ
4315 if (SAFI_UNICAST == safi
4316 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4317 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4318 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4319 }
4320 if ((SAFI_MPLS_VPN == safi)
4321 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4322
4323 vpn_leak_to_vrf_update(bgp, new);
4324 }
49e5a4a0 4325#ifdef ENABLE_BGP_VNC
d62a17ae 4326 if (SAFI_MPLS_VPN == safi) {
4327 mpls_label_t label_decoded = decode_label(label);
28070ee3 4328
d62a17ae 4329 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4330 sub_type, &label_decoded);
4331 }
4332 if (SAFI_ENCAP == safi) {
4333 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4334 sub_type, NULL);
4335 }
28070ee3
PZ
4336#endif
4337
d62a17ae 4338 return 0;
718e3744 4339
d62a17ae 4340/* This BGP update is filtered. Log the reason then update BGP
4341 entry. */
4342filtered:
9bcb3eef 4343 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4344
d62a17ae 4345 if (bgp_debug_update(peer, p, NULL, 1)) {
4346 if (!peer->rcvd_attr_printed) {
4347 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4348 peer->rcvd_attr_str);
4349 peer->rcvd_attr_printed = 1;
4350 }
718e3744 4351
a4d82a8a 4352 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4353 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4354 pfx_buf, sizeof(pfx_buf));
d62a17ae 4355 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4356 peer->host, pfx_buf, reason);
4357 }
128ea8ab 4358
40381db7 4359 if (pi) {
d62a17ae 4360 /* If this is an EVPN route, un-import it as it is now filtered.
4361 */
4362 if (safi == SAFI_EVPN)
40381db7 4363 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4364
ddb5b488
PZ
4365 if (SAFI_UNICAST == safi
4366 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4367 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4368
40381db7 4369 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4370 }
4371 if ((SAFI_MPLS_VPN == safi)
4372 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4373
40381db7 4374 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4375 }
4376
9bcb3eef 4377 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4378 }
4379
9bcb3eef 4380 bgp_dest_unlock_node(dest);
558d1fec 4381
49e5a4a0 4382#ifdef ENABLE_BGP_VNC
d62a17ae 4383 /*
4384 * Filtered update is treated as an implicit withdrawal (see
4385 * bgp_rib_remove()
4386 * a few lines above)
4387 */
4388 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4389 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4390 0);
4391 }
97736e32
PZ
4392#endif
4393
d62a17ae 4394 return 0;
718e3744 4395}
4396
26a3ffd6 4397int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4398 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4399 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4400 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4401{
d62a17ae 4402 struct bgp *bgp;
4403 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4404 struct bgp_dest *dest;
40381db7 4405 struct bgp_path_info *pi;
718e3744 4406
49e5a4a0 4407#ifdef ENABLE_BGP_VNC
d62a17ae 4408 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4409 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4410 0);
4411 }
28070ee3
PZ
4412#endif
4413
d62a17ae 4414 bgp = peer->bgp;
4415
4416 /* Lookup node. */
9bcb3eef 4417 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4418
4419 /* If peer is soft reconfiguration enabled. Record input packet for
4420 * further calculation.
4421 *
4422 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4423 * routes that are filtered. This tanks out Quagga RS pretty badly due
4424 * to
4425 * the iteration over all RS clients.
4426 * Since we need to remove the entry from adj_in anyway, do that first
4427 * and
4428 * if there was no entry, we don't need to do anything more.
4429 */
4430 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4431 && peer != bgp->peer_self)
9bcb3eef 4432 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4433 peer->stat_pfx_dup_withdraw++;
4434
d62a17ae 4435 if (bgp_debug_update(peer, p, NULL, 1)) {
4436 bgp_debug_rdpfxpath2str(
a4d82a8a 4437 afi, safi, prd, p, label, num_labels,
6c995628
AD
4438 addpath_id ? 1 : 0, addpath_id, NULL,
4439 pfx_buf, sizeof(pfx_buf));
d62a17ae 4440 zlog_debug(
4441 "%s withdrawing route %s not in adj-in",
4442 peer->host, pfx_buf);
4443 }
9bcb3eef 4444 bgp_dest_unlock_node(dest);
d62a17ae 4445 return 0;
4446 }
cd808e74 4447
d62a17ae 4448 /* Lookup withdrawn route. */
9bcb3eef 4449 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4450 if (pi->peer == peer && pi->type == type
4451 && pi->sub_type == sub_type
4452 && pi->addpath_rx_id == addpath_id)
d62a17ae 4453 break;
4454
4455 /* Logging. */
4456 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4457 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4458 addpath_id ? 1 : 0, addpath_id, NULL,
4459 pfx_buf, sizeof(pfx_buf));
d62a17ae 4460 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4461 pfx_buf);
4462 }
718e3744 4463
d62a17ae 4464 /* Withdraw specified route from routing table. */
40381db7 4465 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4466 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4467 if (SAFI_UNICAST == safi
4468 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4469 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4470 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4471 }
4472 if ((SAFI_MPLS_VPN == safi)
4473 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4474
40381db7 4475 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4476 }
4477 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4478 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4479 addpath_id ? 1 : 0, addpath_id, NULL,
4480 pfx_buf, sizeof(pfx_buf));
d62a17ae 4481 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4482 }
718e3744 4483
d62a17ae 4484 /* Unlock bgp_node_get() lock. */
9bcb3eef 4485 bgp_dest_unlock_node(dest);
d62a17ae 4486
4487 return 0;
718e3744 4488}
6b0655a2 4489
d62a17ae 4490void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4491 int withdraw)
718e3744 4492{
d62a17ae 4493 struct update_subgroup *subgrp;
4494 subgrp = peer_subgroup(peer, afi, safi);
4495 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4496}
6182d65b 4497
718e3744 4498
3f9c7369
DS
4499/*
4500 * bgp_stop_announce_route_timer
4501 */
d62a17ae 4502void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4503{
d62a17ae 4504 if (!paf->t_announce_route)
4505 return;
4506
50478845 4507 thread_cancel(&paf->t_announce_route);
718e3744 4508}
6b0655a2 4509
3f9c7369
DS
4510/*
4511 * bgp_announce_route_timer_expired
4512 *
4513 * Callback that is invoked when the route announcement timer for a
4514 * peer_af expires.
4515 */
d62a17ae 4516static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4517{
d62a17ae 4518 struct peer_af *paf;
4519 struct peer *peer;
558d1fec 4520
d62a17ae 4521 paf = THREAD_ARG(t);
4522 peer = paf->peer;
718e3744 4523
feb17238 4524 if (!peer_established(peer))
d62a17ae 4525 return 0;
3f9c7369 4526
d62a17ae 4527 if (!peer->afc_nego[paf->afi][paf->safi])
4528 return 0;
3f9c7369 4529
d62a17ae 4530 peer_af_announce_route(paf, 1);
c5aec50b
MK
4531
4532 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4533 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4534
d62a17ae 4535 return 0;
718e3744 4536}
4537
3f9c7369
DS
4538/*
4539 * bgp_announce_route
4540 *
4541 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4542 */
d62a17ae 4543void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4544{
4545 struct peer_af *paf;
4546 struct update_subgroup *subgrp;
4547
4548 paf = peer_af_find(peer, afi, safi);
4549 if (!paf)
4550 return;
4551 subgrp = PAF_SUBGRP(paf);
4552
4553 /*
4554 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4555 * or a refresh has already been triggered.
4556 */
4557 if (!subgrp || paf->t_announce_route)
4558 return;
4559
4560 /*
4561 * Start a timer to stagger/delay the announce. This serves
4562 * two purposes - announcement can potentially be combined for
4563 * multiple peers and the announcement doesn't happen in the
4564 * vty context.
4565 */
4566 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4567 (subgrp->peer_count == 1)
4568 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4569 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4570 &paf->t_announce_route);
3f9c7369
DS
4571}
4572
4573/*
4574 * Announce routes from all AF tables to a peer.
4575 *
4576 * This should ONLY be called when there is a need to refresh the
4577 * routes to the peer based on a policy change for this peer alone
4578 * or a route refresh request received from the peer.
4579 * The operation will result in splitting the peer from its existing
4580 * subgroups and putting it in new subgroups.
4581 */
d62a17ae 4582void bgp_announce_route_all(struct peer *peer)
718e3744 4583{
d62a17ae 4584 afi_t afi;
4585 safi_t safi;
4586
05c7a1cc
QY
4587 FOREACH_AFI_SAFI (afi, safi)
4588 bgp_announce_route(peer, afi, safi);
718e3744 4589}
6b0655a2 4590
46aeabed
LS
4591/* Flag or unflag bgp_dest to determine whether it should be treated by
4592 * bgp_soft_reconfig_table_task.
4593 * Flag if flag is true. Unflag if flag is false.
4594 */
4595static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4596{
4597 struct bgp_dest *dest;
4598 struct bgp_adj_in *ain;
4599
4600 if (!table)
4601 return;
4602
4603 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4604 for (ain = dest->adj_in; ain; ain = ain->next) {
4605 if (ain->peer != NULL)
4606 break;
4607 }
4608 if (flag && ain != NULL && ain->peer != NULL)
4609 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4610 else
4611 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4612 }
4613}
4614
4615static int bgp_soft_reconfig_table_update(struct peer *peer,
4616 struct bgp_dest *dest,
4617 struct bgp_adj_in *ain, afi_t afi,
4618 safi_t safi, struct prefix_rd *prd)
4619{
4620 struct bgp_path_info *pi;
4621 uint32_t num_labels = 0;
4622 mpls_label_t *label_pnt = NULL;
4623 struct bgp_route_evpn evpn;
4624
4625 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4626 if (pi->peer == peer)
4627 break;
4628
4629 if (pi && pi->extra)
4630 num_labels = pi->extra->num_labels;
4631 if (num_labels)
4632 label_pnt = &pi->extra->label[0];
4633 if (pi)
4634 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4635 sizeof(evpn));
4636 else
4637 memset(&evpn, 0, sizeof(evpn));
4638
4639 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4640 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4641 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4642 &evpn);
4643}
4644
d62a17ae 4645static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4646 struct bgp_table *table,
4647 struct prefix_rd *prd)
718e3744 4648{
d62a17ae 4649 int ret;
9bcb3eef 4650 struct bgp_dest *dest;
d62a17ae 4651 struct bgp_adj_in *ain;
718e3744 4652
d62a17ae 4653 if (!table)
4654 table = peer->bgp->rib[afi][safi];
718e3744 4655
9bcb3eef
DS
4656 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4657 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4658 if (ain->peer != peer)
4659 continue;
8692c506 4660
46aeabed
LS
4661 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4662 afi, safi, prd);
ea47320b
DL
4663
4664 if (ret < 0) {
9bcb3eef 4665 bgp_dest_unlock_node(dest);
ea47320b 4666 return;
d62a17ae 4667 }
4668 }
718e3744 4669}
4670
46aeabed
LS
4671/* Do soft reconfig table per bgp table.
4672 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4673 * when BGP_NODE_SOFT_RECONFIG is set,
4674 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4675 * Schedule a new thread to continue the job.
4676 * Without splitting the full job into several part,
4677 * vtysh waits for the job to finish before responding to a BGP command
4678 */
4679static int bgp_soft_reconfig_table_task(struct thread *thread)
4680{
4681 uint32_t iter, max_iter;
4682 int ret;
4683 struct bgp_dest *dest;
4684 struct bgp_adj_in *ain;
4685 struct peer *peer;
4686 struct bgp_table *table;
4687 struct prefix_rd *prd;
4688 struct listnode *node, *nnode;
4689
4690 table = THREAD_ARG(thread);
4691 prd = NULL;
4692
4693 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4694 if (table->soft_reconfig_init) {
4695 /* first call of the function with a new srta structure.
4696 * Don't do any treatment this time on nodes
4697 * in order vtysh to respond quickly
4698 */
4699 max_iter = 0;
4700 }
4701
4702 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4703 dest = bgp_route_next(dest)) {
4704 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4705 continue;
4706
4707 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4708
4709 for (ain = dest->adj_in; ain; ain = ain->next) {
4710 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4711 nnode, peer)) {
4712 if (ain->peer != peer)
4713 continue;
4714
4715 ret = bgp_soft_reconfig_table_update(
4716 peer, dest, ain, table->afi,
4717 table->safi, prd);
4718 iter++;
4719
4720 if (ret < 0) {
4721 bgp_dest_unlock_node(dest);
4722 listnode_delete(
4723 table->soft_reconfig_peers,
4724 peer);
4725 bgp_announce_route(peer, table->afi,
4726 table->safi);
4727 if (list_isempty(
4728 table->soft_reconfig_peers)) {
4729 list_delete(
4730 &table->soft_reconfig_peers);
4731 bgp_soft_reconfig_table_flag(
4732 table, false);
4733 return 0;
4734 }
4735 }
4736 }
4737 }
4738 }
4739
4740 /* we're either starting the initial iteration,
4741 * or we're going to continue an ongoing iteration
4742 */
4743 if (dest || table->soft_reconfig_init) {
4744 table->soft_reconfig_init = false;
4745 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4746 table, 0, &table->soft_reconfig_thread);
4747 return 0;
4748 }
4749 /* we're done, clean up the background iteration context info and
4750 schedule route annoucement
4751 */
4752 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4753 listnode_delete(table->soft_reconfig_peers, peer);
4754 bgp_announce_route(peer, table->afi, table->safi);
4755 }
4756
4757 list_delete(&table->soft_reconfig_peers);
4758
4759 return 0;
4760}
4761
4762
4763/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4764 * and peer.
4765 * - bgp cannot be NULL
4766 * - if table and peer are NULL, cancel all threads within the bgp instance
4767 * - if table is NULL and peer is not,
4768 * remove peer in all threads within the bgp instance
4769 * - if peer is NULL, cancel all threads matching table within the bgp instance
4770 */
4771void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4772 const struct bgp_table *table,
4773 const struct peer *peer)
4774{
4775 struct peer *npeer;
4776 struct listnode *node, *nnode;
4777 int afi, safi;
4778 struct bgp_table *ntable;
4779
4780 if (!bgp)
4781 return;
4782
4783 FOREACH_AFI_SAFI (afi, safi) {
4784 ntable = bgp->rib[afi][safi];
4785 if (!ntable)
4786 continue;
4787 if (table && table != ntable)
4788 continue;
4789
4790 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4791 npeer)) {
4792 if (peer && peer != npeer)
4793 continue;
4794 listnode_delete(ntable->soft_reconfig_peers, npeer);
4795 }
4796
4797 if (!ntable->soft_reconfig_peers
4798 || !list_isempty(ntable->soft_reconfig_peers))
4799 continue;
4800
4801 list_delete(&ntable->soft_reconfig_peers);
4802 bgp_soft_reconfig_table_flag(ntable, false);
4803 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4804 }
4805}
4806
d62a17ae 4807void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4808{
9bcb3eef 4809 struct bgp_dest *dest;
d62a17ae 4810 struct bgp_table *table;
46aeabed
LS
4811 struct listnode *node, *nnode;
4812 struct peer *npeer;
4813 struct peer_af *paf;
718e3744 4814
feb17238 4815 if (!peer_established(peer))
d62a17ae 4816 return;
718e3744 4817
d62a17ae 4818 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
4819 && (safi != SAFI_EVPN)) {
4820 table = peer->bgp->rib[afi][safi];
4821 if (!table)
4822 return;
4823
4824 table->soft_reconfig_init = true;
4825
4826 if (!table->soft_reconfig_peers)
4827 table->soft_reconfig_peers = list_new();
4828 npeer = NULL;
4829 /* add peer to the table soft_reconfig_peers if not already
4830 * there
4831 */
4832 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
4833 npeer)) {
4834 if (peer == npeer)
4835 break;
4836 }
4837 if (peer != npeer)
4838 listnode_add(table->soft_reconfig_peers, peer);
4839
4840 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4841 * on table would start back at the beginning.
4842 */
4843 bgp_soft_reconfig_table_flag(table, true);
4844
4845 if (!table->soft_reconfig_thread)
4846 thread_add_event(bm->master,
4847 bgp_soft_reconfig_table_task, table, 0,
4848 &table->soft_reconfig_thread);
4849 /* Cancel bgp_announce_route_timer_expired threads.
4850 * bgp_announce_route_timer_expired threads have been scheduled
4851 * to announce routes as soon as the soft_reconfigure process
4852 * finishes.
4853 * In this case, soft_reconfigure is also scheduled by using
4854 * a thread but is planned after the
4855 * bgp_announce_route_timer_expired threads. It means that,
4856 * without cancelling the threads, the route announcement task
4857 * would run before the soft reconfiguration one. That would
4858 * useless and would block vtysh during several seconds. Route
4859 * announcements are rescheduled as soon as the soft_reconfigure
4860 * process finishes.
4861 */
4862 paf = peer_af_find(peer, afi, safi);
4863 if (paf)
4864 bgp_stop_announce_route_timer(paf);
4865 } else
9bcb3eef
DS
4866 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4867 dest = bgp_route_next(dest)) {
4868 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4869
b54892e0
DS
4870 if (table == NULL)
4871 continue;
8692c506 4872
9bcb3eef 4873 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4874 struct prefix_rd prd;
4875
4876 prd.family = AF_UNSPEC;
4877 prd.prefixlen = 64;
4878 memcpy(&prd.val, p->u.val, 8);
4879
4880 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4881 }
718e3744 4882}
6b0655a2 4883
228da428 4884
d62a17ae 4885struct bgp_clear_node_queue {
9bcb3eef 4886 struct bgp_dest *dest;
228da428
CC
4887};
4888
d62a17ae 4889static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4890{
d62a17ae 4891 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4892 struct bgp_dest *dest = cnq->dest;
d62a17ae 4893 struct peer *peer = wq->spec.data;
40381db7 4894 struct bgp_path_info *pi;
3103e8d2 4895 struct bgp *bgp;
9bcb3eef
DS
4896 afi_t afi = bgp_dest_table(dest)->afi;
4897 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4898
9bcb3eef 4899 assert(dest && peer);
3103e8d2 4900 bgp = peer->bgp;
d62a17ae 4901
4902 /* It is possible that we have multiple paths for a prefix from a peer
4903 * if that peer is using AddPath.
4904 */
9bcb3eef 4905 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4906 if (pi->peer != peer)
ea47320b
DL
4907 continue;
4908
4909 /* graceful restart STALE flag set. */
9af52ccf
DA
4910 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4911 && peer->nsf[afi][safi])
4912 || CHECK_FLAG(peer->af_sflags[afi][safi],
4913 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4914 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4915 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4916 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4917 else {
4918 /* If this is an EVPN route, process for
4919 * un-import. */
4920 if (safi == SAFI_EVPN)
9bcb3eef
DS
4921 bgp_evpn_unimport_route(
4922 bgp, afi, safi,
4923 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4924 /* Handle withdraw for VRF route-leaking and L3VPN */
4925 if (SAFI_UNICAST == safi
4926 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4927 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4928 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4929 bgp, pi);
960035b2 4930 }
3103e8d2 4931 if (SAFI_MPLS_VPN == safi &&
960035b2 4932 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4933 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4934 }
3103e8d2 4935
9bcb3eef 4936 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4937 }
ea47320b 4938 }
d62a17ae 4939 return WQ_SUCCESS;
200df115 4940}
4941
d62a17ae 4942static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4943{
d62a17ae 4944 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4945 struct bgp_dest *dest = cnq->dest;
4946 struct bgp_table *table = bgp_dest_table(dest);
228da428 4947
9bcb3eef 4948 bgp_dest_unlock_node(dest);
d62a17ae 4949 bgp_table_unlock(table);
4950 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4951}
4952
d62a17ae 4953static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4954{
d62a17ae 4955 struct peer *peer = wq->spec.data;
64e580a7 4956
d62a17ae 4957 /* Tickle FSM to start moving again */
4958 BGP_EVENT_ADD(peer, Clearing_Completed);
4959
4960 peer_unlock(peer); /* bgp_clear_route */
200df115 4961}
718e3744 4962
d62a17ae 4963static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4964{
d62a17ae 4965 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4966
4967 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4968#undef CLEAR_QUEUE_NAME_LEN
4969
0ce1ca80 4970 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4971 peer->clear_node_queue->spec.hold = 10;
4972 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4973 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4974 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4975 peer->clear_node_queue->spec.max_retries = 0;
4976
4977 /* we only 'lock' this peer reference when the queue is actually active
4978 */
4979 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4980}
4981
d62a17ae 4982static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4983 struct bgp_table *table)
65ca75e0 4984{
9bcb3eef 4985 struct bgp_dest *dest;
b6c386bb 4986 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4987
d62a17ae 4988 if (!table)
4989 table = peer->bgp->rib[afi][safi];
dc83d712 4990
d62a17ae 4991 /* If still no table => afi/safi isn't configured at all or smth. */
4992 if (!table)
4993 return;
dc83d712 4994
9bcb3eef 4995 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 4996 struct bgp_path_info *pi, *next;
d62a17ae 4997 struct bgp_adj_in *ain;
4998 struct bgp_adj_in *ain_next;
4999
5000 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5001 * queued for every clearing peer, regardless of whether it is
5002 * relevant to the peer at hand.
5003 *
5004 * Overview: There are 3 different indices which need to be
5005 * scrubbed, potentially, when a peer is removed:
5006 *
5007 * 1 peer's routes visible via the RIB (ie accepted routes)
5008 * 2 peer's routes visible by the (optional) peer's adj-in index
5009 * 3 other routes visible by the peer's adj-out index
5010 *
5011 * 3 there is no hurry in scrubbing, once the struct peer is
5012 * removed from bgp->peer, we could just GC such deleted peer's
5013 * adj-outs at our leisure.
5014 *
5015 * 1 and 2 must be 'scrubbed' in some way, at least made
5016 * invisible via RIB index before peer session is allowed to be
5017 * brought back up. So one needs to know when such a 'search' is
5018 * complete.
5019 *
5020 * Ideally:
5021 *
5022 * - there'd be a single global queue or a single RIB walker
5023 * - rather than tracking which route_nodes still need to be
5024 * examined on a peer basis, we'd track which peers still
5025 * aren't cleared
5026 *
5027 * Given that our per-peer prefix-counts now should be reliable,
5028 * this may actually be achievable. It doesn't seem to be a huge
5029 * problem at this time,
5030 *
5031 * It is possible that we have multiple paths for a prefix from
5032 * a peer
5033 * if that peer is using AddPath.
5034 */
9bcb3eef 5035 ain = dest->adj_in;
d62a17ae 5036 while (ain) {
5037 ain_next = ain->next;
5038
6a840fd9 5039 if (ain->peer == peer)
9bcb3eef 5040 bgp_adj_in_remove(dest, ain);
d62a17ae 5041
5042 ain = ain_next;
5043 }
5044
9bcb3eef 5045 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5046 next = pi->next;
5047 if (pi->peer != peer)
d62a17ae 5048 continue;
5049
5050 if (force)
9bcb3eef 5051 bgp_path_info_reap(dest, pi);
d62a17ae 5052 else {
5053 struct bgp_clear_node_queue *cnq;
5054
5055 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5056 bgp_table_lock(bgp_dest_table(dest));
5057 bgp_dest_lock_node(dest);
d62a17ae 5058 cnq = XCALLOC(
5059 MTYPE_BGP_CLEAR_NODE_QUEUE,
5060 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5061 cnq->dest = dest;
d62a17ae 5062 work_queue_add(peer->clear_node_queue, cnq);
5063 break;
5064 }
5065 }
5066 }
5067 return;
5068}
5069
5070void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5071{
9bcb3eef 5072 struct bgp_dest *dest;
d62a17ae 5073 struct bgp_table *table;
5074
5075 if (peer->clear_node_queue == NULL)
5076 bgp_clear_node_queue_init(peer);
5077
5078 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5079 * Idle until it receives a Clearing_Completed event. This protects
5080 * against peers which flap faster than we can we clear, which could
5081 * lead to:
5082 *
5083 * a) race with routes from the new session being installed before
5084 * clear_route_node visits the node (to delete the route of that
5085 * peer)
5086 * b) resource exhaustion, clear_route_node likely leads to an entry
5087 * on the process_main queue. Fast-flapping could cause that queue
5088 * to grow and grow.
5089 */
5090
5091 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5092 * the unlock will happen upon work-queue completion; other wise, the
5093 * unlock happens at the end of this function.
5094 */
5095 if (!peer->clear_node_queue->thread)
5096 peer_lock(peer);
5097
5098 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5099 bgp_clear_route_table(peer, afi, safi, NULL);
5100 else
9bcb3eef
DS
5101 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5102 dest = bgp_route_next(dest)) {
5103 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5104 if (!table)
5105 continue;
5106
5107 bgp_clear_route_table(peer, afi, safi, table);
5108 }
d62a17ae 5109
5110 /* unlock if no nodes got added to the clear-node-queue. */
5111 if (!peer->clear_node_queue->thread)
5112 peer_unlock(peer);
718e3744 5113}
d62a17ae 5114
5115void bgp_clear_route_all(struct peer *peer)
718e3744 5116{
d62a17ae 5117 afi_t afi;
5118 safi_t safi;
718e3744 5119
05c7a1cc
QY
5120 FOREACH_AFI_SAFI (afi, safi)
5121 bgp_clear_route(peer, afi, safi);
65efcfce 5122
49e5a4a0 5123#ifdef ENABLE_BGP_VNC
d62a17ae 5124 rfapiProcessPeerDown(peer);
65efcfce 5125#endif
718e3744 5126}
5127
d62a17ae 5128void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5129{
d62a17ae 5130 struct bgp_table *table;
9bcb3eef 5131 struct bgp_dest *dest;
d62a17ae 5132 struct bgp_adj_in *ain;
5133 struct bgp_adj_in *ain_next;
718e3744 5134
d62a17ae 5135 table = peer->bgp->rib[afi][safi];
718e3744 5136
d62a17ae 5137 /* It is possible that we have multiple paths for a prefix from a peer
5138 * if that peer is using AddPath.
5139 */
9bcb3eef
DS
5140 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5141 ain = dest->adj_in;
43143c8f 5142
d62a17ae 5143 while (ain) {
5144 ain_next = ain->next;
43143c8f 5145
6a840fd9 5146 if (ain->peer == peer)
9bcb3eef 5147 bgp_adj_in_remove(dest, ain);
43143c8f 5148
d62a17ae 5149 ain = ain_next;
5150 }
5151 }
718e3744 5152}
93406d87 5153
d62a17ae 5154void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5155{
9bcb3eef 5156 struct bgp_dest *dest;
40381db7 5157 struct bgp_path_info *pi;
d62a17ae 5158 struct bgp_table *table;
5159
9af52ccf 5160 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5161 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5162 dest = bgp_route_next(dest)) {
5163 struct bgp_dest *rm;
d62a17ae 5164
5165 /* look for neighbor in tables */
9bcb3eef 5166 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5167 if (!table)
ea47320b
DL
5168 continue;
5169
5170 for (rm = bgp_table_top(table); rm;
5171 rm = bgp_route_next(rm))
9bcb3eef 5172 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5173 pi = pi->next) {
40381db7 5174 if (pi->peer != peer)
ea47320b 5175 continue;
40381db7 5176 if (!CHECK_FLAG(pi->flags,
1defdda8 5177 BGP_PATH_STALE))
ea47320b
DL
5178 break;
5179
40381db7 5180 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5181 break;
5182 }
d62a17ae 5183 }
5184 } else {
9bcb3eef
DS
5185 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5186 dest = bgp_route_next(dest))
5187 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5188 pi = pi->next) {
40381db7 5189 if (pi->peer != peer)
ea47320b 5190 continue;
40381db7 5191 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5192 break;
9bcb3eef 5193 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5194 break;
5195 }
d62a17ae 5196 }
93406d87 5197}
6b0655a2 5198
9af52ccf
DA
5199void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5200{
5201 struct bgp_dest *dest, *ndest;
5202 struct bgp_path_info *pi;
5203 struct bgp_table *table;
5204
5205 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5206 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5207 dest = bgp_route_next(dest)) {
5208 table = bgp_dest_get_bgp_table_info(dest);
5209 if (!table)
5210 continue;
5211
5212 for (ndest = bgp_table_top(table); ndest;
5213 ndest = bgp_route_next(ndest)) {
5214 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5215 pi = pi->next) {
5216 if (pi->peer != peer)
5217 continue;
5218
5219 if ((CHECK_FLAG(
5220 peer->af_sflags[afi][safi],
5221 PEER_STATUS_ENHANCED_REFRESH))
5222 && !CHECK_FLAG(pi->flags,
5223 BGP_PATH_STALE)
5224 && !CHECK_FLAG(
5225 pi->flags,
5226 BGP_PATH_UNUSEABLE)) {
5227 if (bgp_debug_neighbor_events(
5228 peer))
5229 zlog_debug(
5230 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5231 peer->host,
5232 afi2str(afi),
5233 safi2str(safi),
5234 bgp_dest_get_prefix(
5235 ndest));
5236
5237 bgp_path_info_set_flag(
5238 ndest, pi,
5239 BGP_PATH_STALE);
5240 }
5241 }
5242 }
5243 }
5244 } else {
5245 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5246 dest = bgp_route_next(dest)) {
5247 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5248 pi = pi->next) {
5249 if (pi->peer != peer)
5250 continue;
5251
5252 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5253 PEER_STATUS_ENHANCED_REFRESH))
5254 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5255 && !CHECK_FLAG(pi->flags,
5256 BGP_PATH_UNUSEABLE)) {
5257 if (bgp_debug_neighbor_events(peer))
5258 zlog_debug(
5259 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5260 peer->host,
5261 afi2str(afi),
5262 safi2str(safi),
5263 bgp_dest_get_prefix(
5264 dest));
5265
5266 bgp_path_info_set_flag(dest, pi,
5267 BGP_PATH_STALE);
5268 }
5269 }
5270 }
5271 }
5272}
5273
3dc339cd 5274bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5275{
e0df4c04 5276 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5277 return true;
e0df4c04 5278
9dac9fc8
DA
5279 if (peer->sort == BGP_PEER_EBGP
5280 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5281 || FILTER_LIST_OUT_NAME(filter)
5282 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5283 return true;
5284 return false;
9dac9fc8
DA
5285}
5286
3dc339cd 5287bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5288{
e0df4c04 5289 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5290 return true;
e0df4c04 5291
9dac9fc8
DA
5292 if (peer->sort == BGP_PEER_EBGP
5293 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5294 || FILTER_LIST_IN_NAME(filter)
5295 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5296 return true;
5297 return false;
9dac9fc8
DA
5298}
5299
568e10ca 5300static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5301 safi_t safi)
bb86c601 5302{
9bcb3eef 5303 struct bgp_dest *dest;
40381db7 5304 struct bgp_path_info *pi;
4b7e6066 5305 struct bgp_path_info *next;
bb86c601 5306
9bcb3eef
DS
5307 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5308 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5309 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5310
40381db7 5311 next = pi->next;
1b7bb747
CS
5312
5313 /* Unimport EVPN routes from VRFs */
5314 if (safi == SAFI_EVPN)
5315 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5316 SAFI_EVPN, p, pi);
1b7bb747 5317
40381db7
DS
5318 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5319 && pi->type == ZEBRA_ROUTE_BGP
5320 && (pi->sub_type == BGP_ROUTE_NORMAL
5321 || pi->sub_type == BGP_ROUTE_AGGREGATE
5322 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5323
d62a17ae 5324 if (bgp_fibupd_safi(safi))
b54892e0 5325 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5326 }
9514b37d 5327
9bcb3eef 5328 bgp_path_info_reap(dest, pi);
d62a17ae 5329 }
bb86c601
LB
5330}
5331
718e3744 5332/* Delete all kernel routes. */
d62a17ae 5333void bgp_cleanup_routes(struct bgp *bgp)
5334{
5335 afi_t afi;
9bcb3eef 5336 struct bgp_dest *dest;
67009e22 5337 struct bgp_table *table;
d62a17ae 5338
5339 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5340 if (afi == AFI_L2VPN)
5341 continue;
568e10ca 5342 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5343 SAFI_UNICAST);
d62a17ae 5344 /*
5345 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5346 */
5347 if (afi != AFI_L2VPN) {
5348 safi_t safi;
5349 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5350 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5351 dest = bgp_route_next(dest)) {
5352 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5353 if (table != NULL) {
5354 bgp_cleanup_table(bgp, table, safi);
5355 bgp_table_finish(&table);
9bcb3eef
DS
5356 bgp_dest_set_bgp_table_info(dest, NULL);
5357 bgp_dest_unlock_node(dest);
d62a17ae 5358 }
5359 }
5360 safi = SAFI_ENCAP;
9bcb3eef
DS
5361 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5362 dest = bgp_route_next(dest)) {
5363 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5364 if (table != NULL) {
5365 bgp_cleanup_table(bgp, table, safi);
5366 bgp_table_finish(&table);
9bcb3eef
DS
5367 bgp_dest_set_bgp_table_info(dest, NULL);
5368 bgp_dest_unlock_node(dest);
d62a17ae 5369 }
5370 }
5371 }
5372 }
9bcb3eef
DS
5373 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5374 dest = bgp_route_next(dest)) {
5375 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5376 if (table != NULL) {
5377 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5378 bgp_table_finish(&table);
9bcb3eef
DS
5379 bgp_dest_set_bgp_table_info(dest, NULL);
5380 bgp_dest_unlock_node(dest);
d62a17ae 5381 }
bb86c601 5382 }
718e3744 5383}
5384
d62a17ae 5385void bgp_reset(void)
718e3744 5386{
d62a17ae 5387 vty_reset();
5388 bgp_zclient_reset();
5389 access_list_reset();
5390 prefix_list_reset();
718e3744 5391}
6b0655a2 5392
d62a17ae 5393static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5394{
d62a17ae 5395 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5396 && CHECK_FLAG(peer->af_cap[afi][safi],
5397 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5398}
5399
718e3744 5400/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5401 value. */
d62a17ae 5402int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5403 struct bgp_nlri *packet)
5404{
d7c0a89a
QY
5405 uint8_t *pnt;
5406 uint8_t *lim;
d62a17ae 5407 struct prefix p;
5408 int psize;
5409 int ret;
5410 afi_t afi;
5411 safi_t safi;
5412 int addpath_encoded;
d7c0a89a 5413 uint32_t addpath_id;
d62a17ae 5414
d62a17ae 5415 pnt = packet->nlri;
5416 lim = pnt + packet->length;
5417 afi = packet->afi;
5418 safi = packet->safi;
5419 addpath_id = 0;
5420 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5421
5422 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5423 syntactic validity. If the field is syntactically incorrect,
5424 then the Error Subcode is set to Invalid Network Field. */
5425 for (; pnt < lim; pnt += psize) {
5426 /* Clear prefix structure. */
5427 memset(&p, 0, sizeof(struct prefix));
5428
5429 if (addpath_encoded) {
5430
5431 /* When packet overflow occurs return immediately. */
761ed665 5432 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5433 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5434
a3a850a1 5435 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5436 addpath_id = ntohl(addpath_id);
d62a17ae 5437 pnt += BGP_ADDPATH_ID_LEN;
5438 }
718e3744 5439
d62a17ae 5440 /* Fetch prefix length. */
5441 p.prefixlen = *pnt++;
5442 /* afi/safi validity already verified by caller,
5443 * bgp_update_receive */
5444 p.family = afi2family(afi);
5445
5446 /* Prefix length check. */
5447 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5448 flog_err(
e50f7cfd 5449 EC_BGP_UPDATE_RCV,
14454c9f 5450 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5451 peer->host, p.prefixlen, packet->afi);
513386b5 5452 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5453 }
6b0655a2 5454
d62a17ae 5455 /* Packet size overflow check. */
5456 psize = PSIZE(p.prefixlen);
5457
5458 /* When packet overflow occur return immediately. */
5459 if (pnt + psize > lim) {
af4c2728 5460 flog_err(
e50f7cfd 5461 EC_BGP_UPDATE_RCV,
d62a17ae 5462 "%s [Error] Update packet error (prefix length %d overflows packet)",
5463 peer->host, p.prefixlen);
513386b5 5464 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5465 }
5466
5467 /* Defensive coding, double-check the psize fits in a struct
5468 * prefix */
5469 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5470 flog_err(
e50f7cfd 5471 EC_BGP_UPDATE_RCV,
d62a17ae 5472 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5473 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5474 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5475 }
5476
5477 /* Fetch prefix from NLRI packet. */
a85297a7 5478 memcpy(p.u.val, pnt, psize);
d62a17ae 5479
5480 /* Check address. */
5481 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5482 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5483 /* From RFC4271 Section 6.3:
5484 *
5485 * If a prefix in the NLRI field is semantically
5486 * incorrect
5487 * (e.g., an unexpected multicast IP address),
5488 * an error SHOULD
5489 * be logged locally, and the prefix SHOULD be
5490 * ignored.
a4d82a8a 5491 */
af4c2728 5492 flog_err(
e50f7cfd 5493 EC_BGP_UPDATE_RCV,
23d0a753
DA
5494 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5495 peer->host, &p.u.prefix4);
d62a17ae 5496 continue;
5497 }
5498 }
5499
5500 /* Check address. */
5501 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5502 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5503 flog_err(
e50f7cfd 5504 EC_BGP_UPDATE_RCV,
c0d72166
DS
5505 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5506 peer->host, &p.u.prefix6);
d62a17ae 5507
5508 continue;
5509 }
5510 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5511 flog_err(
e50f7cfd 5512 EC_BGP_UPDATE_RCV,
c0d72166
DS
5513 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5514 peer->host, &p.u.prefix6);
d62a17ae 5515
5516 continue;
5517 }
5518 }
5519
5520 /* Normal process. */
5521 if (attr)
5522 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5523 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5524 NULL, NULL, 0, 0, NULL);
d62a17ae 5525 else
5526 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5527 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5528 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5529 NULL);
d62a17ae 5530
513386b5
DA
5531 /* Do not send BGP notification twice when maximum-prefix count
5532 * overflow. */
5533 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5534 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5535
5536 /* Address family configuration mismatch. */
d62a17ae 5537 if (ret < 0)
513386b5 5538 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5539 }
5540
5541 /* Packet length consistency check. */
5542 if (pnt != lim) {
af4c2728 5543 flog_err(
e50f7cfd 5544 EC_BGP_UPDATE_RCV,
d62a17ae 5545 "%s [Error] Update packet error (prefix length mismatch with total length)",
5546 peer->host);
513386b5 5547 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5548 }
6b0655a2 5549
513386b5 5550 return BGP_NLRI_PARSE_OK;
718e3744 5551}
5552
d62a17ae 5553static struct bgp_static *bgp_static_new(void)
718e3744 5554{
d62a17ae 5555 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5556}
5557
d62a17ae 5558static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5559{
0a22ddfb 5560 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5561 route_map_counter_decrement(bgp_static->rmap.map);
5562
0a22ddfb 5563 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5564 XFREE(MTYPE_BGP_STATIC, bgp_static);
5565}
5566
5f040085 5567void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5568 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5569{
9bcb3eef 5570 struct bgp_dest *dest;
40381db7 5571 struct bgp_path_info *pi;
4b7e6066 5572 struct bgp_path_info *new;
40381db7 5573 struct bgp_path_info rmap_path;
d62a17ae 5574 struct attr attr;
5575 struct attr *attr_new;
b68885f9 5576 route_map_result_t ret;
49e5a4a0 5577#ifdef ENABLE_BGP_VNC
d62a17ae 5578 int vnc_implicit_withdraw = 0;
65efcfce 5579#endif
fee0f4c6 5580
d62a17ae 5581 assert(bgp_static);
dd8103a9 5582
9bcb3eef 5583 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5584
d62a17ae 5585 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5586
d62a17ae 5587 attr.nexthop = bgp_static->igpnexthop;
5588 attr.med = bgp_static->igpmetric;
5589 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5590
d62a17ae 5591 if (bgp_static->atomic)
5592 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5593
d62a17ae 5594 /* Store label index, if required. */
5595 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5596 attr.label_index = bgp_static->label_index;
5597 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5598 }
718e3744 5599
d62a17ae 5600 /* Apply route-map. */
5601 if (bgp_static->rmap.name) {
5602 struct attr attr_tmp = attr;
80ced710 5603
40381db7
DS
5604 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5605 rmap_path.peer = bgp->peer_self;
5606 rmap_path.attr = &attr_tmp;
fee0f4c6 5607
d62a17ae 5608 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5609
1782514f 5610 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5611
d62a17ae 5612 bgp->peer_self->rmap_type = 0;
718e3744 5613
d62a17ae 5614 if (ret == RMAP_DENYMATCH) {
5615 /* Free uninterned attribute. */
5616 bgp_attr_flush(&attr_tmp);
718e3744 5617
d62a17ae 5618 /* Unintern original. */
5619 aspath_unintern(&attr.aspath);
5620 bgp_static_withdraw(bgp, p, afi, safi);
5621 return;
5622 }
7f323236 5623
637e5ba4 5624 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5625 bgp_attr_add_gshut_community(&attr_tmp);
5626
d62a17ae 5627 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5628 } else {
5629
637e5ba4 5630 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5631 bgp_attr_add_gshut_community(&attr);
5632
d62a17ae 5633 attr_new = bgp_attr_intern(&attr);
7f323236 5634 }
718e3744 5635
9bcb3eef 5636 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5637 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5638 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5639 break;
5640
40381db7
DS
5641 if (pi) {
5642 if (attrhash_cmp(pi->attr, attr_new)
5643 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5644 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5645 bgp_dest_unlock_node(dest);
d62a17ae 5646 bgp_attr_unintern(&attr_new);
5647 aspath_unintern(&attr.aspath);
5648 return;
5649 } else {
5650 /* The attribute is changed. */
9bcb3eef 5651 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5652
5653 /* Rewrite BGP route information. */
40381db7 5654 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5655 bgp_path_info_restore(dest, pi);
d62a17ae 5656 else
40381db7 5657 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5658#ifdef ENABLE_BGP_VNC
d62a17ae 5659 if ((afi == AFI_IP || afi == AFI_IP6)
5660 && (safi == SAFI_UNICAST)) {
40381db7 5661 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5662 /*
5663 * Implicit withdraw case.
40381db7 5664 * We have to do this before pi is
d62a17ae 5665 * changed
5666 */
5667 ++vnc_implicit_withdraw;
40381db7 5668 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5669 vnc_import_bgp_exterior_del_route(
40381db7 5670 bgp, p, pi);
d62a17ae 5671 }
5672 }
65efcfce 5673#endif
40381db7
DS
5674 bgp_attr_unintern(&pi->attr);
5675 pi->attr = attr_new;
5676 pi->uptime = bgp_clock();
49e5a4a0 5677#ifdef ENABLE_BGP_VNC
d62a17ae 5678 if ((afi == AFI_IP || afi == AFI_IP6)
5679 && (safi == SAFI_UNICAST)) {
5680 if (vnc_implicit_withdraw) {
40381db7 5681 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5682 vnc_import_bgp_exterior_add_route(
40381db7 5683 bgp, p, pi);
d62a17ae 5684 }
5685 }
65efcfce 5686#endif
718e3744 5687
d62a17ae 5688 /* Nexthop reachability check. */
892fedb6 5689 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5690 && (safi == SAFI_UNICAST
5691 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5692
5693 struct bgp *bgp_nexthop = bgp;
5694
40381db7
DS
5695 if (pi->extra && pi->extra->bgp_orig)
5696 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5697
5698 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5699 afi, safi, pi, NULL,
654a5978 5700 0, p))
9bcb3eef 5701 bgp_path_info_set_flag(dest, pi,
18ee8310 5702 BGP_PATH_VALID);
d62a17ae 5703 else {
5704 if (BGP_DEBUG(nht, NHT)) {
5705 char buf1[INET6_ADDRSTRLEN];
5706 inet_ntop(p->family,
5707 &p->u.prefix, buf1,
5708 INET6_ADDRSTRLEN);
5709 zlog_debug(
5710 "%s(%s): Route not in table, not advertising",
15569c58 5711 __func__, buf1);
d62a17ae 5712 }
18ee8310 5713 bgp_path_info_unset_flag(
9bcb3eef 5714 dest, pi, BGP_PATH_VALID);
d62a17ae 5715 }
5716 } else {
5717 /* Delete the NHT structure if any, if we're
5718 * toggling between
5719 * enabling/disabling import check. We
5720 * deregister the route
5721 * from NHT to avoid overloading NHT and the
5722 * process interaction
5723 */
40381db7 5724 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5725 bgp_path_info_set_flag(dest, pi,
5726 BGP_PATH_VALID);
d62a17ae 5727 }
5728 /* Process change. */
40381db7 5729 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5730 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5731
5732 if (SAFI_UNICAST == safi
5733 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5734 || bgp->inst_type
5735 == BGP_INSTANCE_TYPE_DEFAULT)) {
5736 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5737 pi);
ddb5b488
PZ
5738 }
5739
9bcb3eef 5740 bgp_dest_unlock_node(dest);
d62a17ae 5741 aspath_unintern(&attr.aspath);
5742 return;
5743 }
718e3744 5744 }
718e3744 5745
d62a17ae 5746 /* Make new BGP info. */
5747 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5748 attr_new, dest);
d62a17ae 5749 /* Nexthop reachability check. */
892fedb6 5750 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5751 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5752 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5753 p))
9bcb3eef 5754 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5755 else {
5756 if (BGP_DEBUG(nht, NHT)) {
5757 char buf1[INET6_ADDRSTRLEN];
5758 inet_ntop(p->family, &p->u.prefix, buf1,
5759 INET6_ADDRSTRLEN);
5760 zlog_debug(
5761 "%s(%s): Route not in table, not advertising",
15569c58 5762 __func__, buf1);
d62a17ae 5763 }
9bcb3eef 5764 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5765 }
5766 } else {
5767 /* Delete the NHT structure if any, if we're toggling between
5768 * enabling/disabling import check. We deregister the route
5769 * from NHT to avoid overloading NHT and the process interaction
5770 */
5771 bgp_unlink_nexthop(new);
5772
9bcb3eef 5773 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5774 }
078430f6 5775
d62a17ae 5776 /* Aggregate address increment. */
5777 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5778
d62a17ae 5779 /* Register new BGP information. */
9bcb3eef 5780 bgp_path_info_add(dest, new);
718e3744 5781
d62a17ae 5782 /* route_node_get lock */
9bcb3eef 5783 bgp_dest_unlock_node(dest);
d62a17ae 5784
5785 /* Process change. */
9bcb3eef 5786 bgp_process(bgp, dest, afi, safi);
d62a17ae 5787
ddb5b488
PZ
5788 if (SAFI_UNICAST == safi
5789 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5790 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5791 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5792 }
5793
d62a17ae 5794 /* Unintern original. */
5795 aspath_unintern(&attr.aspath);
718e3744 5796}
5797
5f040085 5798void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5799 safi_t safi)
718e3744 5800{
9bcb3eef 5801 struct bgp_dest *dest;
40381db7 5802 struct bgp_path_info *pi;
718e3744 5803
9bcb3eef 5804 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5805
d62a17ae 5806 /* Check selected route and self inserted route. */
9bcb3eef 5807 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5808 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5809 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5810 break;
5811
5812 /* Withdraw static BGP route from routing table. */
40381db7 5813 if (pi) {
ddb5b488
PZ
5814 if (SAFI_UNICAST == safi
5815 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5816 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5817 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5818 }
40381db7
DS
5819 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5820 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5821 bgp_path_info_delete(dest, pi);
5822 bgp_process(bgp, dest, afi, safi);
d62a17ae 5823 }
718e3744 5824
d62a17ae 5825 /* Unlock bgp_node_lookup. */
9bcb3eef 5826 bgp_dest_unlock_node(dest);
718e3744 5827}
5828
137446f9
LB
5829/*
5830 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5831 */
5f040085 5832static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5833 afi_t afi, safi_t safi,
5834 struct prefix_rd *prd)
718e3744 5835{
9bcb3eef 5836 struct bgp_dest *dest;
40381db7 5837 struct bgp_path_info *pi;
718e3744 5838
9bcb3eef 5839 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5840
d62a17ae 5841 /* Check selected route and self inserted route. */
9bcb3eef 5842 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5843 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5844 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5845 break;
718e3744 5846
d62a17ae 5847 /* Withdraw static BGP route from routing table. */
40381db7 5848 if (pi) {
49e5a4a0 5849#ifdef ENABLE_BGP_VNC
d62a17ae 5850 rfapiProcessWithdraw(
40381db7 5851 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5852 1); /* Kill, since it is an administrative change */
65efcfce 5853#endif
ddb5b488
PZ
5854 if (SAFI_MPLS_VPN == safi
5855 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5856 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5857 }
40381db7 5858 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5859 bgp_path_info_delete(dest, pi);
5860 bgp_process(bgp, dest, afi, safi);
d62a17ae 5861 }
718e3744 5862
d62a17ae 5863 /* Unlock bgp_node_lookup. */
9bcb3eef 5864 bgp_dest_unlock_node(dest);
718e3744 5865}
5866
5f040085 5867static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5868 struct bgp_static *bgp_static, afi_t afi,
5869 safi_t safi)
137446f9 5870{
9bcb3eef 5871 struct bgp_dest *dest;
4b7e6066 5872 struct bgp_path_info *new;
d62a17ae 5873 struct attr *attr_new;
5874 struct attr attr = {0};
40381db7 5875 struct bgp_path_info *pi;
49e5a4a0 5876#ifdef ENABLE_BGP_VNC
d62a17ae 5877 mpls_label_t label = 0;
65efcfce 5878#endif
d7c0a89a 5879 uint32_t num_labels = 0;
d62a17ae 5880 union gw_addr add;
137446f9 5881
d62a17ae 5882 assert(bgp_static);
137446f9 5883
b57ba6d2
MK
5884 if (bgp_static->label != MPLS_INVALID_LABEL)
5885 num_labels = 1;
9bcb3eef
DS
5886 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5887 &bgp_static->prd);
137446f9 5888
d62a17ae 5889 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5890
d62a17ae 5891 attr.nexthop = bgp_static->igpnexthop;
5892 attr.med = bgp_static->igpmetric;
5893 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5894
d62a17ae 5895 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5896 || (safi == SAFI_ENCAP)) {
5897 if (afi == AFI_IP) {
5898 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5899 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5900 }
5901 }
5902 if (afi == AFI_L2VPN) {
5903 if (bgp_static->gatewayIp.family == AF_INET)
5904 add.ipv4.s_addr =
5905 bgp_static->gatewayIp.u.prefix4.s_addr;
5906 else if (bgp_static->gatewayIp.family == AF_INET6)
5907 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5908 sizeof(struct in6_addr));
0a50c248 5909 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5910 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5911 struct bgp_encap_type_vxlan bet;
5912 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5913 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5914 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5915 }
5916 if (bgp_static->router_mac) {
5917 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5918 }
5919 }
5920 /* Apply route-map. */
5921 if (bgp_static->rmap.name) {
5922 struct attr attr_tmp = attr;
40381db7 5923 struct bgp_path_info rmap_path;
b68885f9 5924 route_map_result_t ret;
137446f9 5925
40381db7
DS
5926 rmap_path.peer = bgp->peer_self;
5927 rmap_path.attr = &attr_tmp;
137446f9 5928
d62a17ae 5929 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5930
1782514f 5931 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5932
d62a17ae 5933 bgp->peer_self->rmap_type = 0;
137446f9 5934
d62a17ae 5935 if (ret == RMAP_DENYMATCH) {
5936 /* Free uninterned attribute. */
5937 bgp_attr_flush(&attr_tmp);
137446f9 5938
d62a17ae 5939 /* Unintern original. */
5940 aspath_unintern(&attr.aspath);
5941 bgp_static_withdraw_safi(bgp, p, afi, safi,
5942 &bgp_static->prd);
5943 return;
5944 }
137446f9 5945
d62a17ae 5946 attr_new = bgp_attr_intern(&attr_tmp);
5947 } else {
5948 attr_new = bgp_attr_intern(&attr);
5949 }
137446f9 5950
9bcb3eef 5951 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5952 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5953 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5954 break;
5955
40381db7 5956 if (pi) {
d62a17ae 5957 memset(&add, 0, sizeof(union gw_addr));
40381db7 5958 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5959 && overlay_index_equal(afi, pi, &add)
40381db7 5960 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5961 bgp_dest_unlock_node(dest);
d62a17ae 5962 bgp_attr_unintern(&attr_new);
5963 aspath_unintern(&attr.aspath);
5964 return;
5965 } else {
5966 /* The attribute is changed. */
9bcb3eef 5967 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5968
5969 /* Rewrite BGP route information. */
40381db7 5970 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5971 bgp_path_info_restore(dest, pi);
d62a17ae 5972 else
40381db7
DS
5973 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5974 bgp_attr_unintern(&pi->attr);
5975 pi->attr = attr_new;
5976 pi->uptime = bgp_clock();
49e5a4a0 5977#ifdef ENABLE_BGP_VNC
40381db7
DS
5978 if (pi->extra)
5979 label = decode_label(&pi->extra->label[0]);
65efcfce 5980#endif
137446f9 5981
d62a17ae 5982 /* Process change. */
40381db7 5983 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5984 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5985
5986 if (SAFI_MPLS_VPN == safi
5987 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5988 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 5989 }
49e5a4a0 5990#ifdef ENABLE_BGP_VNC
40381db7
DS
5991 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
5992 pi->attr, afi, safi, pi->type,
5993 pi->sub_type, &label);
65efcfce 5994#endif
9bcb3eef 5995 bgp_dest_unlock_node(dest);
d62a17ae 5996 aspath_unintern(&attr.aspath);
5997 return;
5998 }
5999 }
137446f9
LB
6000
6001
d62a17ae 6002 /* Make new BGP info. */
6003 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6004 attr_new, dest);
1defdda8 6005 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 6006 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
6007 if (num_labels) {
6008 new->extra->label[0] = bgp_static->label;
6009 new->extra->num_labels = num_labels;
6010 }
49e5a4a0 6011#ifdef ENABLE_BGP_VNC
d62a17ae 6012 label = decode_label(&bgp_static->label);
65efcfce 6013#endif
137446f9 6014
d62a17ae 6015 /* Aggregate address increment. */
6016 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6017
d62a17ae 6018 /* Register new BGP information. */
9bcb3eef 6019 bgp_path_info_add(dest, new);
d62a17ae 6020 /* route_node_get lock */
9bcb3eef 6021 bgp_dest_unlock_node(dest);
137446f9 6022
d62a17ae 6023 /* Process change. */
9bcb3eef 6024 bgp_process(bgp, dest, afi, safi);
137446f9 6025
ddb5b488
PZ
6026 if (SAFI_MPLS_VPN == safi
6027 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6028 vpn_leak_to_vrf_update(bgp, new);
6029 }
49e5a4a0 6030#ifdef ENABLE_BGP_VNC
d62a17ae 6031 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6032 safi, new->type, new->sub_type, &label);
65efcfce
LB
6033#endif
6034
d62a17ae 6035 /* Unintern original. */
6036 aspath_unintern(&attr.aspath);
137446f9
LB
6037}
6038
718e3744 6039/* Configure static BGP network. When user don't run zebra, static
6040 route should be installed as valid. */
37a87b8f
CS
6041int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
6042 afi_t afi, safi_t safi, const char *rmap, int backdoor,
6043 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 6044{
d62a17ae 6045 struct prefix p;
6046 struct bgp_static *bgp_static;
9bcb3eef 6047 struct bgp_dest *dest;
d7c0a89a 6048 uint8_t need_update = 0;
d62a17ae 6049
37a87b8f 6050 prefix_copy(&p, pfx);
d62a17ae 6051 apply_mask(&p);
718e3744 6052
e2a86ad9 6053 if (negate) {
718e3744 6054
e2a86ad9 6055 /* Set BGP static route configuration. */
9bcb3eef 6056 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6057
9bcb3eef 6058 if (!dest) {
37a87b8f
CS
6059 snprintf(errmsg, errmsg_len,
6060 "Can't find static route specified\n");
6061 return -1;
d62a17ae 6062 }
6063
9bcb3eef 6064 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6065
e2a86ad9
DS
6066 if ((label_index != BGP_INVALID_LABEL_INDEX)
6067 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
6068 snprintf(errmsg, errmsg_len,
6069 "label-index doesn't match static route\n");
70d9b134 6070 bgp_dest_unlock_node(dest);
37a87b8f 6071 return -1;
d62a17ae 6072 }
d62a17ae 6073
e2a86ad9
DS
6074 if ((rmap && bgp_static->rmap.name)
6075 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
6076 snprintf(errmsg, errmsg_len,
6077 "route-map name doesn't match static route\n");
70d9b134 6078 bgp_dest_unlock_node(dest);
37a87b8f 6079 return -1;
d62a17ae 6080 }
718e3744 6081
e2a86ad9
DS
6082 /* Update BGP RIB. */
6083 if (!bgp_static->backdoor)
6084 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6085
e2a86ad9
DS
6086 /* Clear configuration. */
6087 bgp_static_free(bgp_static);
9bcb3eef
DS
6088 bgp_dest_set_bgp_static_info(dest, NULL);
6089 bgp_dest_unlock_node(dest);
6090 bgp_dest_unlock_node(dest);
e2a86ad9 6091 } else {
718e3744 6092
e2a86ad9 6093 /* Set BGP static route configuration. */
9bcb3eef
DS
6094 dest = bgp_node_get(bgp->route[afi][safi], &p);
6095 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6096 if (bgp_static) {
e2a86ad9 6097 /* Configuration change. */
e2a86ad9
DS
6098 /* Label index cannot be changed. */
6099 if (bgp_static->label_index != label_index) {
37a87b8f
CS
6100 snprintf(errmsg, errmsg_len,
6101 "cannot change label-index\n");
6102 return -1;
e2a86ad9 6103 }
d62a17ae 6104
e2a86ad9 6105 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6106 if (bgp_static->valid
6107 && bgp_static->backdoor != backdoor)
e2a86ad9 6108 need_update = 1;
718e3744 6109
e2a86ad9 6110 bgp_static->backdoor = backdoor;
718e3744 6111
e2a86ad9 6112 if (rmap) {
0a22ddfb
QY
6113 XFREE(MTYPE_ROUTE_MAP_NAME,
6114 bgp_static->rmap.name);
b4897fa5 6115 route_map_counter_decrement(
6116 bgp_static->rmap.map);
e2a86ad9
DS
6117 bgp_static->rmap.name =
6118 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6119 bgp_static->rmap.map =
6120 route_map_lookup_by_name(rmap);
b4897fa5 6121 route_map_counter_increment(
6122 bgp_static->rmap.map);
e2a86ad9 6123 } else {
0a22ddfb
QY
6124 XFREE(MTYPE_ROUTE_MAP_NAME,
6125 bgp_static->rmap.name);
b4897fa5 6126 route_map_counter_decrement(
6127 bgp_static->rmap.map);
e2a86ad9
DS
6128 bgp_static->rmap.map = NULL;
6129 bgp_static->valid = 0;
6130 }
9bcb3eef 6131 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6132 } else {
6133 /* New configuration. */
6134 bgp_static = bgp_static_new();
6135 bgp_static->backdoor = backdoor;
6136 bgp_static->valid = 0;
6137 bgp_static->igpmetric = 0;
975a328e 6138 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6139 bgp_static->label_index = label_index;
718e3744 6140
e2a86ad9 6141 if (rmap) {
0a22ddfb
QY
6142 XFREE(MTYPE_ROUTE_MAP_NAME,
6143 bgp_static->rmap.name);
b4897fa5 6144 route_map_counter_decrement(
6145 bgp_static->rmap.map);
e2a86ad9
DS
6146 bgp_static->rmap.name =
6147 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6148 bgp_static->rmap.map =
6149 route_map_lookup_by_name(rmap);
b4897fa5 6150 route_map_counter_increment(
6151 bgp_static->rmap.map);
e2a86ad9 6152 }
9bcb3eef 6153 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6154 }
d62a17ae 6155
e2a86ad9
DS
6156 bgp_static->valid = 1;
6157 if (need_update)
6158 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6159
e2a86ad9
DS
6160 if (!bgp_static->backdoor)
6161 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6162 }
d62a17ae 6163
37a87b8f 6164 return 0;
d62a17ae 6165}
6166
6167void bgp_static_add(struct bgp *bgp)
6168{
6169 afi_t afi;
6170 safi_t safi;
9bcb3eef
DS
6171 struct bgp_dest *dest;
6172 struct bgp_dest *rm;
d62a17ae 6173 struct bgp_table *table;
6174 struct bgp_static *bgp_static;
6175
47fc6261 6176 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6177 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6178 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6179 dest = bgp_route_next(dest)) {
6180 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6181 continue;
ea47320b 6182
05c7a1cc
QY
6183 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6184 || (safi == SAFI_EVPN)) {
9bcb3eef 6185 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6186
6187 for (rm = bgp_table_top(table); rm;
6188 rm = bgp_route_next(rm)) {
a78beeb5 6189 bgp_static =
9bcb3eef 6190 bgp_dest_get_bgp_static_info(
5a8ba9fc 6191 rm);
9bcb3eef
DS
6192 bgp_static_update_safi(
6193 bgp, bgp_dest_get_prefix(rm),
6194 bgp_static, afi, safi);
d62a17ae 6195 }
05c7a1cc 6196 } else {
5a8ba9fc 6197 bgp_static_update(
9bcb3eef
DS
6198 bgp, bgp_dest_get_prefix(dest),
6199 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6200 safi);
ea47320b 6201 }
05c7a1cc 6202 }
47fc6261 6203 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6204}
6205
718e3744 6206/* Called from bgp_delete(). Delete all static routes from the BGP
6207 instance. */
d62a17ae 6208void bgp_static_delete(struct bgp *bgp)
6209{
6210 afi_t afi;
6211 safi_t safi;
9bcb3eef
DS
6212 struct bgp_dest *dest;
6213 struct bgp_dest *rm;
d62a17ae 6214 struct bgp_table *table;
6215 struct bgp_static *bgp_static;
6216
05c7a1cc 6217 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6218 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6219 dest = bgp_route_next(dest)) {
6220 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6221 continue;
ea47320b 6222
05c7a1cc
QY
6223 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6224 || (safi == SAFI_EVPN)) {
9bcb3eef 6225 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6226
6227 for (rm = bgp_table_top(table); rm;
6228 rm = bgp_route_next(rm)) {
a78beeb5 6229 bgp_static =
9bcb3eef 6230 bgp_dest_get_bgp_static_info(
5a8ba9fc 6231 rm);
c7d14ba6
PG
6232 if (!bgp_static)
6233 continue;
6234
05c7a1cc 6235 bgp_static_withdraw_safi(
9bcb3eef 6236 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6237 AFI_IP, safi,
6238 (struct prefix_rd *)
9bcb3eef
DS
6239 bgp_dest_get_prefix(
6240 dest));
ea47320b 6241 bgp_static_free(bgp_static);
811c6797 6242 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6243 NULL);
811c6797 6244 bgp_dest_unlock_node(rm);
d62a17ae 6245 }
05c7a1cc 6246 } else {
9bcb3eef 6247 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6248 bgp_static_withdraw(bgp,
9bcb3eef 6249 bgp_dest_get_prefix(dest),
b54892e0 6250 afi, safi);
05c7a1cc 6251 bgp_static_free(bgp_static);
9bcb3eef
DS
6252 bgp_dest_set_bgp_static_info(dest, NULL);
6253 bgp_dest_unlock_node(dest);
ea47320b 6254 }
05c7a1cc 6255 }
d62a17ae 6256}
6257
6258void bgp_static_redo_import_check(struct bgp *bgp)
6259{
6260 afi_t afi;
6261 safi_t safi;
9bcb3eef
DS
6262 struct bgp_dest *dest;
6263 struct bgp_dest *rm;
d62a17ae 6264 struct bgp_table *table;
6265 struct bgp_static *bgp_static;
6266
6267 /* Use this flag to force reprocessing of the route */
892fedb6 6268 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6269 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6270 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6271 dest = bgp_route_next(dest)) {
6272 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6273 continue;
ea47320b 6274
05c7a1cc
QY
6275 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6276 || (safi == SAFI_EVPN)) {
9bcb3eef 6277 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6278
6279 for (rm = bgp_table_top(table); rm;
6280 rm = bgp_route_next(rm)) {
a78beeb5 6281 bgp_static =
9bcb3eef 6282 bgp_dest_get_bgp_static_info(
5a8ba9fc 6283 rm);
9bcb3eef
DS
6284 bgp_static_update_safi(
6285 bgp, bgp_dest_get_prefix(rm),
6286 bgp_static, afi, safi);
d62a17ae 6287 }
05c7a1cc 6288 } else {
9bcb3eef
DS
6289 bgp_static = bgp_dest_get_bgp_static_info(dest);
6290 bgp_static_update(bgp,
6291 bgp_dest_get_prefix(dest),
6292 bgp_static, afi, safi);
ea47320b 6293 }
05c7a1cc
QY
6294 }
6295 }
892fedb6 6296 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6297}
6298
6299static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6300 safi_t safi)
6301{
6302 struct bgp_table *table;
9bcb3eef 6303 struct bgp_dest *dest;
40381db7 6304 struct bgp_path_info *pi;
d62a17ae 6305
dfb6fd1d
NT
6306 /* Do not install the aggregate route if BGP is in the
6307 * process of termination.
6308 */
892fedb6
DA
6309 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6310 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6311 return;
6312
d62a17ae 6313 table = bgp->rib[afi][safi];
9bcb3eef
DS
6314 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6315 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6316 if (pi->peer == bgp->peer_self
6317 && ((pi->type == ZEBRA_ROUTE_BGP
6318 && pi->sub_type == BGP_ROUTE_STATIC)
6319 || (pi->type != ZEBRA_ROUTE_BGP
6320 && pi->sub_type
d62a17ae 6321 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6322 bgp_aggregate_decrement(
6323 bgp, bgp_dest_get_prefix(dest), pi, afi,
6324 safi);
40381db7 6325 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6326 bgp_path_info_delete(dest, pi);
6327 bgp_process(bgp, dest, afi, safi);
d62a17ae 6328 }
6329 }
6330 }
ad4cbda1 6331}
6332
6333/*
6334 * Purge all networks and redistributed routes from routing table.
6335 * Invoked upon the instance going down.
6336 */
d62a17ae 6337void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6338{
d62a17ae 6339 afi_t afi;
6340 safi_t safi;
ad4cbda1 6341
05c7a1cc
QY
6342 FOREACH_AFI_SAFI (afi, safi)
6343 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6344}
6345
137446f9
LB
6346/*
6347 * gpz 110624
6348 * Currently this is used to set static routes for VPN and ENCAP.
6349 * I think it can probably be factored with bgp_static_set.
6350 */
d62a17ae 6351int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6352 const char *ip_str, const char *rd_str,
6353 const char *label_str, const char *rmap_str,
6354 int evpn_type, const char *esi, const char *gwip,
6355 const char *ethtag, const char *routermac)
6356{
6357 VTY_DECLVAR_CONTEXT(bgp, bgp);
6358 int ret;
6359 struct prefix p;
6360 struct prefix_rd prd;
9bcb3eef
DS
6361 struct bgp_dest *pdest;
6362 struct bgp_dest *dest;
d62a17ae 6363 struct bgp_table *table;
6364 struct bgp_static *bgp_static;
6365 mpls_label_t label = MPLS_INVALID_LABEL;
6366 struct prefix gw_ip;
6367
6368 /* validate ip prefix */
6369 ret = str2prefix(ip_str, &p);
6370 if (!ret) {
6371 vty_out(vty, "%% Malformed prefix\n");
6372 return CMD_WARNING_CONFIG_FAILED;
6373 }
6374 apply_mask(&p);
6375 if ((afi == AFI_L2VPN)
6376 && (bgp_build_evpn_prefix(evpn_type,
6377 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6378 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6379 return CMD_WARNING_CONFIG_FAILED;
6380 }
718e3744 6381
d62a17ae 6382 ret = str2prefix_rd(rd_str, &prd);
6383 if (!ret) {
6384 vty_out(vty, "%% Malformed rd\n");
6385 return CMD_WARNING_CONFIG_FAILED;
6386 }
718e3744 6387
d62a17ae 6388 if (label_str) {
6389 unsigned long label_val;
6390 label_val = strtoul(label_str, NULL, 10);
6391 encode_label(label_val, &label);
6392 }
9bedbb1e 6393
d62a17ae 6394 if (safi == SAFI_EVPN) {
6395 if (esi && str2esi(esi, NULL) == 0) {
6396 vty_out(vty, "%% Malformed ESI\n");
6397 return CMD_WARNING_CONFIG_FAILED;
6398 }
6399 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6400 vty_out(vty, "%% Malformed Router MAC\n");
6401 return CMD_WARNING_CONFIG_FAILED;
6402 }
6403 if (gwip) {
6404 memset(&gw_ip, 0, sizeof(struct prefix));
6405 ret = str2prefix(gwip, &gw_ip);
6406 if (!ret) {
6407 vty_out(vty, "%% Malformed GatewayIp\n");
6408 return CMD_WARNING_CONFIG_FAILED;
6409 }
6410 if ((gw_ip.family == AF_INET
3714a385 6411 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6412 (struct prefix_evpn *)&p))
6413 || (gw_ip.family == AF_INET6
3714a385 6414 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6415 (struct prefix_evpn *)&p))) {
6416 vty_out(vty,
6417 "%% GatewayIp family differs with IP prefix\n");
6418 return CMD_WARNING_CONFIG_FAILED;
6419 }
6420 }
6421 }
9bcb3eef
DS
6422 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6423 if (!bgp_dest_has_bgp_path_info_data(pdest))
6424 bgp_dest_set_bgp_table_info(pdest,
67009e22 6425 bgp_table_init(bgp, afi, safi));
9bcb3eef 6426 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6427
9bcb3eef 6428 dest = bgp_node_get(table, &p);
d62a17ae 6429
9bcb3eef 6430 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6431 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6432 bgp_dest_unlock_node(dest);
d62a17ae 6433 } else {
6434 /* New configuration. */
6435 bgp_static = bgp_static_new();
6436 bgp_static->backdoor = 0;
6437 bgp_static->valid = 0;
6438 bgp_static->igpmetric = 0;
975a328e 6439 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6440 bgp_static->label = label;
6441 bgp_static->prd = prd;
6442
6443 if (rmap_str) {
0a22ddfb 6444 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6445 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6446 bgp_static->rmap.name =
6447 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6448 bgp_static->rmap.map =
6449 route_map_lookup_by_name(rmap_str);
b4897fa5 6450 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6451 }
718e3744 6452
d62a17ae 6453 if (safi == SAFI_EVPN) {
6454 if (esi) {
6455 bgp_static->eth_s_id =
6456 XCALLOC(MTYPE_ATTR,
0a50c248 6457 sizeof(esi_t));
d62a17ae 6458 str2esi(esi, bgp_static->eth_s_id);
6459 }
6460 if (routermac) {
6461 bgp_static->router_mac =
28328ea9 6462 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6463 (void)prefix_str2mac(routermac,
6464 bgp_static->router_mac);
d62a17ae 6465 }
6466 if (gwip)
6467 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6468 }
9bcb3eef 6469 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6470
d62a17ae 6471 bgp_static->valid = 1;
6472 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6473 }
718e3744 6474
d62a17ae 6475 return CMD_SUCCESS;
718e3744 6476}
6477
6478/* Configure static BGP network. */
d62a17ae 6479int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6480 const char *ip_str, const char *rd_str,
6481 const char *label_str, int evpn_type, const char *esi,
6482 const char *gwip, const char *ethtag)
6483{
6484 VTY_DECLVAR_CONTEXT(bgp, bgp);
6485 int ret;
6486 struct prefix p;
6487 struct prefix_rd prd;
9bcb3eef
DS
6488 struct bgp_dest *pdest;
6489 struct bgp_dest *dest;
d62a17ae 6490 struct bgp_table *table;
6491 struct bgp_static *bgp_static;
6492 mpls_label_t label = MPLS_INVALID_LABEL;
6493
6494 /* Convert IP prefix string to struct prefix. */
6495 ret = str2prefix(ip_str, &p);
6496 if (!ret) {
6497 vty_out(vty, "%% Malformed prefix\n");
6498 return CMD_WARNING_CONFIG_FAILED;
6499 }
6500 apply_mask(&p);
6501 if ((afi == AFI_L2VPN)
6502 && (bgp_build_evpn_prefix(evpn_type,
6503 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6504 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6505 return CMD_WARNING_CONFIG_FAILED;
6506 }
6507 ret = str2prefix_rd(rd_str, &prd);
6508 if (!ret) {
6509 vty_out(vty, "%% Malformed rd\n");
6510 return CMD_WARNING_CONFIG_FAILED;
6511 }
718e3744 6512
d62a17ae 6513 if (label_str) {
6514 unsigned long label_val;
6515 label_val = strtoul(label_str, NULL, 10);
6516 encode_label(label_val, &label);
6517 }
718e3744 6518
9bcb3eef
DS
6519 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6520 if (!bgp_dest_has_bgp_path_info_data(pdest))
6521 bgp_dest_set_bgp_table_info(pdest,
67009e22 6522 bgp_table_init(bgp, afi, safi));
d62a17ae 6523 else
9bcb3eef
DS
6524 bgp_dest_unlock_node(pdest);
6525 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6526
9bcb3eef 6527 dest = bgp_node_lookup(table, &p);
6b0655a2 6528
9bcb3eef 6529 if (dest) {
d62a17ae 6530 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6531
9bcb3eef 6532 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6533 bgp_static_free(bgp_static);
9bcb3eef
DS
6534 bgp_dest_set_bgp_static_info(dest, NULL);
6535 bgp_dest_unlock_node(dest);
6536 bgp_dest_unlock_node(dest);
d62a17ae 6537 } else
6538 vty_out(vty, "%% Can't find the route\n");
6539
6540 return CMD_SUCCESS;
6541}
6542
6543static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6544 const char *rmap_name)
6545{
6546 VTY_DECLVAR_CONTEXT(bgp, bgp);
6547 struct bgp_rmap *rmap;
6548
6549 rmap = &bgp->table_map[afi][safi];
6550 if (rmap_name) {
0a22ddfb 6551 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6552 route_map_counter_decrement(rmap->map);
d62a17ae 6553 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6554 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6555 route_map_counter_increment(rmap->map);
d62a17ae 6556 } else {
0a22ddfb 6557 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6558 route_map_counter_decrement(rmap->map);
d62a17ae 6559 rmap->map = NULL;
6560 }
73ac8160 6561
d62a17ae 6562 if (bgp_fibupd_safi(safi))
6563 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6564
d62a17ae 6565 return CMD_SUCCESS;
73ac8160
DS
6566}
6567
d62a17ae 6568static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6569 const char *rmap_name)
73ac8160 6570{
d62a17ae 6571 VTY_DECLVAR_CONTEXT(bgp, bgp);
6572 struct bgp_rmap *rmap;
73ac8160 6573
d62a17ae 6574 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6575 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6576 route_map_counter_decrement(rmap->map);
d62a17ae 6577 rmap->map = NULL;
73ac8160 6578
d62a17ae 6579 if (bgp_fibupd_safi(safi))
6580 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6581
d62a17ae 6582 return CMD_SUCCESS;
73ac8160
DS
6583}
6584
2b791107 6585void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6586 safi_t safi)
73ac8160 6587{
d62a17ae 6588 if (bgp->table_map[afi][safi].name) {
d62a17ae 6589 vty_out(vty, " table-map %s\n",
6590 bgp->table_map[afi][safi].name);
6591 }
73ac8160
DS
6592}
6593
73ac8160
DS
6594DEFUN (bgp_table_map,
6595 bgp_table_map_cmd,
6596 "table-map WORD",
6597 "BGP table to RIB route download filter\n"
6598 "Name of the route map\n")
6599{
d62a17ae 6600 int idx_word = 1;
6601 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6602 argv[idx_word]->arg);
73ac8160
DS
6603}
6604DEFUN (no_bgp_table_map,
6605 no_bgp_table_map_cmd,
6606 "no table-map WORD",
3a2d747c 6607 NO_STR
73ac8160
DS
6608 "BGP table to RIB route download filter\n"
6609 "Name of the route map\n")
6610{
d62a17ae 6611 int idx_word = 2;
6612 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6613 argv[idx_word]->arg);
73ac8160
DS
6614}
6615
37a87b8f
CS
6616DEFPY_YANG (bgp_network, bgp_network_cmd,
6617 "[no] network \
6618 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6619 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6620 backdoor$backdoor}]",
6621 NO_STR
6622 "Specify a network to announce via BGP\n"
6623 "IPv4 prefix\n"
6624 "Network number\n"
6625 "Network mask\n"
6626 "Network mask\n"
6627 "Route-map to modify the attributes\n"
6628 "Name of the route map\n"
6629 "Label index to associate with the prefix\n"
6630 "Label index value\n"
6631 "Specify a BGP backdoor route\n")
6632{
6633 char addr_prefix_str[PREFIX_STRLEN];
6634 char base_xpath[XPATH_MAXLEN];
6635 afi_t afi;
6636 safi_t safi;
e2a86ad9
DS
6637
6638 if (address_str) {
6639 int ret;
718e3744 6640
e2a86ad9 6641 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6642 addr_prefix_str,
6643 sizeof(addr_prefix_str));
e2a86ad9
DS
6644 if (!ret) {
6645 vty_out(vty, "%% Inconsistent address and mask\n");
6646 return CMD_WARNING_CONFIG_FAILED;
6647 }
d62a17ae 6648 }
718e3744 6649
37a87b8f
CS
6650 afi = bgp_node_afi(vty);
6651 safi = bgp_node_safi(vty);
6652
6653 if (no) {
6654 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6655 } else {
6656 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6657
6658 if (map_name)
6659 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6660 NB_OP_CREATE, map_name);
6661 else
6662 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6663 NB_OP_DESTROY, NULL);
6664
6665 if (label_index_str)
6666 nb_cli_enqueue_change(vty, "./label-index",
6667 NB_OP_MODIFY, label_index_str);
6668
6669 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6670 backdoor ? "true" : "false");
6671 }
6672
6673 snprintf(
6674 base_xpath, sizeof(base_xpath),
6675 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6676 yang_afi_safi_value2identity(afi, safi),
6677 bgp_afi_safi_get_container_str(afi, safi),
6678 address_str ? addr_prefix_str : prefix_str);
6679
6680 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6681}
6682
37a87b8f
CS
6683DEFPY_YANG (ipv6_bgp_network,
6684 ipv6_bgp_network_cmd,
6685 "[no] network X:X::X:X/M$prefix \
6686 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6687 NO_STR
6688 "Specify a network to announce via BGP\n"
6689 "IPv6 prefix\n"
6690 "Route-map to modify the attributes\n"
6691 "Name of the route map\n"
6692 "Label index to associate with the prefix\n"
6693 "Label index value\n")
6694{
6695 char base_xpath[XPATH_MAXLEN];
6696 afi_t afi;
6697 safi_t safi;
6698
6699 afi = bgp_node_afi(vty);
6700 safi = bgp_node_safi(vty);
6701
6702 if (no) {
6703 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6704 } else {
6705 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6706
6707 if (map_name)
6708 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6709 NB_OP_MODIFY, map_name);
6710 else
6711 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6712 NB_OP_DESTROY, NULL);
6713
6714 if (label_index_str)
6715 nb_cli_enqueue_change(vty, "./label-index",
6716 NB_OP_MODIFY, label_index_str);
6717 }
6718
6719 snprintf(
6720 base_xpath, sizeof(base_xpath),
6721 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6722 yang_afi_safi_value2identity(afi, safi),
6723 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6724
6725 return nb_cli_apply_changes(vty, base_xpath);
6726}
6727
6728void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6729 struct lyd_node *dnode,
6730 bool show_defaults)
718e3744 6731{
37a87b8f
CS
6732 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6733
6734 if (yang_dnode_exists(dnode, "./label-index"))
6735 vty_out(vty, " label-index %s",
6736 yang_dnode_get_string(dnode, "./label-index"));
6737
6738 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6739 vty_out(vty, " route-map %s",
6740 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6741
6742 if (yang_dnode_get_bool(dnode, "./backdoor"))
6743 vty_out(vty, " backdoor");
6744
6745 vty_out(vty, "\n");
1b6d5c7e
VV
6746}
6747
d62a17ae 6748static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6749{
d62a17ae 6750 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6751}
6752
d62a17ae 6753static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6754{
365ab2e7
RZ
6755 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6756 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6757 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6758 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6759 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6760}
718e3744 6761
365ab2e7
RZ
6762/**
6763 * Helper function to avoid repeated code: prepare variables for a
6764 * `route_map_apply` call.
6765 *
6766 * \returns `true` on route map match, otherwise `false`.
6767 */
6768static bool aggr_suppress_map_test(struct bgp *bgp,
6769 struct bgp_aggregate *aggregate,
6770 struct bgp_path_info *pi)
6771{
6772 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6773 route_map_result_t rmr = RMAP_DENYMATCH;
6774 struct bgp_path_info rmap_path = {};
6775 struct attr attr = {};
6776
6777 /* No route map entries created, just don't match. */
6778 if (aggregate->suppress_map == NULL)
6779 return false;
6780
6781 /* Call route map matching and return result. */
6782 attr.aspath = aspath_empty();
6783 rmap_path.peer = bgp->peer_self;
6784 rmap_path.attr = &attr;
6785
6786 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6787 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6788 bgp->peer_self->rmap_type = 0;
6789
6790 bgp_attr_flush(&attr);
6791
6792 return rmr == RMAP_PERMITMATCH;
6793}
6794
4056a5f6
RZ
6795/** Test whether the aggregation has suppressed this path or not. */
6796static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6797 struct bgp_path_info *pi)
6798{
6799 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6800 return false;
6801
6802 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6803}
6804
6805/**
6806 * Suppress this path and keep the reference.
6807 *
6808 * \returns `true` if needs processing otherwise `false`.
6809 */
6810static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6811 struct bgp_path_info *pi)
6812{
6813 struct bgp_path_info_extra *pie;
6814
6815 /* Path is already suppressed by this aggregation. */
6816 if (aggr_suppress_exists(aggregate, pi))
6817 return false;
6818
6819 pie = bgp_path_info_extra_get(pi);
6820
6821 /* This is the first suppression, allocate memory and list it. */
6822 if (pie->aggr_suppressors == NULL)
6823 pie->aggr_suppressors = list_new();
6824
6825 listnode_add(pie->aggr_suppressors, aggregate);
6826
6827 /* Only mark for processing if suppressed. */
6828 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6829 if (BGP_DEBUG(update, UPDATE_OUT))
6830 zlog_debug("aggregate-address suppressing: %pFX",
6831 bgp_dest_get_prefix(pi->net));
6832
4056a5f6
RZ
6833 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6834 return true;
6835 }
6836
6837 return false;
6838}
6839
6840/**
6841 * Unsuppress this path and remove the reference.
6842 *
6843 * \returns `true` if needs processing otherwise `false`.
6844 */
6845static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6846 struct bgp_path_info *pi)
6847{
6848 /* Path wasn't suppressed. */
6849 if (!aggr_suppress_exists(aggregate, pi))
6850 return false;
6851
6852 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6853
6854 /* Unsuppress and free extra memory if last item. */
6855 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6856 if (BGP_DEBUG(update, UPDATE_OUT))
6857 zlog_debug("aggregate-address unsuppressing: %pFX",
6858 bgp_dest_get_prefix(pi->net));
6859
4056a5f6
RZ
6860 list_delete(&pi->extra->aggr_suppressors);
6861 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6862 return true;
6863 }
6864
6865 return false;
6866}
6867
3dc339cd
DA
6868static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6869 struct aspath *aspath,
6870 struct community *comm,
6871 struct ecommunity *ecomm,
6872 struct lcommunity *lcomm)
eaaf8adb
DS
6873{
6874 static struct aspath *ae = NULL;
6875
6876 if (!ae)
6877 ae = aspath_empty();
6878
40381db7 6879 if (!pi)
3dc339cd 6880 return false;
eaaf8adb 6881
40381db7 6882 if (origin != pi->attr->origin)
3dc339cd 6883 return false;
eaaf8adb 6884
40381db7 6885 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6886 return false;
29f7d023 6887
40381db7 6888 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6889 return false;
eaaf8adb 6890
3da2cc32 6891 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6892 return false;
eaaf8adb 6893
dd18c5a9 6894 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6895 return false;
dd18c5a9 6896
40381db7 6897 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6898 return false;
7ce8a8e0 6899
3dc339cd 6900 return true;
eaaf8adb
DS
6901}
6902
5f040085
DS
6903static void bgp_aggregate_install(
6904 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6905 uint8_t origin, struct aspath *aspath, struct community *community,
6906 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6907 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6908{
9bcb3eef 6909 struct bgp_dest *dest;
c701010e 6910 struct bgp_table *table;
6f94b685 6911 struct bgp_path_info *pi, *orig, *new;
20894f50 6912 struct attr *attr;
c701010e
DS
6913
6914 table = bgp->rib[afi][safi];
6915
9bcb3eef 6916 dest = bgp_node_get(table, p);
eaaf8adb 6917
9bcb3eef 6918 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6919 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6920 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6921 break;
6922
6aabb15d
RZ
6923 /*
6924 * If we have paths with different MEDs, then don't install
6925 * (or uninstall) the aggregate route.
6926 */
6927 if (aggregate->match_med && aggregate->med_mismatched)
6928 goto uninstall_aggregate_route;
6929
c701010e 6930 if (aggregate->count > 0) {
eaaf8adb
DS
6931 /*
6932 * If the aggregate information has not changed
6933 * no need to re-install it again.
6934 */
6f94b685 6935 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6936 ecommunity, lcommunity)) {
9bcb3eef 6937 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6938
6939 if (aspath)
6940 aspath_free(aspath);
6941 if (community)
3c1f53de 6942 community_free(&community);
3da2cc32
DS
6943 if (ecommunity)
6944 ecommunity_free(&ecommunity);
dd18c5a9
DS
6945 if (lcommunity)
6946 lcommunity_free(&lcommunity);
eaaf8adb
DS
6947
6948 return;
6949 }
6950
6951 /*
6952 * Mark the old as unusable
6953 */
40381db7 6954 if (pi)
9bcb3eef 6955 bgp_path_info_delete(dest, pi);
eaaf8adb 6956
20894f50
DA
6957 attr = bgp_attr_aggregate_intern(
6958 bgp, origin, aspath, community, ecommunity, lcommunity,
6959 aggregate, atomic_aggregate, p);
6960
6961 if (!attr) {
6962 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6963 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6964 zlog_debug("%s: %pFX null attribute", __func__,
6965 p);
20894f50
DA
6966 return;
6967 }
6968
3da2cc32 6969 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6970 bgp->peer_self, attr, dest);
20894f50 6971
1defdda8 6972 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6973
9bcb3eef
DS
6974 bgp_path_info_add(dest, new);
6975 bgp_process(bgp, dest, afi, safi);
c701010e 6976 } else {
6aabb15d 6977 uninstall_aggregate_route:
6f94b685 6978 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6979 if (pi->peer == bgp->peer_self
6980 && pi->type == ZEBRA_ROUTE_BGP
6981 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6982 break;
6983
6984 /* Withdraw static BGP route from routing table. */
40381db7 6985 if (pi) {
9bcb3eef
DS
6986 bgp_path_info_delete(dest, pi);
6987 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6988 }
6989 }
6990
9bcb3eef 6991 bgp_dest_unlock_node(dest);
c701010e
DS
6992}
6993
6aabb15d
RZ
6994/**
6995 * Check if the current path has different MED than other known paths.
6996 *
6997 * \returns `true` if the MED matched the others else `false`.
6998 */
6999static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7000 struct bgp *bgp, struct bgp_path_info *pi)
7001{
7002 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7003
7004 /* This is the first route being analyzed. */
7005 if (!aggregate->med_initialized) {
7006 aggregate->med_initialized = true;
7007 aggregate->med_mismatched = false;
7008 aggregate->med_matched_value = cur_med;
7009 } else {
7010 /* Check if routes with different MED showed up. */
7011 if (cur_med != aggregate->med_matched_value)
7012 aggregate->med_mismatched = true;
7013 }
7014
7015 return !aggregate->med_mismatched;
7016}
7017
7018/**
7019 * Initializes and tests all routes in the aggregate address path for MED
7020 * values.
7021 *
7022 * \returns `true` if all MEDs are the same otherwise `false`.
7023 */
7024static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7025 struct bgp *bgp, const struct prefix *p,
7026 afi_t afi, safi_t safi)
7027{
7028 struct bgp_table *table = bgp->rib[afi][safi];
7029 const struct prefix *dest_p;
7030 struct bgp_dest *dest, *top;
7031 struct bgp_path_info *pi;
7032 bool med_matched = true;
7033
7034 aggregate->med_initialized = false;
7035
7036 top = bgp_node_get(table, p);
7037 for (dest = bgp_node_get(table, p); dest;
7038 dest = bgp_route_next_until(dest, top)) {
7039 dest_p = bgp_dest_get_prefix(dest);
7040 if (dest_p->prefixlen <= p->prefixlen)
7041 continue;
7042
7043 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7044 if (BGP_PATH_HOLDDOWN(pi))
7045 continue;
7046 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7047 continue;
7048 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7049 med_matched = false;
7050 break;
7051 }
7052 }
7053 if (!med_matched)
7054 break;
7055 }
7056 bgp_dest_unlock_node(top);
7057
7058 return med_matched;
7059}
7060
7061/**
7062 * Toggles the route suppression status for this aggregate address
7063 * configuration.
7064 */
4056a5f6
RZ
7065void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7066 struct bgp *bgp, const struct prefix *p,
7067 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7068{
7069 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7070 const struct prefix *dest_p;
7071 struct bgp_dest *dest, *top;
7072 struct bgp_path_info *pi;
7073 bool toggle_suppression;
7074
7075 /* We've found a different MED we must revert any suppressed routes. */
7076 top = bgp_node_get(table, p);
7077 for (dest = bgp_node_get(table, p); dest;
7078 dest = bgp_route_next_until(dest, top)) {
7079 dest_p = bgp_dest_get_prefix(dest);
7080 if (dest_p->prefixlen <= p->prefixlen)
7081 continue;
7082
7083 toggle_suppression = false;
7084 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7085 if (BGP_PATH_HOLDDOWN(pi))
7086 continue;
7087 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7088 continue;
7089
6aabb15d
RZ
7090 /* We are toggling suppression back. */
7091 if (suppress) {
6aabb15d 7092 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7093 if (aggr_suppress_path(aggregate, pi))
7094 toggle_suppression = true;
6aabb15d
RZ
7095 continue;
7096 }
7097
6aabb15d 7098 /* Install route if there is no more suppression. */
4056a5f6 7099 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7100 toggle_suppression = true;
6aabb15d
RZ
7101 }
7102
7103 if (toggle_suppression)
7104 bgp_process(bgp, dest, afi, safi);
7105 }
7106 bgp_dest_unlock_node(top);
7107}
7108
7109/**
7110 * Aggregate address MED matching incremental test: this function is called
7111 * when the initial aggregation occurred and we are only testing a single
7112 * new path.
7113 *
7114 * In addition to testing and setting the MED validity it also installs back
7115 * suppressed routes (if summary is configured).
7116 *
7117 * Must not be called in `bgp_aggregate_route`.
7118 */
7119static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7120 struct bgp *bgp, const struct prefix *p,
7121 afi_t afi, safi_t safi,
7122 struct bgp_path_info *pi, bool is_adding)
7123{
7124 /* MED matching disabled. */
7125 if (!aggregate->match_med)
7126 return;
7127
7128 /* Aggregation with different MED, nothing to do. */
7129 if (aggregate->med_mismatched)
7130 return;
7131
7132 /*
7133 * Test the current entry:
7134 *
7135 * is_adding == true: if the new entry doesn't match then we must
7136 * install all suppressed routes.
7137 *
7138 * is_adding == false: if the entry being removed was the last
7139 * unmatching entry then we can suppress all routes.
7140 */
7141 if (!is_adding) {
7142 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7143 && aggregate->summary_only)
7144 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7145 safi, true);
7146 } else
7147 bgp_aggregate_med_match(aggregate, bgp, pi);
7148
7149 /* No mismatches, just quit. */
7150 if (!aggregate->med_mismatched)
7151 return;
7152
7153 /* Route summarization is disabled. */
7154 if (!aggregate->summary_only)
7155 return;
7156
7157 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7158}
7159
b5d58c32 7160/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7161void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7162 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7163{
7164 struct bgp_table *table;
9bcb3eef
DS
7165 struct bgp_dest *top;
7166 struct bgp_dest *dest;
d7c0a89a 7167 uint8_t origin;
d62a17ae 7168 struct aspath *aspath = NULL;
d62a17ae 7169 struct community *community = NULL;
3da2cc32 7170 struct ecommunity *ecommunity = NULL;
dd18c5a9 7171 struct lcommunity *lcommunity = NULL;
40381db7 7172 struct bgp_path_info *pi;
d62a17ae 7173 unsigned long match = 0;
d7c0a89a 7174 uint8_t atomic_aggregate = 0;
d62a17ae 7175
9f822fa2
S
7176 /* If the bgp instance is being deleted or self peer is deleted
7177 * then do not create aggregate route
7178 */
892fedb6
DA
7179 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7180 || (bgp->peer_self == NULL))
9f822fa2
S
7181 return;
7182
6aabb15d
RZ
7183 /* Initialize and test routes for MED difference. */
7184 if (aggregate->match_med)
7185 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7186
4056a5f6
RZ
7187 /*
7188 * Reset aggregate count: we might've been called from route map
7189 * update so in that case we must retest all more specific routes.
7190 *
7191 * \see `bgp_route_map_process_update`.
7192 */
7193 aggregate->count = 0;
7194 aggregate->incomplete_origin_count = 0;
7195 aggregate->incomplete_origin_count = 0;
7196 aggregate->egp_origin_count = 0;
7197
d62a17ae 7198 /* ORIGIN attribute: If at least one route among routes that are
7199 aggregated has ORIGIN with the value INCOMPLETE, then the
7200 aggregated route must have the ORIGIN attribute with the value
7201 INCOMPLETE. Otherwise, if at least one route among routes that
7202 are aggregated has ORIGIN with the value EGP, then the aggregated
7203 route must have the origin attribute with the value EGP. In all
7204 other case the value of the ORIGIN attribute of the aggregated
7205 route is INTERNAL. */
7206 origin = BGP_ORIGIN_IGP;
718e3744 7207
d62a17ae 7208 table = bgp->rib[afi][safi];
718e3744 7209
d62a17ae 7210 top = bgp_node_get(table, p);
9bcb3eef
DS
7211 for (dest = bgp_node_get(table, p); dest;
7212 dest = bgp_route_next_until(dest, top)) {
7213 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7214
9bcb3eef 7215 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7216 continue;
d62a17ae 7217
a77e2f4b
S
7218 /* If suppress fib is enabled and route not installed
7219 * in FIB, skip the route
7220 */
7221 if (!bgp_check_advertise(bgp, dest))
7222 continue;
7223
c2ff8b3e 7224 match = 0;
d62a17ae 7225
9bcb3eef 7226 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7227 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7228 continue;
718e3744 7229
40381db7 7230 if (pi->attr->flag
c2ff8b3e
DS
7231 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7232 atomic_aggregate = 1;
d62a17ae 7233
40381db7 7234 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7235 continue;
d62a17ae 7236
f273fef1
DS
7237 /*
7238 * summary-only aggregate route suppress
7239 * aggregated route announcements.
6aabb15d
RZ
7240 *
7241 * MED matching:
7242 * Don't create summaries if MED didn't match
7243 * otherwise neither the specific routes and the
7244 * aggregation will be announced.
f273fef1 7245 */
6aabb15d
RZ
7246 if (aggregate->summary_only
7247 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7248 if (aggr_suppress_path(aggregate, pi))
7249 match++;
d62a17ae 7250 }
c2ff8b3e 7251
365ab2e7
RZ
7252 /*
7253 * Suppress more specific routes that match the route
7254 * map results.
7255 *
7256 * MED matching:
7257 * Don't suppress routes if MED matching is enabled and
7258 * it mismatched otherwise we might end up with no
7259 * routes for this path.
7260 */
7261 if (aggregate->suppress_map_name
7262 && AGGREGATE_MED_VALID(aggregate)
7263 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7264 if (aggr_suppress_path(aggregate, pi))
7265 match++;
d62a17ae 7266 }
c2ff8b3e
DS
7267
7268 aggregate->count++;
7269
f273fef1
DS
7270 /*
7271 * If at least one route among routes that are
7272 * aggregated has ORIGIN with the value INCOMPLETE,
7273 * then the aggregated route MUST have the ORIGIN
7274 * attribute with the value INCOMPLETE. Otherwise, if
7275 * at least one route among routes that are aggregated
7276 * has ORIGIN with the value EGP, then the aggregated
7277 * route MUST have the ORIGIN attribute with the value
7278 * EGP.
7279 */
fc968841
NT
7280 switch (pi->attr->origin) {
7281 case BGP_ORIGIN_INCOMPLETE:
7282 aggregate->incomplete_origin_count++;
7283 break;
7284 case BGP_ORIGIN_EGP:
7285 aggregate->egp_origin_count++;
7286 break;
7287 default:
7288 /*Do nothing.
7289 */
7290 break;
7291 }
c2ff8b3e
DS
7292
7293 if (!aggregate->as_set)
7294 continue;
7295
f273fef1
DS
7296 /*
7297 * as-set aggregate route generate origin, as path,
7298 * and community aggregation.
7299 */
fc968841
NT
7300 /* Compute aggregate route's as-path.
7301 */
ef51a7d8 7302 bgp_compute_aggregate_aspath_hash(aggregate,
7303 pi->attr->aspath);
c2ff8b3e 7304
fc968841
NT
7305 /* Compute aggregate route's community.
7306 */
7307 if (pi->attr->community)
21fec674 7308 bgp_compute_aggregate_community_hash(
fc968841
NT
7309 aggregate,
7310 pi->attr->community);
dd18c5a9 7311
fc968841
NT
7312 /* Compute aggregate route's extended community.
7313 */
7314 if (pi->attr->ecommunity)
4edd83f9 7315 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7316 aggregate,
7317 pi->attr->ecommunity);
7318
7319 /* Compute aggregate route's large community.
7320 */
7321 if (pi->attr->lcommunity)
f1eb1f05 7322 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7323 aggregate,
7324 pi->attr->lcommunity);
d62a17ae 7325 }
c2ff8b3e 7326 if (match)
9bcb3eef 7327 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7328 }
21fec674 7329 if (aggregate->as_set) {
ef51a7d8 7330 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7331 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7332 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7333 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7334 }
7335
f1eb1f05 7336
9bcb3eef 7337 bgp_dest_unlock_node(top);
718e3744 7338
718e3744 7339
fc968841
NT
7340 if (aggregate->incomplete_origin_count > 0)
7341 origin = BGP_ORIGIN_INCOMPLETE;
7342 else if (aggregate->egp_origin_count > 0)
7343 origin = BGP_ORIGIN_EGP;
d62a17ae 7344
229757f1
DA
7345 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7346 origin = aggregate->origin;
7347
fc968841
NT
7348 if (aggregate->as_set) {
7349 if (aggregate->aspath)
7350 /* Retrieve aggregate route's as-path.
7351 */
7352 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7353
fc968841
NT
7354 if (aggregate->community)
7355 /* Retrieve aggregate route's community.
7356 */
7357 community = community_dup(aggregate->community);
3da2cc32 7358
fc968841
NT
7359 if (aggregate->ecommunity)
7360 /* Retrieve aggregate route's ecommunity.
7361 */
7362 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7363
fc968841
NT
7364 if (aggregate->lcommunity)
7365 /* Retrieve aggregate route's lcommunity.
7366 */
7367 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7368 }
718e3744 7369
c701010e 7370 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7371 ecommunity, lcommunity, atomic_aggregate,
7372 aggregate);
718e3744 7373}
7374
5f040085
DS
7375void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7376 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7377{
7378 struct bgp_table *table;
9bcb3eef
DS
7379 struct bgp_dest *top;
7380 struct bgp_dest *dest;
40381db7 7381 struct bgp_path_info *pi;
3b7db173
DS
7382 unsigned long match;
7383
7384 table = bgp->rib[afi][safi];
7385
7386 /* If routes exists below this node, generate aggregate routes. */
7387 top = bgp_node_get(table, p);
9bcb3eef
DS
7388 for (dest = bgp_node_get(table, p); dest;
7389 dest = bgp_route_next_until(dest, top)) {
7390 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7391
9bcb3eef 7392 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7393 continue;
7394 match = 0;
7395
9bcb3eef 7396 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7397 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7398 continue;
7399
40381db7 7400 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7401 continue;
7402
6aabb15d
RZ
7403 if (aggregate->summary_only && pi->extra
7404 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7405 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7406 match++;
3b7db173 7407 }
3b7db173 7408
365ab2e7
RZ
7409 if (aggregate->suppress_map_name
7410 && AGGREGATE_MED_VALID(aggregate)
7411 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7412 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7413 match++;
3b7db173 7414 }
365ab2e7 7415
3b7db173 7416 aggregate->count--;
fc968841
NT
7417
7418 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7419 aggregate->incomplete_origin_count--;
7420 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7421 aggregate->egp_origin_count--;
7422
7423 if (aggregate->as_set) {
7424 /* Remove as-path from aggregate.
7425 */
ef51a7d8 7426 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7427 aggregate,
7428 pi->attr->aspath);
7429
7430 if (pi->attr->community)
7431 /* Remove community from aggregate.
7432 */
21fec674 7433 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7434 aggregate,
7435 pi->attr->community);
7436
7437 if (pi->attr->ecommunity)
7438 /* Remove ecommunity from aggregate.
7439 */
4edd83f9 7440 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7441 aggregate,
7442 pi->attr->ecommunity);
7443
7444 if (pi->attr->lcommunity)
7445 /* Remove lcommunity from aggregate.
7446 */
f1eb1f05 7447 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7448 aggregate,
7449 pi->attr->lcommunity);
7450 }
3b7db173
DS
7451 }
7452
7453 /* If this node was suppressed, process the change. */
7454 if (match)
9bcb3eef 7455 bgp_process(bgp, dest, afi, safi);
3b7db173 7456 }
f1eb1f05 7457 if (aggregate->as_set) {
ef51a7d8 7458 aspath_free(aggregate->aspath);
7459 aggregate->aspath = NULL;
21fec674 7460 if (aggregate->community)
7461 community_free(&aggregate->community);
4edd83f9 7462 if (aggregate->ecommunity)
7463 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7464 if (aggregate->lcommunity)
7465 lcommunity_free(&aggregate->lcommunity);
7466 }
7467
9bcb3eef 7468 bgp_dest_unlock_node(top);
3b7db173 7469}
718e3744 7470
5f040085
DS
7471static void bgp_add_route_to_aggregate(struct bgp *bgp,
7472 const struct prefix *aggr_p,
fc968841
NT
7473 struct bgp_path_info *pinew, afi_t afi,
7474 safi_t safi,
7475 struct bgp_aggregate *aggregate)
7476{
7477 uint8_t origin;
7478 struct aspath *aspath = NULL;
7479 uint8_t atomic_aggregate = 0;
7480 struct community *community = NULL;
7481 struct ecommunity *ecommunity = NULL;
7482 struct lcommunity *lcommunity = NULL;
7483
a4559740 7484 /* If the bgp instance is being deleted or self peer is deleted
7485 * then do not create aggregate route
7486 */
7487 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7488 || (bgp->peer_self == NULL))
7489 return;
7490
fc968841
NT
7491 /* ORIGIN attribute: If at least one route among routes that are
7492 * aggregated has ORIGIN with the value INCOMPLETE, then the
7493 * aggregated route must have the ORIGIN attribute with the value
7494 * INCOMPLETE. Otherwise, if at least one route among routes that
7495 * are aggregated has ORIGIN with the value EGP, then the aggregated
7496 * route must have the origin attribute with the value EGP. In all
7497 * other case the value of the ORIGIN attribute of the aggregated
7498 * route is INTERNAL.
7499 */
7500 origin = BGP_ORIGIN_IGP;
7501
7502 aggregate->count++;
7503
6aabb15d
RZ
7504 /*
7505 * This must be called before `summary` check to avoid
7506 * "suppressing" twice.
7507 */
7508 if (aggregate->match_med)
7509 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7510 pinew, true);
7511
7512 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7513 aggr_suppress_path(aggregate, pinew);
fc968841 7514
365ab2e7
RZ
7515 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7516 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7517 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7518
7519 switch (pinew->attr->origin) {
7520 case BGP_ORIGIN_INCOMPLETE:
7521 aggregate->incomplete_origin_count++;
7522 break;
7523 case BGP_ORIGIN_EGP:
7524 aggregate->egp_origin_count++;
7525 break;
7526 default:
7527 /* Do nothing.
7528 */
7529 break;
7530 }
7531
7532 if (aggregate->incomplete_origin_count > 0)
7533 origin = BGP_ORIGIN_INCOMPLETE;
7534 else if (aggregate->egp_origin_count > 0)
7535 origin = BGP_ORIGIN_EGP;
7536
229757f1
DA
7537 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7538 origin = aggregate->origin;
7539
fc968841
NT
7540 if (aggregate->as_set) {
7541 /* Compute aggregate route's as-path.
7542 */
7543 bgp_compute_aggregate_aspath(aggregate,
7544 pinew->attr->aspath);
7545
7546 /* Compute aggregate route's community.
7547 */
7548 if (pinew->attr->community)
7549 bgp_compute_aggregate_community(
7550 aggregate,
7551 pinew->attr->community);
7552
7553 /* Compute aggregate route's extended community.
7554 */
7555 if (pinew->attr->ecommunity)
7556 bgp_compute_aggregate_ecommunity(
7557 aggregate,
7558 pinew->attr->ecommunity);
7559
7560 /* Compute aggregate route's large community.
7561 */
7562 if (pinew->attr->lcommunity)
7563 bgp_compute_aggregate_lcommunity(
7564 aggregate,
7565 pinew->attr->lcommunity);
7566
7567 /* Retrieve aggregate route's as-path.
7568 */
7569 if (aggregate->aspath)
7570 aspath = aspath_dup(aggregate->aspath);
7571
7572 /* Retrieve aggregate route's community.
7573 */
7574 if (aggregate->community)
7575 community = community_dup(aggregate->community);
7576
7577 /* Retrieve aggregate route's ecommunity.
7578 */
7579 if (aggregate->ecommunity)
7580 ecommunity = ecommunity_dup(aggregate->ecommunity);
7581
7582 /* Retrieve aggregate route's lcommunity.
7583 */
7584 if (aggregate->lcommunity)
7585 lcommunity = lcommunity_dup(aggregate->lcommunity);
7586 }
7587
7588 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7589 aspath, community, ecommunity,
7590 lcommunity, atomic_aggregate, aggregate);
7591}
7592
7593static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7594 safi_t safi,
7595 struct bgp_path_info *pi,
7596 struct bgp_aggregate *aggregate,
5f040085 7597 const struct prefix *aggr_p)
fc968841
NT
7598{
7599 uint8_t origin;
7600 struct aspath *aspath = NULL;
7601 uint8_t atomic_aggregate = 0;
7602 struct community *community = NULL;
7603 struct ecommunity *ecommunity = NULL;
7604 struct lcommunity *lcommunity = NULL;
7605 unsigned long match = 0;
7606
a4559740 7607 /* If the bgp instance is being deleted or self peer is deleted
7608 * then do not create aggregate route
7609 */
7610 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7611 || (bgp->peer_self == NULL))
7612 return;
7613
fc968841
NT
7614 if (BGP_PATH_HOLDDOWN(pi))
7615 return;
7616
7617 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7618 return;
7619
4056a5f6
RZ
7620 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7621 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7622 match++;
fc968841 7623
365ab2e7 7624 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7625 && aggr_suppress_map_test(bgp, aggregate, pi))
7626 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7627 match++;
fc968841 7628
6aabb15d 7629 /*
365ab2e7 7630 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7631 * "unsuppressing" twice.
7632 */
7633 if (aggregate->match_med)
7634 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7635 true);
7636
fc968841
NT
7637 if (aggregate->count > 0)
7638 aggregate->count--;
7639
7640 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7641 aggregate->incomplete_origin_count--;
7642 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7643 aggregate->egp_origin_count--;
7644
7645 if (aggregate->as_set) {
7646 /* Remove as-path from aggregate.
7647 */
7648 bgp_remove_aspath_from_aggregate(aggregate,
7649 pi->attr->aspath);
7650
7651 if (pi->attr->community)
7652 /* Remove community from aggregate.
7653 */
7654 bgp_remove_community_from_aggregate(
7655 aggregate,
7656 pi->attr->community);
7657
7658 if (pi->attr->ecommunity)
7659 /* Remove ecommunity from aggregate.
7660 */
7661 bgp_remove_ecommunity_from_aggregate(
7662 aggregate,
7663 pi->attr->ecommunity);
7664
7665 if (pi->attr->lcommunity)
7666 /* Remove lcommunity from aggregate.
7667 */
7668 bgp_remove_lcommunity_from_aggregate(
7669 aggregate,
7670 pi->attr->lcommunity);
7671 }
7672
7673 /* If this node was suppressed, process the change. */
7674 if (match)
7675 bgp_process(bgp, pi->net, afi, safi);
7676
7677 origin = BGP_ORIGIN_IGP;
7678 if (aggregate->incomplete_origin_count > 0)
7679 origin = BGP_ORIGIN_INCOMPLETE;
7680 else if (aggregate->egp_origin_count > 0)
7681 origin = BGP_ORIGIN_EGP;
7682
229757f1
DA
7683 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7684 origin = aggregate->origin;
7685
fc968841
NT
7686 if (aggregate->as_set) {
7687 /* Retrieve aggregate route's as-path.
7688 */
7689 if (aggregate->aspath)
7690 aspath = aspath_dup(aggregate->aspath);
7691
7692 /* Retrieve aggregate route's community.
7693 */
7694 if (aggregate->community)
7695 community = community_dup(aggregate->community);
7696
7697 /* Retrieve aggregate route's ecommunity.
7698 */
7699 if (aggregate->ecommunity)
7700 ecommunity = ecommunity_dup(aggregate->ecommunity);
7701
7702 /* Retrieve aggregate route's lcommunity.
7703 */
7704 if (aggregate->lcommunity)
7705 lcommunity = lcommunity_dup(aggregate->lcommunity);
7706 }
7707
7708 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7709 aspath, community, ecommunity,
7710 lcommunity, atomic_aggregate, aggregate);
7711}
7712
5a1ae2c2 7713void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7714 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7715{
9bcb3eef
DS
7716 struct bgp_dest *child;
7717 struct bgp_dest *dest;
d62a17ae 7718 struct bgp_aggregate *aggregate;
7719 struct bgp_table *table;
718e3744 7720
d62a17ae 7721 table = bgp->aggregate[afi][safi];
f018db83 7722
d62a17ae 7723 /* No aggregates configured. */
7724 if (bgp_table_top_nolock(table) == NULL)
7725 return;
f018db83 7726
d62a17ae 7727 if (p->prefixlen == 0)
7728 return;
718e3744 7729
40381db7 7730 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7731 return;
718e3744 7732
a77e2f4b
S
7733 /* If suppress fib is enabled and route not installed
7734 * in FIB, do not update the aggregate route
7735 */
7736 if (!bgp_check_advertise(bgp, pi->net))
7737 return;
7738
d62a17ae 7739 child = bgp_node_get(table, p);
718e3744 7740
d62a17ae 7741 /* Aggregate address configuration check. */
9bcb3eef
DS
7742 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7743 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7744
9bcb3eef
DS
7745 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7746 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7747 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7748 aggregate);
d62a17ae 7749 }
b1e62edd 7750 }
9bcb3eef 7751 bgp_dest_unlock_node(child);
718e3744 7752}
7753
5a1ae2c2 7754void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7755 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7756{
9bcb3eef
DS
7757 struct bgp_dest *child;
7758 struct bgp_dest *dest;
d62a17ae 7759 struct bgp_aggregate *aggregate;
7760 struct bgp_table *table;
718e3744 7761
d62a17ae 7762 table = bgp->aggregate[afi][safi];
718e3744 7763
d62a17ae 7764 /* No aggregates configured. */
7765 if (bgp_table_top_nolock(table) == NULL)
7766 return;
718e3744 7767
d62a17ae 7768 if (p->prefixlen == 0)
7769 return;
718e3744 7770
d62a17ae 7771 child = bgp_node_get(table, p);
718e3744 7772
d62a17ae 7773 /* Aggregate address configuration check. */
9bcb3eef
DS
7774 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7775 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7776
9bcb3eef
DS
7777 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7778 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7779 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7780 aggregate, dest_p);
d62a17ae 7781 }
b1e62edd 7782 }
9bcb3eef 7783 bgp_dest_unlock_node(child);
d62a17ae 7784}
718e3744 7785
718e3744 7786/* Aggregate route attribute. */
7787#define AGGREGATE_SUMMARY_ONLY 1
7788#define AGGREGATE_AS_SET 1
fb29348a 7789#define AGGREGATE_AS_UNSET 0
718e3744 7790
229757f1
DA
7791static const char *bgp_origin2str(uint8_t origin)
7792{
7793 switch (origin) {
7794 case BGP_ORIGIN_IGP:
7795 return "igp";
7796 case BGP_ORIGIN_EGP:
7797 return "egp";
7798 case BGP_ORIGIN_INCOMPLETE:
7799 return "incomplete";
7800 }
7801 return "n/a";
7802}
7803
fdeb5a81 7804static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7805{
7806 switch (v_state) {
fdeb5a81
DS
7807 case RPKI_NOT_BEING_USED:
7808 return "not used";
7809 case RPKI_VALID:
b5b99af8 7810 return "valid";
fdeb5a81 7811 case RPKI_NOTFOUND:
b5b99af8 7812 return "not found";
fdeb5a81 7813 case RPKI_INVALID:
b5b99af8 7814 return "invalid";
b5b99af8 7815 }
fdeb5a81
DS
7816
7817 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7818 return "ERROR";
7819}
7820
37a87b8f
CS
7821int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7822 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7823{
9bcb3eef 7824 struct bgp_dest *dest;
d62a17ae 7825 struct bgp_aggregate *aggregate;
718e3744 7826
a4559740 7827 /* If the bgp instance is being deleted or self peer is deleted
7828 * then do not create aggregate route
7829 */
7830 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7831 || (bgp->peer_self == NULL))
7832 return 0;
7833
37a87b8f 7834 apply_mask(prefix);
d62a17ae 7835 /* Old configuration check. */
37a87b8f 7836 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7837 if (!dest) {
37a87b8f
CS
7838 snprintf(errmsg, errmsg_len,
7839 "There is no aggregate-address configuration.\n");
7840 return -1;
d62a17ae 7841 }
f6269b4f 7842
9bcb3eef 7843 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7844 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7845 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7846 0, aggregate);
d62a17ae 7847
7848 /* Unlock aggregate address configuration. */
9bcb3eef 7849 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7850
7851 if (aggregate->community)
7852 community_free(&aggregate->community);
7853
7854 if (aggregate->community_hash) {
7855 /* Delete all communities in the hash.
7856 */
7857 hash_clean(aggregate->community_hash,
7858 bgp_aggr_community_remove);
7859 /* Free up the community_hash.
7860 */
7861 hash_free(aggregate->community_hash);
7862 }
7863
7864 if (aggregate->ecommunity)
7865 ecommunity_free(&aggregate->ecommunity);
7866
7867 if (aggregate->ecommunity_hash) {
7868 /* Delete all ecommunities in the hash.
7869 */
7870 hash_clean(aggregate->ecommunity_hash,
7871 bgp_aggr_ecommunity_remove);
7872 /* Free up the ecommunity_hash.
7873 */
7874 hash_free(aggregate->ecommunity_hash);
7875 }
7876
7877 if (aggregate->lcommunity)
7878 lcommunity_free(&aggregate->lcommunity);
7879
7880 if (aggregate->lcommunity_hash) {
7881 /* Delete all lcommunities in the hash.
7882 */
7883 hash_clean(aggregate->lcommunity_hash,
7884 bgp_aggr_lcommunity_remove);
7885 /* Free up the lcommunity_hash.
7886 */
7887 hash_free(aggregate->lcommunity_hash);
7888 }
7889
7890 if (aggregate->aspath)
7891 aspath_free(aggregate->aspath);
7892
7893 if (aggregate->aspath_hash) {
7894 /* Delete all as-paths in the hash.
7895 */
7896 hash_clean(aggregate->aspath_hash,
7897 bgp_aggr_aspath_remove);
7898 /* Free up the aspath_hash.
7899 */
7900 hash_free(aggregate->aspath_hash);
7901 }
7902
d62a17ae 7903 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7904 bgp_dest_unlock_node(dest);
7905 bgp_dest_unlock_node(dest);
d62a17ae 7906
37a87b8f 7907 return 0;
d62a17ae 7908}
7909
37a87b8f
CS
7910int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7911 safi_t safi, const char *rmap, uint8_t summary_only,
7912 uint8_t as_set, uint8_t origin, bool match_med,
7913 const char *suppress_map,
7914 char *errmsg, size_t errmsg_len)
d62a17ae 7915{
d62a17ae 7916 int ret;
9bcb3eef 7917 struct bgp_dest *dest;
d62a17ae 7918 struct bgp_aggregate *aggregate;
fb29348a 7919 uint8_t as_set_new = as_set;
37a87b8f 7920 char buf[PREFIX2STR_BUFFER];
d62a17ae 7921
365ab2e7 7922 if (suppress_map && summary_only) {
37a87b8f 7923 snprintf(errmsg, errmsg_len,
365ab2e7 7924 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7925 return -1;
365ab2e7
RZ
7926 }
7927
37a87b8f 7928 apply_mask(prefix);
d62a17ae 7929
37a87b8f
CS
7930 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7931 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7932 snprintf(
7933 errmsg, errmsg_len,
7934 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7935 prefix2str(prefix, buf, PREFIX_STRLEN));
7936 return -1;
3624ac81
DS
7937 }
7938
d62a17ae 7939 /* Old configuration check. */
37a87b8f 7940 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7941 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7942
20894f50 7943 if (aggregate) {
37a87b8f
CS
7944 snprintf(errmsg, errmsg_len,
7945 "There is already same aggregate network.\n");
d62a17ae 7946 /* try to remove the old entry */
37a87b8f
CS
7947 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7948 errmsg_len);
d62a17ae 7949 if (ret) {
37a87b8f
CS
7950 snprintf(errmsg, errmsg_len,
7951 "Error deleting aggregate.\n");
9bcb3eef 7952 bgp_dest_unlock_node(dest);
37a87b8f 7953 return -1;
d62a17ae 7954 }
7955 }
718e3744 7956
d62a17ae 7957 /* Make aggregate address structure. */
7958 aggregate = bgp_aggregate_new();
7959 aggregate->summary_only = summary_only;
6aabb15d 7960 aggregate->match_med = match_med;
fb29348a
DA
7961
7962 /* Network operators MUST NOT locally generate any new
7963 * announcements containing AS_SET or AS_CONFED_SET. If they have
7964 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7965 * SHOULD withdraw those routes and re-announce routes for the
7966 * aggregate or component prefixes (i.e., the more-specific routes
7967 * subsumed by the previously aggregated route) without AS_SET
7968 * or AS_CONFED_SET in the updates.
7969 */
7f972cd8 7970 if (bgp->reject_as_sets) {
fb29348a
DA
7971 if (as_set == AGGREGATE_AS_SET) {
7972 as_set_new = AGGREGATE_AS_UNSET;
7973 zlog_warn(
63efca0e 7974 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7975 __func__);
37a87b8f
CS
7976 snprintf(
7977 errmsg, errmsg_len,
fb29348a
DA
7978 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7979 }
7980 }
7981
7982 aggregate->as_set = as_set_new;
d62a17ae 7983 aggregate->safi = safi;
229757f1
DA
7984 /* Override ORIGIN attribute if defined.
7985 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7986 * to IGP which is not what rfc4271 says.
7987 * This enables the same behavior, optionally.
7988 */
7989 aggregate->origin = origin;
20894f50
DA
7990
7991 if (rmap) {
7992 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
7993 route_map_counter_decrement(aggregate->rmap.map);
7994 aggregate->rmap.name =
7995 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
7996 aggregate->rmap.map = route_map_lookup_by_name(rmap);
7997 route_map_counter_increment(aggregate->rmap.map);
7998 }
365ab2e7
RZ
7999
8000 if (suppress_map) {
8001 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8002 route_map_counter_decrement(aggregate->suppress_map);
8003
8004 aggregate->suppress_map_name =
8005 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8006 aggregate->suppress_map =
8007 route_map_lookup_by_name(aggregate->suppress_map_name);
8008 route_map_counter_increment(aggregate->suppress_map);
8009 }
8010
9bcb3eef 8011 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8012
d62a17ae 8013 /* Aggregate address insert into BGP routing table. */
37a87b8f 8014 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 8015
37a87b8f 8016 return 0;
718e3744 8017}
8018
37a87b8f
CS
8019DEFPY_YANG(
8020 aggregate_addressv4, aggregate_addressv4_cmd,
faff43d0 8021 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
37a87b8f
CS
8022 "as-set$as_set_s"
8023 "|summary-only$summary_only"
8024 "|route-map WORD$rmap_name"
8025 "|origin <egp|igp|incomplete>$origin_s"
8026 "|matching-MED-only$match_med"
90e21f35 8027 "|suppress-map WORD$suppress_map"
faff43d0 8028 "}]",
37a87b8f
CS
8029 NO_STR
8030 "Configure BGP aggregate entries\n"
8031 "Aggregate prefix\n"
8032 "Aggregate address\n"
8033 "Aggregate mask\n"
8034 "Generate AS set path information\n"
8035 "Filter more specific routes from updates\n"
8036 "Apply route map to aggregate network\n"
8037 "Route map name\n"
8038 "BGP origin code\n"
8039 "Remote EGP\n"
8040 "Local IGP\n"
8041 "Unknown heritage\n"
8042 "Only aggregate routes with matching MED\n"
90e21f35
CS
8043 "Suppress the selected more specific routes\n"
8044 "Route map with the route selectors\n")
37a87b8f
CS
8045{
8046 char base_xpath[XPATH_MAXLEN];
554b3b10 8047 safi_t safi = bgp_node_safi(vty);
554b3b10 8048 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8049
554b3b10 8050 if (addr_str) {
7533cad7
QY
8051 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8052 sizeof(prefix_buf))
554b3b10
RZ
8053 == 0) {
8054 vty_out(vty, "%% Inconsistent address and mask\n");
8055 return CMD_WARNING_CONFIG_FAILED;
8056 }
37a87b8f
CS
8057 } else {
8058 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
8059 }
8060
37a87b8f
CS
8061 if (!no && origin_s)
8062 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
8063
8064 if (!no && as_set_s)
8065 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
8066 else
8067 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
8068
8069 if (!no && summary_only)
8070 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8071 "true");
8072 else
8073 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8074 "false");
8075
fa423774
CS
8076 if (!no && match_med)
8077 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
8078 else
8079 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
8080 "false");
8081
37a87b8f
CS
8082 if (rmap_name)
8083 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
8084 rmap_name);
8085 else
8086 nb_cli_enqueue_change(vty, "./rmap-policy-export",
8087 NB_OP_DESTROY, NULL);
8088
90e21f35
CS
8089 if (suppress_map)
8090 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
8091 suppress_map);
8092 else
8093 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
8094 NULL);
8095
37a87b8f
CS
8096 snprintf(
8097 base_xpath, sizeof(base_xpath),
8098 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8099 yang_afi_safi_value2identity(AFI_IP, safi),
8100 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 8101
554b3b10 8102 if (no)
37a87b8f
CS
8103 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8104 else
8105 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
8106
8107 return nb_cli_apply_changes(vty, base_xpath);
8108}
8109
8110DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
faff43d0 8111 "[no] aggregate-address X:X::X:X/M$prefix [{"
37a87b8f
CS
8112 "as-set$as_set_s"
8113 "|summary-only$summary_only"
8114 "|route-map WORD$rmap_name"
8115 "|origin <egp|igp|incomplete>$origin_s"
8116 "|matching-MED-only$match_med"
90e21f35 8117 "|suppress-map WORD$suppress_map"
faff43d0 8118 "}]",
37a87b8f
CS
8119 NO_STR
8120 "Configure BGP aggregate entries\n"
8121 "Aggregate prefix\n"
8122 "Generate AS set path information\n"
8123 "Filter more specific routes from updates\n"
8124 "Apply route map to aggregate network\n"
8125 "Route map name\n"
8126 "BGP origin code\n"
8127 "Remote EGP\n"
8128 "Local IGP\n"
8129 "Unknown heritage\n"
8130 "Only aggregate routes with matching MED\n"
8131 "Suppress the selected more specific routes\n"
90e21f35 8132 "Route map with the route selectors\n")
37a87b8f
CS
8133{
8134 char base_xpath[XPATH_MAXLEN];
8135 safi_t safi = bgp_node_safi(vty);
8136
8137 if (!no && origin_s)
8138 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
8139
8140 if (!no && as_set_s)
8141 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
8142 else
8143 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
8144
8145 if (!no && summary_only)
8146 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8147 "true");
8148 else
8149 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8150 "false");
8151
fa423774
CS
8152 if (!no && match_med)
8153 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
8154 else
8155 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
8156 "false");
8157
37a87b8f
CS
8158 if (rmap_name)
8159 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
8160 rmap_name);
8161
90e21f35
CS
8162 if (suppress_map)
8163 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
8164 suppress_map);
8165 else
8166 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
8167 NULL);
8168
37a87b8f
CS
8169 snprintf(
8170 base_xpath, sizeof(base_xpath),
8171 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8172 yang_afi_safi_value2identity(AFI_IP6, safi),
8173 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
8174
554b3b10 8175 if (no)
37a87b8f
CS
8176 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8177 else
8178 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 8179
37a87b8f
CS
8180 return nb_cli_apply_changes(vty, base_xpath);
8181}
8182
8183void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
8184 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
8185{
8186 uint8_t origin;
8187
8188 vty_out(vty, " aggregate-address %s",
8189 yang_dnode_get_string(dnode, "./prefix"));
8190
8191 if (yang_dnode_get_bool(dnode, "./as-set"))
8192 vty_out(vty, " as-set");
8193
8194 if (yang_dnode_get_bool(dnode, "./summary-only"))
8195 vty_out(vty, " summary-only");
8196
8197 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
8198 vty_out(vty, " route-map %s",
8199 yang_dnode_get_string(dnode, "./rmap-policy-export"));
8200
8201 origin = yang_dnode_get_enum(dnode, "./origin");
8202 if (origin != BGP_ORIGIN_UNSPECIFIED)
8203 vty_out(vty, " origin %s", bgp_origin2str(origin));
8204
fa423774
CS
8205 if (yang_dnode_get_bool(dnode, "./match-med"))
8206 vty_out(vty, " matching-MED-only");
8207
37a87b8f 8208 vty_out(vty, "\n");
718e3744 8209}
8210
718e3744 8211/* Redistribute route treatment. */
d62a17ae 8212void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
8213 const union g_addr *nexthop, ifindex_t ifindex,
8214 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
8215 uint8_t type, unsigned short instance,
8216 route_tag_t tag)
d62a17ae 8217{
4b7e6066 8218 struct bgp_path_info *new;
40381db7
DS
8219 struct bgp_path_info *bpi;
8220 struct bgp_path_info rmap_path;
9bcb3eef 8221 struct bgp_dest *bn;
d62a17ae 8222 struct attr attr;
8223 struct attr *new_attr;
8224 afi_t afi;
b68885f9 8225 route_map_result_t ret;
d62a17ae 8226 struct bgp_redist *red;
8227
8228 /* Make default attribute. */
8229 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8230 /*
8231 * This must not be NULL to satisfy Coverity SA
8232 */
8233 assert(attr.aspath);
9de1f7ff 8234
a4d82a8a 8235 switch (nhtype) {
9de1f7ff
DS
8236 case NEXTHOP_TYPE_IFINDEX:
8237 break;
8238 case NEXTHOP_TYPE_IPV4:
8239 case NEXTHOP_TYPE_IPV4_IFINDEX:
8240 attr.nexthop = nexthop->ipv4;
8241 break;
8242 case NEXTHOP_TYPE_IPV6:
8243 case NEXTHOP_TYPE_IPV6_IFINDEX:
8244 attr.mp_nexthop_global = nexthop->ipv6;
8245 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8246 break;
8247 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8248 switch (p->family) {
8249 case AF_INET:
9de1f7ff 8250 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8251 break;
8252 case AF_INET6:
9de1f7ff
DS
8253 memset(&attr.mp_nexthop_global, 0,
8254 sizeof(attr.mp_nexthop_global));
74489921 8255 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8256 break;
74489921 8257 }
9de1f7ff 8258 break;
d62a17ae 8259 }
74489921 8260 attr.nh_ifindex = ifindex;
f04a80a5 8261
d62a17ae 8262 attr.med = metric;
8263 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8264 attr.tag = tag;
718e3744 8265
d62a17ae 8266 afi = family2afi(p->family);
6aeb9e78 8267
d62a17ae 8268 red = bgp_redist_lookup(bgp, afi, type, instance);
8269 if (red) {
8270 struct attr attr_new;
718e3744 8271
d62a17ae 8272 /* Copy attribute for modification. */
6f4f49b2 8273 attr_new = attr;
718e3744 8274
d62a17ae 8275 if (red->redist_metric_flag)
8276 attr_new.med = red->redist_metric;
718e3744 8277
d62a17ae 8278 /* Apply route-map. */
8279 if (red->rmap.name) {
40381db7
DS
8280 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8281 rmap_path.peer = bgp->peer_self;
8282 rmap_path.attr = &attr_new;
718e3744 8283
d62a17ae 8284 SET_FLAG(bgp->peer_self->rmap_type,
8285 PEER_RMAP_TYPE_REDISTRIBUTE);
8286
1782514f 8287 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8288
8289 bgp->peer_self->rmap_type = 0;
8290
8291 if (ret == RMAP_DENYMATCH) {
8292 /* Free uninterned attribute. */
8293 bgp_attr_flush(&attr_new);
8294
8295 /* Unintern original. */
8296 aspath_unintern(&attr.aspath);
8297 bgp_redistribute_delete(bgp, p, type, instance);
8298 return;
8299 }
8300 }
8301
637e5ba4 8302 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8303 bgp_attr_add_gshut_community(&attr_new);
8304
d62a17ae 8305 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8306 SAFI_UNICAST, p, NULL);
8307
8308 new_attr = bgp_attr_intern(&attr_new);
8309
9bcb3eef 8310 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8311 if (bpi->peer == bgp->peer_self
8312 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8313 break;
8314
40381db7 8315 if (bpi) {
d62a17ae 8316 /* Ensure the (source route) type is updated. */
40381db7
DS
8317 bpi->type = type;
8318 if (attrhash_cmp(bpi->attr, new_attr)
8319 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8320 bgp_attr_unintern(&new_attr);
8321 aspath_unintern(&attr.aspath);
9bcb3eef 8322 bgp_dest_unlock_node(bn);
d62a17ae 8323 return;
8324 } else {
8325 /* The attribute is changed. */
40381db7 8326 bgp_path_info_set_flag(bn, bpi,
18ee8310 8327 BGP_PATH_ATTR_CHANGED);
d62a17ae 8328
8329 /* Rewrite BGP route information. */
40381db7
DS
8330 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8331 bgp_path_info_restore(bn, bpi);
d62a17ae 8332 else
40381db7
DS
8333 bgp_aggregate_decrement(
8334 bgp, p, bpi, afi, SAFI_UNICAST);
8335 bgp_attr_unintern(&bpi->attr);
8336 bpi->attr = new_attr;
8337 bpi->uptime = bgp_clock();
d62a17ae 8338
8339 /* Process change. */
40381db7 8340 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8341 SAFI_UNICAST);
8342 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8343 bgp_dest_unlock_node(bn);
d62a17ae 8344 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8345
8346 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8347 || (bgp->inst_type
8348 == BGP_INSTANCE_TYPE_DEFAULT)) {
8349
8350 vpn_leak_from_vrf_update(
40381db7 8351 bgp_get_default(), bgp, bpi);
ddb5b488 8352 }
d62a17ae 8353 return;
8354 }
8355 }
8356
8357 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8358 bgp->peer_self, new_attr, bn);
1defdda8 8359 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8360
8361 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8362 bgp_path_info_add(bn, new);
9bcb3eef 8363 bgp_dest_unlock_node(bn);
d62a17ae 8364 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8365
8366 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8367 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8368
8369 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8370 }
d62a17ae 8371 }
8372
8373 /* Unintern original. */
8374 aspath_unintern(&attr.aspath);
718e3744 8375}
8376
d7c0a89a
QY
8377void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8378 unsigned short instance)
718e3744 8379{
d62a17ae 8380 afi_t afi;
9bcb3eef 8381 struct bgp_dest *dest;
40381db7 8382 struct bgp_path_info *pi;
d62a17ae 8383 struct bgp_redist *red;
718e3744 8384
d62a17ae 8385 afi = family2afi(p->family);
718e3744 8386
d62a17ae 8387 red = bgp_redist_lookup(bgp, afi, type, instance);
8388 if (red) {
9bcb3eef
DS
8389 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8390 SAFI_UNICAST, p, NULL);
d62a17ae 8391
9bcb3eef 8392 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8393 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8394 break;
8395
40381db7 8396 if (pi) {
ddb5b488
PZ
8397 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8398 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8399
8400 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8401 bgp, pi);
ddb5b488 8402 }
40381db7 8403 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8404 bgp_path_info_delete(dest, pi);
8405 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8406 }
9bcb3eef 8407 bgp_dest_unlock_node(dest);
d62a17ae 8408 }
8409}
8410
8411/* Withdraw specified route type's route. */
8412void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8413 unsigned short instance)
d62a17ae 8414{
9bcb3eef 8415 struct bgp_dest *dest;
40381db7 8416 struct bgp_path_info *pi;
d62a17ae 8417 struct bgp_table *table;
8418
8419 table = bgp->rib[afi][SAFI_UNICAST];
8420
9bcb3eef
DS
8421 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8422 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8423 if (pi->peer == bgp->peer_self && pi->type == type
8424 && pi->instance == instance)
d62a17ae 8425 break;
8426
40381db7 8427 if (pi) {
ddb5b488
PZ
8428 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8429 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8430
8431 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8432 bgp, pi);
ddb5b488 8433 }
9bcb3eef 8434 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8435 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8436 bgp_path_info_delete(dest, pi);
8437 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8438 }
718e3744 8439 }
718e3744 8440}
6b0655a2 8441
718e3744 8442/* Static function to display route. */
7d3cae70
DA
8443static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8444 struct vty *vty, json_object *json, bool wide)
718e3744 8445{
be054588 8446 int len = 0;
d62a17ae 8447 char buf[BUFSIZ];
50e05855 8448 char buf2[BUFSIZ];
718e3744 8449
d62a17ae 8450 if (p->family == AF_INET) {
c6462ff4 8451 if (!json) {
8228a9a7 8452 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8453 } else {
8454 json_object_string_add(json, "prefix",
8455 inet_ntop(p->family,
8456 &p->u.prefix, buf,
8457 BUFSIZ));
8458 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8459 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8460 json_object_string_add(json, "network", buf2);
7d3cae70 8461 json_object_int_add(json, "version", dest->version);
c6462ff4 8462 }
d62a17ae 8463 } else if (p->family == AF_ETHERNET) {
8228a9a7 8464 len = vty_out(vty, "%pFX", p);
b03b8898 8465 } else if (p->family == AF_EVPN) {
57f7feb6 8466 if (!json)
2dbe669b 8467 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8468 else
60466a63 8469 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8470 } else if (p->family == AF_FLOWSPEC) {
8471 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8472 json ?
8473 NLRI_STRING_FORMAT_JSON_SIMPLE :
8474 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8475 } else {
c6462ff4 8476 if (!json)
8228a9a7 8477 len = vty_out(vty, "%pFX", p);
50e05855
AD
8478 else {
8479 json_object_string_add(json, "prefix",
8480 inet_ntop(p->family,
8481 &p->u.prefix, buf,
8482 BUFSIZ));
8483 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8484 prefix2str(p, buf2, PREFIX_STRLEN);
8485 json_object_string_add(json, "network", buf2);
7d3cae70 8486 json_object_int_add(json, "version", dest->version);
37d4e0df 8487 }
9c92b5f7 8488 }
d62a17ae 8489
9c92b5f7 8490 if (!json) {
ae248832 8491 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8492 if (len < 1)
8493 vty_out(vty, "\n%*s", 20, " ");
8494 else
8495 vty_out(vty, "%*s", len, " ");
8496 }
718e3744 8497}
8498
d62a17ae 8499enum bgp_display_type {
8500 normal_list,
718e3744 8501};
8502
bbb46eb5
DA
8503static const char *
8504bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8505{
8506 switch (reason) {
8507 case bgp_path_selection_none:
8508 return "Nothing to Select";
8509 case bgp_path_selection_first:
8510 return "First path received";
8511 case bgp_path_selection_evpn_sticky_mac:
8512 return "EVPN Sticky Mac";
8513 case bgp_path_selection_evpn_seq:
8514 return "EVPN sequence number";
8515 case bgp_path_selection_evpn_lower_ip:
8516 return "EVPN lower IP";
8517 case bgp_path_selection_evpn_local_path:
8518 return "EVPN local ES path";
8519 case bgp_path_selection_evpn_non_proxy:
8520 return "EVPN non proxy";
8521 case bgp_path_selection_weight:
8522 return "Weight";
8523 case bgp_path_selection_local_pref:
8524 return "Local Pref";
8525 case bgp_path_selection_local_route:
8526 return "Local Route";
8527 case bgp_path_selection_confed_as_path:
8528 return "Confederation based AS Path";
8529 case bgp_path_selection_as_path:
8530 return "AS Path";
8531 case bgp_path_selection_origin:
8532 return "Origin";
8533 case bgp_path_selection_med:
8534 return "MED";
8535 case bgp_path_selection_peer:
8536 return "Peer Type";
8537 case bgp_path_selection_confed:
8538 return "Confed Peer Type";
8539 case bgp_path_selection_igp_metric:
8540 return "IGP Metric";
8541 case bgp_path_selection_older:
8542 return "Older Path";
8543 case bgp_path_selection_router_id:
8544 return "Router ID";
8545 case bgp_path_selection_cluster_length:
bcab253c 8546 return "Cluster length";
bbb46eb5
DA
8547 case bgp_path_selection_stale:
8548 return "Path Staleness";
8549 case bgp_path_selection_local_configured:
8550 return "Locally configured route";
8551 case bgp_path_selection_neighbor_ip:
8552 return "Neighbor IP";
8553 case bgp_path_selection_default:
8554 return "Nothing left to compare";
8555 }
8556 return "Invalid (internal error)";
8557}
8558
18ee8310 8559/* Print the short form route status for a bgp_path_info */
4b7e6066 8560static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8561 struct bgp_path_info *path,
82c298be 8562 const struct prefix *p,
d62a17ae 8563 json_object *json_path)
718e3744 8564{
82c298be
DA
8565 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8566
d62a17ae 8567 if (json_path) {
b05a1c8b 8568
d62a17ae 8569 /* Route status display. */
9b6d8fcf 8570 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8571 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8572
9b6d8fcf 8573 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8574 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8575
4056a5f6 8576 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8577 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8578
9b6d8fcf
DS
8579 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8580 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8581 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8582
d62a17ae 8583 /* Selected */
9b6d8fcf 8584 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8585 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8586
9b6d8fcf 8587 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8588 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8589
bbb46eb5 8590 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8591 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8592 json_object_string_add(json_path, "selectionReason",
8593 bgp_path_selection_reason2str(
8594 path->net->reason));
8595 }
b05a1c8b 8596
9b6d8fcf 8597 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8598 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8599
d62a17ae 8600 /* Internal route. */
9b6d8fcf
DS
8601 if ((path->peer->as)
8602 && (path->peer->as == path->peer->local_as))
d62a17ae 8603 json_object_string_add(json_path, "pathFrom",
8604 "internal");
8605 else
8606 json_object_string_add(json_path, "pathFrom",
8607 "external");
b05a1c8b 8608
d62a17ae 8609 return;
8610 }
b05a1c8b 8611
82c298be
DA
8612 /* RPKI validation state */
8613 rpki_state =
8614 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8615
8616 if (rpki_state == RPKI_VALID)
8617 vty_out(vty, "V");
8618 else if (rpki_state == RPKI_INVALID)
8619 vty_out(vty, "I");
8620 else if (rpki_state == RPKI_NOTFOUND)
8621 vty_out(vty, "N");
8622
d62a17ae 8623 /* Route status display. */
9b6d8fcf 8624 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8625 vty_out(vty, "R");
9b6d8fcf 8626 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8627 vty_out(vty, "S");
4056a5f6 8628 else if (bgp_path_suppressed(path))
d62a17ae 8629 vty_out(vty, "s");
9b6d8fcf
DS
8630 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8631 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8632 vty_out(vty, "*");
8633 else
8634 vty_out(vty, " ");
8635
8636 /* Selected */
9b6d8fcf 8637 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8638 vty_out(vty, "h");
9b6d8fcf 8639 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8640 vty_out(vty, "d");
9b6d8fcf 8641 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8642 vty_out(vty, ">");
9b6d8fcf 8643 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8644 vty_out(vty, "=");
8645 else
8646 vty_out(vty, " ");
718e3744 8647
d62a17ae 8648 /* Internal route. */
9b6d8fcf
DS
8649 if (path->peer && (path->peer->as)
8650 && (path->peer->as == path->peer->local_as))
d62a17ae 8651 vty_out(vty, "i");
8652 else
8653 vty_out(vty, " ");
b40d939b 8654}
8655
2ba93fd6
DA
8656static char *bgp_nexthop_hostname(struct peer *peer,
8657 struct bgp_nexthop_cache *bnc)
25b5da8d 8658{
892fedb6 8659 if (peer->hostname
aef999a2 8660 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8661 return peer->hostname;
8662 return NULL;
8663}
8664
b40d939b 8665/* called from terminal list command */
bd494ec5 8666void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8667 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8668 json_object *json_paths, bool wide)
d62a17ae 8669{
aef999a2 8670 int len;
515c2602 8671 struct attr *attr = path->attr;
d62a17ae 8672 json_object *json_path = NULL;
8673 json_object *json_nexthops = NULL;
8674 json_object *json_nexthop_global = NULL;
8675 json_object *json_nexthop_ll = NULL;
6f214dd3 8676 json_object *json_ext_community = NULL;
9df8b37c 8677 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8678 bool nexthop_self =
9b6d8fcf 8679 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8680 bool nexthop_othervrf = false;
43089216 8681 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8682 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8683 char *nexthop_hostname =
8684 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8685 char esi_buf[ESI_STR_LEN];
d62a17ae 8686
8687 if (json_paths)
8688 json_path = json_object_new_object();
8689
8690 /* short status lead text */
82c298be 8691 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8692
8693 if (!json_paths) {
8694 /* print prefix and mask */
8695 if (!display)
7d3cae70 8696 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8697 else
ae248832 8698 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8699 } else {
7d3cae70 8700 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8701 }
47fc97cc 8702
9df8b37c
PZ
8703 /*
8704 * If vrf id of nexthop is different from that of prefix,
8705 * set up printable string to append
8706 */
9b6d8fcf 8707 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8708 const char *self = "";
8709
8710 if (nexthop_self)
8711 self = "<";
8712
8713 nexthop_othervrf = true;
9b6d8fcf 8714 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8715
9b6d8fcf 8716 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8717 snprintf(vrf_id_str, sizeof(vrf_id_str),
8718 "@%s%s", VRFID_NONE_STR, self);
8719 else
8720 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8721 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8722
9b6d8fcf
DS
8723 if (path->extra->bgp_orig->inst_type
8724 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8725
9b6d8fcf 8726 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8727 } else {
8728 const char *self = "";
8729
8730 if (nexthop_self)
8731 self = "<";
8732
8733 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8734 }
8735
445c2480
DS
8736 /*
8737 * For ENCAP and EVPN routes, nexthop address family is not
8738 * neccessarily the same as the prefix address family.
8739 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8740 * EVPN routes are also exchanged with a MP nexthop. Currently,
8741 * this
8742 * is only IPv4, the value will be present in either
8743 * attr->nexthop or
8744 * attr->mp_nexthop_global_in
8745 */
8746 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8747 char buf[BUFSIZ];
8748 char nexthop[128];
8749 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8750
8751 switch (af) {
8752 case AF_INET:
772270f3
QY
8753 snprintf(nexthop, sizeof(nexthop), "%s",
8754 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8755 BUFSIZ));
445c2480
DS
8756 break;
8757 case AF_INET6:
772270f3
QY
8758 snprintf(nexthop, sizeof(nexthop), "%s",
8759 inet_ntop(af, &attr->mp_nexthop_global, buf,
8760 BUFSIZ));
445c2480
DS
8761 break;
8762 default:
772270f3 8763 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8764 break;
d62a17ae 8765 }
d62a17ae 8766
445c2480
DS
8767 if (json_paths) {
8768 json_nexthop_global = json_object_new_object();
8769
515c2602
DA
8770 json_object_string_add(json_nexthop_global, "ip",
8771 nexthop);
8772
939a97f4 8773 if (path->peer->hostname)
515c2602
DA
8774 json_object_string_add(json_nexthop_global,
8775 "hostname",
939a97f4 8776 path->peer->hostname);
515c2602
DA
8777
8778 json_object_string_add(json_nexthop_global, "afi",
8779 (af == AF_INET) ? "ipv4"
8780 : "ipv6");
445c2480
DS
8781 json_object_boolean_true_add(json_nexthop_global,
8782 "used");
aef999a2
DA
8783 } else {
8784 if (nexthop_hostname)
8785 len = vty_out(vty, "%s(%s)%s", nexthop,
8786 nexthop_hostname, vrf_id_str);
8787 else
8788 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8789
ae248832 8790 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8791 if (len < 1)
8792 vty_out(vty, "\n%*s", 36, " ");
8793 else
8794 vty_out(vty, "%*s", len, " ");
8795 }
445c2480
DS
8796 } else if (safi == SAFI_EVPN) {
8797 if (json_paths) {
23d0a753
DA
8798 char buf[BUFSIZ] = {0};
8799
445c2480
DS
8800 json_nexthop_global = json_object_new_object();
8801
515c2602 8802 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8803 inet_ntop(AF_INET,
8804 &attr->nexthop, buf,
8805 sizeof(buf)));
515c2602 8806
939a97f4 8807 if (path->peer->hostname)
515c2602
DA
8808 json_object_string_add(json_nexthop_global,
8809 "hostname",
939a97f4 8810 path->peer->hostname);
515c2602 8811
a4d82a8a
PZ
8812 json_object_string_add(json_nexthop_global, "afi",
8813 "ipv4");
445c2480
DS
8814 json_object_boolean_true_add(json_nexthop_global,
8815 "used");
aef999a2
DA
8816 } else {
8817 if (nexthop_hostname)
8818 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8819 nexthop_hostname, vrf_id_str);
8820 else
8821 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8822 vrf_id_str);
8823
ae248832 8824 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8825 if (len < 1)
8826 vty_out(vty, "\n%*s", 36, " ");
8827 else
8828 vty_out(vty, "%*s", len, " ");
8829 }
d33fc23b 8830 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8831 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8832 if (json_paths) {
23d0a753
DA
8833 char buf[BUFSIZ] = {0};
8834
026b914a 8835 json_nexthop_global = json_object_new_object();
515c2602 8836
026b914a
PG
8837 json_object_string_add(json_nexthop_global,
8838 "afi", "ipv4");
515c2602
DA
8839 json_object_string_add(
8840 json_nexthop_global, "ip",
23d0a753
DA
8841 inet_ntop(AF_INET, &attr->nexthop, buf,
8842 sizeof(buf)));
515c2602 8843
939a97f4 8844 if (path->peer->hostname)
515c2602
DA
8845 json_object_string_add(
8846 json_nexthop_global, "hostname",
939a97f4 8847 path->peer->hostname);
515c2602 8848
50e05855
AD
8849 json_object_boolean_true_add(
8850 json_nexthop_global,
026b914a
PG
8851 "used");
8852 } else {
aef999a2
DA
8853 if (nexthop_hostname)
8854 len = vty_out(vty, "%pI4(%s)%s",
8855 &attr->nexthop,
8856 nexthop_hostname,
8857 vrf_id_str);
8858 else
8859 len = vty_out(vty, "%pI4%s",
8860 &attr->nexthop,
8861 vrf_id_str);
8862
ae248832 8863 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8864 if (len < 1)
8865 vty_out(vty, "\n%*s", 36, " ");
8866 else
8867 vty_out(vty, "%*s", len, " ");
026b914a
PG
8868 }
8869 }
d33fc23b 8870 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8871 if (json_paths) {
23d0a753
DA
8872 char buf[BUFSIZ] = {0};
8873
445c2480 8874 json_nexthop_global = json_object_new_object();
d62a17ae 8875
515c2602 8876 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8877 inet_ntop(AF_INET,
8878 &attr->nexthop, buf,
8879 sizeof(buf)));
515c2602 8880
939a97f4 8881 if (path->peer->hostname)
515c2602
DA
8882 json_object_string_add(json_nexthop_global,
8883 "hostname",
939a97f4 8884 path->peer->hostname);
445c2480 8885
a4d82a8a
PZ
8886 json_object_string_add(json_nexthop_global, "afi",
8887 "ipv4");
445c2480
DS
8888 json_object_boolean_true_add(json_nexthop_global,
8889 "used");
8890 } else {
aef999a2
DA
8891 if (nexthop_hostname)
8892 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8893 nexthop_hostname, vrf_id_str);
8894 else
8895 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8896 vrf_id_str);
9df8b37c 8897
ae248832 8898 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8899 if (len < 1)
8900 vty_out(vty, "\n%*s", 36, " ");
8901 else
8902 vty_out(vty, "%*s", len, " ");
d62a17ae 8903 }
445c2480 8904 }
b05a1c8b 8905
445c2480 8906 /* IPv6 Next Hop */
a4d82a8a 8907 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8908 char buf[BUFSIZ];
d62a17ae 8909
445c2480
DS
8910 if (json_paths) {
8911 json_nexthop_global = json_object_new_object();
a4d82a8a 8912 json_object_string_add(
515c2602
DA
8913 json_nexthop_global, "ip",
8914 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8915 buf, BUFSIZ));
8916
939a97f4 8917 if (path->peer->hostname)
515c2602
DA
8918 json_object_string_add(json_nexthop_global,
8919 "hostname",
939a97f4 8920 path->peer->hostname);
515c2602 8921
a4d82a8a
PZ
8922 json_object_string_add(json_nexthop_global, "afi",
8923 "ipv6");
8924 json_object_string_add(json_nexthop_global, "scope",
8925 "global");
445c2480
DS
8926
8927 /* We display both LL & GL if both have been
8928 * received */
0606039c
DA
8929 if ((attr->mp_nexthop_len
8930 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8931 || (path->peer->conf_if)) {
a4d82a8a 8932 json_nexthop_ll = json_object_new_object();
d62a17ae 8933 json_object_string_add(
515c2602
DA
8934 json_nexthop_ll, "ip",
8935 inet_ntop(AF_INET6,
8936 &attr->mp_nexthop_local, buf,
8937 BUFSIZ));
8938
939a97f4 8939 if (path->peer->hostname)
515c2602
DA
8940 json_object_string_add(
8941 json_nexthop_ll, "hostname",
939a97f4 8942 path->peer->hostname);
515c2602 8943
a4d82a8a
PZ
8944 json_object_string_add(json_nexthop_ll, "afi",
8945 "ipv6");
8946 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8947 "link-local");
d62a17ae 8948
a4d82a8a
PZ
8949 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8950 &attr->mp_nexthop_local)
445c2480
DS
8951 != 0)
8952 && !attr->mp_nexthop_prefer_global)
d62a17ae 8953 json_object_boolean_true_add(
a4d82a8a 8954 json_nexthop_ll, "used");
445c2480
DS
8955 else
8956 json_object_boolean_true_add(
a4d82a8a 8957 json_nexthop_global, "used");
445c2480
DS
8958 } else
8959 json_object_boolean_true_add(
8960 json_nexthop_global, "used");
8961 } else {
8962 /* Display LL if LL/Global both in table unless
8963 * prefer-global is set */
0606039c
DA
8964 if (((attr->mp_nexthop_len
8965 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8966 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8967 || (path->peer->conf_if)) {
8968 if (path->peer->conf_if) {
a4d82a8a 8969 len = vty_out(vty, "%s",
9b6d8fcf 8970 path->peer->conf_if);
ae248832
MK
8971 /* len of IPv6 addr + max len of def
8972 * ifname */
8973 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8974
8975 if (len < 1)
a4d82a8a 8976 vty_out(vty, "\n%*s", 36, " ");
445c2480 8977 else
a4d82a8a 8978 vty_out(vty, "%*s", len, " ");
d62a17ae 8979 } else {
aef999a2
DA
8980 if (nexthop_hostname)
8981 len = vty_out(
8982 vty, "%pI6(%s)%s",
8983 &attr->mp_nexthop_local,
8984 nexthop_hostname,
8985 vrf_id_str);
8986 else
8987 len = vty_out(
8988 vty, "%pI6%s",
8989 &attr->mp_nexthop_local,
8990 vrf_id_str);
8991
ae248832 8992 len = wide ? (41 - len) : (16 - len);
d62a17ae 8993
8994 if (len < 1)
a4d82a8a 8995 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8996 else
a4d82a8a 8997 vty_out(vty, "%*s", len, " ");
d62a17ae 8998 }
445c2480 8999 } else {
aef999a2
DA
9000 if (nexthop_hostname)
9001 len = vty_out(vty, "%pI6(%s)%s",
9002 &attr->mp_nexthop_global,
9003 nexthop_hostname,
9004 vrf_id_str);
9005 else
9006 len = vty_out(vty, "%pI6%s",
9007 &attr->mp_nexthop_global,
9008 vrf_id_str);
9009
ae248832 9010 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9011
9012 if (len < 1)
9013 vty_out(vty, "\n%*s", 36, " ");
9014 else
9015 vty_out(vty, "%*s", len, " ");
d62a17ae 9016 }
9017 }
445c2480 9018 }
718e3744 9019
445c2480
DS
9020 /* MED/Metric */
9021 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9022 if (json_paths)
50e05855 9023 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9024 else if (wide)
9025 vty_out(vty, "%7u", attr->med);
0fbac0b4 9026 else
445c2480 9027 vty_out(vty, "%10u", attr->med);
ae248832
MK
9028 else if (!json_paths) {
9029 if (wide)
9030 vty_out(vty, "%*s", 7, " ");
9031 else
9032 vty_out(vty, "%*s", 10, " ");
9033 }
d62a17ae 9034
445c2480
DS
9035 /* Local Pref */
9036 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9037 if (json_paths)
50e05855 9038 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9039 attr->local_pref);
9040 else
445c2480
DS
9041 vty_out(vty, "%7u", attr->local_pref);
9042 else if (!json_paths)
9043 vty_out(vty, " ");
d62a17ae 9044
445c2480
DS
9045 if (json_paths)
9046 json_object_int_add(json_path, "weight", attr->weight);
9047 else
9048 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9049
445c2480
DS
9050 if (json_paths) {
9051 char buf[BUFSIZ];
a4d82a8a
PZ
9052 json_object_string_add(
9053 json_path, "peerId",
9b6d8fcf 9054 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9055 }
b05a1c8b 9056
445c2480
DS
9057 /* Print aspath */
9058 if (attr->aspath) {
0fbac0b4 9059 if (json_paths)
50e05855 9060 json_object_string_add(json_path, "path",
0fbac0b4
DA
9061 attr->aspath->str);
9062 else
445c2480 9063 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9064 }
f1aa5d8a 9065
445c2480
DS
9066 /* Print origin */
9067 if (json_paths)
a4d82a8a
PZ
9068 json_object_string_add(json_path, "origin",
9069 bgp_origin_long_str[attr->origin]);
445c2480
DS
9070 else
9071 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9072
9df8b37c 9073 if (json_paths) {
d071f237 9074 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9075 json_object_string_add(json_path, "esi",
9076 esi_to_str(&attr->esi,
9077 esi_buf, sizeof(esi_buf)));
9078 }
6f214dd3
CS
9079 if (safi == SAFI_EVPN &&
9080 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9081 json_ext_community = json_object_new_object();
9082 json_object_string_add(json_ext_community,
9083 "string",
9084 attr->ecommunity->str);
9085 json_object_object_add(json_path,
9086 "extendedCommunity",
9087 json_ext_community);
9088 }
9089
9df8b37c
PZ
9090 if (nexthop_self)
9091 json_object_boolean_true_add(json_path,
9092 "announceNexthopSelf");
9093 if (nexthop_othervrf) {
9094 json_object_string_add(json_path, "nhVrfName",
9095 nexthop_vrfname);
9096
9097 json_object_int_add(json_path, "nhVrfId",
9098 ((nexthop_vrfid == VRF_UNKNOWN)
9099 ? -1
9100 : (int)nexthop_vrfid));
9101 }
9102 }
9103
d62a17ae 9104 if (json_paths) {
9105 if (json_nexthop_global || json_nexthop_ll) {
9106 json_nexthops = json_object_new_array();
f1aa5d8a 9107
d62a17ae 9108 if (json_nexthop_global)
9109 json_object_array_add(json_nexthops,
9110 json_nexthop_global);
f1aa5d8a 9111
d62a17ae 9112 if (json_nexthop_ll)
9113 json_object_array_add(json_nexthops,
9114 json_nexthop_ll);
f1aa5d8a 9115
d62a17ae 9116 json_object_object_add(json_path, "nexthops",
9117 json_nexthops);
9118 }
9119
9120 json_object_array_add(json_paths, json_path);
9121 } else {
9122 vty_out(vty, "\n");
6f214dd3 9123
b5e140c8 9124 if (safi == SAFI_EVPN) {
229587fb
AK
9125 struct bgp_path_es_info *path_es_info = NULL;
9126
d071f237 9127 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9128 /* XXX - add these params to the json out */
b5e140c8 9129 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9130 vty_out(vty, "ESI:%s",
9131 esi_to_str(&attr->esi, esi_buf,
9132 sizeof(esi_buf)));
60605cbc
AK
9133
9134 if (path->extra && path->extra->mh_info)
9135 path_es_info =
9136 path->extra->mh_info->es_info;
9137
229587fb
AK
9138 if (path_es_info && path_es_info->es)
9139 vty_out(vty, " VNI: %u",
9140 path_es_info->vni);
9141 vty_out(vty, "\n");
b5e140c8
AK
9142 }
9143 if (attr->flag &
9144 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9145 vty_out(vty, "%*s", 20, " ");
9146 vty_out(vty, "%s\n", attr->ecommunity->str);
9147 }
6f214dd3
CS
9148 }
9149
49e5a4a0 9150#ifdef ENABLE_BGP_VNC
d62a17ae 9151 /* prints an additional line, indented, with VNC info, if
9152 * present */
9153 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9154 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9155#endif
d62a17ae 9156 }
9157}
718e3744 9158
9159/* called from terminal list command */
7d3cae70
DA
9160void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9161 const struct prefix *p, struct attr *attr, safi_t safi,
9162 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9163{
9164 json_object *json_status = NULL;
9165 json_object *json_net = NULL;
aef999a2 9166 int len;
d62a17ae 9167 char buff[BUFSIZ];
dc387b0f 9168
d62a17ae 9169 /* Route status display. */
9170 if (use_json) {
9171 json_status = json_object_new_object();
9172 json_net = json_object_new_object();
9173 } else {
9174 vty_out(vty, "*");
9175 vty_out(vty, ">");
9176 vty_out(vty, " ");
9177 }
718e3744 9178
d62a17ae 9179 /* print prefix and mask */
50e05855 9180 if (use_json) {
dc387b0f
LK
9181 if (safi == SAFI_EVPN)
9182 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9183 else if (p->family == AF_INET || p->family == AF_INET6) {
9184 json_object_string_add(
9185 json_net, "addrPrefix",
9186 inet_ntop(p->family, &p->u.prefix, buff,
9187 BUFSIZ));
9188 json_object_int_add(json_net, "prefixLen",
9189 p->prefixlen);
9190 prefix2str(p, buff, PREFIX_STRLEN);
9191 json_object_string_add(json_net, "network", buff);
9192 }
50e05855 9193 } else
7d3cae70 9194 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9195
9196 /* Print attribute */
9197 if (attr) {
9198 if (use_json) {
23d0a753
DA
9199 char buf[BUFSIZ] = {0};
9200
d62a17ae 9201 if (p->family == AF_INET
9202 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9203 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9204 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 9205 json_object_string_add(
9206 json_net, "nextHop",
23d0a753
DA
9207 inet_ntop(
9208 AF_INET,
9209 &attr->mp_nexthop_global_in,
9210 buf, sizeof(buf)));
d62a17ae 9211 else
9212 json_object_string_add(
9213 json_net, "nextHop",
23d0a753
DA
9214 inet_ntop(AF_INET,
9215 &attr->nexthop, buf,
9216 sizeof(buf)));
d62a17ae 9217 } else if (p->family == AF_INET6
9218 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9219 char buf[BUFSIZ];
9220
9221 json_object_string_add(
aa0a10fc 9222 json_net, "nextHopGlobal",
d62a17ae 9223 inet_ntop(AF_INET6,
9224 &attr->mp_nexthop_global, buf,
9225 BUFSIZ));
23d0a753
DA
9226 } else if (p->family == AF_EVPN
9227 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9228 char buf[BUFSIZ] = {0};
9229
9230 json_object_string_add(
9231 json_net, "nextHop",
9232 inet_ntop(AF_INET,
9233 &attr->mp_nexthop_global_in,
9234 buf, sizeof(buf)));
9235 }
d62a17ae 9236
9237 if (attr->flag
9238 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9239 json_object_int_add(json_net, "metric",
9240 attr->med);
9241
0fbac0b4 9242 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9243 json_object_int_add(json_net, "locPrf",
0fbac0b4 9244 attr->local_pref);
d62a17ae 9245
9246 json_object_int_add(json_net, "weight", attr->weight);
9247
9248 /* Print aspath */
0fbac0b4 9249 if (attr->aspath)
50e05855 9250 json_object_string_add(json_net, "path",
0fbac0b4 9251 attr->aspath->str);
d62a17ae 9252
9253 /* Print origin */
9254 json_object_string_add(json_net, "bgpOriginCode",
9255 bgp_origin_str[attr->origin]);
9256 } else {
9257 if (p->family == AF_INET
9258 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9259 || safi == SAFI_EVPN
9260 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9261 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9262 || safi == SAFI_EVPN)
23d0a753
DA
9263 vty_out(vty, "%-16pI4",
9264 &attr->mp_nexthop_global_in);
ae248832 9265 else if (wide)
23d0a753 9266 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9267 else
23d0a753 9268 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9269 } else if (p->family == AF_INET6
9270 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9271 char buf[BUFSIZ];
9272
9273 len = vty_out(
9274 vty, "%s",
9275 inet_ntop(AF_INET6,
9276 &attr->mp_nexthop_global, buf,
9277 BUFSIZ));
ae248832 9278 len = wide ? (41 - len) : (16 - len);
d62a17ae 9279 if (len < 1)
9280 vty_out(vty, "\n%*s", 36, " ");
9281 else
9282 vty_out(vty, "%*s", len, " ");
9283 }
9284 if (attr->flag
9285 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9286 if (wide)
9287 vty_out(vty, "%7u", attr->med);
9288 else
9289 vty_out(vty, "%10u", attr->med);
9290 else if (wide)
9291 vty_out(vty, " ");
d62a17ae 9292 else
9293 vty_out(vty, " ");
718e3744 9294
d62a17ae 9295 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9296 vty_out(vty, "%7u", attr->local_pref);
9297 else
9298 vty_out(vty, " ");
9299
9300 vty_out(vty, "%7u ", attr->weight);
9301
9302 /* Print aspath */
9303 if (attr->aspath)
9304 aspath_print_vty(vty, "%s", attr->aspath, " ");
9305
9306 /* Print origin */
9307 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9308 }
9309 }
9310 if (use_json) {
9311 json_object_boolean_true_add(json_status, "*");
9312 json_object_boolean_true_add(json_status, ">");
9313 json_object_object_add(json_net, "appliedStatusSymbols",
9314 json_status);
1608ff77 9315
dc387b0f
LK
9316 prefix2str(p, buff, PREFIX_STRLEN);
9317 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9318 } else
9319 vty_out(vty, "\n");
9320}
9321
bd494ec5 9322void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9323 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9324 json_object *json)
9325{
9326 json_object *json_out = NULL;
9327 struct attr *attr;
9328 mpls_label_t label = MPLS_INVALID_LABEL;
9329
9b6d8fcf 9330 if (!path->extra)
d62a17ae 9331 return;
9332
9333 if (json)
9334 json_out = json_object_new_object();
9335
9336 /* short status lead text */
82c298be 9337 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9338
9339 /* print prefix and mask */
9340 if (json == NULL) {
9341 if (!display)
7d3cae70 9342 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9343 else
9344 vty_out(vty, "%*s", 17, " ");
9345 }
9346
9347 /* Print attribute */
9b6d8fcf 9348 attr = path->attr;
05864da7
DS
9349 if (((p->family == AF_INET)
9350 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9351 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9352 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9353 char buf[BUFSIZ] = {0};
9354
05864da7
DS
9355 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9356 || safi == SAFI_EVPN) {
9357 if (json)
9358 json_object_string_add(
9359 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9360 inet_ntop(AF_INET,
9361 &attr->mp_nexthop_global_in,
9362 buf, sizeof(buf)));
05864da7 9363 else
23d0a753
DA
9364 vty_out(vty, "%-16pI4",
9365 &attr->mp_nexthop_global_in);
05864da7
DS
9366 } else {
9367 if (json)
9368 json_object_string_add(
9369 json_out, "nexthop",
23d0a753
DA
9370 inet_ntop(AF_INET, &attr->nexthop, buf,
9371 sizeof(buf)));
05864da7 9372 else
23d0a753 9373 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9374 }
9375 } else if (((p->family == AF_INET6)
9376 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9377 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9378 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9379 char buf_a[512];
9380
9381 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9382 if (json)
9383 json_object_string_add(
9384 json_out, "mpNexthopGlobalIn",
9385 inet_ntop(AF_INET6,
9386 &attr->mp_nexthop_global,
9387 buf_a, sizeof(buf_a)));
9388 else
9389 vty_out(vty, "%s",
9390 inet_ntop(AF_INET6,
9391 &attr->mp_nexthop_global,
9392 buf_a, sizeof(buf_a)));
9393 } else if (attr->mp_nexthop_len
9394 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9395 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9396 &attr->mp_nexthop_global,
9397 &attr->mp_nexthop_local);
9398 if (json)
9399 json_object_string_add(json_out,
9400 "mpNexthopGlobalLocal",
9401 buf_a);
9402 else
9403 vty_out(vty, "%s", buf_a);
d62a17ae 9404 }
9405 }
9406
9b6d8fcf 9407 label = decode_label(&path->extra->label[0]);
d62a17ae 9408
9409 if (bgp_is_valid_label(&label)) {
9410 if (json) {
9411 json_object_int_add(json_out, "notag", label);
9412 json_object_array_add(json, json_out);
9413 } else {
9414 vty_out(vty, "notag/%d", label);
9415 vty_out(vty, "\n");
9416 }
9417 }
9418}
718e3744 9419
bd494ec5 9420void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9421 struct bgp_path_info *path, int display,
d62a17ae 9422 json_object *json_paths)
718e3744 9423{
d62a17ae 9424 struct attr *attr;
14f51eba 9425 char buf[BUFSIZ] = {0};
d62a17ae 9426 json_object *json_path = NULL;
14f51eba
LK
9427 json_object *json_nexthop = NULL;
9428 json_object *json_overlay = NULL;
856ca177 9429
9b6d8fcf 9430 if (!path->extra)
d62a17ae 9431 return;
718e3744 9432
14f51eba
LK
9433 if (json_paths) {
9434 json_path = json_object_new_object();
9435 json_overlay = json_object_new_object();
9436 json_nexthop = json_object_new_object();
9437 }
9438
d62a17ae 9439 /* short status lead text */
82c298be 9440 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9441
d62a17ae 9442 /* print prefix and mask */
9443 if (!display)
7d3cae70 9444 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9445 else
9446 vty_out(vty, "%*s", 17, " ");
9447
9448 /* Print attribute */
9b6d8fcf 9449 attr = path->attr;
05864da7
DS
9450 char buf1[BUFSIZ];
9451 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9452
05864da7
DS
9453 switch (af) {
9454 case AF_INET:
9455 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9456 if (!json_path) {
9457 vty_out(vty, "%-16s", buf);
9458 } else {
9459 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9460
05864da7 9461 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9462
05864da7
DS
9463 json_object_object_add(json_path, "nexthop",
9464 json_nexthop);
9465 }
9466 break;
9467 case AF_INET6:
9468 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9469 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9470 if (!json_path) {
9471 vty_out(vty, "%s(%s)", buf, buf1);
9472 } else {
9473 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9474
05864da7
DS
9475 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9476 buf1);
14f51eba 9477
05864da7 9478 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9479
05864da7
DS
9480 json_object_object_add(json_path, "nexthop",
9481 json_nexthop);
9482 }
9483 break;
9484 default:
9485 if (!json_path) {
9486 vty_out(vty, "?");
9487 } else {
9488 json_object_string_add(json_nexthop, "Error",
9489 "Unsupported address-family");
d62a17ae 9490 }
05864da7 9491 }
988258b4 9492
6c924775
DS
9493 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9494
9495 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9496 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9497 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9498 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9499
05864da7
DS
9500 if (!json_path)
9501 vty_out(vty, "/%s", buf);
9502 else
9503 json_object_string_add(json_overlay, "gw", buf);
9504
9505 if (attr->ecommunity) {
9506 char *mac = NULL;
9507 struct ecommunity_val *routermac = ecommunity_lookup(
9508 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9509 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9510
9511 if (routermac)
9512 mac = ecom_mac2str((char *)routermac->val);
9513 if (mac) {
9514 if (!json_path) {
c4efd0f4 9515 vty_out(vty, "/%s", mac);
05864da7
DS
9516 } else {
9517 json_object_string_add(json_overlay, "rmac",
9518 mac);
988258b4 9519 }
05864da7 9520 XFREE(MTYPE_TMP, mac);
988258b4 9521 }
05864da7 9522 }
718e3744 9523
05864da7
DS
9524 if (!json_path) {
9525 vty_out(vty, "\n");
9526 } else {
9527 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9528
05864da7 9529 json_object_array_add(json_paths, json_path);
14f51eba 9530 }
d62a17ae 9531}
718e3744 9532
d62a17ae 9533/* dampening route */
5f040085
DS
9534static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9535 struct bgp_path_info *path, int display,
9536 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9537 json_object *json_paths)
d62a17ae 9538{
e5be8c1d 9539 struct attr *attr = path->attr;
d62a17ae 9540 int len;
9541 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9542 json_object *json_path = NULL;
9543
9544 if (use_json)
9545 json_path = json_object_new_object();
d62a17ae 9546
9547 /* short status lead text */
e5be8c1d 9548 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9549
9550 /* print prefix and mask */
9551 if (!use_json) {
9552 if (!display)
7d3cae70 9553 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9554 else
9555 vty_out(vty, "%*s", 17, " ");
d62a17ae 9556
e5be8c1d
DA
9557 len = vty_out(vty, "%s", path->peer->host);
9558 len = 17 - len;
9559
9560 if (len < 1)
d62a17ae 9561 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9562 else
9563 vty_out(vty, "%*s", len, " ");
d62a17ae 9564
9b6d8fcf
DS
9565 vty_out(vty, "%s ",
9566 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9567 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9568 use_json, NULL));
d62a17ae 9569
e5be8c1d 9570 if (attr->aspath)
05864da7 9571 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9572
05864da7
DS
9573 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9574
d62a17ae 9575 vty_out(vty, "\n");
e5be8c1d
DA
9576 } else {
9577 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9578 safi, use_json, json_path);
9579
9580 if (attr->aspath)
9581 json_object_string_add(json_path, "asPath",
9582 attr->aspath->str);
9583
9584 json_object_string_add(json_path, "origin",
9585 bgp_origin_str[attr->origin]);
9586 json_object_string_add(json_path, "peerHost", path->peer->host);
9587
9588 json_object_array_add(json_paths, json_path);
9589 }
d62a17ae 9590}
718e3744 9591
d62a17ae 9592/* flap route */
5f040085
DS
9593static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9594 struct bgp_path_info *path, int display,
9595 afi_t afi, safi_t safi, bool use_json,
31258046 9596 json_object *json_paths)
784d3a42 9597{
31258046 9598 struct attr *attr = path->attr;
d62a17ae 9599 struct bgp_damp_info *bdi;
9600 char timebuf[BGP_UPTIME_LEN];
9601 int len;
31258046 9602 json_object *json_path = NULL;
784d3a42 9603
9b6d8fcf 9604 if (!path->extra)
d62a17ae 9605 return;
784d3a42 9606
31258046
DA
9607 if (use_json)
9608 json_path = json_object_new_object();
9609
9b6d8fcf 9610 bdi = path->extra->damp_info;
784d3a42 9611
d62a17ae 9612 /* short status lead text */
31258046 9613 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9614
d62a17ae 9615 if (!use_json) {
9616 if (!display)
7d3cae70 9617 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9618 else
9619 vty_out(vty, "%*s", 17, " ");
784d3a42 9620
31258046
DA
9621 len = vty_out(vty, "%s", path->peer->host);
9622 len = 16 - len;
9623 if (len < 1)
d62a17ae 9624 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9625 else
9626 vty_out(vty, "%*s", len, " ");
784d3a42 9627
31258046
DA
9628 len = vty_out(vty, "%d", bdi->flap);
9629 len = 5 - len;
9630 if (len < 1)
d62a17ae 9631 vty_out(vty, " ");
d62a17ae 9632 else
9633 vty_out(vty, "%*s", len, " ");
d62a17ae 9634
996c9314
LB
9635 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9636 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9637
31258046
DA
9638 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9639 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9640 vty_out(vty, "%s ",
9b6d8fcf 9641 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9642 BGP_UPTIME_LEN, afi,
31258046
DA
9643 safi, use_json, NULL));
9644 else
d62a17ae 9645 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9646
31258046 9647 if (attr->aspath)
05864da7 9648 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9649
05864da7
DS
9650 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9651
d62a17ae 9652 vty_out(vty, "\n");
31258046
DA
9653 } else {
9654 json_object_string_add(json_path, "peerHost", path->peer->host);
9655 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9656
9657 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9658 json_path);
9659
9660 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9661 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9662 bgp_damp_reuse_time_vty(vty, path, timebuf,
9663 BGP_UPTIME_LEN, afi, safi,
9664 use_json, json_path);
9665
9666 if (attr->aspath)
9667 json_object_string_add(json_path, "asPath",
9668 attr->aspath->str);
9669
9670 json_object_string_add(json_path, "origin",
9671 bgp_origin_str[attr->origin]);
9672
9673 json_object_array_add(json_paths, json_path);
9674 }
d62a17ae 9675}
9676
9677static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9678 int *first, const char *header,
9679 json_object *json_adv_to)
9680{
9681 char buf1[INET6_ADDRSTRLEN];
9682 json_object *json_peer = NULL;
9683
9684 if (json_adv_to) {
9685 /* 'advertised-to' is a dictionary of peers we have advertised
9686 * this
9687 * prefix too. The key is the peer's IP or swpX, the value is
9688 * the
9689 * hostname if we know it and "" if not.
9690 */
9691 json_peer = json_object_new_object();
9692
9693 if (peer->hostname)
9694 json_object_string_add(json_peer, "hostname",
9695 peer->hostname);
9696
9697 if (peer->conf_if)
9698 json_object_object_add(json_adv_to, peer->conf_if,
9699 json_peer);
9700 else
9701 json_object_object_add(
9702 json_adv_to,
9703 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9704 json_peer);
9705 } else {
9706 if (*first) {
9707 vty_out(vty, "%s", header);
9708 *first = 0;
9709 }
9710
9711 if (peer->hostname
892fedb6 9712 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9713 if (peer->conf_if)
9714 vty_out(vty, " %s(%s)", peer->hostname,
9715 peer->conf_if);
9716 else
9717 vty_out(vty, " %s(%s)", peer->hostname,
9718 sockunion2str(&peer->su, buf1,
9719 SU_ADDRSTRLEN));
9720 } else {
9721 if (peer->conf_if)
9722 vty_out(vty, " %s", peer->conf_if);
9723 else
9724 vty_out(vty, " %s",
9725 sockunion2str(&peer->su, buf1,
9726 SU_ADDRSTRLEN));
9727 }
9728 }
784d3a42
PG
9729}
9730
dcc68b5e
MS
9731static void route_vty_out_tx_ids(struct vty *vty,
9732 struct bgp_addpath_info_data *d)
9733{
9734 int i;
9735
9736 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9737 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9738 d->addpath_tx_id[i],
9739 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9740 }
9741}
9742
5e4d4c8a 9743static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9744 struct bgp_path_info *pi,
9745 struct attr *attr,
9746 json_object *json_path)
5e4d4c8a
AK
9747{
9748 char esi_buf[ESI_STR_LEN];
9749 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9750 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9751 ATTR_ES_PEER_ROUTER);
9752 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9753 ATTR_ES_PEER_ACTIVE);
9754 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9755 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9756 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9757 if (json_path) {
9758 json_object *json_es_info = NULL;
9759
9760 json_object_string_add(
9761 json_path, "esi",
9762 esi_buf);
9763 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9764 json_es_info = json_object_new_object();
9765 if (es_local)
9766 json_object_boolean_true_add(
9767 json_es_info, "localEs");
9768 if (peer_active)
9769 json_object_boolean_true_add(
9770 json_es_info, "peerActive");
9771 if (peer_proxy)
9772 json_object_boolean_true_add(
9773 json_es_info, "peerProxy");
9774 if (peer_router)
9775 json_object_boolean_true_add(
9776 json_es_info, "peerRouter");
9777 if (attr->mm_sync_seqnum)
9778 json_object_int_add(
9779 json_es_info, "peerSeq",
9780 attr->mm_sync_seqnum);
9781 json_object_object_add(
9782 json_path, "es_info",
9783 json_es_info);
9784 }
9785 } else {
9786 if (bgp_evpn_attr_is_sync(attr))
9787 vty_out(vty,
9788 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9789 esi_buf,
9790 es_local ? "local-es":"",
9791 peer_proxy ? "proxy " : "",
9792 peer_active ? "active ":"",
9793 peer_router ? "router ":"",
9794 attr->mm_sync_seqnum);
9795 else
9796 vty_out(vty, " ESI %s %s\n",
9797 esi_buf,
9798 es_local ? "local-es":"");
9799 }
9800}
9801
4933eaaf
DS
9802void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9803 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9804 enum rpki_states rpki_curr_state,
9805 json_object *json_paths)
d62a17ae 9806{
9807 char buf[INET6_ADDRSTRLEN];
9808 char buf1[BUFSIZ];
515c2602 9809 struct attr *attr = path->attr;
d62a17ae 9810 int sockunion_vty_out(struct vty *, union sockunion *);
9811 time_t tbuf;
9812 json_object *json_bestpath = NULL;
9813 json_object *json_cluster_list = NULL;
9814 json_object *json_cluster_list_list = NULL;
9815 json_object *json_ext_community = NULL;
9816 json_object *json_last_update = NULL;
7fd077aa 9817 json_object *json_pmsi = NULL;
d62a17ae 9818 json_object *json_nexthop_global = NULL;
9819 json_object *json_nexthop_ll = NULL;
9820 json_object *json_nexthops = NULL;
9821 json_object *json_path = NULL;
9822 json_object *json_peer = NULL;
9823 json_object *json_string = NULL;
9824 json_object *json_adv_to = NULL;
9825 int first = 0;
9826 struct listnode *node, *nnode;
9827 struct peer *peer;
9828 int addpath_capable;
9829 int has_adj;
9830 unsigned int first_as;
1defdda8 9831 bool nexthop_self =
9b6d8fcf 9832 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9833 int i;
2ba93fd6
DA
9834 char *nexthop_hostname =
9835 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9836
9837 if (json_paths) {
9838 json_path = json_object_new_object();
9839 json_peer = json_object_new_object();
9840 json_nexthop_global = json_object_new_object();
9841 }
9842
8304dabf
AD
9843 if (safi == SAFI_EVPN) {
9844 if (!json_paths)
9845 vty_out(vty, " Route %pRN", bn);
9846 }
9847
44c69747 9848 if (path->extra) {
b57ba6d2 9849 char tag_buf[30];
d62a17ae 9850
d62a17ae 9851 tag_buf[0] = '\0';
9b6d8fcf
DS
9852 if (path->extra && path->extra->num_labels) {
9853 bgp_evpn_label2str(path->extra->label,
9854 path->extra->num_labels, tag_buf,
a4d82a8a 9855 sizeof(tag_buf));
d62a17ae 9856 }
d7325ee7 9857 if (safi == SAFI_EVPN) {
44c69747 9858 if (!json_paths) {
44c69747
LK
9859 if (tag_buf[0] != '\0')
9860 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9861 } else {
9862 if (tag_buf[0])
9863 json_object_string_add(json_path, "VNI",
9864 tag_buf);
9865 }
d7325ee7
DD
9866 }
9867
44c69747 9868 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9869 struct bgp_path_info *parent_ri;
9bcb3eef 9870 struct bgp_dest *dest, *pdest;
d62a17ae 9871
9b6d8fcf 9872 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9873 dest = parent_ri->net;
9874 if (dest && dest->pdest) {
9875 pdest = dest->pdest;
9876 prefix_rd2str(
9877 (struct prefix_rd *)bgp_dest_get_prefix(
9878 pdest),
9879 buf1, sizeof(buf1));
d7325ee7 9880 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9881 vty_out(vty,
58bff4d1 9882 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9883 buf1,
9884 (struct prefix_evpn *)
9885 bgp_dest_get_prefix(
9886 dest),
9887 tag_buf);
58bff4d1
AK
9888 if (attr->es_flags & ATTR_ES_L3_NHG)
9889 vty_out(vty, ", L3NHG %s",
9890 (attr->es_flags
9891 & ATTR_ES_L3_NHG_ACTIVE)
9892 ? "active"
9893 : "inactive");
9894 vty_out(vty, "\n");
9895
d7325ee7 9896 } else
2dbe669b
DA
9897 vty_out(vty,
9898 " Imported from %s:%pFX\n",
9899 buf1,
9900 (struct prefix_evpn *)
9901 bgp_dest_get_prefix(
9902 dest));
d62a17ae 9903 }
9904 }
9905 }
d62a17ae 9906
8304dabf
AD
9907 if (safi == SAFI_EVPN
9908 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9909 char gwip_buf[INET6_ADDRSTRLEN];
9910
9911 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9912 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9913 gwip_buf, sizeof(gwip_buf));
9914 else
9915 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9916 gwip_buf, sizeof(gwip_buf));
9917
9918 if (json_paths)
9919 json_object_string_add(json_path, "gatewayIP",
9920 gwip_buf);
9921 else
9922 vty_out(vty, " Gateway IP %s", gwip_buf);
9923 }
9924
9925 if (safi == SAFI_EVPN)
9926 vty_out(vty, "\n");
9927
05864da7
DS
9928 /* Line1 display AS-path, Aggregator */
9929 if (attr->aspath) {
9930 if (json_paths) {
9931 if (!attr->aspath->json)
9932 aspath_str_update(attr->aspath, true);
9933 json_object_lock(attr->aspath->json);
9934 json_object_object_add(json_path, "aspath",
9935 attr->aspath->json);
9936 } else {
9937 if (attr->aspath->segments)
9938 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9939 else
05864da7 9940 vty_out(vty, " Local");
d62a17ae 9941 }
05864da7 9942 }
d62a17ae 9943
05864da7
DS
9944 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9945 if (json_paths)
9946 json_object_boolean_true_add(json_path, "removed");
9947 else
9948 vty_out(vty, ", (removed)");
9949 }
d62a17ae 9950
05864da7
DS
9951 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9952 if (json_paths)
9953 json_object_boolean_true_add(json_path, "stale");
9954 else
9955 vty_out(vty, ", (stale)");
9956 }
d62a17ae 9957
05864da7
DS
9958 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9959 if (json_paths) {
23d0a753
DA
9960 char buf[BUFSIZ] = {0};
9961
05864da7
DS
9962 json_object_int_add(json_path, "aggregatorAs",
9963 attr->aggregator_as);
23d0a753
DA
9964 json_object_string_add(json_path, "aggregatorId",
9965 inet_ntop(AF_INET,
9966 &attr->aggregator_addr,
9967 buf, sizeof(buf)));
05864da7 9968 } else {
88d495a9
DA
9969 vty_out(vty, ", (aggregated by %u %pI4)",
9970 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9971 }
05864da7 9972 }
d62a17ae 9973
05864da7
DS
9974 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9975 PEER_FLAG_REFLECTOR_CLIENT)) {
9976 if (json_paths)
9977 json_object_boolean_true_add(json_path,
9978 "rxedFromRrClient");
9979 else
9980 vty_out(vty, ", (Received from a RR-client)");
9981 }
d62a17ae 9982
05864da7
DS
9983 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9984 PEER_FLAG_RSERVER_CLIENT)) {
9985 if (json_paths)
9986 json_object_boolean_true_add(json_path,
9987 "rxedFromRsClient");
9988 else
9989 vty_out(vty, ", (Received from a RS-client)");
9990 }
d62a17ae 9991
05864da7
DS
9992 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9993 if (json_paths)
9994 json_object_boolean_true_add(json_path,
9995 "dampeningHistoryEntry");
9996 else
9997 vty_out(vty, ", (history entry)");
9998 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9999 if (json_paths)
10000 json_object_boolean_true_add(json_path,
10001 "dampeningSuppressed");
10002 else
10003 vty_out(vty, ", (suppressed due to dampening)");
10004 }
d62a17ae 10005
05864da7
DS
10006 if (!json_paths)
10007 vty_out(vty, "\n");
d62a17ae 10008
05864da7
DS
10009 /* Line2 display Next-hop, Neighbor, Router-id */
10010 /* Display the nexthop */
9bcb3eef 10011 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10012
10013 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10014 || bn_p->family == AF_EVPN)
05864da7
DS
10015 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10016 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
10017 char buf[BUFSIZ] = {0};
10018
05864da7
DS
10019 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10020 || safi == SAFI_EVPN) {
515c2602 10021 if (json_paths) {
d62a17ae 10022 json_object_string_add(
515c2602 10023 json_nexthop_global, "ip",
23d0a753
DA
10024 inet_ntop(AF_INET,
10025 &attr->mp_nexthop_global_in,
10026 buf, sizeof(buf)));
515c2602 10027
939a97f4 10028 if (path->peer->hostname)
515c2602
DA
10029 json_object_string_add(
10030 json_nexthop_global, "hostname",
939a97f4 10031 path->peer->hostname);
aef999a2
DA
10032 } else {
10033 if (nexthop_hostname)
10034 vty_out(vty, " %pI4(%s)",
10035 &attr->mp_nexthop_global_in,
10036 nexthop_hostname);
10037 else
10038 vty_out(vty, " %pI4",
10039 &attr->mp_nexthop_global_in);
10040 }
d62a17ae 10041 } else {
515c2602 10042 if (json_paths) {
05864da7 10043 json_object_string_add(
515c2602 10044 json_nexthop_global, "ip",
23d0a753
DA
10045 inet_ntop(AF_INET, &attr->nexthop, buf,
10046 sizeof(buf)));
515c2602 10047
939a97f4 10048 if (path->peer->hostname)
515c2602
DA
10049 json_object_string_add(
10050 json_nexthop_global, "hostname",
939a97f4 10051 path->peer->hostname);
aef999a2
DA
10052 } else {
10053 if (nexthop_hostname)
10054 vty_out(vty, " %pI4(%s)",
10055 &attr->nexthop,
10056 nexthop_hostname);
10057 else
10058 vty_out(vty, " %pI4",
10059 &attr->nexthop);
10060 }
d62a17ae 10061 }
10062
05864da7
DS
10063 if (json_paths)
10064 json_object_string_add(json_nexthop_global, "afi",
10065 "ipv4");
10066 } else {
10067 if (json_paths) {
10068 json_object_string_add(
515c2602
DA
10069 json_nexthop_global, "ip",
10070 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
10071 buf, INET6_ADDRSTRLEN));
10072
939a97f4 10073 if (path->peer->hostname)
515c2602
DA
10074 json_object_string_add(json_nexthop_global,
10075 "hostname",
939a97f4 10076 path->peer->hostname);
515c2602 10077
05864da7
DS
10078 json_object_string_add(json_nexthop_global, "afi",
10079 "ipv6");
10080 json_object_string_add(json_nexthop_global, "scope",
10081 "global");
10082 } else {
aef999a2
DA
10083 if (nexthop_hostname)
10084 vty_out(vty, " %pI6(%s)",
10085 &attr->mp_nexthop_global,
10086 nexthop_hostname);
10087 else
10088 vty_out(vty, " %pI6",
10089 &attr->mp_nexthop_global);
d62a17ae 10090 }
05864da7 10091 }
d62a17ae 10092
05864da7
DS
10093 /* Display the IGP cost or 'inaccessible' */
10094 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10095 if (json_paths)
10096 json_object_boolean_false_add(json_nexthop_global,
10097 "accessible");
10098 else
10099 vty_out(vty, " (inaccessible)");
10100 } else {
10101 if (path->extra && path->extra->igpmetric) {
d62a17ae 10102 if (json_paths)
05864da7
DS
10103 json_object_int_add(json_nexthop_global,
10104 "metric",
10105 path->extra->igpmetric);
d62a17ae 10106 else
05864da7
DS
10107 vty_out(vty, " (metric %u)",
10108 path->extra->igpmetric);
d62a17ae 10109 }
10110
05864da7 10111 /* IGP cost is 0, display this only for json */
d62a17ae 10112 else {
d62a17ae 10113 if (json_paths)
05864da7
DS
10114 json_object_int_add(json_nexthop_global,
10115 "metric", 0);
d62a17ae 10116 }
d62a17ae 10117
05864da7
DS
10118 if (json_paths)
10119 json_object_boolean_true_add(json_nexthop_global,
10120 "accessible");
10121 }
d62a17ae 10122
05864da7
DS
10123 /* Display peer "from" output */
10124 /* This path was originated locally */
10125 if (path->peer == bgp->peer_self) {
d62a17ae 10126
05864da7 10127 if (safi == SAFI_EVPN
b54892e0 10128 || (bn_p->family == AF_INET
05864da7 10129 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10130 if (json_paths)
05864da7
DS
10131 json_object_string_add(json_peer, "peerId",
10132 "0.0.0.0");
d62a17ae 10133 else
05864da7
DS
10134 vty_out(vty, " from 0.0.0.0 ");
10135 } else {
d62a17ae 10136 if (json_paths)
05864da7
DS
10137 json_object_string_add(json_peer, "peerId",
10138 "::");
d62a17ae 10139 else
05864da7 10140 vty_out(vty, " from :: ");
d62a17ae 10141 }
d62a17ae 10142
23d0a753
DA
10143 if (json_paths) {
10144 char buf[BUFSIZ] = {0};
10145
05864da7 10146 json_object_string_add(json_peer, "routerId",
23d0a753
DA
10147 inet_ntop(AF_INET,
10148 &bgp->router_id, buf,
10149 sizeof(buf)));
10150 } else {
10151 vty_out(vty, "(%pI4)", &bgp->router_id);
10152 }
05864da7 10153 }
d62a17ae 10154
05864da7
DS
10155 /* We RXed this path from one of our peers */
10156 else {
10157
10158 if (json_paths) {
10159 json_object_string_add(json_peer, "peerId",
10160 sockunion2str(&path->peer->su,
10161 buf,
10162 SU_ADDRSTRLEN));
10163 json_object_string_add(json_peer, "routerId",
10164 inet_ntop(AF_INET,
10165 &path->peer->remote_id,
10166 buf1, sizeof(buf1)));
10167
10168 if (path->peer->hostname)
10169 json_object_string_add(json_peer, "hostname",
10170 path->peer->hostname);
10171
10172 if (path->peer->domainname)
10173 json_object_string_add(json_peer, "domainname",
10174 path->peer->domainname);
10175
10176 if (path->peer->conf_if)
10177 json_object_string_add(json_peer, "interface",
10178 path->peer->conf_if);
10179 } else {
10180 if (path->peer->conf_if) {
10181 if (path->peer->hostname
892fedb6
DA
10182 && CHECK_FLAG(path->peer->bgp->flags,
10183 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10184 vty_out(vty, " from %s(%s)",
10185 path->peer->hostname,
10186 path->peer->conf_if);
d62a17ae 10187 else
05864da7 10188 vty_out(vty, " from %s",
9b6d8fcf 10189 path->peer->conf_if);
d62a17ae 10190 } else {
05864da7 10191 if (path->peer->hostname
892fedb6
DA
10192 && CHECK_FLAG(path->peer->bgp->flags,
10193 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10194 vty_out(vty, " from %s(%s)",
10195 path->peer->hostname,
10196 path->peer->host);
d62a17ae 10197 else
05864da7
DS
10198 vty_out(vty, " from %s",
10199 sockunion2str(&path->peer->su,
10200 buf,
10201 SU_ADDRSTRLEN));
d62a17ae 10202 }
d62a17ae 10203
05864da7 10204 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10205 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10206 else
10207 vty_out(vty, " (%s)",
10208 inet_ntop(AF_INET,
10209 &path->peer->remote_id, buf1,
10210 sizeof(buf1)));
d62a17ae 10211 }
05864da7 10212 }
9df8b37c 10213
05864da7
DS
10214 /*
10215 * Note when vrfid of nexthop is different from that of prefix
10216 */
10217 if (path->extra && path->extra->bgp_orig) {
10218 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10219
05864da7
DS
10220 if (json_paths) {
10221 const char *vn;
9df8b37c 10222
05864da7
DS
10223 if (path->extra->bgp_orig->inst_type
10224 == BGP_INSTANCE_TYPE_DEFAULT)
10225 vn = VRF_DEFAULT_NAME;
10226 else
10227 vn = path->extra->bgp_orig->name;
9df8b37c 10228
05864da7 10229 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10230
05864da7
DS
10231 if (nexthop_vrfid == VRF_UNKNOWN) {
10232 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10233 } else {
05864da7
DS
10234 json_object_int_add(json_path, "nhVrfId",
10235 (int)nexthop_vrfid);
9df8b37c 10236 }
05864da7
DS
10237 } else {
10238 if (nexthop_vrfid == VRF_UNKNOWN)
10239 vty_out(vty, " vrf ?");
137147c6
DS
10240 else {
10241 struct vrf *vrf;
10242
10243 vrf = vrf_lookup_by_id(nexthop_vrfid);
10244 vty_out(vty, " vrf %s(%u)",
10245 VRF_LOGNAME(vrf), nexthop_vrfid);
10246 }
9df8b37c 10247 }
05864da7 10248 }
9df8b37c 10249
05864da7
DS
10250 if (nexthop_self) {
10251 if (json_paths) {
10252 json_object_boolean_true_add(json_path,
10253 "announceNexthopSelf");
10254 } else {
10255 vty_out(vty, " announce-nh-self");
9df8b37c 10256 }
05864da7 10257 }
9df8b37c 10258
05864da7
DS
10259 if (!json_paths)
10260 vty_out(vty, "\n");
d62a17ae 10261
05864da7
DS
10262 /* display the link-local nexthop */
10263 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10264 if (json_paths) {
10265 json_nexthop_ll = json_object_new_object();
10266 json_object_string_add(
515c2602
DA
10267 json_nexthop_ll, "ip",
10268 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10269 buf, INET6_ADDRSTRLEN));
10270
939a97f4 10271 if (path->peer->hostname)
515c2602
DA
10272 json_object_string_add(json_nexthop_ll,
10273 "hostname",
939a97f4 10274 path->peer->hostname);
515c2602 10275
05864da7
DS
10276 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10277 json_object_string_add(json_nexthop_ll, "scope",
10278 "link-local");
d62a17ae 10279
05864da7
DS
10280 json_object_boolean_true_add(json_nexthop_ll,
10281 "accessible");
d62a17ae 10282
05864da7 10283 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10284 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10285 "used");
10286 else
10287 json_object_boolean_true_add(
10288 json_nexthop_global, "used");
10289 } else {
10290 vty_out(vty, " (%s) %s\n",
10291 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10292 buf, INET6_ADDRSTRLEN),
10293 attr->mp_nexthop_prefer_global
10294 ? "(prefer-global)"
10295 : "(used)");
d62a17ae 10296 }
05864da7
DS
10297 }
10298 /* If we do not have a link-local nexthop then we must flag the
10299 global as "used" */
10300 else {
10301 if (json_paths)
10302 json_object_boolean_true_add(json_nexthop_global,
10303 "used");
10304 }
d62a17ae 10305
b5e140c8 10306 if (safi == SAFI_EVPN &&
5e4d4c8a 10307 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10308 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10309 }
10310
05864da7
DS
10311 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10312 * Int/Ext/Local, Atomic, best */
10313 if (json_paths)
10314 json_object_string_add(json_path, "origin",
10315 bgp_origin_long_str[attr->origin]);
10316 else
10317 vty_out(vty, " Origin %s",
10318 bgp_origin_long_str[attr->origin]);
9df8b37c 10319
05864da7 10320 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10321 if (json_paths)
05864da7 10322 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10323 else
05864da7
DS
10324 vty_out(vty, ", metric %u", attr->med);
10325 }
9df8b37c 10326
05864da7
DS
10327 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10328 if (json_paths)
0fbac0b4 10329 json_object_int_add(json_path, "locPrf",
05864da7
DS
10330 attr->local_pref);
10331 else
10332 vty_out(vty, ", localpref %u", attr->local_pref);
10333 }
9df8b37c 10334
05864da7
DS
10335 if (attr->weight != 0) {
10336 if (json_paths)
10337 json_object_int_add(json_path, "weight", attr->weight);
10338 else
10339 vty_out(vty, ", weight %u", attr->weight);
10340 }
9df8b37c 10341
05864da7
DS
10342 if (attr->tag != 0) {
10343 if (json_paths)
10344 json_object_int_add(json_path, "tag", attr->tag);
10345 else
10346 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10347 }
9df8b37c 10348
05864da7
DS
10349 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10350 if (json_paths)
10351 json_object_boolean_false_add(json_path, "valid");
10352 else
10353 vty_out(vty, ", invalid");
10354 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10355 if (json_paths)
10356 json_object_boolean_true_add(json_path, "valid");
10357 else
10358 vty_out(vty, ", valid");
10359 }
9df8b37c 10360
7d3cae70
DA
10361 if (json_paths)
10362 json_object_int_add(json_path, "version", bn->version);
10363
05864da7
DS
10364 if (path->peer != bgp->peer_self) {
10365 if (path->peer->as == path->peer->local_as) {
10366 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10367 if (json_paths)
10368 json_object_string_add(
10369 json_peer, "type",
10370 "confed-internal");
d62a17ae 10371 else
05864da7 10372 vty_out(vty, ", confed-internal");
d62a17ae 10373 } else {
05864da7
DS
10374 if (json_paths)
10375 json_object_string_add(
10376 json_peer, "type", "internal");
10377 else
10378 vty_out(vty, ", internal");
9df8b37c 10379 }
05864da7
DS
10380 } else {
10381 if (bgp_confederation_peers_check(bgp,
10382 path->peer->as)) {
10383 if (json_paths)
10384 json_object_string_add(
10385 json_peer, "type",
10386 "confed-external");
d62a17ae 10387 else
05864da7 10388 vty_out(vty, ", confed-external");
d62a17ae 10389 } else {
05864da7
DS
10390 if (json_paths)
10391 json_object_string_add(
10392 json_peer, "type", "external");
10393 else
10394 vty_out(vty, ", external");
d62a17ae 10395 }
10396 }
05864da7
DS
10397 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10398 if (json_paths) {
10399 json_object_boolean_true_add(json_path, "aggregated");
10400 json_object_boolean_true_add(json_path, "local");
10401 } else {
10402 vty_out(vty, ", aggregated, local");
10403 }
10404 } else if (path->type != ZEBRA_ROUTE_BGP) {
10405 if (json_paths)
10406 json_object_boolean_true_add(json_path, "sourced");
10407 else
10408 vty_out(vty, ", sourced");
10409 } else {
10410 if (json_paths) {
10411 json_object_boolean_true_add(json_path, "sourced");
10412 json_object_boolean_true_add(json_path, "local");
10413 } else {
10414 vty_out(vty, ", sourced, local");
d62a17ae 10415 }
05864da7 10416 }
718e3744 10417
05864da7 10418 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10419 if (json_paths)
05864da7
DS
10420 json_object_boolean_true_add(json_path,
10421 "atomicAggregate");
d62a17ae 10422 else
05864da7
DS
10423 vty_out(vty, ", atomic-aggregate");
10424 }
d62a17ae 10425
05864da7
DS
10426 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10427 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10428 && bgp_path_info_mpath_count(path))) {
10429 if (json_paths)
10430 json_object_boolean_true_add(json_path, "multipath");
10431 else
10432 vty_out(vty, ", multipath");
10433 }
50e05855 10434
05864da7
DS
10435 // Mark the bestpath(s)
10436 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10437 first_as = aspath_get_first_as(attr->aspath);
718e3744 10438
05864da7
DS
10439 if (json_paths) {
10440 if (!json_bestpath)
10441 json_bestpath = json_object_new_object();
10442 json_object_int_add(json_bestpath, "bestpathFromAs",
10443 first_as);
10444 } else {
10445 if (first_as)
10446 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10447 else
05864da7 10448 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10449 }
05864da7 10450 }
718e3744 10451
05864da7
DS
10452 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10453 if (json_paths) {
10454 if (!json_bestpath)
10455 json_bestpath = json_object_new_object();
10456 json_object_boolean_true_add(json_bestpath, "overall");
10457 json_object_string_add(
10458 json_bestpath, "selectionReason",
10459 bgp_path_selection_reason2str(bn->reason));
10460 } else {
10461 vty_out(vty, ", best");
10462 vty_out(vty, " (%s)",
10463 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10464 }
05864da7 10465 }
718e3744 10466
4027d19b 10467 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10468 if (json_paths)
10469 json_object_string_add(
10470 json_path, "rpkiValidationState",
4027d19b 10471 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10472 else
1d327209 10473 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10474 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10475 }
10476
05864da7
DS
10477 if (json_bestpath)
10478 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10479
05864da7
DS
10480 if (!json_paths)
10481 vty_out(vty, "\n");
10482
10483 /* Line 4 display Community */
29e72930 10484 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10485 if (json_paths) {
10486 if (!attr->community->json)
10487 community_str(attr->community, true);
10488 json_object_lock(attr->community->json);
10489 json_object_object_add(json_path, "community",
10490 attr->community->json);
10491 } else {
10492 vty_out(vty, " Community: %s\n",
10493 attr->community->str);
d62a17ae 10494 }
05864da7 10495 }
718e3744 10496
05864da7
DS
10497 /* Line 5 display Extended-community */
10498 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10499 if (json_paths) {
10500 json_ext_community = json_object_new_object();
10501 json_object_string_add(json_ext_community, "string",
10502 attr->ecommunity->str);
10503 json_object_object_add(json_path, "extendedCommunity",
10504 json_ext_community);
d62a17ae 10505 } else {
05864da7
DS
10506 vty_out(vty, " Extended Community: %s\n",
10507 attr->ecommunity->str);
d62a17ae 10508 }
05864da7 10509 }
718e3744 10510
05864da7
DS
10511 /* Line 6 display Large community */
10512 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10513 if (json_paths) {
10514 if (!attr->lcommunity->json)
10515 lcommunity_str(attr->lcommunity, true);
10516 json_object_lock(attr->lcommunity->json);
10517 json_object_object_add(json_path, "largeCommunity",
10518 attr->lcommunity->json);
10519 } else {
10520 vty_out(vty, " Large Community: %s\n",
10521 attr->lcommunity->str);
d62a17ae 10522 }
05864da7 10523 }
718e3744 10524
05864da7
DS
10525 /* Line 7 display Originator, Cluster-id */
10526 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10527 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10528 char buf[BUFSIZ] = {0};
10529
05864da7 10530 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10531 if (json_paths)
05864da7
DS
10532 json_object_string_add(
10533 json_path, "originatorId",
23d0a753
DA
10534 inet_ntop(AF_INET, &attr->originator_id,
10535 buf, sizeof(buf)));
d62a17ae 10536 else
23d0a753
DA
10537 vty_out(vty, " Originator: %pI4",
10538 &attr->originator_id);
d62a17ae 10539 }
856ca177 10540
05864da7 10541 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10542 struct cluster_list *cluster =
10543 bgp_attr_get_cluster(attr);
05864da7 10544 int i;
d62a17ae 10545
10546 if (json_paths) {
05864da7
DS
10547 json_cluster_list = json_object_new_object();
10548 json_cluster_list_list =
10549 json_object_new_array();
10550
779fee93 10551 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10552 json_string = json_object_new_string(
779fee93
DS
10553 inet_ntop(AF_INET,
10554 &cluster->list[i],
10555 buf, sizeof(buf)));
05864da7
DS
10556 json_object_array_add(
10557 json_cluster_list_list,
10558 json_string);
10559 }
718e3744 10560
05864da7
DS
10561 /*
10562 * struct cluster_list does not have
10563 * "str" variable like aspath and community
10564 * do. Add this someday if someone asks
10565 * for it.
10566 * json_object_string_add(json_cluster_list,
779fee93 10567 * "string", cluster->str);
05864da7
DS
10568 */
10569 json_object_object_add(json_cluster_list,
10570 "list",
10571 json_cluster_list_list);
10572 json_object_object_add(json_path, "clusterList",
10573 json_cluster_list);
0dc8ee70 10574 } else {
05864da7
DS
10575 vty_out(vty, ", Cluster list: ");
10576
779fee93 10577 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10578 vty_out(vty, "%pI4 ",
779fee93 10579 &cluster->list[i]);
05864da7 10580 }
0dc8ee70 10581 }
d62a17ae 10582 }
718e3744 10583
d62a17ae 10584 if (!json_paths)
10585 vty_out(vty, "\n");
05864da7 10586 }
d62a17ae 10587
05864da7 10588 if (path->extra && path->extra->damp_info)
40ec3340 10589 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10590
05864da7
DS
10591 /* Remote Label */
10592 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10593 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10594 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10595
05864da7
DS
10596 if (json_paths)
10597 json_object_int_add(json_path, "remoteLabel", label);
10598 else
10599 vty_out(vty, " Remote label: %d\n", label);
10600 }
d62a17ae 10601
e496b420
HS
10602 /* Remote SID */
10603 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10604 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10605 if (json_paths)
10606 json_object_string_add(json_path, "remoteSid", buf);
10607 else
10608 vty_out(vty, " Remote SID: %s\n", buf);
10609 }
10610
05864da7
DS
10611 /* Label Index */
10612 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10613 if (json_paths)
10614 json_object_int_add(json_path, "labelIndex",
10615 attr->label_index);
10616 else
10617 vty_out(vty, " Label Index: %d\n",
10618 attr->label_index);
10619 }
d62a17ae 10620
05864da7
DS
10621 /* Line 8 display Addpath IDs */
10622 if (path->addpath_rx_id
10623 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10624 if (json_paths) {
10625 json_object_int_add(json_path, "addpathRxId",
10626 path->addpath_rx_id);
d62a17ae 10627
05864da7
DS
10628 /* Keep backwards compatibility with the old API
10629 * by putting TX All's ID in the old field
10630 */
10631 json_object_int_add(
10632 json_path, "addpathTxId",
10633 path->tx_addpath
10634 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10635
05864da7
DS
10636 /* ... but create a specific field for each
10637 * strategy
10638 */
10639 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10640 json_object_int_add(
10641 json_path,
10642 bgp_addpath_names(i)->id_json_name,
10643 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10644 }
05864da7
DS
10645 } else {
10646 vty_out(vty, " AddPath ID: RX %u, ",
10647 path->addpath_rx_id);
d62a17ae 10648
05864da7 10649 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10650 }
05864da7 10651 }
520d5d76 10652
05864da7
DS
10653 /* If we used addpath to TX a non-bestpath we need to display
10654 * "Advertised to" on a path-by-path basis
10655 */
10656 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10657 first = 1;
dcc68b5e 10658
05864da7
DS
10659 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10660 addpath_capable =
10661 bgp_addpath_encode_tx(peer, afi, safi);
10662 has_adj = bgp_adj_out_lookup(
10663 peer, path->net,
10664 bgp_addpath_id_for_peer(peer, afi, safi,
10665 &path->tx_addpath));
10666
10667 if ((addpath_capable && has_adj)
10668 || (!addpath_capable && has_adj
10669 && CHECK_FLAG(path->flags,
10670 BGP_PATH_SELECTED))) {
10671 if (json_path && !json_adv_to)
10672 json_adv_to = json_object_new_object();
dcc68b5e 10673
05864da7
DS
10674 route_vty_out_advertised_to(
10675 vty, peer, &first,
10676 " Advertised to:", json_adv_to);
d62a17ae 10677 }
10678 }
718e3744 10679
05864da7
DS
10680 if (json_path) {
10681 if (json_adv_to) {
10682 json_object_object_add(
10683 json_path, "advertisedTo", json_adv_to);
d62a17ae 10684 }
05864da7
DS
10685 } else {
10686 if (!first) {
10687 vty_out(vty, "\n");
d62a17ae 10688 }
10689 }
05864da7 10690 }
b05a1c8b 10691
05864da7
DS
10692 /* Line 9 display Uptime */
10693 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10694 if (json_paths) {
10695 json_last_update = json_object_new_object();
10696 json_object_int_add(json_last_update, "epoch", tbuf);
10697 json_object_string_add(json_last_update, "string",
10698 ctime(&tbuf));
10699 json_object_object_add(json_path, "lastUpdate",
10700 json_last_update);
10701 } else
10702 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10703
05864da7
DS
10704 /* Line 10 display PMSI tunnel attribute, if present */
10705 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10706 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10707 bgp_attr_get_pmsi_tnl_type(attr),
10708 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10709
05864da7
DS
10710 if (json_paths) {
10711 json_pmsi = json_object_new_object();
10712 json_object_string_add(json_pmsi, "tunnelType", str);
10713 json_object_int_add(json_pmsi, "label",
10714 label2vni(&attr->label));
10715 json_object_object_add(json_path, "pmsi", json_pmsi);
10716 } else
10717 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10718 str, label2vni(&attr->label));
d62a17ae 10719 }
f1aa5d8a 10720
92269aa2
DS
10721 /* Output some debug about internal state of the dest flags */
10722 if (json_paths) {
10723 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10724 json_object_boolean_true_add(json_path, "processScheduled");
10725 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10726 json_object_boolean_true_add(json_path, "userCleared");
10727 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10728 json_object_boolean_true_add(json_path, "labelChanged");
10729 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10730 json_object_boolean_true_add(json_path, "registeredForLabel");
10731 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10732 json_object_boolean_true_add(json_path, "selectDefered");
10733 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10734 json_object_boolean_true_add(json_path, "fibInstalled");
10735 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10736 json_object_boolean_true_add(json_path, "fibPending");
10737 }
10738
d62a17ae 10739 /* We've constructed the json object for this path, add it to the json
10740 * array of paths
10741 */
10742 if (json_paths) {
10743 if (json_nexthop_global || json_nexthop_ll) {
10744 json_nexthops = json_object_new_array();
f1aa5d8a 10745
d62a17ae 10746 if (json_nexthop_global)
10747 json_object_array_add(json_nexthops,
10748 json_nexthop_global);
f1aa5d8a 10749
d62a17ae 10750 if (json_nexthop_ll)
10751 json_object_array_add(json_nexthops,
10752 json_nexthop_ll);
f1aa5d8a 10753
d62a17ae 10754 json_object_object_add(json_path, "nexthops",
10755 json_nexthops);
10756 }
10757
10758 json_object_object_add(json_path, "peer", json_peer);
10759 json_object_array_add(json_paths, json_path);
05864da7 10760 }
b366b518
BB
10761}
10762
96ade3ed 10763#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10764#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10765#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10766
d62a17ae 10767static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10768 const char *prefix_list_str, afi_t afi,
10769 safi_t safi, enum bgp_show_type type);
10770static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10771 const char *filter, afi_t afi, safi_t safi,
10772 enum bgp_show_type type);
10773static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10774 const char *rmap_str, afi_t afi, safi_t safi,
10775 enum bgp_show_type type);
10776static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10777 const char *com, int exact, afi_t afi,
10778 safi_t safi);
10779static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10780 const char *prefix, afi_t afi, safi_t safi,
10781 enum bgp_show_type type);
a4d82a8a 10782static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10783 afi_t afi, safi_t safi, enum bgp_show_type type,
10784 bool use_json);
7f323236
DW
10785static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10786 const char *comstr, int exact, afi_t afi,
96c81f66 10787 safi_t safi, uint16_t show_flags);
d62a17ae 10788
1ae44dfc 10789static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10790 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10791 void *output_arg, char *rd, int is_last,
10792 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10793 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10794 enum rpki_states rpki_target_state)
d62a17ae 10795{
40381db7 10796 struct bgp_path_info *pi;
9bcb3eef 10797 struct bgp_dest *dest;
d62a17ae 10798 int header = 1;
10799 int display;
1ae44dfc
LB
10800 unsigned long output_count = 0;
10801 unsigned long total_count = 0;
d62a17ae 10802 struct prefix *p;
d62a17ae 10803 json_object *json_paths = NULL;
10804 int first = 1;
96f3485c
MK
10805 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10806 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10807 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10808
1ae44dfc
LB
10809 if (output_cum && *output_cum != 0)
10810 header = 0;
10811
9386b588 10812 if (use_json && !*json_header_depth) {
96f3485c
MK
10813 if (all)
10814 *json_header_depth = 1;
10815 else {
10816 vty_out(vty, "{\n");
10817 *json_header_depth = 2;
10818 }
10819
d62a17ae 10820 vty_out(vty,
23d0a753
DA
10821 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10822 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10823 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10824 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10825 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10826 ? VRF_DEFAULT_NAME
10827 : bgp->name,
10828 table->version, &bgp->router_id,
01eced22 10829 bgp->default_local_pref, bgp->as);
9386b588 10830 if (rd) {
445c2480 10831 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10832 ++*json_header_depth;
10833 }
d62a17ae 10834 }
718e3744 10835
445c2480
DS
10836 if (use_json && rd) {
10837 vty_out(vty, " \"%s\" : { ", rd);
10838 }
10839
d62a17ae 10840 /* Start processing of routes. */
9bcb3eef
DS
10841 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10842 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10843 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10844
9bcb3eef 10845 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10846 if (pi == NULL)
98ce9a06 10847 continue;
d62a17ae 10848
98ce9a06 10849 display = 0;
98ce9a06
DS
10850 if (use_json)
10851 json_paths = json_object_new_array();
10852 else
10853 json_paths = NULL;
d62a17ae 10854
6f94b685 10855 for (; pi; pi = pi->next) {
98ce9a06 10856 total_count++;
1e2ce4f1 10857
7d3cae70
DA
10858 if (type == bgp_show_type_prefix_version) {
10859 uint32_t version =
10860 strtoul(output_arg, NULL, 10);
10861 if (dest->version < version)
10862 continue;
10863 }
10864
a70a28a5
DA
10865 if (type == bgp_show_type_community_alias) {
10866 char *alias = output_arg;
10867 char **communities;
10868 int num;
10869 bool found = false;
10870
10871 if (pi->attr->community) {
10872 frrstr_split(pi->attr->community->str,
10873 " ", &communities, &num);
10874 for (int i = 0; i < num; i++) {
10875 const char *com2alias =
10876 bgp_community2alias(
10877 communities[i]);
35a45e80 10878 if (strcmp(alias, com2alias)
a70a28a5
DA
10879 == 0) {
10880 found = true;
10881 break;
10882 }
10883 }
10884 }
10885
10886 if (!found && pi->attr->lcommunity) {
10887 frrstr_split(pi->attr->lcommunity->str,
10888 " ", &communities, &num);
10889 for (int i = 0; i < num; i++) {
10890 const char *com2alias =
10891 bgp_community2alias(
10892 communities[i]);
35a45e80 10893 if (strcmp(alias, com2alias)
a70a28a5
DA
10894 == 0) {
10895 found = true;
10896 break;
10897 }
10898 }
10899 }
10900
10901 if (!found)
10902 continue;
10903 }
10904
1e2ce4f1
DS
10905 if (type == bgp_show_type_rpki) {
10906 if (dest_p->family == AF_INET
10907 || dest_p->family == AF_INET6)
4027d19b 10908 rpki_curr_state = hook_call(
1e2ce4f1
DS
10909 bgp_rpki_prefix_status,
10910 pi->peer, pi->attr, dest_p);
4027d19b
DS
10911 if (rpki_target_state != RPKI_NOT_BEING_USED
10912 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10913 continue;
10914 }
10915
98ce9a06
DS
10916 if (type == bgp_show_type_flap_statistics
10917 || type == bgp_show_type_flap_neighbor
10918 || type == bgp_show_type_dampend_paths
10919 || type == bgp_show_type_damp_neighbor) {
40381db7 10920 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10921 continue;
10922 }
10923 if (type == bgp_show_type_regexp) {
10924 regex_t *regex = output_arg;
d62a17ae 10925
40381db7 10926 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10927 == REG_NOMATCH)
10928 continue;
10929 }
10930 if (type == bgp_show_type_prefix_list) {
10931 struct prefix_list *plist = output_arg;
d62a17ae 10932
9bcb3eef 10933 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10934 != PREFIX_PERMIT)
10935 continue;
10936 }
10937 if (type == bgp_show_type_filter_list) {
10938 struct as_list *as_list = output_arg;
d62a17ae 10939
40381db7 10940 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10941 != AS_FILTER_PERMIT)
10942 continue;
10943 }
10944 if (type == bgp_show_type_route_map) {
10945 struct route_map *rmap = output_arg;
9b6d8fcf 10946 struct bgp_path_info path;
98ce9a06 10947 struct attr dummy_attr;
b68885f9 10948 route_map_result_t ret;
d62a17ae 10949
6f4f49b2 10950 dummy_attr = *pi->attr;
d62a17ae 10951
40381db7 10952 path.peer = pi->peer;
9b6d8fcf 10953 path.attr = &dummy_attr;
d62a17ae 10954
1782514f 10955 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10956 if (ret == RMAP_DENYMATCH)
10957 continue;
10958 }
10959 if (type == bgp_show_type_neighbor
10960 || type == bgp_show_type_flap_neighbor
10961 || type == bgp_show_type_damp_neighbor) {
10962 union sockunion *su = output_arg;
10963
40381db7
DS
10964 if (pi->peer == NULL
10965 || pi->peer->su_remote == NULL
10966 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10967 continue;
10968 }
10969 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10970 uint32_t destination;
d62a17ae 10971
9bcb3eef 10972 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10973 if (IN_CLASSC(destination)
9bcb3eef 10974 && dest_p->prefixlen == 24)
98ce9a06
DS
10975 continue;
10976 if (IN_CLASSB(destination)
9bcb3eef 10977 && dest_p->prefixlen == 16)
98ce9a06
DS
10978 continue;
10979 if (IN_CLASSA(destination)
9bcb3eef 10980 && dest_p->prefixlen == 8)
98ce9a06
DS
10981 continue;
10982 }
10983 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10984 p = output_arg;
9bcb3eef 10985 if (!prefix_match(p, dest_p))
98ce9a06
DS
10986 continue;
10987 }
10988 if (type == bgp_show_type_community_all) {
40381db7 10989 if (!pi->attr->community)
98ce9a06
DS
10990 continue;
10991 }
10992 if (type == bgp_show_type_community) {
10993 struct community *com = output_arg;
d62a17ae 10994
40381db7
DS
10995 if (!pi->attr->community
10996 || !community_match(pi->attr->community,
98ce9a06
DS
10997 com))
10998 continue;
10999 }
11000 if (type == bgp_show_type_community_exact) {
11001 struct community *com = output_arg;
d62a17ae 11002
40381db7
DS
11003 if (!pi->attr->community
11004 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
11005 continue;
11006 }
11007 if (type == bgp_show_type_community_list) {
11008 struct community_list *list = output_arg;
d62a17ae 11009
40381db7 11010 if (!community_list_match(pi->attr->community,
a4d82a8a 11011 list))
98ce9a06
DS
11012 continue;
11013 }
a4d82a8a 11014 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11015 struct community_list *list = output_arg;
d62a17ae 11016
98ce9a06 11017 if (!community_list_exact_match(
40381db7 11018 pi->attr->community, list))
98ce9a06
DS
11019 continue;
11020 }
11021 if (type == bgp_show_type_lcommunity) {
11022 struct lcommunity *lcom = output_arg;
d62a17ae 11023
40381db7
DS
11024 if (!pi->attr->lcommunity
11025 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
11026 lcom))
11027 continue;
11028 }
36a206db 11029
11030 if (type == bgp_show_type_lcommunity_exact) {
11031 struct lcommunity *lcom = output_arg;
11032
11033 if (!pi->attr->lcommunity
11034 || !lcommunity_cmp(pi->attr->lcommunity,
11035 lcom))
11036 continue;
11037 }
98ce9a06
DS
11038 if (type == bgp_show_type_lcommunity_list) {
11039 struct community_list *list = output_arg;
d62a17ae 11040
40381db7 11041 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 11042 list))
98ce9a06
DS
11043 continue;
11044 }
36a206db 11045 if (type
11046 == bgp_show_type_lcommunity_list_exact) {
11047 struct community_list *list = output_arg;
11048
11049 if (!lcommunity_list_exact_match(
11050 pi->attr->lcommunity, list))
11051 continue;
11052 }
98ce9a06 11053 if (type == bgp_show_type_lcommunity_all) {
40381db7 11054 if (!pi->attr->lcommunity)
98ce9a06
DS
11055 continue;
11056 }
11057 if (type == bgp_show_type_dampend_paths
11058 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11059 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11060 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11061 continue;
11062 }
11063
11064 if (!use_json && header) {
23d0a753
DA
11065 vty_out(vty,
11066 "BGP table version is %" PRIu64
11067 ", local router ID is %pI4, vrf id ",
11068 table->version, &bgp->router_id);
9df8b37c
PZ
11069 if (bgp->vrf_id == VRF_UNKNOWN)
11070 vty_out(vty, "%s", VRFID_NONE_STR);
11071 else
11072 vty_out(vty, "%u", bgp->vrf_id);
11073 vty_out(vty, "\n");
01eced22
AD
11074 vty_out(vty, "Default local pref %u, ",
11075 bgp->default_local_pref);
11076 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11077 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11078 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11079 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11080 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11081 if (type == bgp_show_type_dampend_paths
11082 || type == bgp_show_type_damp_neighbor)
98ce9a06 11083 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11084 else if (type == bgp_show_type_flap_statistics
11085 || type == bgp_show_type_flap_neighbor)
98ce9a06 11086 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11087 else
ae248832
MK
11088 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11089 : BGP_SHOW_HEADER));
98ce9a06 11090 header = 0;
d62a17ae 11091 }
98ce9a06
DS
11092 if (rd != NULL && !display && !output_count) {
11093 if (!use_json)
11094 vty_out(vty,
11095 "Route Distinguisher: %s\n",
11096 rd);
d62a17ae 11097 }
98ce9a06
DS
11098 if (type == bgp_show_type_dampend_paths
11099 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11100 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11101 AFI_IP, safi, use_json,
11102 json_paths);
98ce9a06
DS
11103 else if (type == bgp_show_type_flap_statistics
11104 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11105 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11106 AFI_IP, safi, use_json,
11107 json_paths);
f280c93b
DA
11108 else {
11109 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11110 route_vty_out_detail(
11111 vty, bgp, dest, pi,
11112 family2afi(dest_p->family),
11113 safi, RPKI_NOT_BEING_USED,
11114 json_paths);
11115 else
11116 route_vty_out(vty, dest_p, pi, display,
11117 safi, json_paths, wide);
11118 }
98ce9a06 11119 display++;
d62a17ae 11120 }
11121
98ce9a06
DS
11122 if (display) {
11123 output_count++;
11124 if (!use_json)
11125 continue;
11126
625d2931 11127 /* encode prefix */
9bcb3eef 11128 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11129 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11130
1840384b 11131
b54892e0
DS
11132 bgp_fs_nlri_get_string(
11133 (unsigned char *)
9bcb3eef
DS
11134 dest_p->u.prefix_flowspec.ptr,
11135 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11136 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11137 family2afi(dest_p->u
11138 .prefix_flowspec.family));
625d2931 11139 if (first)
b54892e0 11140 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11141 dest_p->u.prefix_flowspec
b54892e0 11142 .prefixlen);
625d2931 11143 else
b54892e0 11144 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11145 dest_p->u.prefix_flowspec
b54892e0 11146 .prefixlen);
625d2931 11147 } else {
625d2931 11148 if (first)
1b78780b 11149 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11150 else
1b78780b 11151 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11152 }
98ce9a06 11153 vty_out(vty, "%s",
f4ec52f7
DA
11154 json_object_to_json_string_ext(
11155 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11156 json_object_free(json_paths);
449feb8e 11157 json_paths = NULL;
98ce9a06 11158 first = 0;
1f83ed02
DS
11159 } else
11160 json_object_free(json_paths);
98ce9a06
DS
11161 }
11162
1ae44dfc
LB
11163 if (output_cum) {
11164 output_count += *output_cum;
11165 *output_cum = output_count;
11166 }
11167 if (total_cum) {
11168 total_count += *total_cum;
11169 *total_cum = total_count;
11170 }
d62a17ae 11171 if (use_json) {
9386b588 11172 if (rd) {
a4d82a8a 11173 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11174 }
11175 if (is_last) {
a4d82a8a
PZ
11176 unsigned long i;
11177 for (i = 0; i < *json_header_depth; ++i)
11178 vty_out(vty, " } ");
96f3485c
MK
11179 if (!all)
11180 vty_out(vty, "\n");
9386b588 11181 }
d62a17ae 11182 } else {
1ae44dfc
LB
11183 if (is_last) {
11184 /* No route is displayed */
11185 if (output_count == 0) {
11186 if (type == bgp_show_type_normal)
11187 vty_out(vty,
11188 "No BGP prefixes displayed, %ld exist\n",
11189 total_count);
11190 } else
d62a17ae 11191 vty_out(vty,
1ae44dfc
LB
11192 "\nDisplayed %ld routes and %ld total paths\n",
11193 output_count, total_count);
11194 }
d62a17ae 11195 }
718e3744 11196
d62a17ae 11197 return CMD_SUCCESS;
718e3744 11198}
11199
1ae44dfc
LB
11200int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11201 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11202 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11203{
9bcb3eef 11204 struct bgp_dest *dest, *next;
1ae44dfc
LB
11205 unsigned long output_cum = 0;
11206 unsigned long total_cum = 0;
9386b588 11207 unsigned long json_header_depth = 0;
67009e22 11208 struct bgp_table *itable;
0136788c 11209 bool show_msg;
96c81f66 11210 uint16_t show_flags = 0;
0136788c
LB
11211
11212 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11213
96f3485c
MK
11214 if (use_json)
11215 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11216
9bcb3eef
DS
11217 for (dest = bgp_table_top(table); dest; dest = next) {
11218 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11219
9bcb3eef
DS
11220 next = bgp_route_next(dest);
11221 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11222 continue;
67009e22 11223
9bcb3eef 11224 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11225 if (itable != NULL) {
1ae44dfc 11226 struct prefix_rd prd;
06b9f471 11227 char rd[RD_ADDRSTRLEN];
1ae44dfc 11228
9bcb3eef 11229 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11230 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11231 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11232 rd, next == NULL, &output_cum,
11233 &total_cum, &json_header_depth,
1e2ce4f1 11234 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11235 if (next == NULL)
11236 show_msg = false;
1ae44dfc
LB
11237 }
11238 }
0136788c
LB
11239 if (show_msg) {
11240 if (output_cum == 0)
11241 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11242 total_cum);
11243 else
11244 vty_out(vty,
11245 "\nDisplayed %ld routes and %ld total paths\n",
11246 output_cum, total_cum);
11247 }
1ae44dfc
LB
11248 return CMD_SUCCESS;
11249}
d62a17ae 11250static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11251 enum bgp_show_type type, void *output_arg,
96c81f66 11252 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11253{
d62a17ae 11254 struct bgp_table *table;
9386b588 11255 unsigned long json_header_depth = 0;
96f3485c 11256 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11257
d62a17ae 11258 if (bgp == NULL) {
11259 bgp = bgp_get_default();
11260 }
fee0f4c6 11261
d62a17ae 11262 if (bgp == NULL) {
11263 if (!use_json)
11264 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11265 else
11266 vty_out(vty, "{}\n");
d62a17ae 11267 return CMD_WARNING;
11268 }
4dd6177e 11269
1ae44dfc 11270 table = bgp->rib[afi][safi];
d62a17ae 11271 /* use MPLS and ENCAP specific shows until they are merged */
11272 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11273 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11274 output_arg, use_json);
d62a17ae 11275 }
dba3c1d3
PG
11276
11277 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11278 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11279 output_arg, use_json,
11280 1, NULL, NULL);
11281 }
d62a17ae 11282 /* labeled-unicast routes live in the unicast table */
11283 else if (safi == SAFI_LABELED_UNICAST)
11284 safi = SAFI_UNICAST;
fee0f4c6 11285
96f3485c 11286 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11287 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11288 rpki_target_state);
fee0f4c6 11289}
11290
d62a17ae 11291static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11292 safi_t safi, uint16_t show_flags)
f186de26 11293{
d62a17ae 11294 struct listnode *node, *nnode;
11295 struct bgp *bgp;
11296 int is_first = 1;
9f049418 11297 bool route_output = false;
96f3485c 11298 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11299
d62a17ae 11300 if (use_json)
11301 vty_out(vty, "{\n");
9f689658 11302
d62a17ae 11303 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11304 route_output = true;
d62a17ae 11305 if (use_json) {
11306 if (!is_first)
11307 vty_out(vty, ",\n");
11308 else
11309 is_first = 0;
11310
11311 vty_out(vty, "\"%s\":",
11312 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11313 ? VRF_DEFAULT_NAME
d62a17ae 11314 : bgp->name);
11315 } else {
11316 vty_out(vty, "\nInstance %s:\n",
11317 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11318 ? VRF_DEFAULT_NAME
d62a17ae 11319 : bgp->name);
11320 }
11321 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11322 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11323 }
9f689658 11324
d62a17ae 11325 if (use_json)
11326 vty_out(vty, "}\n");
9f049418
DS
11327 else if (!route_output)
11328 vty_out(vty, "%% BGP instance not found\n");
f186de26 11329}
11330
718e3744 11331/* Header of detailed BGP route information */
d62a17ae 11332void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11333 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11334 afi_t afi, safi_t safi, json_object *json)
11335{
40381db7 11336 struct bgp_path_info *pi;
b54892e0 11337 const struct prefix *p;
d62a17ae 11338 struct peer *peer;
11339 struct listnode *node, *nnode;
06b9f471 11340 char buf1[RD_ADDRSTRLEN];
0291c246 11341 char prefix_str[BUFSIZ];
d62a17ae 11342 int count = 0;
11343 int best = 0;
11344 int suppress = 0;
c5f1e1b2
C
11345 int accept_own = 0;
11346 int route_filter_translated_v4 = 0;
11347 int route_filter_v4 = 0;
11348 int route_filter_translated_v6 = 0;
11349 int route_filter_v6 = 0;
11350 int llgr_stale = 0;
11351 int no_llgr = 0;
11352 int accept_own_nexthop = 0;
11353 int blackhole = 0;
d62a17ae 11354 int no_export = 0;
11355 int no_advertise = 0;
11356 int local_as = 0;
c5f1e1b2 11357 int no_peer = 0;
d62a17ae 11358 int first = 1;
11359 int has_valid_label = 0;
11360 mpls_label_t label = 0;
11361 json_object *json_adv_to = NULL;
9bedbb1e 11362
9bcb3eef
DS
11363 p = bgp_dest_get_prefix(dest);
11364 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11365
11366 if (has_valid_label)
9bcb3eef 11367 label = label_pton(&dest->local_label);
d62a17ae 11368
44c69747 11369 if (safi == SAFI_EVPN) {
d62a17ae 11370
44c69747 11371 if (!json) {
2dbe669b 11372 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11373 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11374 : "",
2dbe669b 11375 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11376 } else {
11377 json_object_string_add(json, "rd",
11378 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11379 "");
11380 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11381 }
11382 } else {
11383 if (!json) {
9119ef3a
DA
11384 vty_out(vty,
11385 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11386 "\n",
d62a17ae 11387 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11388 ? prefix_rd2str(prd, buf1,
11389 sizeof(buf1))
11390 : ""),
9119ef3a
DA
11391 safi == SAFI_MPLS_VPN ? ":" : "", p,
11392 dest->version);
cd1964ff 11393
9119ef3a 11394 } else {
44c69747
LK
11395 json_object_string_add(json, "prefix",
11396 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11397 json_object_int_add(json, "version", dest->version);
11398
11399 }
44c69747
LK
11400 }
11401
11402 if (has_valid_label) {
11403 if (json)
11404 json_object_int_add(json, "localLabel", label);
11405 else
d62a17ae 11406 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11407 }
11408
11409 if (!json)
d62a17ae 11410 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11411 vty_out(vty, "not allocated\n");
718e3744 11412
9bcb3eef 11413 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11414 count++;
40381db7 11415 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11416 best = count;
4056a5f6 11417 if (bgp_path_suppressed(pi))
d62a17ae 11418 suppress = 1;
cee9c031 11419
40381db7 11420 if (pi->attr->community == NULL)
cee9c031
QY
11421 continue;
11422
11423 no_advertise += community_include(
40381db7
DS
11424 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11425 no_export += community_include(pi->attr->community,
cee9c031 11426 COMMUNITY_NO_EXPORT);
40381db7 11427 local_as += community_include(pi->attr->community,
cee9c031 11428 COMMUNITY_LOCAL_AS);
40381db7 11429 accept_own += community_include(pi->attr->community,
cee9c031
QY
11430 COMMUNITY_ACCEPT_OWN);
11431 route_filter_translated_v4 += community_include(
40381db7 11432 pi->attr->community,
cee9c031
QY
11433 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11434 route_filter_translated_v6 += community_include(
40381db7 11435 pi->attr->community,
cee9c031
QY
11436 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11437 route_filter_v4 += community_include(
40381db7 11438 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11439 route_filter_v6 += community_include(
40381db7
DS
11440 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11441 llgr_stale += community_include(pi->attr->community,
cee9c031 11442 COMMUNITY_LLGR_STALE);
40381db7 11443 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11444 COMMUNITY_NO_LLGR);
11445 accept_own_nexthop +=
40381db7 11446 community_include(pi->attr->community,
cee9c031 11447 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11448 blackhole += community_include(pi->attr->community,
cee9c031 11449 COMMUNITY_BLACKHOLE);
40381db7 11450 no_peer += community_include(pi->attr->community,
cee9c031 11451 COMMUNITY_NO_PEER);
d62a17ae 11452 }
718e3744 11453 }
718e3744 11454
d62a17ae 11455 if (!json) {
11456 vty_out(vty, "Paths: (%d available", count);
11457 if (best) {
11458 vty_out(vty, ", best #%d", best);
b84060bb
PG
11459 if (safi == SAFI_UNICAST) {
11460 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11461 vty_out(vty, ", table %s",
11462 VRF_DEFAULT_NAME);
11463 else
11464 vty_out(vty, ", vrf %s",
11465 bgp->name);
11466 }
d62a17ae 11467 } else
11468 vty_out(vty, ", no best path");
11469
c5f1e1b2
C
11470 if (accept_own)
11471 vty_out(vty,
11472 ", accept own local route exported and imported in different VRF");
11473 else if (route_filter_translated_v4)
11474 vty_out(vty,
11475 ", mark translated RTs for VPNv4 route filtering");
11476 else if (route_filter_v4)
11477 vty_out(vty,
11478 ", attach RT as-is for VPNv4 route filtering");
11479 else if (route_filter_translated_v6)
11480 vty_out(vty,
11481 ", mark translated RTs for VPNv6 route filtering");
11482 else if (route_filter_v6)
11483 vty_out(vty,
11484 ", attach RT as-is for VPNv6 route filtering");
11485 else if (llgr_stale)
11486 vty_out(vty,
11487 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11488 else if (no_llgr)
11489 vty_out(vty,
11490 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11491 else if (accept_own_nexthop)
11492 vty_out(vty,
11493 ", accept local nexthop");
11494 else if (blackhole)
11495 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11496 else if (no_export)
11497 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11498 else if (no_advertise)
11499 vty_out(vty, ", not advertised to any peer");
d62a17ae 11500 else if (local_as)
11501 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11502 else if (no_peer)
11503 vty_out(vty,
11504 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11505
11506 if (suppress)
11507 vty_out(vty,
11508 ", Advertisements suppressed by an aggregate.");
11509 vty_out(vty, ")\n");
11510 }
718e3744 11511
d62a17ae 11512 /* If we are not using addpath then we can display Advertised to and
11513 * that will
11514 * show what peers we advertised the bestpath to. If we are using
11515 * addpath
11516 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11517 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11518 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11519 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11520 if (json && !json_adv_to)
11521 json_adv_to = json_object_new_object();
11522
11523 route_vty_out_advertised_to(
11524 vty, peer, &first,
11525 " Advertised to non peer-group peers:\n ",
11526 json_adv_to);
11527 }
11528 }
11529
11530 if (json) {
11531 if (json_adv_to) {
11532 json_object_object_add(json, "advertisedTo",
11533 json_adv_to);
11534 }
11535 } else {
11536 if (first)
11537 vty_out(vty, " Not advertised to any peer");
11538 vty_out(vty, "\n");
11539 }
11540 }
718e3744 11541}
11542
44c69747 11543static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11544 struct bgp_dest *bgp_node, struct vty *vty,
11545 struct bgp *bgp, afi_t afi, safi_t safi,
11546 json_object *json, enum bgp_path_type pathtype,
4027d19b 11547 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11548{
11549 struct bgp_path_info *pi;
11550 int header = 1;
11551 char rdbuf[RD_ADDRSTRLEN];
11552 json_object *json_header = NULL;
11553 json_object *json_paths = NULL;
4933eaaf 11554 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11555
9bcb3eef 11556 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11557 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11558
11559 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11560 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11561 pi->peer, pi->attr, p);
4933eaaf 11562
4027d19b
DS
11563 if (rpki_target_state != RPKI_NOT_BEING_USED
11564 && rpki_curr_state != rpki_target_state)
4933eaaf 11565 continue;
44c69747
LK
11566
11567 if (json && !json_paths) {
11568 /* Instantiate json_paths only if path is valid */
11569 json_paths = json_object_new_array();
11570 if (pfx_rd) {
11571 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11572 json_header = json_object_new_object();
11573 } else
11574 json_header = json;
11575 }
11576
11577 if (header) {
11578 route_vty_out_detail_header(
11579 vty, bgp, bgp_node, pfx_rd,
11580 AFI_IP, safi, json_header);
11581 header = 0;
11582 }
11583 (*display)++;
11584
11585 if (pathtype == BGP_PATH_SHOW_ALL
11586 || (pathtype == BGP_PATH_SHOW_BESTPATH
11587 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11588 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11589 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11590 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11591 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11592 safi, rpki_curr_state, json_paths);
44c69747
LK
11593 }
11594
11595 if (json && json_paths) {
11596 json_object_object_add(json_header, "paths", json_paths);
11597
11598 if (pfx_rd)
11599 json_object_object_add(json, rdbuf, json_header);
11600 }
11601}
11602
718e3744 11603/* Display specified route of BGP table. */
d62a17ae 11604static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11605 struct bgp_table *rib, const char *ip_str,
11606 afi_t afi, safi_t safi,
4027d19b 11607 enum rpki_states rpki_target_state,
d62a17ae 11608 struct prefix_rd *prd, int prefix_check,
9f049418 11609 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11610{
11611 int ret;
d62a17ae 11612 int display = 0;
11613 struct prefix match;
9bcb3eef
DS
11614 struct bgp_dest *dest;
11615 struct bgp_dest *rm;
d62a17ae 11616 struct bgp_table *table;
11617 json_object *json = NULL;
11618 json_object *json_paths = NULL;
11619
11620 /* Check IP address argument. */
11621 ret = str2prefix(ip_str, &match);
11622 if (!ret) {
11623 vty_out(vty, "address is malformed\n");
11624 return CMD_WARNING;
11625 }
718e3744 11626
d62a17ae 11627 match.family = afi2family(afi);
b05a1c8b 11628
44c69747 11629 if (use_json)
d62a17ae 11630 json = json_object_new_object();
718e3744 11631
44c69747 11632 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11633 for (dest = bgp_table_top(rib); dest;
11634 dest = bgp_route_next(dest)) {
11635 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11636
9bcb3eef 11637 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11638 continue;
9bcb3eef 11639 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11640 if (!table)
ea47320b 11641 continue;
d62a17ae 11642
4953391b
DA
11643 rm = bgp_node_match(table, &match);
11644 if (rm == NULL)
ea47320b 11645 continue;
d62a17ae 11646
9bcb3eef 11647 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11648 if (prefix_check
b54892e0 11649 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11650 bgp_dest_unlock_node(rm);
ea47320b
DL
11651 continue;
11652 }
d62a17ae 11653
9bcb3eef 11654 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11655 bgp, afi, safi, json, pathtype,
4027d19b 11656 &display, rpki_target_state);
44c69747 11657
9bcb3eef 11658 bgp_dest_unlock_node(rm);
44c69747
LK
11659 }
11660 } else if (safi == SAFI_EVPN) {
9bcb3eef 11661 struct bgp_dest *longest_pfx;
cded3b72 11662 bool is_exact_pfxlen_match = false;
44c69747 11663
9bcb3eef
DS
11664 for (dest = bgp_table_top(rib); dest;
11665 dest = bgp_route_next(dest)) {
11666 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11667
9bcb3eef 11668 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11669 continue;
9bcb3eef 11670 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11671 if (!table)
11672 continue;
11673
11674 longest_pfx = NULL;
cded3b72 11675 is_exact_pfxlen_match = false;
44c69747
LK
11676 /*
11677 * Search through all the prefixes for a match. The
11678 * pfx's are enumerated in ascending order of pfxlens.
11679 * So, the last pfx match is the longest match. Set
11680 * is_exact_pfxlen_match when we get exact pfxlen match
11681 */
11682 for (rm = bgp_table_top(table); rm;
11683 rm = bgp_route_next(rm)) {
b54892e0 11684 const struct prefix *rm_p =
9bcb3eef 11685 bgp_dest_get_prefix(rm);
44c69747
LK
11686 /*
11687 * Get prefixlen of the ip-prefix within type5
11688 * evpn route
11689 */
b54892e0
DS
11690 if (evpn_type5_prefix_match(rm_p, &match)
11691 && rm->info) {
44c69747
LK
11692 longest_pfx = rm;
11693 int type5_pfxlen =
b54892e0
DS
11694 bgp_evpn_get_type5_prefixlen(
11695 rm_p);
44c69747 11696 if (type5_pfxlen == match.prefixlen) {
cded3b72 11697 is_exact_pfxlen_match = true;
9bcb3eef 11698 bgp_dest_unlock_node(rm);
44c69747
LK
11699 break;
11700 }
d62a17ae 11701 }
11702 }
ea47320b 11703
44c69747
LK
11704 if (!longest_pfx)
11705 continue;
11706
11707 if (prefix_check && !is_exact_pfxlen_match)
11708 continue;
11709
11710 rm = longest_pfx;
9bcb3eef 11711 bgp_dest_lock_node(rm);
44c69747 11712
9bcb3eef 11713 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11714 bgp, afi, safi, json, pathtype,
4027d19b 11715 &display, rpki_target_state);
44c69747 11716
9bcb3eef 11717 bgp_dest_unlock_node(rm);
d62a17ae 11718 }
98a9dbc7 11719 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11720 if (use_json)
11721 json_paths = json_object_new_array();
11722
63a0b7a9
PG
11723 display = bgp_flowspec_display_match_per_ip(afi, rib,
11724 &match, prefix_check,
11725 vty,
11726 use_json,
11727 json_paths);
d5f20468
SP
11728 if (use_json) {
11729 if (display)
11730 json_object_object_add(json, "paths",
11731 json_paths);
11732 else
11733 json_object_free(json_paths);
11734 }
d62a17ae 11735 } else {
4953391b
DA
11736 dest = bgp_node_match(rib, &match);
11737 if (dest != NULL) {
9bcb3eef 11738 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11739 if (!prefix_check
9bcb3eef
DS
11740 || dest_p->prefixlen == match.prefixlen) {
11741 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11742 safi, json, pathtype,
4027d19b 11743 &display, rpki_target_state);
d62a17ae 11744 }
11745
9bcb3eef 11746 bgp_dest_unlock_node(dest);
d62a17ae 11747 }
11748 }
e5eee9af 11749
d62a17ae 11750 if (use_json) {
996c9314 11751 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11752 json, JSON_C_TO_STRING_PRETTY |
11753 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11754 json_object_free(json);
11755 } else {
11756 if (!display) {
11757 vty_out(vty, "%% Network not in table\n");
11758 return CMD_WARNING;
11759 }
11760 }
b05a1c8b 11761
d62a17ae 11762 return CMD_SUCCESS;
718e3744 11763}
11764
fee0f4c6 11765/* Display specified route of Main RIB */
d62a17ae 11766static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11767 afi_t afi, safi_t safi, struct prefix_rd *prd,
11768 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11769 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11770{
9b86009a 11771 if (!bgp) {
d62a17ae 11772 bgp = bgp_get_default();
9b86009a
RW
11773 if (!bgp) {
11774 if (!use_json)
11775 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11776 else
11777 vty_out(vty, "{}\n");
9b86009a
RW
11778 return CMD_WARNING;
11779 }
11780 }
d62a17ae 11781
11782 /* labeled-unicast routes live in the unicast table */
11783 if (safi == SAFI_LABELED_UNICAST)
11784 safi = SAFI_UNICAST;
11785
11786 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11787 afi, safi, rpki_target_state, prd,
8aa22bbb 11788 prefix_check, pathtype, use_json);
d62a17ae 11789}
11790
11791static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11792 struct cmd_token **argv, bool exact, afi_t afi,
11793 safi_t safi, bool uj)
d62a17ae 11794{
11795 struct lcommunity *lcom;
11796 struct buffer *b;
11797 int i;
11798 char *str;
11799 int first = 0;
96c81f66 11800 uint16_t show_flags = 0;
4f28b2b5 11801 int ret;
96f3485c
MK
11802
11803 if (uj)
11804 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11805
11806 b = buffer_new(1024);
11807 for (i = 0; i < argc; i++) {
11808 if (first)
11809 buffer_putc(b, ' ');
11810 else {
11811 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11812 first = 1;
11813 buffer_putstr(b, argv[i]->arg);
11814 }
11815 }
11816 }
11817 buffer_putc(b, '\0');
57d187bc 11818
d62a17ae 11819 str = buffer_getstr(b);
11820 buffer_free(b);
57d187bc 11821
d62a17ae 11822 lcom = lcommunity_str2com(str);
11823 XFREE(MTYPE_TMP, str);
11824 if (!lcom) {
11825 vty_out(vty, "%% Large-community malformed\n");
11826 return CMD_WARNING;
11827 }
57d187bc 11828
4f28b2b5 11829 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11830 (exact ? bgp_show_type_lcommunity_exact
11831 : bgp_show_type_lcommunity),
11832 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11833
11834 lcommunity_free(&lcom);
11835 return ret;
57d187bc
JS
11836}
11837
d62a17ae 11838static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11839 const char *lcom, bool exact, afi_t afi,
11840 safi_t safi, bool uj)
57d187bc 11841{
d62a17ae 11842 struct community_list *list;
96c81f66 11843 uint16_t show_flags = 0;
96f3485c
MK
11844
11845 if (uj)
11846 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11847
57d187bc 11848
e237b0d2 11849 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11850 LARGE_COMMUNITY_LIST_MASTER);
11851 if (list == NULL) {
11852 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11853 lcom);
11854 return CMD_WARNING;
11855 }
57d187bc 11856
36a206db 11857 return bgp_show(vty, bgp, afi, safi,
11858 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11859 : bgp_show_type_lcommunity_list),
1e2ce4f1 11860 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11861}
11862
52951b63
DS
11863DEFUN (show_ip_bgp_large_community_list,
11864 show_ip_bgp_large_community_list_cmd,
36a206db 11865 "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
11866 SHOW_STR
11867 IP_STR
11868 BGP_STR
11869 BGP_INSTANCE_HELP_STR
9bedbb1e 11870 BGP_AFI_HELP_STR
4dd6177e 11871 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11872 "Display routes matching the large-community-list\n"
11873 "large-community-list number\n"
11874 "large-community-list name\n"
36a206db 11875 "Exact match of the large-communities\n"
52951b63
DS
11876 JSON_STR)
11877{
d62a17ae 11878 afi_t afi = AFI_IP6;
11879 safi_t safi = SAFI_UNICAST;
11880 int idx = 0;
36a206db 11881 bool exact_match = 0;
4d678463 11882 struct bgp *bgp = NULL;
9f049418 11883 bool uj = use_json(argc, argv);
d62a17ae 11884
ef3364f0
DA
11885 if (uj)
11886 argc--;
4d678463 11887
ef3364f0
DA
11888 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11889 &bgp, uj);
11890 if (!idx)
11891 return CMD_WARNING;
d62a17ae 11892
11893 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11894
11895 const char *clist_number_or_name = argv[++idx]->arg;
11896
11897 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11898 exact_match = 1;
11899
11900 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11901 exact_match, afi, safi, uj);
52951b63
DS
11902}
11903DEFUN (show_ip_bgp_large_community,
11904 show_ip_bgp_large_community_cmd,
36a206db 11905 "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
11906 SHOW_STR
11907 IP_STR
11908 BGP_STR
11909 BGP_INSTANCE_HELP_STR
9bedbb1e 11910 BGP_AFI_HELP_STR
4dd6177e 11911 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11912 "Display routes matching the large-communities\n"
11913 "List of large-community numbers\n"
36a206db 11914 "Exact match of the large-communities\n"
52951b63
DS
11915 JSON_STR)
11916{
d62a17ae 11917 afi_t afi = AFI_IP6;
11918 safi_t safi = SAFI_UNICAST;
11919 int idx = 0;
36a206db 11920 bool exact_match = 0;
4d678463 11921 struct bgp *bgp = NULL;
9f049418 11922 bool uj = use_json(argc, argv);
96c81f66 11923 uint16_t show_flags = 0;
d62a17ae 11924
96f3485c
MK
11925 if (uj) {
11926 argc--;
11927 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11928 }
4d678463 11929
96f3485c
MK
11930 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11931 &bgp, uj);
11932 if (!idx)
11933 return CMD_WARNING;
d62a17ae 11934
36a206db 11935 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11936 if (argv_find(argv, argc, "exact-match", &idx))
11937 exact_match = 1;
11938 return bgp_show_lcommunity(vty, bgp, argc, argv,
11939 exact_match, afi, safi, uj);
11940 } else
d62a17ae 11941 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11942 bgp_show_type_lcommunity_all, NULL, show_flags,
11943 RPKI_NOT_BEING_USED);
52951b63
DS
11944}
11945
71f1613a
DA
11946static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11947 safi_t safi, struct json_object *json_array);
d62a17ae 11948static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11949 safi_t safi, struct json_object *json);
e01ca200 11950
7b2ff250 11951
9ab0cf58
PG
11952DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11953 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11954 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11955 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11956{
11957 bool uj = use_json(argc, argv);
11958 struct bgp *bgp = NULL;
ec76a1d1
DA
11959 safi_t safi = SAFI_UNICAST;
11960 afi_t afi = AFI_IP6;
4265b261 11961 int idx = 0;
6c9d22e2
PG
11962 struct json_object *json_all = NULL;
11963 struct json_object *json_afi_safi = NULL;
4265b261
PG
11964
11965 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11966 &bgp, false);
71f1613a 11967 if (!idx)
4265b261 11968 return CMD_WARNING;
6c9d22e2 11969
4265b261 11970 if (uj)
6c9d22e2 11971 json_all = json_object_new_object();
4265b261 11972
9ab0cf58
PG
11973 FOREACH_AFI_SAFI (afi, safi) {
11974 /*
11975 * So limit output to those afi/safi pairs that
11976 * actually have something interesting in them
11977 */
11978 if (strmatch(get_afi_safi_str(afi, safi, true),
11979 "Unknown")) {
11980 continue;
11981 }
11982 if (uj) {
11983 json_afi_safi = json_object_new_array();
11984 json_object_object_add(
11985 json_all,
11986 get_afi_safi_str(afi, safi, true),
11987 json_afi_safi);
11988 } else {
11989 json_afi_safi = NULL;
6c9d22e2 11990 }
9ab0cf58
PG
11991
11992 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11993 }
6c9d22e2
PG
11994
11995 if (uj) {
9ab0cf58
PG
11996 vty_out(vty, "%s",
11997 json_object_to_json_string_ext(
11998 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11999 json_object_free(json_all);
4265b261 12000 }
6c9d22e2 12001
4265b261
PG
12002 return CMD_SUCCESS;
12003}
12004
7b2ff250 12005/* BGP route print out function without JSON */
14718643
PG
12006DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12007 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12008 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12009 SHOW_STR
12010 IP_STR
12011 BGP_STR
12012 BGP_INSTANCE_HELP_STR
12013 L2VPN_HELP_STR
12014 EVPN_HELP_STR
12015 "BGP RIB advertisement statistics\n"
12016 JSON_STR)
12017{
ec76a1d1
DA
12018 afi_t afi = AFI_IP6;
12019 safi_t safi = SAFI_UNICAST;
14718643
PG
12020 struct bgp *bgp = NULL;
12021 int idx = 0, ret;
12022 bool uj = use_json(argc, argv);
12023 struct json_object *json_afi_safi = NULL, *json = NULL;
12024
12025 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12026 &bgp, false);
12027 if (!idx)
12028 return CMD_WARNING;
12029
12030 if (uj)
12031 json_afi_safi = json_object_new_array();
12032 else
12033 json_afi_safi = NULL;
12034
12035 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12036
12037 if (uj) {
12038 json = json_object_new_object();
12039 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12040 json_afi_safi);
12041 vty_out(vty, "%s", json_object_to_json_string_ext(
12042 json, JSON_C_TO_STRING_PRETTY));
12043 json_object_free(json);
12044 }
12045 return ret;
12046}
12047
893cccd0 12048/* BGP route print out function without JSON */
9ab0cf58
PG
12049DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12050 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12051 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12052 "]]\
893cccd0 12053 statistics [json]",
9ab0cf58
PG
12054 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12055 BGP_SAFI_WITH_LABEL_HELP_STR
12056 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12057{
ec76a1d1
DA
12058 afi_t afi = AFI_IP6;
12059 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12060 struct bgp *bgp = NULL;
12061 int idx = 0, ret;
12062 bool uj = use_json(argc, argv);
6c9d22e2 12063 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12064
12065 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12066 &bgp, false);
12067 if (!idx)
12068 return CMD_WARNING;
6c9d22e2 12069
893cccd0 12070 if (uj)
6c9d22e2
PG
12071 json_afi_safi = json_object_new_array();
12072 else
12073 json_afi_safi = NULL;
12074
12075 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12076
12077 if (uj) {
12078 json = json_object_new_object();
12079 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12080 json_afi_safi);
9ab0cf58
PG
12081 vty_out(vty, "%s",
12082 json_object_to_json_string_ext(
12083 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
12084 json_object_free(json);
12085 }
12086 return ret;
893cccd0 12087}
7b2ff250
DW
12088
12089/* BGP route print out function without JSON */
96f3485c 12090DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
12091 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12092 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12093 "]]\
96f3485c 12094 <[all$all] dampening <parameters>\
7b2ff250
DW
12095 |route-map WORD\
12096 |prefix-list WORD\
12097 |filter-list WORD\
7b2ff250
DW
12098 |community-list <(1-500)|WORD> [exact-match]\
12099 |A.B.C.D/M longer-prefixes\
12100 |X:X::X:X/M longer-prefixes\
893cccd0 12101 >",
9ab0cf58
PG
12102 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12103 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12104 "Display the entries for all address families\n"
9ab0cf58
PG
12105 "Display detailed information about dampening\n"
12106 "Display detail of configured dampening parameters\n"
12107 "Display routes matching the route-map\n"
12108 "A route-map to match on\n"
12109 "Display routes conforming to the prefix-list\n"
12110 "Prefix-list name\n"
12111 "Display routes conforming to the filter-list\n"
12112 "Regular expression access list name\n"
12113 "Display routes matching the community-list\n"
12114 "community-list number\n"
12115 "community-list name\n"
12116 "Exact match of the communities\n"
12117 "IPv4 prefix\n"
12118 "Display route and more specific routes\n"
12119 "IPv6 prefix\n"
12120 "Display route and more specific routes\n")
718e3744 12121{
d62a17ae 12122 afi_t afi = AFI_IP6;
12123 safi_t safi = SAFI_UNICAST;
12124 int exact_match = 0;
d62a17ae 12125 struct bgp *bgp = NULL;
12126 int idx = 0;
96c81f66 12127 uint16_t show_flags = 0;
96f3485c
MK
12128
12129 /* [<ipv4|ipv6> [all]] */
12130 if (all) {
12131 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12132 if (argv_find(argv, argc, "ipv4", &idx))
12133 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12134
12135 if (argv_find(argv, argc, "ipv6", &idx))
12136 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12137 }
d62a17ae 12138
12139 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12140 &bgp, false);
d62a17ae 12141 if (!idx)
12142 return CMD_WARNING;
12143
d62a17ae 12144 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 12145 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
12146 return bgp_show_dampening_parameters(vty, afi, safi,
12147 show_flags);
d62a17ae 12148 }
c016b6c7 12149
d62a17ae 12150 if (argv_find(argv, argc, "prefix-list", &idx))
12151 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12152 safi, bgp_show_type_prefix_list);
12153
12154 if (argv_find(argv, argc, "filter-list", &idx))
12155 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12156 safi, bgp_show_type_filter_list);
12157
d62a17ae 12158 if (argv_find(argv, argc, "route-map", &idx))
12159 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12160 safi, bgp_show_type_route_map);
12161
d62a17ae 12162 if (argv_find(argv, argc, "community-list", &idx)) {
12163 const char *clist_number_or_name = argv[++idx]->arg;
12164 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12165 exact_match = 1;
12166 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12167 exact_match, afi, safi);
12168 }
12169 /* prefix-longer */
12170 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12171 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12172 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12173 safi,
12174 bgp_show_type_prefix_longer);
12175
7b2ff250
DW
12176 return CMD_WARNING;
12177}
12178
12179/* BGP route print out function with JSON */
a70a28a5
DA
12180DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12181 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12182 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12183 "]]\
96f3485c 12184 [all$all]\
cf4898bc
QY
12185 [cidr-only\
12186 |dampening <flap-statistics|dampened-paths>\
12187 |community [AA:NN|local-AS|no-advertise|no-export\
12188 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12189 |accept-own|accept-own-nexthop|route-filter-v6\
12190 |route-filter-v4|route-filter-translated-v6\
12191 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 12192 |rpki <invalid|valid|notfound>\
7d3cae70 12193 |version (1-4294967295)\
b4ad2fae 12194 |alias ALIAS_NAME\
f280c93b 12195 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12196 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12197 BGP_SAFI_WITH_LABEL_HELP_STR
12198 "Display the entries for all address families\n"
12199 "Display only routes with non-natural netmasks\n"
12200 "Display detailed information about dampening\n"
12201 "Display flap statistics of routes\n"
12202 "Display paths suppressed due to dampening\n"
12203 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12204 "Do not send outside local AS (well-known community)\n"
12205 "Do not advertise to any peer (well-known community)\n"
12206 "Do not export to next AS (well-known community)\n"
12207 "Graceful shutdown (well-known community)\n"
12208 "Do not export to any peer (well-known community)\n"
12209 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12210 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12211 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12212 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12213 "Should accept VPN route with local nexthop (well-known community)\n"
12214 "RT VPNv6 route filtering (well-known community)\n"
12215 "RT VPNv4 route filtering (well-known community)\n"
12216 "RT translated VPNv6 route filtering (well-known community)\n"
12217 "RT translated VPNv4 route filtering (well-known community)\n"
12218 "Exact match of the communities\n"
12219 "RPKI route types\n"
12220 "A valid path as determined by rpki\n"
12221 "A invalid path as determined by rpki\n"
12222 "A path that has no rpki data\n"
12223 "Display prefixes with matching version numbers\n"
12224 "Version number and above\n"
12225 "Display prefixes with matching BGP community alias\n"
12226 "BGP community alias\n" JSON_STR
12227 "Display detailed version of JSON output\n"
12228 "Increase table width for longer prefixes\n")
7b2ff250
DW
12229{
12230 afi_t afi = AFI_IP6;
12231 safi_t safi = SAFI_UNICAST;
12232 enum bgp_show_type sh_type = bgp_show_type_normal;
12233 struct bgp *bgp = NULL;
12234 int idx = 0;
d0086e8e 12235 int exact_match = 0;
96f3485c 12236 char *community = NULL;
7d3cae70 12237 char *prefix_version = NULL;
a70a28a5 12238 char *bgp_community_alias = NULL;
96f3485c 12239 bool first = true;
96c81f66 12240 uint16_t show_flags = 0;
4027d19b 12241 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12242
12243 if (uj) {
9f049418 12244 argc--;
96f3485c
MK
12245 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12246 }
12247
f280c93b
DA
12248 if (detail)
12249 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12250
96f3485c
MK
12251 /* [<ipv4|ipv6> [all]] */
12252 if (all) {
12253 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12254
12255 if (argv_find(argv, argc, "ipv4", &idx))
12256 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12257
12258 if (argv_find(argv, argc, "ipv6", &idx))
12259 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12260 }
12261
12262 if (wide)
12263 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12264
12265 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12266 &bgp, uj);
7b2ff250
DW
12267 if (!idx)
12268 return CMD_WARNING;
12269
7b2ff250 12270 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12271 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12272
12273 if (argv_find(argv, argc, "dampening", &idx)) {
12274 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12275 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12276 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12277 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12278 }
12279
12280 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12281 char *maybecomm = NULL;
d0086e8e 12282
79bc257a
RW
12283 if (idx + 1 < argc) {
12284 if (argv[idx + 1]->type == VARIABLE_TKN)
12285 maybecomm = argv[idx + 1]->arg;
12286 else
12287 maybecomm = argv[idx + 1]->text;
12288 }
12289
cf4898bc
QY
12290 if (maybecomm && !strmatch(maybecomm, "json")
12291 && !strmatch(maybecomm, "exact-match"))
12292 community = maybecomm;
d0086e8e 12293
cf4898bc
QY
12294 if (argv_find(argv, argc, "exact-match", &idx))
12295 exact_match = 1;
d0086e8e 12296
96f3485c
MK
12297 if (!community)
12298 sh_type = bgp_show_type_community_all;
12299 }
12300
1e2ce4f1
DS
12301 if (argv_find(argv, argc, "rpki", &idx)) {
12302 sh_type = bgp_show_type_rpki;
12303 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12304 rpki_target_state = RPKI_VALID;
1e2ce4f1 12305 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12306 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12307 }
12308
7d3cae70
DA
12309 /* Display prefixes with matching version numbers */
12310 if (argv_find(argv, argc, "version", &idx)) {
12311 sh_type = bgp_show_type_prefix_version;
12312 prefix_version = argv[idx + 1]->arg;
12313 }
12314
a70a28a5
DA
12315 /* Display prefixes with matching BGP community alias */
12316 if (argv_find(argv, argc, "alias", &idx)) {
12317 sh_type = bgp_show_type_community_alias;
12318 bgp_community_alias = argv[idx + 1]->arg;
12319 }
12320
96f3485c
MK
12321 if (!all) {
12322 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12323 if (community)
12324 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12325 exact_match, afi, safi,
12326 show_flags);
7d3cae70
DA
12327 else if (prefix_version)
12328 return bgp_show(vty, bgp, afi, safi, sh_type,
12329 prefix_version, show_flags,
12330 rpki_target_state);
a70a28a5
DA
12331 else if (bgp_community_alias)
12332 return bgp_show(vty, bgp, afi, safi, sh_type,
12333 bgp_community_alias, show_flags,
12334 rpki_target_state);
cf4898bc 12335 else
96f3485c 12336 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12337 show_flags, rpki_target_state);
96f3485c
MK
12338 } else {
12339 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12340 * AFI_IP6 */
12341
12342 if (uj)
12343 vty_out(vty, "{\n");
12344
12345 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12346 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12347 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12348 ? AFI_IP
12349 : AFI_IP6;
12350 FOREACH_SAFI (safi) {
96f3485c
MK
12351 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12352 continue;
12353
12354 if (uj) {
12355 if (first)
12356 first = false;
12357 else
12358 vty_out(vty, ",\n");
12359 vty_out(vty, "\"%s\":{\n",
12360 get_afi_safi_str(afi, safi,
12361 true));
12362 } else
12363 vty_out(vty,
12364 "\nFor address family: %s\n",
12365 get_afi_safi_str(afi, safi,
12366 false));
12367
12368 if (community)
12369 bgp_show_community(vty, bgp, community,
12370 exact_match, afi,
12371 safi, show_flags);
7d3cae70
DA
12372 else if (prefix_version)
12373 return bgp_show(vty, bgp, afi, safi,
12374 sh_type, prefix_version,
12375 show_flags,
12376 rpki_target_state);
a70a28a5
DA
12377 else if (bgp_community_alias)
12378 return bgp_show(
12379 vty, bgp, afi, safi, sh_type,
12380 bgp_community_alias, show_flags,
12381 rpki_target_state);
96f3485c
MK
12382 else
12383 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12384 NULL, show_flags,
4027d19b 12385 rpki_target_state);
96f3485c
MK
12386 if (uj)
12387 vty_out(vty, "}\n");
12388 }
12389 } else {
12390 /* show <ip> bgp all: for each AFI and SAFI*/
12391 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12392 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12393 continue;
12394
12395 if (uj) {
12396 if (first)
12397 first = false;
12398 else
12399 vty_out(vty, ",\n");
d0086e8e 12400
96f3485c
MK
12401 vty_out(vty, "\"%s\":{\n",
12402 get_afi_safi_str(afi, safi,
12403 true));
12404 } else
12405 vty_out(vty,
12406 "\nFor address family: %s\n",
12407 get_afi_safi_str(afi, safi,
12408 false));
12409
12410 if (community)
12411 bgp_show_community(vty, bgp, community,
12412 exact_match, afi,
12413 safi, show_flags);
7d3cae70
DA
12414 else if (prefix_version)
12415 return bgp_show(vty, bgp, afi, safi,
12416 sh_type, prefix_version,
12417 show_flags,
12418 rpki_target_state);
96f3485c
MK
12419 else
12420 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12421 NULL, show_flags,
4027d19b 12422 rpki_target_state);
96f3485c
MK
12423 if (uj)
12424 vty_out(vty, "}\n");
12425 }
12426 }
12427 if (uj)
12428 vty_out(vty, "}\n");
12429 }
12430 return CMD_SUCCESS;
a636c635 12431}
47fc97cc 12432
718e3744 12433DEFUN (show_ip_bgp_route,
12434 show_ip_bgp_route_cmd,
8aa22bbb 12435 "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>] [rpki <valid|invalid|notfound>] [json]",
718e3744 12436 SHOW_STR
12437 IP_STR
12438 BGP_STR
a636c635 12439 BGP_INSTANCE_HELP_STR
4f280b15 12440 BGP_AFI_HELP_STR
4dd6177e 12441 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12442 "Network in the BGP routing table to display\n"
0c7b1b01 12443 "IPv4 prefix\n"
8c3deaae 12444 "Network in the BGP routing table to display\n"
0c7b1b01 12445 "IPv6 prefix\n"
4092b06c 12446 "Display only the bestpath\n"
b05a1c8b 12447 "Display only multipaths\n"
8aa22bbb
DS
12448 "Display only paths that match the specified rpki state\n"
12449 "A valid path as determined by rpki\n"
12450 "A invalid path as determined by rpki\n"
12451 "A path that has no rpki data\n"
9973d184 12452 JSON_STR)
4092b06c 12453{
d62a17ae 12454 int prefix_check = 0;
ae19d7dd 12455
d62a17ae 12456 afi_t afi = AFI_IP6;
12457 safi_t safi = SAFI_UNICAST;
12458 char *prefix = NULL;
12459 struct bgp *bgp = NULL;
12460 enum bgp_path_type path_type;
9f049418 12461 bool uj = use_json(argc, argv);
b05a1c8b 12462
d62a17ae 12463 int idx = 0;
ae19d7dd 12464
d62a17ae 12465 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12466 &bgp, uj);
d62a17ae 12467 if (!idx)
12468 return CMD_WARNING;
c41247f5 12469
d62a17ae 12470 if (!bgp) {
12471 vty_out(vty,
12472 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12473 return CMD_WARNING;
12474 }
a636c635 12475
d62a17ae 12476 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12477 if (argv_find(argv, argc, "A.B.C.D", &idx)
12478 || argv_find(argv, argc, "X:X::X:X", &idx))
12479 prefix_check = 0;
12480 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12481 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12482 prefix_check = 1;
12483
12484 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12485 && afi != AFI_IP6) {
12486 vty_out(vty,
12487 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12488 return CMD_WARNING;
12489 }
12490 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12491 && afi != AFI_IP) {
12492 vty_out(vty,
12493 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12494 return CMD_WARNING;
12495 }
12496
12497 prefix = argv[idx]->arg;
12498
12499 /* [<bestpath|multipath>] */
12500 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12501 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12502 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12503 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12504 else
360660c6 12505 path_type = BGP_PATH_SHOW_ALL;
a636c635 12506
d62a17ae 12507 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12508 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12509}
12510
8c3deaae
QY
12511DEFUN (show_ip_bgp_regexp,
12512 show_ip_bgp_regexp_cmd,
3e5b31b3 12513 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12514 SHOW_STR
12515 IP_STR
12516 BGP_STR
b00b230a 12517 BGP_INSTANCE_HELP_STR
4f280b15 12518 BGP_AFI_HELP_STR
4dd6177e 12519 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12520 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12521 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12522 JSON_STR)
8c3deaae 12523{
d62a17ae 12524 afi_t afi = AFI_IP6;
12525 safi_t safi = SAFI_UNICAST;
12526 struct bgp *bgp = NULL;
3e5b31b3
DA
12527 bool uj = use_json(argc, argv);
12528 char *regstr = NULL;
8c3deaae 12529
d62a17ae 12530 int idx = 0;
12531 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12532 &bgp, false);
d62a17ae 12533 if (!idx)
12534 return CMD_WARNING;
8c3deaae 12535
d62a17ae 12536 // get index of regex
3e5b31b3
DA
12537 if (argv_find(argv, argc, "REGEX", &idx))
12538 regstr = argv[idx]->arg;
8c3deaae 12539
5f71d11c 12540 assert(regstr);
3e5b31b3
DA
12541 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12542 bgp_show_type_regexp, uj);
8c3deaae
QY
12543}
12544
ae248832 12545DEFPY (show_ip_bgp_instance_all,
a636c635 12546 show_ip_bgp_instance_all_cmd,
ae248832 12547 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12548 SHOW_STR
a636c635 12549 IP_STR
4092b06c 12550 BGP_STR
a636c635 12551 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12552 BGP_AFI_HELP_STR
4dd6177e 12553 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12554 JSON_STR
12555 "Increase table width for longer prefixes\n")
4092b06c 12556{
d62a17ae 12557 afi_t afi = AFI_IP;
12558 safi_t safi = SAFI_UNICAST;
12559 struct bgp *bgp = NULL;
d62a17ae 12560 int idx = 0;
96c81f66 12561 uint16_t show_flags = 0;
ae19d7dd 12562
96f3485c 12563 if (uj) {
d62a17ae 12564 argc--;
96f3485c
MK
12565 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12566 }
12567
12568 if (wide)
12569 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12570
9f049418
DS
12571 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12572 &bgp, uj);
12573 if (!idx)
12574 return CMD_WARNING;
12575
96f3485c 12576 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12577 return CMD_SUCCESS;
e3e29b32
LB
12578}
12579
a4d82a8a 12580static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12581 afi_t afi, safi_t safi, enum bgp_show_type type,
12582 bool use_json)
718e3744 12583{
d62a17ae 12584 regex_t *regex;
12585 int rc;
96c81f66 12586 uint16_t show_flags = 0;
96f3485c
MK
12587
12588 if (use_json)
12589 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12590
c3900853 12591 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12592 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12593 regstr);
12594 return CMD_WARNING_CONFIG_FAILED;
12595 }
12596
d62a17ae 12597 regex = bgp_regcomp(regstr);
12598 if (!regex) {
12599 vty_out(vty, "Can't compile regexp %s\n", regstr);
12600 return CMD_WARNING;
12601 }
a636c635 12602
1e2ce4f1
DS
12603 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12604 RPKI_NOT_BEING_USED);
d62a17ae 12605 bgp_regex_free(regex);
12606 return rc;
e3e29b32
LB
12607}
12608
d62a17ae 12609static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12610 const char *prefix_list_str, afi_t afi,
12611 safi_t safi, enum bgp_show_type type)
e3e29b32 12612{
d62a17ae 12613 struct prefix_list *plist;
96c81f66 12614 uint16_t show_flags = 0;
718e3744 12615
d62a17ae 12616 plist = prefix_list_lookup(afi, prefix_list_str);
12617 if (plist == NULL) {
12618 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12619 prefix_list_str);
12620 return CMD_WARNING;
12621 }
718e3744 12622
1e2ce4f1
DS
12623 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12624 RPKI_NOT_BEING_USED);
4092b06c
DS
12625}
12626
d62a17ae 12627static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12628 const char *filter, afi_t afi, safi_t safi,
12629 enum bgp_show_type type)
4092b06c 12630{
d62a17ae 12631 struct as_list *as_list;
96c81f66 12632 uint16_t show_flags = 0;
718e3744 12633
d62a17ae 12634 as_list = as_list_lookup(filter);
12635 if (as_list == NULL) {
12636 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12637 filter);
12638 return CMD_WARNING;
12639 }
a636c635 12640
1e2ce4f1
DS
12641 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12642 RPKI_NOT_BEING_USED);
718e3744 12643}
12644
d62a17ae 12645static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12646 const char *rmap_str, afi_t afi, safi_t safi,
12647 enum bgp_show_type type)
718e3744 12648{
d62a17ae 12649 struct route_map *rmap;
96c81f66 12650 uint16_t show_flags = 0;
bb46e94f 12651
d62a17ae 12652 rmap = route_map_lookup_by_name(rmap_str);
12653 if (!rmap) {
12654 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12655 return CMD_WARNING;
12656 }
12657
1e2ce4f1
DS
12658 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12659 RPKI_NOT_BEING_USED);
d62a17ae 12660}
12661
7f323236
DW
12662static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12663 const char *comstr, int exact, afi_t afi,
96c81f66 12664 safi_t safi, uint16_t show_flags)
d62a17ae 12665{
12666 struct community *com;
d62a17ae 12667 int ret = 0;
12668
7f323236 12669 com = community_str2com(comstr);
d62a17ae 12670 if (!com) {
7f323236 12671 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12672 return CMD_WARNING;
12673 }
12674
12675 ret = bgp_show(vty, bgp, afi, safi,
12676 (exact ? bgp_show_type_community_exact
12677 : bgp_show_type_community),
1e2ce4f1 12678 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12679 community_free(&com);
46c3ce83 12680
d62a17ae 12681 return ret;
718e3744 12682}
12683
d62a17ae 12684static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12685 const char *com, int exact, afi_t afi,
12686 safi_t safi)
50ef26d4 12687{
d62a17ae 12688 struct community_list *list;
96c81f66 12689 uint16_t show_flags = 0;
50ef26d4 12690
e237b0d2 12691 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12692 if (list == NULL) {
12693 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12694 return CMD_WARNING;
12695 }
718e3744 12696
d62a17ae 12697 return bgp_show(vty, bgp, afi, safi,
12698 (exact ? bgp_show_type_community_list_exact
12699 : bgp_show_type_community_list),
1e2ce4f1 12700 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12701}
12702
d62a17ae 12703static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12704 const char *prefix, afi_t afi, safi_t safi,
12705 enum bgp_show_type type)
718e3744 12706{
d62a17ae 12707 int ret;
12708 struct prefix *p;
96c81f66 12709 uint16_t show_flags = 0;
47fc97cc 12710
d62a17ae 12711 p = prefix_new();
95cbbd2a 12712
d62a17ae 12713 ret = str2prefix(prefix, p);
12714 if (!ret) {
12715 vty_out(vty, "%% Malformed Prefix\n");
12716 return CMD_WARNING;
12717 }
47e9b292 12718
1e2ce4f1
DS
12719 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12720 RPKI_NOT_BEING_USED);
63265b5c 12721 prefix_free(&p);
d62a17ae 12722 return ret;
12723}
12724
d62a17ae 12725enum bgp_stats {
12726 BGP_STATS_MAXBITLEN = 0,
12727 BGP_STATS_RIB,
12728 BGP_STATS_PREFIXES,
12729 BGP_STATS_TOTPLEN,
12730 BGP_STATS_UNAGGREGATEABLE,
12731 BGP_STATS_MAX_AGGREGATEABLE,
12732 BGP_STATS_AGGREGATES,
12733 BGP_STATS_SPACE,
12734 BGP_STATS_ASPATH_COUNT,
12735 BGP_STATS_ASPATH_MAXHOPS,
12736 BGP_STATS_ASPATH_TOTHOPS,
12737 BGP_STATS_ASPATH_MAXSIZE,
12738 BGP_STATS_ASPATH_TOTSIZE,
12739 BGP_STATS_ASN_HIGHEST,
12740 BGP_STATS_MAX,
a636c635 12741};
2815e61f 12742
9ab0cf58 12743#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12744#define TABLE_STATS_IDX_JSON 1
12745
12746static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12747 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12748 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12749 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12750 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12751 "unaggregateablePrefixes"},
12752 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12753 "maximumAggregateablePrefixes"},
12754 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12755 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12756 [BGP_STATS_SPACE] = {"Address space advertised",
12757 "addressSpaceAdvertised"},
9ab0cf58
PG
12758 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12759 "advertisementsWithPaths"},
12760 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12761 "longestAsPath"},
12762 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12763 "largestAsPath"},
12764 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12765 "averageAsPathLengthHops"},
12766 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12767 "averageAsPathSizeBytes"},
12768 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12769 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12770};
2815e61f 12771
d62a17ae 12772struct bgp_table_stats {
12773 struct bgp_table *table;
12774 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12775 double total_space;
ff7924f6
PJ
12776};
12777
9bcb3eef 12778static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12779 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12780{
9bcb3eef 12781 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12782 struct bgp_path_info *pi;
b54892e0 12783 const struct prefix *rn_p;
d62a17ae 12784
9bcb3eef 12785 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12786 return;
d62a17ae 12787
9bcb3eef 12788 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12789 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12790 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12791
9c14ec72 12792 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12793 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12794 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12795
9bcb3eef 12796 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12797 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12798 /* announced address space */
12799 if (space)
b54892e0 12800 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12801 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12802 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12803
9c14ec72 12804
9bcb3eef 12805 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12806 ts->counts[BGP_STATS_RIB]++;
12807
05864da7
DS
12808 if (CHECK_FLAG(pi->attr->flag,
12809 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12810 ts->counts[BGP_STATS_AGGREGATES]++;
12811
12812 /* as-path stats */
05864da7 12813 if (pi->attr->aspath) {
9c14ec72
RW
12814 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12815 unsigned int size = aspath_size(pi->attr->aspath);
12816 as_t highest = aspath_highest(pi->attr->aspath);
12817
12818 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12819
12820 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12821 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12822
12823 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12824 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12825
12826 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12827 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12828 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12829 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12830 }
12831 }
12832}
12833
12834static int bgp_table_stats_walker(struct thread *t)
12835{
9bcb3eef
DS
12836 struct bgp_dest *dest, *ndest;
12837 struct bgp_dest *top;
9c14ec72
RW
12838 struct bgp_table_stats *ts = THREAD_ARG(t);
12839 unsigned int space = 0;
12840
12841 if (!(top = bgp_table_top(ts->table)))
12842 return 0;
12843
12844 switch (ts->table->afi) {
12845 case AFI_IP:
12846 space = IPV4_MAX_BITLEN;
12847 break;
12848 case AFI_IP6:
12849 space = IPV6_MAX_BITLEN;
12850 break;
3ba7b4af
TA
12851 case AFI_L2VPN:
12852 space = EVPN_ROUTE_PREFIXLEN;
12853 break;
9c14ec72
RW
12854 default:
12855 return 0;
12856 }
12857
12858 ts->counts[BGP_STATS_MAXBITLEN] = space;
12859
9bcb3eef 12860 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12861 if (ts->table->safi == SAFI_MPLS_VPN
12862 || ts->table->safi == SAFI_ENCAP
12863 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12864 struct bgp_table *table;
12865
9bcb3eef 12866 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12867 if (!table)
12868 continue;
12869
12870 top = bgp_table_top(table);
9bcb3eef
DS
12871 for (ndest = bgp_table_top(table); ndest;
12872 ndest = bgp_route_next(ndest))
12873 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12874 } else {
9bcb3eef 12875 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12876 }
12877 }
9c14ec72 12878
d62a17ae 12879 return 0;
2815e61f 12880}
ff7924f6 12881
71f1613a
DA
12882static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12883 struct json_object *json_array)
12884{
12885 struct listnode *node, *nnode;
12886 struct bgp *bgp;
12887
12888 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12889 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12890}
12891
12892static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12893 safi_t safi, struct json_object *json_array)
2815e61f 12894{
d62a17ae 12895 struct bgp_table_stats ts;
12896 unsigned int i;
893cccd0
PG
12897 int ret = CMD_SUCCESS;
12898 char temp_buf[20];
6c9d22e2
PG
12899 struct json_object *json = NULL;
12900
12901 if (json_array)
12902 json = json_object_new_object();
019386c2 12903
d62a17ae 12904 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12905 char warning_msg[50];
12906
12907 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12908 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12909 safi);
6c9d22e2
PG
12910
12911 if (!json)
893cccd0
PG
12912 vty_out(vty, "%s\n", warning_msg);
12913 else
9ab0cf58 12914 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12915
893cccd0
PG
12916 ret = CMD_WARNING;
12917 goto end_table_stats;
d62a17ae 12918 }
019386c2 12919
893cccd0 12920 if (!json)
5290ceab
DA
12921 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12922 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12923 else
12924 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12925
d62a17ae 12926 /* labeled-unicast routes live in the unicast table */
12927 if (safi == SAFI_LABELED_UNICAST)
12928 safi = SAFI_UNICAST;
019386c2 12929
d62a17ae 12930 memset(&ts, 0, sizeof(ts));
12931 ts.table = bgp->rib[afi][safi];
12932 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12933
d62a17ae 12934 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12935 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12936 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12937 continue;
12938
12939 switch (i) {
d62a17ae 12940 case BGP_STATS_ASPATH_TOTHOPS:
12941 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12942 if (!json) {
9ab0cf58
PG
12943 snprintf(
12944 temp_buf, sizeof(temp_buf), "%12.2f",
12945 ts.counts[i]
12946 ? (float)ts.counts[i]
12947 / (float)ts.counts
12948 [BGP_STATS_ASPATH_COUNT]
12949 : 0);
893cccd0 12950 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12951 table_stats_strs[i]
12952 [TABLE_STATS_IDX_VTY],
893cccd0 12953 temp_buf);
9ab0cf58
PG
12954 } else {
12955 json_object_double_add(
12956 json,
12957 table_stats_strs[i]
12958 [TABLE_STATS_IDX_JSON],
12959 ts.counts[i]
12960 ? (double)ts.counts[i]
12961 / (double)ts.counts
d62a17ae 12962 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12963 : 0);
12964 }
d62a17ae 12965 break;
12966 case BGP_STATS_TOTPLEN:
6c9d22e2 12967 if (!json) {
9ab0cf58
PG
12968 snprintf(
12969 temp_buf, sizeof(temp_buf), "%12.2f",
12970 ts.counts[i]
12971 ? (float)ts.counts[i]
12972 / (float)ts.counts
12973 [BGP_STATS_PREFIXES]
12974 : 0);
893cccd0 12975 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12976 table_stats_strs[i]
12977 [TABLE_STATS_IDX_VTY],
893cccd0 12978 temp_buf);
9ab0cf58
PG
12979 } else {
12980 json_object_double_add(
12981 json,
12982 table_stats_strs[i]
12983 [TABLE_STATS_IDX_JSON],
12984 ts.counts[i]
12985 ? (double)ts.counts[i]
12986 / (double)ts.counts
d62a17ae 12987 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12988 : 0);
12989 }
d62a17ae 12990 break;
12991 case BGP_STATS_SPACE:
6c9d22e2
PG
12992 if (!json) {
12993 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12994 ts.total_space);
893cccd0 12995 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12996 table_stats_strs[i]
12997 [TABLE_STATS_IDX_VTY],
893cccd0 12998 temp_buf);
9ab0cf58
PG
12999 } else {
13000 json_object_double_add(
13001 json,
13002 table_stats_strs[i]
13003 [TABLE_STATS_IDX_JSON],
13004 (double)ts.total_space);
13005 }
8d0ab76d 13006 if (afi == AFI_IP6) {
6c9d22e2
PG
13007 if (!json) {
13008 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13009 "%12g",
13010 ts.total_space
13011 * pow(2.0, -128 + 32));
6c9d22e2
PG
13012 vty_out(vty, "%30s: %s\n",
13013 "/32 equivalent %s\n",
13014 temp_buf);
9ab0cf58
PG
13015 } else {
13016 json_object_double_add(
13017 json, "/32equivalent",
13018 (double)(ts.total_space
13019 * pow(2.0,
13020 -128 + 32)));
13021 }
6c9d22e2
PG
13022 if (!json) {
13023 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13024 "%12g",
13025 ts.total_space
13026 * pow(2.0, -128 + 48));
6c9d22e2
PG
13027 vty_out(vty, "%30s: %s\n",
13028 "/48 equivalent %s\n",
13029 temp_buf);
9ab0cf58
PG
13030 } else {
13031 json_object_double_add(
13032 json, "/48equivalent",
13033 (double)(ts.total_space
13034 * pow(2.0,
13035 -128 + 48)));
13036 }
8d0ab76d 13037 } else {
6c9d22e2
PG
13038 if (!json) {
13039 snprintf(temp_buf, sizeof(temp_buf),
13040 "%12.2f",
9ab0cf58
PG
13041 ts.total_space * 100.
13042 * pow(2.0, -32));
6c9d22e2 13043 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13044 "% announced ", temp_buf);
13045 } else {
13046 json_object_double_add(
13047 json, "%announced",
13048 (double)(ts.total_space * 100.
13049 * pow(2.0, -32)));
13050 }
6c9d22e2
PG
13051 if (!json) {
13052 snprintf(temp_buf, sizeof(temp_buf),
13053 "%12.2f",
9ab0cf58
PG
13054 ts.total_space
13055 * pow(2.0, -32 + 8));
6c9d22e2
PG
13056 vty_out(vty, "%30s: %s\n",
13057 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13058 } else {
13059 json_object_double_add(
13060 json, "/8equivalent",
13061 (double)(ts.total_space
13062 * pow(2.0, -32 + 8)));
13063 }
6c9d22e2
PG
13064 if (!json) {
13065 snprintf(temp_buf, sizeof(temp_buf),
13066 "%12.2f",
9ab0cf58
PG
13067 ts.total_space
13068 * pow(2.0, -32 + 24));
6c9d22e2 13069 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13070 "/24 equivalent ", temp_buf);
13071 } else {
13072 json_object_double_add(
13073 json, "/24equivalent",
13074 (double)(ts.total_space
13075 * pow(2.0, -32 + 24)));
13076 }
8d0ab76d 13077 }
d62a17ae 13078 break;
13079 default:
6c9d22e2
PG
13080 if (!json) {
13081 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13082 ts.counts[i]);
893cccd0 13083 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13084 table_stats_strs[i]
13085 [TABLE_STATS_IDX_VTY],
13086 temp_buf);
13087 } else {
13088 json_object_int_add(
13089 json,
13090 table_stats_strs[i]
13091 [TABLE_STATS_IDX_JSON],
13092 ts.counts[i]);
13093 }
d62a17ae 13094 }
893cccd0
PG
13095 if (!json)
13096 vty_out(vty, "\n");
d62a17ae 13097 }
9ab0cf58 13098end_table_stats:
6c9d22e2
PG
13099 if (json)
13100 json_object_array_add(json_array, json);
893cccd0 13101 return ret;
d62a17ae 13102}
13103
71f1613a
DA
13104static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13105 safi_t safi, struct json_object *json_array)
13106{
13107 if (!bgp) {
13108 bgp_table_stats_all(vty, afi, safi, json_array);
13109 return CMD_SUCCESS;
13110 }
13111
13112 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13113}
13114
d62a17ae 13115enum bgp_pcounts {
13116 PCOUNT_ADJ_IN = 0,
13117 PCOUNT_DAMPED,
13118 PCOUNT_REMOVED,
13119 PCOUNT_HISTORY,
13120 PCOUNT_STALE,
13121 PCOUNT_VALID,
13122 PCOUNT_ALL,
13123 PCOUNT_COUNTED,
7e3d9632 13124 PCOUNT_BPATH_SELECTED,
d62a17ae 13125 PCOUNT_PFCNT, /* the figure we display to users */
13126 PCOUNT_MAX,
a636c635 13127};
718e3744 13128
2b64873d 13129static const char *const pcount_strs[] = {
9d303b37
DL
13130 [PCOUNT_ADJ_IN] = "Adj-in",
13131 [PCOUNT_DAMPED] = "Damped",
13132 [PCOUNT_REMOVED] = "Removed",
13133 [PCOUNT_HISTORY] = "History",
13134 [PCOUNT_STALE] = "Stale",
13135 [PCOUNT_VALID] = "Valid",
13136 [PCOUNT_ALL] = "All RIB",
13137 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13138 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13139 [PCOUNT_PFCNT] = "Useable",
13140 [PCOUNT_MAX] = NULL,
a636c635 13141};
718e3744 13142
d62a17ae 13143struct peer_pcounts {
13144 unsigned int count[PCOUNT_MAX];
13145 const struct peer *peer;
13146 const struct bgp_table *table;
54317cba 13147 safi_t safi;
a636c635 13148};
47fc97cc 13149
9bcb3eef 13150static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13151{
54317cba
JW
13152 const struct bgp_adj_in *ain;
13153 const struct bgp_path_info *pi;
d62a17ae 13154 const struct peer *peer = pc->peer;
13155
54317cba
JW
13156 for (ain = rn->adj_in; ain; ain = ain->next)
13157 if (ain->peer == peer)
13158 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13159
9bcb3eef 13160 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13161
54317cba
JW
13162 if (pi->peer != peer)
13163 continue;
d62a17ae 13164
54317cba 13165 pc->count[PCOUNT_ALL]++;
d62a17ae 13166
54317cba
JW
13167 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13168 pc->count[PCOUNT_DAMPED]++;
13169 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13170 pc->count[PCOUNT_HISTORY]++;
13171 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13172 pc->count[PCOUNT_REMOVED]++;
13173 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13174 pc->count[PCOUNT_STALE]++;
13175 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13176 pc->count[PCOUNT_VALID]++;
13177 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13178 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13179 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13180 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13181
13182 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13183 pc->count[PCOUNT_COUNTED]++;
13184 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13185 flog_err(
13186 EC_LIB_DEVELOPMENT,
13187 "Attempting to count but flags say it is unusable");
13188 } else {
40381db7 13189 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13190 flog_err(
13191 EC_LIB_DEVELOPMENT,
13192 "Not counted but flags say we should");
d62a17ae 13193 }
13194 }
54317cba
JW
13195}
13196
13197static int bgp_peer_count_walker(struct thread *t)
13198{
9bcb3eef 13199 struct bgp_dest *rn, *rm;
54317cba
JW
13200 const struct bgp_table *table;
13201 struct peer_pcounts *pc = THREAD_ARG(t);
13202
13203 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13204 || pc->safi == SAFI_EVPN) {
13205 /* Special handling for 2-level routing tables. */
13206 for (rn = bgp_table_top(pc->table); rn;
13207 rn = bgp_route_next(rn)) {
9bcb3eef 13208 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13209 if (table != NULL)
13210 for (rm = bgp_table_top(table); rm;
13211 rm = bgp_route_next(rm))
13212 bgp_peer_count_proc(rm, pc);
13213 }
13214 } else
13215 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13216 bgp_peer_count_proc(rn, pc);
13217
d62a17ae 13218 return 0;
718e3744 13219}
13220
d62a17ae 13221static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13222 safi_t safi, bool use_json)
856ca177 13223{
d62a17ae 13224 struct peer_pcounts pcounts = {.peer = peer};
13225 unsigned int i;
13226 json_object *json = NULL;
13227 json_object *json_loop = NULL;
856ca177 13228
d62a17ae 13229 if (use_json) {
13230 json = json_object_new_object();
13231 json_loop = json_object_new_object();
13232 }
718e3744 13233
d62a17ae 13234 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13235 || !peer->bgp->rib[afi][safi]) {
13236 if (use_json) {
13237 json_object_string_add(
13238 json, "warning",
13239 "No such neighbor or address family");
13240 vty_out(vty, "%s\n", json_object_to_json_string(json));
13241 json_object_free(json);
d5f20468 13242 json_object_free(json_loop);
d62a17ae 13243 } else
13244 vty_out(vty, "%% No such neighbor or address family\n");
13245
13246 return CMD_WARNING;
13247 }
2a71e9ce 13248
d62a17ae 13249 memset(&pcounts, 0, sizeof(pcounts));
13250 pcounts.peer = peer;
13251 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13252 pcounts.safi = safi;
d62a17ae 13253
13254 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13255 * stats for the thread-walk (i.e. ensure this can't be blamed on
13256 * on just vty_read()).
13257 */
d62a17ae 13258 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13259
13260 if (use_json) {
13261 json_object_string_add(json, "prefixCountsFor", peer->host);
13262 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13263 get_afi_safi_str(afi, safi, true));
d62a17ae 13264 json_object_int_add(json, "pfxCounter",
13265 peer->pcount[afi][safi]);
13266
13267 for (i = 0; i < PCOUNT_MAX; i++)
13268 json_object_int_add(json_loop, pcount_strs[i],
13269 pcounts.count[i]);
13270
13271 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13272
13273 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13274 json_object_string_add(json, "pfxctDriftFor",
13275 peer->host);
13276 json_object_string_add(
13277 json, "recommended",
13278 "Please report this bug, with the above command output");
13279 }
996c9314
LB
13280 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13281 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13282 json_object_free(json);
13283 } else {
13284
13285 if (peer->hostname
892fedb6 13286 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13287 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13288 peer->hostname, peer->host,
5cb5f4d0 13289 get_afi_safi_str(afi, safi, false));
d62a17ae 13290 } else {
13291 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13292 get_afi_safi_str(afi, safi, false));
d62a17ae 13293 }
13294
6cde4b45 13295 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13296 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13297
13298 for (i = 0; i < PCOUNT_MAX; i++)
13299 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13300 pcounts.count[i]);
13301
13302 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13303 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13304 vty_out(vty,
13305 "Please report this bug, with the above command output\n");
13306 }
13307 }
13308
13309 return CMD_SUCCESS;
718e3744 13310}
13311
a636c635
DW
13312DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13313 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13314 "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 13315 SHOW_STR
13316 IP_STR
13317 BGP_STR
8386ac43 13318 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13319 BGP_AFI_HELP_STR
13320 BGP_SAFI_HELP_STR
0b16f239
DS
13321 "Detailed information on TCP and BGP neighbor connections\n"
13322 "Neighbor to display information about\n"
13323 "Neighbor to display information about\n"
91d37724 13324 "Neighbor on BGP configured interface\n"
a636c635 13325 "Display detailed prefix count information\n"
9973d184 13326 JSON_STR)
0b16f239 13327{
d62a17ae 13328 afi_t afi = AFI_IP6;
13329 safi_t safi = SAFI_UNICAST;
13330 struct peer *peer;
13331 int idx = 0;
13332 struct bgp *bgp = NULL;
9f049418
DS
13333 bool uj = use_json(argc, argv);
13334
13335 if (uj)
13336 argc--;
856ca177 13337
d62a17ae 13338 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13339 &bgp, uj);
d62a17ae 13340 if (!idx)
13341 return CMD_WARNING;
0b16f239 13342
d62a17ae 13343 argv_find(argv, argc, "neighbors", &idx);
13344 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13345 if (!peer)
13346 return CMD_WARNING;
bb46e94f 13347
29c8d9da 13348 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13349}
0b16f239 13350
d6902373
PG
13351#ifdef KEEP_OLD_VPN_COMMANDS
13352DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13353 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13354 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13355 SHOW_STR
13356 IP_STR
13357 BGP_STR
d6902373 13358 BGP_VPNVX_HELP_STR
91d37724 13359 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13360 "Detailed information on TCP and BGP neighbor connections\n"
13361 "Neighbor to display information about\n"
13362 "Neighbor to display information about\n"
91d37724 13363 "Neighbor on BGP configured interface\n"
a636c635 13364 "Display detailed prefix count information\n"
9973d184 13365 JSON_STR)
a636c635 13366{
d62a17ae 13367 int idx_peer = 6;
13368 struct peer *peer;
9f049418 13369 bool uj = use_json(argc, argv);
a636c635 13370
d62a17ae 13371 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13372 if (!peer)
13373 return CMD_WARNING;
13374
13375 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13376}
13377
d6902373
PG
13378DEFUN (show_ip_bgp_vpn_all_route_prefix,
13379 show_ip_bgp_vpn_all_route_prefix_cmd,
13380 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13381 SHOW_STR
13382 IP_STR
13383 BGP_STR
d6902373 13384 BGP_VPNVX_HELP_STR
91d37724
QY
13385 "Display information about all VPNv4 NLRIs\n"
13386 "Network in the BGP routing table to display\n"
3a2d747c 13387 "Network in the BGP routing table to display\n"
9973d184 13388 JSON_STR)
91d37724 13389{
d62a17ae 13390 int idx = 0;
13391 char *network = NULL;
13392 struct bgp *bgp = bgp_get_default();
13393 if (!bgp) {
13394 vty_out(vty, "Can't find default instance\n");
13395 return CMD_WARNING;
13396 }
87e34b58 13397
d62a17ae 13398 if (argv_find(argv, argc, "A.B.C.D", &idx))
13399 network = argv[idx]->arg;
13400 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13401 network = argv[idx]->arg;
13402 else {
13403 vty_out(vty, "Unable to figure out Network\n");
13404 return CMD_WARNING;
13405 }
87e34b58 13406
d62a17ae 13407 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13408 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13409 use_json(argc, argv));
91d37724 13410}
d6902373 13411#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13412
44c69747
LK
13413DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13414 show_bgp_l2vpn_evpn_route_prefix_cmd,
13415 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13416 SHOW_STR
4c63a661
PG
13417 BGP_STR
13418 L2VPN_HELP_STR
13419 EVPN_HELP_STR
44c69747
LK
13420 "Network in the BGP routing table to display\n"
13421 "Network in the BGP routing table to display\n"
4c63a661
PG
13422 "Network in the BGP routing table to display\n"
13423 "Network in the BGP routing table to display\n"
13424 JSON_STR)
13425{
d62a17ae 13426 int idx = 0;
13427 char *network = NULL;
44c69747 13428 int prefix_check = 0;
a636c635 13429
44c69747
LK
13430 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13431 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13432 network = argv[idx]->arg;
44c69747 13433 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13434 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13435 network = argv[idx]->arg;
44c69747
LK
13436 prefix_check = 1;
13437 } else {
d62a17ae 13438 vty_out(vty, "Unable to figure out Network\n");
13439 return CMD_WARNING;
13440 }
44c69747
LK
13441 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13442 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13443 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13444}
13445
2f9bc755
DS
13446static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13447 struct bgp_table *table, int *header1,
13448 int *header2, json_object *json,
13449 json_object *json_scode,
13450 json_object *json_ocode, bool wide)
13451{
13452 uint64_t version = table ? table->version : 0;
23d0a753 13453 char buf[BUFSIZ] = {0};
2f9bc755
DS
13454
13455 if (*header1) {
13456 if (json) {
13457 json_object_int_add(json, "bgpTableVersion", version);
13458 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13459 inet_ntop(AF_INET,
13460 &bgp->router_id, buf,
13461 sizeof(buf)));
2f9bc755
DS
13462 json_object_int_add(json, "defaultLocPrf",
13463 bgp->default_local_pref);
13464 json_object_int_add(json, "localAS", bgp->as);
13465 json_object_object_add(json, "bgpStatusCodes",
13466 json_scode);
13467 json_object_object_add(json, "bgpOriginCodes",
13468 json_ocode);
13469 } else {
13470 vty_out(vty,
23d0a753
DA
13471 "BGP table version is %" PRIu64
13472 ", local router ID is %pI4, vrf id ",
13473 version, &bgp->router_id);
2f9bc755
DS
13474 if (bgp->vrf_id == VRF_UNKNOWN)
13475 vty_out(vty, "%s", VRFID_NONE_STR);
13476 else
13477 vty_out(vty, "%u", bgp->vrf_id);
13478 vty_out(vty, "\n");
13479 vty_out(vty, "Default local pref %u, ",
13480 bgp->default_local_pref);
13481 vty_out(vty, "local AS %u\n", bgp->as);
13482 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13483 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13484 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13485 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13486 }
13487 *header1 = 0;
13488 }
13489 if (*header2) {
13490 if (!json)
13491 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13492 : BGP_SHOW_HEADER));
13493 *header2 = 0;
13494 }
13495}
13496
d9478df0
TA
13497static void
13498show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13499 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13500 const char *rmap_name, json_object *json, json_object *json_ar,
13501 json_object *json_scode, json_object *json_ocode,
96c81f66 13502 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13503 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13504{
d62a17ae 13505 struct bgp_adj_in *ain;
13506 struct bgp_adj_out *adj;
9bcb3eef 13507 struct bgp_dest *dest;
d62a17ae 13508 struct bgp *bgp;
d62a17ae 13509 struct attr attr;
13510 int ret;
13511 struct update_subgroup *subgrp;
d62a17ae 13512 struct peer_af *paf;
f99def61 13513 bool route_filtered;
96f3485c
MK
13514 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13515 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13516 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13517 || (safi == SAFI_EVPN))
13518 ? true
13519 : false;
a636c635 13520
d62a17ae 13521 bgp = peer->bgp;
a636c635 13522
d62a17ae 13523 if (!bgp) {
13524 if (use_json) {
13525 json_object_string_add(json, "alert", "no BGP");
13526 vty_out(vty, "%s\n", json_object_to_json_string(json));
13527 json_object_free(json);
13528 } else
13529 vty_out(vty, "%% No bgp\n");
13530 return;
13531 }
a636c635 13532
d62a17ae 13533 subgrp = peer_subgroup(peer, afi, safi);
13534
6392aaa6 13535 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13536 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13537 char buf[BUFSIZ] = {0};
13538
d62a17ae 13539 if (use_json) {
13540 json_object_int_add(json, "bgpTableVersion",
13541 table->version);
13542 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13543 inet_ntop(AF_INET,
13544 &bgp->router_id, buf,
13545 sizeof(buf)));
01eced22
AD
13546 json_object_int_add(json, "defaultLocPrf",
13547 bgp->default_local_pref);
13548 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13549 json_object_object_add(json, "bgpStatusCodes",
13550 json_scode);
13551 json_object_object_add(json, "bgpOriginCodes",
13552 json_ocode);
07d0c4ed
DA
13553 json_object_string_add(
13554 json, "bgpOriginatingDefaultNetwork",
13555 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13556 } else {
23d0a753
DA
13557 vty_out(vty,
13558 "BGP table version is %" PRIu64
13559 ", local router ID is %pI4, vrf id ",
13560 table->version, &bgp->router_id);
9df8b37c
PZ
13561 if (bgp->vrf_id == VRF_UNKNOWN)
13562 vty_out(vty, "%s", VRFID_NONE_STR);
13563 else
13564 vty_out(vty, "%u", bgp->vrf_id);
13565 vty_out(vty, "\n");
01eced22
AD
13566 vty_out(vty, "Default local pref %u, ",
13567 bgp->default_local_pref);
13568 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13569 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13570 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13571 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13572 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13573
07d0c4ed
DA
13574 vty_out(vty, "Originating default network %s\n\n",
13575 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13576 }
d9478df0 13577 *header1 = 0;
d62a17ae 13578 }
a636c635 13579
9bcb3eef 13580 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13581 if (type == bgp_show_adj_route_received
13582 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13583 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13584 if (ain->peer != peer)
ea47320b 13585 continue;
6392aaa6 13586
d9478df0
TA
13587 show_adj_route_header(vty, bgp, table, header1,
13588 header2, json, json_scode,
13589 json_ocode, wide);
13590
13591 if ((safi == SAFI_MPLS_VPN)
13592 || (safi == SAFI_ENCAP)
13593 || (safi == SAFI_EVPN)) {
13594 if (use_json)
13595 json_object_string_add(
13596 json_ar, "rd", rd_str);
13597 else if (show_rd && rd_str) {
13598 vty_out(vty,
13599 "Route Distinguisher: %s\n",
13600 rd_str);
13601 show_rd = false;
13602 }
13603 }
6392aaa6 13604
6f4f49b2 13605 attr = *ain->attr;
f99def61
AD
13606 route_filtered = false;
13607
13608 /* Filter prefix using distribute list,
13609 * filter list or prefix list
13610 */
b54892e0 13611 const struct prefix *rn_p =
9bcb3eef 13612 bgp_dest_get_prefix(dest);
b54892e0
DS
13613 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13614 safi))
13615 == FILTER_DENY)
f99def61
AD
13616 route_filtered = true;
13617
13618 /* Filter prefix using route-map */
b54892e0
DS
13619 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13620 safi, rmap_name, NULL,
13621 0, NULL);
6392aaa6 13622
13c8e163
AD
13623 if (type == bgp_show_adj_route_filtered &&
13624 !route_filtered && ret != RMAP_DENY) {
b755861b 13625 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13626 continue;
d62a17ae 13627 }
6392aaa6 13628
d9478df0
TA
13629 if (type == bgp_show_adj_route_received
13630 && (route_filtered || ret == RMAP_DENY))
13631 (*filtered_count)++;
6392aaa6 13632
7d3cae70 13633 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13634 use_json, json_ar, wide);
b755861b 13635 bgp_attr_undup(&attr, ain->attr);
d9478df0 13636 (*output_count)++;
d62a17ae 13637 }
6392aaa6 13638 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13639 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13640 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13641 if (paf->peer != peer || !adj->attr)
924c3f6a 13642 continue;
d62a17ae 13643
d9478df0
TA
13644 show_adj_route_header(vty, bgp, table,
13645 header1, header2,
13646 json, json_scode,
13647 json_ocode, wide);
d62a17ae 13648
b54892e0 13649 const struct prefix *rn_p =
9bcb3eef 13650 bgp_dest_get_prefix(dest);
b54892e0 13651
6f4f49b2 13652 attr = *adj->attr;
b755861b 13653 ret = bgp_output_modifier(
b54892e0 13654 peer, rn_p, &attr, afi, safi,
b755861b 13655 rmap_name);
f46d8e1e 13656
b755861b 13657 if (ret != RMAP_DENY) {
d9478df0
TA
13658 if ((safi == SAFI_MPLS_VPN)
13659 || (safi == SAFI_ENCAP)
13660 || (safi == SAFI_EVPN)) {
13661 if (use_json)
13662 json_object_string_add(
13663 json_ar,
13664 "rd",
13665 rd_str);
13666 else if (show_rd
13667 && rd_str) {
13668 vty_out(vty,
13669 "Route Distinguisher: %s\n",
13670 rd_str);
13671 show_rd = false;
13672 }
13673 }
b54892e0 13674 route_vty_out_tmp(
7d3cae70
DA
13675 vty, dest, rn_p, &attr,
13676 safi, use_json, json_ar,
ae248832 13677 wide);
d9478df0 13678 (*output_count)++;
b755861b 13679 } else {
d9478df0 13680 (*filtered_count)++;
a2addae8 13681 }
b755861b
PM
13682
13683 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13684 }
f20ce998
DS
13685 } else if (type == bgp_show_adj_route_bestpath) {
13686 struct bgp_path_info *pi;
13687
d9478df0
TA
13688 show_adj_route_header(vty, bgp, table, header1, header2,
13689 json, json_scode, json_ocode,
13690 wide);
f20ce998
DS
13691
13692 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13693 pi = pi->next) {
13694 if (pi->peer != peer)
13695 continue;
13696
13697 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13698 continue;
13699
7d3cae70 13700 route_vty_out_tmp(vty, dest,
f20ce998
DS
13701 bgp_dest_get_prefix(dest),
13702 pi->attr, safi, use_json,
13703 json_ar, wide);
d9478df0 13704 (*output_count)++;
f20ce998 13705 }
d62a17ae 13706 }
13707 }
a636c635 13708}
2a71e9ce 13709
d62a17ae 13710static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13711 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13712 const char *rmap_name, uint16_t show_flags)
0b16f239 13713{
d9478df0
TA
13714 struct bgp *bgp;
13715 struct bgp_table *table;
d62a17ae 13716 json_object *json = NULL;
d9478df0
TA
13717 json_object *json_scode = NULL;
13718 json_object *json_ocode = NULL;
13719 json_object *json_ar = NULL;
96f3485c 13720 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13721
d9478df0
TA
13722 /* Init BGP headers here so they're only displayed once
13723 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13724 */
13725 int header1 = 1;
13726 int header2 = 1;
13727
13728 /*
13729 * Initialize variables for each RD
13730 * All prefixes under an RD is aggregated within "json_routes"
13731 */
13732 char rd_str[BUFSIZ] = {0};
13733 json_object *json_routes = NULL;
13734
13735
13736 /* For 2-tier tables, prefix counts need to be
13737 * maintained across multiple runs of show_adj_route()
13738 */
13739 unsigned long output_count_per_rd;
13740 unsigned long filtered_count_per_rd;
13741 unsigned long output_count = 0;
13742 unsigned long filtered_count = 0;
13743
13744 if (use_json) {
d62a17ae 13745 json = json_object_new_object();
d9478df0
TA
13746 json_ar = json_object_new_object();
13747 json_scode = json_object_new_object();
13748 json_ocode = json_object_new_object();
13749
13750 json_object_string_add(json_scode, "suppressed", "s");
13751 json_object_string_add(json_scode, "damped", "d");
13752 json_object_string_add(json_scode, "history", "h");
13753 json_object_string_add(json_scode, "valid", "*");
13754 json_object_string_add(json_scode, "best", ">");
13755 json_object_string_add(json_scode, "multipath", "=");
13756 json_object_string_add(json_scode, "internal", "i");
13757 json_object_string_add(json_scode, "ribFailure", "r");
13758 json_object_string_add(json_scode, "stale", "S");
13759 json_object_string_add(json_scode, "removed", "R");
13760
13761 json_object_string_add(json_ocode, "igp", "i");
13762 json_object_string_add(json_ocode, "egp", "e");
13763 json_object_string_add(json_ocode, "incomplete", "?");
13764 }
0b16f239 13765
d62a17ae 13766 if (!peer || !peer->afc[afi][safi]) {
13767 if (use_json) {
13768 json_object_string_add(
13769 json, "warning",
13770 "No such neighbor or address family");
13771 vty_out(vty, "%s\n", json_object_to_json_string(json));
13772 json_object_free(json);
13773 } else
13774 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13775
d62a17ae 13776 return CMD_WARNING;
13777 }
13778
6392aaa6
PM
13779 if ((type == bgp_show_adj_route_received
13780 || type == bgp_show_adj_route_filtered)
d62a17ae 13781 && !CHECK_FLAG(peer->af_flags[afi][safi],
13782 PEER_FLAG_SOFT_RECONFIG)) {
13783 if (use_json) {
13784 json_object_string_add(
13785 json, "warning",
13786 "Inbound soft reconfiguration not enabled");
13787 vty_out(vty, "%s\n", json_object_to_json_string(json));
13788 json_object_free(json);
13789 } else
13790 vty_out(vty,
13791 "%% Inbound soft reconfiguration not enabled\n");
13792
13793 return CMD_WARNING;
13794 }
0b16f239 13795
d9478df0
TA
13796 bgp = peer->bgp;
13797
13798 /* labeled-unicast routes live in the unicast table */
13799 if (safi == SAFI_LABELED_UNICAST)
13800 table = bgp->rib[afi][SAFI_UNICAST];
13801 else
13802 table = bgp->rib[afi][safi];
13803
13804 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13805 || (safi == SAFI_EVPN)) {
13806
13807 struct bgp_dest *dest;
13808
13809 for (dest = bgp_table_top(table); dest;
13810 dest = bgp_route_next(dest)) {
13811 table = bgp_dest_get_bgp_table_info(dest);
13812 if (!table)
13813 continue;
13814
13815 output_count_per_rd = 0;
13816 filtered_count_per_rd = 0;
13817
13818 if (use_json)
13819 json_routes = json_object_new_object();
13820
13821 const struct prefix_rd *prd;
13822 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13823 dest);
13824
13825 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13826
13827 show_adj_route(vty, peer, table, afi, safi, type,
13828 rmap_name, json, json_routes, json_scode,
13829 json_ocode, show_flags, &header1,
13830 &header2, rd_str, &output_count_per_rd,
13831 &filtered_count_per_rd);
13832
13833 /* Don't include an empty RD in the output! */
13834 if (json_routes && (output_count_per_rd > 0))
13835 json_object_object_add(json_ar, rd_str,
13836 json_routes);
13837
13838 output_count += output_count_per_rd;
13839 filtered_count += filtered_count_per_rd;
13840 }
13841 } else
13842 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13843 json, json_ar, json_scode, json_ocode,
13844 show_flags, &header1, &header2, rd_str,
13845 &output_count, &filtered_count);
13846
13847 if (use_json) {
13848 json_object_object_add(json, "advertisedRoutes", json_ar);
13849 json_object_int_add(json, "totalPrefixCounter", output_count);
13850 json_object_int_add(json, "filteredPrefixCounter",
13851 filtered_count);
13852
13853 vty_out(vty, "%s\n",
13854 json_object_to_json_string_ext(
13855 json, JSON_C_TO_STRING_PRETTY));
13856
13857 if (!output_count && !filtered_count) {
13858 json_object_free(json_scode);
13859 json_object_free(json_ocode);
13860 }
13861
13862 if (json)
13863 json_object_free(json);
13864
13865 } else if (output_count > 0) {
13866 if (filtered_count > 0)
13867 vty_out(vty,
13868 "\nTotal number of prefixes %ld (%ld filtered)\n",
13869 output_count, filtered_count);
13870 else
13871 vty_out(vty, "\nTotal number of prefixes %ld\n",
13872 output_count);
13873 }
0b16f239 13874
d62a17ae 13875 return CMD_SUCCESS;
a636c635 13876}
50ef26d4 13877
f20ce998
DS
13878DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13879 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13880 "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]",
13881 SHOW_STR
13882 IP_STR
13883 BGP_STR
13884 BGP_INSTANCE_HELP_STR
13885 BGP_AFI_HELP_STR
13886 BGP_SAFI_WITH_LABEL_HELP_STR
13887 "Detailed information on TCP and BGP neighbor connections\n"
13888 "Neighbor to display information about\n"
13889 "Neighbor to display information about\n"
13890 "Neighbor on BGP configured interface\n"
13891 "Display the routes selected by best path\n"
13892 JSON_STR
13893 "Increase table width for longer prefixes\n")
13894{
13895 afi_t afi = AFI_IP6;
13896 safi_t safi = SAFI_UNICAST;
13897 char *rmap_name = NULL;
13898 char *peerstr = NULL;
13899 struct bgp *bgp = NULL;
13900 struct peer *peer;
13901 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13902 int idx = 0;
96c81f66 13903 uint16_t show_flags = 0;
96f3485c
MK
13904
13905 if (uj)
13906 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13907
13908 if (wide)
13909 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13910
13911 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13912 &bgp, uj);
13913
13914 if (!idx)
13915 return CMD_WARNING;
13916
13917 argv_find(argv, argc, "neighbors", &idx);
13918 peerstr = argv[++idx]->arg;
13919
13920 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13921 if (!peer)
13922 return CMD_WARNING;
13923
96f3485c
MK
13924 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13925 show_flags);
f20ce998
DS
13926}
13927
ae248832 13928DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13929 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13930 "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 13931 SHOW_STR
13932 IP_STR
13933 BGP_STR
a636c635 13934 BGP_INSTANCE_HELP_STR
7395a2c9 13935 BGP_AFI_HELP_STR
4dd6177e 13936 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13937 "Display the entries for all address families\n"
718e3744 13938 "Detailed information on TCP and BGP neighbor connections\n"
13939 "Neighbor to display information about\n"
13940 "Neighbor to display information about\n"
91d37724 13941 "Neighbor on BGP configured interface\n"
a636c635 13942 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13943 "Display the received routes from neighbor\n"
13944 "Display the filtered routes received from neighbor\n"
a636c635
DW
13945 "Route-map to modify the attributes\n"
13946 "Name of the route map\n"
ae248832
MK
13947 JSON_STR
13948 "Increase table width for longer prefixes\n")
718e3744 13949{
d62a17ae 13950 afi_t afi = AFI_IP6;
13951 safi_t safi = SAFI_UNICAST;
13952 char *rmap_name = NULL;
13953 char *peerstr = NULL;
d62a17ae 13954 struct bgp *bgp = NULL;
13955 struct peer *peer;
6392aaa6 13956 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13957 int idx = 0;
96f3485c 13958 bool first = true;
96c81f66 13959 uint16_t show_flags = 0;
6392aaa6 13960
96f3485c 13961 if (uj) {
d62a17ae 13962 argc--;
96f3485c
MK
13963 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13964 }
13965
13966 if (all) {
13967 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13968 if (argv_find(argv, argc, "ipv4", &idx))
13969 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13970
13971 if (argv_find(argv, argc, "ipv6", &idx))
13972 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13973 }
13974
13975 if (wide)
13976 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13977
9f049418
DS
13978 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13979 &bgp, uj);
13980 if (!idx)
13981 return CMD_WARNING;
13982
d62a17ae 13983 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13984 argv_find(argv, argc, "neighbors", &idx);
13985 peerstr = argv[++idx]->arg;
8c3deaae 13986
d62a17ae 13987 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13988 if (!peer)
13989 return CMD_WARNING;
856ca177 13990
d62a17ae 13991 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13992 type = bgp_show_adj_route_advertised;
13993 else if (argv_find(argv, argc, "received-routes", &idx))
13994 type = bgp_show_adj_route_received;
13995 else if (argv_find(argv, argc, "filtered-routes", &idx))
13996 type = bgp_show_adj_route_filtered;
13997
d62a17ae 13998 if (argv_find(argv, argc, "route-map", &idx))
13999 rmap_name = argv[++idx]->arg;
95cbbd2a 14000
96f3485c
MK
14001 if (!all)
14002 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14003 show_flags);
14004 if (uj)
14005 vty_out(vty, "{\n");
14006
14007 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14008 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14009 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14010 : AFI_IP6;
14011 FOREACH_SAFI (safi) {
96f3485c
MK
14012 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14013 continue;
14014
14015 if (uj) {
14016 if (first)
14017 first = false;
14018 else
14019 vty_out(vty, ",\n");
14020 vty_out(vty, "\"%s\":",
14021 get_afi_safi_str(afi, safi, true));
14022 } else
14023 vty_out(vty, "\nFor address family: %s\n",
14024 get_afi_safi_str(afi, safi, false));
14025
14026 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14027 show_flags);
14028 }
14029 } else {
14030 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
14031 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14032 continue;
14033
14034 if (uj) {
14035 if (first)
14036 first = false;
14037 else
14038 vty_out(vty, ",\n");
14039 vty_out(vty, "\"%s\":",
14040 get_afi_safi_str(afi, safi, true));
14041 } else
14042 vty_out(vty, "\nFor address family: %s\n",
14043 get_afi_safi_str(afi, safi, false));
14044
14045 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14046 show_flags);
14047 }
14048 }
14049 if (uj)
14050 vty_out(vty, "}\n");
14051
14052 return CMD_SUCCESS;
95cbbd2a
ML
14053}
14054
718e3744 14055DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14056 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 14057 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14058 SHOW_STR
14059 IP_STR
14060 BGP_STR
8c3deaae
QY
14061 "Address Family\n"
14062 "Address Family\n"
718e3744 14063 "Address Family modifier\n"
14064 "Detailed information on TCP and BGP neighbor connections\n"
14065 "Neighbor to display information about\n"
14066 "Neighbor to display information about\n"
91d37724 14067 "Neighbor on BGP configured interface\n"
718e3744 14068 "Display information received from a BGP neighbor\n"
856ca177 14069 "Display the prefixlist filter\n"
9973d184 14070 JSON_STR)
718e3744 14071{
d62a17ae 14072 afi_t afi = AFI_IP6;
14073 safi_t safi = SAFI_UNICAST;
14074 char *peerstr = NULL;
14075
14076 char name[BUFSIZ];
14077 union sockunion su;
14078 struct peer *peer;
14079 int count, ret;
14080
14081 int idx = 0;
14082
14083 /* show [ip] bgp */
14084 if (argv_find(argv, argc, "ip", &idx))
14085 afi = AFI_IP;
14086 /* [<ipv4|ipv6> [unicast]] */
14087 if (argv_find(argv, argc, "ipv4", &idx))
14088 afi = AFI_IP;
14089 if (argv_find(argv, argc, "ipv6", &idx))
14090 afi = AFI_IP6;
14091 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14092 argv_find(argv, argc, "neighbors", &idx);
14093 peerstr = argv[++idx]->arg;
14094
9f049418 14095 bool uj = use_json(argc, argv);
d62a17ae 14096
14097 ret = str2sockunion(peerstr, &su);
14098 if (ret < 0) {
14099 peer = peer_lookup_by_conf_if(NULL, peerstr);
14100 if (!peer) {
14101 if (uj)
14102 vty_out(vty, "{}\n");
14103 else
14104 vty_out(vty,
14105 "%% Malformed address or name: %s\n",
14106 peerstr);
14107 return CMD_WARNING;
14108 }
14109 } else {
14110 peer = peer_lookup(NULL, &su);
14111 if (!peer) {
14112 if (uj)
14113 vty_out(vty, "{}\n");
14114 else
14115 vty_out(vty, "No peer\n");
14116 return CMD_WARNING;
14117 }
14118 }
718e3744 14119
4ced1a2c 14120 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14121 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14122 if (count) {
14123 if (!uj)
14124 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14125 get_afi_safi_str(afi, safi, false));
d62a17ae 14126 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14127 } else {
14128 if (uj)
14129 vty_out(vty, "{}\n");
14130 else
14131 vty_out(vty, "No functional output\n");
14132 }
718e3744 14133
d62a17ae 14134 return CMD_SUCCESS;
14135}
14136
14137static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14138 afi_t afi, safi_t safi,
9f049418 14139 enum bgp_show_type type, bool use_json)
d62a17ae 14140{
96c81f66 14141 uint16_t show_flags = 0;
96f3485c
MK
14142
14143 if (use_json)
14144 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14145
d62a17ae 14146 if (!peer || !peer->afc[afi][safi]) {
14147 if (use_json) {
14148 json_object *json_no = NULL;
14149 json_no = json_object_new_object();
14150 json_object_string_add(
14151 json_no, "warning",
14152 "No such neighbor or address family");
14153 vty_out(vty, "%s\n",
14154 json_object_to_json_string(json_no));
14155 json_object_free(json_no);
14156 } else
14157 vty_out(vty, "%% No such neighbor or address family\n");
14158 return CMD_WARNING;
14159 }
47fc97cc 14160
7daf25a3
TA
14161 /* labeled-unicast routes live in the unicast table */
14162 if (safi == SAFI_LABELED_UNICAST)
14163 safi = SAFI_UNICAST;
14164
1e2ce4f1
DS
14165 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14166 RPKI_NOT_BEING_USED);
718e3744 14167}
14168
dba3c1d3
PG
14169DEFUN (show_ip_bgp_flowspec_routes_detailed,
14170 show_ip_bgp_flowspec_routes_detailed_cmd,
14171 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14172 SHOW_STR
14173 IP_STR
14174 BGP_STR
14175 BGP_INSTANCE_HELP_STR
14176 BGP_AFI_HELP_STR
14177 "SAFI Flowspec\n"
14178 "Detailed information on flowspec entries\n"
14179 JSON_STR)
14180{
14181 afi_t afi = AFI_IP;
14182 safi_t safi = SAFI_UNICAST;
14183 struct bgp *bgp = NULL;
14184 int idx = 0;
9f049418 14185 bool uj = use_json(argc, argv);
96c81f66 14186 uint16_t show_flags = 0;
9f049418 14187
96f3485c 14188 if (uj) {
9f049418 14189 argc--;
96f3485c
MK
14190 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14191 }
dba3c1d3
PG
14192
14193 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14194 &bgp, uj);
dba3c1d3
PG
14195 if (!idx)
14196 return CMD_WARNING;
14197
96f3485c 14198 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14199 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14200}
14201
718e3744 14202DEFUN (show_ip_bgp_neighbor_routes,
14203 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14204 "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 14205 SHOW_STR
14206 IP_STR
14207 BGP_STR
8386ac43 14208 BGP_INSTANCE_HELP_STR
4f280b15 14209 BGP_AFI_HELP_STR
4dd6177e 14210 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14211 "Detailed information on TCP and BGP neighbor connections\n"
14212 "Neighbor to display information about\n"
14213 "Neighbor to display information about\n"
91d37724 14214 "Neighbor on BGP configured interface\n"
2525cf39 14215 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14216 "Display the dampened routes received from neighbor\n"
14217 "Display routes learned from neighbor\n"
9973d184 14218 JSON_STR)
718e3744 14219{
d62a17ae 14220 char *peerstr = NULL;
14221 struct bgp *bgp = NULL;
14222 afi_t afi = AFI_IP6;
14223 safi_t safi = SAFI_UNICAST;
14224 struct peer *peer;
14225 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14226 int idx = 0;
9f049418
DS
14227 bool uj = use_json(argc, argv);
14228
14229 if (uj)
14230 argc--;
bb46e94f 14231
d62a17ae 14232 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14233 &bgp, uj);
d62a17ae 14234 if (!idx)
14235 return CMD_WARNING;
c493f2d8 14236
d62a17ae 14237 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14238 argv_find(argv, argc, "neighbors", &idx);
14239 peerstr = argv[++idx]->arg;
8c3deaae 14240
d62a17ae 14241 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14242 if (!peer)
d62a17ae 14243 return CMD_WARNING;
bb46e94f 14244
d62a17ae 14245 if (argv_find(argv, argc, "flap-statistics", &idx))
14246 sh_type = bgp_show_type_flap_neighbor;
14247 else if (argv_find(argv, argc, "dampened-routes", &idx))
14248 sh_type = bgp_show_type_damp_neighbor;
14249 else if (argv_find(argv, argc, "routes", &idx))
14250 sh_type = bgp_show_type_neighbor;
2525cf39 14251
d62a17ae 14252 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14253}
6b0655a2 14254
734b349e 14255struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14256
d62a17ae 14257struct bgp_distance {
14258 /* Distance value for the IP source prefix. */
d7c0a89a 14259 uint8_t distance;
718e3744 14260
d62a17ae 14261 /* Name of the access-list to be matched. */
14262 char *access_list;
718e3744 14263};
14264
4f280b15
LB
14265DEFUN (show_bgp_afi_vpn_rd_route,
14266 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14267 "show bgp "BGP_AFI_CMD_STR" vpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> <A.B.C.D/M|X:X::X:X/M> [json]",
4f280b15
LB
14268 SHOW_STR
14269 BGP_STR
14270 BGP_AFI_HELP_STR
14271 "Address Family modifier\n"
14272 "Display information for a route distinguisher\n"
14273 "Route Distinguisher\n"
a111dd97 14274 "All Route Distinguishers\n"
7395a2c9
DS
14275 "Network in the BGP routing table to display\n"
14276 "Network in the BGP routing table to display\n"
14277 JSON_STR)
4f280b15 14278{
d62a17ae 14279 int ret;
14280 struct prefix_rd prd;
14281 afi_t afi = AFI_MAX;
14282 int idx = 0;
4f280b15 14283
ff6566f3
DS
14284 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14285 vty_out(vty, "%% Malformed Address Family\n");
14286 return CMD_WARNING;
14287 }
14288
a111dd97
TA
14289 if (!strcmp(argv[5]->arg, "all"))
14290 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14291 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14292 RPKI_NOT_BEING_USED,
14293 use_json(argc, argv));
14294
d62a17ae 14295 ret = str2prefix_rd(argv[5]->arg, &prd);
14296 if (!ret) {
14297 vty_out(vty, "%% Malformed Route Distinguisher\n");
14298 return CMD_WARNING;
14299 }
ff6566f3 14300
d62a17ae 14301 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14302 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14303 use_json(argc, argv));
4f280b15
LB
14304}
14305
d62a17ae 14306static struct bgp_distance *bgp_distance_new(void)
718e3744 14307{
d62a17ae 14308 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14309}
14310
d62a17ae 14311static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14312{
d62a17ae 14313 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14314}
14315
37a87b8f
CS
14316int bgp_distance_set(uint8_t distance, const char *ip_str,
14317 const char *access_list_str, afi_t afi, safi_t safi,
14318 char *errmsg, size_t errmsg_len)
718e3744 14319{
d62a17ae 14320 int ret;
d62a17ae 14321 struct prefix p;
9bcb3eef 14322 struct bgp_dest *dest;
d62a17ae 14323 struct bgp_distance *bdistance;
718e3744 14324
d62a17ae 14325 ret = str2prefix(ip_str, &p);
14326 if (ret == 0) {
37a87b8f 14327 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14328 return CMD_WARNING_CONFIG_FAILED;
14329 }
718e3744 14330
d62a17ae 14331 /* Get BGP distance node. */
9bcb3eef
DS
14332 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14333 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14334 if (bdistance)
9bcb3eef 14335 bgp_dest_unlock_node(dest);
ca2e160d 14336 else {
d62a17ae 14337 bdistance = bgp_distance_new();
9bcb3eef 14338 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14339 }
718e3744 14340
d62a17ae 14341 /* Set distance value. */
14342 bdistance->distance = distance;
718e3744 14343
d62a17ae 14344 /* Reset access-list configuration. */
e1b36e13 14345 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14346 if (access_list_str)
14347 bdistance->access_list =
14348 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14349
d62a17ae 14350 return CMD_SUCCESS;
718e3744 14351}
14352
37a87b8f
CS
14353int bgp_distance_unset(uint8_t distance, const char *ip_str,
14354 const char *access_list_str, afi_t afi, safi_t safi,
14355 char *errmsg, size_t errmsg_len)
718e3744 14356{
d62a17ae 14357 int ret;
d62a17ae 14358 struct prefix p;
9bcb3eef 14359 struct bgp_dest *dest;
d62a17ae 14360 struct bgp_distance *bdistance;
718e3744 14361
d62a17ae 14362 ret = str2prefix(ip_str, &p);
14363 if (ret == 0) {
37a87b8f 14364 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14365 return CMD_WARNING_CONFIG_FAILED;
14366 }
718e3744 14367
9bcb3eef
DS
14368 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14369 if (!dest) {
37a87b8f 14370 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 14371 return CMD_WARNING_CONFIG_FAILED;
14372 }
718e3744 14373
9bcb3eef 14374 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 14375
d62a17ae 14376 if (bdistance->distance != distance) {
37a87b8f
CS
14377 snprintf(errmsg, errmsg_len,
14378 "Distance does not match configured\n");
89f4bd87 14379 bgp_dest_unlock_node(dest);
d62a17ae 14380 return CMD_WARNING_CONFIG_FAILED;
14381 }
718e3744 14382
0a22ddfb 14383 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14384 bgp_distance_free(bdistance);
718e3744 14385
9bcb3eef
DS
14386 bgp_dest_set_bgp_path_info(dest, NULL);
14387 bgp_dest_unlock_node(dest);
14388 bgp_dest_unlock_node(dest);
718e3744 14389
d62a17ae 14390 return CMD_SUCCESS;
718e3744 14391}
14392
718e3744 14393/* Apply BGP information to distance method. */
b8685f9b 14394uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14395 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14396{
9bcb3eef 14397 struct bgp_dest *dest;
801bb996 14398 struct prefix q = {0};
d62a17ae 14399 struct peer *peer;
14400 struct bgp_distance *bdistance;
14401 struct access_list *alist;
14402 struct bgp_static *bgp_static;
14403
14404 if (!bgp)
14405 return 0;
14406
40381db7 14407 peer = pinfo->peer;
d62a17ae 14408
7b7d48e5
DS
14409 if (pinfo->attr->distance)
14410 return pinfo->attr->distance;
14411
801bb996
CS
14412 /* Check source address.
14413 * Note: for aggregate route, peer can have unspec af type.
14414 */
14415 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14416 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14417 return 0;
14418
9bcb3eef
DS
14419 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14420 if (dest) {
14421 bdistance = bgp_dest_get_bgp_distance_info(dest);
14422 bgp_dest_unlock_node(dest);
d62a17ae 14423
14424 if (bdistance->access_list) {
14425 alist = access_list_lookup(afi, bdistance->access_list);
14426 if (alist
14427 && access_list_apply(alist, p) == FILTER_PERMIT)
14428 return bdistance->distance;
14429 } else
14430 return bdistance->distance;
718e3744 14431 }
718e3744 14432
d62a17ae 14433 /* Backdoor check. */
9bcb3eef
DS
14434 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14435 if (dest) {
14436 bgp_static = bgp_dest_get_bgp_static_info(dest);
14437 bgp_dest_unlock_node(dest);
718e3744 14438
d62a17ae 14439 if (bgp_static->backdoor) {
14440 if (bgp->distance_local[afi][safi])
14441 return bgp->distance_local[afi][safi];
14442 else
14443 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14444 }
718e3744 14445 }
718e3744 14446
d62a17ae 14447 if (peer->sort == BGP_PEER_EBGP) {
14448 if (bgp->distance_ebgp[afi][safi])
14449 return bgp->distance_ebgp[afi][safi];
14450 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14451 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14452 if (bgp->distance_ibgp[afi][safi])
14453 return bgp->distance_ibgp[afi][safi];
14454 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14455 } else {
14456 if (bgp->distance_local[afi][safi])
14457 return bgp->distance_local[afi][safi];
14458 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14459 }
718e3744 14460}
14461
a612fb77
DA
14462/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14463 * we should tell ZEBRA update the routes for a specific
14464 * AFI/SAFI to reflect changes in RIB.
14465 */
37a87b8f
CS
14466void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14467 safi_t update_safi)
a612fb77
DA
14468{
14469 afi_t afi;
14470 safi_t safi;
14471
14472 FOREACH_AFI_SAFI (afi, safi) {
14473 if (!bgp_fibupd_safi(safi))
14474 continue;
14475
8b54bc30
DA
14476 if (afi != update_afi && safi != update_safi)
14477 continue;
14478
14479 if (BGP_DEBUG(zebra, ZEBRA))
14480 zlog_debug(
14481 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14482 __func__, afi, safi);
14483 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14484 }
14485}
14486
37a87b8f
CS
14487DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14488 "distance bgp (1-255) (1-255) (1-255)",
14489 "Define an administrative distance\n"
14490 "BGP distance\n"
14491 "Distance for routes external to the AS\n"
14492 "Distance for routes internal to the AS\n"
14493 "Distance for local routes\n")
718e3744 14494{
d62a17ae 14495 int idx_number = 2;
14496 int idx_number_2 = 3;
14497 int idx_number_3 = 4;
14498 afi_t afi;
14499 safi_t safi;
37a87b8f 14500 char xpath[XPATH_MAXLEN];
718e3744 14501
d62a17ae 14502 afi = bgp_node_afi(vty);
14503 safi = bgp_node_safi(vty);
718e3744 14504
37a87b8f
CS
14505 snprintf(
14506 xpath, sizeof(xpath),
14507 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14508 yang_afi_safi_value2identity(afi, safi),
14509 bgp_afi_safi_get_container_str(afi, safi));
14510 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14511 snprintf(
14512 xpath, sizeof(xpath),
14513 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14514 yang_afi_safi_value2identity(afi, safi),
14515 bgp_afi_safi_get_container_str(afi, safi));
14516 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14517 argv[idx_number_2]->arg);
14518 snprintf(
14519 xpath, sizeof(xpath),
14520 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14521 yang_afi_safi_value2identity(afi, safi),
14522 bgp_afi_safi_get_container_str(afi, safi));
14523
14524 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14525 argv[idx_number_3]->arg);
14526
14527 return nb_cli_apply_changes(vty, NULL);
14528}
14529
14530DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14531 "no distance bgp [(1-255) (1-255) (1-255)]",
14532 NO_STR
14533 "Define an administrative distance\n"
14534 "BGP distance\n"
14535 "Distance for routes external to the AS\n"
14536 "Distance for routes internal to the AS\n"
14537 "Distance for local routes\n")
14538{
14539 afi_t afi;
14540 safi_t safi;
14541 char xpath[XPATH_MAXLEN];
14542
14543 afi = bgp_node_afi(vty);
14544 safi = bgp_node_safi(vty);
14545
14546 snprintf(
14547 xpath, sizeof(xpath),
14548 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14549 yang_afi_safi_value2identity(afi, safi),
14550 bgp_afi_safi_get_container_str(afi, safi));
14551 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14552 snprintf(
14553 xpath, sizeof(xpath),
14554 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14555 yang_afi_safi_value2identity(afi, safi),
14556 bgp_afi_safi_get_container_str(afi, safi));
14557 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14558 snprintf(
14559 xpath, sizeof(xpath),
14560 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14561 yang_afi_safi_value2identity(afi, safi),
14562 bgp_afi_safi_get_container_str(afi, safi));
14563
14564 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14565
14566 return nb_cli_apply_changes(vty, NULL);
718e3744 14567}
14568
37a87b8f
CS
14569void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14570 struct lyd_node *dnode,
14571 bool show_defaults)
718e3744 14572{
37a87b8f
CS
14573 uint8_t distance_ebgp, distance_ibgp, distance_local;
14574
14575 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14576 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14577 distance_local = yang_dnode_get_uint8(dnode, "./local");
14578
14579 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14580 distance_local);
14581}
14582
8cc7152a
CS
14583DEFPY_YANG(bgp_distance_source,
14584 bgp_distance_source_cmd,
14585 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14586 NO_STR
14587 "Define an administrative distance\n"
8cc7152a 14588 "Distance value\n"
e12affc1
SW
14589 "IPv4 source prefix\n"
14590 "IPv6 source prefix\n"
37a87b8f 14591 "Access list name\n")
718e3744 14592{
37a87b8f
CS
14593 afi_t afi;
14594 safi_t safi;
14595 char xpath[XPATH_MAXLEN];
14596
14597 afi = bgp_node_afi(vty);
14598 safi = bgp_node_safi(vty);
14599
8cc7152a
CS
14600 if (!no) {
14601 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14602 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14603 distance_str);
14604 if (acl)
14605 nb_cli_enqueue_change(vty,
14606 "./access-list-policy-export",
14607 NB_OP_CREATE, acl);
14608 else
14609 nb_cli_enqueue_change(vty,
14610 "./access-list-policy-export",
14611 NB_OP_DESTROY, NULL);
14612 } else {
14613 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14614 }
37a87b8f
CS
14615
14616 snprintf(
14617 xpath, sizeof(xpath),
14618 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14619 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14620 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14621
14622 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14623}
14624
37a87b8f
CS
14625void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14626 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14627{
14628 vty_out(vty, " distance %d %s %s\n",
14629 yang_dnode_get_uint8(dnode, "./distance"),
14630 yang_dnode_get_string(dnode, "./prefix"),
14631 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14632 ? yang_dnode_get_string(dnode,
14633 "./access-list-policy-export")
14634 : "");
14635}
14636
7c98d487
DA
14637DEFPY_YANG(
14638 bgp_dampening, bgp_dampening_cmd,
14639 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14640 NO_STR
14641 "BGP Specific commands\n"
14642 "Enable route-flap dampening\n"
14643 "Half-life time for the penalty\n"
14644 "Value to start reusing a route\n"
14645 "Value to start suppressing a route\n"
14646 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14647{
14648 afi_t afi;
14649 safi_t safi;
14650 char xpath[XPATH_MAXLEN];
718e3744 14651
37a87b8f
CS
14652 afi = bgp_node_afi(vty);
14653 safi = bgp_node_safi(vty);
14654
d9ce5113
CS
14655 if (!no) {
14656 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14657 if (argc == 6) {
14658 nb_cli_enqueue_change(vty, "./reach-decay",
14659 NB_OP_MODIFY, halflife_str);
14660 nb_cli_enqueue_change(vty, "./reuse-above",
14661 NB_OP_MODIFY, reuse_str);
14662 nb_cli_enqueue_change(vty, "./suppress-above",
14663 NB_OP_MODIFY, suppress_str);
14664 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14665 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14666 } if (argc == 3) {
14667 nb_cli_enqueue_change(vty, "./reach-decay",
14668 NB_OP_MODIFY, halflife_str);
14669 }
14670 } else {
14671 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14672 }
7ebe9748 14673
37a87b8f
CS
14674 snprintf(
14675 xpath, sizeof(xpath),
14676 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14677 yang_afi_safi_value2identity(afi, safi),
14678 bgp_afi_safi_get_container_str(afi, safi));
14679
14680 return nb_cli_apply_changes(vty, xpath);
718e3744 14681}
14682
37a87b8f
CS
14683void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14684 struct lyd_node *dnode,
14685 bool show_defaults)
718e3744 14686{
37a87b8f
CS
14687 if (!yang_dnode_get_bool(dnode, "./enable"))
14688 return;
14689
14690 int half = DEFAULT_HALF_LIFE * 60;
14691 int reuse = DEFAULT_REUSE;
14692 int suppress = DEFAULT_SUPPRESS;
14693 int max;
14694
14695 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14696 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14697 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14698 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14699
14700 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14701 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14702 vty_out(vty, " bgp dampening\n");
14703 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14704 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14705 vty_out(vty, " bgp dampening %u\n", half);
14706 else
14707 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14708 suppress, max);
718e3744 14709}
14710
718e3744 14711/* Display specified route of BGP table. */
d62a17ae 14712static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14713 const char *ip_str, afi_t afi, safi_t safi,
14714 struct prefix_rd *prd, int prefix_check)
14715{
14716 int ret;
14717 struct prefix match;
9bcb3eef
DS
14718 struct bgp_dest *dest;
14719 struct bgp_dest *rm;
40381db7
DS
14720 struct bgp_path_info *pi;
14721 struct bgp_path_info *pi_temp;
d62a17ae 14722 struct bgp *bgp;
14723 struct bgp_table *table;
14724
14725 /* BGP structure lookup. */
14726 if (view_name) {
14727 bgp = bgp_lookup_by_name(view_name);
14728 if (bgp == NULL) {
14729 vty_out(vty, "%% Can't find BGP instance %s\n",
14730 view_name);
14731 return CMD_WARNING;
14732 }
14733 } else {
14734 bgp = bgp_get_default();
14735 if (bgp == NULL) {
14736 vty_out(vty, "%% No BGP process is configured\n");
14737 return CMD_WARNING;
14738 }
718e3744 14739 }
718e3744 14740
d62a17ae 14741 /* Check IP address argument. */
14742 ret = str2prefix(ip_str, &match);
14743 if (!ret) {
14744 vty_out(vty, "%% address is malformed\n");
14745 return CMD_WARNING;
14746 }
718e3744 14747
d62a17ae 14748 match.family = afi2family(afi);
14749
14750 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14751 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14752 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14753 dest = bgp_route_next(dest)) {
14754 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14755
9bcb3eef 14756 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14757 continue;
9bcb3eef 14758 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14759 if (!table)
ea47320b 14760 continue;
4953391b
DA
14761 rm = bgp_node_match(table, &match);
14762 if (rm == NULL)
ea47320b 14763 continue;
d62a17ae 14764
9bcb3eef 14765 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14766
ea47320b 14767 if (!prefix_check
b54892e0 14768 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14769 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14770 while (pi) {
14771 if (pi->extra && pi->extra->damp_info) {
14772 pi_temp = pi->next;
ea47320b 14773 bgp_damp_info_free(
19971c9a 14774 pi->extra->damp_info,
97766ac8 14775 1);
40381db7 14776 pi = pi_temp;
ea47320b 14777 } else
40381db7 14778 pi = pi->next;
d62a17ae 14779 }
ea47320b
DL
14780 }
14781
9bcb3eef 14782 bgp_dest_unlock_node(rm);
d62a17ae 14783 }
14784 } else {
4953391b
DA
14785 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14786 if (dest != NULL) {
9bcb3eef 14787 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14788
d62a17ae 14789 if (!prefix_check
9bcb3eef
DS
14790 || dest_p->prefixlen == match.prefixlen) {
14791 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14792 while (pi) {
14793 if (pi->extra && pi->extra->damp_info) {
14794 pi_temp = pi->next;
c8ddbd48 14795 struct bgp_damp_info *bdi =
14796 pi->extra->damp_info;
14797 if (bdi->lastrecord
14798 == BGP_RECORD_UPDATE) {
14799 bgp_aggregate_increment(
14800 bgp,
14801 &bdi->dest->p,
14802 bdi->path,
14803 bdi->afi,
14804 bdi->safi);
14805 bgp_process(bgp,
14806 bdi->dest,
14807 bdi->afi,
14808 bdi->safi);
14809 }
d62a17ae 14810 bgp_damp_info_free(
19971c9a 14811 pi->extra->damp_info,
97766ac8 14812 1);
40381db7 14813 pi = pi_temp;
d62a17ae 14814 } else
40381db7 14815 pi = pi->next;
d62a17ae 14816 }
14817 }
14818
9bcb3eef 14819 bgp_dest_unlock_node(dest);
d62a17ae 14820 }
14821 }
718e3744 14822
d62a17ae 14823 return CMD_SUCCESS;
718e3744 14824}
14825
14826DEFUN (clear_ip_bgp_dampening,
14827 clear_ip_bgp_dampening_cmd,
14828 "clear ip bgp dampening",
14829 CLEAR_STR
14830 IP_STR
14831 BGP_STR
14832 "Clear route flap dampening information\n")
14833{
40ec3340 14834 VTY_DECLVAR_CONTEXT(bgp, bgp);
c8ddbd48 14835 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
40ec3340 14836 SAFI_UNICAST);
d62a17ae 14837 return CMD_SUCCESS;
718e3744 14838}
14839
14840DEFUN (clear_ip_bgp_dampening_prefix,
14841 clear_ip_bgp_dampening_prefix_cmd,
14842 "clear ip bgp dampening A.B.C.D/M",
14843 CLEAR_STR
14844 IP_STR
14845 BGP_STR
14846 "Clear route flap dampening information\n"
0c7b1b01 14847 "IPv4 prefix\n")
718e3744 14848{
d62a17ae 14849 int idx_ipv4_prefixlen = 4;
14850 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14851 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14852}
14853
14854DEFUN (clear_ip_bgp_dampening_address,
14855 clear_ip_bgp_dampening_address_cmd,
14856 "clear ip bgp dampening A.B.C.D",
14857 CLEAR_STR
14858 IP_STR
14859 BGP_STR
14860 "Clear route flap dampening information\n"
14861 "Network to clear damping information\n")
14862{
d62a17ae 14863 int idx_ipv4 = 4;
14864 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14865 SAFI_UNICAST, NULL, 0);
718e3744 14866}
14867
14868DEFUN (clear_ip_bgp_dampening_address_mask,
14869 clear_ip_bgp_dampening_address_mask_cmd,
14870 "clear ip bgp dampening A.B.C.D A.B.C.D",
14871 CLEAR_STR
14872 IP_STR
14873 BGP_STR
14874 "Clear route flap dampening information\n"
14875 "Network to clear damping information\n"
14876 "Network mask\n")
14877{
d62a17ae 14878 int idx_ipv4 = 4;
14879 int idx_ipv4_2 = 5;
14880 int ret;
14881 char prefix_str[BUFSIZ];
718e3744 14882
d62a17ae 14883 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14884 prefix_str, sizeof(prefix_str));
d62a17ae 14885 if (!ret) {
14886 vty_out(vty, "%% Inconsistent address and mask\n");
14887 return CMD_WARNING;
14888 }
718e3744 14889
d62a17ae 14890 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14891 NULL, 0);
718e3744 14892}
6b0655a2 14893
e3b78da8 14894static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14895{
14896 struct vty *vty = arg;
e3b78da8 14897 struct peer *peer = bucket->data;
825d9834
DS
14898 char buf[SU_ADDRSTRLEN];
14899
14900 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14901 sockunion2str(&peer->su, buf, sizeof(buf)));
14902}
14903
2a0e69ae
DS
14904DEFUN (show_bgp_listeners,
14905 show_bgp_listeners_cmd,
14906 "show bgp listeners",
14907 SHOW_STR
14908 BGP_STR
14909 "Display Listen Sockets and who created them\n")
14910{
14911 bgp_dump_listener_info(vty);
14912
14913 return CMD_SUCCESS;
14914}
14915
825d9834
DS
14916DEFUN (show_bgp_peerhash,
14917 show_bgp_peerhash_cmd,
14918 "show bgp peerhash",
14919 SHOW_STR
14920 BGP_STR
14921 "Display information about the BGP peerhash\n")
14922{
14923 struct list *instances = bm->bgp;
14924 struct listnode *node;
14925 struct bgp *bgp;
14926
14927 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14928 vty_out(vty, "BGP: %s\n", bgp->name);
14929 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14930 vty);
14931 }
14932
14933 return CMD_SUCCESS;
14934}
14935
587ff0fd 14936/* also used for encap safi */
2b791107
DL
14937static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14938 afi_t afi, safi_t safi)
d62a17ae 14939{
9bcb3eef
DS
14940 struct bgp_dest *pdest;
14941 struct bgp_dest *dest;
d62a17ae 14942 struct bgp_table *table;
b54892e0
DS
14943 const struct prefix *p;
14944 const struct prefix_rd *prd;
d62a17ae 14945 struct bgp_static *bgp_static;
14946 mpls_label_t label;
d62a17ae 14947 char rdbuf[RD_ADDRSTRLEN];
14948
14949 /* Network configuration. */
9bcb3eef
DS
14950 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14951 pdest = bgp_route_next(pdest)) {
14952 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14953 if (!table)
ea47320b 14954 continue;
d62a17ae 14955
9bcb3eef
DS
14956 for (dest = bgp_table_top(table); dest;
14957 dest = bgp_route_next(dest)) {
14958 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14959 if (bgp_static == NULL)
ea47320b 14960 continue;
d62a17ae 14961
9bcb3eef
DS
14962 p = bgp_dest_get_prefix(dest);
14963 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14964 pdest);
d62a17ae 14965
ea47320b 14966 /* "network" configuration display. */
06b9f471 14967 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14968 label = decode_label(&bgp_static->label);
14969
8228a9a7 14970 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14971 if (safi == SAFI_MPLS_VPN)
14972 vty_out(vty, " label %u", label);
14973
14974 if (bgp_static->rmap.name)
14975 vty_out(vty, " route-map %s",
14976 bgp_static->rmap.name);
e2a86ad9
DS
14977
14978 if (bgp_static->backdoor)
14979 vty_out(vty, " backdoor");
14980
ea47320b
DL
14981 vty_out(vty, "\n");
14982 }
14983 }
d62a17ae 14984}
14985
2b791107
DL
14986static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14987 afi_t afi, safi_t safi)
d62a17ae 14988{
9bcb3eef
DS
14989 struct bgp_dest *pdest;
14990 struct bgp_dest *dest;
d62a17ae 14991 struct bgp_table *table;
b54892e0
DS
14992 const struct prefix *p;
14993 const struct prefix_rd *prd;
d62a17ae 14994 struct bgp_static *bgp_static;
ff44f570 14995 char buf[PREFIX_STRLEN * 2];
d62a17ae 14996 char buf2[SU_ADDRSTRLEN];
14997 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14998 char esi_buf[ESI_BYTES];
d62a17ae 14999
15000 /* Network configuration. */
9bcb3eef
DS
15001 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15002 pdest = bgp_route_next(pdest)) {
15003 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15004 if (!table)
ea47320b 15005 continue;
d62a17ae 15006
9bcb3eef
DS
15007 for (dest = bgp_table_top(table); dest;
15008 dest = bgp_route_next(dest)) {
15009 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15010 if (bgp_static == NULL)
ea47320b 15011 continue;
d62a17ae 15012
ea47320b 15013 char *macrouter = NULL;
d62a17ae 15014
ea47320b
DL
15015 if (bgp_static->router_mac)
15016 macrouter = prefix_mac2str(
15017 bgp_static->router_mac, NULL, 0);
15018 if (bgp_static->eth_s_id)
0a50c248
AK
15019 esi_to_str(bgp_static->eth_s_id,
15020 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15021 p = bgp_dest_get_prefix(dest);
15022 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15023
ea47320b 15024 /* "network" configuration display. */
06b9f471 15025 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15026 if (p->u.prefix_evpn.route_type == 5) {
15027 char local_buf[PREFIX_STRLEN];
3714a385 15028 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15029 struct prefix_evpn *)p)
15030 ? AF_INET
15031 : AF_INET6;
3714a385 15032 inet_ntop(family,
15033 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15034 local_buf, PREFIX_STRLEN);
772270f3
QY
15035 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15036 p->u.prefix_evpn.prefix_addr
15037 .ip_prefix_length);
197cb530
PG
15038 } else {
15039 prefix2str(p, buf, sizeof(buf));
15040 }
ea47320b 15041
a4d82a8a
PZ
15042 if (bgp_static->gatewayIp.family == AF_INET
15043 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15044 inet_ntop(bgp_static->gatewayIp.family,
15045 &bgp_static->gatewayIp.u.prefix, buf2,
15046 sizeof(buf2));
ea47320b 15047 vty_out(vty,
7bcc8dac 15048 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15049 buf, rdbuf,
15050 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15051 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15052 macrouter);
15053
0a22ddfb 15054 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15055 }
15056 }
3da6fcd5
PG
15057}
15058
718e3744 15059/* Configuration of static route announcement and aggregate
15060 information. */
2b791107
DL
15061void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15062 safi_t safi)
d62a17ae 15063{
9bcb3eef 15064 struct bgp_dest *dest;
b54892e0 15065 const struct prefix *p;
d62a17ae 15066 struct bgp_static *bgp_static;
15067 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15068
2b791107
DL
15069 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15070 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15071 return;
15072 }
d62a17ae 15073
2b791107
DL
15074 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15075 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15076 return;
15077 }
d62a17ae 15078
15079 /* Network configuration. */
9bcb3eef
DS
15080 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15081 dest = bgp_route_next(dest)) {
15082 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15083 if (bgp_static == NULL)
ea47320b 15084 continue;
d62a17ae 15085
9bcb3eef 15086 p = bgp_dest_get_prefix(dest);
d62a17ae 15087
8228a9a7 15088 vty_out(vty, " network %pFX", p);
d62a17ae 15089
ea47320b
DL
15090 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15091 vty_out(vty, " label-index %u",
15092 bgp_static->label_index);
d62a17ae 15093
ea47320b
DL
15094 if (bgp_static->rmap.name)
15095 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15096
15097 if (bgp_static->backdoor)
15098 vty_out(vty, " backdoor");
718e3744 15099
ea47320b
DL
15100 vty_out(vty, "\n");
15101 }
15102
d62a17ae 15103 /* Aggregate-address configuration. */
9bcb3eef
DS
15104 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15105 dest = bgp_route_next(dest)) {
15106 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15107 if (bgp_aggregate == NULL)
ea47320b 15108 continue;
d62a17ae 15109
9bcb3eef 15110 p = bgp_dest_get_prefix(dest);
d62a17ae 15111
8228a9a7 15112 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15113
ea47320b
DL
15114 if (bgp_aggregate->as_set)
15115 vty_out(vty, " as-set");
d62a17ae 15116
ea47320b
DL
15117 if (bgp_aggregate->summary_only)
15118 vty_out(vty, " summary-only");
718e3744 15119
20894f50
DA
15120 if (bgp_aggregate->rmap.name)
15121 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15122
229757f1
DA
15123 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15124 vty_out(vty, " origin %s",
15125 bgp_origin2str(bgp_aggregate->origin));
15126
6aabb15d
RZ
15127 if (bgp_aggregate->match_med)
15128 vty_out(vty, " matching-MED-only");
15129
365ab2e7
RZ
15130 if (bgp_aggregate->suppress_map_name)
15131 vty_out(vty, " suppress-map %s",
15132 bgp_aggregate->suppress_map_name);
15133
ea47320b
DL
15134 vty_out(vty, "\n");
15135 }
d62a17ae 15136}
734b349e 15137
2b791107 15138void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15139 safi_t safi)
d62a17ae 15140{
9bcb3eef 15141 struct bgp_dest *dest;
d62a17ae 15142 struct bgp_distance *bdistance;
15143
15144 /* Distance configuration. */
15145 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15146 && bgp->distance_local[afi][safi]
15147 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15148 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15149 || bgp->distance_local[afi][safi]
15150 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15151 vty_out(vty, " distance bgp %d %d %d\n",
15152 bgp->distance_ebgp[afi][safi],
15153 bgp->distance_ibgp[afi][safi],
15154 bgp->distance_local[afi][safi]);
15155 }
734b349e 15156
9bcb3eef
DS
15157 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15158 dest = bgp_route_next(dest)) {
15159 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15160 if (bdistance != NULL)
56ca3b5b 15161 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15162 bdistance->distance, dest,
d62a17ae 15163 bdistance->access_list ? bdistance->access_list
15164 : "");
ca2e160d 15165 }
718e3744 15166}
15167
15168/* Allocate routing table structure and install commands. */
d62a17ae 15169void bgp_route_init(void)
15170{
15171 afi_t afi;
15172 safi_t safi;
15173
15174 /* Init BGP distance table. */
05c7a1cc 15175 FOREACH_AFI_SAFI (afi, safi)
960035b2 15176 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15177
15178 /* IPv4 BGP commands. */
15179 install_element(BGP_NODE, &bgp_table_map_cmd);
15180 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15181 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15182
554b3b10 15183 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15184
15185 /* IPv4 unicast configuration. */
15186 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15187 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15188 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15189
554b3b10 15190 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15191
15192 /* IPv4 multicast configuration. */
15193 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15194 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15195 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15196 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15197
15198 /* IPv4 labeled-unicast configuration. */
fb985e0c 15199 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15200 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15201
d62a17ae 15202 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15203 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 15204 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15205 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 15206 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 15207 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15208 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15209 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15210
15211 install_element(VIEW_NODE,
15212 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15213 install_element(VIEW_NODE,
15214 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15215 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15216 install_element(VIEW_NODE,
15217 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15218#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15219 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15220#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15221 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15222 install_element(VIEW_NODE,
44c69747 15223 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15224
d62a17ae 15225 /* BGP dampening clear commands */
15226 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15227 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15228
d62a17ae 15229 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15230 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15231
15232 /* prefix count */
15233 install_element(ENABLE_NODE,
15234 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15235#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15236 install_element(ENABLE_NODE,
15237 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15238#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15239
d62a17ae 15240 /* New config IPv6 BGP commands. */
15241 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15242 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15243 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15244
554b3b10 15245 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15246
15247 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15248
fb985e0c
DA
15249 /* IPv6 labeled unicast address family. */
15250 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15251 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15252
d62a17ae 15253 install_element(BGP_NODE, &bgp_distance_cmd);
15254 install_element(BGP_NODE, &no_bgp_distance_cmd);
15255 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 15256 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15257 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15258 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 15259 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15260 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15261 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 15262 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15263 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 15264 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 15265 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15266 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 15267 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 15268
ef5f4b23 15269 /* BGP dampening */
d9ce5113
CS
15270 install_element(BGP_NODE, &bgp_dampening_cmd);
15271 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
15272 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
15273 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
15274 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
15275 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
15276 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 15277
15278 /* Large Communities */
15279 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15280 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15281
15282 /* show bgp ipv4 flowspec detailed */
15283 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15284
2a0e69ae 15285 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15286 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15287}
15288
15289void bgp_route_finish(void)
15290{
15291 afi_t afi;
15292 safi_t safi;
15293
05c7a1cc
QY
15294 FOREACH_AFI_SAFI (afi, safi) {
15295 bgp_table_unlock(bgp_distance_table[afi][safi]);
15296 bgp_distance_table[afi][safi] = NULL;
15297 }
228da428 15298}