]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
Merge pull request #8829 from donaldsharp/last_command
[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
c93a3b77
DS
225 e->damp_info = NULL;
226 if (e->parent) {
40381db7 227 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 228
40381db7 229 if (bpi->net) {
0e70e6c8
DL
230 /* FIXME: since multiple e may have the same e->parent
231 * and e->parent->net is holding a refcount for each
232 * of them, we need to do some fudging here.
233 *
40381db7
DS
234 * WARNING: if bpi->net->lock drops to 0, bpi may be
235 * freed as well (because bpi->net was holding the
236 * last reference to bpi) => write after free!
0e70e6c8
DL
237 */
238 unsigned refcount;
239
40381db7 240 bpi = bgp_path_info_lock(bpi);
c10e14e9 241 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 242 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 243 if (!refcount)
40381db7
DS
244 bpi->net = NULL;
245 bgp_path_info_unlock(bpi);
0e70e6c8 246 }
18ee8310 247 bgp_path_info_unlock(e->parent);
c93a3b77 248 e->parent = NULL;
d62a17ae 249 }
c93a3b77
DS
250
251 if (e->bgp_orig)
252 bgp_unlock(e->bgp_orig);
c26edcda 253
ff3bf9a4
DS
254 if (e->aggr_suppressors)
255 list_delete(&e->aggr_suppressors);
256
60605cbc
AK
257 if (e->mh_info)
258 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 259
ce3c0614
PG
260 if ((*extra)->bgp_fs_iprule)
261 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 262 if ((*extra)->bgp_fs_pbr)
6a154c88 263 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 264 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
265}
266
18ee8310
DS
267/* Get bgp_path_info extra information for the given bgp_path_info, lazy
268 * allocated if required.
fb982c25 269 */
40381db7 270struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 271{
40381db7
DS
272 if (!pi->extra)
273 pi->extra = bgp_path_info_extra_new();
274 return pi->extra;
fb982c25
PJ
275}
276
718e3744 277/* Free bgp route information. */
9b6d8fcf 278static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 279{
05864da7 280 bgp_attr_unintern(&path->attr);
fb018d25 281
9b6d8fcf
DS
282 bgp_unlink_nexthop(path);
283 bgp_path_info_extra_free(&path->extra);
284 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
285 if (path->net)
286 bgp_addpath_free_info_data(&path->tx_addpath,
287 &path->net->tx_addpath);
718e3744 288
9b6d8fcf 289 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 290
9b6d8fcf 291 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 292}
293
9b6d8fcf 294struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 295{
9b6d8fcf
DS
296 path->lock++;
297 return path;
200df115 298}
299
9b6d8fcf 300struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 301{
9b6d8fcf
DS
302 assert(path && path->lock > 0);
303 path->lock--;
d62a17ae 304
9b6d8fcf 305 if (path->lock == 0) {
200df115 306#if 0
307 zlog_debug ("%s: unlocked and freeing", __func__);
308 zlog_backtrace (LOG_DEBUG);
309#endif
9b6d8fcf 310 bgp_path_info_free(path);
d62a17ae 311 return NULL;
312 }
200df115 313
314#if 0
9b6d8fcf 315 if (path->lock == 1)
200df115 316 {
317 zlog_debug ("%s: unlocked to 1", __func__);
318 zlog_backtrace (LOG_DEBUG);
319 }
320#endif
d62a17ae 321
9b6d8fcf 322 return path;
200df115 323}
324
f009ff26 325/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 326static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 327{
328 struct peer *peer;
329 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 330 bool set_flag = false;
f009ff26 331 struct bgp *bgp = NULL;
332 struct bgp_table *table = NULL;
333 afi_t afi = 0;
334 safi_t safi = 0;
f009ff26 335
336 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
337 * then the route selection is deferred
338 */
9bcb3eef 339 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 340 return 0;
341
9bcb3eef 342 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 343 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 344 zlog_debug(
56ca3b5b
DL
345 "Route %pBD is in workqueue and being processed, not deferred.",
346 dest);
b54892e0 347
5f9c1aa2 348 return 0;
349 }
350
9bcb3eef 351 table = bgp_dest_table(dest);
f009ff26 352 if (table) {
353 bgp = table->bgp;
354 afi = table->afi;
355 safi = table->safi;
356 }
357
9bcb3eef 358 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 359 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
360 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
361 continue;
362
363 /* Route selection is deferred if there is a stale path which
364 * which indicates peer is in restart mode
365 */
36235319
QY
366 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
367 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 368 set_flag = true;
f009ff26 369 } else {
370 /* If the peer is graceful restart capable and peer is
371 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
372 */
373 peer = old_pi->peer;
36235319
QY
374 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
375 && BGP_PEER_RESTARTING_MODE(peer)
376 && (old_pi
377 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 378 set_flag = true;
f009ff26 379 }
380 }
381 if (set_flag)
382 break;
383 }
384
385 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
386 * is active
387 */
2ba1fe69 388 if (set_flag && table) {
f009ff26 389 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
390 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
391 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 392 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 393 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
394 zlog_debug("DEFER route %pBD, dest %p", dest,
395 dest);
f009ff26 396 return 0;
397 }
398 }
399 return -1;
400}
401
9bcb3eef 402void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 403{
4b7e6066 404 struct bgp_path_info *top;
718e3744 405
9bcb3eef 406 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 407
6f94b685 408 pi->next = top;
40381db7 409 pi->prev = NULL;
d62a17ae 410 if (top)
40381db7 411 top->prev = pi;
9bcb3eef 412 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 413
40381db7 414 bgp_path_info_lock(pi);
9bcb3eef 415 bgp_dest_lock_node(dest);
40381db7 416 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 417 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 418 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 419}
420
d62a17ae 421/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 422 completion callback *only* */
9bcb3eef 423void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 424{
40381db7
DS
425 if (pi->next)
426 pi->next->prev = pi->prev;
427 if (pi->prev)
428 pi->prev->next = pi->next;
d62a17ae 429 else
9bcb3eef 430 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 431
40381db7
DS
432 bgp_path_info_mpath_dequeue(pi);
433 bgp_path_info_unlock(pi);
7fd28dd2 434 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 435 bgp_dest_unlock_node(dest);
718e3744 436}
437
9bcb3eef 438void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 439{
9bcb3eef 440 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 441 /* set of previous already took care of pcount */
40381db7 442 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 443}
444
18ee8310 445/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
446 called when a route is deleted and then quickly re-added before the
447 deletion has been processed */
9bcb3eef 448void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 449{
9bcb3eef 450 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 451 /* unset of previous already took care of pcount */
40381db7 452 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
453}
454
d62a17ae 455/* Adjust pcount as required */
9bcb3eef 456static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 457{
d62a17ae 458 struct bgp_table *table;
67174041 459
9bcb3eef 460 assert(dest && bgp_dest_table(dest));
40381db7 461 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 462
9bcb3eef 463 table = bgp_dest_table(dest);
67174041 464
40381db7 465 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 466 return;
467
40381db7
DS
468 if (!BGP_PATH_COUNTABLE(pi)
469 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 470
40381db7 471 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 472
473 /* slight hack, but more robust against errors. */
40381db7
DS
474 if (pi->peer->pcount[table->afi][table->safi])
475 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 476 else
450971aa 477 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 478 "Asked to decrement 0 prefix count for peer");
40381db7
DS
479 } else if (BGP_PATH_COUNTABLE(pi)
480 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
481 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
482 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 483 }
1a392d46
PJ
484}
485
40381db7
DS
486static int bgp_label_index_differs(struct bgp_path_info *pi1,
487 struct bgp_path_info *pi2)
28d58fd7 488{
40381db7 489 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 490}
1a392d46 491
18ee8310 492/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
493 * This is here primarily to keep prefix-count in check.
494 */
9bcb3eef 495void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 496 uint32_t flag)
1a392d46 497{
40381db7 498 SET_FLAG(pi->flags, flag);
d62a17ae 499
500 /* early bath if we know it's not a flag that changes countability state
501 */
502 if (!CHECK_FLAG(flag,
1defdda8 503 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 504 return;
505
9bcb3eef 506 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
507}
508
9bcb3eef 509void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 510 uint32_t flag)
1a392d46 511{
40381db7 512 UNSET_FLAG(pi->flags, flag);
d62a17ae 513
514 /* early bath if we know it's not a flag that changes countability state
515 */
516 if (!CHECK_FLAG(flag,
1defdda8 517 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 518 return;
519
9bcb3eef 520 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
521}
522
718e3744 523/* Get MED value. If MED value is missing and "bgp bestpath
524 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 525static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 526{
527 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
528 return attr->med;
529 else {
892fedb6 530 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 531 return BGP_MED_MAX;
532 else
533 return 0;
534 }
718e3744 535}
536
7533cad7
QY
537void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
538 size_t buf_len)
2ec1e66f 539{
40381db7 540 if (pi->addpath_rx_id)
7533cad7
QY
541 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
542 pi->peer->host, pi->addpath_rx_id);
d62a17ae 543 else
7533cad7 544 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 545}
9fbdd100 546
d62a17ae 547/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
548 */
18ee8310
DS
549static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
550 struct bgp_path_info *exist, int *paths_eq,
551 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
552 char *pfx_buf, afi_t afi, safi_t safi,
553 enum bgp_path_selection_reason *reason)
d62a17ae 554{
5df26422 555 const struct prefix *new_p;
d62a17ae 556 struct attr *newattr, *existattr;
557 bgp_peer_sort_t new_sort;
558 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
559 uint32_t new_pref;
560 uint32_t exist_pref;
561 uint32_t new_med;
562 uint32_t exist_med;
563 uint32_t new_weight;
564 uint32_t exist_weight;
d62a17ae 565 uint32_t newm, existm;
566 struct in_addr new_id;
567 struct in_addr exist_id;
568 int new_cluster;
569 int exist_cluster;
570 int internal_as_route;
571 int confed_as_route;
04d14c8b 572 int ret = 0;
ee88563a
JM
573 int igp_metric_ret = 0;
574 int peer_sort_ret = -1;
d62a17ae 575 char new_buf[PATH_ADDPATH_STR_BUFFER];
576 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
577 uint32_t new_mm_seq;
578 uint32_t exist_mm_seq;
6d8c603a 579 int nh_cmp;
d071f237
AK
580 esi_t *exist_esi;
581 esi_t *new_esi;
582 bool same_esi;
583 bool old_proxy;
584 bool new_proxy;
33c6e933 585 bool new_origin, exist_origin;
d62a17ae 586
587 *paths_eq = 0;
588
589 /* 0. Null check. */
590 if (new == NULL) {
fdf81fa0 591 *reason = bgp_path_selection_none;
d62a17ae 592 if (debug)
593 zlog_debug("%s: new is NULL", pfx_buf);
594 return 0;
595 }
2ec1e66f 596
d62a17ae 597 if (debug)
7533cad7
QY
598 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
599 sizeof(new_buf));
718e3744 600
d62a17ae 601 if (exist == NULL) {
fdf81fa0 602 *reason = bgp_path_selection_first;
d62a17ae 603 if (debug)
604 zlog_debug("%s: %s is the initial bestpath", pfx_buf,
605 new_buf);
606 return 1;
607 }
2ec1e66f 608
d62a17ae 609 if (debug) {
7533cad7
QY
610 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
611 sizeof(exist_buf));
d62a17ae 612 zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
613 pfx_buf, new_buf, new->flags, exist_buf,
614 exist->flags);
615 }
8ff56318 616
d62a17ae 617 newattr = new->attr;
618 existattr = exist->attr;
619
5df26422
NS
620 new_p = bgp_dest_get_prefix(new->net);
621
d62a17ae 622 /* For EVPN routes, we cannot just go by local vs remote, we have to
623 * look at the MAC mobility sequence number, if present.
624 */
5df26422
NS
625 if ((safi == SAFI_EVPN)
626 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 627 /* This is an error condition described in RFC 7432 Section
628 * 15.2. The RFC
629 * states that in this scenario "the PE MUST alert the operator"
630 * but it
631 * does not state what other action to take. In order to provide
632 * some
633 * consistency in this scenario we are going to prefer the path
634 * with the
635 * sticky flag.
636 */
637 if (newattr->sticky != existattr->sticky) {
638 if (!debug) {
5df26422
NS
639 prefix2str(new_p, pfx_buf,
640 sizeof(*pfx_buf)
641 * PREFIX2STR_BUFFER);
18ee8310 642 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
643 new, new_buf, sizeof(new_buf));
644 bgp_path_info_path_with_addpath_rx_str(
645 exist, exist_buf, sizeof(exist_buf));
d62a17ae 646 }
647
648 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 649 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
650 if (debug)
651 zlog_debug(
652 "%s: %s wins over %s due to sticky MAC flag",
653 pfx_buf, new_buf, exist_buf);
d62a17ae 654 return 1;
655 }
656
657 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 658 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
659 if (debug)
660 zlog_debug(
661 "%s: %s loses to %s due to sticky MAC flag",
662 pfx_buf, new_buf, exist_buf);
d62a17ae 663 return 0;
664 }
665 }
128ea8ab 666
d071f237
AK
667 new_esi = bgp_evpn_attr_get_esi(newattr);
668 exist_esi = bgp_evpn_attr_get_esi(existattr);
669 if (bgp_evpn_is_esi_valid(new_esi) &&
670 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
671 same_esi = true;
672 } else {
673 same_esi = false;
674 }
675
676 /* If both paths have the same non-zero ES and
677 * one path is local it wins.
678 * PS: Note the local path wins even if the remote
679 * has the higher MM seq. The local path's
680 * MM seq will be fixed up to match the highest
681 * rem seq, subsequently.
682 */
683 if (same_esi) {
684 char esi_buf[ESI_STR_LEN];
685
686 if (bgp_evpn_is_path_local(bgp, new)) {
687 *reason = bgp_path_selection_evpn_local_path;
688 if (debug)
689 zlog_debug(
690 "%s: %s wins over %s as ES %s is same and local",
691 pfx_buf, new_buf, exist_buf,
692 esi_to_str(new_esi, esi_buf,
693 sizeof(esi_buf)));
694 return 1;
695 }
696 if (bgp_evpn_is_path_local(bgp, exist)) {
697 *reason = bgp_path_selection_evpn_local_path;
698 if (debug)
699 zlog_debug(
700 "%s: %s loses to %s as ES %s is same and local",
701 pfx_buf, new_buf, exist_buf,
702 esi_to_str(new_esi, esi_buf,
703 sizeof(esi_buf)));
704 return 0;
705 }
706 }
707
d62a17ae 708 new_mm_seq = mac_mobility_seqnum(newattr);
709 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 710
d62a17ae 711 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 712 *reason = bgp_path_selection_evpn_seq;
d62a17ae 713 if (debug)
714 zlog_debug(
715 "%s: %s wins over %s due to MM seq %u > %u",
716 pfx_buf, new_buf, exist_buf, new_mm_seq,
717 exist_mm_seq);
718 return 1;
719 }
8ff56318 720
d62a17ae 721 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 722 *reason = bgp_path_selection_evpn_seq;
d62a17ae 723 if (debug)
724 zlog_debug(
725 "%s: %s loses to %s due to MM seq %u < %u",
726 pfx_buf, new_buf, exist_buf, new_mm_seq,
727 exist_mm_seq);
728 return 0;
729 }
6d8c603a 730
d071f237
AK
731 /* if the sequence numbers and ESI are the same and one path
732 * is non-proxy it wins (over proxy)
733 */
734 new_proxy = bgp_evpn_attr_is_proxy(newattr);
735 old_proxy = bgp_evpn_attr_is_proxy(existattr);
736 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
737 old_proxy != new_proxy) {
738 if (!new_proxy) {
739 *reason = bgp_path_selection_evpn_non_proxy;
740 if (debug)
741 zlog_debug(
742 "%s: %s wins over %s, same seq/es and non-proxy",
743 pfx_buf, new_buf, exist_buf);
744 return 1;
745 }
746
747 *reason = bgp_path_selection_evpn_non_proxy;
748 if (debug)
749 zlog_debug(
750 "%s: %s loses to %s, same seq/es and non-proxy",
751 pfx_buf, new_buf, exist_buf);
752 return 0;
753 }
754
6d8c603a
AK
755 /*
756 * if sequence numbers are the same path with the lowest IP
757 * wins
758 */
759 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
760 if (nh_cmp < 0) {
fdf81fa0 761 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
762 if (debug)
763 zlog_debug(
23d0a753 764 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 765 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 766 &new->attr->nexthop);
6d8c603a
AK
767 return 1;
768 }
769 if (nh_cmp > 0) {
fdf81fa0 770 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
771 if (debug)
772 zlog_debug(
23d0a753 773 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 774 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 775 &new->attr->nexthop);
6d8c603a
AK
776 return 0;
777 }
d62a17ae 778 }
9fbdd100 779
d62a17ae 780 /* 1. Weight check. */
d62a17ae 781 new_weight = newattr->weight;
782 exist_weight = existattr->weight;
8ff56318 783
d62a17ae 784 if (new_weight > exist_weight) {
fdf81fa0 785 *reason = bgp_path_selection_weight;
d62a17ae 786 if (debug)
787 zlog_debug("%s: %s wins over %s due to weight %d > %d",
788 pfx_buf, new_buf, exist_buf, new_weight,
789 exist_weight);
790 return 1;
791 }
718e3744 792
d62a17ae 793 if (new_weight < exist_weight) {
fdf81fa0 794 *reason = bgp_path_selection_weight;
d62a17ae 795 if (debug)
796 zlog_debug("%s: %s loses to %s due to weight %d < %d",
797 pfx_buf, new_buf, exist_buf, new_weight,
798 exist_weight);
799 return 0;
800 }
9fbdd100 801
d62a17ae 802 /* 2. Local preference check. */
803 new_pref = exist_pref = bgp->default_local_pref;
804
805 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
806 new_pref = newattr->local_pref;
807 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
808 exist_pref = existattr->local_pref;
809
810 if (new_pref > exist_pref) {
fdf81fa0 811 *reason = bgp_path_selection_local_pref;
d62a17ae 812 if (debug)
813 zlog_debug(
814 "%s: %s wins over %s due to localpref %d > %d",
815 pfx_buf, new_buf, exist_buf, new_pref,
816 exist_pref);
817 return 1;
818 }
718e3744 819
d62a17ae 820 if (new_pref < exist_pref) {
fdf81fa0 821 *reason = bgp_path_selection_local_pref;
d62a17ae 822 if (debug)
823 zlog_debug(
824 "%s: %s loses to %s due to localpref %d < %d",
825 pfx_buf, new_buf, exist_buf, new_pref,
826 exist_pref);
827 return 0;
828 }
9fbdd100 829
d62a17ae 830 /* 3. Local route check. We prefer:
831 * - BGP_ROUTE_STATIC
832 * - BGP_ROUTE_AGGREGATE
833 * - BGP_ROUTE_REDISTRIBUTE
834 */
33c6e933
DS
835 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
836 new->sub_type == BGP_ROUTE_IMPORTED);
837 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
838 exist->sub_type == BGP_ROUTE_IMPORTED);
839
840 if (new_origin && !exist_origin) {
fdf81fa0 841 *reason = bgp_path_selection_local_route;
d62a17ae 842 if (debug)
843 zlog_debug(
844 "%s: %s wins over %s due to preferred BGP_ROUTE type",
845 pfx_buf, new_buf, exist_buf);
846 return 1;
847 }
718e3744 848
33c6e933 849 if (!new_origin && exist_origin) {
fdf81fa0 850 *reason = bgp_path_selection_local_route;
d62a17ae 851 if (debug)
852 zlog_debug(
853 "%s: %s loses to %s due to preferred BGP_ROUTE type",
854 pfx_buf, new_buf, exist_buf);
855 return 0;
6811845b 856 }
718e3744 857
d62a17ae 858 /* 4. AS path length check. */
892fedb6 859 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 860 int exist_hops = aspath_count_hops(existattr->aspath);
861 int exist_confeds = aspath_count_confeds(existattr->aspath);
862
892fedb6 863 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 864 int aspath_hops;
865
866 aspath_hops = aspath_count_hops(newattr->aspath);
867 aspath_hops += aspath_count_confeds(newattr->aspath);
868
869 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 870 *reason = bgp_path_selection_confed_as_path;
d62a17ae 871 if (debug)
872 zlog_debug(
873 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
874 pfx_buf, new_buf, exist_buf,
875 aspath_hops,
876 (exist_hops + exist_confeds));
877 return 1;
878 }
879
880 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 881 *reason = bgp_path_selection_confed_as_path;
d62a17ae 882 if (debug)
883 zlog_debug(
884 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
885 pfx_buf, new_buf, exist_buf,
886 aspath_hops,
887 (exist_hops + exist_confeds));
888 return 0;
889 }
890 } else {
891 int newhops = aspath_count_hops(newattr->aspath);
892
893 if (newhops < exist_hops) {
fdf81fa0 894 *reason = bgp_path_selection_as_path;
d62a17ae 895 if (debug)
896 zlog_debug(
897 "%s: %s wins over %s due to aspath hopcount %d < %d",
898 pfx_buf, new_buf, exist_buf,
899 newhops, exist_hops);
900 return 1;
901 }
902
903 if (newhops > exist_hops) {
fdf81fa0 904 *reason = bgp_path_selection_as_path;
d62a17ae 905 if (debug)
906 zlog_debug(
907 "%s: %s loses to %s due to aspath hopcount %d > %d",
908 pfx_buf, new_buf, exist_buf,
909 newhops, exist_hops);
910 return 0;
911 }
912 }
913 }
9fbdd100 914
d62a17ae 915 /* 5. Origin check. */
916 if (newattr->origin < existattr->origin) {
fdf81fa0 917 *reason = bgp_path_selection_origin;
d62a17ae 918 if (debug)
919 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
920 pfx_buf, new_buf, exist_buf,
921 bgp_origin_long_str[newattr->origin],
922 bgp_origin_long_str[existattr->origin]);
923 return 1;
924 }
718e3744 925
d62a17ae 926 if (newattr->origin > existattr->origin) {
fdf81fa0 927 *reason = bgp_path_selection_origin;
d62a17ae 928 if (debug)
929 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
930 pfx_buf, new_buf, exist_buf,
931 bgp_origin_long_str[newattr->origin],
932 bgp_origin_long_str[existattr->origin]);
933 return 0;
934 }
718e3744 935
d62a17ae 936 /* 6. MED check. */
937 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
938 && aspath_count_hops(existattr->aspath) == 0);
939 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
940 && aspath_count_confeds(existattr->aspath) > 0
941 && aspath_count_hops(newattr->aspath) == 0
942 && aspath_count_hops(existattr->aspath) == 0);
943
892fedb6
DA
944 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
945 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 946 || aspath_cmp_left(newattr->aspath, existattr->aspath)
947 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
948 || internal_as_route) {
949 new_med = bgp_med_value(new->attr, bgp);
950 exist_med = bgp_med_value(exist->attr, bgp);
951
952 if (new_med < exist_med) {
fdf81fa0 953 *reason = bgp_path_selection_med;
d62a17ae 954 if (debug)
955 zlog_debug(
956 "%s: %s wins over %s due to MED %d < %d",
957 pfx_buf, new_buf, exist_buf, new_med,
958 exist_med);
959 return 1;
960 }
8ff56318 961
d62a17ae 962 if (new_med > exist_med) {
fdf81fa0 963 *reason = bgp_path_selection_med;
d62a17ae 964 if (debug)
965 zlog_debug(
966 "%s: %s loses to %s due to MED %d > %d",
967 pfx_buf, new_buf, exist_buf, new_med,
968 exist_med);
969 return 0;
970 }
971 }
9fbdd100 972
d62a17ae 973 /* 7. Peer type check. */
974 new_sort = new->peer->sort;
975 exist_sort = exist->peer->sort;
976
977 if (new_sort == BGP_PEER_EBGP
978 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 979 *reason = bgp_path_selection_peer;
d62a17ae 980 if (debug)
981 zlog_debug(
982 "%s: %s wins over %s due to eBGP peer > iBGP peer",
983 pfx_buf, new_buf, exist_buf);
ee88563a
JM
984 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
985 return 1;
986 peer_sort_ret = 1;
d62a17ae 987 }
718e3744 988
d62a17ae 989 if (exist_sort == BGP_PEER_EBGP
990 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 991 *reason = bgp_path_selection_peer;
d62a17ae 992 if (debug)
993 zlog_debug(
994 "%s: %s loses to %s due to iBGP peer < eBGP peer",
995 pfx_buf, new_buf, exist_buf);
ee88563a
JM
996 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
997 return 0;
998 peer_sort_ret = 0;
d62a17ae 999 }
8ff56318 1000
d62a17ae 1001 /* 8. IGP metric check. */
1002 newm = existm = 0;
8ff56318 1003
d62a17ae 1004 if (new->extra)
1005 newm = new->extra->igpmetric;
1006 if (exist->extra)
1007 existm = exist->extra->igpmetric;
9fbdd100 1008
d62a17ae 1009 if (newm < existm) {
ee88563a 1010 if (debug && peer_sort_ret < 0)
d62a17ae 1011 zlog_debug(
d588b995 1012 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1013 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1014 igp_metric_ret = 1;
d62a17ae 1015 }
718e3744 1016
d62a17ae 1017 if (newm > existm) {
ee88563a 1018 if (debug && peer_sort_ret < 0)
d62a17ae 1019 zlog_debug(
d588b995 1020 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1021 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1022 igp_metric_ret = 0;
5e242b0d 1023 }
5e242b0d 1024
d62a17ae 1025 /* 9. Same IGP metric. Compare the cluster list length as
1026 representative of IGP hops metric. Rewrite the metric value
1027 pair (newm, existm) with the cluster list length. Prefer the
1028 path with smaller cluster list length. */
1029 if (newm == existm) {
bf0d28dc
DS
1030 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1031 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1032 && (mpath_cfg == NULL
1033 || CHECK_FLAG(
1034 mpath_cfg->ibgp_flags,
1035 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1036 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1037 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1038
1039 if (newm < existm) {
ee88563a 1040 if (debug && peer_sort_ret < 0)
d62a17ae 1041 zlog_debug(
d588b995 1042 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1043 pfx_buf, new_buf, exist_buf,
1044 newm, existm);
ee88563a 1045 igp_metric_ret = 1;
d62a17ae 1046 }
1047
1048 if (newm > existm) {
ee88563a 1049 if (debug && peer_sort_ret < 0)
d62a17ae 1050 zlog_debug(
d588b995 1051 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1052 pfx_buf, new_buf, exist_buf,
1053 newm, existm);
ee88563a 1054 igp_metric_ret = 0;
d62a17ae 1055 }
1056 }
1057 }
31a4638f 1058
d62a17ae 1059 /* 10. confed-external vs. confed-internal */
1060 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1061 if (new_sort == BGP_PEER_CONFED
1062 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1063 *reason = bgp_path_selection_confed;
d62a17ae 1064 if (debug)
1065 zlog_debug(
1066 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1067 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1068 if (!CHECK_FLAG(bgp->flags,
1069 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1070 return 1;
1071 peer_sort_ret = 1;
d62a17ae 1072 }
718e3744 1073
d62a17ae 1074 if (exist_sort == BGP_PEER_CONFED
1075 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1076 *reason = bgp_path_selection_confed;
d62a17ae 1077 if (debug)
1078 zlog_debug(
1079 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1080 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1081 if (!CHECK_FLAG(bgp->flags,
1082 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1083 return 0;
1084 peer_sort_ret = 0;
d62a17ae 1085 }
1086 }
718e3744 1087
d62a17ae 1088 /* 11. Maximum path check. */
1089 if (newm == existm) {
1090 /* If one path has a label but the other does not, do not treat
1091 * them as equals for multipath
1092 */
a4d82a8a 1093 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1094 != (exist->extra
b57ba6d2 1095 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1096 if (debug)
1097 zlog_debug(
1098 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1099 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1100 } else if (CHECK_FLAG(bgp->flags,
1101 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1102
1103 /*
1104 * For the two paths, all comparison steps till IGP
1105 * metric
1106 * have succeeded - including AS_PATH hop count. Since
1107 * 'bgp
1108 * bestpath as-path multipath-relax' knob is on, we
1109 * don't need
1110 * an exact match of AS_PATH. Thus, mark the paths are
1111 * equal.
1112 * That will trigger both these paths to get into the
1113 * multipath
1114 * array.
1115 */
1116 *paths_eq = 1;
1117
1118 if (debug)
1119 zlog_debug(
1120 "%s: %s and %s are equal via multipath-relax",
1121 pfx_buf, new_buf, exist_buf);
1122 } else if (new->peer->sort == BGP_PEER_IBGP) {
1123 if (aspath_cmp(new->attr->aspath,
1124 exist->attr->aspath)) {
1125 *paths_eq = 1;
1126
1127 if (debug)
1128 zlog_debug(
1129 "%s: %s and %s are equal via matching aspaths",
1130 pfx_buf, new_buf, exist_buf);
1131 }
1132 } else if (new->peer->as == exist->peer->as) {
1133 *paths_eq = 1;
1134
1135 if (debug)
1136 zlog_debug(
1137 "%s: %s and %s are equal via same remote-as",
1138 pfx_buf, new_buf, exist_buf);
1139 }
1140 } else {
1141 /*
1142 * TODO: If unequal cost ibgp multipath is enabled we can
1143 * mark the paths as equal here instead of returning
1144 */
ee88563a
JM
1145
1146 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1147 * if either step 7 or 10 (peer type checks) yielded a winner,
1148 * that result was returned immediately. Returning from step 10
1149 * ignored the return value computed in steps 8 and 9 (IGP
1150 * metric checks). In order to preserve that behavior, if
1151 * peer_sort_ret is set, return that rather than igp_metric_ret.
1152 */
1153 ret = peer_sort_ret;
1154 if (peer_sort_ret < 0) {
1155 ret = igp_metric_ret;
1156 if (debug) {
1157 if (ret == 1)
1158 zlog_debug(
1159 "%s: %s wins over %s after IGP metric comparison",
1160 pfx_buf, new_buf, exist_buf);
1161 else
1162 zlog_debug(
1163 "%s: %s loses to %s after IGP metric comparison",
1164 pfx_buf, new_buf, exist_buf);
1165 }
1166 *reason = bgp_path_selection_igp_metric;
d62a17ae 1167 }
1168 return ret;
1169 }
718e3744 1170
ee88563a
JM
1171 /*
1172 * At this point, the decision whether to set *paths_eq = 1 has been
1173 * completed. If we deferred returning because of bestpath peer-type
1174 * relax configuration, return now.
1175 */
1176 if (peer_sort_ret >= 0)
1177 return peer_sort_ret;
1178
d62a17ae 1179 /* 12. If both paths are external, prefer the path that was received
1180 first (the oldest one). This step minimizes route-flap, since a
1181 newer path won't displace an older one, even if it was the
1182 preferred route based on the additional decision criteria below. */
892fedb6 1183 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1184 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1185 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1186 *reason = bgp_path_selection_older;
d62a17ae 1187 if (debug)
1188 zlog_debug(
1189 "%s: %s wins over %s due to oldest external",
1190 pfx_buf, new_buf, exist_buf);
1191 return 1;
1192 }
9fbdd100 1193
1defdda8 1194 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1195 *reason = bgp_path_selection_older;
d62a17ae 1196 if (debug)
1197 zlog_debug(
1198 "%s: %s loses to %s due to oldest external",
1199 pfx_buf, new_buf, exist_buf);
1200 return 0;
1201 }
1202 }
718e3744 1203
d62a17ae 1204 /* 13. Router-ID comparision. */
1205 /* If one of the paths is "stale", the corresponding peer router-id will
1206 * be 0 and would always win over the other path. If originator id is
1207 * used for the comparision, it will decide which path is better.
1208 */
1209 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1210 new_id.s_addr = newattr->originator_id.s_addr;
1211 else
1212 new_id.s_addr = new->peer->remote_id.s_addr;
1213 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1214 exist_id.s_addr = existattr->originator_id.s_addr;
1215 else
1216 exist_id.s_addr = exist->peer->remote_id.s_addr;
1217
1218 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1219 *reason = bgp_path_selection_router_id;
d62a17ae 1220 if (debug)
1221 zlog_debug(
1222 "%s: %s wins over %s due to Router-ID comparison",
1223 pfx_buf, new_buf, exist_buf);
1224 return 1;
1225 }
718e3744 1226
d62a17ae 1227 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1228 *reason = bgp_path_selection_router_id;
d62a17ae 1229 if (debug)
1230 zlog_debug(
1231 "%s: %s loses to %s due to Router-ID comparison",
1232 pfx_buf, new_buf, exist_buf);
1233 return 0;
1234 }
9fbdd100 1235
d62a17ae 1236 /* 14. Cluster length comparision. */
1237 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1238 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1239
1240 if (new_cluster < exist_cluster) {
fdf81fa0 1241 *reason = bgp_path_selection_cluster_length;
d62a17ae 1242 if (debug)
1243 zlog_debug(
1244 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1245 pfx_buf, new_buf, exist_buf, new_cluster,
1246 exist_cluster);
1247 return 1;
1248 }
718e3744 1249
d62a17ae 1250 if (new_cluster > exist_cluster) {
fdf81fa0 1251 *reason = bgp_path_selection_cluster_length;
d62a17ae 1252 if (debug)
1253 zlog_debug(
1254 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1255 pfx_buf, new_buf, exist_buf, new_cluster,
1256 exist_cluster);
1257 return 0;
1258 }
9fbdd100 1259
d62a17ae 1260 /* 15. Neighbor address comparision. */
1261 /* Do this only if neither path is "stale" as stale paths do not have
1262 * valid peer information (as the connection may or may not be up).
1263 */
1defdda8 1264 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1265 *reason = bgp_path_selection_stale;
d62a17ae 1266 if (debug)
1267 zlog_debug(
1268 "%s: %s wins over %s due to latter path being STALE",
1269 pfx_buf, new_buf, exist_buf);
1270 return 1;
1271 }
0de5153c 1272
1defdda8 1273 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1274 *reason = bgp_path_selection_stale;
d62a17ae 1275 if (debug)
1276 zlog_debug(
1277 "%s: %s loses to %s due to former path being STALE",
1278 pfx_buf, new_buf, exist_buf);
1279 return 0;
1280 }
718e3744 1281
d62a17ae 1282 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1283 if (new->peer->su_remote == NULL) {
1284 *reason = bgp_path_selection_local_configured;
d62a17ae 1285 return 0;
fdf81fa0
DS
1286 }
1287 if (exist->peer->su_remote == NULL) {
1288 *reason = bgp_path_selection_local_configured;
d62a17ae 1289 return 1;
fdf81fa0 1290 }
9fbdd100 1291
d62a17ae 1292 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1293
1294 if (ret == 1) {
fdf81fa0 1295 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1296 if (debug)
1297 zlog_debug(
1298 "%s: %s loses to %s due to Neighor IP comparison",
1299 pfx_buf, new_buf, exist_buf);
1300 return 0;
1301 }
1302
1303 if (ret == -1) {
fdf81fa0 1304 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1305 if (debug)
1306 zlog_debug(
1307 "%s: %s wins over %s due to Neighor IP comparison",
1308 pfx_buf, new_buf, exist_buf);
1309 return 1;
1310 }
9fbdd100 1311
fdf81fa0 1312 *reason = bgp_path_selection_default;
d62a17ae 1313 if (debug)
1314 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1315 pfx_buf, new_buf, exist_buf);
718e3744 1316
d62a17ae 1317 return 1;
718e3744 1318}
1319
d071f237
AK
1320
1321int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1322 struct bgp_path_info *exist, int *paths_eq)
1323{
1324 enum bgp_path_selection_reason reason;
1325 char pfx_buf[PREFIX2STR_BUFFER];
1326
1327 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1328 AFI_L2VPN, SAFI_EVPN, &reason);
1329}
1330
65efcfce
LB
1331/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1332 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1333 * multipath is enabled
65efcfce 1334 * This version is compatible with */
18ee8310
DS
1335int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1336 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1337 afi_t afi, safi_t safi,
1338 enum bgp_path_selection_reason *reason)
d62a17ae 1339{
1340 int paths_eq;
1341 int ret;
18ee8310 1342 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1343 afi, safi, reason);
d62a17ae 1344
1345 if (paths_eq)
1346 ret = 0;
1347 else {
1348 if (ret == 1)
1349 ret = -1;
1350 else
1351 ret = 1;
1352 }
1353 return ret;
65efcfce
LB
1354}
1355
5a1ae2c2
DS
1356static enum filter_type bgp_input_filter(struct peer *peer,
1357 const struct prefix *p,
d62a17ae 1358 struct attr *attr, afi_t afi,
1359 safi_t safi)
718e3744 1360{
d62a17ae 1361 struct bgp_filter *filter;
6401252f 1362 enum filter_type ret = FILTER_PERMIT;
718e3744 1363
d62a17ae 1364 filter = &peer->filter[afi][safi];
718e3744 1365
d62a17ae 1366#define FILTER_EXIST_WARN(F, f, filter) \
1367 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1368 zlog_debug("%s: Could not find configured input %s-list %s!", \
1369 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1370
1371 if (DISTRIBUTE_IN_NAME(filter)) {
1372 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1373
6401252f
QY
1374 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1375 == FILTER_DENY) {
1376 ret = FILTER_DENY;
1377 goto done;
1378 }
d62a17ae 1379 }
1380
1381 if (PREFIX_LIST_IN_NAME(filter)) {
1382 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1383
6401252f
QY
1384 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1385 == PREFIX_DENY) {
1386 ret = FILTER_DENY;
1387 goto done;
1388 }
d62a17ae 1389 }
1390
1391 if (FILTER_LIST_IN_NAME(filter)) {
1392 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1393
1394 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1395 == AS_FILTER_DENY) {
1396 ret = FILTER_DENY;
1397 goto done;
1398 }
d62a17ae 1399 }
1400
6401252f 1401done:
c7bb4f00 1402 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1403 char pfxprint[PREFIX2STR_BUFFER];
1404
1405 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1406 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1407 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1408 }
1409
1410 return ret;
650f76c2 1411#undef FILTER_EXIST_WARN
718e3744 1412}
1413
b8685f9b
DS
1414static enum filter_type bgp_output_filter(struct peer *peer,
1415 const struct prefix *p,
d62a17ae 1416 struct attr *attr, afi_t afi,
1417 safi_t safi)
718e3744 1418{
d62a17ae 1419 struct bgp_filter *filter;
6401252f 1420 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1421
1422 filter = &peer->filter[afi][safi];
1423
1424#define FILTER_EXIST_WARN(F, f, filter) \
1425 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1426 zlog_debug("%s: Could not find configured output %s-list %s!", \
1427 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1428
d62a17ae 1429 if (DISTRIBUTE_OUT_NAME(filter)) {
1430 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1431
6401252f
QY
1432 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1433 == FILTER_DENY) {
1434 ret = FILTER_DENY;
1435 goto done;
1436 }
d62a17ae 1437 }
1438
1439 if (PREFIX_LIST_OUT_NAME(filter)) {
1440 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1441
d62a17ae 1442 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1443 == PREFIX_DENY) {
1444 ret = FILTER_DENY;
1445 goto done;
1446 }
d62a17ae 1447 }
718e3744 1448
d62a17ae 1449 if (FILTER_LIST_OUT_NAME(filter)) {
1450 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1451
d62a17ae 1452 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1453 == AS_FILTER_DENY) {
1454 ret = FILTER_DENY;
1455 goto done;
1456 }
1457 }
1458
c7bb4f00 1459 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1460 char pfxprint[PREFIX2STR_BUFFER];
1461
1462 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1463 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1464 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1465 }
718e3744 1466
6401252f
QY
1467done:
1468 return ret;
650f76c2 1469#undef FILTER_EXIST_WARN
718e3744 1470}
1471
1472/* If community attribute includes no_export then return 1. */
3dc339cd 1473static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1474{
1475 if (attr->community) {
1476 /* NO_ADVERTISE check. */
1477 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1478 return true;
d62a17ae 1479
1480 /* NO_EXPORT check. */
1481 if (peer->sort == BGP_PEER_EBGP
1482 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1483 return true;
d62a17ae 1484
1485 /* NO_EXPORT_SUBCONFED check. */
1486 if (peer->sort == BGP_PEER_EBGP
1487 || peer->sort == BGP_PEER_CONFED)
1488 if (community_include(attr->community,
1489 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1490 return true;
d62a17ae 1491 }
3dc339cd 1492 return false;
718e3744 1493}
1494
1495/* Route reflection loop check. */
3dc339cd 1496static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1497{
d62a17ae 1498 struct in_addr cluster_id;
779fee93 1499 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1500
779fee93 1501 if (cluster) {
d62a17ae 1502 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1503 cluster_id = peer->bgp->cluster_id;
1504 else
1505 cluster_id = peer->bgp->router_id;
1506
779fee93 1507 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1508 return true;
d62a17ae 1509 }
3dc339cd 1510 return false;
718e3744 1511}
6b0655a2 1512
5a1ae2c2 1513static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1514 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1515 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1516 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1517{
d62a17ae 1518 struct bgp_filter *filter;
82b692c0
LK
1519 struct bgp_path_info rmap_path = { 0 };
1520 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1521 route_map_result_t ret;
1522 struct route_map *rmap = NULL;
718e3744 1523
d62a17ae 1524 filter = &peer->filter[afi][safi];
718e3744 1525
d62a17ae 1526 /* Apply default weight value. */
1527 if (peer->weight[afi][safi])
1528 attr->weight = peer->weight[afi][safi];
718e3744 1529
d62a17ae 1530 if (rmap_name) {
1531 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1532
d62a17ae 1533 if (rmap == NULL)
1534 return RMAP_DENY;
1535 } else {
1536 if (ROUTE_MAP_IN_NAME(filter)) {
1537 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1538
d62a17ae 1539 if (rmap == NULL)
1540 return RMAP_DENY;
1541 }
1542 }
0b16f239 1543
d62a17ae 1544 /* Route map apply. */
1545 if (rmap) {
40381db7 1546 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1547 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1548 rmap_path.peer = peer;
1549 rmap_path.attr = attr;
82b692c0 1550 rmap_path.extra = &extra;
9bcb3eef 1551 rmap_path.net = dest;
196c6b09 1552
82b692c0
LK
1553 extra.num_labels = num_labels;
1554 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1555 memcpy(extra.label, label,
1556 num_labels * sizeof(mpls_label_t));
718e3744 1557
d62a17ae 1558 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1559
d62a17ae 1560 /* Apply BGP route map to the attribute. */
1782514f 1561 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1562
d62a17ae 1563 peer->rmap_type = 0;
0b16f239 1564
1f2263be 1565 if (ret == RMAP_DENYMATCH)
d62a17ae 1566 return RMAP_DENY;
0b16f239 1567 }
d62a17ae 1568 return RMAP_PERMIT;
0b16f239
DS
1569}
1570
5f040085 1571static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1572 struct attr *attr, afi_t afi, safi_t safi,
1573 const char *rmap_name)
0b16f239 1574{
40381db7 1575 struct bgp_path_info rmap_path;
d62a17ae 1576 route_map_result_t ret;
1577 struct route_map *rmap = NULL;
d7c0a89a 1578 uint8_t rmap_type;
0b16f239 1579
b787157a
DS
1580 /*
1581 * So if we get to this point and have no rmap_name
1582 * we want to just show the output as it currently
1583 * exists.
1584 */
1585 if (!rmap_name)
1586 return RMAP_PERMIT;
0b16f239 1587
d62a17ae 1588 /* Apply default weight value. */
1589 if (peer->weight[afi][safi])
1590 attr->weight = peer->weight[afi][safi];
0b16f239 1591
b787157a 1592 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1593
b787157a
DS
1594 /*
1595 * If we have a route map name and we do not find
1596 * the routemap that means we have an implicit
1597 * deny.
1598 */
1599 if (rmap == NULL)
1600 return RMAP_DENY;
0b16f239 1601
40381db7 1602 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1603 /* Route map apply. */
b787157a 1604 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1605 rmap_path.peer = peer;
1606 rmap_path.attr = attr;
0b16f239 1607
0f672529 1608 rmap_type = peer->rmap_type;
b787157a 1609 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1610
b787157a 1611 /* Apply BGP route map to the attribute. */
1782514f 1612 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1613
0f672529 1614 peer->rmap_type = rmap_type;
b787157a
DS
1615
1616 if (ret == RMAP_DENYMATCH)
1617 /*
1618 * caller has multiple error paths with bgp_attr_flush()
1619 */
1620 return RMAP_DENY;
ac41b2a2 1621
d62a17ae 1622 return RMAP_PERMIT;
718e3744 1623}
6b0655a2 1624
5000f21c 1625/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1626static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1627 struct peer *peer, struct attr *attr)
1628{
1629 if (peer->sort == BGP_PEER_EBGP
1630 && (peer_af_flag_check(peer, afi, safi,
1631 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1632 || peer_af_flag_check(peer, afi, safi,
1633 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1634 || peer_af_flag_check(peer, afi, safi,
1635 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1636 || peer_af_flag_check(peer, afi, safi,
1637 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1638 // Take action on the entire aspath
1639 if (peer_af_flag_check(peer, afi, safi,
1640 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1641 || peer_af_flag_check(peer, afi, safi,
1642 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1643 if (peer_af_flag_check(
1644 peer, afi, safi,
1645 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1646 attr->aspath = aspath_replace_private_asns(
bf26b80e 1647 attr->aspath, bgp->as, peer->as);
d62a17ae 1648
1649 // The entire aspath consists of private ASNs so create
1650 // an empty aspath
1651 else if (aspath_private_as_check(attr->aspath))
1652 attr->aspath = aspath_empty_get();
1653
1654 // There are some public and some private ASNs, remove
1655 // the private ASNs
1656 else
1657 attr->aspath = aspath_remove_private_asns(
bf26b80e 1658 attr->aspath, peer->as);
d62a17ae 1659 }
1660
1661 // 'all' was not specified so the entire aspath must be private
1662 // ASNs
1663 // for us to do anything
1664 else if (aspath_private_as_check(attr->aspath)) {
1665 if (peer_af_flag_check(
1666 peer, afi, safi,
1667 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1668 attr->aspath = aspath_replace_private_asns(
bf26b80e 1669 attr->aspath, bgp->as, peer->as);
d62a17ae 1670 else
1671 attr->aspath = aspath_empty_get();
1672 }
1673 }
5000f21c
DS
1674}
1675
c7122e14 1676/* If this is an EBGP peer with as-override */
d62a17ae 1677static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1678 struct peer *peer, struct attr *attr)
1679{
1680 if (peer->sort == BGP_PEER_EBGP
1681 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1682 if (aspath_single_asn_check(attr->aspath, peer->as))
1683 attr->aspath = aspath_replace_specific_asn(
1684 attr->aspath, peer->as, bgp->as);
1685 }
1686}
1687
7f323236
DW
1688void bgp_attr_add_gshut_community(struct attr *attr)
1689{
1690 struct community *old;
1691 struct community *new;
1692 struct community *merge;
1693 struct community *gshut;
1694
1695 old = attr->community;
1696 gshut = community_str2com("graceful-shutdown");
1697
990f4f91 1698 assert(gshut);
1699
7f323236
DW
1700 if (old) {
1701 merge = community_merge(community_dup(old), gshut);
1702
a4d82a8a 1703 if (old->refcnt == 0)
3c1f53de 1704 community_free(&old);
7f323236
DW
1705
1706 new = community_uniq_sort(merge);
3c1f53de 1707 community_free(&merge);
7f323236
DW
1708 } else {
1709 new = community_dup(gshut);
1710 }
1711
3c1f53de 1712 community_free(&gshut);
7f323236
DW
1713 attr->community = new;
1714 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1715
1716 /* When we add the graceful-shutdown community we must also
1717 * lower the local-preference */
1718 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1719 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1720}
1721
1722
e73c112e
MK
1723/* Notify BGP Conditional advertisement scanner process. */
1724void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1725{
1726 struct peer *temp_peer;
1727 struct peer *peer = SUBGRP_PEER(subgrp);
1728 struct listnode *temp_node, *temp_nnode = NULL;
1729 afi_t afi = SUBGRP_AFI(subgrp);
1730 safi_t safi = SUBGRP_SAFI(subgrp);
1731 struct bgp *bgp = SUBGRP_INST(subgrp);
1732 struct bgp_filter *filter = &peer->filter[afi][safi];
1733
1734 if (!ADVERTISE_MAP_NAME(filter))
1735 return;
1736
1737 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1738 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1739 continue;
1740
1741 if (peer != temp_peer)
1742 continue;
1743
1744 temp_peer->advmap_table_change = true;
1745 break;
1746 }
1747}
1748
1749
f2ee6d5c 1750void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1751{
960035b2 1752 if (family == AF_INET) {
975a328e
DA
1753 attr->nexthop.s_addr = INADDR_ANY;
1754 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1755 }
d62a17ae 1756 if (family == AF_INET6)
1757 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1758 if (family == AF_EVPN)
1759 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1760}
1761
9bcb3eef 1762bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1763 struct update_subgroup *subgrp,
7f7940e6
MK
1764 const struct prefix *p, struct attr *attr,
1765 bool skip_rmap_check)
d62a17ae 1766{
1767 struct bgp_filter *filter;
1768 struct peer *from;
1769 struct peer *peer;
1770 struct peer *onlypeer;
1771 struct bgp *bgp;
40381db7 1772 struct attr *piattr;
b68885f9 1773 route_map_result_t ret;
d62a17ae 1774 int transparent;
1775 int reflect;
1776 afi_t afi;
1777 safi_t safi;
1778 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1779 bool nh_reset = false;
1780 uint64_t cum_bw;
d62a17ae 1781
1782 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1783 return false;
d62a17ae 1784
1785 afi = SUBGRP_AFI(subgrp);
1786 safi = SUBGRP_SAFI(subgrp);
1787 peer = SUBGRP_PEER(subgrp);
1788 onlypeer = NULL;
1789 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1790 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1791
40381db7 1792 from = pi->peer;
d62a17ae 1793 filter = &peer->filter[afi][safi];
1794 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1795 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1796 : pi->attr;
3f9c7369 1797
49e5a4a0 1798#ifdef ENABLE_BGP_VNC
d62a17ae 1799 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1800 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1801 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1802
1803 /*
1804 * direct and direct_ext type routes originate internally even
1805 * though they can have peer pointers that reference other
1806 * systems
1807 */
8228a9a7
DS
1808 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1809 __func__, p);
d62a17ae 1810 samepeer_safe = 1;
1811 }
65efcfce
LB
1812#endif
1813
ddb5b488
PZ
1814 if (((afi == AFI_IP) || (afi == AFI_IP6))
1815 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1816 && (pi->type == ZEBRA_ROUTE_BGP)
1817 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1818
1819 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1820
1821 samepeer_safe = 1;
1822 }
1823
d62a17ae 1824 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1825 * pi is valid */
1826 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1827 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1828 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1829 return false;
d62a17ae 1830 }
adbac85e 1831
d62a17ae 1832 /* If this is not the bestpath then check to see if there is an enabled
1833 * addpath
1834 * feature that requires us to advertise it */
40381db7 1835 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1836 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1837 return false;
d62a17ae 1838 }
1839 }
06370dac 1840
d62a17ae 1841 /* Aggregate-address suppress check. */
4056a5f6
RZ
1842 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1843 return false;
3f9c7369 1844
13b7e7f0
DS
1845 /*
1846 * If we are doing VRF 2 VRF leaking via the import
1847 * statement, we want to prevent the route going
1848 * off box as that the RT and RD created are localy
1849 * significant and globaly useless.
1850 */
40381db7
DS
1851 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1852 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1853 return false;
13b7e7f0 1854
d62a17ae 1855 /* If it's labeled safi, make sure the route has a valid label. */
1856 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1857 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1858 if (!bgp_is_valid_label(&label)) {
1859 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1860 zlog_debug("u%" PRIu64 ":s%" PRIu64
1861 " %pFX is filtered - no label (%p)",
d62a17ae 1862 subgrp->update_group->id, subgrp->id,
8228a9a7 1863 p, &label);
3dc339cd 1864 return false;
d62a17ae 1865 }
1866 }
cd1964ff 1867
d62a17ae 1868 /* Do not send back route to sender. */
1869 if (onlypeer && from == onlypeer) {
3dc339cd 1870 return false;
d62a17ae 1871 }
3f9c7369 1872
d62a17ae 1873 /* Do not send the default route in the BGP table if the neighbor is
1874 * configured for default-originate */
1875 if (CHECK_FLAG(peer->af_flags[afi][safi],
1876 PEER_FLAG_DEFAULT_ORIGINATE)) {
1877 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1878 return false;
d62a17ae 1879 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1880 return false;
d62a17ae 1881 }
4125bb67 1882
d62a17ae 1883 /* Transparency check. */
1884 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1885 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1886 transparent = 1;
1887 else
1888 transparent = 0;
1889
1890 /* If community is not disabled check the no-export and local. */
40381db7 1891 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1892 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1893 zlog_debug("%s: community filter check fail for %pFX",
1894 __func__, p);
3dc339cd 1895 return false;
d62a17ae 1896 }
3f9c7369 1897
d62a17ae 1898 /* If the attribute has originator-id and it is same as remote
1899 peer's id. */
40381db7
DS
1900 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1901 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1902 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1903 zlog_debug(
8228a9a7
DS
1904 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1905 onlypeer->host, p);
3dc339cd 1906 return false;
d62a17ae 1907 }
3f9c7369 1908
d62a17ae 1909 /* ORF prefix-list filter check */
1910 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1911 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1912 || CHECK_FLAG(peer->af_cap[afi][safi],
1913 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1914 if (peer->orf_plist[afi][safi]) {
1915 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1916 == PREFIX_DENY) {
1917 if (bgp_debug_update(NULL, p,
1918 subgrp->update_group, 0))
1919 zlog_debug(
8228a9a7
DS
1920 "%s [Update:SEND] %pFX is filtered via ORF",
1921 peer->host, p);
3dc339cd 1922 return false;
d62a17ae 1923 }
1924 }
1925
1926 /* Output filter check. */
40381db7 1927 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1928 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1929 zlog_debug("%s [Update:SEND] %pFX is filtered",
1930 peer->host, p);
3dc339cd 1931 return false;
d62a17ae 1932 }
3f9c7369 1933
d62a17ae 1934 /* AS path loop check. */
2b31007c
RZ
1935 if (onlypeer && onlypeer->as_path_loop_detection
1936 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1937 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1938 zlog_debug(
3efd0893 1939 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1940 onlypeer->host, onlypeer->as);
3dc339cd 1941 return false;
d62a17ae 1942 }
3f9c7369 1943
d62a17ae 1944 /* If we're a CONFED we need to loop check the CONFED ID too */
1945 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1946 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1947 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1948 zlog_debug(
3efd0893 1949 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1950 peer->host, bgp->confed_id);
3dc339cd 1951 return false;
d62a17ae 1952 }
3f9c7369 1953 }
3f9c7369 1954
d62a17ae 1955 /* Route-Reflect check. */
1956 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1957 reflect = 1;
1958 else
1959 reflect = 0;
1960
1961 /* IBGP reflection check. */
1962 if (reflect && !samepeer_safe) {
1963 /* A route from a Client peer. */
1964 if (CHECK_FLAG(from->af_flags[afi][safi],
1965 PEER_FLAG_REFLECTOR_CLIENT)) {
1966 /* Reflect to all the Non-Client peers and also to the
1967 Client peers other than the originator. Originator
1968 check
1969 is already done. So there is noting to do. */
1970 /* no bgp client-to-client reflection check. */
892fedb6
DA
1971 if (CHECK_FLAG(bgp->flags,
1972 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1973 if (CHECK_FLAG(peer->af_flags[afi][safi],
1974 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1975 return false;
d62a17ae 1976 } else {
1977 /* A route from a Non-client peer. Reflect to all other
1978 clients. */
1979 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1980 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1981 return false;
d62a17ae 1982 }
1983 }
3f9c7369 1984
d62a17ae 1985 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1986 *attr = *piattr;
d62a17ae 1987
1988 /* If local-preference is not set. */
1989 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1990 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1991 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1992 attr->local_pref = bgp->default_local_pref;
3f9c7369 1993 }
3f9c7369 1994
d62a17ae 1995 /* If originator-id is not set and the route is to be reflected,
1996 set the originator id */
1997 if (reflect
1998 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
1999 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2000 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2001 }
3f9c7369 2002
d62a17ae 2003 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2004 */
2005 if (peer->sort == BGP_PEER_EBGP
2006 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2007 if (from != bgp->peer_self && !transparent
2008 && !CHECK_FLAG(peer->af_flags[afi][safi],
2009 PEER_FLAG_MED_UNCHANGED))
2010 attr->flag &=
2011 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2012 }
3f9c7369 2013
d62a17ae 2014 /* Since the nexthop attribute can vary per peer, it is not explicitly
2015 * set
2016 * in announce check, only certain flags and length (or number of
2017 * nexthops
2018 * -- for IPv6/MP_REACH) are set here in order to guide the update
2019 * formation
2020 * code in setting the nexthop(s) on a per peer basis in
2021 * reformat_peer().
2022 * Typically, the source nexthop in the attribute is preserved but in
2023 * the
2024 * scenarios where we know it will always be overwritten, we reset the
2025 * nexthop to "0" in an attempt to achieve better Update packing. An
2026 * example of this is when a prefix from each of 2 IBGP peers needs to
2027 * be
2028 * announced to an EBGP peer (and they have the same attributes barring
2029 * their nexthop).
2030 */
2031 if (reflect)
2032 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2033
2034#define NEXTHOP_IS_V6 \
2035 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2036 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2037 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2038 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2039
2040 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2041 * if
2042 * the peer (group) is configured to receive link-local nexthop
2043 * unchanged
c728d027
DA
2044 * and it is available in the prefix OR we're not reflecting the route,
2045 * link-local nexthop address is valid and
d62a17ae 2046 * the peer (group) to whom we're going to announce is on a shared
2047 * network
2048 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2049 * By checking if nexthop LL address is valid we are sure that
2050 * we do not announce LL address as `::`.
d62a17ae 2051 */
2052 if (NEXTHOP_IS_V6) {
2053 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2054 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2055 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2056 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2057 || (!reflect
2058 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2059 && peer->shared_network
d62a17ae 2060 && (from == bgp->peer_self
2061 || peer->sort == BGP_PEER_EBGP))) {
2062 attr->mp_nexthop_len =
2063 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2064 }
3f9c7369 2065
d62a17ae 2066 /* Clear off link-local nexthop in source, whenever it is not
2067 * needed to
2068 * ensure more prefixes share the same attribute for
2069 * announcement.
2070 */
2071 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2072 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2073 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2074 }
3f9c7369 2075
d62a17ae 2076 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2077 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2078
2079 /* Route map & unsuppress-map apply. */
7f7940e6 2080 if (!skip_rmap_check
e73c112e 2081 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2082 struct bgp_path_info rmap_path = {0};
2083 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2084 struct attr dummy_attr = {0};
d62a17ae 2085
e34291b8 2086 /* Fill temp path_info */
9bcb3eef
DS
2087 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2088 pi, peer, attr);
16f7ce2b 2089
d62a17ae 2090 /* don't confuse inbound and outbound setting */
2091 RESET_FLAG(attr->rmap_change_flags);
2092
2093 /*
2094 * The route reflector is not allowed to modify the attributes
2095 * of the reflected IBGP routes unless explicitly allowed.
2096 */
2097 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2098 && !CHECK_FLAG(bgp->flags,
2099 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2100 dummy_attr = *attr;
40381db7 2101 rmap_path.attr = &dummy_attr;
d62a17ae 2102 }
3f9c7369 2103
d62a17ae 2104 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2105
4056a5f6 2106 if (bgp_path_suppressed(pi))
d62a17ae 2107 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2108 &rmap_path);
d62a17ae 2109 else
2110 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2111 &rmap_path);
d62a17ae 2112
2113 peer->rmap_type = 0;
2114
2115 if (ret == RMAP_DENYMATCH) {
778048bf 2116 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2117 zlog_debug(
2118 "%s [Update:SEND] %pFX is filtered by route-map",
2119 peer->host, p);
778048bf 2120
d62a17ae 2121 bgp_attr_flush(attr);
3dc339cd 2122 return false;
d62a17ae 2123 }
3f9c7369 2124 }
3f9c7369 2125
9dac9fc8
DA
2126 /* RFC 8212 to prevent route leaks.
2127 * This specification intends to improve this situation by requiring the
2128 * explicit configuration of both BGP Import and Export Policies for any
2129 * External BGP (EBGP) session such as customers, peers, or
2130 * confederation boundaries for all enabled address families. Through
2131 * codification of the aforementioned requirement, operators will
2132 * benefit from consistent behavior across different BGP
2133 * implementations.
2134 */
1d3fdccf 2135 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2136 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2137 return false;
9dac9fc8 2138
fb29348a
DA
2139 /* draft-ietf-idr-deprecate-as-set-confed-set
2140 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2141 * Eventually, This document (if approved) updates RFC 4271
2142 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2143 * and obsoletes RFC 6472.
2144 */
7f972cd8 2145 if (peer->bgp->reject_as_sets)
fb29348a 2146 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2147 return false;
fb29348a 2148
33d022bc
DA
2149 /* Codification of AS 0 Processing */
2150 if (aspath_check_as_zero(attr->aspath))
e2369003 2151 return false;
33d022bc 2152
637e5ba4 2153 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2154 if (peer->sort == BGP_PEER_IBGP
2155 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2156 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2157 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2158 } else {
2159 bgp_attr_add_gshut_community(attr);
2160 }
2161 }
2162
d62a17ae 2163 /* After route-map has been applied, we check to see if the nexthop to
2164 * be carried in the attribute (that is used for the announcement) can
2165 * be cleared off or not. We do this in all cases where we would be
2166 * setting the nexthop to "ourselves". For IPv6, we only need to
2167 * consider
2168 * the global nexthop here; the link-local nexthop would have been
2169 * cleared
2170 * already, and if not, it is required by the update formation code.
2171 * Also see earlier comments in this function.
2172 */
2173 /*
2174 * If route-map has performed some operation on the nexthop or the peer
2175 * configuration says to pass it unchanged, we cannot reset the nexthop
2176 * here, so only attempt to do it if these aren't true. Note that the
2177 * route-map handler itself might have cleared the nexthop, if for
2178 * example,
2179 * it is configured as 'peer-address'.
2180 */
2181 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2182 piattr->rmap_change_flags)
d62a17ae 2183 && !transparent
2184 && !CHECK_FLAG(peer->af_flags[afi][safi],
2185 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2186 /* We can reset the nexthop, if setting (or forcing) it to
2187 * 'self' */
2188 if (CHECK_FLAG(peer->af_flags[afi][safi],
2189 PEER_FLAG_NEXTHOP_SELF)
2190 || CHECK_FLAG(peer->af_flags[afi][safi],
2191 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2192 if (!reflect
2193 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2194 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2195 subgroup_announce_reset_nhop(
2196 (peer_cap_enhe(peer, afi, safi)
2197 ? AF_INET6
2198 : p->family),
2199 attr);
7b651a32 2200 nh_reset = true;
2201 }
d62a17ae 2202 } else if (peer->sort == BGP_PEER_EBGP) {
2203 /* Can also reset the nexthop if announcing to EBGP, but
2204 * only if
2205 * no peer in the subgroup is on a shared subnet.
2206 * Note: 3rd party nexthop currently implemented for
2207 * IPv4 only.
2208 */
737af885
BS
2209 if ((p->family == AF_INET) &&
2210 (!bgp_subgrp_multiaccess_check_v4(
2211 piattr->nexthop,
7b651a32 2212 subgrp, from))) {
d62a17ae 2213 subgroup_announce_reset_nhop(
2214 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2215 ? AF_INET6
2216 : p->family),
737af885 2217 attr);
7b651a32 2218 nh_reset = true;
2219 }
737af885
BS
2220
2221 if ((p->family == AF_INET6) &&
2222 (!bgp_subgrp_multiaccess_check_v6(
2223 piattr->mp_nexthop_global,
7b651a32 2224 subgrp, from))) {
737af885
BS
2225 subgroup_announce_reset_nhop(
2226 (peer_cap_enhe(peer, afi, safi)
2227 ? AF_INET6
2228 : p->family),
2229 attr);
7b651a32 2230 nh_reset = true;
2231 }
737af885
BS
2232
2233
2234
40381db7 2235 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2236 /*
2237 * This flag is used for leaked vpn-vrf routes
2238 */
2239 int family = p->family;
2240
2241 if (peer_cap_enhe(peer, afi, safi))
2242 family = AF_INET6;
2243
2244 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2245 zlog_debug(
1defdda8 2246 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2247 __func__, family2str(family));
2248 subgroup_announce_reset_nhop(family, attr);
7b651a32 2249 nh_reset = true;
d62a17ae 2250 }
63696f1d 2251 }
960035b2 2252
63696f1d 2253 /* If IPv6/MP and nexthop does not have any override and happens
2254 * to
2255 * be a link-local address, reset it so that we don't pass along
2256 * the
2257 * source's link-local IPv6 address to recipients who may not be
2258 * on
2259 * the same interface.
2260 */
2261 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2262 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2263 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2264 nh_reset = true;
2265 }
d62a17ae 2266 }
3f9c7369 2267
7b651a32 2268 /*
2269 * When the next hop is set to ourselves, if all multipaths have
2270 * link-bandwidth announce the cumulative bandwidth as that makes
2271 * the most sense. However, don't modify if the link-bandwidth has
2272 * been explicitly set by user policy.
2273 */
2274 if (nh_reset &&
f7e1c681 2275 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2276 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2277 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2278 attr->ecommunity = ecommunity_replace_linkbw(
2279 bgp->as, attr->ecommunity, cum_bw);
2280
3dc339cd 2281 return true;
3f9c7369
DS
2282}
2283
f009ff26 2284static int bgp_route_select_timer_expire(struct thread *thread)
2285{
2286 struct afi_safi_info *info;
2287 afi_t afi;
2288 safi_t safi;
2289 struct bgp *bgp;
2290
2291 info = THREAD_ARG(thread);
2292 afi = info->afi;
2293 safi = info->safi;
2294 bgp = info->bgp;
2295
2296 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2297 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2298 safi);
f009ff26 2299
2300 bgp->gr_info[afi][safi].t_route_select = NULL;
2301
2302 XFREE(MTYPE_TMP, info);
2303
2304 /* Best path selection */
2305 return bgp_best_path_select_defer(bgp, afi, safi);
2306}
2307
9bcb3eef 2308void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2309 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2310 struct bgp_path_info_pair *result, afi_t afi,
2311 safi_t safi)
2312{
2313 struct bgp_path_info *new_select;
2314 struct bgp_path_info *old_select;
40381db7
DS
2315 struct bgp_path_info *pi;
2316 struct bgp_path_info *pi1;
2317 struct bgp_path_info *pi2;
2318 struct bgp_path_info *nextpi = NULL;
d62a17ae 2319 int paths_eq, do_mpath, debug;
2320 struct list mp_list;
2321 char pfx_buf[PREFIX2STR_BUFFER];
2322 char path_buf[PATH_ADDPATH_STR_BUFFER];
2323
2324 bgp_mp_list_init(&mp_list);
2325 do_mpath =
2326 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2327
9bcb3eef 2328 debug = bgp_debug_bestpath(dest);
d62a17ae 2329
2330 if (debug)
9bcb3eef 2331 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2332
9bcb3eef 2333 dest->reason = bgp_path_selection_none;
d62a17ae 2334 /* bgp deterministic-med */
2335 new_select = NULL;
892fedb6 2336 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2337
1defdda8 2338 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2339 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2340 pi1 = pi1->next)
9bcb3eef 2341 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2342 BGP_PATH_DMED_SELECTED);
d62a17ae 2343
9bcb3eef 2344 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2345 pi1 = pi1->next) {
40381db7 2346 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2347 continue;
40381db7 2348 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2349 continue;
ea8b2282 2350 if (pi1->peer != bgp->peer_self)
feb17238 2351 if (!peer_established(pi1->peer))
d62a17ae 2352 continue;
2353
40381db7
DS
2354 new_select = pi1;
2355 if (pi1->next) {
2356 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2357 if (CHECK_FLAG(pi2->flags,
1defdda8 2358 BGP_PATH_DMED_CHECK))
d62a17ae 2359 continue;
40381db7 2360 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2361 continue;
ea8b2282 2362 if (pi2->peer != bgp->peer_self
d62a17ae 2363 && !CHECK_FLAG(
ea8b2282
DS
2364 pi2->peer->sflags,
2365 PEER_STATUS_NSF_WAIT))
40381db7 2366 if (pi2->peer->status
d62a17ae 2367 != Established)
2368 continue;
2369
121e245d
DS
2370 if (!aspath_cmp_left(pi1->attr->aspath,
2371 pi2->attr->aspath)
2372 && !aspath_cmp_left_confed(
40381db7 2373 pi1->attr->aspath,
121e245d
DS
2374 pi2->attr->aspath))
2375 continue;
d62a17ae 2376
121e245d
DS
2377 if (bgp_path_info_cmp(
2378 bgp, pi2, new_select,
2379 &paths_eq, mpath_cfg, debug,
fdf81fa0 2380 pfx_buf, afi, safi,
9bcb3eef 2381 &dest->reason)) {
121e245d 2382 bgp_path_info_unset_flag(
9bcb3eef 2383 dest, new_select,
121e245d
DS
2384 BGP_PATH_DMED_SELECTED);
2385 new_select = pi2;
d62a17ae 2386 }
121e245d
DS
2387
2388 bgp_path_info_set_flag(
9bcb3eef 2389 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2390 }
2391 }
9bcb3eef 2392 bgp_path_info_set_flag(dest, new_select,
18ee8310 2393 BGP_PATH_DMED_CHECK);
9bcb3eef 2394 bgp_path_info_set_flag(dest, new_select,
18ee8310 2395 BGP_PATH_DMED_SELECTED);
d62a17ae 2396
2397 if (debug) {
18ee8310 2398 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2399 new_select, path_buf, sizeof(path_buf));
8228a9a7
DS
2400 zlog_debug(
2401 "%pBD: %s is the bestpath from AS %u",
2402 dest, path_buf,
2403 aspath_get_first_as(
2404 new_select->attr->aspath));
d62a17ae 2405 }
2406 }
2407 }
96450faf 2408
d62a17ae 2409 /* Check old selected route and new selected route. */
2410 old_select = NULL;
2411 new_select = NULL;
9bcb3eef 2412 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2413 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2414 enum bgp_path_selection_reason reason;
2415
40381db7
DS
2416 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2417 old_select = pi;
d62a17ae 2418
40381db7 2419 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2420 /* reap REMOVED routes, if needs be
2421 * selected route must stay for a while longer though
2422 */
40381db7
DS
2423 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2424 && (pi != old_select))
9bcb3eef 2425 bgp_path_info_reap(dest, pi);
d62a17ae 2426
ddb5b488 2427 if (debug)
40381db7
DS
2428 zlog_debug("%s: pi %p in holddown", __func__,
2429 pi);
ddb5b488 2430
d62a17ae 2431 continue;
2432 }
96450faf 2433
40381db7
DS
2434 if (pi->peer && pi->peer != bgp->peer_self
2435 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2436 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2437
2438 if (debug)
2439 zlog_debug(
40381db7
DS
2440 "%s: pi %p non self peer %s not estab state",
2441 __func__, pi, pi->peer->host);
ddb5b488 2442
d62a17ae 2443 continue;
ddb5b488 2444 }
9fbdd100 2445
892fedb6 2446 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2447 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2448 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2449 if (debug)
40381db7 2450 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2451 continue;
2452 }
9fbdd100 2453
9bcb3eef 2454 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2455
9bcb3eef 2456 reason = dest->reason;
40381db7 2457 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2458 debug, pfx_buf, afi, safi,
2459 &dest->reason)) {
19ea4cec
DS
2460 if (new_select == NULL &&
2461 reason != bgp_path_selection_none)
9bcb3eef 2462 dest->reason = reason;
40381db7 2463 new_select = pi;
d62a17ae 2464 }
2465 }
718e3744 2466
d62a17ae 2467 /* Now that we know which path is the bestpath see if any of the other
2468 * paths
2469 * qualify as multipaths
2470 */
2471 if (debug) {
2472 if (new_select)
7533cad7
QY
2473 bgp_path_info_path_with_addpath_rx_str(
2474 new_select, path_buf, sizeof(path_buf));
d62a17ae 2475 else
772270f3 2476 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2477 zlog_debug(
8228a9a7
DS
2478 "%pBD: After path selection, newbest is %s oldbest was %s",
2479 dest, path_buf,
d62a17ae 2480 old_select ? old_select->peer->host : "NONE");
96450faf 2481 }
9fbdd100 2482
d62a17ae 2483 if (do_mpath && new_select) {
9bcb3eef 2484 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2485 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2486
2487 if (debug)
18ee8310 2488 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2489 pi, path_buf, sizeof(path_buf));
d62a17ae 2490
40381db7 2491 if (pi == new_select) {
d62a17ae 2492 if (debug)
2493 zlog_debug(
8228a9a7
DS
2494 "%pBD: %s is the bestpath, add to the multipath list",
2495 dest, path_buf);
40381db7 2496 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2497 continue;
2498 }
2499
40381db7 2500 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2501 continue;
2502
40381db7
DS
2503 if (pi->peer && pi->peer != bgp->peer_self
2504 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2505 PEER_STATUS_NSF_WAIT))
feb17238 2506 if (!peer_established(pi->peer))
d62a17ae 2507 continue;
2508
40381db7 2509 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2510 if (debug)
2511 zlog_debug(
8228a9a7
DS
2512 "%pBD: %s has the same nexthop as the bestpath, skip it",
2513 dest, path_buf);
d62a17ae 2514 continue;
2515 }
2516
40381db7 2517 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2518 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2519 &dest->reason);
d62a17ae 2520
2521 if (paths_eq) {
2522 if (debug)
2523 zlog_debug(
8228a9a7
DS
2524 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2525 dest, path_buf);
40381db7 2526 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2527 }
2528 }
2529 }
fee0f4c6 2530
9bcb3eef 2531 bgp_path_info_mpath_update(dest, new_select, old_select, &mp_list,
18ee8310
DS
2532 mpath_cfg);
2533 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2534 bgp_mp_list_clear(&mp_list);
96450faf 2535
9bcb3eef 2536 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2537
d62a17ae 2538 result->old = old_select;
2539 result->new = new_select;
96450faf 2540
d62a17ae 2541 return;
fee0f4c6 2542}
2543
3f9c7369
DS
2544/*
2545 * A new route/change in bestpath of an existing route. Evaluate the path
2546 * for advertisement to the subgroup.
2547 */
3dc339cd
DA
2548void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2549 struct bgp_path_info *selected,
9bcb3eef 2550 struct bgp_dest *dest,
3dc339cd 2551 uint32_t addpath_tx_id)
d62a17ae 2552{
b54892e0 2553 const struct prefix *p;
d62a17ae 2554 struct peer *onlypeer;
2555 struct attr attr;
2556 afi_t afi;
2557 safi_t safi;
a77e2f4b
S
2558 struct bgp *bgp;
2559 bool advertise;
adbac85e 2560
9bcb3eef 2561 p = bgp_dest_get_prefix(dest);
d62a17ae 2562 afi = SUBGRP_AFI(subgrp);
2563 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2564 bgp = SUBGRP_INST(subgrp);
d62a17ae 2565 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2566 : NULL);
2567
2dbe669b
DA
2568 if (BGP_DEBUG(update, UPDATE_OUT))
2569 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2570
d62a17ae 2571 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2572 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2573 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2574 return;
d62a17ae 2575
2576 memset(&attr, 0, sizeof(struct attr));
2577 /* It's initialized in bgp_announce_check() */
2578
a77e2f4b
S
2579 /* Announcement to the subgroup. If the route is filtered withdraw it.
2580 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2581 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2582 * route
d62a17ae 2583 */
a77e2f4b
S
2584 advertise = bgp_check_advertise(bgp, dest);
2585
d62a17ae 2586 if (selected) {
7f7940e6 2587 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2588 false)) {
2589 /* Route is selected, if the route is already installed
2590 * in FIB, then it is advertised
2591 */
2592 if (advertise)
2593 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2594 selected);
2595 } else
9bcb3eef 2596 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2597 addpath_tx_id);
d62a17ae 2598 }
2599
2600 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2601 else {
9bcb3eef 2602 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2603 }
200df115 2604}
fee0f4c6 2605
3064bf43 2606/*
e1072051 2607 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2608 * This is called at the end of route processing.
3064bf43 2609 */
9bcb3eef 2610void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2611{
40381db7 2612 struct bgp_path_info *pi;
3064bf43 2613
9bcb3eef 2614 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2615 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2616 continue;
40381db7
DS
2617 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2618 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2619 }
3064bf43 2620}
2621
2622/*
2623 * Has the route changed from the RIB's perspective? This is invoked only
2624 * if the route selection returns the same best route as earlier - to
2625 * determine if we need to update zebra or not.
2626 */
9bcb3eef 2627bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2628{
4b7e6066 2629 struct bgp_path_info *mpinfo;
d62a17ae 2630
2bb9eff4
DS
2631 /* If this is multipath, check all selected paths for any nexthop
2632 * change or attribute change. Some attribute changes (e.g., community)
2633 * aren't of relevance to the RIB, but we'll update zebra to ensure
2634 * we handle the case of BGP nexthop change. This is the behavior
2635 * when the best path has an attribute change anyway.
d62a17ae 2636 */
1defdda8 2637 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2638 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2639 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2640 return true;
d62a17ae 2641
2bb9eff4
DS
2642 /*
2643 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2644 */
18ee8310
DS
2645 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2646 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2647 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2648 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2649 return true;
d62a17ae 2650 }
3064bf43 2651
d62a17ae 2652 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2653 return false;
3064bf43 2654}
2655
d62a17ae 2656struct bgp_process_queue {
2657 struct bgp *bgp;
9bcb3eef 2658 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2659#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2660 unsigned int flags;
2661 unsigned int queued;
200df115 2662};
2663
3b0c17e1 2664static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2665 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2666 struct bgp_path_info *new_select,
2667 struct bgp_path_info *old_select)
2668{
9bcb3eef 2669 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2670
2671 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2672 return;
2673
2674 if (advertise_type5_routes(bgp, afi) && new_select
2675 && is_route_injectable_into_evpn(new_select)) {
2676
2677 /* apply the route-map */
2678 if (bgp->adv_cmd_rmap[afi][safi].map) {
2679 route_map_result_t ret;
2680 struct bgp_path_info rmap_path;
2681 struct bgp_path_info_extra rmap_path_extra;
2682 struct attr dummy_attr;
2683
2684 dummy_attr = *new_select->attr;
2685
2686 /* Fill temp path_info */
9bcb3eef 2687 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2688 new_select, new_select->peer,
2689 &dummy_attr);
2690
2691 RESET_FLAG(dummy_attr.rmap_change_flags);
2692
2693 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2694 p, &rmap_path);
3b0c17e1 2695
2696 if (ret == RMAP_DENYMATCH) {
2697 bgp_attr_flush(&dummy_attr);
2698 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2699 safi);
2700 } else
2701 bgp_evpn_advertise_type5_route(
2702 bgp, p, &dummy_attr, afi, safi);
2703 } else {
2704 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2705 afi, safi);
2706 }
2707 } else if (advertise_type5_routes(bgp, afi) && old_select
2708 && is_route_injectable_into_evpn(old_select))
2709 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2710}
2711
3103e8d2
DS
2712/*
2713 * old_select = The old best path
2714 * new_select = the new best path
2715 *
2716 * if (!old_select && new_select)
2717 * We are sending new information on.
2718 *
2719 * if (old_select && new_select) {
2720 * if (new_select != old_select)
2721 * We have a new best path send a change
2722 * else
2723 * We've received a update with new attributes that needs
2724 * to be passed on.
2725 * }
2726 *
2727 * if (old_select && !new_select)
2728 * We have no eligible route that we can announce or the rn
2729 * is being removed.
2730 */
9bcb3eef 2731static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2732 afi_t afi, safi_t safi)
d62a17ae 2733{
4b7e6066
DS
2734 struct bgp_path_info *new_select;
2735 struct bgp_path_info *old_select;
2736 struct bgp_path_info_pair old_and_new;
ddb5b488 2737 int debug = 0;
d62a17ae 2738
892fedb6 2739 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2740 if (dest)
2741 debug = bgp_debug_bestpath(dest);
b54892e0 2742 if (debug)
f4c713ae 2743 zlog_debug(
56ca3b5b 2744 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2745 __func__, dest);
f4c713ae
LB
2746 return;
2747 }
d62a17ae 2748 /* Is it end of initial update? (after startup) */
9bcb3eef 2749 if (!dest) {
d62a17ae 2750 quagga_timestamp(3, bgp->update_delay_zebra_resume_time,
2751 sizeof(bgp->update_delay_zebra_resume_time));
2752
2753 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2754 FOREACH_AFI_SAFI (afi, safi) {
2755 if (bgp_fibupd_safi(safi))
2756 bgp_zebra_announce_table(bgp, afi, safi);
2757 }
d62a17ae 2758 bgp->main_peers_update_hold = 0;
2759
2760 bgp_start_routeadv(bgp);
aac24838 2761 return;
d62a17ae 2762 }
cb1faec9 2763
9bcb3eef 2764 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2765
9bcb3eef 2766 debug = bgp_debug_bestpath(dest);
b54892e0 2767 if (debug)
56ca3b5b 2768 zlog_debug("%s: p=%pBD afi=%s, safi=%s start", __func__, dest,
ddb5b488 2769 afi2str(afi), safi2str(safi));
ddb5b488 2770
f009ff26 2771 /* The best path calculation for the route is deferred if
2772 * BGP_NODE_SELECT_DEFER is set
2773 */
9bcb3eef 2774 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2775 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2776 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2777 return;
2778 }
2779
d62a17ae 2780 /* Best path selection. */
9bcb3eef 2781 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2782 afi, safi);
2783 old_select = old_and_new.old;
2784 new_select = old_and_new.new;
2785
2786 /* Do we need to allocate or free labels?
2787 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2788 * necessary to do this upon changes to best path. Exceptions:
2789 * - label index has changed -> recalculate resulting label
2790 * - path_info sub_type changed -> switch to/from implicit-null
2791 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2792 */
318cac96 2793 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2794 if (new_select) {
2795 if (!old_select
2796 || bgp_label_index_differs(new_select, old_select)
57592a53 2797 || new_select->sub_type != old_select->sub_type
9bcb3eef 2798 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2799 /* Enforced penultimate hop popping:
2800 * implicit-null for local routes, aggregate
2801 * and redistributed routes
2802 */
d62a17ae 2803 if (new_select->sub_type == BGP_ROUTE_STATIC
57592a53
AD
2804 || new_select->sub_type
2805 == BGP_ROUTE_AGGREGATE
2806 || new_select->sub_type
2807 == BGP_ROUTE_REDISTRIBUTE) {
d62a17ae 2808 if (CHECK_FLAG(
9bcb3eef 2809 dest->flags,
992dd67e
PR
2810 BGP_NODE_REGISTERED_FOR_LABEL)
2811 || CHECK_FLAG(
2812 dest->flags,
2813 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2814 bgp_unregister_for_label(dest);
70e98a7f 2815 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2816 &dest->local_label);
2817 bgp_set_valid_label(&dest->local_label);
d62a17ae 2818 } else
9bcb3eef
DS
2819 bgp_register_for_label(dest,
2820 new_select);
d62a17ae 2821 }
9bcb3eef 2822 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2823 BGP_NODE_REGISTERED_FOR_LABEL)
2824 || CHECK_FLAG(dest->flags,
2825 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2826 bgp_unregister_for_label(dest);
318cac96 2827 }
992dd67e
PR
2828 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2829 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2830 bgp_unregister_for_label(dest);
d62a17ae 2831 }
cd1964ff 2832
b54892e0 2833 if (debug)
ddb5b488 2834 zlog_debug(
56ca3b5b 2835 "%s: p=%pBD afi=%s, safi=%s, old_select=%p, new_select=%p",
9bcb3eef 2836 __func__, dest, afi2str(afi), safi2str(safi),
ddb5b488 2837 old_select, new_select);
ddb5b488 2838
d62a17ae 2839 /* If best route remains the same and this is not due to user-initiated
2840 * clear, see exactly what needs to be done.
2841 */
d62a17ae 2842 if (old_select && old_select == new_select
9bcb3eef 2843 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2844 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2845 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2846 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2847#ifdef ENABLE_BGP_VNC
d62a17ae 2848 vnc_import_bgp_add_route(bgp, p, old_select);
2849 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2850#endif
bb744275 2851 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2852 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2853
2854 if (new_select->type == ZEBRA_ROUTE_BGP
2855 && (new_select->sub_type == BGP_ROUTE_NORMAL
2856 || new_select->sub_type
2857 == BGP_ROUTE_IMPORTED))
2858
9bcb3eef 2859 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2860 bgp, afi, safi);
2861 }
d62a17ae 2862 }
d62a17ae 2863
2864 /* If there is a change of interest to peers, reannounce the
2865 * route. */
1defdda8 2866 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2867 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2868 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2869 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2870
2871 /* unicast routes must also be annouced to
2872 * labeled-unicast update-groups */
2873 if (safi == SAFI_UNICAST)
2874 group_announce_route(bgp, afi,
9bcb3eef 2875 SAFI_LABELED_UNICAST, dest,
d62a17ae 2876 new_select);
2877
1defdda8 2878 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2879 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2880 }
fee0f4c6 2881
3b0c17e1 2882 /* advertise/withdraw type-5 routes */
2883 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2884 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2885 bgp_process_evpn_route_injection(
9bcb3eef 2886 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2887
b1875e65 2888 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2889 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2890 bgp_zebra_clear_route_change_flags(dest);
2891 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2892 return;
d62a17ae 2893 }
8ad7271d 2894
d62a17ae 2895 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2896 */
9bcb3eef 2897 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2898
2899 /* bestpath has changed; bump version */
2900 if (old_select || new_select) {
9bcb3eef 2901 bgp_bump_version(dest);
d62a17ae 2902
2903 if (!bgp->t_rmap_def_originate_eval) {
2904 bgp_lock(bgp);
2905 thread_add_timer(
2906 bm->master,
2907 update_group_refresh_default_originate_route_map,
2908 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2909 &bgp->t_rmap_def_originate_eval);
2910 }
2911 }
3f9c7369 2912
d62a17ae 2913 if (old_select)
9bcb3eef 2914 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2915 if (new_select) {
ddb5b488
PZ
2916 if (debug)
2917 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2918 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2919 bgp_path_info_unset_flag(dest, new_select,
2920 BGP_PATH_ATTR_CHANGED);
1defdda8 2921 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2922 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2923 }
338b3424 2924
49e5a4a0 2925#ifdef ENABLE_BGP_VNC
d62a17ae 2926 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2927 if (old_select != new_select) {
2928 if (old_select) {
2929 vnc_import_bgp_exterior_del_route(bgp, p,
2930 old_select);
2931 vnc_import_bgp_del_route(bgp, p, old_select);
2932 }
2933 if (new_select) {
2934 vnc_import_bgp_exterior_add_route(bgp, p,
2935 new_select);
2936 vnc_import_bgp_add_route(bgp, p, new_select);
2937 }
2938 }
2939 }
65efcfce
LB
2940#endif
2941
9bcb3eef 2942 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2943
2944 /* unicast routes must also be annouced to labeled-unicast update-groups
2945 */
2946 if (safi == SAFI_UNICAST)
9bcb3eef 2947 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2948 new_select);
2949
2950 /* FIB update. */
2951 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2952 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2953 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2954 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2955 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2956 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2957
2958 /* if this is an evpn imported type-5 prefix,
2959 * we need to withdraw the route first to clear
2960 * the nh neigh and the RMAC entry.
2961 */
2962 if (old_select &&
2963 is_route_parent_evpn(old_select))
2964 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2965
9bcb3eef 2966 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2967 } else {
d62a17ae 2968 /* Withdraw the route from the kernel. */
2969 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2970 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2971 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2972 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2973
568e10ca 2974 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 2975 }
718e3744 2976 }
3064bf43 2977
9bcb3eef 2978 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 2979 old_select);
5424b7ba 2980
d62a17ae 2981 /* Clear any route change flags. */
9bcb3eef 2982 bgp_zebra_clear_route_change_flags(dest);
3064bf43 2983
18ee8310 2984 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 2985 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 2986 bgp_path_info_reap(dest, old_select);
d62a17ae 2987
9bcb3eef 2988 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2989 return;
718e3744 2990}
2991
f009ff26 2992/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
2993int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
2994{
9bcb3eef 2995 struct bgp_dest *dest;
f009ff26 2996 int cnt = 0;
2997 struct afi_safi_info *thread_info;
f009ff26 2998
56c226e7
DS
2999 if (bgp->gr_info[afi][safi].t_route_select) {
3000 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3001
3002 thread_info = THREAD_ARG(t);
3003 XFREE(MTYPE_TMP, thread_info);
f009ff26 3004 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3005 }
f009ff26 3006
3007 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3008 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3009 get_afi_safi_str(afi, safi, false),
26742171 3010 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3011 }
3012
3013 /* Process the route list */
6338d242
DS
3014 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3015 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3016 dest = bgp_route_next(dest)) {
3017 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3018 continue;
3019
3020 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3021 bgp->gr_info[afi][safi].gr_deferred--;
3022 bgp_process_main_one(bgp, dest, afi, safi);
3023 cnt++;
3024 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3025 bgp_dest_unlock_node(dest);
3026 break;
f009ff26 3027 }
f009ff26 3028 }
3029
9e3b51a7 3030 /* Send EOR message when all routes are processed */
6338d242 3031 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3032 bgp_send_delayed_eor(bgp);
8c48b3b6 3033 /* Send route processing complete message to RIB */
3034 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3035 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3036 return 0;
9e3b51a7 3037 }
f009ff26 3038
3039 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3040
3041 thread_info->afi = afi;
3042 thread_info->safi = safi;
3043 thread_info->bgp = bgp;
3044
3045 /* If there are more routes to be processed, start the
3046 * selection timer
3047 */
3048 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3049 BGP_ROUTE_SELECT_DELAY,
3050 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3051 return 0;
3052}
3053
aac24838 3054static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3055{
aac24838
JB
3056 struct bgp_process_queue *pqnode = data;
3057 struct bgp *bgp = pqnode->bgp;
d62a17ae 3058 struct bgp_table *table;
9bcb3eef 3059 struct bgp_dest *dest;
aac24838
JB
3060
3061 /* eoiu marker */
3062 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3063 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3064 /* should always have dedicated wq call */
3065 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3066 return WQ_SUCCESS;
3067 }
3068
ac021f40 3069 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3070 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3071 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3072 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3073 table = bgp_dest_table(dest);
3074 /* note, new DESTs may be added as part of processing */
3075 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3076
9bcb3eef 3077 bgp_dest_unlock_node(dest);
d62a17ae 3078 bgp_table_unlock(table);
3079 }
aac24838
JB
3080
3081 return WQ_SUCCESS;
3082}
3083
3084static void bgp_processq_del(struct work_queue *wq, void *data)
3085{
3086 struct bgp_process_queue *pqnode = data;
3087
3088 bgp_unlock(pqnode->bgp);
3089
3090 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3091}
3092
b6c386bb 3093void bgp_process_queue_init(struct bgp *bgp)
200df115 3094{
b6c386bb
DS
3095 if (!bgp->process_queue) {
3096 char name[BUFSIZ];
3097
3098 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3099 bgp->process_queue = work_queue_new(bm->master, name);
3100 }
3101
3102 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3103 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3104 bgp->process_queue->spec.max_retries = 0;
3105 bgp->process_queue->spec.hold = 50;
d62a17ae 3106 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3107 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3108}
3109
cfe8d15a 3110static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3111{
3112 struct bgp_process_queue *pqnode;
3113
a4d82a8a
PZ
3114 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3115 sizeof(struct bgp_process_queue));
aac24838
JB
3116
3117 /* unlocked in bgp_processq_del */
3118 pqnode->bgp = bgp_lock(bgp);
3119 STAILQ_INIT(&pqnode->pqueue);
3120
aac24838
JB
3121 return pqnode;
3122}
3123
9bcb3eef 3124void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3125{
aac24838 3126#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3127 struct work_queue *wq = bgp->process_queue;
d62a17ae 3128 struct bgp_process_queue *pqnode;
cfe8d15a 3129 int pqnode_reuse = 0;
495f0b13 3130
d62a17ae 3131 /* already scheduled for processing? */
9bcb3eef 3132 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3133 return;
2e02b9b2 3134
f009ff26 3135 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3136 * the workqueue
3137 */
9bcb3eef 3138 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3139 if (BGP_DEBUG(update, UPDATE_OUT))
3140 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3141 dest);
f009ff26 3142 return;
3143 }
3144
46aeabed
LS
3145 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3146 if (BGP_DEBUG(update, UPDATE_OUT))
3147 zlog_debug(
3148 "Soft reconfigure table in progress for route %p",
3149 dest);
3150 return;
3151 }
3152
aac24838 3153 if (wq == NULL)
d62a17ae 3154 return;
3155
aac24838 3156 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3157 limit only if is from the same BGP view and it's not an EOIU marker
3158 */
aac24838
JB
3159 if (work_queue_item_count(wq)) {
3160 struct work_queue_item *item = work_queue_last_item(wq);
3161 pqnode = item->data;
228da428 3162
a4d82a8a
PZ
3163 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3164 || pqnode->bgp != bgp
3165 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3166 pqnode = bgp_processq_alloc(bgp);
3167 else
3168 pqnode_reuse = 1;
aac24838 3169 } else
cfe8d15a 3170 pqnode = bgp_processq_alloc(bgp);
aac24838 3171 /* all unlocked in bgp_process_wq */
9bcb3eef 3172 bgp_table_lock(bgp_dest_table(dest));
aac24838 3173
9bcb3eef
DS
3174 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3175 bgp_dest_lock_node(dest);
aac24838 3176
60466a63 3177 /* can't be enqueued twice */
9bcb3eef
DS
3178 assert(STAILQ_NEXT(dest, pq) == NULL);
3179 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3180 pqnode->queued++;
3181
cfe8d15a
LB
3182 if (!pqnode_reuse)
3183 work_queue_add(wq, pqnode);
3184
d62a17ae 3185 return;
fee0f4c6 3186}
0a486e5f 3187
d62a17ae 3188void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3189{
d62a17ae 3190 struct bgp_process_queue *pqnode;
cb1faec9 3191
b6c386bb 3192 if (bgp->process_queue == NULL)
d62a17ae 3193 return;
2e02b9b2 3194
cfe8d15a 3195 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3196
aac24838 3197 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3198 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3199}
3200
d62a17ae 3201static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3202{
d62a17ae 3203 struct peer *peer;
0a486e5f 3204
d62a17ae 3205 peer = THREAD_ARG(thread);
3206 peer->t_pmax_restart = NULL;
0a486e5f 3207
d62a17ae 3208 if (bgp_debug_neighbor_events(peer))
3209 zlog_debug(
3210 "%s Maximum-prefix restart timer expired, restore peering",
3211 peer->host);
0a486e5f 3212
a9bafa95 3213 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3214 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3215
d62a17ae 3216 return 0;
0a486e5f 3217}
3218
9cbd06e0
DA
3219static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3220 safi_t safi)
3221{
3222 uint32_t count = 0;
f41b0459 3223 bool filtered = false;
9cbd06e0
DA
3224 struct bgp_dest *dest;
3225 struct bgp_adj_in *ain;
40bb2ccf 3226 struct attr attr = {};
9cbd06e0
DA
3227 struct bgp_table *table = peer->bgp->rib[afi][safi];
3228
3229 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3230 for (ain = dest->adj_in; ain; ain = ain->next) {
3231 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3232
3233 attr = *ain->attr;
9cbd06e0
DA
3234
3235 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3236 == FILTER_DENY)
f41b0459
DA
3237 filtered = true;
3238
3239 if (bgp_input_modifier(
3240 peer, rn_p, &attr, afi, safi,
3241 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3242 NULL, 0, NULL)
3243 == RMAP_DENY)
3244 filtered = true;
3245
3246 if (filtered)
9cbd06e0 3247 count++;
f41b0459
DA
3248
3249 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3250 }
3251 }
3252
3253 return count;
3254}
3255
3dc339cd
DA
3256bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3257 int always)
718e3744 3258{
d62a17ae 3259 iana_afi_t pkt_afi;
5c525538 3260 iana_safi_t pkt_safi;
9cbd06e0
DA
3261 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3262 PEER_FLAG_MAX_PREFIX_FORCE))
3263 ? bgp_filtered_routes_count(peer, afi, safi)
3264 + peer->pcount[afi][safi]
3265 : peer->pcount[afi][safi];
9cabb64b 3266
d62a17ae 3267 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3268 return false;
e0701b79 3269
9cbd06e0 3270 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3271 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3272 PEER_STATUS_PREFIX_LIMIT)
3273 && !always)
3dc339cd 3274 return false;
e0701b79 3275
d62a17ae 3276 zlog_info(
6cde4b45 3277 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3278 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3279 peer->pmax[afi][safi]);
d62a17ae 3280 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3281
3282 if (CHECK_FLAG(peer->af_flags[afi][safi],
3283 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3284 return false;
d62a17ae 3285
3286 /* Convert AFI, SAFI to values for packet. */
3287 pkt_afi = afi_int2iana(afi);
3288 pkt_safi = safi_int2iana(safi);
3289 {
d7c0a89a 3290 uint8_t ndata[7];
d62a17ae 3291
3292 ndata[0] = (pkt_afi >> 8);
3293 ndata[1] = pkt_afi;
3294 ndata[2] = pkt_safi;
3295 ndata[3] = (peer->pmax[afi][safi] >> 24);
3296 ndata[4] = (peer->pmax[afi][safi] >> 16);
3297 ndata[5] = (peer->pmax[afi][safi] >> 8);
3298 ndata[6] = (peer->pmax[afi][safi]);
3299
3300 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3301 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3302 BGP_NOTIFY_CEASE_MAX_PREFIX,
3303 ndata, 7);
3304 }
3305
3306 /* Dynamic peers will just close their connection. */
3307 if (peer_dynamic_neighbor(peer))
3dc339cd 3308 return true;
d62a17ae 3309
3310 /* restart timer start */
3311 if (peer->pmax_restart[afi][safi]) {
3312 peer->v_pmax_restart =
3313 peer->pmax_restart[afi][safi] * 60;
3314
3315 if (bgp_debug_neighbor_events(peer))
3316 zlog_debug(
3317 "%s Maximum-prefix restart timer started for %d secs",
3318 peer->host, peer->v_pmax_restart);
3319
3320 BGP_TIMER_ON(peer->t_pmax_restart,
3321 bgp_maximum_prefix_restart_timer,
3322 peer->v_pmax_restart);
3323 }
3324
3dc339cd 3325 return true;
d62a17ae 3326 } else
3327 UNSET_FLAG(peer->af_sflags[afi][safi],
3328 PEER_STATUS_PREFIX_LIMIT);
3329
b1823b69
DS
3330 if (pcount
3331 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3332 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3333 PEER_STATUS_PREFIX_THRESHOLD)
3334 && !always)
3dc339cd 3335 return false;
d62a17ae 3336
3337 zlog_info(
6cde4b45 3338 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3339 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3340 peer->pmax[afi][safi]);
d62a17ae 3341 SET_FLAG(peer->af_sflags[afi][safi],
3342 PEER_STATUS_PREFIX_THRESHOLD);
3343 } else
3344 UNSET_FLAG(peer->af_sflags[afi][safi],
3345 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3346 return false;
718e3744 3347}
3348
b40d939b 3349/* Unconditionally remove the route from the RIB, without taking
3350 * damping into consideration (eg, because the session went down)
3351 */
9bcb3eef 3352void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3353 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3354{
f009ff26 3355
3356 struct bgp *bgp = NULL;
3357 bool delete_route = false;
3358
9bcb3eef
DS
3359 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3360 safi);
d62a17ae 3361
f009ff26 3362 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3363 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3364
f009ff26 3365 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3366 * flag
3367 */
3368 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3369 delete_route = true;
9bcb3eef 3370 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3371 delete_route = true;
f009ff26 3372 if (delete_route) {
9bcb3eef
DS
3373 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3374 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3375 bgp = pi->peer->bgp;
26742171 3376 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3377 }
3378 }
3379 }
4a11bf2c 3380
9bcb3eef
DS
3381 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3382 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3383}
3384
9bcb3eef 3385static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3386 struct peer *peer, afi_t afi, safi_t safi,
3387 struct prefix_rd *prd)
3388{
9bcb3eef 3389 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3390
d62a17ae 3391 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3392 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3393 */
40ec3340
DS
3394 if (peer->sort == BGP_PEER_EBGP) {
3395 if (get_active_bdc_from_pi(pi, afi, safi)) {
3396 if (bgp_damp_withdraw(pi, dest, afi, safi, 0)
3397 == BGP_DAMP_SUPPRESSED) {
3398 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3399 safi);
3400 return;
3401 }
d62a17ae 3402 }
40ec3340 3403 }
d62a17ae 3404
49e5a4a0 3405#ifdef ENABLE_BGP_VNC
d62a17ae 3406 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3407 struct bgp_dest *pdest = NULL;
d62a17ae 3408 struct bgp_table *table = NULL;
3409
9bcb3eef
DS
3410 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3411 (struct prefix *)prd);
3412 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3413 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3414
3415 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3416 peer->bgp, prd, table, p, pi);
d62a17ae 3417 }
9bcb3eef 3418 bgp_dest_unlock_node(pdest);
d62a17ae 3419 }
3420 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3421 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3422
b54892e0
DS
3423 vnc_import_bgp_del_route(peer->bgp, p, pi);
3424 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3425 }
65efcfce 3426 }
d62a17ae 3427#endif
128ea8ab 3428
d62a17ae 3429 /* If this is an EVPN route, process for un-import. */
3430 if (safi == SAFI_EVPN)
b54892e0 3431 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3432
9bcb3eef 3433 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3434}
3435
4b7e6066
DS
3436struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3437 struct peer *peer, struct attr *attr,
9bcb3eef 3438 struct bgp_dest *dest)
fb018d25 3439{
4b7e6066 3440 struct bgp_path_info *new;
fb018d25 3441
d62a17ae 3442 /* Make new BGP info. */
4b7e6066 3443 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3444 new->type = type;
3445 new->instance = instance;
3446 new->sub_type = sub_type;
3447 new->peer = peer;
3448 new->attr = attr;
3449 new->uptime = bgp_clock();
9bcb3eef 3450 new->net = dest;
d62a17ae 3451 return new;
fb018d25
DS
3452}
3453
d62a17ae 3454static void overlay_index_update(struct attr *attr,
d62a17ae 3455 union gw_addr *gw_ip)
684a7227 3456{
d62a17ae 3457 if (!attr)
3458 return;
d62a17ae 3459 if (gw_ip == NULL) {
6c924775
DS
3460 struct bgp_route_evpn eo;
3461
3462 memset(&eo, 0, sizeof(eo));
3463 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3464 } else {
6c924775
DS
3465 struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
3466
3467 bgp_attr_set_evpn_overlay(attr, &eo);
d62a17ae 3468 }
684a7227
PG
3469}
3470
40381db7 3471static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3472 union gw_addr *gw_ip)
3473{
6c924775
DS
3474 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3475 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3476 union {
0a50c248 3477 esi_t esi;
11ebf4ed
DS
3478 union gw_addr ip;
3479 } temp;
d62a17ae 3480
3481 if (afi != AFI_L2VPN)
3482 return true;
11ebf4ed 3483
6c924775 3484 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3485
3486 if (gw_ip == NULL) {
3487 memset(&temp, 0, sizeof(temp));
40381db7 3488 path_gw_ip_remote = &temp.ip;
11ebf4ed 3489 } else
40381db7 3490 path_gw_ip_remote = gw_ip;
11ebf4ed 3491
6c924775 3492 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3493}
3494
c265ee22 3495/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3496bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3497 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3498 struct bgp_dest *dest)
d62a17ae 3499{
2dbe3fa9 3500 bool ret = false;
b099a5c8
DA
3501 bool is_bgp_static_route =
3502 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3503 : false;
d62a17ae 3504
e8442016
DS
3505 /*
3506 * Only validated for unicast and multicast currently.
3507 * Also valid for EVPN where the nexthop is an IP address.
3508 * If we are a bgp static route being checked then there is
3509 * no need to check to see if the nexthop is martian as
3510 * that it should be ok.
3511 */
3512 if (is_bgp_static_route ||
3513 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3514 return false;
d62a17ae 3515
3516 /* If NEXT_HOP is present, validate it. */
3517 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3518 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3519 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3520 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3521 return true;
d62a17ae 3522 }
c265ee22 3523
d62a17ae 3524 /* If MP_NEXTHOP is present, validate it. */
3525 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3526 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3527 * it is not an IPv6 link-local address.
0355b41d
DA
3528 *
3529 * If we receive an UPDATE with nexthop length set to 32 bytes
3530 * we shouldn't discard an UPDATE if it's set to (::).
3531 * The link-local (2st) is validated along the code path later.
d62a17ae 3532 */
3533 if (attr->mp_nexthop_len) {
3534 switch (attr->mp_nexthop_len) {
3535 case BGP_ATTR_NHLEN_IPV4:
3536 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3537 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3538 || IPV4_CLASS_DE(
3539 ntohl(attr->mp_nexthop_global_in.s_addr))
3540 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3541 dest));
d62a17ae 3542 break;
3543
3544 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3545 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3546 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3547 &attr->mp_nexthop_global)
d62a17ae 3548 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3549 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3550 &attr->mp_nexthop_global)
3551 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3552 dest));
d62a17ae 3553 break;
0355b41d
DA
3554 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3555 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3556 || IN6_IS_ADDR_MULTICAST(
3557 &attr->mp_nexthop_global)
3558 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3559 dest));
0355b41d 3560 break;
d62a17ae 3561
3562 default:
3dc339cd 3563 ret = true;
d62a17ae 3564 break;
3565 }
3566 }
c265ee22 3567
d62a17ae 3568 return ret;
3569}
3570
aade37d7 3571static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3572{
3573 struct community *old;
3574 struct community *new;
3575 struct community *merge;
aade37d7 3576 struct community *no_export;
2721dd61
DA
3577
3578 old = attr->community;
aade37d7 3579 no_export = community_str2com("no-export");
2721dd61 3580
b4efa101
DA
3581 assert(no_export);
3582
2721dd61 3583 if (old) {
aade37d7 3584 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3585
3586 if (!old->refcnt)
3587 community_free(&old);
3588
3589 new = community_uniq_sort(merge);
3590 community_free(&merge);
3591 } else {
aade37d7 3592 new = community_dup(no_export);
2721dd61
DA
3593 }
3594
aade37d7 3595 community_free(&no_export);
2721dd61
DA
3596
3597 attr->community = new;
3598 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3599}
3600
5a1ae2c2 3601int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3602 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3603 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3604 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3605 struct bgp_route_evpn *evpn)
d62a17ae 3606{
3607 int ret;
3608 int aspath_loop_count = 0;
9bcb3eef 3609 struct bgp_dest *dest;
d62a17ae 3610 struct bgp *bgp;
3611 struct attr new_attr;
3612 struct attr *attr_new;
40381db7 3613 struct bgp_path_info *pi;
4b7e6066
DS
3614 struct bgp_path_info *new;
3615 struct bgp_path_info_extra *extra;
d62a17ae 3616 const char *reason;
3617 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3618 int connected = 0;
3619 int do_loop_check = 1;
3620 int has_valid_label = 0;
7c312383 3621 afi_t nh_afi;
949b0f24 3622 uint8_t pi_type = 0;
3623 uint8_t pi_sub_type = 0;
3624
c7bb4f00 3625 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3626 char pfxprint[PREFIX2STR_BUFFER];
3627
3628 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3629 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3630 afi, safi, attr);
6401252f
QY
3631 }
3632
49e5a4a0 3633#ifdef ENABLE_BGP_VNC
d62a17ae 3634 int vnc_implicit_withdraw = 0;
65efcfce 3635#endif
d62a17ae 3636 int same_attr = 0;
718e3744 3637
d62a17ae 3638 memset(&new_attr, 0, sizeof(struct attr));
3639 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3640 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3641
d62a17ae 3642 bgp = peer->bgp;
9bcb3eef 3643 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3644 /* TODO: Check to see if we can get rid of "is_valid_label" */
3645 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3646 has_valid_label = (num_labels > 0) ? 1 : 0;
3647 else
3648 has_valid_label = bgp_is_valid_label(label);
718e3744 3649
28f66de2
MS
3650 if (has_valid_label)
3651 assert(label != NULL);
3652
d62a17ae 3653 /* When peer's soft reconfiguration enabled. Record input packet in
3654 Adj-RIBs-In. */
3655 if (!soft_reconfig
3656 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3657 && peer != bgp->peer_self)
9bcb3eef 3658 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3659
3660 /* Check previously received route. */
9bcb3eef 3661 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3662 if (pi->peer == peer && pi->type == type
3663 && pi->sub_type == sub_type
3664 && pi->addpath_rx_id == addpath_id)
d62a17ae 3665 break;
3666
3667 /* AS path local-as loop check. */
3668 if (peer->change_local_as) {
c4368918
DW
3669 if (peer->allowas_in[afi][safi])
3670 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3671 else if (!CHECK_FLAG(peer->flags,
3672 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3673 aspath_loop_count = 1;
3674
3675 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3676 > aspath_loop_count) {
b4d46cc9 3677 peer->stat_pfx_aspath_loop++;
9bcb3eef 3678 reason = "as-path contains our own AS A;";
d62a17ae 3679 goto filtered;
3680 }
718e3744 3681 }
718e3744 3682
d62a17ae 3683 /* If the peer is configured for "allowas-in origin" and the last ASN in
3684 * the
3685 * as-path is our ASN then we do not need to call aspath_loop_check
3686 */
3687 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3688 if (aspath_get_last_as(attr->aspath) == bgp->as)
3689 do_loop_check = 0;
3690
3691 /* AS path loop check. */
3692 if (do_loop_check) {
3693 if (aspath_loop_check(attr->aspath, bgp->as)
3694 > peer->allowas_in[afi][safi]
3695 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3696 && aspath_loop_check(attr->aspath, bgp->confed_id)
3697 > peer->allowas_in[afi][safi])) {
b4d46cc9 3698 peer->stat_pfx_aspath_loop++;
d62a17ae 3699 reason = "as-path contains our own AS;";
3700 goto filtered;
3701 }
3702 }
aac9ef6c 3703
d62a17ae 3704 /* Route reflector originator ID check. */
3705 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3706 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3707 peer->stat_pfx_originator_loop++;
d62a17ae 3708 reason = "originator is us;";
3709 goto filtered;
3710 }
718e3744 3711
d62a17ae 3712 /* Route reflector cluster ID check. */
3713 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3714 peer->stat_pfx_cluster_loop++;
d62a17ae 3715 reason = "reflected from the same cluster;";
3716 goto filtered;
3717 }
718e3744 3718
d62a17ae 3719 /* Apply incoming filter. */
3720 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3721 peer->stat_pfx_filter++;
d62a17ae 3722 reason = "filter;";
3723 goto filtered;
3724 }
718e3744 3725
a8b72dc6
DA
3726 /* RFC 8212 to prevent route leaks.
3727 * This specification intends to improve this situation by requiring the
3728 * explicit configuration of both BGP Import and Export Policies for any
3729 * External BGP (EBGP) session such as customers, peers, or
3730 * confederation boundaries for all enabled address families. Through
3731 * codification of the aforementioned requirement, operators will
3732 * benefit from consistent behavior across different BGP
3733 * implementations.
3734 */
1d3fdccf 3735 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3736 if (!bgp_inbound_policy_exists(peer,
3737 &peer->filter[afi][safi])) {
3738 reason = "inbound policy missing";
3739 goto filtered;
3740 }
3741
fb29348a
DA
3742 /* draft-ietf-idr-deprecate-as-set-confed-set
3743 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3744 * Eventually, This document (if approved) updates RFC 4271
3745 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3746 * and obsoletes RFC 6472.
3747 */
7f972cd8 3748 if (peer->bgp->reject_as_sets)
fb29348a
DA
3749 if (aspath_check_as_sets(attr->aspath)) {
3750 reason =
3751 "as-path contains AS_SET or AS_CONFED_SET type;";
3752 goto filtered;
3753 }
3754
6f4f49b2 3755 new_attr = *attr;
d62a17ae 3756
3757 /* Apply incoming route-map.
3758 * NB: new_attr may now contain newly allocated values from route-map
3759 * "set"
3760 * commands, so we need bgp_attr_flush in the error paths, until we
3761 * intern
3762 * the attr (which takes over the memory references) */
9bcb3eef
DS
3763 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3764 num_labels, dest)
3765 == RMAP_DENY) {
b4d46cc9 3766 peer->stat_pfx_filter++;
d62a17ae 3767 reason = "route-map;";
3768 bgp_attr_flush(&new_attr);
3769 goto filtered;
3770 }
718e3744 3771
05864da7 3772 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3773 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3774 /* remove from RIB previous entry */
3775 bgp_zebra_withdraw(p, pi, bgp, safi);
3776 }
3777
7f323236
DW
3778 if (peer->sort == BGP_PEER_EBGP) {
3779
2721dd61
DA
3780 /* rfc7999:
3781 * A BGP speaker receiving an announcement tagged with the
3782 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3783 * NO_EXPORT community as defined in RFC1997, or a
3784 * similar community, to prevent propagation of the
3785 * prefix outside the local AS. The community to prevent
3786 * propagation SHOULD be chosen according to the operator's
3787 * routing policy.
3788 */
3789 if (new_attr.community
3790 && community_include(new_attr.community,
3791 COMMUNITY_BLACKHOLE))
aade37d7 3792 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3793
a4d82a8a
PZ
3794 /* If we receive the graceful-shutdown community from an eBGP
3795 * peer we must lower local-preference */
3796 if (new_attr.community
3797 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3798 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3799 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3800
a4d82a8a
PZ
3801 /* If graceful-shutdown is configured then add the GSHUT
3802 * community to all paths received from eBGP peers */
637e5ba4 3803 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3804 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3805 }
3806
949b0f24 3807 if (pi) {
3808 pi_type = pi->type;
3809 pi_sub_type = pi->sub_type;
3810 }
3811
d62a17ae 3812 /* next hop check. */
a4d82a8a 3813 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3814 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3815 &new_attr, dest)) {
b4d46cc9 3816 peer->stat_pfx_nh_invalid++;
d62a17ae 3817 reason = "martian or self next-hop;";
3818 bgp_attr_flush(&new_attr);
3819 goto filtered;
3820 }
718e3744 3821
5c14a191 3822 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3823 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3824 reason = "self mac;";
3825 goto filtered;
3826 }
3827
1e9be514
QY
3828 /* Update Overlay Index */
3829 if (afi == AFI_L2VPN) {
3830 overlay_index_update(&new_attr,
3831 evpn == NULL ? NULL : &evpn->gw_ip);
3832 }
3833
a1b773e2
DS
3834 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3835 * condition :
3836 * Suppress fib is enabled
3837 * BGP_OPT_NO_FIB is not enabled
3838 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3839 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3840 */
3841 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3842 && (sub_type == BGP_ROUTE_NORMAL)
3843 && (!bgp_option_check(BGP_OPT_NO_FIB))
3844 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3845 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3846
d62a17ae 3847 attr_new = bgp_attr_intern(&new_attr);
3848
9cbd06e0
DA
3849 /* If maximum prefix count is configured and current prefix
3850 * count exeed it.
3851 */
3852 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3853 return -1;
3854
d62a17ae 3855 /* If the update is implicit withdraw. */
40381db7
DS
3856 if (pi) {
3857 pi->uptime = bgp_clock();
3858 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3859
9bcb3eef 3860 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3861
d62a17ae 3862 /* Same attribute comes in. */
40381db7 3863 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3864 && same_attr
d62a17ae 3865 && (!has_valid_label
40381db7 3866 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3867 num_labels * sizeof(mpls_label_t))
d62a17ae 3868 == 0)
3869 && (overlay_index_equal(
0a50c248 3870 afi, pi,
d62a17ae 3871 evpn == NULL ? NULL : &evpn->gw_ip))) {
40ec3340 3872 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3873 && peer->sort == BGP_PEER_EBGP
40381db7 3874 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3875 if (bgp_debug_update(peer, p, NULL, 1)) {
3876 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3877 afi, safi, prd, p, label,
3878 num_labels, addpath_id ? 1 : 0,
3879 addpath_id, pfx_buf,
3880 sizeof(pfx_buf));
d62a17ae 3881 zlog_debug("%s rcvd %s", peer->host,
3882 pfx_buf);
3883 }
3884
9bcb3eef 3885 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3886 != BGP_DAMP_SUPPRESSED) {
40381db7 3887 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3888 safi);
9bcb3eef 3889 bgp_process(bgp, dest, afi, safi);
d62a17ae 3890 }
3891 } else /* Duplicate - odd */
3892 {
3893 if (bgp_debug_update(peer, p, NULL, 1)) {
3894 if (!peer->rcvd_attr_printed) {
3895 zlog_debug(
3896 "%s rcvd UPDATE w/ attr: %s",
3897 peer->host,
3898 peer->rcvd_attr_str);
3899 peer->rcvd_attr_printed = 1;
3900 }
3901
3902 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3903 afi, safi, prd, p, label,
3904 num_labels, addpath_id ? 1 : 0,
3905 addpath_id, pfx_buf,
3906 sizeof(pfx_buf));
d62a17ae 3907 zlog_debug(
3908 "%s rcvd %s...duplicate ignored",
3909 peer->host, pfx_buf);
3910 }
3911
3912 /* graceful restart STALE flag unset. */
40381db7 3913 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3914 bgp_path_info_unset_flag(
9bcb3eef
DS
3915 dest, pi, BGP_PATH_STALE);
3916 bgp_dest_set_defer_flag(dest, false);
3917 bgp_process(bgp, dest, afi, safi);
d62a17ae 3918 }
3919 }
3920
9bcb3eef 3921 bgp_dest_unlock_node(dest);
d62a17ae 3922 bgp_attr_unintern(&attr_new);
3923
3924 return 0;
3925 }
718e3744 3926
d62a17ae 3927 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3928 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3929 if (bgp_debug_update(peer, p, NULL, 1)) {
3930 bgp_debug_rdpfxpath2str(
a4d82a8a 3931 afi, safi, prd, p, label, num_labels,
d62a17ae 3932 addpath_id ? 1 : 0, addpath_id, pfx_buf,
3933 sizeof(pfx_buf));
3934 zlog_debug(
3935 "%s rcvd %s, flapped quicker than processing",
3936 peer->host, pfx_buf);
3937 }
3938
9bcb3eef 3939 bgp_path_info_restore(dest, pi);
d62a17ae 3940 }
718e3744 3941
d62a17ae 3942 /* Received Logging. */
3943 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3944 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3945 num_labels, addpath_id ? 1 : 0,
3946 addpath_id, pfx_buf,
3947 sizeof(pfx_buf));
d62a17ae 3948 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3949 }
718e3744 3950
d62a17ae 3951 /* graceful restart STALE flag unset. */
f009ff26 3952 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3953 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3954 bgp_dest_set_defer_flag(dest, false);
f009ff26 3955 }
d62a17ae 3956
3957 /* The attribute is changed. */
9bcb3eef 3958 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3959
3960 /* implicit withdraw, decrement aggregate and pcount here.
3961 * only if update is accepted, they'll increment below.
3962 */
40381db7 3963 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3964
3965 /* Update bgp route dampening information. */
40ec3340 3966 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 3967 && peer->sort == BGP_PEER_EBGP) {
3968 /* This is implicit withdraw so we should update
40ec3340
DS
3969 * dampening information.
3970 */
40381db7 3971 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3972 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3973 }
49e5a4a0 3974#ifdef ENABLE_BGP_VNC
d62a17ae 3975 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3976 struct bgp_dest *pdest = NULL;
d62a17ae 3977 struct bgp_table *table = NULL;
3978
9bcb3eef
DS
3979 pdest = bgp_node_get(bgp->rib[afi][safi],
3980 (struct prefix *)prd);
3981 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3982 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3983
3984 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3985 bgp, prd, table, p, pi);
d62a17ae 3986 }
9bcb3eef 3987 bgp_dest_unlock_node(pdest);
d62a17ae 3988 }
3989 if ((afi == AFI_IP || afi == AFI_IP6)
3990 && (safi == SAFI_UNICAST)) {
40381db7 3991 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 3992 /*
3993 * Implicit withdraw case.
3994 */
3995 ++vnc_implicit_withdraw;
40381db7
DS
3996 vnc_import_bgp_del_route(bgp, p, pi);
3997 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 3998 }
3999 }
65efcfce 4000#endif
128ea8ab 4001
d62a17ae 4002 /* Special handling for EVPN update of an existing route. If the
4003 * extended community attribute has changed, we need to
4004 * un-import
4005 * the route using its existing extended community. It will be
4006 * subsequently processed for import with the new extended
4007 * community.
4008 */
6f8c9c11
PR
4009 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4010 && !same_attr) {
40381db7 4011 if ((pi->attr->flag
d62a17ae 4012 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4013 && (attr_new->flag
4014 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4015 int cmp;
4016
40381db7 4017 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4018 attr_new->ecommunity);
4019 if (!cmp) {
4020 if (bgp_debug_update(peer, p, NULL, 1))
4021 zlog_debug(
4022 "Change in EXT-COMM, existing %s new %s",
4023 ecommunity_str(
40381db7 4024 pi->attr->ecommunity),
d62a17ae 4025 ecommunity_str(
4026 attr_new->ecommunity));
6f8c9c11
PR
4027 if (safi == SAFI_EVPN)
4028 bgp_evpn_unimport_route(
4029 bgp, afi, safi, p, pi);
4030 else /* SAFI_MPLS_VPN */
4031 vpn_leak_to_vrf_withdraw(bgp,
4032 pi);
d62a17ae 4033 }
4034 }
4035 }
718e3744 4036
d62a17ae 4037 /* Update to new attribute. */
40381db7
DS
4038 bgp_attr_unintern(&pi->attr);
4039 pi->attr = attr_new;
d62a17ae 4040
4041 /* Update MPLS label */
4042 if (has_valid_label) {
40381db7 4043 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4044 if (extra->label != label) {
4045 memcpy(&extra->label, label,
dbd587da 4046 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4047 extra->num_labels = num_labels;
4048 }
b57ba6d2
MK
4049 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4050 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4051 }
718e3744 4052
e496b420
HS
4053 /* Update SRv6 SID */
4054 if (attr->srv6_l3vpn) {
4055 extra = bgp_path_info_extra_get(pi);
4056 if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
4057 sid_copy(&extra->sid[0],
4058 &attr->srv6_l3vpn->sid);
4059 extra->num_sids = 1;
4060 }
4061 } else if (attr->srv6_vpn) {
4062 extra = bgp_path_info_extra_get(pi);
4063 if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
4064 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4065 extra->num_sids = 1;
4066 }
4067 }
4068
49e5a4a0 4069#ifdef ENABLE_BGP_VNC
d62a17ae 4070 if ((afi == AFI_IP || afi == AFI_IP6)
4071 && (safi == SAFI_UNICAST)) {
4072 if (vnc_implicit_withdraw) {
4073 /*
4074 * Add back the route with its new attributes
4075 * (e.g., nexthop).
4076 * The route is still selected, until the route
4077 * selection
4078 * queued by bgp_process actually runs. We have
4079 * to make this
4080 * update to the VNC side immediately to avoid
4081 * racing against
4082 * configuration changes (e.g., route-map
4083 * changes) which
4084 * trigger re-importation of the entire RIB.
4085 */
40381db7
DS
4086 vnc_import_bgp_add_route(bgp, p, pi);
4087 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4088 }
4089 }
65efcfce
LB
4090#endif
4091
d62a17ae 4092 /* Update bgp route dampening information. */
40ec3340 4093 if (get_active_bdc_from_pi(pi, afi, safi)
d62a17ae 4094 && peer->sort == BGP_PEER_EBGP) {
4095 /* Now we do normal update dampening. */
9bcb3eef 4096 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4097 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4098 bgp_dest_unlock_node(dest);
d62a17ae 4099 return 0;
4100 }
4101 }
128ea8ab 4102
d62a17ae 4103 /* Nexthop reachability check - for unicast and
4104 * labeled-unicast.. */
7c312383
AD
4105 if (((afi == AFI_IP || afi == AFI_IP6)
4106 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4107 || (safi == SAFI_EVPN &&
4108 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4109 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4110 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4111 && !CHECK_FLAG(peer->flags,
4112 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4113 && !CHECK_FLAG(bgp->flags,
4114 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4115 connected = 1;
4116 else
4117 connected = 0;
4118
960035b2
PZ
4119 struct bgp *bgp_nexthop = bgp;
4120
40381db7
DS
4121 if (pi->extra && pi->extra->bgp_orig)
4122 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4123
7c312383
AD
4124 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4125
4126 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
4053e952 4127 safi, pi, NULL, connected)
a4d82a8a 4128 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4129 bgp_path_info_set_flag(dest, pi,
4130 BGP_PATH_VALID);
d62a17ae 4131 else {
4132 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4133 zlog_debug("%s(%pI4): NH unresolved",
4134 __func__,
4135 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4136 }
9bcb3eef 4137 bgp_path_info_unset_flag(dest, pi,
18ee8310 4138 BGP_PATH_VALID);
d62a17ae 4139 }
4140 } else
9bcb3eef 4141 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4142
49e5a4a0 4143#ifdef ENABLE_BGP_VNC
d62a17ae 4144 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4145 struct bgp_dest *pdest = NULL;
d62a17ae 4146 struct bgp_table *table = NULL;
4147
9bcb3eef
DS
4148 pdest = bgp_node_get(bgp->rib[afi][safi],
4149 (struct prefix *)prd);
4150 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4151 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4152
4153 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4154 bgp, prd, table, p, pi);
d62a17ae 4155 }
9bcb3eef 4156 bgp_dest_unlock_node(pdest);
d62a17ae 4157 }
4158#endif
718e3744 4159
d62a17ae 4160 /* If this is an EVPN route and some attribute has changed,
4161 * process
4162 * route for import. If the extended community has changed, we
4163 * would
4164 * have done the un-import earlier and the import would result
4165 * in the
4166 * route getting injected into appropriate L2 VNIs. If it is
4167 * just
4168 * some other attribute change, the import will result in
4169 * updating
4170 * the attributes for the route in the VNI(s).
4171 */
7c312383
AD
4172 if (safi == SAFI_EVPN && !same_attr &&
4173 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4174 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4175
4176 /* Process change. */
40381db7 4177 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4178
9bcb3eef
DS
4179 bgp_process(bgp, dest, afi, safi);
4180 bgp_dest_unlock_node(dest);
558d1fec 4181
ddb5b488
PZ
4182 if (SAFI_UNICAST == safi
4183 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4184 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4185
40381db7 4186 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4187 }
4188 if ((SAFI_MPLS_VPN == safi)
4189 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4190
40381db7 4191 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4192 }
4193
49e5a4a0 4194#ifdef ENABLE_BGP_VNC
d62a17ae 4195 if (SAFI_MPLS_VPN == safi) {
4196 mpls_label_t label_decoded = decode_label(label);
28070ee3 4197
d62a17ae 4198 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4199 type, sub_type, &label_decoded);
4200 }
4201 if (SAFI_ENCAP == safi) {
4202 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4203 type, sub_type, NULL);
4204 }
28070ee3
PZ
4205#endif
4206
d62a17ae 4207 return 0;
4208 } // End of implicit withdraw
718e3744 4209
d62a17ae 4210 /* Received Logging. */
4211 if (bgp_debug_update(peer, p, NULL, 1)) {
4212 if (!peer->rcvd_attr_printed) {
4213 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4214 peer->rcvd_attr_str);
4215 peer->rcvd_attr_printed = 1;
4216 }
718e3744 4217
a4d82a8a 4218 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4219 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4220 sizeof(pfx_buf));
4221 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4222 }
718e3744 4223
d62a17ae 4224 /* Make new BGP info. */
9bcb3eef 4225 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4226
d62a17ae 4227 /* Update MPLS label */
4228 if (has_valid_label) {
18ee8310 4229 extra = bgp_path_info_extra_get(new);
8ba71050 4230 if (extra->label != label) {
dbd587da
QY
4231 memcpy(&extra->label, label,
4232 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4233 extra->num_labels = num_labels;
4234 }
b57ba6d2
MK
4235 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4236 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4237 }
718e3744 4238
e496b420
HS
4239 /* Update SRv6 SID */
4240 if (safi == SAFI_MPLS_VPN) {
4241 extra = bgp_path_info_extra_get(new);
4242 if (attr->srv6_l3vpn) {
4243 sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
4244 extra->num_sids = 1;
4245 } else if (attr->srv6_vpn) {
4246 sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
4247 extra->num_sids = 1;
4248 }
4249 }
4250
d62a17ae 4251 /* Update Overlay Index */
4252 if (afi == AFI_L2VPN) {
4253 overlay_index_update(new->attr,
d62a17ae 4254 evpn == NULL ? NULL : &evpn->gw_ip);
4255 }
4256 /* Nexthop reachability check. */
7c312383
AD
4257 if (((afi == AFI_IP || afi == AFI_IP6)
4258 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4259 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4260 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4261 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4262 && !CHECK_FLAG(peer->flags,
4263 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4264 && !CHECK_FLAG(bgp->flags,
4265 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4266 connected = 1;
4267 else
4268 connected = 0;
4269
7c312383
AD
4270 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4271
4053e952 4272 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
7c312383 4273 connected)
a4d82a8a 4274 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4275 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4276 else {
4277 if (BGP_DEBUG(nht, NHT)) {
4278 char buf1[INET6_ADDRSTRLEN];
4279 inet_ntop(AF_INET,
4280 (const void *)&attr_new->nexthop,
4281 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4282 zlog_debug("%s(%s): NH unresolved", __func__,
4283 buf1);
d62a17ae 4284 }
9bcb3eef 4285 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4286 }
4287 } else
9bcb3eef 4288 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4289
d62a17ae 4290 /* Addpath ID */
4291 new->addpath_rx_id = addpath_id;
4292
4293 /* Increment prefix */
4294 bgp_aggregate_increment(bgp, p, new, afi, safi);
4295
4296 /* Register new BGP information. */
9bcb3eef 4297 bgp_path_info_add(dest, new);
d62a17ae 4298
4299 /* route_node_get lock */
9bcb3eef 4300 bgp_dest_unlock_node(dest);
558d1fec 4301
49e5a4a0 4302#ifdef ENABLE_BGP_VNC
d62a17ae 4303 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4304 struct bgp_dest *pdest = NULL;
d62a17ae 4305 struct bgp_table *table = NULL;
4306
9bcb3eef
DS
4307 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4308 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4309 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4310
4311 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4312 bgp, prd, table, p, new);
4313 }
9bcb3eef 4314 bgp_dest_unlock_node(pdest);
d62a17ae 4315 }
65efcfce
LB
4316#endif
4317
d62a17ae 4318 /* If this is an EVPN route, process for import. */
7c312383 4319 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4320 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4321
9bcb3eef 4322 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4323
d62a17ae 4324 /* Process change. */
9bcb3eef 4325 bgp_process(bgp, dest, afi, safi);
718e3744 4326
ddb5b488
PZ
4327 if (SAFI_UNICAST == safi
4328 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4329 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4330 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4331 }
4332 if ((SAFI_MPLS_VPN == safi)
4333 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4334
4335 vpn_leak_to_vrf_update(bgp, new);
4336 }
49e5a4a0 4337#ifdef ENABLE_BGP_VNC
d62a17ae 4338 if (SAFI_MPLS_VPN == safi) {
4339 mpls_label_t label_decoded = decode_label(label);
28070ee3 4340
d62a17ae 4341 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4342 sub_type, &label_decoded);
4343 }
4344 if (SAFI_ENCAP == safi) {
4345 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4346 sub_type, NULL);
4347 }
28070ee3
PZ
4348#endif
4349
d62a17ae 4350 return 0;
718e3744 4351
d62a17ae 4352/* This BGP update is filtered. Log the reason then update BGP
4353 entry. */
4354filtered:
9bcb3eef 4355 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4356
d62a17ae 4357 if (bgp_debug_update(peer, p, NULL, 1)) {
4358 if (!peer->rcvd_attr_printed) {
4359 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4360 peer->rcvd_attr_str);
4361 peer->rcvd_attr_printed = 1;
4362 }
718e3744 4363
a4d82a8a 4364 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4365 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4366 sizeof(pfx_buf));
4367 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4368 peer->host, pfx_buf, reason);
4369 }
128ea8ab 4370
40381db7 4371 if (pi) {
d62a17ae 4372 /* If this is an EVPN route, un-import it as it is now filtered.
4373 */
4374 if (safi == SAFI_EVPN)
40381db7 4375 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4376
ddb5b488
PZ
4377 if (SAFI_UNICAST == safi
4378 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4379 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4380
40381db7 4381 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4382 }
4383 if ((SAFI_MPLS_VPN == safi)
4384 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4385
40381db7 4386 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4387 }
4388
9bcb3eef 4389 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4390 }
4391
9bcb3eef 4392 bgp_dest_unlock_node(dest);
558d1fec 4393
49e5a4a0 4394#ifdef ENABLE_BGP_VNC
d62a17ae 4395 /*
4396 * Filtered update is treated as an implicit withdrawal (see
4397 * bgp_rib_remove()
4398 * a few lines above)
4399 */
4400 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4401 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4402 0);
4403 }
97736e32
PZ
4404#endif
4405
d62a17ae 4406 return 0;
718e3744 4407}
4408
26a3ffd6 4409int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4410 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4411 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4412 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4413{
d62a17ae 4414 struct bgp *bgp;
4415 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4416 struct bgp_dest *dest;
40381db7 4417 struct bgp_path_info *pi;
718e3744 4418
49e5a4a0 4419#ifdef ENABLE_BGP_VNC
d62a17ae 4420 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4421 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4422 0);
4423 }
28070ee3
PZ
4424#endif
4425
d62a17ae 4426 bgp = peer->bgp;
4427
4428 /* Lookup node. */
9bcb3eef 4429 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4430
4431 /* If peer is soft reconfiguration enabled. Record input packet for
4432 * further calculation.
4433 *
4434 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4435 * routes that are filtered. This tanks out Quagga RS pretty badly due
4436 * to
4437 * the iteration over all RS clients.
4438 * Since we need to remove the entry from adj_in anyway, do that first
4439 * and
4440 * if there was no entry, we don't need to do anything more.
4441 */
4442 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4443 && peer != bgp->peer_self)
9bcb3eef 4444 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4445 peer->stat_pfx_dup_withdraw++;
4446
d62a17ae 4447 if (bgp_debug_update(peer, p, NULL, 1)) {
4448 bgp_debug_rdpfxpath2str(
a4d82a8a 4449 afi, safi, prd, p, label, num_labels,
d62a17ae 4450 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4451 sizeof(pfx_buf));
4452 zlog_debug(
4453 "%s withdrawing route %s not in adj-in",
4454 peer->host, pfx_buf);
4455 }
9bcb3eef 4456 bgp_dest_unlock_node(dest);
d62a17ae 4457 return 0;
4458 }
cd808e74 4459
d62a17ae 4460 /* Lookup withdrawn route. */
9bcb3eef 4461 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4462 if (pi->peer == peer && pi->type == type
4463 && pi->sub_type == sub_type
4464 && pi->addpath_rx_id == addpath_id)
d62a17ae 4465 break;
4466
4467 /* Logging. */
4468 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4469 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4470 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4471 sizeof(pfx_buf));
4472 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4473 pfx_buf);
4474 }
718e3744 4475
d62a17ae 4476 /* Withdraw specified route from routing table. */
40381db7 4477 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4478 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4479 if (SAFI_UNICAST == safi
4480 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4481 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4482 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4483 }
4484 if ((SAFI_MPLS_VPN == safi)
4485 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4486
40381db7 4487 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4488 }
4489 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4490 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
d62a17ae 4491 addpath_id ? 1 : 0, addpath_id, pfx_buf,
4492 sizeof(pfx_buf));
4493 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4494 }
718e3744 4495
d62a17ae 4496 /* Unlock bgp_node_get() lock. */
9bcb3eef 4497 bgp_dest_unlock_node(dest);
d62a17ae 4498
4499 return 0;
718e3744 4500}
6b0655a2 4501
d62a17ae 4502void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4503 int withdraw)
718e3744 4504{
d62a17ae 4505 struct update_subgroup *subgrp;
4506 subgrp = peer_subgroup(peer, afi, safi);
4507 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4508}
6182d65b 4509
718e3744 4510
3f9c7369
DS
4511/*
4512 * bgp_stop_announce_route_timer
4513 */
d62a17ae 4514void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4515{
d62a17ae 4516 if (!paf->t_announce_route)
4517 return;
4518
50478845 4519 thread_cancel(&paf->t_announce_route);
718e3744 4520}
6b0655a2 4521
3f9c7369
DS
4522/*
4523 * bgp_announce_route_timer_expired
4524 *
4525 * Callback that is invoked when the route announcement timer for a
4526 * peer_af expires.
4527 */
d62a17ae 4528static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4529{
d62a17ae 4530 struct peer_af *paf;
4531 struct peer *peer;
558d1fec 4532
d62a17ae 4533 paf = THREAD_ARG(t);
4534 peer = paf->peer;
718e3744 4535
feb17238 4536 if (!peer_established(peer))
d62a17ae 4537 return 0;
3f9c7369 4538
d62a17ae 4539 if (!peer->afc_nego[paf->afi][paf->safi])
4540 return 0;
3f9c7369 4541
d62a17ae 4542 peer_af_announce_route(paf, 1);
c5aec50b
MK
4543
4544 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4545 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4546
d62a17ae 4547 return 0;
718e3744 4548}
4549
3f9c7369
DS
4550/*
4551 * bgp_announce_route
4552 *
4553 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
4554 */
d62a17ae 4555void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi)
4556{
4557 struct peer_af *paf;
4558 struct update_subgroup *subgrp;
4559
4560 paf = peer_af_find(peer, afi, safi);
4561 if (!paf)
4562 return;
4563 subgrp = PAF_SUBGRP(paf);
4564
4565 /*
4566 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4567 * or a refresh has already been triggered.
4568 */
4569 if (!subgrp || paf->t_announce_route)
4570 return;
4571
4572 /*
4573 * Start a timer to stagger/delay the announce. This serves
4574 * two purposes - announcement can potentially be combined for
4575 * multiple peers and the announcement doesn't happen in the
4576 * vty context.
4577 */
4578 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4579 (subgrp->peer_count == 1)
4580 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4581 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4582 &paf->t_announce_route);
3f9c7369
DS
4583}
4584
4585/*
4586 * Announce routes from all AF tables to a peer.
4587 *
4588 * This should ONLY be called when there is a need to refresh the
4589 * routes to the peer based on a policy change for this peer alone
4590 * or a route refresh request received from the peer.
4591 * The operation will result in splitting the peer from its existing
4592 * subgroups and putting it in new subgroups.
4593 */
d62a17ae 4594void bgp_announce_route_all(struct peer *peer)
718e3744 4595{
d62a17ae 4596 afi_t afi;
4597 safi_t safi;
4598
05c7a1cc
QY
4599 FOREACH_AFI_SAFI (afi, safi)
4600 bgp_announce_route(peer, afi, safi);
718e3744 4601}
6b0655a2 4602
46aeabed
LS
4603/* Flag or unflag bgp_dest to determine whether it should be treated by
4604 * bgp_soft_reconfig_table_task.
4605 * Flag if flag is true. Unflag if flag is false.
4606 */
4607static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4608{
4609 struct bgp_dest *dest;
4610 struct bgp_adj_in *ain;
4611
4612 if (!table)
4613 return;
4614
4615 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4616 for (ain = dest->adj_in; ain; ain = ain->next) {
4617 if (ain->peer != NULL)
4618 break;
4619 }
4620 if (flag && ain != NULL && ain->peer != NULL)
4621 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4622 else
4623 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4624 }
4625}
4626
4627static int bgp_soft_reconfig_table_update(struct peer *peer,
4628 struct bgp_dest *dest,
4629 struct bgp_adj_in *ain, afi_t afi,
4630 safi_t safi, struct prefix_rd *prd)
4631{
4632 struct bgp_path_info *pi;
4633 uint32_t num_labels = 0;
4634 mpls_label_t *label_pnt = NULL;
4635 struct bgp_route_evpn evpn;
4636
4637 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4638 if (pi->peer == peer)
4639 break;
4640
4641 if (pi && pi->extra)
4642 num_labels = pi->extra->num_labels;
4643 if (num_labels)
4644 label_pnt = &pi->extra->label[0];
4645 if (pi)
4646 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4647 sizeof(evpn));
4648 else
4649 memset(&evpn, 0, sizeof(evpn));
4650
4651 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4652 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4653 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4654 &evpn);
4655}
4656
d62a17ae 4657static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4658 struct bgp_table *table,
4659 struct prefix_rd *prd)
718e3744 4660{
d62a17ae 4661 int ret;
9bcb3eef 4662 struct bgp_dest *dest;
d62a17ae 4663 struct bgp_adj_in *ain;
718e3744 4664
d62a17ae 4665 if (!table)
4666 table = peer->bgp->rib[afi][safi];
718e3744 4667
9bcb3eef
DS
4668 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4669 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4670 if (ain->peer != peer)
4671 continue;
8692c506 4672
46aeabed
LS
4673 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4674 afi, safi, prd);
ea47320b
DL
4675
4676 if (ret < 0) {
9bcb3eef 4677 bgp_dest_unlock_node(dest);
ea47320b 4678 return;
d62a17ae 4679 }
4680 }
718e3744 4681}
4682
46aeabed
LS
4683/* Do soft reconfig table per bgp table.
4684 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4685 * when BGP_NODE_SOFT_RECONFIG is set,
4686 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4687 * Schedule a new thread to continue the job.
4688 * Without splitting the full job into several part,
4689 * vtysh waits for the job to finish before responding to a BGP command
4690 */
4691static int bgp_soft_reconfig_table_task(struct thread *thread)
4692{
4693 uint32_t iter, max_iter;
4694 int ret;
4695 struct bgp_dest *dest;
4696 struct bgp_adj_in *ain;
4697 struct peer *peer;
4698 struct bgp_table *table;
4699 struct prefix_rd *prd;
4700 struct listnode *node, *nnode;
4701
4702 table = THREAD_ARG(thread);
4703 prd = NULL;
4704
4705 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4706 if (table->soft_reconfig_init) {
4707 /* first call of the function with a new srta structure.
4708 * Don't do any treatment this time on nodes
4709 * in order vtysh to respond quickly
4710 */
4711 max_iter = 0;
4712 }
4713
4714 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4715 dest = bgp_route_next(dest)) {
4716 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4717 continue;
4718
4719 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4720
4721 for (ain = dest->adj_in; ain; ain = ain->next) {
4722 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4723 nnode, peer)) {
4724 if (ain->peer != peer)
4725 continue;
4726
4727 ret = bgp_soft_reconfig_table_update(
4728 peer, dest, ain, table->afi,
4729 table->safi, prd);
4730 iter++;
4731
4732 if (ret < 0) {
4733 bgp_dest_unlock_node(dest);
4734 listnode_delete(
4735 table->soft_reconfig_peers,
4736 peer);
4737 bgp_announce_route(peer, table->afi,
4738 table->safi);
4739 if (list_isempty(
4740 table->soft_reconfig_peers)) {
4741 list_delete(
4742 &table->soft_reconfig_peers);
4743 bgp_soft_reconfig_table_flag(
4744 table, false);
4745 return 0;
4746 }
4747 }
4748 }
4749 }
4750 }
4751
4752 /* we're either starting the initial iteration,
4753 * or we're going to continue an ongoing iteration
4754 */
4755 if (dest || table->soft_reconfig_init) {
4756 table->soft_reconfig_init = false;
4757 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4758 table, 0, &table->soft_reconfig_thread);
4759 return 0;
4760 }
4761 /* we're done, clean up the background iteration context info and
4762 schedule route annoucement
4763 */
4764 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4765 listnode_delete(table->soft_reconfig_peers, peer);
4766 bgp_announce_route(peer, table->afi, table->safi);
4767 }
4768
4769 list_delete(&table->soft_reconfig_peers);
4770
4771 return 0;
4772}
4773
4774
4775/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4776 * and peer.
4777 * - bgp cannot be NULL
4778 * - if table and peer are NULL, cancel all threads within the bgp instance
4779 * - if table is NULL and peer is not,
4780 * remove peer in all threads within the bgp instance
4781 * - if peer is NULL, cancel all threads matching table within the bgp instance
4782 */
4783void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4784 const struct bgp_table *table,
4785 const struct peer *peer)
4786{
4787 struct peer *npeer;
4788 struct listnode *node, *nnode;
4789 int afi, safi;
4790 struct bgp_table *ntable;
4791
4792 if (!bgp)
4793 return;
4794
4795 FOREACH_AFI_SAFI (afi, safi) {
4796 ntable = bgp->rib[afi][safi];
4797 if (!ntable)
4798 continue;
4799 if (table && table != ntable)
4800 continue;
4801
4802 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4803 npeer)) {
4804 if (peer && peer != npeer)
4805 continue;
4806 listnode_delete(ntable->soft_reconfig_peers, npeer);
4807 }
4808
4809 if (!ntable->soft_reconfig_peers
4810 || !list_isempty(ntable->soft_reconfig_peers))
4811 continue;
4812
4813 list_delete(&ntable->soft_reconfig_peers);
4814 bgp_soft_reconfig_table_flag(ntable, false);
4815 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4816 }
4817}
4818
d62a17ae 4819void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4820{
9bcb3eef 4821 struct bgp_dest *dest;
d62a17ae 4822 struct bgp_table *table;
46aeabed
LS
4823 struct listnode *node, *nnode;
4824 struct peer *npeer;
4825 struct peer_af *paf;
718e3744 4826
feb17238 4827 if (!peer_established(peer))
d62a17ae 4828 return;
718e3744 4829
d62a17ae 4830 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
4831 && (safi != SAFI_EVPN)) {
4832 table = peer->bgp->rib[afi][safi];
4833 if (!table)
4834 return;
4835
4836 table->soft_reconfig_init = true;
4837
4838 if (!table->soft_reconfig_peers)
4839 table->soft_reconfig_peers = list_new();
4840 npeer = NULL;
4841 /* add peer to the table soft_reconfig_peers if not already
4842 * there
4843 */
4844 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
4845 npeer)) {
4846 if (peer == npeer)
4847 break;
4848 }
4849 if (peer != npeer)
4850 listnode_add(table->soft_reconfig_peers, peer);
4851
4852 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4853 * on table would start back at the beginning.
4854 */
4855 bgp_soft_reconfig_table_flag(table, true);
4856
4857 if (!table->soft_reconfig_thread)
4858 thread_add_event(bm->master,
4859 bgp_soft_reconfig_table_task, table, 0,
4860 &table->soft_reconfig_thread);
4861 /* Cancel bgp_announce_route_timer_expired threads.
4862 * bgp_announce_route_timer_expired threads have been scheduled
4863 * to announce routes as soon as the soft_reconfigure process
4864 * finishes.
4865 * In this case, soft_reconfigure is also scheduled by using
4866 * a thread but is planned after the
4867 * bgp_announce_route_timer_expired threads. It means that,
4868 * without cancelling the threads, the route announcement task
4869 * would run before the soft reconfiguration one. That would
4870 * useless and would block vtysh during several seconds. Route
4871 * announcements are rescheduled as soon as the soft_reconfigure
4872 * process finishes.
4873 */
4874 paf = peer_af_find(peer, afi, safi);
4875 if (paf)
4876 bgp_stop_announce_route_timer(paf);
4877 } else
9bcb3eef
DS
4878 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4879 dest = bgp_route_next(dest)) {
4880 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4881
b54892e0
DS
4882 if (table == NULL)
4883 continue;
8692c506 4884
9bcb3eef 4885 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4886 struct prefix_rd prd;
4887
4888 prd.family = AF_UNSPEC;
4889 prd.prefixlen = 64;
4890 memcpy(&prd.val, p->u.val, 8);
4891
4892 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4893 }
718e3744 4894}
6b0655a2 4895
228da428 4896
d62a17ae 4897struct bgp_clear_node_queue {
9bcb3eef 4898 struct bgp_dest *dest;
228da428
CC
4899};
4900
d62a17ae 4901static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4902{
d62a17ae 4903 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4904 struct bgp_dest *dest = cnq->dest;
d62a17ae 4905 struct peer *peer = wq->spec.data;
40381db7 4906 struct bgp_path_info *pi;
3103e8d2 4907 struct bgp *bgp;
9bcb3eef
DS
4908 afi_t afi = bgp_dest_table(dest)->afi;
4909 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4910
9bcb3eef 4911 assert(dest && peer);
3103e8d2 4912 bgp = peer->bgp;
d62a17ae 4913
4914 /* It is possible that we have multiple paths for a prefix from a peer
4915 * if that peer is using AddPath.
4916 */
9bcb3eef 4917 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4918 if (pi->peer != peer)
ea47320b
DL
4919 continue;
4920
4921 /* graceful restart STALE flag set. */
9af52ccf
DA
4922 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4923 && peer->nsf[afi][safi])
4924 || CHECK_FLAG(peer->af_sflags[afi][safi],
4925 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4926 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4927 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4928 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4929 else {
4930 /* If this is an EVPN route, process for
4931 * un-import. */
4932 if (safi == SAFI_EVPN)
9bcb3eef
DS
4933 bgp_evpn_unimport_route(
4934 bgp, afi, safi,
4935 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
4936 /* Handle withdraw for VRF route-leaking and L3VPN */
4937 if (SAFI_UNICAST == safi
4938 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 4939 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 4940 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 4941 bgp, pi);
960035b2 4942 }
3103e8d2 4943 if (SAFI_MPLS_VPN == safi &&
960035b2 4944 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 4945 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 4946 }
3103e8d2 4947
9bcb3eef 4948 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4949 }
ea47320b 4950 }
d62a17ae 4951 return WQ_SUCCESS;
200df115 4952}
4953
d62a17ae 4954static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 4955{
d62a17ae 4956 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
4957 struct bgp_dest *dest = cnq->dest;
4958 struct bgp_table *table = bgp_dest_table(dest);
228da428 4959
9bcb3eef 4960 bgp_dest_unlock_node(dest);
d62a17ae 4961 bgp_table_unlock(table);
4962 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 4963}
4964
d62a17ae 4965static void bgp_clear_node_complete(struct work_queue *wq)
200df115 4966{
d62a17ae 4967 struct peer *peer = wq->spec.data;
64e580a7 4968
d62a17ae 4969 /* Tickle FSM to start moving again */
4970 BGP_EVENT_ADD(peer, Clearing_Completed);
4971
4972 peer_unlock(peer); /* bgp_clear_route */
200df115 4973}
718e3744 4974
d62a17ae 4975static void bgp_clear_node_queue_init(struct peer *peer)
200df115 4976{
d62a17ae 4977 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
4978
4979 snprintf(wname, sizeof(wname), "clear %s", peer->host);
4980#undef CLEAR_QUEUE_NAME_LEN
4981
0ce1ca80 4982 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 4983 peer->clear_node_queue->spec.hold = 10;
4984 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
4985 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
4986 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
4987 peer->clear_node_queue->spec.max_retries = 0;
4988
4989 /* we only 'lock' this peer reference when the queue is actually active
4990 */
4991 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
4992}
4993
d62a17ae 4994static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
4995 struct bgp_table *table)
65ca75e0 4996{
9bcb3eef 4997 struct bgp_dest *dest;
b6c386bb 4998 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 4999
d62a17ae 5000 if (!table)
5001 table = peer->bgp->rib[afi][safi];
dc83d712 5002
d62a17ae 5003 /* If still no table => afi/safi isn't configured at all or smth. */
5004 if (!table)
5005 return;
dc83d712 5006
9bcb3eef 5007 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5008 struct bgp_path_info *pi, *next;
d62a17ae 5009 struct bgp_adj_in *ain;
5010 struct bgp_adj_in *ain_next;
5011
5012 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5013 * queued for every clearing peer, regardless of whether it is
5014 * relevant to the peer at hand.
5015 *
5016 * Overview: There are 3 different indices which need to be
5017 * scrubbed, potentially, when a peer is removed:
5018 *
5019 * 1 peer's routes visible via the RIB (ie accepted routes)
5020 * 2 peer's routes visible by the (optional) peer's adj-in index
5021 * 3 other routes visible by the peer's adj-out index
5022 *
5023 * 3 there is no hurry in scrubbing, once the struct peer is
5024 * removed from bgp->peer, we could just GC such deleted peer's
5025 * adj-outs at our leisure.
5026 *
5027 * 1 and 2 must be 'scrubbed' in some way, at least made
5028 * invisible via RIB index before peer session is allowed to be
5029 * brought back up. So one needs to know when such a 'search' is
5030 * complete.
5031 *
5032 * Ideally:
5033 *
5034 * - there'd be a single global queue or a single RIB walker
5035 * - rather than tracking which route_nodes still need to be
5036 * examined on a peer basis, we'd track which peers still
5037 * aren't cleared
5038 *
5039 * Given that our per-peer prefix-counts now should be reliable,
5040 * this may actually be achievable. It doesn't seem to be a huge
5041 * problem at this time,
5042 *
5043 * It is possible that we have multiple paths for a prefix from
5044 * a peer
5045 * if that peer is using AddPath.
5046 */
9bcb3eef 5047 ain = dest->adj_in;
d62a17ae 5048 while (ain) {
5049 ain_next = ain->next;
5050
6a840fd9 5051 if (ain->peer == peer)
9bcb3eef 5052 bgp_adj_in_remove(dest, ain);
d62a17ae 5053
5054 ain = ain_next;
5055 }
5056
9bcb3eef 5057 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5058 next = pi->next;
5059 if (pi->peer != peer)
d62a17ae 5060 continue;
5061
5062 if (force)
9bcb3eef 5063 bgp_path_info_reap(dest, pi);
d62a17ae 5064 else {
5065 struct bgp_clear_node_queue *cnq;
5066
5067 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5068 bgp_table_lock(bgp_dest_table(dest));
5069 bgp_dest_lock_node(dest);
d62a17ae 5070 cnq = XCALLOC(
5071 MTYPE_BGP_CLEAR_NODE_QUEUE,
5072 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5073 cnq->dest = dest;
d62a17ae 5074 work_queue_add(peer->clear_node_queue, cnq);
5075 break;
5076 }
5077 }
5078 }
5079 return;
5080}
5081
5082void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5083{
9bcb3eef 5084 struct bgp_dest *dest;
d62a17ae 5085 struct bgp_table *table;
5086
5087 if (peer->clear_node_queue == NULL)
5088 bgp_clear_node_queue_init(peer);
5089
5090 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5091 * Idle until it receives a Clearing_Completed event. This protects
5092 * against peers which flap faster than we can we clear, which could
5093 * lead to:
5094 *
5095 * a) race with routes from the new session being installed before
5096 * clear_route_node visits the node (to delete the route of that
5097 * peer)
5098 * b) resource exhaustion, clear_route_node likely leads to an entry
5099 * on the process_main queue. Fast-flapping could cause that queue
5100 * to grow and grow.
5101 */
5102
5103 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5104 * the unlock will happen upon work-queue completion; other wise, the
5105 * unlock happens at the end of this function.
5106 */
5107 if (!peer->clear_node_queue->thread)
5108 peer_lock(peer);
5109
5110 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5111 bgp_clear_route_table(peer, afi, safi, NULL);
5112 else
9bcb3eef
DS
5113 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5114 dest = bgp_route_next(dest)) {
5115 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5116 if (!table)
5117 continue;
5118
5119 bgp_clear_route_table(peer, afi, safi, table);
5120 }
d62a17ae 5121
5122 /* unlock if no nodes got added to the clear-node-queue. */
5123 if (!peer->clear_node_queue->thread)
5124 peer_unlock(peer);
718e3744 5125}
d62a17ae 5126
5127void bgp_clear_route_all(struct peer *peer)
718e3744 5128{
d62a17ae 5129 afi_t afi;
5130 safi_t safi;
718e3744 5131
05c7a1cc
QY
5132 FOREACH_AFI_SAFI (afi, safi)
5133 bgp_clear_route(peer, afi, safi);
65efcfce 5134
49e5a4a0 5135#ifdef ENABLE_BGP_VNC
d62a17ae 5136 rfapiProcessPeerDown(peer);
65efcfce 5137#endif
718e3744 5138}
5139
d62a17ae 5140void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5141{
d62a17ae 5142 struct bgp_table *table;
9bcb3eef 5143 struct bgp_dest *dest;
d62a17ae 5144 struct bgp_adj_in *ain;
5145 struct bgp_adj_in *ain_next;
718e3744 5146
d62a17ae 5147 table = peer->bgp->rib[afi][safi];
718e3744 5148
d62a17ae 5149 /* It is possible that we have multiple paths for a prefix from a peer
5150 * if that peer is using AddPath.
5151 */
9bcb3eef
DS
5152 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5153 ain = dest->adj_in;
43143c8f 5154
d62a17ae 5155 while (ain) {
5156 ain_next = ain->next;
43143c8f 5157
6a840fd9 5158 if (ain->peer == peer)
9bcb3eef 5159 bgp_adj_in_remove(dest, ain);
43143c8f 5160
d62a17ae 5161 ain = ain_next;
5162 }
5163 }
718e3744 5164}
93406d87 5165
d62a17ae 5166void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5167{
9bcb3eef 5168 struct bgp_dest *dest;
40381db7 5169 struct bgp_path_info *pi;
d62a17ae 5170 struct bgp_table *table;
5171
9af52ccf 5172 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5173 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5174 dest = bgp_route_next(dest)) {
5175 struct bgp_dest *rm;
d62a17ae 5176
5177 /* look for neighbor in tables */
9bcb3eef 5178 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5179 if (!table)
ea47320b
DL
5180 continue;
5181
5182 for (rm = bgp_table_top(table); rm;
5183 rm = bgp_route_next(rm))
9bcb3eef 5184 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5185 pi = pi->next) {
40381db7 5186 if (pi->peer != peer)
ea47320b 5187 continue;
40381db7 5188 if (!CHECK_FLAG(pi->flags,
1defdda8 5189 BGP_PATH_STALE))
ea47320b
DL
5190 break;
5191
40381db7 5192 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5193 break;
5194 }
d62a17ae 5195 }
5196 } else {
9bcb3eef
DS
5197 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5198 dest = bgp_route_next(dest))
5199 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5200 pi = pi->next) {
40381db7 5201 if (pi->peer != peer)
ea47320b 5202 continue;
40381db7 5203 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5204 break;
9bcb3eef 5205 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5206 break;
5207 }
d62a17ae 5208 }
93406d87 5209}
6b0655a2 5210
9af52ccf
DA
5211void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5212{
5213 struct bgp_dest *dest, *ndest;
5214 struct bgp_path_info *pi;
5215 struct bgp_table *table;
5216
5217 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5218 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5219 dest = bgp_route_next(dest)) {
5220 table = bgp_dest_get_bgp_table_info(dest);
5221 if (!table)
5222 continue;
5223
5224 for (ndest = bgp_table_top(table); ndest;
5225 ndest = bgp_route_next(ndest)) {
5226 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5227 pi = pi->next) {
5228 if (pi->peer != peer)
5229 continue;
5230
5231 if ((CHECK_FLAG(
5232 peer->af_sflags[afi][safi],
5233 PEER_STATUS_ENHANCED_REFRESH))
5234 && !CHECK_FLAG(pi->flags,
5235 BGP_PATH_STALE)
5236 && !CHECK_FLAG(
5237 pi->flags,
5238 BGP_PATH_UNUSEABLE)) {
5239 if (bgp_debug_neighbor_events(
5240 peer))
5241 zlog_debug(
5242 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5243 peer->host,
5244 afi2str(afi),
5245 safi2str(safi),
5246 bgp_dest_get_prefix(
5247 ndest));
5248
5249 bgp_path_info_set_flag(
5250 ndest, pi,
5251 BGP_PATH_STALE);
5252 }
5253 }
5254 }
5255 }
5256 } else {
5257 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5258 dest = bgp_route_next(dest)) {
5259 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5260 pi = pi->next) {
5261 if (pi->peer != peer)
5262 continue;
5263
5264 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5265 PEER_STATUS_ENHANCED_REFRESH))
5266 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5267 && !CHECK_FLAG(pi->flags,
5268 BGP_PATH_UNUSEABLE)) {
5269 if (bgp_debug_neighbor_events(peer))
5270 zlog_debug(
5271 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5272 peer->host,
5273 afi2str(afi),
5274 safi2str(safi),
5275 bgp_dest_get_prefix(
5276 dest));
5277
5278 bgp_path_info_set_flag(dest, pi,
5279 BGP_PATH_STALE);
5280 }
5281 }
5282 }
5283 }
5284}
5285
3dc339cd 5286bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5287{
e0df4c04 5288 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5289 return true;
e0df4c04 5290
9dac9fc8
DA
5291 if (peer->sort == BGP_PEER_EBGP
5292 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5293 || FILTER_LIST_OUT_NAME(filter)
5294 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5295 return true;
5296 return false;
9dac9fc8
DA
5297}
5298
3dc339cd 5299bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5300{
e0df4c04 5301 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5302 return true;
e0df4c04 5303
9dac9fc8
DA
5304 if (peer->sort == BGP_PEER_EBGP
5305 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5306 || FILTER_LIST_IN_NAME(filter)
5307 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5308 return true;
5309 return false;
9dac9fc8
DA
5310}
5311
568e10ca 5312static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5313 safi_t safi)
bb86c601 5314{
9bcb3eef 5315 struct bgp_dest *dest;
40381db7 5316 struct bgp_path_info *pi;
4b7e6066 5317 struct bgp_path_info *next;
bb86c601 5318
9bcb3eef
DS
5319 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5320 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5321 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5322
40381db7 5323 next = pi->next;
1b7bb747
CS
5324
5325 /* Unimport EVPN routes from VRFs */
5326 if (safi == SAFI_EVPN)
5327 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5328 SAFI_EVPN, p, pi);
1b7bb747 5329
40381db7
DS
5330 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5331 && pi->type == ZEBRA_ROUTE_BGP
5332 && (pi->sub_type == BGP_ROUTE_NORMAL
5333 || pi->sub_type == BGP_ROUTE_AGGREGATE
5334 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5335
d62a17ae 5336 if (bgp_fibupd_safi(safi))
b54892e0 5337 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5338 }
9514b37d 5339
9bcb3eef 5340 bgp_path_info_reap(dest, pi);
d62a17ae 5341 }
bb86c601
LB
5342}
5343
718e3744 5344/* Delete all kernel routes. */
d62a17ae 5345void bgp_cleanup_routes(struct bgp *bgp)
5346{
5347 afi_t afi;
9bcb3eef 5348 struct bgp_dest *dest;
67009e22 5349 struct bgp_table *table;
d62a17ae 5350
5351 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5352 if (afi == AFI_L2VPN)
5353 continue;
568e10ca 5354 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5355 SAFI_UNICAST);
d62a17ae 5356 /*
5357 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5358 */
5359 if (afi != AFI_L2VPN) {
5360 safi_t safi;
5361 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5362 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5363 dest = bgp_route_next(dest)) {
5364 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5365 if (table != NULL) {
5366 bgp_cleanup_table(bgp, table, safi);
5367 bgp_table_finish(&table);
9bcb3eef
DS
5368 bgp_dest_set_bgp_table_info(dest, NULL);
5369 bgp_dest_unlock_node(dest);
d62a17ae 5370 }
5371 }
5372 safi = SAFI_ENCAP;
9bcb3eef
DS
5373 for (dest = bgp_table_top(bgp->rib[afi][safi]); 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);
5378 bgp_table_finish(&table);
9bcb3eef
DS
5379 bgp_dest_set_bgp_table_info(dest, NULL);
5380 bgp_dest_unlock_node(dest);
d62a17ae 5381 }
5382 }
5383 }
5384 }
9bcb3eef
DS
5385 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5386 dest = bgp_route_next(dest)) {
5387 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5388 if (table != NULL) {
5389 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5390 bgp_table_finish(&table);
9bcb3eef
DS
5391 bgp_dest_set_bgp_table_info(dest, NULL);
5392 bgp_dest_unlock_node(dest);
d62a17ae 5393 }
bb86c601 5394 }
718e3744 5395}
5396
d62a17ae 5397void bgp_reset(void)
718e3744 5398{
d62a17ae 5399 vty_reset();
5400 bgp_zclient_reset();
5401 access_list_reset();
5402 prefix_list_reset();
718e3744 5403}
6b0655a2 5404
d62a17ae 5405static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5406{
d62a17ae 5407 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5408 && CHECK_FLAG(peer->af_cap[afi][safi],
5409 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5410}
5411
718e3744 5412/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5413 value. */
d62a17ae 5414int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5415 struct bgp_nlri *packet)
5416{
d7c0a89a
QY
5417 uint8_t *pnt;
5418 uint8_t *lim;
d62a17ae 5419 struct prefix p;
5420 int psize;
5421 int ret;
5422 afi_t afi;
5423 safi_t safi;
5424 int addpath_encoded;
d7c0a89a 5425 uint32_t addpath_id;
d62a17ae 5426
d62a17ae 5427 pnt = packet->nlri;
5428 lim = pnt + packet->length;
5429 afi = packet->afi;
5430 safi = packet->safi;
5431 addpath_id = 0;
5432 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5433
5434 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5435 syntactic validity. If the field is syntactically incorrect,
5436 then the Error Subcode is set to Invalid Network Field. */
5437 for (; pnt < lim; pnt += psize) {
5438 /* Clear prefix structure. */
5439 memset(&p, 0, sizeof(struct prefix));
5440
5441 if (addpath_encoded) {
5442
5443 /* When packet overflow occurs return immediately. */
761ed665 5444 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5445 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5446
a3a850a1 5447 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5448 addpath_id = ntohl(addpath_id);
d62a17ae 5449 pnt += BGP_ADDPATH_ID_LEN;
5450 }
718e3744 5451
d62a17ae 5452 /* Fetch prefix length. */
5453 p.prefixlen = *pnt++;
5454 /* afi/safi validity already verified by caller,
5455 * bgp_update_receive */
5456 p.family = afi2family(afi);
5457
5458 /* Prefix length check. */
5459 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5460 flog_err(
e50f7cfd 5461 EC_BGP_UPDATE_RCV,
14454c9f 5462 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5463 peer->host, p.prefixlen, packet->afi);
513386b5 5464 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5465 }
6b0655a2 5466
d62a17ae 5467 /* Packet size overflow check. */
5468 psize = PSIZE(p.prefixlen);
5469
5470 /* When packet overflow occur return immediately. */
5471 if (pnt + psize > lim) {
af4c2728 5472 flog_err(
e50f7cfd 5473 EC_BGP_UPDATE_RCV,
d62a17ae 5474 "%s [Error] Update packet error (prefix length %d overflows packet)",
5475 peer->host, p.prefixlen);
513386b5 5476 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5477 }
5478
5479 /* Defensive coding, double-check the psize fits in a struct
5480 * prefix */
5481 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5482 flog_err(
e50f7cfd 5483 EC_BGP_UPDATE_RCV,
d62a17ae 5484 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5485 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5486 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5487 }
5488
5489 /* Fetch prefix from NLRI packet. */
a85297a7 5490 memcpy(p.u.val, pnt, psize);
d62a17ae 5491
5492 /* Check address. */
5493 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5494 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5495 /* From RFC4271 Section 6.3:
5496 *
5497 * If a prefix in the NLRI field is semantically
5498 * incorrect
5499 * (e.g., an unexpected multicast IP address),
5500 * an error SHOULD
5501 * be logged locally, and the prefix SHOULD be
5502 * ignored.
a4d82a8a 5503 */
af4c2728 5504 flog_err(
e50f7cfd 5505 EC_BGP_UPDATE_RCV,
23d0a753
DA
5506 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5507 peer->host, &p.u.prefix4);
d62a17ae 5508 continue;
5509 }
5510 }
5511
5512 /* Check address. */
5513 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5514 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5515 flog_err(
e50f7cfd 5516 EC_BGP_UPDATE_RCV,
c0d72166
DS
5517 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5518 peer->host, &p.u.prefix6);
d62a17ae 5519
5520 continue;
5521 }
5522 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5523 flog_err(
e50f7cfd 5524 EC_BGP_UPDATE_RCV,
c0d72166
DS
5525 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5526 peer->host, &p.u.prefix6);
d62a17ae 5527
5528 continue;
5529 }
5530 }
5531
5532 /* Normal process. */
5533 if (attr)
5534 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5535 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5536 NULL, NULL, 0, 0, NULL);
d62a17ae 5537 else
5538 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5539 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5540 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5541 NULL);
d62a17ae 5542
513386b5
DA
5543 /* Do not send BGP notification twice when maximum-prefix count
5544 * overflow. */
5545 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5546 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5547
5548 /* Address family configuration mismatch. */
d62a17ae 5549 if (ret < 0)
513386b5 5550 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5551 }
5552
5553 /* Packet length consistency check. */
5554 if (pnt != lim) {
af4c2728 5555 flog_err(
e50f7cfd 5556 EC_BGP_UPDATE_RCV,
d62a17ae 5557 "%s [Error] Update packet error (prefix length mismatch with total length)",
5558 peer->host);
513386b5 5559 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5560 }
6b0655a2 5561
513386b5 5562 return BGP_NLRI_PARSE_OK;
718e3744 5563}
5564
d62a17ae 5565static struct bgp_static *bgp_static_new(void)
718e3744 5566{
d62a17ae 5567 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5568}
5569
d62a17ae 5570static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5571{
0a22ddfb 5572 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5573 route_map_counter_decrement(bgp_static->rmap.map);
5574
0a22ddfb 5575 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5576 XFREE(MTYPE_BGP_STATIC, bgp_static);
5577}
5578
5f040085 5579void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5580 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5581{
9bcb3eef 5582 struct bgp_dest *dest;
40381db7 5583 struct bgp_path_info *pi;
4b7e6066 5584 struct bgp_path_info *new;
40381db7 5585 struct bgp_path_info rmap_path;
d62a17ae 5586 struct attr attr;
5587 struct attr *attr_new;
b68885f9 5588 route_map_result_t ret;
49e5a4a0 5589#ifdef ENABLE_BGP_VNC
d62a17ae 5590 int vnc_implicit_withdraw = 0;
65efcfce 5591#endif
fee0f4c6 5592
d62a17ae 5593 assert(bgp_static);
dd8103a9 5594
9bcb3eef 5595 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5596
d62a17ae 5597 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5598
d62a17ae 5599 attr.nexthop = bgp_static->igpnexthop;
5600 attr.med = bgp_static->igpmetric;
5601 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5602
d62a17ae 5603 if (bgp_static->atomic)
5604 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5605
d62a17ae 5606 /* Store label index, if required. */
5607 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5608 attr.label_index = bgp_static->label_index;
5609 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5610 }
718e3744 5611
d62a17ae 5612 /* Apply route-map. */
5613 if (bgp_static->rmap.name) {
5614 struct attr attr_tmp = attr;
80ced710 5615
40381db7
DS
5616 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5617 rmap_path.peer = bgp->peer_self;
5618 rmap_path.attr = &attr_tmp;
fee0f4c6 5619
d62a17ae 5620 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5621
1782514f 5622 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5623
d62a17ae 5624 bgp->peer_self->rmap_type = 0;
718e3744 5625
d62a17ae 5626 if (ret == RMAP_DENYMATCH) {
5627 /* Free uninterned attribute. */
5628 bgp_attr_flush(&attr_tmp);
718e3744 5629
d62a17ae 5630 /* Unintern original. */
5631 aspath_unintern(&attr.aspath);
5632 bgp_static_withdraw(bgp, p, afi, safi);
5633 return;
5634 }
7f323236 5635
637e5ba4 5636 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5637 bgp_attr_add_gshut_community(&attr_tmp);
5638
d62a17ae 5639 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5640 } else {
5641
637e5ba4 5642 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5643 bgp_attr_add_gshut_community(&attr);
5644
d62a17ae 5645 attr_new = bgp_attr_intern(&attr);
7f323236 5646 }
718e3744 5647
9bcb3eef 5648 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5649 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5650 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5651 break;
5652
40381db7
DS
5653 if (pi) {
5654 if (attrhash_cmp(pi->attr, attr_new)
5655 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5656 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5657 bgp_dest_unlock_node(dest);
d62a17ae 5658 bgp_attr_unintern(&attr_new);
5659 aspath_unintern(&attr.aspath);
5660 return;
5661 } else {
5662 /* The attribute is changed. */
9bcb3eef 5663 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5664
5665 /* Rewrite BGP route information. */
40381db7 5666 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5667 bgp_path_info_restore(dest, pi);
d62a17ae 5668 else
40381db7 5669 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5670#ifdef ENABLE_BGP_VNC
d62a17ae 5671 if ((afi == AFI_IP || afi == AFI_IP6)
5672 && (safi == SAFI_UNICAST)) {
40381db7 5673 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5674 /*
5675 * Implicit withdraw case.
40381db7 5676 * We have to do this before pi is
d62a17ae 5677 * changed
5678 */
5679 ++vnc_implicit_withdraw;
40381db7 5680 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5681 vnc_import_bgp_exterior_del_route(
40381db7 5682 bgp, p, pi);
d62a17ae 5683 }
5684 }
65efcfce 5685#endif
40381db7
DS
5686 bgp_attr_unintern(&pi->attr);
5687 pi->attr = attr_new;
5688 pi->uptime = bgp_clock();
49e5a4a0 5689#ifdef ENABLE_BGP_VNC
d62a17ae 5690 if ((afi == AFI_IP || afi == AFI_IP6)
5691 && (safi == SAFI_UNICAST)) {
5692 if (vnc_implicit_withdraw) {
40381db7 5693 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5694 vnc_import_bgp_exterior_add_route(
40381db7 5695 bgp, p, pi);
d62a17ae 5696 }
5697 }
65efcfce 5698#endif
718e3744 5699
d62a17ae 5700 /* Nexthop reachability check. */
892fedb6 5701 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5702 && (safi == SAFI_UNICAST
5703 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5704
5705 struct bgp *bgp_nexthop = bgp;
5706
40381db7
DS
5707 if (pi->extra && pi->extra->bgp_orig)
5708 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5709
5710 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952
PR
5711 afi, safi, pi, NULL,
5712 0))
9bcb3eef 5713 bgp_path_info_set_flag(dest, pi,
18ee8310 5714 BGP_PATH_VALID);
d62a17ae 5715 else {
5716 if (BGP_DEBUG(nht, NHT)) {
5717 char buf1[INET6_ADDRSTRLEN];
5718 inet_ntop(p->family,
5719 &p->u.prefix, buf1,
5720 INET6_ADDRSTRLEN);
5721 zlog_debug(
5722 "%s(%s): Route not in table, not advertising",
15569c58 5723 __func__, buf1);
d62a17ae 5724 }
18ee8310 5725 bgp_path_info_unset_flag(
9bcb3eef 5726 dest, pi, BGP_PATH_VALID);
d62a17ae 5727 }
5728 } else {
5729 /* Delete the NHT structure if any, if we're
5730 * toggling between
5731 * enabling/disabling import check. We
5732 * deregister the route
5733 * from NHT to avoid overloading NHT and the
5734 * process interaction
5735 */
40381db7 5736 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5737 bgp_path_info_set_flag(dest, pi,
5738 BGP_PATH_VALID);
d62a17ae 5739 }
5740 /* Process change. */
40381db7 5741 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5742 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5743
5744 if (SAFI_UNICAST == safi
5745 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5746 || bgp->inst_type
5747 == BGP_INSTANCE_TYPE_DEFAULT)) {
5748 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5749 pi);
ddb5b488
PZ
5750 }
5751
9bcb3eef 5752 bgp_dest_unlock_node(dest);
d62a17ae 5753 aspath_unintern(&attr.aspath);
5754 return;
5755 }
718e3744 5756 }
718e3744 5757
d62a17ae 5758 /* Make new BGP info. */
5759 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5760 attr_new, dest);
d62a17ae 5761 /* Nexthop reachability check. */
892fedb6 5762 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5763 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
4053e952 5764 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0))
9bcb3eef 5765 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5766 else {
5767 if (BGP_DEBUG(nht, NHT)) {
5768 char buf1[INET6_ADDRSTRLEN];
5769 inet_ntop(p->family, &p->u.prefix, buf1,
5770 INET6_ADDRSTRLEN);
5771 zlog_debug(
5772 "%s(%s): Route not in table, not advertising",
15569c58 5773 __func__, buf1);
d62a17ae 5774 }
9bcb3eef 5775 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5776 }
5777 } else {
5778 /* Delete the NHT structure if any, if we're toggling between
5779 * enabling/disabling import check. We deregister the route
5780 * from NHT to avoid overloading NHT and the process interaction
5781 */
5782 bgp_unlink_nexthop(new);
5783
9bcb3eef 5784 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5785 }
078430f6 5786
d62a17ae 5787 /* Aggregate address increment. */
5788 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5789
d62a17ae 5790 /* Register new BGP information. */
9bcb3eef 5791 bgp_path_info_add(dest, new);
718e3744 5792
d62a17ae 5793 /* route_node_get lock */
9bcb3eef 5794 bgp_dest_unlock_node(dest);
d62a17ae 5795
5796 /* Process change. */
9bcb3eef 5797 bgp_process(bgp, dest, afi, safi);
d62a17ae 5798
ddb5b488
PZ
5799 if (SAFI_UNICAST == safi
5800 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5801 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5802 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5803 }
5804
d62a17ae 5805 /* Unintern original. */
5806 aspath_unintern(&attr.aspath);
718e3744 5807}
5808
5f040085 5809void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5810 safi_t safi)
718e3744 5811{
9bcb3eef 5812 struct bgp_dest *dest;
40381db7 5813 struct bgp_path_info *pi;
718e3744 5814
9bcb3eef 5815 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5816
d62a17ae 5817 /* Check selected route and self inserted route. */
9bcb3eef 5818 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5819 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5820 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5821 break;
5822
5823 /* Withdraw static BGP route from routing table. */
40381db7 5824 if (pi) {
ddb5b488
PZ
5825 if (SAFI_UNICAST == safi
5826 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5827 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5828 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5829 }
40381db7
DS
5830 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5831 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5832 bgp_path_info_delete(dest, pi);
5833 bgp_process(bgp, dest, afi, safi);
d62a17ae 5834 }
718e3744 5835
d62a17ae 5836 /* Unlock bgp_node_lookup. */
9bcb3eef 5837 bgp_dest_unlock_node(dest);
718e3744 5838}
5839
137446f9
LB
5840/*
5841 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5842 */
5f040085 5843static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5844 afi_t afi, safi_t safi,
5845 struct prefix_rd *prd)
718e3744 5846{
9bcb3eef 5847 struct bgp_dest *dest;
40381db7 5848 struct bgp_path_info *pi;
718e3744 5849
9bcb3eef 5850 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5851
d62a17ae 5852 /* Check selected route and self inserted route. */
9bcb3eef 5853 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5854 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5855 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5856 break;
718e3744 5857
d62a17ae 5858 /* Withdraw static BGP route from routing table. */
40381db7 5859 if (pi) {
49e5a4a0 5860#ifdef ENABLE_BGP_VNC
d62a17ae 5861 rfapiProcessWithdraw(
40381db7 5862 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5863 1); /* Kill, since it is an administrative change */
65efcfce 5864#endif
ddb5b488
PZ
5865 if (SAFI_MPLS_VPN == safi
5866 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5867 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5868 }
40381db7 5869 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5870 bgp_path_info_delete(dest, pi);
5871 bgp_process(bgp, dest, afi, safi);
d62a17ae 5872 }
718e3744 5873
d62a17ae 5874 /* Unlock bgp_node_lookup. */
9bcb3eef 5875 bgp_dest_unlock_node(dest);
718e3744 5876}
5877
5f040085 5878static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5879 struct bgp_static *bgp_static, afi_t afi,
5880 safi_t safi)
137446f9 5881{
9bcb3eef 5882 struct bgp_dest *dest;
4b7e6066 5883 struct bgp_path_info *new;
d62a17ae 5884 struct attr *attr_new;
5885 struct attr attr = {0};
40381db7 5886 struct bgp_path_info *pi;
49e5a4a0 5887#ifdef ENABLE_BGP_VNC
d62a17ae 5888 mpls_label_t label = 0;
65efcfce 5889#endif
d7c0a89a 5890 uint32_t num_labels = 0;
d62a17ae 5891 union gw_addr add;
137446f9 5892
d62a17ae 5893 assert(bgp_static);
137446f9 5894
b57ba6d2
MK
5895 if (bgp_static->label != MPLS_INVALID_LABEL)
5896 num_labels = 1;
9bcb3eef
DS
5897 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5898 &bgp_static->prd);
137446f9 5899
d62a17ae 5900 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5901
d62a17ae 5902 attr.nexthop = bgp_static->igpnexthop;
5903 attr.med = bgp_static->igpmetric;
5904 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5905
d62a17ae 5906 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5907 || (safi == SAFI_ENCAP)) {
5908 if (afi == AFI_IP) {
5909 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5910 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5911 }
5912 }
5913 if (afi == AFI_L2VPN) {
5914 if (bgp_static->gatewayIp.family == AF_INET)
5915 add.ipv4.s_addr =
5916 bgp_static->gatewayIp.u.prefix4.s_addr;
5917 else if (bgp_static->gatewayIp.family == AF_INET6)
5918 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5919 sizeof(struct in6_addr));
0a50c248 5920 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5921 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5922 struct bgp_encap_type_vxlan bet;
5923 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5924 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5925 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5926 }
5927 if (bgp_static->router_mac) {
5928 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5929 }
5930 }
5931 /* Apply route-map. */
5932 if (bgp_static->rmap.name) {
5933 struct attr attr_tmp = attr;
40381db7 5934 struct bgp_path_info rmap_path;
b68885f9 5935 route_map_result_t ret;
137446f9 5936
40381db7
DS
5937 rmap_path.peer = bgp->peer_self;
5938 rmap_path.attr = &attr_tmp;
137446f9 5939
d62a17ae 5940 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 5941
1782514f 5942 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 5943
d62a17ae 5944 bgp->peer_self->rmap_type = 0;
137446f9 5945
d62a17ae 5946 if (ret == RMAP_DENYMATCH) {
5947 /* Free uninterned attribute. */
5948 bgp_attr_flush(&attr_tmp);
137446f9 5949
d62a17ae 5950 /* Unintern original. */
5951 aspath_unintern(&attr.aspath);
5952 bgp_static_withdraw_safi(bgp, p, afi, safi,
5953 &bgp_static->prd);
5954 return;
5955 }
137446f9 5956
d62a17ae 5957 attr_new = bgp_attr_intern(&attr_tmp);
5958 } else {
5959 attr_new = bgp_attr_intern(&attr);
5960 }
137446f9 5961
9bcb3eef 5962 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5963 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5964 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5965 break;
5966
40381db7 5967 if (pi) {
d62a17ae 5968 memset(&add, 0, sizeof(union gw_addr));
40381db7 5969 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 5970 && overlay_index_equal(afi, pi, &add)
40381db7 5971 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 5972 bgp_dest_unlock_node(dest);
d62a17ae 5973 bgp_attr_unintern(&attr_new);
5974 aspath_unintern(&attr.aspath);
5975 return;
5976 } else {
5977 /* The attribute is changed. */
9bcb3eef 5978 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5979
5980 /* Rewrite BGP route information. */
40381db7 5981 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5982 bgp_path_info_restore(dest, pi);
d62a17ae 5983 else
40381db7
DS
5984 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5985 bgp_attr_unintern(&pi->attr);
5986 pi->attr = attr_new;
5987 pi->uptime = bgp_clock();
49e5a4a0 5988#ifdef ENABLE_BGP_VNC
40381db7
DS
5989 if (pi->extra)
5990 label = decode_label(&pi->extra->label[0]);
65efcfce 5991#endif
137446f9 5992
d62a17ae 5993 /* Process change. */
40381db7 5994 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5995 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5996
5997 if (SAFI_MPLS_VPN == safi
5998 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5999 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6000 }
49e5a4a0 6001#ifdef ENABLE_BGP_VNC
40381db7
DS
6002 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6003 pi->attr, afi, safi, pi->type,
6004 pi->sub_type, &label);
65efcfce 6005#endif
9bcb3eef 6006 bgp_dest_unlock_node(dest);
d62a17ae 6007 aspath_unintern(&attr.aspath);
6008 return;
6009 }
6010 }
137446f9
LB
6011
6012
d62a17ae 6013 /* Make new BGP info. */
6014 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6015 attr_new, dest);
1defdda8 6016 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 6017 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
6018 if (num_labels) {
6019 new->extra->label[0] = bgp_static->label;
6020 new->extra->num_labels = num_labels;
6021 }
49e5a4a0 6022#ifdef ENABLE_BGP_VNC
d62a17ae 6023 label = decode_label(&bgp_static->label);
65efcfce 6024#endif
137446f9 6025
d62a17ae 6026 /* Aggregate address increment. */
6027 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6028
d62a17ae 6029 /* Register new BGP information. */
9bcb3eef 6030 bgp_path_info_add(dest, new);
d62a17ae 6031 /* route_node_get lock */
9bcb3eef 6032 bgp_dest_unlock_node(dest);
137446f9 6033
d62a17ae 6034 /* Process change. */
9bcb3eef 6035 bgp_process(bgp, dest, afi, safi);
137446f9 6036
ddb5b488
PZ
6037 if (SAFI_MPLS_VPN == safi
6038 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6039 vpn_leak_to_vrf_update(bgp, new);
6040 }
49e5a4a0 6041#ifdef ENABLE_BGP_VNC
d62a17ae 6042 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6043 safi, new->type, new->sub_type, &label);
65efcfce
LB
6044#endif
6045
d62a17ae 6046 /* Unintern original. */
6047 aspath_unintern(&attr.aspath);
137446f9
LB
6048}
6049
718e3744 6050/* Configure static BGP network. When user don't run zebra, static
6051 route should be installed as valid. */
37a87b8f
CS
6052int bgp_static_set(struct bgp *bgp, const char *negate, struct prefix *pfx,
6053 afi_t afi, safi_t safi, const char *rmap, int backdoor,
6054 uint32_t label_index, char *errmsg, size_t errmsg_len)
d62a17ae 6055{
d62a17ae 6056 struct prefix p;
6057 struct bgp_static *bgp_static;
9bcb3eef 6058 struct bgp_dest *dest;
d7c0a89a 6059 uint8_t need_update = 0;
d62a17ae 6060
37a87b8f 6061 prefix_copy(&p, pfx);
d62a17ae 6062 apply_mask(&p);
718e3744 6063
e2a86ad9 6064 if (negate) {
718e3744 6065
e2a86ad9 6066 /* Set BGP static route configuration. */
9bcb3eef 6067 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6068
9bcb3eef 6069 if (!dest) {
37a87b8f
CS
6070 snprintf(errmsg, errmsg_len,
6071 "Can't find static route specified\n");
6072 return -1;
d62a17ae 6073 }
6074
9bcb3eef 6075 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6076
e2a86ad9
DS
6077 if ((label_index != BGP_INVALID_LABEL_INDEX)
6078 && (label_index != bgp_static->label_index)) {
37a87b8f
CS
6079 snprintf(errmsg, errmsg_len,
6080 "label-index doesn't match static route\n");
6081 return -1;
d62a17ae 6082 }
d62a17ae 6083
e2a86ad9
DS
6084 if ((rmap && bgp_static->rmap.name)
6085 && strcmp(rmap, bgp_static->rmap.name)) {
37a87b8f
CS
6086 snprintf(errmsg, errmsg_len,
6087 "route-map name doesn't match static route\n");
6088 return -1;
d62a17ae 6089 }
718e3744 6090
e2a86ad9
DS
6091 /* Update BGP RIB. */
6092 if (!bgp_static->backdoor)
6093 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6094
e2a86ad9
DS
6095 /* Clear configuration. */
6096 bgp_static_free(bgp_static);
9bcb3eef
DS
6097 bgp_dest_set_bgp_static_info(dest, NULL);
6098 bgp_dest_unlock_node(dest);
6099 bgp_dest_unlock_node(dest);
e2a86ad9 6100 } else {
718e3744 6101
e2a86ad9 6102 /* Set BGP static route configuration. */
9bcb3eef
DS
6103 dest = bgp_node_get(bgp->route[afi][safi], &p);
6104 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6105 if (bgp_static) {
e2a86ad9 6106 /* Configuration change. */
e2a86ad9
DS
6107 /* Label index cannot be changed. */
6108 if (bgp_static->label_index != label_index) {
37a87b8f
CS
6109 snprintf(errmsg, errmsg_len,
6110 "cannot change label-index\n");
6111 return -1;
e2a86ad9 6112 }
d62a17ae 6113
e2a86ad9 6114 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6115 if (bgp_static->valid
6116 && bgp_static->backdoor != backdoor)
e2a86ad9 6117 need_update = 1;
718e3744 6118
e2a86ad9 6119 bgp_static->backdoor = backdoor;
718e3744 6120
e2a86ad9 6121 if (rmap) {
0a22ddfb
QY
6122 XFREE(MTYPE_ROUTE_MAP_NAME,
6123 bgp_static->rmap.name);
b4897fa5 6124 route_map_counter_decrement(
6125 bgp_static->rmap.map);
e2a86ad9
DS
6126 bgp_static->rmap.name =
6127 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6128 bgp_static->rmap.map =
6129 route_map_lookup_by_name(rmap);
b4897fa5 6130 route_map_counter_increment(
6131 bgp_static->rmap.map);
e2a86ad9 6132 } else {
0a22ddfb
QY
6133 XFREE(MTYPE_ROUTE_MAP_NAME,
6134 bgp_static->rmap.name);
b4897fa5 6135 route_map_counter_decrement(
6136 bgp_static->rmap.map);
e2a86ad9
DS
6137 bgp_static->rmap.map = NULL;
6138 bgp_static->valid = 0;
6139 }
9bcb3eef 6140 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6141 } else {
6142 /* New configuration. */
6143 bgp_static = bgp_static_new();
6144 bgp_static->backdoor = backdoor;
6145 bgp_static->valid = 0;
6146 bgp_static->igpmetric = 0;
975a328e 6147 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6148 bgp_static->label_index = label_index;
718e3744 6149
e2a86ad9 6150 if (rmap) {
0a22ddfb
QY
6151 XFREE(MTYPE_ROUTE_MAP_NAME,
6152 bgp_static->rmap.name);
b4897fa5 6153 route_map_counter_decrement(
6154 bgp_static->rmap.map);
e2a86ad9
DS
6155 bgp_static->rmap.name =
6156 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6157 bgp_static->rmap.map =
6158 route_map_lookup_by_name(rmap);
b4897fa5 6159 route_map_counter_increment(
6160 bgp_static->rmap.map);
e2a86ad9 6161 }
9bcb3eef 6162 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6163 }
d62a17ae 6164
e2a86ad9
DS
6165 bgp_static->valid = 1;
6166 if (need_update)
6167 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6168
e2a86ad9
DS
6169 if (!bgp_static->backdoor)
6170 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6171 }
d62a17ae 6172
37a87b8f 6173 return 0;
d62a17ae 6174}
6175
6176void bgp_static_add(struct bgp *bgp)
6177{
6178 afi_t afi;
6179 safi_t safi;
9bcb3eef
DS
6180 struct bgp_dest *dest;
6181 struct bgp_dest *rm;
d62a17ae 6182 struct bgp_table *table;
6183 struct bgp_static *bgp_static;
6184
05c7a1cc 6185 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6186 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6187 dest = bgp_route_next(dest)) {
6188 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6189 continue;
ea47320b 6190
05c7a1cc
QY
6191 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6192 || (safi == SAFI_EVPN)) {
9bcb3eef 6193 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6194
6195 for (rm = bgp_table_top(table); rm;
6196 rm = bgp_route_next(rm)) {
a78beeb5 6197 bgp_static =
9bcb3eef 6198 bgp_dest_get_bgp_static_info(
5a8ba9fc 6199 rm);
9bcb3eef
DS
6200 bgp_static_update_safi(
6201 bgp, bgp_dest_get_prefix(rm),
6202 bgp_static, afi, safi);
d62a17ae 6203 }
05c7a1cc 6204 } else {
5a8ba9fc 6205 bgp_static_update(
9bcb3eef
DS
6206 bgp, bgp_dest_get_prefix(dest),
6207 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6208 safi);
ea47320b 6209 }
05c7a1cc 6210 }
6aeb9e78
DS
6211}
6212
718e3744 6213/* Called from bgp_delete(). Delete all static routes from the BGP
6214 instance. */
d62a17ae 6215void bgp_static_delete(struct bgp *bgp)
6216{
6217 afi_t afi;
6218 safi_t safi;
9bcb3eef
DS
6219 struct bgp_dest *dest;
6220 struct bgp_dest *rm;
d62a17ae 6221 struct bgp_table *table;
6222 struct bgp_static *bgp_static;
6223
05c7a1cc 6224 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6225 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6226 dest = bgp_route_next(dest)) {
6227 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6228 continue;
ea47320b 6229
05c7a1cc
QY
6230 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6231 || (safi == SAFI_EVPN)) {
9bcb3eef 6232 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6233
6234 for (rm = bgp_table_top(table); rm;
6235 rm = bgp_route_next(rm)) {
a78beeb5 6236 bgp_static =
9bcb3eef 6237 bgp_dest_get_bgp_static_info(
5a8ba9fc 6238 rm);
c7d14ba6
PG
6239 if (!bgp_static)
6240 continue;
6241
05c7a1cc 6242 bgp_static_withdraw_safi(
9bcb3eef 6243 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6244 AFI_IP, safi,
6245 (struct prefix_rd *)
9bcb3eef
DS
6246 bgp_dest_get_prefix(
6247 dest));
ea47320b 6248 bgp_static_free(bgp_static);
811c6797 6249 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6250 NULL);
811c6797 6251 bgp_dest_unlock_node(rm);
d62a17ae 6252 }
05c7a1cc 6253 } else {
9bcb3eef 6254 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6255 bgp_static_withdraw(bgp,
9bcb3eef 6256 bgp_dest_get_prefix(dest),
b54892e0 6257 afi, safi);
05c7a1cc 6258 bgp_static_free(bgp_static);
9bcb3eef
DS
6259 bgp_dest_set_bgp_static_info(dest, NULL);
6260 bgp_dest_unlock_node(dest);
ea47320b 6261 }
05c7a1cc 6262 }
d62a17ae 6263}
6264
6265void bgp_static_redo_import_check(struct bgp *bgp)
6266{
6267 afi_t afi;
6268 safi_t safi;
9bcb3eef
DS
6269 struct bgp_dest *dest;
6270 struct bgp_dest *rm;
d62a17ae 6271 struct bgp_table *table;
6272 struct bgp_static *bgp_static;
6273
6274 /* Use this flag to force reprocessing of the route */
892fedb6 6275 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6276 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6277 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6278 dest = bgp_route_next(dest)) {
6279 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6280 continue;
ea47320b 6281
05c7a1cc
QY
6282 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6283 || (safi == SAFI_EVPN)) {
9bcb3eef 6284 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6285
6286 for (rm = bgp_table_top(table); rm;
6287 rm = bgp_route_next(rm)) {
a78beeb5 6288 bgp_static =
9bcb3eef 6289 bgp_dest_get_bgp_static_info(
5a8ba9fc 6290 rm);
9bcb3eef
DS
6291 bgp_static_update_safi(
6292 bgp, bgp_dest_get_prefix(rm),
6293 bgp_static, afi, safi);
d62a17ae 6294 }
05c7a1cc 6295 } else {
9bcb3eef
DS
6296 bgp_static = bgp_dest_get_bgp_static_info(dest);
6297 bgp_static_update(bgp,
6298 bgp_dest_get_prefix(dest),
6299 bgp_static, afi, safi);
ea47320b 6300 }
05c7a1cc
QY
6301 }
6302 }
892fedb6 6303 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6304}
6305
6306static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6307 safi_t safi)
6308{
6309 struct bgp_table *table;
9bcb3eef 6310 struct bgp_dest *dest;
40381db7 6311 struct bgp_path_info *pi;
d62a17ae 6312
dfb6fd1d
NT
6313 /* Do not install the aggregate route if BGP is in the
6314 * process of termination.
6315 */
892fedb6
DA
6316 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6317 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6318 return;
6319
d62a17ae 6320 table = bgp->rib[afi][safi];
9bcb3eef
DS
6321 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6322 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6323 if (pi->peer == bgp->peer_self
6324 && ((pi->type == ZEBRA_ROUTE_BGP
6325 && pi->sub_type == BGP_ROUTE_STATIC)
6326 || (pi->type != ZEBRA_ROUTE_BGP
6327 && pi->sub_type
d62a17ae 6328 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6329 bgp_aggregate_decrement(
6330 bgp, bgp_dest_get_prefix(dest), pi, afi,
6331 safi);
40381db7 6332 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6333 bgp_path_info_delete(dest, pi);
6334 bgp_process(bgp, dest, afi, safi);
d62a17ae 6335 }
6336 }
6337 }
ad4cbda1 6338}
6339
6340/*
6341 * Purge all networks and redistributed routes from routing table.
6342 * Invoked upon the instance going down.
6343 */
d62a17ae 6344void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6345{
d62a17ae 6346 afi_t afi;
6347 safi_t safi;
ad4cbda1 6348
05c7a1cc
QY
6349 FOREACH_AFI_SAFI (afi, safi)
6350 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6351}
6352
137446f9
LB
6353/*
6354 * gpz 110624
6355 * Currently this is used to set static routes for VPN and ENCAP.
6356 * I think it can probably be factored with bgp_static_set.
6357 */
d62a17ae 6358int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6359 const char *ip_str, const char *rd_str,
6360 const char *label_str, const char *rmap_str,
6361 int evpn_type, const char *esi, const char *gwip,
6362 const char *ethtag, const char *routermac)
6363{
6364 VTY_DECLVAR_CONTEXT(bgp, bgp);
6365 int ret;
6366 struct prefix p;
6367 struct prefix_rd prd;
9bcb3eef
DS
6368 struct bgp_dest *pdest;
6369 struct bgp_dest *dest;
d62a17ae 6370 struct bgp_table *table;
6371 struct bgp_static *bgp_static;
6372 mpls_label_t label = MPLS_INVALID_LABEL;
6373 struct prefix gw_ip;
6374
6375 /* validate ip prefix */
6376 ret = str2prefix(ip_str, &p);
6377 if (!ret) {
6378 vty_out(vty, "%% Malformed prefix\n");
6379 return CMD_WARNING_CONFIG_FAILED;
6380 }
6381 apply_mask(&p);
6382 if ((afi == AFI_L2VPN)
6383 && (bgp_build_evpn_prefix(evpn_type,
6384 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6385 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6386 return CMD_WARNING_CONFIG_FAILED;
6387 }
718e3744 6388
d62a17ae 6389 ret = str2prefix_rd(rd_str, &prd);
6390 if (!ret) {
6391 vty_out(vty, "%% Malformed rd\n");
6392 return CMD_WARNING_CONFIG_FAILED;
6393 }
718e3744 6394
d62a17ae 6395 if (label_str) {
6396 unsigned long label_val;
6397 label_val = strtoul(label_str, NULL, 10);
6398 encode_label(label_val, &label);
6399 }
9bedbb1e 6400
d62a17ae 6401 if (safi == SAFI_EVPN) {
6402 if (esi && str2esi(esi, NULL) == 0) {
6403 vty_out(vty, "%% Malformed ESI\n");
6404 return CMD_WARNING_CONFIG_FAILED;
6405 }
6406 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6407 vty_out(vty, "%% Malformed Router MAC\n");
6408 return CMD_WARNING_CONFIG_FAILED;
6409 }
6410 if (gwip) {
6411 memset(&gw_ip, 0, sizeof(struct prefix));
6412 ret = str2prefix(gwip, &gw_ip);
6413 if (!ret) {
6414 vty_out(vty, "%% Malformed GatewayIp\n");
6415 return CMD_WARNING_CONFIG_FAILED;
6416 }
6417 if ((gw_ip.family == AF_INET
3714a385 6418 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6419 (struct prefix_evpn *)&p))
6420 || (gw_ip.family == AF_INET6
3714a385 6421 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6422 (struct prefix_evpn *)&p))) {
6423 vty_out(vty,
6424 "%% GatewayIp family differs with IP prefix\n");
6425 return CMD_WARNING_CONFIG_FAILED;
6426 }
6427 }
6428 }
9bcb3eef
DS
6429 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6430 if (!bgp_dest_has_bgp_path_info_data(pdest))
6431 bgp_dest_set_bgp_table_info(pdest,
67009e22 6432 bgp_table_init(bgp, afi, safi));
9bcb3eef 6433 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6434
9bcb3eef 6435 dest = bgp_node_get(table, &p);
d62a17ae 6436
9bcb3eef 6437 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6438 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6439 bgp_dest_unlock_node(dest);
d62a17ae 6440 } else {
6441 /* New configuration. */
6442 bgp_static = bgp_static_new();
6443 bgp_static->backdoor = 0;
6444 bgp_static->valid = 0;
6445 bgp_static->igpmetric = 0;
975a328e 6446 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6447 bgp_static->label = label;
6448 bgp_static->prd = prd;
6449
6450 if (rmap_str) {
0a22ddfb 6451 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6452 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6453 bgp_static->rmap.name =
6454 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6455 bgp_static->rmap.map =
6456 route_map_lookup_by_name(rmap_str);
b4897fa5 6457 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6458 }
718e3744 6459
d62a17ae 6460 if (safi == SAFI_EVPN) {
6461 if (esi) {
6462 bgp_static->eth_s_id =
6463 XCALLOC(MTYPE_ATTR,
0a50c248 6464 sizeof(esi_t));
d62a17ae 6465 str2esi(esi, bgp_static->eth_s_id);
6466 }
6467 if (routermac) {
6468 bgp_static->router_mac =
28328ea9 6469 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6470 (void)prefix_str2mac(routermac,
6471 bgp_static->router_mac);
d62a17ae 6472 }
6473 if (gwip)
6474 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6475 }
9bcb3eef 6476 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6477
d62a17ae 6478 bgp_static->valid = 1;
6479 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6480 }
718e3744 6481
d62a17ae 6482 return CMD_SUCCESS;
718e3744 6483}
6484
6485/* Configure static BGP network. */
d62a17ae 6486int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6487 const char *ip_str, const char *rd_str,
6488 const char *label_str, int evpn_type, const char *esi,
6489 const char *gwip, const char *ethtag)
6490{
6491 VTY_DECLVAR_CONTEXT(bgp, bgp);
6492 int ret;
6493 struct prefix p;
6494 struct prefix_rd prd;
9bcb3eef
DS
6495 struct bgp_dest *pdest;
6496 struct bgp_dest *dest;
d62a17ae 6497 struct bgp_table *table;
6498 struct bgp_static *bgp_static;
6499 mpls_label_t label = MPLS_INVALID_LABEL;
6500
6501 /* Convert IP prefix string to struct prefix. */
6502 ret = str2prefix(ip_str, &p);
6503 if (!ret) {
6504 vty_out(vty, "%% Malformed prefix\n");
6505 return CMD_WARNING_CONFIG_FAILED;
6506 }
6507 apply_mask(&p);
6508 if ((afi == AFI_L2VPN)
6509 && (bgp_build_evpn_prefix(evpn_type,
6510 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6511 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6512 return CMD_WARNING_CONFIG_FAILED;
6513 }
6514 ret = str2prefix_rd(rd_str, &prd);
6515 if (!ret) {
6516 vty_out(vty, "%% Malformed rd\n");
6517 return CMD_WARNING_CONFIG_FAILED;
6518 }
718e3744 6519
d62a17ae 6520 if (label_str) {
6521 unsigned long label_val;
6522 label_val = strtoul(label_str, NULL, 10);
6523 encode_label(label_val, &label);
6524 }
718e3744 6525
9bcb3eef
DS
6526 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6527 if (!bgp_dest_has_bgp_path_info_data(pdest))
6528 bgp_dest_set_bgp_table_info(pdest,
67009e22 6529 bgp_table_init(bgp, afi, safi));
d62a17ae 6530 else
9bcb3eef
DS
6531 bgp_dest_unlock_node(pdest);
6532 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6533
9bcb3eef 6534 dest = bgp_node_lookup(table, &p);
6b0655a2 6535
9bcb3eef 6536 if (dest) {
d62a17ae 6537 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6538
9bcb3eef 6539 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6540 bgp_static_free(bgp_static);
9bcb3eef
DS
6541 bgp_dest_set_bgp_static_info(dest, NULL);
6542 bgp_dest_unlock_node(dest);
6543 bgp_dest_unlock_node(dest);
d62a17ae 6544 } else
6545 vty_out(vty, "%% Can't find the route\n");
6546
6547 return CMD_SUCCESS;
6548}
6549
6550static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6551 const char *rmap_name)
6552{
6553 VTY_DECLVAR_CONTEXT(bgp, bgp);
6554 struct bgp_rmap *rmap;
6555
6556 rmap = &bgp->table_map[afi][safi];
6557 if (rmap_name) {
0a22ddfb 6558 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6559 route_map_counter_decrement(rmap->map);
d62a17ae 6560 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6561 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6562 route_map_counter_increment(rmap->map);
d62a17ae 6563 } else {
0a22ddfb 6564 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6565 route_map_counter_decrement(rmap->map);
d62a17ae 6566 rmap->map = NULL;
6567 }
73ac8160 6568
d62a17ae 6569 if (bgp_fibupd_safi(safi))
6570 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6571
d62a17ae 6572 return CMD_SUCCESS;
73ac8160
DS
6573}
6574
d62a17ae 6575static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6576 const char *rmap_name)
73ac8160 6577{
d62a17ae 6578 VTY_DECLVAR_CONTEXT(bgp, bgp);
6579 struct bgp_rmap *rmap;
73ac8160 6580
d62a17ae 6581 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6582 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6583 route_map_counter_decrement(rmap->map);
d62a17ae 6584 rmap->map = NULL;
73ac8160 6585
d62a17ae 6586 if (bgp_fibupd_safi(safi))
6587 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6588
d62a17ae 6589 return CMD_SUCCESS;
73ac8160
DS
6590}
6591
2b791107 6592void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6593 safi_t safi)
73ac8160 6594{
d62a17ae 6595 if (bgp->table_map[afi][safi].name) {
d62a17ae 6596 vty_out(vty, " table-map %s\n",
6597 bgp->table_map[afi][safi].name);
6598 }
73ac8160
DS
6599}
6600
73ac8160
DS
6601DEFUN (bgp_table_map,
6602 bgp_table_map_cmd,
6603 "table-map WORD",
6604 "BGP table to RIB route download filter\n"
6605 "Name of the route map\n")
6606{
d62a17ae 6607 int idx_word = 1;
6608 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6609 argv[idx_word]->arg);
73ac8160
DS
6610}
6611DEFUN (no_bgp_table_map,
6612 no_bgp_table_map_cmd,
6613 "no table-map WORD",
3a2d747c 6614 NO_STR
73ac8160
DS
6615 "BGP table to RIB route download filter\n"
6616 "Name of the route map\n")
6617{
d62a17ae 6618 int idx_word = 2;
6619 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6620 argv[idx_word]->arg);
73ac8160
DS
6621}
6622
37a87b8f
CS
6623DEFPY_YANG (bgp_network, bgp_network_cmd,
6624 "[no] network \
6625 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6626 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6627 backdoor$backdoor}]",
6628 NO_STR
6629 "Specify a network to announce via BGP\n"
6630 "IPv4 prefix\n"
6631 "Network number\n"
6632 "Network mask\n"
6633 "Network mask\n"
6634 "Route-map to modify the attributes\n"
6635 "Name of the route map\n"
6636 "Label index to associate with the prefix\n"
6637 "Label index value\n"
6638 "Specify a BGP backdoor route\n")
6639{
6640 char addr_prefix_str[PREFIX_STRLEN];
6641 char base_xpath[XPATH_MAXLEN];
6642 afi_t afi;
6643 safi_t safi;
e2a86ad9
DS
6644
6645 if (address_str) {
6646 int ret;
718e3744 6647
e2a86ad9 6648 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6649 addr_prefix_str,
6650 sizeof(addr_prefix_str));
e2a86ad9
DS
6651 if (!ret) {
6652 vty_out(vty, "%% Inconsistent address and mask\n");
6653 return CMD_WARNING_CONFIG_FAILED;
6654 }
d62a17ae 6655 }
718e3744 6656
37a87b8f
CS
6657 afi = bgp_node_afi(vty);
6658 safi = bgp_node_safi(vty);
6659
6660 if (no) {
6661 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6662 } else {
6663 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6664
6665 if (map_name)
6666 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6667 NB_OP_CREATE, map_name);
6668 else
6669 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6670 NB_OP_DESTROY, NULL);
6671
6672 if (label_index_str)
6673 nb_cli_enqueue_change(vty, "./label-index",
6674 NB_OP_MODIFY, label_index_str);
6675
6676 nb_cli_enqueue_change(vty, "./backdoor", NB_OP_MODIFY,
6677 backdoor ? "true" : "false");
6678 }
6679
6680 snprintf(
6681 base_xpath, sizeof(base_xpath),
6682 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6683 yang_afi_safi_value2identity(afi, safi),
6684 bgp_afi_safi_get_container_str(afi, safi),
6685 address_str ? addr_prefix_str : prefix_str);
6686
6687 return nb_cli_apply_changes(vty, base_xpath);
718e3744 6688}
6689
37a87b8f
CS
6690DEFPY_YANG (ipv6_bgp_network,
6691 ipv6_bgp_network_cmd,
6692 "[no] network X:X::X:X/M$prefix \
6693 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6694 NO_STR
6695 "Specify a network to announce via BGP\n"
6696 "IPv6 prefix\n"
6697 "Route-map to modify the attributes\n"
6698 "Name of the route map\n"
6699 "Label index to associate with the prefix\n"
6700 "Label index value\n")
6701{
6702 char base_xpath[XPATH_MAXLEN];
6703 afi_t afi;
6704 safi_t safi;
6705
6706 afi = bgp_node_afi(vty);
6707 safi = bgp_node_safi(vty);
6708
6709 if (no) {
6710 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
6711 } else {
6712 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
6713
6714 if (map_name)
6715 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6716 NB_OP_MODIFY, map_name);
6717 else
6718 nb_cli_enqueue_change(vty, "./rmap-policy-export",
6719 NB_OP_DESTROY, NULL);
6720
6721 if (label_index_str)
6722 nb_cli_enqueue_change(vty, "./label-index",
6723 NB_OP_MODIFY, label_index_str);
6724 }
6725
6726 snprintf(
6727 base_xpath, sizeof(base_xpath),
6728 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/network-config[prefix='%s']",
6729 yang_afi_safi_value2identity(afi, safi),
6730 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
6731
6732 return nb_cli_apply_changes(vty, base_xpath);
6733}
6734
6735void cli_show_bgp_global_afi_safi_network_config(struct vty *vty,
6736 struct lyd_node *dnode,
6737 bool show_defaults)
718e3744 6738{
37a87b8f
CS
6739 vty_out(vty, " network %s", yang_dnode_get_string(dnode, "./prefix"));
6740
6741 if (yang_dnode_exists(dnode, "./label-index"))
6742 vty_out(vty, " label-index %s",
6743 yang_dnode_get_string(dnode, "./label-index"));
6744
6745 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
6746 vty_out(vty, " route-map %s",
6747 yang_dnode_get_string(dnode, "./rmap-policy-export"));
6748
6749 if (yang_dnode_get_bool(dnode, "./backdoor"))
6750 vty_out(vty, " backdoor");
6751
6752 vty_out(vty, "\n");
1b6d5c7e
VV
6753}
6754
d62a17ae 6755static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6756{
d62a17ae 6757 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6758}
6759
d62a17ae 6760static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6761{
365ab2e7
RZ
6762 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6763 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6764 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6765 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6766 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6767}
718e3744 6768
365ab2e7
RZ
6769/**
6770 * Helper function to avoid repeated code: prepare variables for a
6771 * `route_map_apply` call.
6772 *
6773 * \returns `true` on route map match, otherwise `false`.
6774 */
6775static bool aggr_suppress_map_test(struct bgp *bgp,
6776 struct bgp_aggregate *aggregate,
6777 struct bgp_path_info *pi)
6778{
6779 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6780 route_map_result_t rmr = RMAP_DENYMATCH;
6781 struct bgp_path_info rmap_path = {};
6782 struct attr attr = {};
6783
6784 /* No route map entries created, just don't match. */
6785 if (aggregate->suppress_map == NULL)
6786 return false;
6787
6788 /* Call route map matching and return result. */
6789 attr.aspath = aspath_empty();
6790 rmap_path.peer = bgp->peer_self;
6791 rmap_path.attr = &attr;
6792
6793 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6794 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6795 bgp->peer_self->rmap_type = 0;
6796
6797 bgp_attr_flush(&attr);
6798
6799 return rmr == RMAP_PERMITMATCH;
6800}
6801
4056a5f6
RZ
6802/** Test whether the aggregation has suppressed this path or not. */
6803static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6804 struct bgp_path_info *pi)
6805{
6806 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6807 return false;
6808
6809 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6810}
6811
6812/**
6813 * Suppress this path and keep the reference.
6814 *
6815 * \returns `true` if needs processing otherwise `false`.
6816 */
6817static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6818 struct bgp_path_info *pi)
6819{
6820 struct bgp_path_info_extra *pie;
6821
6822 /* Path is already suppressed by this aggregation. */
6823 if (aggr_suppress_exists(aggregate, pi))
6824 return false;
6825
6826 pie = bgp_path_info_extra_get(pi);
6827
6828 /* This is the first suppression, allocate memory and list it. */
6829 if (pie->aggr_suppressors == NULL)
6830 pie->aggr_suppressors = list_new();
6831
6832 listnode_add(pie->aggr_suppressors, aggregate);
6833
6834 /* Only mark for processing if suppressed. */
6835 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6836 if (BGP_DEBUG(update, UPDATE_OUT))
6837 zlog_debug("aggregate-address suppressing: %pFX",
6838 bgp_dest_get_prefix(pi->net));
6839
4056a5f6
RZ
6840 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6841 return true;
6842 }
6843
6844 return false;
6845}
6846
6847/**
6848 * Unsuppress this path and remove the reference.
6849 *
6850 * \returns `true` if needs processing otherwise `false`.
6851 */
6852static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6853 struct bgp_path_info *pi)
6854{
6855 /* Path wasn't suppressed. */
6856 if (!aggr_suppress_exists(aggregate, pi))
6857 return false;
6858
6859 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6860
6861 /* Unsuppress and free extra memory if last item. */
6862 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6863 if (BGP_DEBUG(update, UPDATE_OUT))
6864 zlog_debug("aggregate-address unsuppressing: %pFX",
6865 bgp_dest_get_prefix(pi->net));
6866
4056a5f6
RZ
6867 list_delete(&pi->extra->aggr_suppressors);
6868 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6869 return true;
6870 }
6871
6872 return false;
6873}
6874
3dc339cd
DA
6875static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6876 struct aspath *aspath,
6877 struct community *comm,
6878 struct ecommunity *ecomm,
6879 struct lcommunity *lcomm)
eaaf8adb
DS
6880{
6881 static struct aspath *ae = NULL;
6882
6883 if (!ae)
6884 ae = aspath_empty();
6885
40381db7 6886 if (!pi)
3dc339cd 6887 return false;
eaaf8adb 6888
40381db7 6889 if (origin != pi->attr->origin)
3dc339cd 6890 return false;
eaaf8adb 6891
40381db7 6892 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6893 return false;
29f7d023 6894
40381db7 6895 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6896 return false;
eaaf8adb 6897
3da2cc32 6898 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6899 return false;
eaaf8adb 6900
dd18c5a9 6901 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6902 return false;
dd18c5a9 6903
40381db7 6904 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6905 return false;
7ce8a8e0 6906
3dc339cd 6907 return true;
eaaf8adb
DS
6908}
6909
5f040085
DS
6910static void bgp_aggregate_install(
6911 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6912 uint8_t origin, struct aspath *aspath, struct community *community,
6913 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6914 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6915{
9bcb3eef 6916 struct bgp_dest *dest;
c701010e 6917 struct bgp_table *table;
6f94b685 6918 struct bgp_path_info *pi, *orig, *new;
20894f50 6919 struct attr *attr;
c701010e
DS
6920
6921 table = bgp->rib[afi][safi];
6922
9bcb3eef 6923 dest = bgp_node_get(table, p);
eaaf8adb 6924
9bcb3eef 6925 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6926 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6927 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6928 break;
6929
6aabb15d
RZ
6930 /*
6931 * If we have paths with different MEDs, then don't install
6932 * (or uninstall) the aggregate route.
6933 */
6934 if (aggregate->match_med && aggregate->med_mismatched)
6935 goto uninstall_aggregate_route;
6936
c701010e 6937 if (aggregate->count > 0) {
eaaf8adb
DS
6938 /*
6939 * If the aggregate information has not changed
6940 * no need to re-install it again.
6941 */
6f94b685 6942 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6943 ecommunity, lcommunity)) {
9bcb3eef 6944 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6945
6946 if (aspath)
6947 aspath_free(aspath);
6948 if (community)
3c1f53de 6949 community_free(&community);
3da2cc32
DS
6950 if (ecommunity)
6951 ecommunity_free(&ecommunity);
dd18c5a9
DS
6952 if (lcommunity)
6953 lcommunity_free(&lcommunity);
eaaf8adb
DS
6954
6955 return;
6956 }
6957
6958 /*
6959 * Mark the old as unusable
6960 */
40381db7 6961 if (pi)
9bcb3eef 6962 bgp_path_info_delete(dest, pi);
eaaf8adb 6963
20894f50
DA
6964 attr = bgp_attr_aggregate_intern(
6965 bgp, origin, aspath, community, ecommunity, lcommunity,
6966 aggregate, atomic_aggregate, p);
6967
6968 if (!attr) {
6969 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6970 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6971 zlog_debug("%s: %pFX null attribute", __func__,
6972 p);
20894f50
DA
6973 return;
6974 }
6975
3da2cc32 6976 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6977 bgp->peer_self, attr, dest);
20894f50 6978
1defdda8 6979 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6980
9bcb3eef
DS
6981 bgp_path_info_add(dest, new);
6982 bgp_process(bgp, dest, afi, safi);
c701010e 6983 } else {
6aabb15d 6984 uninstall_aggregate_route:
6f94b685 6985 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6986 if (pi->peer == bgp->peer_self
6987 && pi->type == ZEBRA_ROUTE_BGP
6988 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6989 break;
6990
6991 /* Withdraw static BGP route from routing table. */
40381db7 6992 if (pi) {
9bcb3eef
DS
6993 bgp_path_info_delete(dest, pi);
6994 bgp_process(bgp, dest, afi, safi);
c701010e
DS
6995 }
6996 }
6997
9bcb3eef 6998 bgp_dest_unlock_node(dest);
c701010e
DS
6999}
7000
6aabb15d
RZ
7001/**
7002 * Check if the current path has different MED than other known paths.
7003 *
7004 * \returns `true` if the MED matched the others else `false`.
7005 */
7006static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7007 struct bgp *bgp, struct bgp_path_info *pi)
7008{
7009 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7010
7011 /* This is the first route being analyzed. */
7012 if (!aggregate->med_initialized) {
7013 aggregate->med_initialized = true;
7014 aggregate->med_mismatched = false;
7015 aggregate->med_matched_value = cur_med;
7016 } else {
7017 /* Check if routes with different MED showed up. */
7018 if (cur_med != aggregate->med_matched_value)
7019 aggregate->med_mismatched = true;
7020 }
7021
7022 return !aggregate->med_mismatched;
7023}
7024
7025/**
7026 * Initializes and tests all routes in the aggregate address path for MED
7027 * values.
7028 *
7029 * \returns `true` if all MEDs are the same otherwise `false`.
7030 */
7031static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7032 struct bgp *bgp, const struct prefix *p,
7033 afi_t afi, safi_t safi)
7034{
7035 struct bgp_table *table = bgp->rib[afi][safi];
7036 const struct prefix *dest_p;
7037 struct bgp_dest *dest, *top;
7038 struct bgp_path_info *pi;
7039 bool med_matched = true;
7040
7041 aggregate->med_initialized = false;
7042
7043 top = bgp_node_get(table, p);
7044 for (dest = bgp_node_get(table, p); dest;
7045 dest = bgp_route_next_until(dest, top)) {
7046 dest_p = bgp_dest_get_prefix(dest);
7047 if (dest_p->prefixlen <= p->prefixlen)
7048 continue;
7049
7050 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7051 if (BGP_PATH_HOLDDOWN(pi))
7052 continue;
7053 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7054 continue;
7055 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7056 med_matched = false;
7057 break;
7058 }
7059 }
7060 if (!med_matched)
7061 break;
7062 }
7063 bgp_dest_unlock_node(top);
7064
7065 return med_matched;
7066}
7067
7068/**
7069 * Toggles the route suppression status for this aggregate address
7070 * configuration.
7071 */
4056a5f6
RZ
7072void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7073 struct bgp *bgp, const struct prefix *p,
7074 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7075{
7076 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7077 const struct prefix *dest_p;
7078 struct bgp_dest *dest, *top;
7079 struct bgp_path_info *pi;
7080 bool toggle_suppression;
7081
7082 /* We've found a different MED we must revert any suppressed routes. */
7083 top = bgp_node_get(table, p);
7084 for (dest = bgp_node_get(table, p); dest;
7085 dest = bgp_route_next_until(dest, top)) {
7086 dest_p = bgp_dest_get_prefix(dest);
7087 if (dest_p->prefixlen <= p->prefixlen)
7088 continue;
7089
7090 toggle_suppression = false;
7091 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7092 if (BGP_PATH_HOLDDOWN(pi))
7093 continue;
7094 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7095 continue;
7096
6aabb15d
RZ
7097 /* We are toggling suppression back. */
7098 if (suppress) {
6aabb15d 7099 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7100 if (aggr_suppress_path(aggregate, pi))
7101 toggle_suppression = true;
6aabb15d
RZ
7102 continue;
7103 }
7104
6aabb15d 7105 /* Install route if there is no more suppression. */
4056a5f6 7106 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7107 toggle_suppression = true;
6aabb15d
RZ
7108 }
7109
7110 if (toggle_suppression)
7111 bgp_process(bgp, dest, afi, safi);
7112 }
7113 bgp_dest_unlock_node(top);
7114}
7115
7116/**
7117 * Aggregate address MED matching incremental test: this function is called
7118 * when the initial aggregation occurred and we are only testing a single
7119 * new path.
7120 *
7121 * In addition to testing and setting the MED validity it also installs back
7122 * suppressed routes (if summary is configured).
7123 *
7124 * Must not be called in `bgp_aggregate_route`.
7125 */
7126static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7127 struct bgp *bgp, const struct prefix *p,
7128 afi_t afi, safi_t safi,
7129 struct bgp_path_info *pi, bool is_adding)
7130{
7131 /* MED matching disabled. */
7132 if (!aggregate->match_med)
7133 return;
7134
7135 /* Aggregation with different MED, nothing to do. */
7136 if (aggregate->med_mismatched)
7137 return;
7138
7139 /*
7140 * Test the current entry:
7141 *
7142 * is_adding == true: if the new entry doesn't match then we must
7143 * install all suppressed routes.
7144 *
7145 * is_adding == false: if the entry being removed was the last
7146 * unmatching entry then we can suppress all routes.
7147 */
7148 if (!is_adding) {
7149 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7150 && aggregate->summary_only)
7151 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7152 safi, true);
7153 } else
7154 bgp_aggregate_med_match(aggregate, bgp, pi);
7155
7156 /* No mismatches, just quit. */
7157 if (!aggregate->med_mismatched)
7158 return;
7159
7160 /* Route summarization is disabled. */
7161 if (!aggregate->summary_only)
7162 return;
7163
7164 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7165}
7166
b5d58c32 7167/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7168void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7169 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7170{
7171 struct bgp_table *table;
9bcb3eef
DS
7172 struct bgp_dest *top;
7173 struct bgp_dest *dest;
d7c0a89a 7174 uint8_t origin;
d62a17ae 7175 struct aspath *aspath = NULL;
d62a17ae 7176 struct community *community = NULL;
3da2cc32 7177 struct ecommunity *ecommunity = NULL;
dd18c5a9 7178 struct lcommunity *lcommunity = NULL;
40381db7 7179 struct bgp_path_info *pi;
d62a17ae 7180 unsigned long match = 0;
d7c0a89a 7181 uint8_t atomic_aggregate = 0;
d62a17ae 7182
9f822fa2
S
7183 /* If the bgp instance is being deleted or self peer is deleted
7184 * then do not create aggregate route
7185 */
892fedb6
DA
7186 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7187 || (bgp->peer_self == NULL))
9f822fa2
S
7188 return;
7189
6aabb15d
RZ
7190 /* Initialize and test routes for MED difference. */
7191 if (aggregate->match_med)
7192 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7193
4056a5f6
RZ
7194 /*
7195 * Reset aggregate count: we might've been called from route map
7196 * update so in that case we must retest all more specific routes.
7197 *
7198 * \see `bgp_route_map_process_update`.
7199 */
7200 aggregate->count = 0;
7201 aggregate->incomplete_origin_count = 0;
7202 aggregate->incomplete_origin_count = 0;
7203 aggregate->egp_origin_count = 0;
7204
d62a17ae 7205 /* ORIGIN attribute: If at least one route among routes that are
7206 aggregated has ORIGIN with the value INCOMPLETE, then the
7207 aggregated route must have the ORIGIN attribute with the value
7208 INCOMPLETE. Otherwise, if at least one route among routes that
7209 are aggregated has ORIGIN with the value EGP, then the aggregated
7210 route must have the origin attribute with the value EGP. In all
7211 other case the value of the ORIGIN attribute of the aggregated
7212 route is INTERNAL. */
7213 origin = BGP_ORIGIN_IGP;
718e3744 7214
d62a17ae 7215 table = bgp->rib[afi][safi];
718e3744 7216
d62a17ae 7217 top = bgp_node_get(table, p);
9bcb3eef
DS
7218 for (dest = bgp_node_get(table, p); dest;
7219 dest = bgp_route_next_until(dest, top)) {
7220 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7221
9bcb3eef 7222 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7223 continue;
d62a17ae 7224
a77e2f4b
S
7225 /* If suppress fib is enabled and route not installed
7226 * in FIB, skip the route
7227 */
7228 if (!bgp_check_advertise(bgp, dest))
7229 continue;
7230
c2ff8b3e 7231 match = 0;
d62a17ae 7232
9bcb3eef 7233 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7234 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7235 continue;
718e3744 7236
40381db7 7237 if (pi->attr->flag
c2ff8b3e
DS
7238 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7239 atomic_aggregate = 1;
d62a17ae 7240
40381db7 7241 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7242 continue;
d62a17ae 7243
f273fef1
DS
7244 /*
7245 * summary-only aggregate route suppress
7246 * aggregated route announcements.
6aabb15d
RZ
7247 *
7248 * MED matching:
7249 * Don't create summaries if MED didn't match
7250 * otherwise neither the specific routes and the
7251 * aggregation will be announced.
f273fef1 7252 */
6aabb15d
RZ
7253 if (aggregate->summary_only
7254 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7255 if (aggr_suppress_path(aggregate, pi))
7256 match++;
d62a17ae 7257 }
c2ff8b3e 7258
365ab2e7
RZ
7259 /*
7260 * Suppress more specific routes that match the route
7261 * map results.
7262 *
7263 * MED matching:
7264 * Don't suppress routes if MED matching is enabled and
7265 * it mismatched otherwise we might end up with no
7266 * routes for this path.
7267 */
7268 if (aggregate->suppress_map_name
7269 && AGGREGATE_MED_VALID(aggregate)
7270 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7271 if (aggr_suppress_path(aggregate, pi))
7272 match++;
d62a17ae 7273 }
c2ff8b3e
DS
7274
7275 aggregate->count++;
7276
f273fef1
DS
7277 /*
7278 * If at least one route among routes that are
7279 * aggregated has ORIGIN with the value INCOMPLETE,
7280 * then the aggregated route MUST have the ORIGIN
7281 * attribute with the value INCOMPLETE. Otherwise, if
7282 * at least one route among routes that are aggregated
7283 * has ORIGIN with the value EGP, then the aggregated
7284 * route MUST have the ORIGIN attribute with the value
7285 * EGP.
7286 */
fc968841
NT
7287 switch (pi->attr->origin) {
7288 case BGP_ORIGIN_INCOMPLETE:
7289 aggregate->incomplete_origin_count++;
7290 break;
7291 case BGP_ORIGIN_EGP:
7292 aggregate->egp_origin_count++;
7293 break;
7294 default:
7295 /*Do nothing.
7296 */
7297 break;
7298 }
c2ff8b3e
DS
7299
7300 if (!aggregate->as_set)
7301 continue;
7302
f273fef1
DS
7303 /*
7304 * as-set aggregate route generate origin, as path,
7305 * and community aggregation.
7306 */
fc968841
NT
7307 /* Compute aggregate route's as-path.
7308 */
ef51a7d8 7309 bgp_compute_aggregate_aspath_hash(aggregate,
7310 pi->attr->aspath);
c2ff8b3e 7311
fc968841
NT
7312 /* Compute aggregate route's community.
7313 */
7314 if (pi->attr->community)
21fec674 7315 bgp_compute_aggregate_community_hash(
fc968841
NT
7316 aggregate,
7317 pi->attr->community);
dd18c5a9 7318
fc968841
NT
7319 /* Compute aggregate route's extended community.
7320 */
7321 if (pi->attr->ecommunity)
4edd83f9 7322 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7323 aggregate,
7324 pi->attr->ecommunity);
7325
7326 /* Compute aggregate route's large community.
7327 */
7328 if (pi->attr->lcommunity)
f1eb1f05 7329 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7330 aggregate,
7331 pi->attr->lcommunity);
d62a17ae 7332 }
c2ff8b3e 7333 if (match)
9bcb3eef 7334 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7335 }
21fec674 7336 if (aggregate->as_set) {
ef51a7d8 7337 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7338 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7339 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7340 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7341 }
7342
f1eb1f05 7343
9bcb3eef 7344 bgp_dest_unlock_node(top);
718e3744 7345
718e3744 7346
fc968841
NT
7347 if (aggregate->incomplete_origin_count > 0)
7348 origin = BGP_ORIGIN_INCOMPLETE;
7349 else if (aggregate->egp_origin_count > 0)
7350 origin = BGP_ORIGIN_EGP;
d62a17ae 7351
229757f1
DA
7352 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7353 origin = aggregate->origin;
7354
fc968841
NT
7355 if (aggregate->as_set) {
7356 if (aggregate->aspath)
7357 /* Retrieve aggregate route's as-path.
7358 */
7359 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7360
fc968841
NT
7361 if (aggregate->community)
7362 /* Retrieve aggregate route's community.
7363 */
7364 community = community_dup(aggregate->community);
3da2cc32 7365
fc968841
NT
7366 if (aggregate->ecommunity)
7367 /* Retrieve aggregate route's ecommunity.
7368 */
7369 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7370
fc968841
NT
7371 if (aggregate->lcommunity)
7372 /* Retrieve aggregate route's lcommunity.
7373 */
7374 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7375 }
718e3744 7376
c701010e 7377 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7378 ecommunity, lcommunity, atomic_aggregate,
7379 aggregate);
718e3744 7380}
7381
5f040085
DS
7382void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7383 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7384{
7385 struct bgp_table *table;
9bcb3eef
DS
7386 struct bgp_dest *top;
7387 struct bgp_dest *dest;
40381db7 7388 struct bgp_path_info *pi;
3b7db173
DS
7389 unsigned long match;
7390
7391 table = bgp->rib[afi][safi];
7392
7393 /* If routes exists below this node, generate aggregate routes. */
7394 top = bgp_node_get(table, p);
9bcb3eef
DS
7395 for (dest = bgp_node_get(table, p); dest;
7396 dest = bgp_route_next_until(dest, top)) {
7397 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7398
9bcb3eef 7399 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7400 continue;
7401 match = 0;
7402
9bcb3eef 7403 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7404 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7405 continue;
7406
40381db7 7407 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7408 continue;
7409
6aabb15d
RZ
7410 if (aggregate->summary_only && pi->extra
7411 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7412 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7413 match++;
3b7db173 7414 }
3b7db173 7415
365ab2e7
RZ
7416 if (aggregate->suppress_map_name
7417 && AGGREGATE_MED_VALID(aggregate)
7418 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7419 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7420 match++;
3b7db173 7421 }
365ab2e7 7422
3b7db173 7423 aggregate->count--;
fc968841
NT
7424
7425 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7426 aggregate->incomplete_origin_count--;
7427 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7428 aggregate->egp_origin_count--;
7429
7430 if (aggregate->as_set) {
7431 /* Remove as-path from aggregate.
7432 */
ef51a7d8 7433 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7434 aggregate,
7435 pi->attr->aspath);
7436
7437 if (pi->attr->community)
7438 /* Remove community from aggregate.
7439 */
21fec674 7440 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7441 aggregate,
7442 pi->attr->community);
7443
7444 if (pi->attr->ecommunity)
7445 /* Remove ecommunity from aggregate.
7446 */
4edd83f9 7447 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7448 aggregate,
7449 pi->attr->ecommunity);
7450
7451 if (pi->attr->lcommunity)
7452 /* Remove lcommunity from aggregate.
7453 */
f1eb1f05 7454 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7455 aggregate,
7456 pi->attr->lcommunity);
7457 }
3b7db173
DS
7458 }
7459
7460 /* If this node was suppressed, process the change. */
7461 if (match)
9bcb3eef 7462 bgp_process(bgp, dest, afi, safi);
3b7db173 7463 }
f1eb1f05 7464 if (aggregate->as_set) {
ef51a7d8 7465 aspath_free(aggregate->aspath);
7466 aggregate->aspath = NULL;
21fec674 7467 if (aggregate->community)
7468 community_free(&aggregate->community);
4edd83f9 7469 if (aggregate->ecommunity)
7470 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7471 if (aggregate->lcommunity)
7472 lcommunity_free(&aggregate->lcommunity);
7473 }
7474
9bcb3eef 7475 bgp_dest_unlock_node(top);
3b7db173 7476}
718e3744 7477
5f040085
DS
7478static void bgp_add_route_to_aggregate(struct bgp *bgp,
7479 const struct prefix *aggr_p,
fc968841
NT
7480 struct bgp_path_info *pinew, afi_t afi,
7481 safi_t safi,
7482 struct bgp_aggregate *aggregate)
7483{
7484 uint8_t origin;
7485 struct aspath *aspath = NULL;
7486 uint8_t atomic_aggregate = 0;
7487 struct community *community = NULL;
7488 struct ecommunity *ecommunity = NULL;
7489 struct lcommunity *lcommunity = NULL;
7490
a4559740 7491 /* If the bgp instance is being deleted or self peer is deleted
7492 * then do not create aggregate route
7493 */
7494 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7495 || (bgp->peer_self == NULL))
7496 return;
7497
fc968841
NT
7498 /* ORIGIN attribute: If at least one route among routes that are
7499 * aggregated has ORIGIN with the value INCOMPLETE, then the
7500 * aggregated route must have the ORIGIN attribute with the value
7501 * INCOMPLETE. Otherwise, if at least one route among routes that
7502 * are aggregated has ORIGIN with the value EGP, then the aggregated
7503 * route must have the origin attribute with the value EGP. In all
7504 * other case the value of the ORIGIN attribute of the aggregated
7505 * route is INTERNAL.
7506 */
7507 origin = BGP_ORIGIN_IGP;
7508
7509 aggregate->count++;
7510
6aabb15d
RZ
7511 /*
7512 * This must be called before `summary` check to avoid
7513 * "suppressing" twice.
7514 */
7515 if (aggregate->match_med)
7516 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7517 pinew, true);
7518
7519 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7520 aggr_suppress_path(aggregate, pinew);
fc968841 7521
365ab2e7
RZ
7522 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7523 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7524 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7525
7526 switch (pinew->attr->origin) {
7527 case BGP_ORIGIN_INCOMPLETE:
7528 aggregate->incomplete_origin_count++;
7529 break;
7530 case BGP_ORIGIN_EGP:
7531 aggregate->egp_origin_count++;
7532 break;
7533 default:
7534 /* Do nothing.
7535 */
7536 break;
7537 }
7538
7539 if (aggregate->incomplete_origin_count > 0)
7540 origin = BGP_ORIGIN_INCOMPLETE;
7541 else if (aggregate->egp_origin_count > 0)
7542 origin = BGP_ORIGIN_EGP;
7543
229757f1
DA
7544 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7545 origin = aggregate->origin;
7546
fc968841
NT
7547 if (aggregate->as_set) {
7548 /* Compute aggregate route's as-path.
7549 */
7550 bgp_compute_aggregate_aspath(aggregate,
7551 pinew->attr->aspath);
7552
7553 /* Compute aggregate route's community.
7554 */
7555 if (pinew->attr->community)
7556 bgp_compute_aggregate_community(
7557 aggregate,
7558 pinew->attr->community);
7559
7560 /* Compute aggregate route's extended community.
7561 */
7562 if (pinew->attr->ecommunity)
7563 bgp_compute_aggregate_ecommunity(
7564 aggregate,
7565 pinew->attr->ecommunity);
7566
7567 /* Compute aggregate route's large community.
7568 */
7569 if (pinew->attr->lcommunity)
7570 bgp_compute_aggregate_lcommunity(
7571 aggregate,
7572 pinew->attr->lcommunity);
7573
7574 /* Retrieve aggregate route's as-path.
7575 */
7576 if (aggregate->aspath)
7577 aspath = aspath_dup(aggregate->aspath);
7578
7579 /* Retrieve aggregate route's community.
7580 */
7581 if (aggregate->community)
7582 community = community_dup(aggregate->community);
7583
7584 /* Retrieve aggregate route's ecommunity.
7585 */
7586 if (aggregate->ecommunity)
7587 ecommunity = ecommunity_dup(aggregate->ecommunity);
7588
7589 /* Retrieve aggregate route's lcommunity.
7590 */
7591 if (aggregate->lcommunity)
7592 lcommunity = lcommunity_dup(aggregate->lcommunity);
7593 }
7594
7595 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7596 aspath, community, ecommunity,
7597 lcommunity, atomic_aggregate, aggregate);
7598}
7599
7600static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7601 safi_t safi,
7602 struct bgp_path_info *pi,
7603 struct bgp_aggregate *aggregate,
5f040085 7604 const struct prefix *aggr_p)
fc968841
NT
7605{
7606 uint8_t origin;
7607 struct aspath *aspath = NULL;
7608 uint8_t atomic_aggregate = 0;
7609 struct community *community = NULL;
7610 struct ecommunity *ecommunity = NULL;
7611 struct lcommunity *lcommunity = NULL;
7612 unsigned long match = 0;
7613
a4559740 7614 /* If the bgp instance is being deleted or self peer is deleted
7615 * then do not create aggregate route
7616 */
7617 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7618 || (bgp->peer_self == NULL))
7619 return;
7620
fc968841
NT
7621 if (BGP_PATH_HOLDDOWN(pi))
7622 return;
7623
7624 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7625 return;
7626
4056a5f6
RZ
7627 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7628 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7629 match++;
fc968841 7630
365ab2e7 7631 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7632 && aggr_suppress_map_test(bgp, aggregate, pi))
7633 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7634 match++;
fc968841 7635
6aabb15d 7636 /*
365ab2e7 7637 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7638 * "unsuppressing" twice.
7639 */
7640 if (aggregate->match_med)
7641 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7642 true);
7643
fc968841
NT
7644 if (aggregate->count > 0)
7645 aggregate->count--;
7646
7647 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7648 aggregate->incomplete_origin_count--;
7649 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7650 aggregate->egp_origin_count--;
7651
7652 if (aggregate->as_set) {
7653 /* Remove as-path from aggregate.
7654 */
7655 bgp_remove_aspath_from_aggregate(aggregate,
7656 pi->attr->aspath);
7657
7658 if (pi->attr->community)
7659 /* Remove community from aggregate.
7660 */
7661 bgp_remove_community_from_aggregate(
7662 aggregate,
7663 pi->attr->community);
7664
7665 if (pi->attr->ecommunity)
7666 /* Remove ecommunity from aggregate.
7667 */
7668 bgp_remove_ecommunity_from_aggregate(
7669 aggregate,
7670 pi->attr->ecommunity);
7671
7672 if (pi->attr->lcommunity)
7673 /* Remove lcommunity from aggregate.
7674 */
7675 bgp_remove_lcommunity_from_aggregate(
7676 aggregate,
7677 pi->attr->lcommunity);
7678 }
7679
7680 /* If this node was suppressed, process the change. */
7681 if (match)
7682 bgp_process(bgp, pi->net, afi, safi);
7683
7684 origin = BGP_ORIGIN_IGP;
7685 if (aggregate->incomplete_origin_count > 0)
7686 origin = BGP_ORIGIN_INCOMPLETE;
7687 else if (aggregate->egp_origin_count > 0)
7688 origin = BGP_ORIGIN_EGP;
7689
229757f1
DA
7690 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7691 origin = aggregate->origin;
7692
fc968841
NT
7693 if (aggregate->as_set) {
7694 /* Retrieve aggregate route's as-path.
7695 */
7696 if (aggregate->aspath)
7697 aspath = aspath_dup(aggregate->aspath);
7698
7699 /* Retrieve aggregate route's community.
7700 */
7701 if (aggregate->community)
7702 community = community_dup(aggregate->community);
7703
7704 /* Retrieve aggregate route's ecommunity.
7705 */
7706 if (aggregate->ecommunity)
7707 ecommunity = ecommunity_dup(aggregate->ecommunity);
7708
7709 /* Retrieve aggregate route's lcommunity.
7710 */
7711 if (aggregate->lcommunity)
7712 lcommunity = lcommunity_dup(aggregate->lcommunity);
7713 }
7714
7715 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7716 aspath, community, ecommunity,
7717 lcommunity, atomic_aggregate, aggregate);
7718}
7719
5a1ae2c2 7720void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7721 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7722{
9bcb3eef
DS
7723 struct bgp_dest *child;
7724 struct bgp_dest *dest;
d62a17ae 7725 struct bgp_aggregate *aggregate;
7726 struct bgp_table *table;
718e3744 7727
d62a17ae 7728 table = bgp->aggregate[afi][safi];
f018db83 7729
d62a17ae 7730 /* No aggregates configured. */
7731 if (bgp_table_top_nolock(table) == NULL)
7732 return;
f018db83 7733
d62a17ae 7734 if (p->prefixlen == 0)
7735 return;
718e3744 7736
40381db7 7737 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7738 return;
718e3744 7739
a77e2f4b
S
7740 /* If suppress fib is enabled and route not installed
7741 * in FIB, do not update the aggregate route
7742 */
7743 if (!bgp_check_advertise(bgp, pi->net))
7744 return;
7745
d62a17ae 7746 child = bgp_node_get(table, p);
718e3744 7747
d62a17ae 7748 /* Aggregate address configuration check. */
9bcb3eef
DS
7749 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7750 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7751
9bcb3eef
DS
7752 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7753 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7754 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7755 aggregate);
d62a17ae 7756 }
b1e62edd 7757 }
9bcb3eef 7758 bgp_dest_unlock_node(child);
718e3744 7759}
7760
5a1ae2c2 7761void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7762 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7763{
9bcb3eef
DS
7764 struct bgp_dest *child;
7765 struct bgp_dest *dest;
d62a17ae 7766 struct bgp_aggregate *aggregate;
7767 struct bgp_table *table;
718e3744 7768
d62a17ae 7769 table = bgp->aggregate[afi][safi];
718e3744 7770
d62a17ae 7771 /* No aggregates configured. */
7772 if (bgp_table_top_nolock(table) == NULL)
7773 return;
718e3744 7774
d62a17ae 7775 if (p->prefixlen == 0)
7776 return;
718e3744 7777
d62a17ae 7778 child = bgp_node_get(table, p);
718e3744 7779
d62a17ae 7780 /* Aggregate address configuration check. */
9bcb3eef
DS
7781 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7782 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7783
9bcb3eef
DS
7784 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7785 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7786 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7787 aggregate, dest_p);
d62a17ae 7788 }
b1e62edd 7789 }
9bcb3eef 7790 bgp_dest_unlock_node(child);
d62a17ae 7791}
718e3744 7792
718e3744 7793/* Aggregate route attribute. */
7794#define AGGREGATE_SUMMARY_ONLY 1
7795#define AGGREGATE_AS_SET 1
fb29348a 7796#define AGGREGATE_AS_UNSET 0
718e3744 7797
229757f1
DA
7798static const char *bgp_origin2str(uint8_t origin)
7799{
7800 switch (origin) {
7801 case BGP_ORIGIN_IGP:
7802 return "igp";
7803 case BGP_ORIGIN_EGP:
7804 return "egp";
7805 case BGP_ORIGIN_INCOMPLETE:
7806 return "incomplete";
7807 }
7808 return "n/a";
7809}
7810
fdeb5a81 7811static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7812{
7813 switch (v_state) {
fdeb5a81
DS
7814 case RPKI_NOT_BEING_USED:
7815 return "not used";
7816 case RPKI_VALID:
b5b99af8 7817 return "valid";
fdeb5a81 7818 case RPKI_NOTFOUND:
b5b99af8 7819 return "not found";
fdeb5a81 7820 case RPKI_INVALID:
b5b99af8 7821 return "invalid";
b5b99af8 7822 }
fdeb5a81
DS
7823
7824 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7825 return "ERROR";
7826}
7827
37a87b8f
CS
7828int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7829 safi_t safi, char *errmsg, size_t errmsg_len)
718e3744 7830{
9bcb3eef 7831 struct bgp_dest *dest;
d62a17ae 7832 struct bgp_aggregate *aggregate;
718e3744 7833
a4559740 7834 /* If the bgp instance is being deleted or self peer is deleted
7835 * then do not create aggregate route
7836 */
7837 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7838 || (bgp->peer_self == NULL))
7839 return 0;
7840
37a87b8f 7841 apply_mask(prefix);
d62a17ae 7842 /* Old configuration check. */
37a87b8f 7843 dest = bgp_node_lookup(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7844 if (!dest) {
37a87b8f
CS
7845 snprintf(errmsg, errmsg_len,
7846 "There is no aggregate-address configuration.\n");
7847 return -1;
d62a17ae 7848 }
f6269b4f 7849
9bcb3eef 7850 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
37a87b8f
CS
7851 bgp_aggregate_delete(bgp, prefix, afi, safi, aggregate);
7852 bgp_aggregate_install(bgp, afi, safi, prefix, 0, NULL, NULL, NULL, NULL,
7853 0, aggregate);
d62a17ae 7854
7855 /* Unlock aggregate address configuration. */
9bcb3eef 7856 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7857
7858 if (aggregate->community)
7859 community_free(&aggregate->community);
7860
7861 if (aggregate->community_hash) {
7862 /* Delete all communities in the hash.
7863 */
7864 hash_clean(aggregate->community_hash,
7865 bgp_aggr_community_remove);
7866 /* Free up the community_hash.
7867 */
7868 hash_free(aggregate->community_hash);
7869 }
7870
7871 if (aggregate->ecommunity)
7872 ecommunity_free(&aggregate->ecommunity);
7873
7874 if (aggregate->ecommunity_hash) {
7875 /* Delete all ecommunities in the hash.
7876 */
7877 hash_clean(aggregate->ecommunity_hash,
7878 bgp_aggr_ecommunity_remove);
7879 /* Free up the ecommunity_hash.
7880 */
7881 hash_free(aggregate->ecommunity_hash);
7882 }
7883
7884 if (aggregate->lcommunity)
7885 lcommunity_free(&aggregate->lcommunity);
7886
7887 if (aggregate->lcommunity_hash) {
7888 /* Delete all lcommunities in the hash.
7889 */
7890 hash_clean(aggregate->lcommunity_hash,
7891 bgp_aggr_lcommunity_remove);
7892 /* Free up the lcommunity_hash.
7893 */
7894 hash_free(aggregate->lcommunity_hash);
7895 }
7896
7897 if (aggregate->aspath)
7898 aspath_free(aggregate->aspath);
7899
7900 if (aggregate->aspath_hash) {
7901 /* Delete all as-paths in the hash.
7902 */
7903 hash_clean(aggregate->aspath_hash,
7904 bgp_aggr_aspath_remove);
7905 /* Free up the aspath_hash.
7906 */
7907 hash_free(aggregate->aspath_hash);
7908 }
7909
d62a17ae 7910 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7911 bgp_dest_unlock_node(dest);
7912 bgp_dest_unlock_node(dest);
d62a17ae 7913
37a87b8f 7914 return 0;
d62a17ae 7915}
7916
37a87b8f
CS
7917int bgp_aggregate_set(struct bgp *bgp, struct prefix *prefix, afi_t afi,
7918 safi_t safi, const char *rmap, uint8_t summary_only,
7919 uint8_t as_set, uint8_t origin, bool match_med,
7920 const char *suppress_map,
7921 char *errmsg, size_t errmsg_len)
d62a17ae 7922{
d62a17ae 7923 int ret;
9bcb3eef 7924 struct bgp_dest *dest;
d62a17ae 7925 struct bgp_aggregate *aggregate;
fb29348a 7926 uint8_t as_set_new = as_set;
37a87b8f 7927 char buf[PREFIX2STR_BUFFER];
d62a17ae 7928
365ab2e7 7929 if (suppress_map && summary_only) {
37a87b8f 7930 snprintf(errmsg, errmsg_len,
365ab2e7 7931 "'summary-only' and 'suppress-map' can't be used at the same time\n");
37a87b8f 7932 return -1;
365ab2e7
RZ
7933 }
7934
37a87b8f 7935 apply_mask(prefix);
d62a17ae 7936
37a87b8f
CS
7937 if ((afi == AFI_IP && prefix->prefixlen == IPV4_MAX_BITLEN)
7938 || (afi == AFI_IP6 && prefix->prefixlen == IPV6_MAX_BITLEN)) {
7939 snprintf(
7940 errmsg, errmsg_len,
7941 "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7942 prefix2str(prefix, buf, PREFIX_STRLEN));
7943 return -1;
3624ac81
DS
7944 }
7945
d62a17ae 7946 /* Old configuration check. */
37a87b8f 7947 dest = bgp_node_get(bgp->aggregate[afi][safi], prefix);
9bcb3eef 7948 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7949
20894f50 7950 if (aggregate) {
37a87b8f
CS
7951 snprintf(errmsg, errmsg_len,
7952 "There is already same aggregate network.\n");
d62a17ae 7953 /* try to remove the old entry */
37a87b8f
CS
7954 ret = bgp_aggregate_unset(bgp, prefix, afi, safi, errmsg,
7955 errmsg_len);
d62a17ae 7956 if (ret) {
37a87b8f
CS
7957 snprintf(errmsg, errmsg_len,
7958 "Error deleting aggregate.\n");
9bcb3eef 7959 bgp_dest_unlock_node(dest);
37a87b8f 7960 return -1;
d62a17ae 7961 }
7962 }
718e3744 7963
d62a17ae 7964 /* Make aggregate address structure. */
7965 aggregate = bgp_aggregate_new();
7966 aggregate->summary_only = summary_only;
6aabb15d 7967 aggregate->match_med = match_med;
fb29348a
DA
7968
7969 /* Network operators MUST NOT locally generate any new
7970 * announcements containing AS_SET or AS_CONFED_SET. If they have
7971 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7972 * SHOULD withdraw those routes and re-announce routes for the
7973 * aggregate or component prefixes (i.e., the more-specific routes
7974 * subsumed by the previously aggregated route) without AS_SET
7975 * or AS_CONFED_SET in the updates.
7976 */
7f972cd8 7977 if (bgp->reject_as_sets) {
fb29348a
DA
7978 if (as_set == AGGREGATE_AS_SET) {
7979 as_set_new = AGGREGATE_AS_UNSET;
7980 zlog_warn(
63efca0e 7981 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7982 __func__);
37a87b8f
CS
7983 snprintf(
7984 errmsg, errmsg_len,
fb29348a
DA
7985 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7986 }
7987 }
7988
7989 aggregate->as_set = as_set_new;
d62a17ae 7990 aggregate->safi = safi;
229757f1
DA
7991 /* Override ORIGIN attribute if defined.
7992 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
7993 * to IGP which is not what rfc4271 says.
7994 * This enables the same behavior, optionally.
7995 */
7996 aggregate->origin = origin;
20894f50
DA
7997
7998 if (rmap) {
7999 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8000 route_map_counter_decrement(aggregate->rmap.map);
8001 aggregate->rmap.name =
8002 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8003 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8004 route_map_counter_increment(aggregate->rmap.map);
8005 }
365ab2e7
RZ
8006
8007 if (suppress_map) {
8008 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8009 route_map_counter_decrement(aggregate->suppress_map);
8010
8011 aggregate->suppress_map_name =
8012 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8013 aggregate->suppress_map =
8014 route_map_lookup_by_name(aggregate->suppress_map_name);
8015 route_map_counter_increment(aggregate->suppress_map);
8016 }
8017
9bcb3eef 8018 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8019
d62a17ae 8020 /* Aggregate address insert into BGP routing table. */
37a87b8f 8021 bgp_aggregate_route(bgp, prefix, afi, safi, aggregate);
718e3744 8022
37a87b8f 8023 return 0;
718e3744 8024}
8025
37a87b8f
CS
8026DEFPY_YANG(
8027 aggregate_addressv4, aggregate_addressv4_cmd,
faff43d0 8028 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
37a87b8f
CS
8029 "as-set$as_set_s"
8030 "|summary-only$summary_only"
8031 "|route-map WORD$rmap_name"
8032 "|origin <egp|igp|incomplete>$origin_s"
8033 "|matching-MED-only$match_med"
90e21f35 8034 "|suppress-map WORD$suppress_map"
faff43d0 8035 "}]",
37a87b8f
CS
8036 NO_STR
8037 "Configure BGP aggregate entries\n"
8038 "Aggregate prefix\n"
8039 "Aggregate address\n"
8040 "Aggregate mask\n"
8041 "Generate AS set path information\n"
8042 "Filter more specific routes from updates\n"
8043 "Apply route map to aggregate network\n"
8044 "Route map name\n"
8045 "BGP origin code\n"
8046 "Remote EGP\n"
8047 "Local IGP\n"
8048 "Unknown heritage\n"
8049 "Only aggregate routes with matching MED\n"
90e21f35
CS
8050 "Suppress the selected more specific routes\n"
8051 "Route map with the route selectors\n")
37a87b8f
CS
8052{
8053 char base_xpath[XPATH_MAXLEN];
554b3b10 8054 safi_t safi = bgp_node_safi(vty);
554b3b10 8055 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8056
554b3b10 8057 if (addr_str) {
7533cad7
QY
8058 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8059 sizeof(prefix_buf))
554b3b10
RZ
8060 == 0) {
8061 vty_out(vty, "%% Inconsistent address and mask\n");
8062 return CMD_WARNING_CONFIG_FAILED;
8063 }
37a87b8f
CS
8064 } else {
8065 strlcpy(prefix_buf, prefix_str, sizeof(prefix_buf));
229757f1
DA
8066 }
8067
37a87b8f
CS
8068 if (!no && origin_s)
8069 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
8070
8071 if (!no && as_set_s)
8072 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
8073 else
8074 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
8075
8076 if (!no && summary_only)
8077 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8078 "true");
8079 else
8080 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8081 "false");
8082
fa423774
CS
8083 if (!no && match_med)
8084 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
8085 else
8086 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
8087 "false");
8088
37a87b8f
CS
8089 if (rmap_name)
8090 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
8091 rmap_name);
8092 else
8093 nb_cli_enqueue_change(vty, "./rmap-policy-export",
8094 NB_OP_DESTROY, NULL);
8095
90e21f35
CS
8096 if (suppress_map)
8097 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
8098 suppress_map);
8099 else
8100 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
8101 NULL);
8102
37a87b8f
CS
8103 snprintf(
8104 base_xpath, sizeof(base_xpath),
8105 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8106 yang_afi_safi_value2identity(AFI_IP, safi),
8107 bgp_afi_safi_get_container_str(AFI_IP, safi), prefix_buf);
554b3b10 8108
554b3b10 8109 if (no)
37a87b8f
CS
8110 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8111 else
8112 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
8113
8114 return nb_cli_apply_changes(vty, base_xpath);
8115}
8116
8117DEFPY_YANG(aggregate_addressv6, aggregate_addressv6_cmd,
faff43d0 8118 "[no] aggregate-address X:X::X:X/M$prefix [{"
37a87b8f
CS
8119 "as-set$as_set_s"
8120 "|summary-only$summary_only"
8121 "|route-map WORD$rmap_name"
8122 "|origin <egp|igp|incomplete>$origin_s"
8123 "|matching-MED-only$match_med"
90e21f35 8124 "|suppress-map WORD$suppress_map"
faff43d0 8125 "}]",
37a87b8f
CS
8126 NO_STR
8127 "Configure BGP aggregate entries\n"
8128 "Aggregate prefix\n"
8129 "Generate AS set path information\n"
8130 "Filter more specific routes from updates\n"
8131 "Apply route map to aggregate network\n"
8132 "Route map name\n"
8133 "BGP origin code\n"
8134 "Remote EGP\n"
8135 "Local IGP\n"
8136 "Unknown heritage\n"
8137 "Only aggregate routes with matching MED\n"
8138 "Suppress the selected more specific routes\n"
90e21f35 8139 "Route map with the route selectors\n")
37a87b8f
CS
8140{
8141 char base_xpath[XPATH_MAXLEN];
8142 safi_t safi = bgp_node_safi(vty);
8143
8144 if (!no && origin_s)
8145 nb_cli_enqueue_change(vty, "./origin", NB_OP_MODIFY, origin_s);
8146
8147 if (!no && as_set_s)
8148 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "true");
8149 else
8150 nb_cli_enqueue_change(vty, "./as-set", NB_OP_MODIFY, "false");
8151
8152 if (!no && summary_only)
8153 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8154 "true");
8155 else
8156 nb_cli_enqueue_change(vty, "./summary-only", NB_OP_MODIFY,
8157 "false");
8158
fa423774
CS
8159 if (!no && match_med)
8160 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY, "true");
8161 else
8162 nb_cli_enqueue_change(vty, "./match-med", NB_OP_MODIFY,
8163 "false");
8164
37a87b8f
CS
8165 if (rmap_name)
8166 nb_cli_enqueue_change(vty, "./rmap-policy-export", NB_OP_MODIFY,
8167 rmap_name);
8168
90e21f35
CS
8169 if (suppress_map)
8170 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_MODIFY,
8171 suppress_map);
8172 else
8173 nb_cli_enqueue_change(vty, "./suppress-map", NB_OP_DESTROY,
8174 NULL);
8175
37a87b8f
CS
8176 snprintf(
8177 base_xpath, sizeof(base_xpath),
8178 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/aggregate-route[prefix='%s']",
8179 yang_afi_safi_value2identity(AFI_IP6, safi),
8180 bgp_afi_safi_get_container_str(AFI_IP6, safi), prefix_str);
8181
554b3b10 8182 if (no)
37a87b8f
CS
8183 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
8184 else
8185 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
554b3b10 8186
37a87b8f
CS
8187 return nb_cli_apply_changes(vty, base_xpath);
8188}
8189
8190void cli_show_bgp_global_afi_safi_unicast_aggregate_route(
8191 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
8192{
8193 uint8_t origin;
8194
8195 vty_out(vty, " aggregate-address %s",
8196 yang_dnode_get_string(dnode, "./prefix"));
8197
8198 if (yang_dnode_get_bool(dnode, "./as-set"))
8199 vty_out(vty, " as-set");
8200
8201 if (yang_dnode_get_bool(dnode, "./summary-only"))
8202 vty_out(vty, " summary-only");
8203
8204 if (yang_dnode_exists(dnode, "./rmap-policy-export"))
8205 vty_out(vty, " route-map %s",
8206 yang_dnode_get_string(dnode, "./rmap-policy-export"));
8207
8208 origin = yang_dnode_get_enum(dnode, "./origin");
8209 if (origin != BGP_ORIGIN_UNSPECIFIED)
8210 vty_out(vty, " origin %s", bgp_origin2str(origin));
8211
fa423774
CS
8212 if (yang_dnode_get_bool(dnode, "./match-med"))
8213 vty_out(vty, " matching-MED-only");
8214
37a87b8f 8215 vty_out(vty, "\n");
718e3744 8216}
8217
718e3744 8218/* Redistribute route treatment. */
d62a17ae 8219void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff
DS
8220 const union g_addr *nexthop, ifindex_t ifindex,
8221 enum nexthop_types_t nhtype, uint32_t metric,
d7c0a89a
QY
8222 uint8_t type, unsigned short instance,
8223 route_tag_t tag)
d62a17ae 8224{
4b7e6066 8225 struct bgp_path_info *new;
40381db7
DS
8226 struct bgp_path_info *bpi;
8227 struct bgp_path_info rmap_path;
9bcb3eef 8228 struct bgp_dest *bn;
d62a17ae 8229 struct attr attr;
8230 struct attr *new_attr;
8231 afi_t afi;
b68885f9 8232 route_map_result_t ret;
d62a17ae 8233 struct bgp_redist *red;
8234
8235 /* Make default attribute. */
8236 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8237 /*
8238 * This must not be NULL to satisfy Coverity SA
8239 */
8240 assert(attr.aspath);
9de1f7ff 8241
a4d82a8a 8242 switch (nhtype) {
9de1f7ff
DS
8243 case NEXTHOP_TYPE_IFINDEX:
8244 break;
8245 case NEXTHOP_TYPE_IPV4:
8246 case NEXTHOP_TYPE_IPV4_IFINDEX:
8247 attr.nexthop = nexthop->ipv4;
8248 break;
8249 case NEXTHOP_TYPE_IPV6:
8250 case NEXTHOP_TYPE_IPV6_IFINDEX:
8251 attr.mp_nexthop_global = nexthop->ipv6;
8252 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8253 break;
8254 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8255 switch (p->family) {
8256 case AF_INET:
9de1f7ff 8257 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8258 break;
8259 case AF_INET6:
9de1f7ff
DS
8260 memset(&attr.mp_nexthop_global, 0,
8261 sizeof(attr.mp_nexthop_global));
74489921 8262 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8263 break;
74489921 8264 }
9de1f7ff 8265 break;
d62a17ae 8266 }
74489921 8267 attr.nh_ifindex = ifindex;
f04a80a5 8268
d62a17ae 8269 attr.med = metric;
8270 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8271 attr.tag = tag;
718e3744 8272
d62a17ae 8273 afi = family2afi(p->family);
6aeb9e78 8274
d62a17ae 8275 red = bgp_redist_lookup(bgp, afi, type, instance);
8276 if (red) {
8277 struct attr attr_new;
718e3744 8278
d62a17ae 8279 /* Copy attribute for modification. */
6f4f49b2 8280 attr_new = attr;
718e3744 8281
d62a17ae 8282 if (red->redist_metric_flag)
8283 attr_new.med = red->redist_metric;
718e3744 8284
d62a17ae 8285 /* Apply route-map. */
8286 if (red->rmap.name) {
40381db7
DS
8287 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8288 rmap_path.peer = bgp->peer_self;
8289 rmap_path.attr = &attr_new;
718e3744 8290
d62a17ae 8291 SET_FLAG(bgp->peer_self->rmap_type,
8292 PEER_RMAP_TYPE_REDISTRIBUTE);
8293
1782514f 8294 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8295
8296 bgp->peer_self->rmap_type = 0;
8297
8298 if (ret == RMAP_DENYMATCH) {
8299 /* Free uninterned attribute. */
8300 bgp_attr_flush(&attr_new);
8301
8302 /* Unintern original. */
8303 aspath_unintern(&attr.aspath);
8304 bgp_redistribute_delete(bgp, p, type, instance);
8305 return;
8306 }
8307 }
8308
637e5ba4 8309 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8310 bgp_attr_add_gshut_community(&attr_new);
8311
d62a17ae 8312 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8313 SAFI_UNICAST, p, NULL);
8314
8315 new_attr = bgp_attr_intern(&attr_new);
8316
9bcb3eef 8317 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8318 if (bpi->peer == bgp->peer_self
8319 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8320 break;
8321
40381db7 8322 if (bpi) {
d62a17ae 8323 /* Ensure the (source route) type is updated. */
40381db7
DS
8324 bpi->type = type;
8325 if (attrhash_cmp(bpi->attr, new_attr)
8326 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8327 bgp_attr_unintern(&new_attr);
8328 aspath_unintern(&attr.aspath);
9bcb3eef 8329 bgp_dest_unlock_node(bn);
d62a17ae 8330 return;
8331 } else {
8332 /* The attribute is changed. */
40381db7 8333 bgp_path_info_set_flag(bn, bpi,
18ee8310 8334 BGP_PATH_ATTR_CHANGED);
d62a17ae 8335
8336 /* Rewrite BGP route information. */
40381db7
DS
8337 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8338 bgp_path_info_restore(bn, bpi);
d62a17ae 8339 else
40381db7
DS
8340 bgp_aggregate_decrement(
8341 bgp, p, bpi, afi, SAFI_UNICAST);
8342 bgp_attr_unintern(&bpi->attr);
8343 bpi->attr = new_attr;
8344 bpi->uptime = bgp_clock();
d62a17ae 8345
8346 /* Process change. */
40381db7 8347 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8348 SAFI_UNICAST);
8349 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8350 bgp_dest_unlock_node(bn);
d62a17ae 8351 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8352
8353 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8354 || (bgp->inst_type
8355 == BGP_INSTANCE_TYPE_DEFAULT)) {
8356
8357 vpn_leak_from_vrf_update(
40381db7 8358 bgp_get_default(), bgp, bpi);
ddb5b488 8359 }
d62a17ae 8360 return;
8361 }
8362 }
8363
8364 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8365 bgp->peer_self, new_attr, bn);
1defdda8 8366 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8367
8368 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8369 bgp_path_info_add(bn, new);
9bcb3eef 8370 bgp_dest_unlock_node(bn);
d62a17ae 8371 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8372
8373 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8374 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8375
8376 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8377 }
d62a17ae 8378 }
8379
8380 /* Unintern original. */
8381 aspath_unintern(&attr.aspath);
718e3744 8382}
8383
d7c0a89a
QY
8384void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8385 unsigned short instance)
718e3744 8386{
d62a17ae 8387 afi_t afi;
9bcb3eef 8388 struct bgp_dest *dest;
40381db7 8389 struct bgp_path_info *pi;
d62a17ae 8390 struct bgp_redist *red;
718e3744 8391
d62a17ae 8392 afi = family2afi(p->family);
718e3744 8393
d62a17ae 8394 red = bgp_redist_lookup(bgp, afi, type, instance);
8395 if (red) {
9bcb3eef
DS
8396 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8397 SAFI_UNICAST, p, NULL);
d62a17ae 8398
9bcb3eef 8399 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8400 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8401 break;
8402
40381db7 8403 if (pi) {
ddb5b488
PZ
8404 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8405 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8406
8407 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8408 bgp, pi);
ddb5b488 8409 }
40381db7 8410 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8411 bgp_path_info_delete(dest, pi);
8412 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8413 }
9bcb3eef 8414 bgp_dest_unlock_node(dest);
d62a17ae 8415 }
8416}
8417
8418/* Withdraw specified route type's route. */
8419void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8420 unsigned short instance)
d62a17ae 8421{
9bcb3eef 8422 struct bgp_dest *dest;
40381db7 8423 struct bgp_path_info *pi;
d62a17ae 8424 struct bgp_table *table;
8425
8426 table = bgp->rib[afi][SAFI_UNICAST];
8427
9bcb3eef
DS
8428 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8429 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8430 if (pi->peer == bgp->peer_self && pi->type == type
8431 && pi->instance == instance)
d62a17ae 8432 break;
8433
40381db7 8434 if (pi) {
ddb5b488
PZ
8435 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8436 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8437
8438 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8439 bgp, pi);
ddb5b488 8440 }
9bcb3eef 8441 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8442 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8443 bgp_path_info_delete(dest, pi);
8444 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8445 }
718e3744 8446 }
718e3744 8447}
6b0655a2 8448
718e3744 8449/* Static function to display route. */
7d3cae70
DA
8450static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8451 struct vty *vty, json_object *json, bool wide)
718e3744 8452{
be054588 8453 int len = 0;
d62a17ae 8454 char buf[BUFSIZ];
50e05855 8455 char buf2[BUFSIZ];
718e3744 8456
d62a17ae 8457 if (p->family == AF_INET) {
c6462ff4 8458 if (!json) {
8228a9a7 8459 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8460 } else {
8461 json_object_string_add(json, "prefix",
8462 inet_ntop(p->family,
8463 &p->u.prefix, buf,
8464 BUFSIZ));
8465 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8466 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8467 json_object_string_add(json, "network", buf2);
7d3cae70 8468 json_object_int_add(json, "version", dest->version);
c6462ff4 8469 }
d62a17ae 8470 } else if (p->family == AF_ETHERNET) {
8228a9a7 8471 len = vty_out(vty, "%pFX", p);
b03b8898 8472 } else if (p->family == AF_EVPN) {
57f7feb6 8473 if (!json)
2dbe669b 8474 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8475 else
60466a63 8476 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8477 } else if (p->family == AF_FLOWSPEC) {
8478 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8479 json ?
8480 NLRI_STRING_FORMAT_JSON_SIMPLE :
8481 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8482 } else {
c6462ff4 8483 if (!json)
8228a9a7 8484 len = vty_out(vty, "%pFX", p);
50e05855
AD
8485 else {
8486 json_object_string_add(json, "prefix",
8487 inet_ntop(p->family,
8488 &p->u.prefix, buf,
8489 BUFSIZ));
8490 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8491 prefix2str(p, buf2, PREFIX_STRLEN);
8492 json_object_string_add(json, "network", buf2);
7d3cae70 8493 json_object_int_add(json, "version", dest->version);
37d4e0df 8494 }
9c92b5f7 8495 }
d62a17ae 8496
9c92b5f7 8497 if (!json) {
ae248832 8498 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8499 if (len < 1)
8500 vty_out(vty, "\n%*s", 20, " ");
8501 else
8502 vty_out(vty, "%*s", len, " ");
8503 }
718e3744 8504}
8505
d62a17ae 8506enum bgp_display_type {
8507 normal_list,
718e3744 8508};
8509
bbb46eb5
DA
8510static const char *
8511bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
8512{
8513 switch (reason) {
8514 case bgp_path_selection_none:
8515 return "Nothing to Select";
8516 case bgp_path_selection_first:
8517 return "First path received";
8518 case bgp_path_selection_evpn_sticky_mac:
8519 return "EVPN Sticky Mac";
8520 case bgp_path_selection_evpn_seq:
8521 return "EVPN sequence number";
8522 case bgp_path_selection_evpn_lower_ip:
8523 return "EVPN lower IP";
8524 case bgp_path_selection_evpn_local_path:
8525 return "EVPN local ES path";
8526 case bgp_path_selection_evpn_non_proxy:
8527 return "EVPN non proxy";
8528 case bgp_path_selection_weight:
8529 return "Weight";
8530 case bgp_path_selection_local_pref:
8531 return "Local Pref";
8532 case bgp_path_selection_local_route:
8533 return "Local Route";
8534 case bgp_path_selection_confed_as_path:
8535 return "Confederation based AS Path";
8536 case bgp_path_selection_as_path:
8537 return "AS Path";
8538 case bgp_path_selection_origin:
8539 return "Origin";
8540 case bgp_path_selection_med:
8541 return "MED";
8542 case bgp_path_selection_peer:
8543 return "Peer Type";
8544 case bgp_path_selection_confed:
8545 return "Confed Peer Type";
8546 case bgp_path_selection_igp_metric:
8547 return "IGP Metric";
8548 case bgp_path_selection_older:
8549 return "Older Path";
8550 case bgp_path_selection_router_id:
8551 return "Router ID";
8552 case bgp_path_selection_cluster_length:
bcab253c 8553 return "Cluster length";
bbb46eb5
DA
8554 case bgp_path_selection_stale:
8555 return "Path Staleness";
8556 case bgp_path_selection_local_configured:
8557 return "Locally configured route";
8558 case bgp_path_selection_neighbor_ip:
8559 return "Neighbor IP";
8560 case bgp_path_selection_default:
8561 return "Nothing left to compare";
8562 }
8563 return "Invalid (internal error)";
8564}
8565
18ee8310 8566/* Print the short form route status for a bgp_path_info */
4b7e6066 8567static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8568 struct bgp_path_info *path,
82c298be 8569 const struct prefix *p,
d62a17ae 8570 json_object *json_path)
718e3744 8571{
82c298be
DA
8572 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8573
d62a17ae 8574 if (json_path) {
b05a1c8b 8575
d62a17ae 8576 /* Route status display. */
9b6d8fcf 8577 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8578 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8579
9b6d8fcf 8580 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8581 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8582
4056a5f6 8583 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8584 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8585
9b6d8fcf
DS
8586 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8587 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8588 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8589
d62a17ae 8590 /* Selected */
9b6d8fcf 8591 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8592 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8593
9b6d8fcf 8594 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8595 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8596
bbb46eb5 8597 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8598 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8599 json_object_string_add(json_path, "selectionReason",
8600 bgp_path_selection_reason2str(
8601 path->net->reason));
8602 }
b05a1c8b 8603
9b6d8fcf 8604 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8605 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8606
d62a17ae 8607 /* Internal route. */
9b6d8fcf
DS
8608 if ((path->peer->as)
8609 && (path->peer->as == path->peer->local_as))
d62a17ae 8610 json_object_string_add(json_path, "pathFrom",
8611 "internal");
8612 else
8613 json_object_string_add(json_path, "pathFrom",
8614 "external");
b05a1c8b 8615
d62a17ae 8616 return;
8617 }
b05a1c8b 8618
82c298be
DA
8619 /* RPKI validation state */
8620 rpki_state =
8621 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8622
8623 if (rpki_state == RPKI_VALID)
8624 vty_out(vty, "V");
8625 else if (rpki_state == RPKI_INVALID)
8626 vty_out(vty, "I");
8627 else if (rpki_state == RPKI_NOTFOUND)
8628 vty_out(vty, "N");
8629
d62a17ae 8630 /* Route status display. */
9b6d8fcf 8631 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8632 vty_out(vty, "R");
9b6d8fcf 8633 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8634 vty_out(vty, "S");
4056a5f6 8635 else if (bgp_path_suppressed(path))
d62a17ae 8636 vty_out(vty, "s");
9b6d8fcf
DS
8637 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8638 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8639 vty_out(vty, "*");
8640 else
8641 vty_out(vty, " ");
8642
8643 /* Selected */
9b6d8fcf 8644 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8645 vty_out(vty, "h");
9b6d8fcf 8646 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8647 vty_out(vty, "d");
9b6d8fcf 8648 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8649 vty_out(vty, ">");
9b6d8fcf 8650 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8651 vty_out(vty, "=");
8652 else
8653 vty_out(vty, " ");
718e3744 8654
d62a17ae 8655 /* Internal route. */
9b6d8fcf
DS
8656 if (path->peer && (path->peer->as)
8657 && (path->peer->as == path->peer->local_as))
d62a17ae 8658 vty_out(vty, "i");
8659 else
8660 vty_out(vty, " ");
b40d939b 8661}
8662
2ba93fd6
DA
8663static char *bgp_nexthop_hostname(struct peer *peer,
8664 struct bgp_nexthop_cache *bnc)
25b5da8d 8665{
892fedb6 8666 if (peer->hostname
aef999a2 8667 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8668 return peer->hostname;
8669 return NULL;
8670}
8671
b40d939b 8672/* called from terminal list command */
bd494ec5 8673void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8674 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8675 json_object *json_paths, bool wide)
d62a17ae 8676{
aef999a2 8677 int len;
515c2602 8678 struct attr *attr = path->attr;
d62a17ae 8679 json_object *json_path = NULL;
8680 json_object *json_nexthops = NULL;
8681 json_object *json_nexthop_global = NULL;
8682 json_object *json_nexthop_ll = NULL;
6f214dd3 8683 json_object *json_ext_community = NULL;
9df8b37c 8684 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8685 bool nexthop_self =
9b6d8fcf 8686 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8687 bool nexthop_othervrf = false;
43089216 8688 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8689 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8690 char *nexthop_hostname =
8691 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8692 char esi_buf[ESI_STR_LEN];
d62a17ae 8693
8694 if (json_paths)
8695 json_path = json_object_new_object();
8696
8697 /* short status lead text */
82c298be 8698 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8699
8700 if (!json_paths) {
8701 /* print prefix and mask */
8702 if (!display)
7d3cae70 8703 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8704 else
ae248832 8705 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8706 } else {
7d3cae70 8707 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8708 }
47fc97cc 8709
9df8b37c
PZ
8710 /*
8711 * If vrf id of nexthop is different from that of prefix,
8712 * set up printable string to append
8713 */
9b6d8fcf 8714 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8715 const char *self = "";
8716
8717 if (nexthop_self)
8718 self = "<";
8719
8720 nexthop_othervrf = true;
9b6d8fcf 8721 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8722
9b6d8fcf 8723 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8724 snprintf(vrf_id_str, sizeof(vrf_id_str),
8725 "@%s%s", VRFID_NONE_STR, self);
8726 else
8727 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8728 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8729
9b6d8fcf
DS
8730 if (path->extra->bgp_orig->inst_type
8731 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8732
9b6d8fcf 8733 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8734 } else {
8735 const char *self = "";
8736
8737 if (nexthop_self)
8738 self = "<";
8739
8740 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8741 }
8742
445c2480
DS
8743 /*
8744 * For ENCAP and EVPN routes, nexthop address family is not
8745 * neccessarily the same as the prefix address family.
8746 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8747 * EVPN routes are also exchanged with a MP nexthop. Currently,
8748 * this
8749 * is only IPv4, the value will be present in either
8750 * attr->nexthop or
8751 * attr->mp_nexthop_global_in
8752 */
8753 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8754 char buf[BUFSIZ];
8755 char nexthop[128];
8756 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8757
8758 switch (af) {
8759 case AF_INET:
772270f3
QY
8760 snprintf(nexthop, sizeof(nexthop), "%s",
8761 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8762 BUFSIZ));
445c2480
DS
8763 break;
8764 case AF_INET6:
772270f3
QY
8765 snprintf(nexthop, sizeof(nexthop), "%s",
8766 inet_ntop(af, &attr->mp_nexthop_global, buf,
8767 BUFSIZ));
445c2480
DS
8768 break;
8769 default:
772270f3 8770 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8771 break;
d62a17ae 8772 }
d62a17ae 8773
445c2480
DS
8774 if (json_paths) {
8775 json_nexthop_global = json_object_new_object();
8776
515c2602
DA
8777 json_object_string_add(json_nexthop_global, "ip",
8778 nexthop);
8779
939a97f4 8780 if (path->peer->hostname)
515c2602
DA
8781 json_object_string_add(json_nexthop_global,
8782 "hostname",
939a97f4 8783 path->peer->hostname);
515c2602
DA
8784
8785 json_object_string_add(json_nexthop_global, "afi",
8786 (af == AF_INET) ? "ipv4"
8787 : "ipv6");
445c2480
DS
8788 json_object_boolean_true_add(json_nexthop_global,
8789 "used");
aef999a2
DA
8790 } else {
8791 if (nexthop_hostname)
8792 len = vty_out(vty, "%s(%s)%s", nexthop,
8793 nexthop_hostname, vrf_id_str);
8794 else
8795 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8796
ae248832 8797 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8798 if (len < 1)
8799 vty_out(vty, "\n%*s", 36, " ");
8800 else
8801 vty_out(vty, "%*s", len, " ");
8802 }
445c2480
DS
8803 } else if (safi == SAFI_EVPN) {
8804 if (json_paths) {
23d0a753
DA
8805 char buf[BUFSIZ] = {0};
8806
445c2480
DS
8807 json_nexthop_global = json_object_new_object();
8808
515c2602 8809 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8810 inet_ntop(AF_INET,
8811 &attr->nexthop, buf,
8812 sizeof(buf)));
515c2602 8813
939a97f4 8814 if (path->peer->hostname)
515c2602
DA
8815 json_object_string_add(json_nexthop_global,
8816 "hostname",
939a97f4 8817 path->peer->hostname);
515c2602 8818
a4d82a8a
PZ
8819 json_object_string_add(json_nexthop_global, "afi",
8820 "ipv4");
445c2480
DS
8821 json_object_boolean_true_add(json_nexthop_global,
8822 "used");
aef999a2
DA
8823 } else {
8824 if (nexthop_hostname)
8825 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8826 nexthop_hostname, vrf_id_str);
8827 else
8828 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8829 vrf_id_str);
8830
ae248832 8831 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8832 if (len < 1)
8833 vty_out(vty, "\n%*s", 36, " ");
8834 else
8835 vty_out(vty, "%*s", len, " ");
8836 }
d33fc23b 8837 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8838 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8839 if (json_paths) {
23d0a753
DA
8840 char buf[BUFSIZ] = {0};
8841
026b914a 8842 json_nexthop_global = json_object_new_object();
515c2602 8843
026b914a
PG
8844 json_object_string_add(json_nexthop_global,
8845 "afi", "ipv4");
515c2602
DA
8846 json_object_string_add(
8847 json_nexthop_global, "ip",
23d0a753
DA
8848 inet_ntop(AF_INET, &attr->nexthop, buf,
8849 sizeof(buf)));
515c2602 8850
939a97f4 8851 if (path->peer->hostname)
515c2602
DA
8852 json_object_string_add(
8853 json_nexthop_global, "hostname",
939a97f4 8854 path->peer->hostname);
515c2602 8855
50e05855
AD
8856 json_object_boolean_true_add(
8857 json_nexthop_global,
026b914a
PG
8858 "used");
8859 } else {
aef999a2
DA
8860 if (nexthop_hostname)
8861 len = vty_out(vty, "%pI4(%s)%s",
8862 &attr->nexthop,
8863 nexthop_hostname,
8864 vrf_id_str);
8865 else
8866 len = vty_out(vty, "%pI4%s",
8867 &attr->nexthop,
8868 vrf_id_str);
8869
ae248832 8870 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8871 if (len < 1)
8872 vty_out(vty, "\n%*s", 36, " ");
8873 else
8874 vty_out(vty, "%*s", len, " ");
026b914a
PG
8875 }
8876 }
d33fc23b 8877 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8878 if (json_paths) {
23d0a753
DA
8879 char buf[BUFSIZ] = {0};
8880
445c2480 8881 json_nexthop_global = json_object_new_object();
d62a17ae 8882
515c2602 8883 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8884 inet_ntop(AF_INET,
8885 &attr->nexthop, buf,
8886 sizeof(buf)));
515c2602 8887
939a97f4 8888 if (path->peer->hostname)
515c2602
DA
8889 json_object_string_add(json_nexthop_global,
8890 "hostname",
939a97f4 8891 path->peer->hostname);
445c2480 8892
a4d82a8a
PZ
8893 json_object_string_add(json_nexthop_global, "afi",
8894 "ipv4");
445c2480
DS
8895 json_object_boolean_true_add(json_nexthop_global,
8896 "used");
8897 } else {
aef999a2
DA
8898 if (nexthop_hostname)
8899 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8900 nexthop_hostname, vrf_id_str);
8901 else
8902 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8903 vrf_id_str);
9df8b37c 8904
ae248832 8905 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8906 if (len < 1)
8907 vty_out(vty, "\n%*s", 36, " ");
8908 else
8909 vty_out(vty, "%*s", len, " ");
d62a17ae 8910 }
445c2480 8911 }
b05a1c8b 8912
445c2480 8913 /* IPv6 Next Hop */
a4d82a8a 8914 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8915 char buf[BUFSIZ];
d62a17ae 8916
445c2480
DS
8917 if (json_paths) {
8918 json_nexthop_global = json_object_new_object();
a4d82a8a 8919 json_object_string_add(
515c2602
DA
8920 json_nexthop_global, "ip",
8921 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8922 buf, BUFSIZ));
8923
939a97f4 8924 if (path->peer->hostname)
515c2602
DA
8925 json_object_string_add(json_nexthop_global,
8926 "hostname",
939a97f4 8927 path->peer->hostname);
515c2602 8928
a4d82a8a
PZ
8929 json_object_string_add(json_nexthop_global, "afi",
8930 "ipv6");
8931 json_object_string_add(json_nexthop_global, "scope",
8932 "global");
445c2480
DS
8933
8934 /* We display both LL & GL if both have been
8935 * received */
0606039c
DA
8936 if ((attr->mp_nexthop_len
8937 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8938 || (path->peer->conf_if)) {
a4d82a8a 8939 json_nexthop_ll = json_object_new_object();
d62a17ae 8940 json_object_string_add(
515c2602
DA
8941 json_nexthop_ll, "ip",
8942 inet_ntop(AF_INET6,
8943 &attr->mp_nexthop_local, buf,
8944 BUFSIZ));
8945
939a97f4 8946 if (path->peer->hostname)
515c2602
DA
8947 json_object_string_add(
8948 json_nexthop_ll, "hostname",
939a97f4 8949 path->peer->hostname);
515c2602 8950
a4d82a8a
PZ
8951 json_object_string_add(json_nexthop_ll, "afi",
8952 "ipv6");
8953 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8954 "link-local");
d62a17ae 8955
a4d82a8a
PZ
8956 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8957 &attr->mp_nexthop_local)
445c2480
DS
8958 != 0)
8959 && !attr->mp_nexthop_prefer_global)
d62a17ae 8960 json_object_boolean_true_add(
a4d82a8a 8961 json_nexthop_ll, "used");
445c2480
DS
8962 else
8963 json_object_boolean_true_add(
a4d82a8a 8964 json_nexthop_global, "used");
445c2480
DS
8965 } else
8966 json_object_boolean_true_add(
8967 json_nexthop_global, "used");
8968 } else {
8969 /* Display LL if LL/Global both in table unless
8970 * prefer-global is set */
0606039c
DA
8971 if (((attr->mp_nexthop_len
8972 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8973 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8974 || (path->peer->conf_if)) {
8975 if (path->peer->conf_if) {
a4d82a8a 8976 len = vty_out(vty, "%s",
9b6d8fcf 8977 path->peer->conf_if);
ae248832
MK
8978 /* len of IPv6 addr + max len of def
8979 * ifname */
8980 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8981
8982 if (len < 1)
a4d82a8a 8983 vty_out(vty, "\n%*s", 36, " ");
445c2480 8984 else
a4d82a8a 8985 vty_out(vty, "%*s", len, " ");
d62a17ae 8986 } else {
aef999a2
DA
8987 if (nexthop_hostname)
8988 len = vty_out(
8989 vty, "%pI6(%s)%s",
8990 &attr->mp_nexthop_local,
8991 nexthop_hostname,
8992 vrf_id_str);
8993 else
8994 len = vty_out(
8995 vty, "%pI6%s",
8996 &attr->mp_nexthop_local,
8997 vrf_id_str);
8998
ae248832 8999 len = wide ? (41 - len) : (16 - len);
d62a17ae 9000
9001 if (len < 1)
a4d82a8a 9002 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 9003 else
a4d82a8a 9004 vty_out(vty, "%*s", len, " ");
d62a17ae 9005 }
445c2480 9006 } else {
aef999a2
DA
9007 if (nexthop_hostname)
9008 len = vty_out(vty, "%pI6(%s)%s",
9009 &attr->mp_nexthop_global,
9010 nexthop_hostname,
9011 vrf_id_str);
9012 else
9013 len = vty_out(vty, "%pI6%s",
9014 &attr->mp_nexthop_global,
9015 vrf_id_str);
9016
ae248832 9017 len = wide ? (41 - len) : (16 - len);
445c2480
DS
9018
9019 if (len < 1)
9020 vty_out(vty, "\n%*s", 36, " ");
9021 else
9022 vty_out(vty, "%*s", len, " ");
d62a17ae 9023 }
9024 }
445c2480 9025 }
718e3744 9026
445c2480
DS
9027 /* MED/Metric */
9028 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 9029 if (json_paths)
50e05855 9030 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
9031 else if (wide)
9032 vty_out(vty, "%7u", attr->med);
0fbac0b4 9033 else
445c2480 9034 vty_out(vty, "%10u", attr->med);
ae248832
MK
9035 else if (!json_paths) {
9036 if (wide)
9037 vty_out(vty, "%*s", 7, " ");
9038 else
9039 vty_out(vty, "%*s", 10, " ");
9040 }
d62a17ae 9041
445c2480
DS
9042 /* Local Pref */
9043 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 9044 if (json_paths)
50e05855 9045 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
9046 attr->local_pref);
9047 else
445c2480
DS
9048 vty_out(vty, "%7u", attr->local_pref);
9049 else if (!json_paths)
9050 vty_out(vty, " ");
d62a17ae 9051
445c2480
DS
9052 if (json_paths)
9053 json_object_int_add(json_path, "weight", attr->weight);
9054 else
9055 vty_out(vty, "%7u ", attr->weight);
47fc97cc 9056
445c2480
DS
9057 if (json_paths) {
9058 char buf[BUFSIZ];
a4d82a8a
PZ
9059 json_object_string_add(
9060 json_path, "peerId",
9b6d8fcf 9061 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 9062 }
b05a1c8b 9063
445c2480
DS
9064 /* Print aspath */
9065 if (attr->aspath) {
0fbac0b4 9066 if (json_paths)
50e05855 9067 json_object_string_add(json_path, "path",
0fbac0b4
DA
9068 attr->aspath->str);
9069 else
445c2480 9070 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9071 }
f1aa5d8a 9072
445c2480
DS
9073 /* Print origin */
9074 if (json_paths)
a4d82a8a
PZ
9075 json_object_string_add(json_path, "origin",
9076 bgp_origin_long_str[attr->origin]);
445c2480
DS
9077 else
9078 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9079
9df8b37c 9080 if (json_paths) {
d071f237 9081 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9082 json_object_string_add(json_path, "esi",
9083 esi_to_str(&attr->esi,
9084 esi_buf, sizeof(esi_buf)));
9085 }
6f214dd3
CS
9086 if (safi == SAFI_EVPN &&
9087 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9088 json_ext_community = json_object_new_object();
9089 json_object_string_add(json_ext_community,
9090 "string",
9091 attr->ecommunity->str);
9092 json_object_object_add(json_path,
9093 "extendedCommunity",
9094 json_ext_community);
9095 }
9096
9df8b37c
PZ
9097 if (nexthop_self)
9098 json_object_boolean_true_add(json_path,
9099 "announceNexthopSelf");
9100 if (nexthop_othervrf) {
9101 json_object_string_add(json_path, "nhVrfName",
9102 nexthop_vrfname);
9103
9104 json_object_int_add(json_path, "nhVrfId",
9105 ((nexthop_vrfid == VRF_UNKNOWN)
9106 ? -1
9107 : (int)nexthop_vrfid));
9108 }
9109 }
9110
d62a17ae 9111 if (json_paths) {
9112 if (json_nexthop_global || json_nexthop_ll) {
9113 json_nexthops = json_object_new_array();
f1aa5d8a 9114
d62a17ae 9115 if (json_nexthop_global)
9116 json_object_array_add(json_nexthops,
9117 json_nexthop_global);
f1aa5d8a 9118
d62a17ae 9119 if (json_nexthop_ll)
9120 json_object_array_add(json_nexthops,
9121 json_nexthop_ll);
f1aa5d8a 9122
d62a17ae 9123 json_object_object_add(json_path, "nexthops",
9124 json_nexthops);
9125 }
9126
9127 json_object_array_add(json_paths, json_path);
9128 } else {
9129 vty_out(vty, "\n");
6f214dd3 9130
b5e140c8 9131 if (safi == SAFI_EVPN) {
229587fb
AK
9132 struct bgp_path_es_info *path_es_info = NULL;
9133
d071f237 9134 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9135 /* XXX - add these params to the json out */
b5e140c8 9136 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9137 vty_out(vty, "ESI:%s",
9138 esi_to_str(&attr->esi, esi_buf,
9139 sizeof(esi_buf)));
60605cbc
AK
9140
9141 if (path->extra && path->extra->mh_info)
9142 path_es_info =
9143 path->extra->mh_info->es_info;
9144
229587fb
AK
9145 if (path_es_info && path_es_info->es)
9146 vty_out(vty, " VNI: %u",
9147 path_es_info->vni);
9148 vty_out(vty, "\n");
b5e140c8
AK
9149 }
9150 if (attr->flag &
9151 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9152 vty_out(vty, "%*s", 20, " ");
9153 vty_out(vty, "%s\n", attr->ecommunity->str);
9154 }
6f214dd3
CS
9155 }
9156
49e5a4a0 9157#ifdef ENABLE_BGP_VNC
d62a17ae 9158 /* prints an additional line, indented, with VNC info, if
9159 * present */
9160 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9161 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9162#endif
d62a17ae 9163 }
9164}
718e3744 9165
9166/* called from terminal list command */
7d3cae70
DA
9167void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9168 const struct prefix *p, struct attr *attr, safi_t safi,
9169 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9170{
9171 json_object *json_status = NULL;
9172 json_object *json_net = NULL;
aef999a2 9173 int len;
d62a17ae 9174 char buff[BUFSIZ];
dc387b0f 9175
d62a17ae 9176 /* Route status display. */
9177 if (use_json) {
9178 json_status = json_object_new_object();
9179 json_net = json_object_new_object();
9180 } else {
9181 vty_out(vty, "*");
9182 vty_out(vty, ">");
9183 vty_out(vty, " ");
9184 }
718e3744 9185
d62a17ae 9186 /* print prefix and mask */
50e05855 9187 if (use_json) {
dc387b0f
LK
9188 if (safi == SAFI_EVPN)
9189 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9190 else if (p->family == AF_INET || p->family == AF_INET6) {
9191 json_object_string_add(
9192 json_net, "addrPrefix",
9193 inet_ntop(p->family, &p->u.prefix, buff,
9194 BUFSIZ));
9195 json_object_int_add(json_net, "prefixLen",
9196 p->prefixlen);
9197 prefix2str(p, buff, PREFIX_STRLEN);
9198 json_object_string_add(json_net, "network", buff);
9199 }
50e05855 9200 } else
7d3cae70 9201 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9202
9203 /* Print attribute */
9204 if (attr) {
9205 if (use_json) {
23d0a753
DA
9206 char buf[BUFSIZ] = {0};
9207
d62a17ae 9208 if (p->family == AF_INET
9209 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9210 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9211 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 9212 json_object_string_add(
9213 json_net, "nextHop",
23d0a753
DA
9214 inet_ntop(
9215 AF_INET,
9216 &attr->mp_nexthop_global_in,
9217 buf, sizeof(buf)));
d62a17ae 9218 else
9219 json_object_string_add(
9220 json_net, "nextHop",
23d0a753
DA
9221 inet_ntop(AF_INET,
9222 &attr->nexthop, buf,
9223 sizeof(buf)));
d62a17ae 9224 } else if (p->family == AF_INET6
9225 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9226 char buf[BUFSIZ];
9227
9228 json_object_string_add(
aa0a10fc 9229 json_net, "nextHopGlobal",
d62a17ae 9230 inet_ntop(AF_INET6,
9231 &attr->mp_nexthop_global, buf,
9232 BUFSIZ));
23d0a753
DA
9233 } else if (p->family == AF_EVPN
9234 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9235 char buf[BUFSIZ] = {0};
9236
9237 json_object_string_add(
9238 json_net, "nextHop",
9239 inet_ntop(AF_INET,
9240 &attr->mp_nexthop_global_in,
9241 buf, sizeof(buf)));
9242 }
d62a17ae 9243
9244 if (attr->flag
9245 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9246 json_object_int_add(json_net, "metric",
9247 attr->med);
9248
0fbac0b4 9249 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9250 json_object_int_add(json_net, "locPrf",
0fbac0b4 9251 attr->local_pref);
d62a17ae 9252
9253 json_object_int_add(json_net, "weight", attr->weight);
9254
9255 /* Print aspath */
0fbac0b4 9256 if (attr->aspath)
50e05855 9257 json_object_string_add(json_net, "path",
0fbac0b4 9258 attr->aspath->str);
d62a17ae 9259
9260 /* Print origin */
9261 json_object_string_add(json_net, "bgpOriginCode",
9262 bgp_origin_str[attr->origin]);
9263 } else {
9264 if (p->family == AF_INET
9265 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9266 || safi == SAFI_EVPN
9267 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9268 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9269 || safi == SAFI_EVPN)
23d0a753
DA
9270 vty_out(vty, "%-16pI4",
9271 &attr->mp_nexthop_global_in);
ae248832 9272 else if (wide)
23d0a753 9273 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9274 else
23d0a753 9275 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9276 } else if (p->family == AF_INET6
9277 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9278 char buf[BUFSIZ];
9279
9280 len = vty_out(
9281 vty, "%s",
9282 inet_ntop(AF_INET6,
9283 &attr->mp_nexthop_global, buf,
9284 BUFSIZ));
ae248832 9285 len = wide ? (41 - len) : (16 - len);
d62a17ae 9286 if (len < 1)
9287 vty_out(vty, "\n%*s", 36, " ");
9288 else
9289 vty_out(vty, "%*s", len, " ");
9290 }
9291 if (attr->flag
9292 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9293 if (wide)
9294 vty_out(vty, "%7u", attr->med);
9295 else
9296 vty_out(vty, "%10u", attr->med);
9297 else if (wide)
9298 vty_out(vty, " ");
d62a17ae 9299 else
9300 vty_out(vty, " ");
718e3744 9301
d62a17ae 9302 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9303 vty_out(vty, "%7u", attr->local_pref);
9304 else
9305 vty_out(vty, " ");
9306
9307 vty_out(vty, "%7u ", attr->weight);
9308
9309 /* Print aspath */
9310 if (attr->aspath)
9311 aspath_print_vty(vty, "%s", attr->aspath, " ");
9312
9313 /* Print origin */
9314 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9315 }
9316 }
9317 if (use_json) {
9318 json_object_boolean_true_add(json_status, "*");
9319 json_object_boolean_true_add(json_status, ">");
9320 json_object_object_add(json_net, "appliedStatusSymbols",
9321 json_status);
1608ff77 9322
dc387b0f
LK
9323 prefix2str(p, buff, PREFIX_STRLEN);
9324 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9325 } else
9326 vty_out(vty, "\n");
9327}
9328
bd494ec5 9329void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9330 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9331 json_object *json)
9332{
9333 json_object *json_out = NULL;
9334 struct attr *attr;
9335 mpls_label_t label = MPLS_INVALID_LABEL;
9336
9b6d8fcf 9337 if (!path->extra)
d62a17ae 9338 return;
9339
9340 if (json)
9341 json_out = json_object_new_object();
9342
9343 /* short status lead text */
82c298be 9344 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9345
9346 /* print prefix and mask */
9347 if (json == NULL) {
9348 if (!display)
7d3cae70 9349 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9350 else
9351 vty_out(vty, "%*s", 17, " ");
9352 }
9353
9354 /* Print attribute */
9b6d8fcf 9355 attr = path->attr;
05864da7
DS
9356 if (((p->family == AF_INET)
9357 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9358 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9359 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9360 char buf[BUFSIZ] = {0};
9361
05864da7
DS
9362 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9363 || safi == SAFI_EVPN) {
9364 if (json)
9365 json_object_string_add(
9366 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9367 inet_ntop(AF_INET,
9368 &attr->mp_nexthop_global_in,
9369 buf, sizeof(buf)));
05864da7 9370 else
23d0a753
DA
9371 vty_out(vty, "%-16pI4",
9372 &attr->mp_nexthop_global_in);
05864da7
DS
9373 } else {
9374 if (json)
9375 json_object_string_add(
9376 json_out, "nexthop",
23d0a753
DA
9377 inet_ntop(AF_INET, &attr->nexthop, buf,
9378 sizeof(buf)));
05864da7 9379 else
23d0a753 9380 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9381 }
9382 } else if (((p->family == AF_INET6)
9383 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9384 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9385 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9386 char buf_a[512];
9387
9388 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9389 if (json)
9390 json_object_string_add(
9391 json_out, "mpNexthopGlobalIn",
9392 inet_ntop(AF_INET6,
9393 &attr->mp_nexthop_global,
9394 buf_a, sizeof(buf_a)));
9395 else
9396 vty_out(vty, "%s",
9397 inet_ntop(AF_INET6,
9398 &attr->mp_nexthop_global,
9399 buf_a, sizeof(buf_a)));
9400 } else if (attr->mp_nexthop_len
9401 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9402 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9403 &attr->mp_nexthop_global,
9404 &attr->mp_nexthop_local);
9405 if (json)
9406 json_object_string_add(json_out,
9407 "mpNexthopGlobalLocal",
9408 buf_a);
9409 else
9410 vty_out(vty, "%s", buf_a);
d62a17ae 9411 }
9412 }
9413
9b6d8fcf 9414 label = decode_label(&path->extra->label[0]);
d62a17ae 9415
9416 if (bgp_is_valid_label(&label)) {
9417 if (json) {
9418 json_object_int_add(json_out, "notag", label);
9419 json_object_array_add(json, json_out);
9420 } else {
9421 vty_out(vty, "notag/%d", label);
9422 vty_out(vty, "\n");
9423 }
9424 }
9425}
718e3744 9426
bd494ec5 9427void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9428 struct bgp_path_info *path, int display,
d62a17ae 9429 json_object *json_paths)
718e3744 9430{
d62a17ae 9431 struct attr *attr;
14f51eba 9432 char buf[BUFSIZ] = {0};
d62a17ae 9433 json_object *json_path = NULL;
14f51eba
LK
9434 json_object *json_nexthop = NULL;
9435 json_object *json_overlay = NULL;
856ca177 9436
9b6d8fcf 9437 if (!path->extra)
d62a17ae 9438 return;
718e3744 9439
14f51eba
LK
9440 if (json_paths) {
9441 json_path = json_object_new_object();
9442 json_overlay = json_object_new_object();
9443 json_nexthop = json_object_new_object();
9444 }
9445
d62a17ae 9446 /* short status lead text */
82c298be 9447 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9448
d62a17ae 9449 /* print prefix and mask */
9450 if (!display)
7d3cae70 9451 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9452 else
9453 vty_out(vty, "%*s", 17, " ");
9454
9455 /* Print attribute */
9b6d8fcf 9456 attr = path->attr;
05864da7
DS
9457 char buf1[BUFSIZ];
9458 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9459
05864da7
DS
9460 switch (af) {
9461 case AF_INET:
9462 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9463 if (!json_path) {
9464 vty_out(vty, "%-16s", buf);
9465 } else {
9466 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9467
05864da7 9468 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9469
05864da7
DS
9470 json_object_object_add(json_path, "nexthop",
9471 json_nexthop);
9472 }
9473 break;
9474 case AF_INET6:
9475 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9476 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9477 if (!json_path) {
9478 vty_out(vty, "%s(%s)", buf, buf1);
9479 } else {
9480 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9481
05864da7
DS
9482 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9483 buf1);
14f51eba 9484
05864da7 9485 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9486
05864da7
DS
9487 json_object_object_add(json_path, "nexthop",
9488 json_nexthop);
9489 }
9490 break;
9491 default:
9492 if (!json_path) {
9493 vty_out(vty, "?");
9494 } else {
9495 json_object_string_add(json_nexthop, "Error",
9496 "Unsupported address-family");
d62a17ae 9497 }
05864da7 9498 }
988258b4 9499
6c924775
DS
9500 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9501
9502 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9503 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9504 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9505 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9506
05864da7
DS
9507 if (!json_path)
9508 vty_out(vty, "/%s", buf);
9509 else
9510 json_object_string_add(json_overlay, "gw", buf);
9511
9512 if (attr->ecommunity) {
9513 char *mac = NULL;
9514 struct ecommunity_val *routermac = ecommunity_lookup(
9515 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9516 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9517
9518 if (routermac)
9519 mac = ecom_mac2str((char *)routermac->val);
9520 if (mac) {
9521 if (!json_path) {
c4efd0f4 9522 vty_out(vty, "/%s", mac);
05864da7
DS
9523 } else {
9524 json_object_string_add(json_overlay, "rmac",
9525 mac);
988258b4 9526 }
05864da7 9527 XFREE(MTYPE_TMP, mac);
988258b4 9528 }
05864da7 9529 }
718e3744 9530
05864da7
DS
9531 if (!json_path) {
9532 vty_out(vty, "\n");
9533 } else {
9534 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9535
05864da7 9536 json_object_array_add(json_paths, json_path);
14f51eba 9537 }
d62a17ae 9538}
718e3744 9539
d62a17ae 9540/* dampening route */
5f040085
DS
9541static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9542 struct bgp_path_info *path, int display,
9543 afi_t afi, safi_t safi, bool use_json,
9544 json_object *json)
d62a17ae 9545{
9546 struct attr *attr;
9547 int len;
9548 char timebuf[BGP_UPTIME_LEN];
9549
9550 /* short status lead text */
82c298be 9551 route_vty_short_status_out(vty, path, p, json);
d62a17ae 9552
9553 /* print prefix and mask */
9554 if (!use_json) {
9555 if (!display)
7d3cae70 9556 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9557 else
9558 vty_out(vty, "%*s", 17, " ");
9559 }
9560
9b6d8fcf 9561 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9562 len = 17 - len;
9563 if (len < 1) {
9564 if (!use_json)
9565 vty_out(vty, "\n%*s", 34, " ");
9566 } else {
9567 if (use_json)
9568 json_object_int_add(json, "peerHost", len);
9569 else
9570 vty_out(vty, "%*s", len, " ");
9571 }
9572
9573 if (use_json)
a935f597
DA
9574 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9575 safi, use_json, json);
d62a17ae 9576 else
9b6d8fcf
DS
9577 vty_out(vty, "%s ",
9578 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9579 BGP_UPTIME_LEN, afi, safi,
9580 use_json, json));
d62a17ae 9581
9582 /* Print attribute */
9b6d8fcf 9583 attr = path->attr;
d62a17ae 9584
05864da7
DS
9585 /* Print aspath */
9586 if (attr->aspath) {
d62a17ae 9587 if (use_json)
05864da7
DS
9588 json_object_string_add(json, "asPath",
9589 attr->aspath->str);
d62a17ae 9590 else
05864da7 9591 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9592 }
05864da7
DS
9593
9594 /* Print origin */
9595 if (use_json)
9596 json_object_string_add(json, "origin",
9597 bgp_origin_str[attr->origin]);
9598 else
9599 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9600
d62a17ae 9601 if (!use_json)
9602 vty_out(vty, "\n");
9603}
718e3744 9604
d62a17ae 9605/* flap route */
5f040085
DS
9606static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9607 struct bgp_path_info *path, int display,
9608 afi_t afi, safi_t safi, bool use_json,
9609 json_object *json)
784d3a42 9610{
d62a17ae 9611 struct attr *attr;
9612 struct bgp_damp_info *bdi;
9613 char timebuf[BGP_UPTIME_LEN];
9614 int len;
784d3a42 9615
9b6d8fcf 9616 if (!path->extra)
d62a17ae 9617 return;
784d3a42 9618
9b6d8fcf 9619 bdi = path->extra->damp_info;
784d3a42 9620
d62a17ae 9621 /* short status lead text */
82c298be 9622 route_vty_short_status_out(vty, path, p, json);
784d3a42 9623
d62a17ae 9624 /* print prefix and mask */
9625 if (!use_json) {
9626 if (!display)
7d3cae70 9627 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9628 else
9629 vty_out(vty, "%*s", 17, " ");
9630 }
784d3a42 9631
9b6d8fcf 9632 len = vty_out(vty, "%s", path->peer->host);
d62a17ae 9633 len = 16 - len;
9634 if (len < 1) {
9635 if (!use_json)
9636 vty_out(vty, "\n%*s", 33, " ");
9637 } else {
9638 if (use_json)
9639 json_object_int_add(json, "peerHost", len);
9640 else
9641 vty_out(vty, "%*s", len, " ");
9642 }
784d3a42 9643
d62a17ae 9644 len = vty_out(vty, "%d", bdi->flap);
9645 len = 5 - len;
9646 if (len < 1) {
9647 if (!use_json)
9648 vty_out(vty, " ");
9649 } else {
9650 if (use_json)
9651 json_object_int_add(json, "bdiFlap", len);
9652 else
9653 vty_out(vty, "%*s", len, " ");
9654 }
9655
9656 if (use_json)
9657 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9658 json);
9659 else
996c9314
LB
9660 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9661 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9662
9b6d8fcf
DS
9663 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9664 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
d62a17ae 9665 if (use_json)
9b6d8fcf 9666 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9667 BGP_UPTIME_LEN, afi, safi,
9668 use_json, json);
d62a17ae 9669 else
9670 vty_out(vty, "%s ",
9b6d8fcf 9671 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597
DA
9672 BGP_UPTIME_LEN, afi,
9673 safi, use_json, json));
d62a17ae 9674 } else {
9675 if (!use_json)
9676 vty_out(vty, "%*s ", 8, " ");
9677 }
9678
9679 /* Print attribute */
9b6d8fcf 9680 attr = path->attr;
d62a17ae 9681
05864da7
DS
9682 /* Print aspath */
9683 if (attr->aspath) {
d62a17ae 9684 if (use_json)
05864da7
DS
9685 json_object_string_add(json, "asPath",
9686 attr->aspath->str);
d62a17ae 9687 else
05864da7 9688 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9689 }
05864da7
DS
9690
9691 /* Print origin */
9692 if (use_json)
9693 json_object_string_add(json, "origin",
9694 bgp_origin_str[attr->origin]);
9695 else
9696 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9697
d62a17ae 9698 if (!use_json)
9699 vty_out(vty, "\n");
9700}
9701
9702static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9703 int *first, const char *header,
9704 json_object *json_adv_to)
9705{
9706 char buf1[INET6_ADDRSTRLEN];
9707 json_object *json_peer = NULL;
9708
9709 if (json_adv_to) {
9710 /* 'advertised-to' is a dictionary of peers we have advertised
9711 * this
9712 * prefix too. The key is the peer's IP or swpX, the value is
9713 * the
9714 * hostname if we know it and "" if not.
9715 */
9716 json_peer = json_object_new_object();
9717
9718 if (peer->hostname)
9719 json_object_string_add(json_peer, "hostname",
9720 peer->hostname);
9721
9722 if (peer->conf_if)
9723 json_object_object_add(json_adv_to, peer->conf_if,
9724 json_peer);
9725 else
9726 json_object_object_add(
9727 json_adv_to,
9728 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9729 json_peer);
9730 } else {
9731 if (*first) {
9732 vty_out(vty, "%s", header);
9733 *first = 0;
9734 }
9735
9736 if (peer->hostname
892fedb6 9737 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9738 if (peer->conf_if)
9739 vty_out(vty, " %s(%s)", peer->hostname,
9740 peer->conf_if);
9741 else
9742 vty_out(vty, " %s(%s)", peer->hostname,
9743 sockunion2str(&peer->su, buf1,
9744 SU_ADDRSTRLEN));
9745 } else {
9746 if (peer->conf_if)
9747 vty_out(vty, " %s", peer->conf_if);
9748 else
9749 vty_out(vty, " %s",
9750 sockunion2str(&peer->su, buf1,
9751 SU_ADDRSTRLEN));
9752 }
9753 }
784d3a42
PG
9754}
9755
dcc68b5e
MS
9756static void route_vty_out_tx_ids(struct vty *vty,
9757 struct bgp_addpath_info_data *d)
9758{
9759 int i;
9760
9761 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9762 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9763 d->addpath_tx_id[i],
9764 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9765 }
9766}
9767
5e4d4c8a 9768static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9769 struct bgp_path_info *pi,
9770 struct attr *attr,
9771 json_object *json_path)
5e4d4c8a
AK
9772{
9773 char esi_buf[ESI_STR_LEN];
9774 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9775 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9776 ATTR_ES_PEER_ROUTER);
9777 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9778 ATTR_ES_PEER_ACTIVE);
9779 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9780 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9781 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9782 if (json_path) {
9783 json_object *json_es_info = NULL;
9784
9785 json_object_string_add(
9786 json_path, "esi",
9787 esi_buf);
9788 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9789 json_es_info = json_object_new_object();
9790 if (es_local)
9791 json_object_boolean_true_add(
9792 json_es_info, "localEs");
9793 if (peer_active)
9794 json_object_boolean_true_add(
9795 json_es_info, "peerActive");
9796 if (peer_proxy)
9797 json_object_boolean_true_add(
9798 json_es_info, "peerProxy");
9799 if (peer_router)
9800 json_object_boolean_true_add(
9801 json_es_info, "peerRouter");
9802 if (attr->mm_sync_seqnum)
9803 json_object_int_add(
9804 json_es_info, "peerSeq",
9805 attr->mm_sync_seqnum);
9806 json_object_object_add(
9807 json_path, "es_info",
9808 json_es_info);
9809 }
9810 } else {
9811 if (bgp_evpn_attr_is_sync(attr))
9812 vty_out(vty,
9813 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9814 esi_buf,
9815 es_local ? "local-es":"",
9816 peer_proxy ? "proxy " : "",
9817 peer_active ? "active ":"",
9818 peer_router ? "router ":"",
9819 attr->mm_sync_seqnum);
9820 else
9821 vty_out(vty, " ESI %s %s\n",
9822 esi_buf,
9823 es_local ? "local-es":"");
9824 }
9825}
9826
4933eaaf
DS
9827void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9828 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9829 enum rpki_states rpki_curr_state,
9830 json_object *json_paths)
d62a17ae 9831{
9832 char buf[INET6_ADDRSTRLEN];
9833 char buf1[BUFSIZ];
515c2602 9834 struct attr *attr = path->attr;
d62a17ae 9835 int sockunion_vty_out(struct vty *, union sockunion *);
9836 time_t tbuf;
9837 json_object *json_bestpath = NULL;
9838 json_object *json_cluster_list = NULL;
9839 json_object *json_cluster_list_list = NULL;
9840 json_object *json_ext_community = NULL;
9841 json_object *json_last_update = NULL;
7fd077aa 9842 json_object *json_pmsi = NULL;
d62a17ae 9843 json_object *json_nexthop_global = NULL;
9844 json_object *json_nexthop_ll = NULL;
9845 json_object *json_nexthops = NULL;
9846 json_object *json_path = NULL;
9847 json_object *json_peer = NULL;
9848 json_object *json_string = NULL;
9849 json_object *json_adv_to = NULL;
9850 int first = 0;
9851 struct listnode *node, *nnode;
9852 struct peer *peer;
9853 int addpath_capable;
9854 int has_adj;
9855 unsigned int first_as;
1defdda8 9856 bool nexthop_self =
9b6d8fcf 9857 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9858 int i;
2ba93fd6
DA
9859 char *nexthop_hostname =
9860 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9861
9862 if (json_paths) {
9863 json_path = json_object_new_object();
9864 json_peer = json_object_new_object();
9865 json_nexthop_global = json_object_new_object();
9866 }
9867
44c69747 9868 if (path->extra) {
b57ba6d2 9869 char tag_buf[30];
d62a17ae 9870
d62a17ae 9871 tag_buf[0] = '\0';
9b6d8fcf
DS
9872 if (path->extra && path->extra->num_labels) {
9873 bgp_evpn_label2str(path->extra->label,
9874 path->extra->num_labels, tag_buf,
a4d82a8a 9875 sizeof(tag_buf));
d62a17ae 9876 }
d7325ee7 9877 if (safi == SAFI_EVPN) {
44c69747 9878 if (!json_paths) {
2dbe669b
DA
9879 vty_out(vty, " Route %pFX",
9880 (struct prefix_evpn *)
9881 bgp_dest_get_prefix(bn));
44c69747
LK
9882 if (tag_buf[0] != '\0')
9883 vty_out(vty, " VNI %s", tag_buf);
9884 vty_out(vty, "\n");
9885 } else {
9886 if (tag_buf[0])
9887 json_object_string_add(json_path, "VNI",
9888 tag_buf);
9889 }
d7325ee7
DD
9890 }
9891
44c69747 9892 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9893 struct bgp_path_info *parent_ri;
9bcb3eef 9894 struct bgp_dest *dest, *pdest;
d62a17ae 9895
9b6d8fcf 9896 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9897 dest = parent_ri->net;
9898 if (dest && dest->pdest) {
9899 pdest = dest->pdest;
9900 prefix_rd2str(
9901 (struct prefix_rd *)bgp_dest_get_prefix(
9902 pdest),
9903 buf1, sizeof(buf1));
d7325ee7 9904 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9905 vty_out(vty,
58bff4d1 9906 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9907 buf1,
9908 (struct prefix_evpn *)
9909 bgp_dest_get_prefix(
9910 dest),
9911 tag_buf);
58bff4d1
AK
9912 if (attr->es_flags & ATTR_ES_L3_NHG)
9913 vty_out(vty, ", L3NHG %s",
9914 (attr->es_flags
9915 & ATTR_ES_L3_NHG_ACTIVE)
9916 ? "active"
9917 : "inactive");
9918 vty_out(vty, "\n");
9919
d7325ee7 9920 } else
2dbe669b
DA
9921 vty_out(vty,
9922 " Imported from %s:%pFX\n",
9923 buf1,
9924 (struct prefix_evpn *)
9925 bgp_dest_get_prefix(
9926 dest));
d62a17ae 9927 }
9928 }
9929 }
d62a17ae 9930
05864da7
DS
9931 /* Line1 display AS-path, Aggregator */
9932 if (attr->aspath) {
9933 if (json_paths) {
9934 if (!attr->aspath->json)
9935 aspath_str_update(attr->aspath, true);
9936 json_object_lock(attr->aspath->json);
9937 json_object_object_add(json_path, "aspath",
9938 attr->aspath->json);
9939 } else {
9940 if (attr->aspath->segments)
9941 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9942 else
05864da7 9943 vty_out(vty, " Local");
d62a17ae 9944 }
05864da7 9945 }
d62a17ae 9946
05864da7
DS
9947 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9948 if (json_paths)
9949 json_object_boolean_true_add(json_path, "removed");
9950 else
9951 vty_out(vty, ", (removed)");
9952 }
d62a17ae 9953
05864da7
DS
9954 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9955 if (json_paths)
9956 json_object_boolean_true_add(json_path, "stale");
9957 else
9958 vty_out(vty, ", (stale)");
9959 }
d62a17ae 9960
05864da7
DS
9961 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9962 if (json_paths) {
23d0a753
DA
9963 char buf[BUFSIZ] = {0};
9964
05864da7
DS
9965 json_object_int_add(json_path, "aggregatorAs",
9966 attr->aggregator_as);
23d0a753
DA
9967 json_object_string_add(json_path, "aggregatorId",
9968 inet_ntop(AF_INET,
9969 &attr->aggregator_addr,
9970 buf, sizeof(buf)));
05864da7 9971 } else {
88d495a9
DA
9972 vty_out(vty, ", (aggregated by %u %pI4)",
9973 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9974 }
05864da7 9975 }
d62a17ae 9976
05864da7
DS
9977 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9978 PEER_FLAG_REFLECTOR_CLIENT)) {
9979 if (json_paths)
9980 json_object_boolean_true_add(json_path,
9981 "rxedFromRrClient");
9982 else
9983 vty_out(vty, ", (Received from a RR-client)");
9984 }
d62a17ae 9985
05864da7
DS
9986 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9987 PEER_FLAG_RSERVER_CLIENT)) {
9988 if (json_paths)
9989 json_object_boolean_true_add(json_path,
9990 "rxedFromRsClient");
9991 else
9992 vty_out(vty, ", (Received from a RS-client)");
9993 }
d62a17ae 9994
05864da7
DS
9995 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9996 if (json_paths)
9997 json_object_boolean_true_add(json_path,
9998 "dampeningHistoryEntry");
9999 else
10000 vty_out(vty, ", (history entry)");
10001 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
10002 if (json_paths)
10003 json_object_boolean_true_add(json_path,
10004 "dampeningSuppressed");
10005 else
10006 vty_out(vty, ", (suppressed due to dampening)");
10007 }
d62a17ae 10008
05864da7
DS
10009 if (!json_paths)
10010 vty_out(vty, "\n");
d62a17ae 10011
05864da7
DS
10012 /* Line2 display Next-hop, Neighbor, Router-id */
10013 /* Display the nexthop */
9bcb3eef 10014 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
10015
10016 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
10017 || bn_p->family == AF_EVPN)
05864da7
DS
10018 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
10019 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
10020 char buf[BUFSIZ] = {0};
10021
05864da7
DS
10022 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
10023 || safi == SAFI_EVPN) {
515c2602 10024 if (json_paths) {
d62a17ae 10025 json_object_string_add(
515c2602 10026 json_nexthop_global, "ip",
23d0a753
DA
10027 inet_ntop(AF_INET,
10028 &attr->mp_nexthop_global_in,
10029 buf, sizeof(buf)));
515c2602 10030
939a97f4 10031 if (path->peer->hostname)
515c2602
DA
10032 json_object_string_add(
10033 json_nexthop_global, "hostname",
939a97f4 10034 path->peer->hostname);
aef999a2
DA
10035 } else {
10036 if (nexthop_hostname)
10037 vty_out(vty, " %pI4(%s)",
10038 &attr->mp_nexthop_global_in,
10039 nexthop_hostname);
10040 else
10041 vty_out(vty, " %pI4",
10042 &attr->mp_nexthop_global_in);
10043 }
d62a17ae 10044 } else {
515c2602 10045 if (json_paths) {
05864da7 10046 json_object_string_add(
515c2602 10047 json_nexthop_global, "ip",
23d0a753
DA
10048 inet_ntop(AF_INET, &attr->nexthop, buf,
10049 sizeof(buf)));
515c2602 10050
939a97f4 10051 if (path->peer->hostname)
515c2602
DA
10052 json_object_string_add(
10053 json_nexthop_global, "hostname",
939a97f4 10054 path->peer->hostname);
aef999a2
DA
10055 } else {
10056 if (nexthop_hostname)
10057 vty_out(vty, " %pI4(%s)",
10058 &attr->nexthop,
10059 nexthop_hostname);
10060 else
10061 vty_out(vty, " %pI4",
10062 &attr->nexthop);
10063 }
d62a17ae 10064 }
10065
05864da7
DS
10066 if (json_paths)
10067 json_object_string_add(json_nexthop_global, "afi",
10068 "ipv4");
10069 } else {
10070 if (json_paths) {
10071 json_object_string_add(
515c2602
DA
10072 json_nexthop_global, "ip",
10073 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
10074 buf, INET6_ADDRSTRLEN));
10075
939a97f4 10076 if (path->peer->hostname)
515c2602
DA
10077 json_object_string_add(json_nexthop_global,
10078 "hostname",
939a97f4 10079 path->peer->hostname);
515c2602 10080
05864da7
DS
10081 json_object_string_add(json_nexthop_global, "afi",
10082 "ipv6");
10083 json_object_string_add(json_nexthop_global, "scope",
10084 "global");
10085 } else {
aef999a2
DA
10086 if (nexthop_hostname)
10087 vty_out(vty, " %pI6(%s)",
10088 &attr->mp_nexthop_global,
10089 nexthop_hostname);
10090 else
10091 vty_out(vty, " %pI6",
10092 &attr->mp_nexthop_global);
d62a17ae 10093 }
05864da7 10094 }
d62a17ae 10095
05864da7
DS
10096 /* Display the IGP cost or 'inaccessible' */
10097 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10098 if (json_paths)
10099 json_object_boolean_false_add(json_nexthop_global,
10100 "accessible");
10101 else
10102 vty_out(vty, " (inaccessible)");
10103 } else {
10104 if (path->extra && path->extra->igpmetric) {
d62a17ae 10105 if (json_paths)
05864da7
DS
10106 json_object_int_add(json_nexthop_global,
10107 "metric",
10108 path->extra->igpmetric);
d62a17ae 10109 else
05864da7
DS
10110 vty_out(vty, " (metric %u)",
10111 path->extra->igpmetric);
d62a17ae 10112 }
10113
05864da7 10114 /* IGP cost is 0, display this only for json */
d62a17ae 10115 else {
d62a17ae 10116 if (json_paths)
05864da7
DS
10117 json_object_int_add(json_nexthop_global,
10118 "metric", 0);
d62a17ae 10119 }
d62a17ae 10120
05864da7
DS
10121 if (json_paths)
10122 json_object_boolean_true_add(json_nexthop_global,
10123 "accessible");
10124 }
d62a17ae 10125
05864da7
DS
10126 /* Display peer "from" output */
10127 /* This path was originated locally */
10128 if (path->peer == bgp->peer_self) {
d62a17ae 10129
05864da7 10130 if (safi == SAFI_EVPN
b54892e0 10131 || (bn_p->family == AF_INET
05864da7 10132 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10133 if (json_paths)
05864da7
DS
10134 json_object_string_add(json_peer, "peerId",
10135 "0.0.0.0");
d62a17ae 10136 else
05864da7
DS
10137 vty_out(vty, " from 0.0.0.0 ");
10138 } else {
d62a17ae 10139 if (json_paths)
05864da7
DS
10140 json_object_string_add(json_peer, "peerId",
10141 "::");
d62a17ae 10142 else
05864da7 10143 vty_out(vty, " from :: ");
d62a17ae 10144 }
d62a17ae 10145
23d0a753
DA
10146 if (json_paths) {
10147 char buf[BUFSIZ] = {0};
10148
05864da7 10149 json_object_string_add(json_peer, "routerId",
23d0a753
DA
10150 inet_ntop(AF_INET,
10151 &bgp->router_id, buf,
10152 sizeof(buf)));
10153 } else {
10154 vty_out(vty, "(%pI4)", &bgp->router_id);
10155 }
05864da7 10156 }
d62a17ae 10157
05864da7
DS
10158 /* We RXed this path from one of our peers */
10159 else {
10160
10161 if (json_paths) {
10162 json_object_string_add(json_peer, "peerId",
10163 sockunion2str(&path->peer->su,
10164 buf,
10165 SU_ADDRSTRLEN));
10166 json_object_string_add(json_peer, "routerId",
10167 inet_ntop(AF_INET,
10168 &path->peer->remote_id,
10169 buf1, sizeof(buf1)));
10170
10171 if (path->peer->hostname)
10172 json_object_string_add(json_peer, "hostname",
10173 path->peer->hostname);
10174
10175 if (path->peer->domainname)
10176 json_object_string_add(json_peer, "domainname",
10177 path->peer->domainname);
10178
10179 if (path->peer->conf_if)
10180 json_object_string_add(json_peer, "interface",
10181 path->peer->conf_if);
10182 } else {
10183 if (path->peer->conf_if) {
10184 if (path->peer->hostname
892fedb6
DA
10185 && CHECK_FLAG(path->peer->bgp->flags,
10186 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10187 vty_out(vty, " from %s(%s)",
10188 path->peer->hostname,
10189 path->peer->conf_if);
d62a17ae 10190 else
05864da7 10191 vty_out(vty, " from %s",
9b6d8fcf 10192 path->peer->conf_if);
d62a17ae 10193 } else {
05864da7 10194 if (path->peer->hostname
892fedb6
DA
10195 && CHECK_FLAG(path->peer->bgp->flags,
10196 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10197 vty_out(vty, " from %s(%s)",
10198 path->peer->hostname,
10199 path->peer->host);
d62a17ae 10200 else
05864da7
DS
10201 vty_out(vty, " from %s",
10202 sockunion2str(&path->peer->su,
10203 buf,
10204 SU_ADDRSTRLEN));
d62a17ae 10205 }
d62a17ae 10206
05864da7 10207 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10208 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10209 else
10210 vty_out(vty, " (%s)",
10211 inet_ntop(AF_INET,
10212 &path->peer->remote_id, buf1,
10213 sizeof(buf1)));
d62a17ae 10214 }
05864da7 10215 }
9df8b37c 10216
05864da7
DS
10217 /*
10218 * Note when vrfid of nexthop is different from that of prefix
10219 */
10220 if (path->extra && path->extra->bgp_orig) {
10221 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10222
05864da7
DS
10223 if (json_paths) {
10224 const char *vn;
9df8b37c 10225
05864da7
DS
10226 if (path->extra->bgp_orig->inst_type
10227 == BGP_INSTANCE_TYPE_DEFAULT)
10228 vn = VRF_DEFAULT_NAME;
10229 else
10230 vn = path->extra->bgp_orig->name;
9df8b37c 10231
05864da7 10232 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10233
05864da7
DS
10234 if (nexthop_vrfid == VRF_UNKNOWN) {
10235 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10236 } else {
05864da7
DS
10237 json_object_int_add(json_path, "nhVrfId",
10238 (int)nexthop_vrfid);
9df8b37c 10239 }
05864da7
DS
10240 } else {
10241 if (nexthop_vrfid == VRF_UNKNOWN)
10242 vty_out(vty, " vrf ?");
137147c6
DS
10243 else {
10244 struct vrf *vrf;
10245
10246 vrf = vrf_lookup_by_id(nexthop_vrfid);
10247 vty_out(vty, " vrf %s(%u)",
10248 VRF_LOGNAME(vrf), nexthop_vrfid);
10249 }
9df8b37c 10250 }
05864da7 10251 }
9df8b37c 10252
05864da7
DS
10253 if (nexthop_self) {
10254 if (json_paths) {
10255 json_object_boolean_true_add(json_path,
10256 "announceNexthopSelf");
10257 } else {
10258 vty_out(vty, " announce-nh-self");
9df8b37c 10259 }
05864da7 10260 }
9df8b37c 10261
05864da7
DS
10262 if (!json_paths)
10263 vty_out(vty, "\n");
d62a17ae 10264
05864da7
DS
10265 /* display the link-local nexthop */
10266 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10267 if (json_paths) {
10268 json_nexthop_ll = json_object_new_object();
10269 json_object_string_add(
515c2602
DA
10270 json_nexthop_ll, "ip",
10271 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10272 buf, INET6_ADDRSTRLEN));
10273
939a97f4 10274 if (path->peer->hostname)
515c2602
DA
10275 json_object_string_add(json_nexthop_ll,
10276 "hostname",
939a97f4 10277 path->peer->hostname);
515c2602 10278
05864da7
DS
10279 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10280 json_object_string_add(json_nexthop_ll, "scope",
10281 "link-local");
d62a17ae 10282
05864da7
DS
10283 json_object_boolean_true_add(json_nexthop_ll,
10284 "accessible");
d62a17ae 10285
05864da7 10286 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10287 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10288 "used");
10289 else
10290 json_object_boolean_true_add(
10291 json_nexthop_global, "used");
10292 } else {
10293 vty_out(vty, " (%s) %s\n",
10294 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10295 buf, INET6_ADDRSTRLEN),
10296 attr->mp_nexthop_prefer_global
10297 ? "(prefer-global)"
10298 : "(used)");
d62a17ae 10299 }
05864da7
DS
10300 }
10301 /* If we do not have a link-local nexthop then we must flag the
10302 global as "used" */
10303 else {
10304 if (json_paths)
10305 json_object_boolean_true_add(json_nexthop_global,
10306 "used");
10307 }
d62a17ae 10308
b5e140c8 10309 if (safi == SAFI_EVPN &&
5e4d4c8a 10310 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10311 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10312 }
10313
05864da7
DS
10314 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10315 * Int/Ext/Local, Atomic, best */
10316 if (json_paths)
10317 json_object_string_add(json_path, "origin",
10318 bgp_origin_long_str[attr->origin]);
10319 else
10320 vty_out(vty, " Origin %s",
10321 bgp_origin_long_str[attr->origin]);
9df8b37c 10322
05864da7 10323 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10324 if (json_paths)
05864da7 10325 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10326 else
05864da7
DS
10327 vty_out(vty, ", metric %u", attr->med);
10328 }
9df8b37c 10329
05864da7
DS
10330 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10331 if (json_paths)
0fbac0b4 10332 json_object_int_add(json_path, "locPrf",
05864da7
DS
10333 attr->local_pref);
10334 else
10335 vty_out(vty, ", localpref %u", attr->local_pref);
10336 }
9df8b37c 10337
05864da7
DS
10338 if (attr->weight != 0) {
10339 if (json_paths)
10340 json_object_int_add(json_path, "weight", attr->weight);
10341 else
10342 vty_out(vty, ", weight %u", attr->weight);
10343 }
9df8b37c 10344
05864da7
DS
10345 if (attr->tag != 0) {
10346 if (json_paths)
10347 json_object_int_add(json_path, "tag", attr->tag);
10348 else
10349 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10350 }
9df8b37c 10351
05864da7
DS
10352 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10353 if (json_paths)
10354 json_object_boolean_false_add(json_path, "valid");
10355 else
10356 vty_out(vty, ", invalid");
10357 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10358 if (json_paths)
10359 json_object_boolean_true_add(json_path, "valid");
10360 else
10361 vty_out(vty, ", valid");
10362 }
9df8b37c 10363
7d3cae70
DA
10364 if (json_paths)
10365 json_object_int_add(json_path, "version", bn->version);
10366
05864da7
DS
10367 if (path->peer != bgp->peer_self) {
10368 if (path->peer->as == path->peer->local_as) {
10369 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10370 if (json_paths)
10371 json_object_string_add(
10372 json_peer, "type",
10373 "confed-internal");
d62a17ae 10374 else
05864da7 10375 vty_out(vty, ", confed-internal");
d62a17ae 10376 } else {
05864da7
DS
10377 if (json_paths)
10378 json_object_string_add(
10379 json_peer, "type", "internal");
10380 else
10381 vty_out(vty, ", internal");
9df8b37c 10382 }
05864da7
DS
10383 } else {
10384 if (bgp_confederation_peers_check(bgp,
10385 path->peer->as)) {
10386 if (json_paths)
10387 json_object_string_add(
10388 json_peer, "type",
10389 "confed-external");
d62a17ae 10390 else
05864da7 10391 vty_out(vty, ", confed-external");
d62a17ae 10392 } else {
05864da7
DS
10393 if (json_paths)
10394 json_object_string_add(
10395 json_peer, "type", "external");
10396 else
10397 vty_out(vty, ", external");
d62a17ae 10398 }
10399 }
05864da7
DS
10400 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10401 if (json_paths) {
10402 json_object_boolean_true_add(json_path, "aggregated");
10403 json_object_boolean_true_add(json_path, "local");
10404 } else {
10405 vty_out(vty, ", aggregated, local");
10406 }
10407 } else if (path->type != ZEBRA_ROUTE_BGP) {
10408 if (json_paths)
10409 json_object_boolean_true_add(json_path, "sourced");
10410 else
10411 vty_out(vty, ", sourced");
10412 } else {
10413 if (json_paths) {
10414 json_object_boolean_true_add(json_path, "sourced");
10415 json_object_boolean_true_add(json_path, "local");
10416 } else {
10417 vty_out(vty, ", sourced, local");
d62a17ae 10418 }
05864da7 10419 }
718e3744 10420
05864da7 10421 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10422 if (json_paths)
05864da7
DS
10423 json_object_boolean_true_add(json_path,
10424 "atomicAggregate");
d62a17ae 10425 else
05864da7
DS
10426 vty_out(vty, ", atomic-aggregate");
10427 }
d62a17ae 10428
05864da7
DS
10429 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10430 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10431 && bgp_path_info_mpath_count(path))) {
10432 if (json_paths)
10433 json_object_boolean_true_add(json_path, "multipath");
10434 else
10435 vty_out(vty, ", multipath");
10436 }
50e05855 10437
05864da7
DS
10438 // Mark the bestpath(s)
10439 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10440 first_as = aspath_get_first_as(attr->aspath);
718e3744 10441
05864da7
DS
10442 if (json_paths) {
10443 if (!json_bestpath)
10444 json_bestpath = json_object_new_object();
10445 json_object_int_add(json_bestpath, "bestpathFromAs",
10446 first_as);
10447 } else {
10448 if (first_as)
10449 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10450 else
05864da7 10451 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10452 }
05864da7 10453 }
718e3744 10454
05864da7
DS
10455 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10456 if (json_paths) {
10457 if (!json_bestpath)
10458 json_bestpath = json_object_new_object();
10459 json_object_boolean_true_add(json_bestpath, "overall");
10460 json_object_string_add(
10461 json_bestpath, "selectionReason",
10462 bgp_path_selection_reason2str(bn->reason));
10463 } else {
10464 vty_out(vty, ", best");
10465 vty_out(vty, " (%s)",
10466 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10467 }
05864da7 10468 }
718e3744 10469
4027d19b 10470 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10471 if (json_paths)
10472 json_object_string_add(
10473 json_path, "rpkiValidationState",
4027d19b 10474 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10475 else
1d327209 10476 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10477 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10478 }
10479
05864da7
DS
10480 if (json_bestpath)
10481 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10482
05864da7
DS
10483 if (!json_paths)
10484 vty_out(vty, "\n");
10485
10486 /* Line 4 display Community */
29e72930 10487 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10488 if (json_paths) {
10489 if (!attr->community->json)
10490 community_str(attr->community, true);
10491 json_object_lock(attr->community->json);
10492 json_object_object_add(json_path, "community",
10493 attr->community->json);
10494 } else {
10495 vty_out(vty, " Community: %s\n",
10496 attr->community->str);
d62a17ae 10497 }
05864da7 10498 }
718e3744 10499
05864da7
DS
10500 /* Line 5 display Extended-community */
10501 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10502 if (json_paths) {
10503 json_ext_community = json_object_new_object();
10504 json_object_string_add(json_ext_community, "string",
10505 attr->ecommunity->str);
10506 json_object_object_add(json_path, "extendedCommunity",
10507 json_ext_community);
d62a17ae 10508 } else {
05864da7
DS
10509 vty_out(vty, " Extended Community: %s\n",
10510 attr->ecommunity->str);
d62a17ae 10511 }
05864da7 10512 }
718e3744 10513
05864da7
DS
10514 /* Line 6 display Large community */
10515 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10516 if (json_paths) {
10517 if (!attr->lcommunity->json)
10518 lcommunity_str(attr->lcommunity, true);
10519 json_object_lock(attr->lcommunity->json);
10520 json_object_object_add(json_path, "largeCommunity",
10521 attr->lcommunity->json);
10522 } else {
10523 vty_out(vty, " Large Community: %s\n",
10524 attr->lcommunity->str);
d62a17ae 10525 }
05864da7 10526 }
718e3744 10527
05864da7
DS
10528 /* Line 7 display Originator, Cluster-id */
10529 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10530 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10531 char buf[BUFSIZ] = {0};
10532
05864da7 10533 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10534 if (json_paths)
05864da7
DS
10535 json_object_string_add(
10536 json_path, "originatorId",
23d0a753
DA
10537 inet_ntop(AF_INET, &attr->originator_id,
10538 buf, sizeof(buf)));
d62a17ae 10539 else
23d0a753
DA
10540 vty_out(vty, " Originator: %pI4",
10541 &attr->originator_id);
d62a17ae 10542 }
856ca177 10543
05864da7 10544 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10545 struct cluster_list *cluster =
10546 bgp_attr_get_cluster(attr);
05864da7 10547 int i;
d62a17ae 10548
10549 if (json_paths) {
05864da7
DS
10550 json_cluster_list = json_object_new_object();
10551 json_cluster_list_list =
10552 json_object_new_array();
10553
779fee93 10554 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10555 json_string = json_object_new_string(
779fee93
DS
10556 inet_ntop(AF_INET,
10557 &cluster->list[i],
10558 buf, sizeof(buf)));
05864da7
DS
10559 json_object_array_add(
10560 json_cluster_list_list,
10561 json_string);
10562 }
718e3744 10563
05864da7
DS
10564 /*
10565 * struct cluster_list does not have
10566 * "str" variable like aspath and community
10567 * do. Add this someday if someone asks
10568 * for it.
10569 * json_object_string_add(json_cluster_list,
779fee93 10570 * "string", cluster->str);
05864da7
DS
10571 */
10572 json_object_object_add(json_cluster_list,
10573 "list",
10574 json_cluster_list_list);
10575 json_object_object_add(json_path, "clusterList",
10576 json_cluster_list);
0dc8ee70 10577 } else {
05864da7
DS
10578 vty_out(vty, ", Cluster list: ");
10579
779fee93 10580 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10581 vty_out(vty, "%pI4 ",
779fee93 10582 &cluster->list[i]);
05864da7 10583 }
0dc8ee70 10584 }
d62a17ae 10585 }
718e3744 10586
d62a17ae 10587 if (!json_paths)
10588 vty_out(vty, "\n");
05864da7 10589 }
d62a17ae 10590
05864da7 10591 if (path->extra && path->extra->damp_info)
40ec3340 10592 bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
adbac85e 10593
05864da7
DS
10594 /* Remote Label */
10595 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10596 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10597 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10598
05864da7
DS
10599 if (json_paths)
10600 json_object_int_add(json_path, "remoteLabel", label);
10601 else
10602 vty_out(vty, " Remote label: %d\n", label);
10603 }
d62a17ae 10604
e496b420
HS
10605 /* Remote SID */
10606 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
10607 inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
10608 if (json_paths)
10609 json_object_string_add(json_path, "remoteSid", buf);
10610 else
10611 vty_out(vty, " Remote SID: %s\n", buf);
10612 }
10613
05864da7
DS
10614 /* Label Index */
10615 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10616 if (json_paths)
10617 json_object_int_add(json_path, "labelIndex",
10618 attr->label_index);
10619 else
10620 vty_out(vty, " Label Index: %d\n",
10621 attr->label_index);
10622 }
d62a17ae 10623
05864da7
DS
10624 /* Line 8 display Addpath IDs */
10625 if (path->addpath_rx_id
10626 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10627 if (json_paths) {
10628 json_object_int_add(json_path, "addpathRxId",
10629 path->addpath_rx_id);
d62a17ae 10630
05864da7
DS
10631 /* Keep backwards compatibility with the old API
10632 * by putting TX All's ID in the old field
10633 */
10634 json_object_int_add(
10635 json_path, "addpathTxId",
10636 path->tx_addpath
10637 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10638
05864da7
DS
10639 /* ... but create a specific field for each
10640 * strategy
10641 */
10642 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10643 json_object_int_add(
10644 json_path,
10645 bgp_addpath_names(i)->id_json_name,
10646 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10647 }
05864da7
DS
10648 } else {
10649 vty_out(vty, " AddPath ID: RX %u, ",
10650 path->addpath_rx_id);
d62a17ae 10651
05864da7 10652 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10653 }
05864da7 10654 }
520d5d76 10655
05864da7
DS
10656 /* If we used addpath to TX a non-bestpath we need to display
10657 * "Advertised to" on a path-by-path basis
10658 */
10659 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10660 first = 1;
dcc68b5e 10661
05864da7
DS
10662 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10663 addpath_capable =
10664 bgp_addpath_encode_tx(peer, afi, safi);
10665 has_adj = bgp_adj_out_lookup(
10666 peer, path->net,
10667 bgp_addpath_id_for_peer(peer, afi, safi,
10668 &path->tx_addpath));
10669
10670 if ((addpath_capable && has_adj)
10671 || (!addpath_capable && has_adj
10672 && CHECK_FLAG(path->flags,
10673 BGP_PATH_SELECTED))) {
10674 if (json_path && !json_adv_to)
10675 json_adv_to = json_object_new_object();
dcc68b5e 10676
05864da7
DS
10677 route_vty_out_advertised_to(
10678 vty, peer, &first,
10679 " Advertised to:", json_adv_to);
d62a17ae 10680 }
10681 }
718e3744 10682
05864da7
DS
10683 if (json_path) {
10684 if (json_adv_to) {
10685 json_object_object_add(
10686 json_path, "advertisedTo", json_adv_to);
d62a17ae 10687 }
05864da7
DS
10688 } else {
10689 if (!first) {
10690 vty_out(vty, "\n");
d62a17ae 10691 }
10692 }
05864da7 10693 }
b05a1c8b 10694
05864da7
DS
10695 /* Line 9 display Uptime */
10696 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10697 if (json_paths) {
10698 json_last_update = json_object_new_object();
10699 json_object_int_add(json_last_update, "epoch", tbuf);
10700 json_object_string_add(json_last_update, "string",
10701 ctime(&tbuf));
10702 json_object_object_add(json_path, "lastUpdate",
10703 json_last_update);
10704 } else
10705 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10706
05864da7
DS
10707 /* Line 10 display PMSI tunnel attribute, if present */
10708 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10709 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10710 bgp_attr_get_pmsi_tnl_type(attr),
10711 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10712
05864da7
DS
10713 if (json_paths) {
10714 json_pmsi = json_object_new_object();
10715 json_object_string_add(json_pmsi, "tunnelType", str);
10716 json_object_int_add(json_pmsi, "label",
10717 label2vni(&attr->label));
10718 json_object_object_add(json_path, "pmsi", json_pmsi);
10719 } else
10720 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10721 str, label2vni(&attr->label));
d62a17ae 10722 }
f1aa5d8a 10723
92269aa2
DS
10724 /* Output some debug about internal state of the dest flags */
10725 if (json_paths) {
10726 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10727 json_object_boolean_true_add(json_path, "processScheduled");
10728 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10729 json_object_boolean_true_add(json_path, "userCleared");
10730 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10731 json_object_boolean_true_add(json_path, "labelChanged");
10732 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10733 json_object_boolean_true_add(json_path, "registeredForLabel");
10734 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10735 json_object_boolean_true_add(json_path, "selectDefered");
10736 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10737 json_object_boolean_true_add(json_path, "fibInstalled");
10738 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10739 json_object_boolean_true_add(json_path, "fibPending");
10740 }
10741
d62a17ae 10742 /* We've constructed the json object for this path, add it to the json
10743 * array of paths
10744 */
10745 if (json_paths) {
10746 if (json_nexthop_global || json_nexthop_ll) {
10747 json_nexthops = json_object_new_array();
f1aa5d8a 10748
d62a17ae 10749 if (json_nexthop_global)
10750 json_object_array_add(json_nexthops,
10751 json_nexthop_global);
f1aa5d8a 10752
d62a17ae 10753 if (json_nexthop_ll)
10754 json_object_array_add(json_nexthops,
10755 json_nexthop_ll);
f1aa5d8a 10756
d62a17ae 10757 json_object_object_add(json_path, "nexthops",
10758 json_nexthops);
10759 }
10760
10761 json_object_object_add(json_path, "peer", json_peer);
10762 json_object_array_add(json_paths, json_path);
05864da7 10763 }
b366b518
BB
10764}
10765
96ade3ed 10766#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10767#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10768#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10769
d62a17ae 10770static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10771 const char *prefix_list_str, afi_t afi,
10772 safi_t safi, enum bgp_show_type type);
10773static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10774 const char *filter, afi_t afi, safi_t safi,
10775 enum bgp_show_type type);
10776static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10777 const char *rmap_str, afi_t afi, safi_t safi,
10778 enum bgp_show_type type);
10779static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10780 const char *com, int exact, afi_t afi,
10781 safi_t safi);
10782static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10783 const char *prefix, afi_t afi, safi_t safi,
10784 enum bgp_show_type type);
a4d82a8a 10785static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10786 afi_t afi, safi_t safi, enum bgp_show_type type,
10787 bool use_json);
7f323236
DW
10788static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10789 const char *comstr, int exact, afi_t afi,
96c81f66 10790 safi_t safi, uint16_t show_flags);
d62a17ae 10791
1ae44dfc 10792static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10793 struct bgp_table *table, enum bgp_show_type type,
96f3485c
MK
10794 void *output_arg, char *rd, int is_last,
10795 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10796 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10797 enum rpki_states rpki_target_state)
d62a17ae 10798{
40381db7 10799 struct bgp_path_info *pi;
9bcb3eef 10800 struct bgp_dest *dest;
d62a17ae 10801 int header = 1;
10802 int display;
1ae44dfc
LB
10803 unsigned long output_count = 0;
10804 unsigned long total_count = 0;
d62a17ae 10805 struct prefix *p;
d62a17ae 10806 json_object *json_paths = NULL;
10807 int first = 1;
96f3485c
MK
10808 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10809 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10810 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10811
1ae44dfc
LB
10812 if (output_cum && *output_cum != 0)
10813 header = 0;
10814
9386b588 10815 if (use_json && !*json_header_depth) {
96f3485c
MK
10816 if (all)
10817 *json_header_depth = 1;
10818 else {
10819 vty_out(vty, "{\n");
10820 *json_header_depth = 2;
10821 }
10822
d62a17ae 10823 vty_out(vty,
23d0a753
DA
10824 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10825 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10826 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10827 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10828 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10829 ? VRF_DEFAULT_NAME
10830 : bgp->name,
10831 table->version, &bgp->router_id,
01eced22 10832 bgp->default_local_pref, bgp->as);
9386b588 10833 if (rd) {
445c2480 10834 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10835 ++*json_header_depth;
10836 }
d62a17ae 10837 }
718e3744 10838
445c2480
DS
10839 if (use_json && rd) {
10840 vty_out(vty, " \"%s\" : { ", rd);
10841 }
10842
d62a17ae 10843 /* Start processing of routes. */
9bcb3eef
DS
10844 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10845 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10846 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
b54892e0 10847
9bcb3eef 10848 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10849 if (pi == NULL)
98ce9a06 10850 continue;
d62a17ae 10851
98ce9a06 10852 display = 0;
98ce9a06
DS
10853 if (use_json)
10854 json_paths = json_object_new_array();
10855 else
10856 json_paths = NULL;
d62a17ae 10857
6f94b685 10858 for (; pi; pi = pi->next) {
98ce9a06 10859 total_count++;
1e2ce4f1 10860
7d3cae70
DA
10861 if (type == bgp_show_type_prefix_version) {
10862 uint32_t version =
10863 strtoul(output_arg, NULL, 10);
10864 if (dest->version < version)
10865 continue;
10866 }
10867
a70a28a5
DA
10868 if (type == bgp_show_type_community_alias) {
10869 char *alias = output_arg;
10870 char **communities;
10871 int num;
10872 bool found = false;
10873
10874 if (pi->attr->community) {
10875 frrstr_split(pi->attr->community->str,
10876 " ", &communities, &num);
10877 for (int i = 0; i < num; i++) {
10878 const char *com2alias =
10879 bgp_community2alias(
10880 communities[i]);
10881 if (strncmp(alias, com2alias,
10882 strlen(com2alias))
10883 == 0) {
10884 found = true;
10885 break;
10886 }
10887 }
10888 }
10889
10890 if (!found && pi->attr->lcommunity) {
10891 frrstr_split(pi->attr->lcommunity->str,
10892 " ", &communities, &num);
10893 for (int i = 0; i < num; i++) {
10894 const char *com2alias =
10895 bgp_community2alias(
10896 communities[i]);
10897 if (strncmp(alias, com2alias,
10898 strlen(com2alias))
10899 == 0) {
10900 found = true;
10901 break;
10902 }
10903 }
10904 }
10905
10906 if (!found)
10907 continue;
10908 }
10909
1e2ce4f1
DS
10910 if (type == bgp_show_type_rpki) {
10911 if (dest_p->family == AF_INET
10912 || dest_p->family == AF_INET6)
4027d19b 10913 rpki_curr_state = hook_call(
1e2ce4f1
DS
10914 bgp_rpki_prefix_status,
10915 pi->peer, pi->attr, dest_p);
4027d19b
DS
10916 if (rpki_target_state != RPKI_NOT_BEING_USED
10917 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10918 continue;
10919 }
10920
98ce9a06
DS
10921 if (type == bgp_show_type_flap_statistics
10922 || type == bgp_show_type_flap_neighbor
10923 || type == bgp_show_type_dampend_paths
10924 || type == bgp_show_type_damp_neighbor) {
40381db7 10925 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10926 continue;
10927 }
10928 if (type == bgp_show_type_regexp) {
10929 regex_t *regex = output_arg;
d62a17ae 10930
40381db7 10931 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10932 == REG_NOMATCH)
10933 continue;
10934 }
10935 if (type == bgp_show_type_prefix_list) {
10936 struct prefix_list *plist = output_arg;
d62a17ae 10937
9bcb3eef 10938 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10939 != PREFIX_PERMIT)
10940 continue;
10941 }
10942 if (type == bgp_show_type_filter_list) {
10943 struct as_list *as_list = output_arg;
d62a17ae 10944
40381db7 10945 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10946 != AS_FILTER_PERMIT)
10947 continue;
10948 }
10949 if (type == bgp_show_type_route_map) {
10950 struct route_map *rmap = output_arg;
9b6d8fcf 10951 struct bgp_path_info path;
98ce9a06 10952 struct attr dummy_attr;
b68885f9 10953 route_map_result_t ret;
d62a17ae 10954
6f4f49b2 10955 dummy_attr = *pi->attr;
d62a17ae 10956
40381db7 10957 path.peer = pi->peer;
9b6d8fcf 10958 path.attr = &dummy_attr;
d62a17ae 10959
1782514f 10960 ret = route_map_apply(rmap, dest_p, &path);
98ce9a06
DS
10961 if (ret == RMAP_DENYMATCH)
10962 continue;
10963 }
10964 if (type == bgp_show_type_neighbor
10965 || type == bgp_show_type_flap_neighbor
10966 || type == bgp_show_type_damp_neighbor) {
10967 union sockunion *su = output_arg;
10968
40381db7
DS
10969 if (pi->peer == NULL
10970 || pi->peer->su_remote == NULL
10971 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10972 continue;
10973 }
10974 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10975 uint32_t destination;
d62a17ae 10976
9bcb3eef 10977 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10978 if (IN_CLASSC(destination)
9bcb3eef 10979 && dest_p->prefixlen == 24)
98ce9a06
DS
10980 continue;
10981 if (IN_CLASSB(destination)
9bcb3eef 10982 && dest_p->prefixlen == 16)
98ce9a06
DS
10983 continue;
10984 if (IN_CLASSA(destination)
9bcb3eef 10985 && dest_p->prefixlen == 8)
98ce9a06
DS
10986 continue;
10987 }
10988 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10989 p = output_arg;
9bcb3eef 10990 if (!prefix_match(p, dest_p))
98ce9a06
DS
10991 continue;
10992 }
10993 if (type == bgp_show_type_community_all) {
40381db7 10994 if (!pi->attr->community)
98ce9a06
DS
10995 continue;
10996 }
10997 if (type == bgp_show_type_community) {
10998 struct community *com = output_arg;
d62a17ae 10999
40381db7
DS
11000 if (!pi->attr->community
11001 || !community_match(pi->attr->community,
98ce9a06
DS
11002 com))
11003 continue;
11004 }
11005 if (type == bgp_show_type_community_exact) {
11006 struct community *com = output_arg;
d62a17ae 11007
40381db7
DS
11008 if (!pi->attr->community
11009 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
11010 continue;
11011 }
11012 if (type == bgp_show_type_community_list) {
11013 struct community_list *list = output_arg;
d62a17ae 11014
40381db7 11015 if (!community_list_match(pi->attr->community,
a4d82a8a 11016 list))
98ce9a06
DS
11017 continue;
11018 }
a4d82a8a 11019 if (type == bgp_show_type_community_list_exact) {
98ce9a06 11020 struct community_list *list = output_arg;
d62a17ae 11021
98ce9a06 11022 if (!community_list_exact_match(
40381db7 11023 pi->attr->community, list))
98ce9a06
DS
11024 continue;
11025 }
11026 if (type == bgp_show_type_lcommunity) {
11027 struct lcommunity *lcom = output_arg;
d62a17ae 11028
40381db7
DS
11029 if (!pi->attr->lcommunity
11030 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
11031 lcom))
11032 continue;
11033 }
36a206db 11034
11035 if (type == bgp_show_type_lcommunity_exact) {
11036 struct lcommunity *lcom = output_arg;
11037
11038 if (!pi->attr->lcommunity
11039 || !lcommunity_cmp(pi->attr->lcommunity,
11040 lcom))
11041 continue;
11042 }
98ce9a06
DS
11043 if (type == bgp_show_type_lcommunity_list) {
11044 struct community_list *list = output_arg;
d62a17ae 11045
40381db7 11046 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 11047 list))
98ce9a06
DS
11048 continue;
11049 }
36a206db 11050 if (type
11051 == bgp_show_type_lcommunity_list_exact) {
11052 struct community_list *list = output_arg;
11053
11054 if (!lcommunity_list_exact_match(
11055 pi->attr->lcommunity, list))
11056 continue;
11057 }
98ce9a06 11058 if (type == bgp_show_type_lcommunity_all) {
40381db7 11059 if (!pi->attr->lcommunity)
98ce9a06
DS
11060 continue;
11061 }
11062 if (type == bgp_show_type_dampend_paths
11063 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11064 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11065 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11066 continue;
11067 }
11068
11069 if (!use_json && header) {
23d0a753
DA
11070 vty_out(vty,
11071 "BGP table version is %" PRIu64
11072 ", local router ID is %pI4, vrf id ",
11073 table->version, &bgp->router_id);
9df8b37c
PZ
11074 if (bgp->vrf_id == VRF_UNKNOWN)
11075 vty_out(vty, "%s", VRFID_NONE_STR);
11076 else
11077 vty_out(vty, "%u", bgp->vrf_id);
11078 vty_out(vty, "\n");
01eced22
AD
11079 vty_out(vty, "Default local pref %u, ",
11080 bgp->default_local_pref);
11081 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11082 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11083 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11084 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11085 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11086 if (type == bgp_show_type_dampend_paths
11087 || type == bgp_show_type_damp_neighbor)
98ce9a06 11088 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11089 else if (type == bgp_show_type_flap_statistics
11090 || type == bgp_show_type_flap_neighbor)
98ce9a06 11091 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11092 else
ae248832
MK
11093 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11094 : BGP_SHOW_HEADER));
98ce9a06 11095 header = 0;
d62a17ae 11096 }
98ce9a06
DS
11097 if (rd != NULL && !display && !output_count) {
11098 if (!use_json)
11099 vty_out(vty,
11100 "Route Distinguisher: %s\n",
11101 rd);
d62a17ae 11102 }
98ce9a06
DS
11103 if (type == bgp_show_type_dampend_paths
11104 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11105 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11106 AFI_IP, safi, use_json,
11107 json_paths);
98ce9a06
DS
11108 else if (type == bgp_show_type_flap_statistics
11109 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11110 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11111 AFI_IP, safi, use_json,
11112 json_paths);
f280c93b
DA
11113 else {
11114 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11115 route_vty_out_detail(
11116 vty, bgp, dest, pi,
11117 family2afi(dest_p->family),
11118 safi, RPKI_NOT_BEING_USED,
11119 json_paths);
11120 else
11121 route_vty_out(vty, dest_p, pi, display,
11122 safi, json_paths, wide);
11123 }
98ce9a06 11124 display++;
d62a17ae 11125 }
11126
98ce9a06
DS
11127 if (display) {
11128 output_count++;
11129 if (!use_json)
11130 continue;
11131
625d2931 11132 /* encode prefix */
9bcb3eef 11133 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11134 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11135
1840384b 11136
b54892e0
DS
11137 bgp_fs_nlri_get_string(
11138 (unsigned char *)
9bcb3eef
DS
11139 dest_p->u.prefix_flowspec.ptr,
11140 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11141 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11142 family2afi(dest_p->u
11143 .prefix_flowspec.family));
625d2931 11144 if (first)
b54892e0 11145 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11146 dest_p->u.prefix_flowspec
b54892e0 11147 .prefixlen);
625d2931 11148 else
b54892e0 11149 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11150 dest_p->u.prefix_flowspec
b54892e0 11151 .prefixlen);
625d2931 11152 } else {
625d2931 11153 if (first)
1b78780b 11154 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11155 else
1b78780b 11156 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11157 }
98ce9a06 11158 vty_out(vty, "%s",
f4ec52f7
DA
11159 json_object_to_json_string_ext(
11160 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11161 json_object_free(json_paths);
449feb8e 11162 json_paths = NULL;
98ce9a06 11163 first = 0;
1f83ed02
DS
11164 } else
11165 json_object_free(json_paths);
98ce9a06
DS
11166 }
11167
1ae44dfc
LB
11168 if (output_cum) {
11169 output_count += *output_cum;
11170 *output_cum = output_count;
11171 }
11172 if (total_cum) {
11173 total_count += *total_cum;
11174 *total_cum = total_count;
11175 }
d62a17ae 11176 if (use_json) {
9386b588 11177 if (rd) {
a4d82a8a 11178 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11179 }
11180 if (is_last) {
a4d82a8a
PZ
11181 unsigned long i;
11182 for (i = 0; i < *json_header_depth; ++i)
11183 vty_out(vty, " } ");
96f3485c
MK
11184 if (!all)
11185 vty_out(vty, "\n");
9386b588 11186 }
d62a17ae 11187 } else {
1ae44dfc
LB
11188 if (is_last) {
11189 /* No route is displayed */
11190 if (output_count == 0) {
11191 if (type == bgp_show_type_normal)
11192 vty_out(vty,
11193 "No BGP prefixes displayed, %ld exist\n",
11194 total_count);
11195 } else
d62a17ae 11196 vty_out(vty,
1ae44dfc
LB
11197 "\nDisplayed %ld routes and %ld total paths\n",
11198 output_count, total_count);
11199 }
d62a17ae 11200 }
718e3744 11201
d62a17ae 11202 return CMD_SUCCESS;
718e3744 11203}
11204
1ae44dfc
LB
11205int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11206 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11207 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11208{
9bcb3eef 11209 struct bgp_dest *dest, *next;
1ae44dfc
LB
11210 unsigned long output_cum = 0;
11211 unsigned long total_cum = 0;
9386b588 11212 unsigned long json_header_depth = 0;
67009e22 11213 struct bgp_table *itable;
0136788c 11214 bool show_msg;
96c81f66 11215 uint16_t show_flags = 0;
0136788c
LB
11216
11217 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11218
96f3485c
MK
11219 if (use_json)
11220 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11221
9bcb3eef
DS
11222 for (dest = bgp_table_top(table); dest; dest = next) {
11223 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11224
9bcb3eef
DS
11225 next = bgp_route_next(dest);
11226 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11227 continue;
67009e22 11228
9bcb3eef 11229 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11230 if (itable != NULL) {
1ae44dfc 11231 struct prefix_rd prd;
06b9f471 11232 char rd[RD_ADDRSTRLEN];
1ae44dfc 11233
9bcb3eef 11234 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11235 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11236 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11237 rd, next == NULL, &output_cum,
11238 &total_cum, &json_header_depth,
1e2ce4f1 11239 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11240 if (next == NULL)
11241 show_msg = false;
1ae44dfc
LB
11242 }
11243 }
0136788c
LB
11244 if (show_msg) {
11245 if (output_cum == 0)
11246 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11247 total_cum);
11248 else
11249 vty_out(vty,
11250 "\nDisplayed %ld routes and %ld total paths\n",
11251 output_cum, total_cum);
11252 }
1ae44dfc
LB
11253 return CMD_SUCCESS;
11254}
d62a17ae 11255static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11256 enum bgp_show_type type, void *output_arg,
96c81f66 11257 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11258{
d62a17ae 11259 struct bgp_table *table;
9386b588 11260 unsigned long json_header_depth = 0;
96f3485c 11261 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11262
d62a17ae 11263 if (bgp == NULL) {
11264 bgp = bgp_get_default();
11265 }
fee0f4c6 11266
d62a17ae 11267 if (bgp == NULL) {
11268 if (!use_json)
11269 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11270 else
11271 vty_out(vty, "{}\n");
d62a17ae 11272 return CMD_WARNING;
11273 }
4dd6177e 11274
1ae44dfc 11275 table = bgp->rib[afi][safi];
d62a17ae 11276 /* use MPLS and ENCAP specific shows until they are merged */
11277 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11278 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11279 output_arg, use_json);
d62a17ae 11280 }
dba3c1d3
PG
11281
11282 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11283 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11284 output_arg, use_json,
11285 1, NULL, NULL);
11286 }
d62a17ae 11287 /* labeled-unicast routes live in the unicast table */
11288 else if (safi == SAFI_LABELED_UNICAST)
11289 safi = SAFI_UNICAST;
fee0f4c6 11290
96f3485c 11291 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11292 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11293 rpki_target_state);
fee0f4c6 11294}
11295
d62a17ae 11296static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11297 safi_t safi, uint16_t show_flags)
f186de26 11298{
d62a17ae 11299 struct listnode *node, *nnode;
11300 struct bgp *bgp;
11301 int is_first = 1;
9f049418 11302 bool route_output = false;
96f3485c 11303 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11304
d62a17ae 11305 if (use_json)
11306 vty_out(vty, "{\n");
9f689658 11307
d62a17ae 11308 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11309 route_output = true;
d62a17ae 11310 if (use_json) {
11311 if (!is_first)
11312 vty_out(vty, ",\n");
11313 else
11314 is_first = 0;
11315
11316 vty_out(vty, "\"%s\":",
11317 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11318 ? VRF_DEFAULT_NAME
d62a17ae 11319 : bgp->name);
11320 } else {
11321 vty_out(vty, "\nInstance %s:\n",
11322 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11323 ? VRF_DEFAULT_NAME
d62a17ae 11324 : bgp->name);
11325 }
11326 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11327 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11328 }
9f689658 11329
d62a17ae 11330 if (use_json)
11331 vty_out(vty, "}\n");
9f049418
DS
11332 else if (!route_output)
11333 vty_out(vty, "%% BGP instance not found\n");
f186de26 11334}
11335
718e3744 11336/* Header of detailed BGP route information */
d62a17ae 11337void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
9bcb3eef 11338 struct bgp_dest *dest, struct prefix_rd *prd,
d62a17ae 11339 afi_t afi, safi_t safi, json_object *json)
11340{
40381db7 11341 struct bgp_path_info *pi;
b54892e0 11342 const struct prefix *p;
d62a17ae 11343 struct peer *peer;
11344 struct listnode *node, *nnode;
06b9f471 11345 char buf1[RD_ADDRSTRLEN];
0291c246 11346 char prefix_str[BUFSIZ];
d62a17ae 11347 int count = 0;
11348 int best = 0;
11349 int suppress = 0;
c5f1e1b2
C
11350 int accept_own = 0;
11351 int route_filter_translated_v4 = 0;
11352 int route_filter_v4 = 0;
11353 int route_filter_translated_v6 = 0;
11354 int route_filter_v6 = 0;
11355 int llgr_stale = 0;
11356 int no_llgr = 0;
11357 int accept_own_nexthop = 0;
11358 int blackhole = 0;
d62a17ae 11359 int no_export = 0;
11360 int no_advertise = 0;
11361 int local_as = 0;
c5f1e1b2 11362 int no_peer = 0;
d62a17ae 11363 int first = 1;
11364 int has_valid_label = 0;
11365 mpls_label_t label = 0;
11366 json_object *json_adv_to = NULL;
9bedbb1e 11367
9bcb3eef
DS
11368 p = bgp_dest_get_prefix(dest);
11369 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11370
11371 if (has_valid_label)
9bcb3eef 11372 label = label_pton(&dest->local_label);
d62a17ae 11373
44c69747 11374 if (safi == SAFI_EVPN) {
d62a17ae 11375
44c69747 11376 if (!json) {
2dbe669b 11377 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11378 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11379 : "",
2dbe669b 11380 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11381 } else {
11382 json_object_string_add(json, "rd",
11383 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11384 "");
11385 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11386 }
11387 } else {
11388 if (!json) {
9119ef3a
DA
11389 vty_out(vty,
11390 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11391 "\n",
d62a17ae 11392 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11393 ? prefix_rd2str(prd, buf1,
11394 sizeof(buf1))
11395 : ""),
9119ef3a
DA
11396 safi == SAFI_MPLS_VPN ? ":" : "", p,
11397 dest->version);
cd1964ff 11398
9119ef3a 11399 } else {
44c69747
LK
11400 json_object_string_add(json, "prefix",
11401 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11402 json_object_int_add(json, "version", dest->version);
11403
11404 }
44c69747
LK
11405 }
11406
11407 if (has_valid_label) {
11408 if (json)
11409 json_object_int_add(json, "localLabel", label);
11410 else
d62a17ae 11411 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11412 }
11413
11414 if (!json)
d62a17ae 11415 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11416 vty_out(vty, "not allocated\n");
718e3744 11417
9bcb3eef 11418 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11419 count++;
40381db7 11420 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11421 best = count;
4056a5f6 11422 if (bgp_path_suppressed(pi))
d62a17ae 11423 suppress = 1;
cee9c031 11424
40381db7 11425 if (pi->attr->community == NULL)
cee9c031
QY
11426 continue;
11427
11428 no_advertise += community_include(
40381db7
DS
11429 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11430 no_export += community_include(pi->attr->community,
cee9c031 11431 COMMUNITY_NO_EXPORT);
40381db7 11432 local_as += community_include(pi->attr->community,
cee9c031 11433 COMMUNITY_LOCAL_AS);
40381db7 11434 accept_own += community_include(pi->attr->community,
cee9c031
QY
11435 COMMUNITY_ACCEPT_OWN);
11436 route_filter_translated_v4 += community_include(
40381db7 11437 pi->attr->community,
cee9c031
QY
11438 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11439 route_filter_translated_v6 += community_include(
40381db7 11440 pi->attr->community,
cee9c031
QY
11441 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11442 route_filter_v4 += community_include(
40381db7 11443 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11444 route_filter_v6 += community_include(
40381db7
DS
11445 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11446 llgr_stale += community_include(pi->attr->community,
cee9c031 11447 COMMUNITY_LLGR_STALE);
40381db7 11448 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11449 COMMUNITY_NO_LLGR);
11450 accept_own_nexthop +=
40381db7 11451 community_include(pi->attr->community,
cee9c031 11452 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11453 blackhole += community_include(pi->attr->community,
cee9c031 11454 COMMUNITY_BLACKHOLE);
40381db7 11455 no_peer += community_include(pi->attr->community,
cee9c031 11456 COMMUNITY_NO_PEER);
d62a17ae 11457 }
718e3744 11458 }
718e3744 11459
d62a17ae 11460 if (!json) {
11461 vty_out(vty, "Paths: (%d available", count);
11462 if (best) {
11463 vty_out(vty, ", best #%d", best);
b84060bb
PG
11464 if (safi == SAFI_UNICAST) {
11465 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11466 vty_out(vty, ", table %s",
11467 VRF_DEFAULT_NAME);
11468 else
11469 vty_out(vty, ", vrf %s",
11470 bgp->name);
11471 }
d62a17ae 11472 } else
11473 vty_out(vty, ", no best path");
11474
c5f1e1b2
C
11475 if (accept_own)
11476 vty_out(vty,
11477 ", accept own local route exported and imported in different VRF");
11478 else if (route_filter_translated_v4)
11479 vty_out(vty,
11480 ", mark translated RTs for VPNv4 route filtering");
11481 else if (route_filter_v4)
11482 vty_out(vty,
11483 ", attach RT as-is for VPNv4 route filtering");
11484 else if (route_filter_translated_v6)
11485 vty_out(vty,
11486 ", mark translated RTs for VPNv6 route filtering");
11487 else if (route_filter_v6)
11488 vty_out(vty,
11489 ", attach RT as-is for VPNv6 route filtering");
11490 else if (llgr_stale)
11491 vty_out(vty,
11492 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11493 else if (no_llgr)
11494 vty_out(vty,
11495 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11496 else if (accept_own_nexthop)
11497 vty_out(vty,
11498 ", accept local nexthop");
11499 else if (blackhole)
11500 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11501 else if (no_export)
11502 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11503 else if (no_advertise)
11504 vty_out(vty, ", not advertised to any peer");
d62a17ae 11505 else if (local_as)
11506 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11507 else if (no_peer)
11508 vty_out(vty,
11509 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11510
11511 if (suppress)
11512 vty_out(vty,
11513 ", Advertisements suppressed by an aggregate.");
11514 vty_out(vty, ")\n");
11515 }
718e3744 11516
d62a17ae 11517 /* If we are not using addpath then we can display Advertised to and
11518 * that will
11519 * show what peers we advertised the bestpath to. If we are using
11520 * addpath
11521 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11522 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11523 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11524 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11525 if (json && !json_adv_to)
11526 json_adv_to = json_object_new_object();
11527
11528 route_vty_out_advertised_to(
11529 vty, peer, &first,
11530 " Advertised to non peer-group peers:\n ",
11531 json_adv_to);
11532 }
11533 }
11534
11535 if (json) {
11536 if (json_adv_to) {
11537 json_object_object_add(json, "advertisedTo",
11538 json_adv_to);
11539 }
11540 } else {
11541 if (first)
11542 vty_out(vty, " Not advertised to any peer");
11543 vty_out(vty, "\n");
11544 }
11545 }
718e3744 11546}
11547
44c69747 11548static void bgp_show_path_info(struct prefix_rd *pfx_rd,
9bcb3eef
DS
11549 struct bgp_dest *bgp_node, struct vty *vty,
11550 struct bgp *bgp, afi_t afi, safi_t safi,
11551 json_object *json, enum bgp_path_type pathtype,
4027d19b 11552 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11553{
11554 struct bgp_path_info *pi;
11555 int header = 1;
11556 char rdbuf[RD_ADDRSTRLEN];
11557 json_object *json_header = NULL;
11558 json_object *json_paths = NULL;
4933eaaf 11559 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11560
9bcb3eef 11561 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11562 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11563
11564 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11565 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11566 pi->peer, pi->attr, p);
4933eaaf 11567
4027d19b
DS
11568 if (rpki_target_state != RPKI_NOT_BEING_USED
11569 && rpki_curr_state != rpki_target_state)
4933eaaf 11570 continue;
44c69747
LK
11571
11572 if (json && !json_paths) {
11573 /* Instantiate json_paths only if path is valid */
11574 json_paths = json_object_new_array();
11575 if (pfx_rd) {
11576 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11577 json_header = json_object_new_object();
11578 } else
11579 json_header = json;
11580 }
11581
11582 if (header) {
11583 route_vty_out_detail_header(
11584 vty, bgp, bgp_node, pfx_rd,
11585 AFI_IP, safi, json_header);
11586 header = 0;
11587 }
11588 (*display)++;
11589
11590 if (pathtype == BGP_PATH_SHOW_ALL
11591 || (pathtype == BGP_PATH_SHOW_BESTPATH
11592 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11593 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11594 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11595 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11596 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11597 safi, rpki_curr_state, json_paths);
44c69747
LK
11598 }
11599
11600 if (json && json_paths) {
11601 json_object_object_add(json_header, "paths", json_paths);
11602
11603 if (pfx_rd)
11604 json_object_object_add(json, rdbuf, json_header);
11605 }
11606}
11607
718e3744 11608/* Display specified route of BGP table. */
d62a17ae 11609static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11610 struct bgp_table *rib, const char *ip_str,
11611 afi_t afi, safi_t safi,
4027d19b 11612 enum rpki_states rpki_target_state,
d62a17ae 11613 struct prefix_rd *prd, int prefix_check,
9f049418 11614 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11615{
11616 int ret;
d62a17ae 11617 int display = 0;
11618 struct prefix match;
9bcb3eef
DS
11619 struct bgp_dest *dest;
11620 struct bgp_dest *rm;
d62a17ae 11621 struct bgp_table *table;
11622 json_object *json = NULL;
11623 json_object *json_paths = NULL;
11624
11625 /* Check IP address argument. */
11626 ret = str2prefix(ip_str, &match);
11627 if (!ret) {
11628 vty_out(vty, "address is malformed\n");
11629 return CMD_WARNING;
11630 }
718e3744 11631
d62a17ae 11632 match.family = afi2family(afi);
b05a1c8b 11633
44c69747 11634 if (use_json)
d62a17ae 11635 json = json_object_new_object();
718e3744 11636
44c69747 11637 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11638 for (dest = bgp_table_top(rib); dest;
11639 dest = bgp_route_next(dest)) {
11640 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11641
9bcb3eef 11642 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11643 continue;
9bcb3eef 11644 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11645 if (!table)
ea47320b 11646 continue;
d62a17ae 11647
ea47320b
DL
11648 if ((rm = bgp_node_match(table, &match)) == NULL)
11649 continue;
d62a17ae 11650
9bcb3eef 11651 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11652 if (prefix_check
b54892e0 11653 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11654 bgp_dest_unlock_node(rm);
ea47320b
DL
11655 continue;
11656 }
d62a17ae 11657
9bcb3eef 11658 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11659 bgp, afi, safi, json, pathtype,
4027d19b 11660 &display, rpki_target_state);
44c69747 11661
9bcb3eef 11662 bgp_dest_unlock_node(rm);
44c69747
LK
11663 }
11664 } else if (safi == SAFI_EVPN) {
9bcb3eef 11665 struct bgp_dest *longest_pfx;
cded3b72 11666 bool is_exact_pfxlen_match = false;
44c69747 11667
9bcb3eef
DS
11668 for (dest = bgp_table_top(rib); dest;
11669 dest = bgp_route_next(dest)) {
11670 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11671
9bcb3eef 11672 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11673 continue;
9bcb3eef 11674 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11675 if (!table)
11676 continue;
11677
11678 longest_pfx = NULL;
cded3b72 11679 is_exact_pfxlen_match = false;
44c69747
LK
11680 /*
11681 * Search through all the prefixes for a match. The
11682 * pfx's are enumerated in ascending order of pfxlens.
11683 * So, the last pfx match is the longest match. Set
11684 * is_exact_pfxlen_match when we get exact pfxlen match
11685 */
11686 for (rm = bgp_table_top(table); rm;
11687 rm = bgp_route_next(rm)) {
b54892e0 11688 const struct prefix *rm_p =
9bcb3eef 11689 bgp_dest_get_prefix(rm);
44c69747
LK
11690 /*
11691 * Get prefixlen of the ip-prefix within type5
11692 * evpn route
11693 */
b54892e0
DS
11694 if (evpn_type5_prefix_match(rm_p, &match)
11695 && rm->info) {
44c69747
LK
11696 longest_pfx = rm;
11697 int type5_pfxlen =
b54892e0
DS
11698 bgp_evpn_get_type5_prefixlen(
11699 rm_p);
44c69747 11700 if (type5_pfxlen == match.prefixlen) {
cded3b72 11701 is_exact_pfxlen_match = true;
9bcb3eef 11702 bgp_dest_unlock_node(rm);
44c69747
LK
11703 break;
11704 }
d62a17ae 11705 }
11706 }
ea47320b 11707
44c69747
LK
11708 if (!longest_pfx)
11709 continue;
11710
11711 if (prefix_check && !is_exact_pfxlen_match)
11712 continue;
11713
11714 rm = longest_pfx;
9bcb3eef 11715 bgp_dest_lock_node(rm);
44c69747 11716
9bcb3eef 11717 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11718 bgp, afi, safi, json, pathtype,
4027d19b 11719 &display, rpki_target_state);
44c69747 11720
9bcb3eef 11721 bgp_dest_unlock_node(rm);
d62a17ae 11722 }
98a9dbc7 11723 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11724 if (use_json)
11725 json_paths = json_object_new_array();
11726
63a0b7a9
PG
11727 display = bgp_flowspec_display_match_per_ip(afi, rib,
11728 &match, prefix_check,
11729 vty,
11730 use_json,
11731 json_paths);
d5f20468
SP
11732 if (use_json) {
11733 if (display)
11734 json_object_object_add(json, "paths",
11735 json_paths);
11736 else
11737 json_object_free(json_paths);
11738 }
d62a17ae 11739 } else {
9bcb3eef
DS
11740 if ((dest = bgp_node_match(rib, &match)) != NULL) {
11741 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11742 if (!prefix_check
9bcb3eef
DS
11743 || dest_p->prefixlen == match.prefixlen) {
11744 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11745 safi, json, pathtype,
4027d19b 11746 &display, rpki_target_state);
d62a17ae 11747 }
11748
9bcb3eef 11749 bgp_dest_unlock_node(dest);
d62a17ae 11750 }
11751 }
e5eee9af 11752
d62a17ae 11753 if (use_json) {
996c9314 11754 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11755 json, JSON_C_TO_STRING_PRETTY |
11756 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11757 json_object_free(json);
11758 } else {
11759 if (!display) {
11760 vty_out(vty, "%% Network not in table\n");
11761 return CMD_WARNING;
11762 }
11763 }
b05a1c8b 11764
d62a17ae 11765 return CMD_SUCCESS;
718e3744 11766}
11767
fee0f4c6 11768/* Display specified route of Main RIB */
d62a17ae 11769static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11770 afi_t afi, safi_t safi, struct prefix_rd *prd,
11771 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11772 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11773{
9b86009a 11774 if (!bgp) {
d62a17ae 11775 bgp = bgp_get_default();
9b86009a
RW
11776 if (!bgp) {
11777 if (!use_json)
11778 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11779 else
11780 vty_out(vty, "{}\n");
9b86009a
RW
11781 return CMD_WARNING;
11782 }
11783 }
d62a17ae 11784
11785 /* labeled-unicast routes live in the unicast table */
11786 if (safi == SAFI_LABELED_UNICAST)
11787 safi = SAFI_UNICAST;
11788
11789 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11790 afi, safi, rpki_target_state, prd,
8aa22bbb 11791 prefix_check, pathtype, use_json);
d62a17ae 11792}
11793
11794static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11795 struct cmd_token **argv, bool exact, afi_t afi,
11796 safi_t safi, bool uj)
d62a17ae 11797{
11798 struct lcommunity *lcom;
11799 struct buffer *b;
11800 int i;
11801 char *str;
11802 int first = 0;
96c81f66 11803 uint16_t show_flags = 0;
4f28b2b5 11804 int ret;
96f3485c
MK
11805
11806 if (uj)
11807 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11808
11809 b = buffer_new(1024);
11810 for (i = 0; i < argc; i++) {
11811 if (first)
11812 buffer_putc(b, ' ');
11813 else {
11814 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11815 first = 1;
11816 buffer_putstr(b, argv[i]->arg);
11817 }
11818 }
11819 }
11820 buffer_putc(b, '\0');
57d187bc 11821
d62a17ae 11822 str = buffer_getstr(b);
11823 buffer_free(b);
57d187bc 11824
d62a17ae 11825 lcom = lcommunity_str2com(str);
11826 XFREE(MTYPE_TMP, str);
11827 if (!lcom) {
11828 vty_out(vty, "%% Large-community malformed\n");
11829 return CMD_WARNING;
11830 }
57d187bc 11831
4f28b2b5 11832 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11833 (exact ? bgp_show_type_lcommunity_exact
11834 : bgp_show_type_lcommunity),
11835 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11836
11837 lcommunity_free(&lcom);
11838 return ret;
57d187bc
JS
11839}
11840
d62a17ae 11841static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11842 const char *lcom, bool exact, afi_t afi,
11843 safi_t safi, bool uj)
57d187bc 11844{
d62a17ae 11845 struct community_list *list;
96c81f66 11846 uint16_t show_flags = 0;
96f3485c
MK
11847
11848 if (uj)
11849 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11850
57d187bc 11851
e237b0d2 11852 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11853 LARGE_COMMUNITY_LIST_MASTER);
11854 if (list == NULL) {
11855 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11856 lcom);
11857 return CMD_WARNING;
11858 }
57d187bc 11859
36a206db 11860 return bgp_show(vty, bgp, afi, safi,
11861 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11862 : bgp_show_type_lcommunity_list),
1e2ce4f1 11863 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11864}
11865
52951b63
DS
11866DEFUN (show_ip_bgp_large_community_list,
11867 show_ip_bgp_large_community_list_cmd,
36a206db 11868 "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
11869 SHOW_STR
11870 IP_STR
11871 BGP_STR
11872 BGP_INSTANCE_HELP_STR
9bedbb1e 11873 BGP_AFI_HELP_STR
4dd6177e 11874 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11875 "Display routes matching the large-community-list\n"
11876 "large-community-list number\n"
11877 "large-community-list name\n"
36a206db 11878 "Exact match of the large-communities\n"
52951b63
DS
11879 JSON_STR)
11880{
d62a17ae 11881 afi_t afi = AFI_IP6;
11882 safi_t safi = SAFI_UNICAST;
11883 int idx = 0;
36a206db 11884 bool exact_match = 0;
4d678463 11885 struct bgp *bgp = NULL;
9f049418 11886 bool uj = use_json(argc, argv);
d62a17ae 11887
ef3364f0
DA
11888 if (uj)
11889 argc--;
4d678463 11890
ef3364f0
DA
11891 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11892 &bgp, uj);
11893 if (!idx)
11894 return CMD_WARNING;
d62a17ae 11895
11896 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11897
11898 const char *clist_number_or_name = argv[++idx]->arg;
11899
11900 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11901 exact_match = 1;
11902
11903 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11904 exact_match, afi, safi, uj);
52951b63
DS
11905}
11906DEFUN (show_ip_bgp_large_community,
11907 show_ip_bgp_large_community_cmd,
36a206db 11908 "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
11909 SHOW_STR
11910 IP_STR
11911 BGP_STR
11912 BGP_INSTANCE_HELP_STR
9bedbb1e 11913 BGP_AFI_HELP_STR
4dd6177e 11914 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11915 "Display routes matching the large-communities\n"
11916 "List of large-community numbers\n"
36a206db 11917 "Exact match of the large-communities\n"
52951b63
DS
11918 JSON_STR)
11919{
d62a17ae 11920 afi_t afi = AFI_IP6;
11921 safi_t safi = SAFI_UNICAST;
11922 int idx = 0;
36a206db 11923 bool exact_match = 0;
4d678463 11924 struct bgp *bgp = NULL;
9f049418 11925 bool uj = use_json(argc, argv);
96c81f66 11926 uint16_t show_flags = 0;
d62a17ae 11927
96f3485c
MK
11928 if (uj) {
11929 argc--;
11930 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11931 }
4d678463 11932
96f3485c
MK
11933 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11934 &bgp, uj);
11935 if (!idx)
11936 return CMD_WARNING;
d62a17ae 11937
36a206db 11938 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11939 if (argv_find(argv, argc, "exact-match", &idx))
11940 exact_match = 1;
11941 return bgp_show_lcommunity(vty, bgp, argc, argv,
11942 exact_match, afi, safi, uj);
11943 } else
d62a17ae 11944 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11945 bgp_show_type_lcommunity_all, NULL, show_flags,
11946 RPKI_NOT_BEING_USED);
52951b63
DS
11947}
11948
71f1613a
DA
11949static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11950 safi_t safi, struct json_object *json_array);
d62a17ae 11951static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11952 safi_t safi, struct json_object *json);
e01ca200 11953
7b2ff250 11954
9ab0cf58
PG
11955DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11956 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11957 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11958 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11959{
11960 bool uj = use_json(argc, argv);
11961 struct bgp *bgp = NULL;
ec76a1d1
DA
11962 safi_t safi = SAFI_UNICAST;
11963 afi_t afi = AFI_IP6;
4265b261 11964 int idx = 0;
6c9d22e2
PG
11965 struct json_object *json_all = NULL;
11966 struct json_object *json_afi_safi = NULL;
4265b261
PG
11967
11968 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11969 &bgp, false);
71f1613a 11970 if (!idx)
4265b261 11971 return CMD_WARNING;
6c9d22e2 11972
4265b261 11973 if (uj)
6c9d22e2 11974 json_all = json_object_new_object();
4265b261 11975
9ab0cf58
PG
11976 FOREACH_AFI_SAFI (afi, safi) {
11977 /*
11978 * So limit output to those afi/safi pairs that
11979 * actually have something interesting in them
11980 */
11981 if (strmatch(get_afi_safi_str(afi, safi, true),
11982 "Unknown")) {
11983 continue;
11984 }
11985 if (uj) {
11986 json_afi_safi = json_object_new_array();
11987 json_object_object_add(
11988 json_all,
11989 get_afi_safi_str(afi, safi, true),
11990 json_afi_safi);
11991 } else {
11992 json_afi_safi = NULL;
6c9d22e2 11993 }
9ab0cf58
PG
11994
11995 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11996 }
6c9d22e2
PG
11997
11998 if (uj) {
9ab0cf58
PG
11999 vty_out(vty, "%s",
12000 json_object_to_json_string_ext(
12001 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 12002 json_object_free(json_all);
4265b261 12003 }
6c9d22e2 12004
4265b261
PG
12005 return CMD_SUCCESS;
12006}
12007
7b2ff250 12008/* BGP route print out function without JSON */
14718643
PG
12009DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
12010 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 12011 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
12012 SHOW_STR
12013 IP_STR
12014 BGP_STR
12015 BGP_INSTANCE_HELP_STR
12016 L2VPN_HELP_STR
12017 EVPN_HELP_STR
12018 "BGP RIB advertisement statistics\n"
12019 JSON_STR)
12020{
ec76a1d1
DA
12021 afi_t afi = AFI_IP6;
12022 safi_t safi = SAFI_UNICAST;
14718643
PG
12023 struct bgp *bgp = NULL;
12024 int idx = 0, ret;
12025 bool uj = use_json(argc, argv);
12026 struct json_object *json_afi_safi = NULL, *json = NULL;
12027
12028 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12029 &bgp, false);
12030 if (!idx)
12031 return CMD_WARNING;
12032
12033 if (uj)
12034 json_afi_safi = json_object_new_array();
12035 else
12036 json_afi_safi = NULL;
12037
12038 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12039
12040 if (uj) {
12041 json = json_object_new_object();
12042 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12043 json_afi_safi);
12044 vty_out(vty, "%s", json_object_to_json_string_ext(
12045 json, JSON_C_TO_STRING_PRETTY));
12046 json_object_free(json);
12047 }
12048 return ret;
12049}
12050
893cccd0 12051/* BGP route print out function without JSON */
9ab0cf58
PG
12052DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12053 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12054 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12055 "]]\
893cccd0 12056 statistics [json]",
9ab0cf58
PG
12057 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12058 BGP_SAFI_WITH_LABEL_HELP_STR
12059 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12060{
ec76a1d1
DA
12061 afi_t afi = AFI_IP6;
12062 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12063 struct bgp *bgp = NULL;
12064 int idx = 0, ret;
12065 bool uj = use_json(argc, argv);
6c9d22e2 12066 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12067
12068 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12069 &bgp, false);
12070 if (!idx)
12071 return CMD_WARNING;
6c9d22e2 12072
893cccd0 12073 if (uj)
6c9d22e2
PG
12074 json_afi_safi = json_object_new_array();
12075 else
12076 json_afi_safi = NULL;
12077
12078 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12079
12080 if (uj) {
12081 json = json_object_new_object();
12082 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12083 json_afi_safi);
9ab0cf58
PG
12084 vty_out(vty, "%s",
12085 json_object_to_json_string_ext(
12086 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
12087 json_object_free(json);
12088 }
12089 return ret;
893cccd0 12090}
7b2ff250
DW
12091
12092/* BGP route print out function without JSON */
96f3485c 12093DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
12094 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12095 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12096 "]]\
96f3485c 12097 <[all$all] dampening <parameters>\
7b2ff250
DW
12098 |route-map WORD\
12099 |prefix-list WORD\
12100 |filter-list WORD\
7b2ff250
DW
12101 |community-list <(1-500)|WORD> [exact-match]\
12102 |A.B.C.D/M longer-prefixes\
12103 |X:X::X:X/M longer-prefixes\
893cccd0 12104 >",
9ab0cf58
PG
12105 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12106 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12107 "Display the entries for all address families\n"
9ab0cf58
PG
12108 "Display detailed information about dampening\n"
12109 "Display detail of configured dampening parameters\n"
12110 "Display routes matching the route-map\n"
12111 "A route-map to match on\n"
12112 "Display routes conforming to the prefix-list\n"
12113 "Prefix-list name\n"
12114 "Display routes conforming to the filter-list\n"
12115 "Regular expression access list name\n"
12116 "Display routes matching the community-list\n"
12117 "community-list number\n"
12118 "community-list name\n"
12119 "Exact match of the communities\n"
12120 "IPv4 prefix\n"
12121 "Display route and more specific routes\n"
12122 "IPv6 prefix\n"
12123 "Display route and more specific routes\n")
718e3744 12124{
d62a17ae 12125 afi_t afi = AFI_IP6;
12126 safi_t safi = SAFI_UNICAST;
12127 int exact_match = 0;
d62a17ae 12128 struct bgp *bgp = NULL;
12129 int idx = 0;
96c81f66 12130 uint16_t show_flags = 0;
96f3485c
MK
12131
12132 /* [<ipv4|ipv6> [all]] */
12133 if (all) {
12134 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12135 if (argv_find(argv, argc, "ipv4", &idx))
12136 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12137
12138 if (argv_find(argv, argc, "ipv6", &idx))
12139 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12140 }
d62a17ae 12141
12142 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12143 &bgp, false);
d62a17ae 12144 if (!idx)
12145 return CMD_WARNING;
12146
d62a17ae 12147 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 12148 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
12149 return bgp_show_dampening_parameters(vty, afi, safi,
12150 show_flags);
d62a17ae 12151 }
c016b6c7 12152
d62a17ae 12153 if (argv_find(argv, argc, "prefix-list", &idx))
12154 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12155 safi, bgp_show_type_prefix_list);
12156
12157 if (argv_find(argv, argc, "filter-list", &idx))
12158 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12159 safi, bgp_show_type_filter_list);
12160
d62a17ae 12161 if (argv_find(argv, argc, "route-map", &idx))
12162 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12163 safi, bgp_show_type_route_map);
12164
d62a17ae 12165 if (argv_find(argv, argc, "community-list", &idx)) {
12166 const char *clist_number_or_name = argv[++idx]->arg;
12167 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12168 exact_match = 1;
12169 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12170 exact_match, afi, safi);
12171 }
12172 /* prefix-longer */
12173 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12174 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12175 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12176 safi,
12177 bgp_show_type_prefix_longer);
12178
7b2ff250
DW
12179 return CMD_WARNING;
12180}
12181
12182/* BGP route print out function with JSON */
a70a28a5
DA
12183DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12184 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12185 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12186 "]]\
96f3485c 12187 [all$all]\
cf4898bc
QY
12188 [cidr-only\
12189 |dampening <flap-statistics|dampened-paths>\
12190 |community [AA:NN|local-AS|no-advertise|no-export\
12191 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12192 |accept-own|accept-own-nexthop|route-filter-v6\
12193 |route-filter-v4|route-filter-translated-v6\
12194 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 12195 |rpki <invalid|valid|notfound>\
7d3cae70 12196 |version (1-4294967295)\
a70a28a5 12197 |alias WORD\
f280c93b 12198 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12199 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12200 BGP_SAFI_WITH_LABEL_HELP_STR
12201 "Display the entries for all address families\n"
12202 "Display only routes with non-natural netmasks\n"
12203 "Display detailed information about dampening\n"
12204 "Display flap statistics of routes\n"
12205 "Display paths suppressed due to dampening\n"
12206 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12207 "Do not send outside local AS (well-known community)\n"
12208 "Do not advertise to any peer (well-known community)\n"
12209 "Do not export to next AS (well-known community)\n"
12210 "Graceful shutdown (well-known community)\n"
12211 "Do not export to any peer (well-known community)\n"
12212 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12213 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12214 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12215 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12216 "Should accept VPN route with local nexthop (well-known community)\n"
12217 "RT VPNv6 route filtering (well-known community)\n"
12218 "RT VPNv4 route filtering (well-known community)\n"
12219 "RT translated VPNv6 route filtering (well-known community)\n"
12220 "RT translated VPNv4 route filtering (well-known community)\n"
12221 "Exact match of the communities\n"
12222 "RPKI route types\n"
12223 "A valid path as determined by rpki\n"
12224 "A invalid path as determined by rpki\n"
12225 "A path that has no rpki data\n"
12226 "Display prefixes with matching version numbers\n"
12227 "Version number and above\n"
12228 "Display prefixes with matching BGP community alias\n"
12229 "BGP community alias\n" JSON_STR
12230 "Display detailed version of JSON output\n"
12231 "Increase table width for longer prefixes\n")
7b2ff250
DW
12232{
12233 afi_t afi = AFI_IP6;
12234 safi_t safi = SAFI_UNICAST;
12235 enum bgp_show_type sh_type = bgp_show_type_normal;
12236 struct bgp *bgp = NULL;
12237 int idx = 0;
d0086e8e 12238 int exact_match = 0;
96f3485c 12239 char *community = NULL;
7d3cae70 12240 char *prefix_version = NULL;
a70a28a5 12241 char *bgp_community_alias = NULL;
96f3485c 12242 bool first = true;
96c81f66 12243 uint16_t show_flags = 0;
4027d19b 12244 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12245
12246 if (uj) {
9f049418 12247 argc--;
96f3485c
MK
12248 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12249 }
12250
f280c93b
DA
12251 if (detail)
12252 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12253
96f3485c
MK
12254 /* [<ipv4|ipv6> [all]] */
12255 if (all) {
12256 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12257
12258 if (argv_find(argv, argc, "ipv4", &idx))
12259 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12260
12261 if (argv_find(argv, argc, "ipv6", &idx))
12262 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12263 }
12264
12265 if (wide)
12266 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12267
12268 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12269 &bgp, uj);
7b2ff250
DW
12270 if (!idx)
12271 return CMD_WARNING;
12272
7b2ff250 12273 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12274 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12275
12276 if (argv_find(argv, argc, "dampening", &idx)) {
12277 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12278 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12279 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12280 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12281 }
12282
12283 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12284 char *maybecomm = NULL;
d0086e8e 12285
79bc257a
RW
12286 if (idx + 1 < argc) {
12287 if (argv[idx + 1]->type == VARIABLE_TKN)
12288 maybecomm = argv[idx + 1]->arg;
12289 else
12290 maybecomm = argv[idx + 1]->text;
12291 }
12292
cf4898bc
QY
12293 if (maybecomm && !strmatch(maybecomm, "json")
12294 && !strmatch(maybecomm, "exact-match"))
12295 community = maybecomm;
d0086e8e 12296
cf4898bc
QY
12297 if (argv_find(argv, argc, "exact-match", &idx))
12298 exact_match = 1;
d0086e8e 12299
96f3485c
MK
12300 if (!community)
12301 sh_type = bgp_show_type_community_all;
12302 }
12303
1e2ce4f1
DS
12304 if (argv_find(argv, argc, "rpki", &idx)) {
12305 sh_type = bgp_show_type_rpki;
12306 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12307 rpki_target_state = RPKI_VALID;
1e2ce4f1 12308 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12309 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12310 }
12311
7d3cae70
DA
12312 /* Display prefixes with matching version numbers */
12313 if (argv_find(argv, argc, "version", &idx)) {
12314 sh_type = bgp_show_type_prefix_version;
12315 prefix_version = argv[idx + 1]->arg;
12316 }
12317
a70a28a5
DA
12318 /* Display prefixes with matching BGP community alias */
12319 if (argv_find(argv, argc, "alias", &idx)) {
12320 sh_type = bgp_show_type_community_alias;
12321 bgp_community_alias = argv[idx + 1]->arg;
12322 }
12323
96f3485c
MK
12324 if (!all) {
12325 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12326 if (community)
12327 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12328 exact_match, afi, safi,
12329 show_flags);
7d3cae70
DA
12330 else if (prefix_version)
12331 return bgp_show(vty, bgp, afi, safi, sh_type,
12332 prefix_version, show_flags,
12333 rpki_target_state);
a70a28a5
DA
12334 else if (bgp_community_alias)
12335 return bgp_show(vty, bgp, afi, safi, sh_type,
12336 bgp_community_alias, show_flags,
12337 rpki_target_state);
cf4898bc 12338 else
96f3485c 12339 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12340 show_flags, rpki_target_state);
96f3485c
MK
12341 } else {
12342 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12343 * AFI_IP6 */
12344
12345 if (uj)
12346 vty_out(vty, "{\n");
12347
12348 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12349 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12350 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12351 ? AFI_IP
12352 : AFI_IP6;
12353 FOREACH_SAFI (safi) {
96f3485c
MK
12354 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12355 continue;
12356
12357 if (uj) {
12358 if (first)
12359 first = false;
12360 else
12361 vty_out(vty, ",\n");
12362 vty_out(vty, "\"%s\":{\n",
12363 get_afi_safi_str(afi, safi,
12364 true));
12365 } else
12366 vty_out(vty,
12367 "\nFor address family: %s\n",
12368 get_afi_safi_str(afi, safi,
12369 false));
12370
12371 if (community)
12372 bgp_show_community(vty, bgp, community,
12373 exact_match, afi,
12374 safi, show_flags);
7d3cae70
DA
12375 else if (prefix_version)
12376 return bgp_show(vty, bgp, afi, safi,
12377 sh_type, prefix_version,
12378 show_flags,
12379 rpki_target_state);
a70a28a5
DA
12380 else if (bgp_community_alias)
12381 return bgp_show(
12382 vty, bgp, afi, safi, sh_type,
12383 bgp_community_alias, show_flags,
12384 rpki_target_state);
96f3485c
MK
12385 else
12386 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12387 NULL, show_flags,
4027d19b 12388 rpki_target_state);
96f3485c
MK
12389 if (uj)
12390 vty_out(vty, "}\n");
12391 }
12392 } else {
12393 /* show <ip> bgp all: for each AFI and SAFI*/
12394 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12395 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12396 continue;
12397
12398 if (uj) {
12399 if (first)
12400 first = false;
12401 else
12402 vty_out(vty, ",\n");
d0086e8e 12403
96f3485c
MK
12404 vty_out(vty, "\"%s\":{\n",
12405 get_afi_safi_str(afi, safi,
12406 true));
12407 } else
12408 vty_out(vty,
12409 "\nFor address family: %s\n",
12410 get_afi_safi_str(afi, safi,
12411 false));
12412
12413 if (community)
12414 bgp_show_community(vty, bgp, community,
12415 exact_match, afi,
12416 safi, show_flags);
7d3cae70
DA
12417 else if (prefix_version)
12418 return bgp_show(vty, bgp, afi, safi,
12419 sh_type, prefix_version,
12420 show_flags,
12421 rpki_target_state);
96f3485c
MK
12422 else
12423 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12424 NULL, show_flags,
4027d19b 12425 rpki_target_state);
96f3485c
MK
12426 if (uj)
12427 vty_out(vty, "}\n");
12428 }
12429 }
12430 if (uj)
12431 vty_out(vty, "}\n");
12432 }
12433 return CMD_SUCCESS;
a636c635 12434}
47fc97cc 12435
718e3744 12436DEFUN (show_ip_bgp_route,
12437 show_ip_bgp_route_cmd,
8aa22bbb 12438 "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 12439 SHOW_STR
12440 IP_STR
12441 BGP_STR
a636c635 12442 BGP_INSTANCE_HELP_STR
4f280b15 12443 BGP_AFI_HELP_STR
4dd6177e 12444 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12445 "Network in the BGP routing table to display\n"
0c7b1b01 12446 "IPv4 prefix\n"
8c3deaae 12447 "Network in the BGP routing table to display\n"
0c7b1b01 12448 "IPv6 prefix\n"
4092b06c 12449 "Display only the bestpath\n"
b05a1c8b 12450 "Display only multipaths\n"
8aa22bbb
DS
12451 "Display only paths that match the specified rpki state\n"
12452 "A valid path as determined by rpki\n"
12453 "A invalid path as determined by rpki\n"
12454 "A path that has no rpki data\n"
9973d184 12455 JSON_STR)
4092b06c 12456{
d62a17ae 12457 int prefix_check = 0;
ae19d7dd 12458
d62a17ae 12459 afi_t afi = AFI_IP6;
12460 safi_t safi = SAFI_UNICAST;
12461 char *prefix = NULL;
12462 struct bgp *bgp = NULL;
12463 enum bgp_path_type path_type;
9f049418 12464 bool uj = use_json(argc, argv);
b05a1c8b 12465
d62a17ae 12466 int idx = 0;
ae19d7dd 12467
d62a17ae 12468 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12469 &bgp, uj);
d62a17ae 12470 if (!idx)
12471 return CMD_WARNING;
c41247f5 12472
d62a17ae 12473 if (!bgp) {
12474 vty_out(vty,
12475 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12476 return CMD_WARNING;
12477 }
a636c635 12478
d62a17ae 12479 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12480 if (argv_find(argv, argc, "A.B.C.D", &idx)
12481 || argv_find(argv, argc, "X:X::X:X", &idx))
12482 prefix_check = 0;
12483 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12484 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12485 prefix_check = 1;
12486
12487 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12488 && afi != AFI_IP6) {
12489 vty_out(vty,
12490 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12491 return CMD_WARNING;
12492 }
12493 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12494 && afi != AFI_IP) {
12495 vty_out(vty,
12496 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12497 return CMD_WARNING;
12498 }
12499
12500 prefix = argv[idx]->arg;
12501
12502 /* [<bestpath|multipath>] */
12503 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12504 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12505 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12506 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12507 else
360660c6 12508 path_type = BGP_PATH_SHOW_ALL;
a636c635 12509
d62a17ae 12510 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12511 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12512}
12513
8c3deaae
QY
12514DEFUN (show_ip_bgp_regexp,
12515 show_ip_bgp_regexp_cmd,
3e5b31b3 12516 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12517 SHOW_STR
12518 IP_STR
12519 BGP_STR
b00b230a 12520 BGP_INSTANCE_HELP_STR
4f280b15 12521 BGP_AFI_HELP_STR
4dd6177e 12522 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12523 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12524 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12525 JSON_STR)
8c3deaae 12526{
d62a17ae 12527 afi_t afi = AFI_IP6;
12528 safi_t safi = SAFI_UNICAST;
12529 struct bgp *bgp = NULL;
3e5b31b3
DA
12530 bool uj = use_json(argc, argv);
12531 char *regstr = NULL;
8c3deaae 12532
d62a17ae 12533 int idx = 0;
12534 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12535 &bgp, false);
d62a17ae 12536 if (!idx)
12537 return CMD_WARNING;
8c3deaae 12538
d62a17ae 12539 // get index of regex
3e5b31b3
DA
12540 if (argv_find(argv, argc, "REGEX", &idx))
12541 regstr = argv[idx]->arg;
8c3deaae 12542
5f71d11c 12543 assert(regstr);
3e5b31b3
DA
12544 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12545 bgp_show_type_regexp, uj);
8c3deaae
QY
12546}
12547
ae248832 12548DEFPY (show_ip_bgp_instance_all,
a636c635 12549 show_ip_bgp_instance_all_cmd,
ae248832 12550 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12551 SHOW_STR
a636c635 12552 IP_STR
4092b06c 12553 BGP_STR
a636c635 12554 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12555 BGP_AFI_HELP_STR
4dd6177e 12556 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12557 JSON_STR
12558 "Increase table width for longer prefixes\n")
4092b06c 12559{
d62a17ae 12560 afi_t afi = AFI_IP;
12561 safi_t safi = SAFI_UNICAST;
12562 struct bgp *bgp = NULL;
d62a17ae 12563 int idx = 0;
96c81f66 12564 uint16_t show_flags = 0;
ae19d7dd 12565
96f3485c 12566 if (uj) {
d62a17ae 12567 argc--;
96f3485c
MK
12568 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12569 }
12570
12571 if (wide)
12572 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12573
9f049418
DS
12574 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12575 &bgp, uj);
12576 if (!idx)
12577 return CMD_WARNING;
12578
96f3485c 12579 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12580 return CMD_SUCCESS;
e3e29b32
LB
12581}
12582
a4d82a8a 12583static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12584 afi_t afi, safi_t safi, enum bgp_show_type type,
12585 bool use_json)
718e3744 12586{
d62a17ae 12587 regex_t *regex;
12588 int rc;
96c81f66 12589 uint16_t show_flags = 0;
96f3485c
MK
12590
12591 if (use_json)
12592 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12593
c3900853 12594 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12595 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12596 regstr);
12597 return CMD_WARNING_CONFIG_FAILED;
12598 }
12599
d62a17ae 12600 regex = bgp_regcomp(regstr);
12601 if (!regex) {
12602 vty_out(vty, "Can't compile regexp %s\n", regstr);
12603 return CMD_WARNING;
12604 }
a636c635 12605
1e2ce4f1
DS
12606 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12607 RPKI_NOT_BEING_USED);
d62a17ae 12608 bgp_regex_free(regex);
12609 return rc;
e3e29b32
LB
12610}
12611
d62a17ae 12612static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12613 const char *prefix_list_str, afi_t afi,
12614 safi_t safi, enum bgp_show_type type)
e3e29b32 12615{
d62a17ae 12616 struct prefix_list *plist;
96c81f66 12617 uint16_t show_flags = 0;
718e3744 12618
d62a17ae 12619 plist = prefix_list_lookup(afi, prefix_list_str);
12620 if (plist == NULL) {
12621 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12622 prefix_list_str);
12623 return CMD_WARNING;
12624 }
718e3744 12625
1e2ce4f1
DS
12626 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12627 RPKI_NOT_BEING_USED);
4092b06c
DS
12628}
12629
d62a17ae 12630static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12631 const char *filter, afi_t afi, safi_t safi,
12632 enum bgp_show_type type)
4092b06c 12633{
d62a17ae 12634 struct as_list *as_list;
96c81f66 12635 uint16_t show_flags = 0;
718e3744 12636
d62a17ae 12637 as_list = as_list_lookup(filter);
12638 if (as_list == NULL) {
12639 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12640 filter);
12641 return CMD_WARNING;
12642 }
a636c635 12643
1e2ce4f1
DS
12644 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12645 RPKI_NOT_BEING_USED);
718e3744 12646}
12647
d62a17ae 12648static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12649 const char *rmap_str, afi_t afi, safi_t safi,
12650 enum bgp_show_type type)
718e3744 12651{
d62a17ae 12652 struct route_map *rmap;
96c81f66 12653 uint16_t show_flags = 0;
bb46e94f 12654
d62a17ae 12655 rmap = route_map_lookup_by_name(rmap_str);
12656 if (!rmap) {
12657 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12658 return CMD_WARNING;
12659 }
12660
1e2ce4f1
DS
12661 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12662 RPKI_NOT_BEING_USED);
d62a17ae 12663}
12664
7f323236
DW
12665static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12666 const char *comstr, int exact, afi_t afi,
96c81f66 12667 safi_t safi, uint16_t show_flags)
d62a17ae 12668{
12669 struct community *com;
d62a17ae 12670 int ret = 0;
12671
7f323236 12672 com = community_str2com(comstr);
d62a17ae 12673 if (!com) {
7f323236 12674 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12675 return CMD_WARNING;
12676 }
12677
12678 ret = bgp_show(vty, bgp, afi, safi,
12679 (exact ? bgp_show_type_community_exact
12680 : bgp_show_type_community),
1e2ce4f1 12681 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12682 community_free(&com);
46c3ce83 12683
d62a17ae 12684 return ret;
718e3744 12685}
12686
d62a17ae 12687static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12688 const char *com, int exact, afi_t afi,
12689 safi_t safi)
50ef26d4 12690{
d62a17ae 12691 struct community_list *list;
96c81f66 12692 uint16_t show_flags = 0;
50ef26d4 12693
e237b0d2 12694 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12695 if (list == NULL) {
12696 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12697 return CMD_WARNING;
12698 }
718e3744 12699
d62a17ae 12700 return bgp_show(vty, bgp, afi, safi,
12701 (exact ? bgp_show_type_community_list_exact
12702 : bgp_show_type_community_list),
1e2ce4f1 12703 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12704}
12705
d62a17ae 12706static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12707 const char *prefix, afi_t afi, safi_t safi,
12708 enum bgp_show_type type)
718e3744 12709{
d62a17ae 12710 int ret;
12711 struct prefix *p;
96c81f66 12712 uint16_t show_flags = 0;
47fc97cc 12713
d62a17ae 12714 p = prefix_new();
95cbbd2a 12715
d62a17ae 12716 ret = str2prefix(prefix, p);
12717 if (!ret) {
12718 vty_out(vty, "%% Malformed Prefix\n");
12719 return CMD_WARNING;
12720 }
47e9b292 12721
1e2ce4f1
DS
12722 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12723 RPKI_NOT_BEING_USED);
63265b5c 12724 prefix_free(&p);
d62a17ae 12725 return ret;
12726}
12727
d62a17ae 12728enum bgp_stats {
12729 BGP_STATS_MAXBITLEN = 0,
12730 BGP_STATS_RIB,
12731 BGP_STATS_PREFIXES,
12732 BGP_STATS_TOTPLEN,
12733 BGP_STATS_UNAGGREGATEABLE,
12734 BGP_STATS_MAX_AGGREGATEABLE,
12735 BGP_STATS_AGGREGATES,
12736 BGP_STATS_SPACE,
12737 BGP_STATS_ASPATH_COUNT,
12738 BGP_STATS_ASPATH_MAXHOPS,
12739 BGP_STATS_ASPATH_TOTHOPS,
12740 BGP_STATS_ASPATH_MAXSIZE,
12741 BGP_STATS_ASPATH_TOTSIZE,
12742 BGP_STATS_ASN_HIGHEST,
12743 BGP_STATS_MAX,
a636c635 12744};
2815e61f 12745
9ab0cf58 12746#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12747#define TABLE_STATS_IDX_JSON 1
12748
12749static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12750 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12751 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12752 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12753 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12754 "unaggregateablePrefixes"},
12755 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12756 "maximumAggregateablePrefixes"},
12757 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12758 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12759 [BGP_STATS_SPACE] = {"Address space advertised",
12760 "addressSpaceAdvertised"},
9ab0cf58
PG
12761 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12762 "advertisementsWithPaths"},
12763 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12764 "longestAsPath"},
12765 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12766 "largestAsPath"},
12767 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12768 "averageAsPathLengthHops"},
12769 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12770 "averageAsPathSizeBytes"},
12771 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12772 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12773};
2815e61f 12774
d62a17ae 12775struct bgp_table_stats {
12776 struct bgp_table *table;
12777 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12778 double total_space;
ff7924f6
PJ
12779};
12780
9bcb3eef 12781static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12782 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12783{
9bcb3eef 12784 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12785 struct bgp_path_info *pi;
b54892e0 12786 const struct prefix *rn_p;
d62a17ae 12787
9bcb3eef 12788 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12789 return;
d62a17ae 12790
9bcb3eef 12791 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12792 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12793 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12794
9c14ec72 12795 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12796 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12797 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12798
9bcb3eef 12799 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12800 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12801 /* announced address space */
12802 if (space)
b54892e0 12803 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12804 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12805 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12806
9c14ec72 12807
9bcb3eef 12808 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12809 ts->counts[BGP_STATS_RIB]++;
12810
05864da7
DS
12811 if (CHECK_FLAG(pi->attr->flag,
12812 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12813 ts->counts[BGP_STATS_AGGREGATES]++;
12814
12815 /* as-path stats */
05864da7 12816 if (pi->attr->aspath) {
9c14ec72
RW
12817 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12818 unsigned int size = aspath_size(pi->attr->aspath);
12819 as_t highest = aspath_highest(pi->attr->aspath);
12820
12821 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12822
12823 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12824 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12825
12826 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12827 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12828
12829 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12830 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12831 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12832 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12833 }
12834 }
12835}
12836
12837static int bgp_table_stats_walker(struct thread *t)
12838{
9bcb3eef
DS
12839 struct bgp_dest *dest, *ndest;
12840 struct bgp_dest *top;
9c14ec72
RW
12841 struct bgp_table_stats *ts = THREAD_ARG(t);
12842 unsigned int space = 0;
12843
12844 if (!(top = bgp_table_top(ts->table)))
12845 return 0;
12846
12847 switch (ts->table->afi) {
12848 case AFI_IP:
12849 space = IPV4_MAX_BITLEN;
12850 break;
12851 case AFI_IP6:
12852 space = IPV6_MAX_BITLEN;
12853 break;
3ba7b4af
TA
12854 case AFI_L2VPN:
12855 space = EVPN_ROUTE_PREFIXLEN;
12856 break;
9c14ec72
RW
12857 default:
12858 return 0;
12859 }
12860
12861 ts->counts[BGP_STATS_MAXBITLEN] = space;
12862
9bcb3eef 12863 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12864 if (ts->table->safi == SAFI_MPLS_VPN
12865 || ts->table->safi == SAFI_ENCAP
12866 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12867 struct bgp_table *table;
12868
9bcb3eef 12869 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12870 if (!table)
12871 continue;
12872
12873 top = bgp_table_top(table);
9bcb3eef
DS
12874 for (ndest = bgp_table_top(table); ndest;
12875 ndest = bgp_route_next(ndest))
12876 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12877 } else {
9bcb3eef 12878 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12879 }
12880 }
9c14ec72 12881
d62a17ae 12882 return 0;
2815e61f 12883}
ff7924f6 12884
71f1613a
DA
12885static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12886 struct json_object *json_array)
12887{
12888 struct listnode *node, *nnode;
12889 struct bgp *bgp;
12890
12891 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12892 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12893}
12894
12895static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12896 safi_t safi, struct json_object *json_array)
2815e61f 12897{
d62a17ae 12898 struct bgp_table_stats ts;
12899 unsigned int i;
893cccd0
PG
12900 int ret = CMD_SUCCESS;
12901 char temp_buf[20];
6c9d22e2
PG
12902 struct json_object *json = NULL;
12903
12904 if (json_array)
12905 json = json_object_new_object();
019386c2 12906
d62a17ae 12907 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12908 char warning_msg[50];
12909
12910 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12911 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12912 safi);
6c9d22e2
PG
12913
12914 if (!json)
893cccd0
PG
12915 vty_out(vty, "%s\n", warning_msg);
12916 else
9ab0cf58 12917 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12918
893cccd0
PG
12919 ret = CMD_WARNING;
12920 goto end_table_stats;
d62a17ae 12921 }
019386c2 12922
893cccd0 12923 if (!json)
5290ceab
DA
12924 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12925 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12926 else
12927 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12928
d62a17ae 12929 /* labeled-unicast routes live in the unicast table */
12930 if (safi == SAFI_LABELED_UNICAST)
12931 safi = SAFI_UNICAST;
019386c2 12932
d62a17ae 12933 memset(&ts, 0, sizeof(ts));
12934 ts.table = bgp->rib[afi][safi];
12935 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12936
d62a17ae 12937 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12938 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12939 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12940 continue;
12941
12942 switch (i) {
d62a17ae 12943 case BGP_STATS_ASPATH_TOTHOPS:
12944 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12945 if (!json) {
9ab0cf58
PG
12946 snprintf(
12947 temp_buf, sizeof(temp_buf), "%12.2f",
12948 ts.counts[i]
12949 ? (float)ts.counts[i]
12950 / (float)ts.counts
12951 [BGP_STATS_ASPATH_COUNT]
12952 : 0);
893cccd0 12953 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12954 table_stats_strs[i]
12955 [TABLE_STATS_IDX_VTY],
893cccd0 12956 temp_buf);
9ab0cf58
PG
12957 } else {
12958 json_object_double_add(
12959 json,
12960 table_stats_strs[i]
12961 [TABLE_STATS_IDX_JSON],
12962 ts.counts[i]
12963 ? (double)ts.counts[i]
12964 / (double)ts.counts
d62a17ae 12965 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12966 : 0);
12967 }
d62a17ae 12968 break;
12969 case BGP_STATS_TOTPLEN:
6c9d22e2 12970 if (!json) {
9ab0cf58
PG
12971 snprintf(
12972 temp_buf, sizeof(temp_buf), "%12.2f",
12973 ts.counts[i]
12974 ? (float)ts.counts[i]
12975 / (float)ts.counts
12976 [BGP_STATS_PREFIXES]
12977 : 0);
893cccd0 12978 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12979 table_stats_strs[i]
12980 [TABLE_STATS_IDX_VTY],
893cccd0 12981 temp_buf);
9ab0cf58
PG
12982 } else {
12983 json_object_double_add(
12984 json,
12985 table_stats_strs[i]
12986 [TABLE_STATS_IDX_JSON],
12987 ts.counts[i]
12988 ? (double)ts.counts[i]
12989 / (double)ts.counts
d62a17ae 12990 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12991 : 0);
12992 }
d62a17ae 12993 break;
12994 case BGP_STATS_SPACE:
6c9d22e2
PG
12995 if (!json) {
12996 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12997 ts.total_space);
893cccd0 12998 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12999 table_stats_strs[i]
13000 [TABLE_STATS_IDX_VTY],
893cccd0 13001 temp_buf);
9ab0cf58
PG
13002 } else {
13003 json_object_double_add(
13004 json,
13005 table_stats_strs[i]
13006 [TABLE_STATS_IDX_JSON],
13007 (double)ts.total_space);
13008 }
8d0ab76d 13009 if (afi == AFI_IP6) {
6c9d22e2
PG
13010 if (!json) {
13011 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13012 "%12g",
13013 ts.total_space
13014 * pow(2.0, -128 + 32));
6c9d22e2
PG
13015 vty_out(vty, "%30s: %s\n",
13016 "/32 equivalent %s\n",
13017 temp_buf);
9ab0cf58
PG
13018 } else {
13019 json_object_double_add(
13020 json, "/32equivalent",
13021 (double)(ts.total_space
13022 * pow(2.0,
13023 -128 + 32)));
13024 }
6c9d22e2
PG
13025 if (!json) {
13026 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13027 "%12g",
13028 ts.total_space
13029 * pow(2.0, -128 + 48));
6c9d22e2
PG
13030 vty_out(vty, "%30s: %s\n",
13031 "/48 equivalent %s\n",
13032 temp_buf);
9ab0cf58
PG
13033 } else {
13034 json_object_double_add(
13035 json, "/48equivalent",
13036 (double)(ts.total_space
13037 * pow(2.0,
13038 -128 + 48)));
13039 }
8d0ab76d 13040 } else {
6c9d22e2
PG
13041 if (!json) {
13042 snprintf(temp_buf, sizeof(temp_buf),
13043 "%12.2f",
9ab0cf58
PG
13044 ts.total_space * 100.
13045 * pow(2.0, -32));
6c9d22e2 13046 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13047 "% announced ", temp_buf);
13048 } else {
13049 json_object_double_add(
13050 json, "%announced",
13051 (double)(ts.total_space * 100.
13052 * pow(2.0, -32)));
13053 }
6c9d22e2
PG
13054 if (!json) {
13055 snprintf(temp_buf, sizeof(temp_buf),
13056 "%12.2f",
9ab0cf58
PG
13057 ts.total_space
13058 * pow(2.0, -32 + 8));
6c9d22e2
PG
13059 vty_out(vty, "%30s: %s\n",
13060 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13061 } else {
13062 json_object_double_add(
13063 json, "/8equivalent",
13064 (double)(ts.total_space
13065 * pow(2.0, -32 + 8)));
13066 }
6c9d22e2
PG
13067 if (!json) {
13068 snprintf(temp_buf, sizeof(temp_buf),
13069 "%12.2f",
9ab0cf58
PG
13070 ts.total_space
13071 * pow(2.0, -32 + 24));
6c9d22e2 13072 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13073 "/24 equivalent ", temp_buf);
13074 } else {
13075 json_object_double_add(
13076 json, "/24equivalent",
13077 (double)(ts.total_space
13078 * pow(2.0, -32 + 24)));
13079 }
8d0ab76d 13080 }
d62a17ae 13081 break;
13082 default:
6c9d22e2
PG
13083 if (!json) {
13084 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13085 ts.counts[i]);
893cccd0 13086 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13087 table_stats_strs[i]
13088 [TABLE_STATS_IDX_VTY],
13089 temp_buf);
13090 } else {
13091 json_object_int_add(
13092 json,
13093 table_stats_strs[i]
13094 [TABLE_STATS_IDX_JSON],
13095 ts.counts[i]);
13096 }
d62a17ae 13097 }
893cccd0
PG
13098 if (!json)
13099 vty_out(vty, "\n");
d62a17ae 13100 }
9ab0cf58 13101end_table_stats:
6c9d22e2
PG
13102 if (json)
13103 json_object_array_add(json_array, json);
893cccd0 13104 return ret;
d62a17ae 13105}
13106
71f1613a
DA
13107static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13108 safi_t safi, struct json_object *json_array)
13109{
13110 if (!bgp) {
13111 bgp_table_stats_all(vty, afi, safi, json_array);
13112 return CMD_SUCCESS;
13113 }
13114
13115 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13116}
13117
d62a17ae 13118enum bgp_pcounts {
13119 PCOUNT_ADJ_IN = 0,
13120 PCOUNT_DAMPED,
13121 PCOUNT_REMOVED,
13122 PCOUNT_HISTORY,
13123 PCOUNT_STALE,
13124 PCOUNT_VALID,
13125 PCOUNT_ALL,
13126 PCOUNT_COUNTED,
7e3d9632 13127 PCOUNT_BPATH_SELECTED,
d62a17ae 13128 PCOUNT_PFCNT, /* the figure we display to users */
13129 PCOUNT_MAX,
a636c635 13130};
718e3744 13131
2b64873d 13132static const char *const pcount_strs[] = {
9d303b37
DL
13133 [PCOUNT_ADJ_IN] = "Adj-in",
13134 [PCOUNT_DAMPED] = "Damped",
13135 [PCOUNT_REMOVED] = "Removed",
13136 [PCOUNT_HISTORY] = "History",
13137 [PCOUNT_STALE] = "Stale",
13138 [PCOUNT_VALID] = "Valid",
13139 [PCOUNT_ALL] = "All RIB",
13140 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13141 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13142 [PCOUNT_PFCNT] = "Useable",
13143 [PCOUNT_MAX] = NULL,
a636c635 13144};
718e3744 13145
d62a17ae 13146struct peer_pcounts {
13147 unsigned int count[PCOUNT_MAX];
13148 const struct peer *peer;
13149 const struct bgp_table *table;
54317cba 13150 safi_t safi;
a636c635 13151};
47fc97cc 13152
9bcb3eef 13153static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13154{
54317cba
JW
13155 const struct bgp_adj_in *ain;
13156 const struct bgp_path_info *pi;
d62a17ae 13157 const struct peer *peer = pc->peer;
13158
54317cba
JW
13159 for (ain = rn->adj_in; ain; ain = ain->next)
13160 if (ain->peer == peer)
13161 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13162
9bcb3eef 13163 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13164
54317cba
JW
13165 if (pi->peer != peer)
13166 continue;
d62a17ae 13167
54317cba 13168 pc->count[PCOUNT_ALL]++;
d62a17ae 13169
54317cba
JW
13170 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13171 pc->count[PCOUNT_DAMPED]++;
13172 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13173 pc->count[PCOUNT_HISTORY]++;
13174 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13175 pc->count[PCOUNT_REMOVED]++;
13176 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13177 pc->count[PCOUNT_STALE]++;
13178 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13179 pc->count[PCOUNT_VALID]++;
13180 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13181 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13182 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13183 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13184
13185 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13186 pc->count[PCOUNT_COUNTED]++;
13187 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13188 flog_err(
13189 EC_LIB_DEVELOPMENT,
13190 "Attempting to count but flags say it is unusable");
13191 } else {
40381db7 13192 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13193 flog_err(
13194 EC_LIB_DEVELOPMENT,
13195 "Not counted but flags say we should");
d62a17ae 13196 }
13197 }
54317cba
JW
13198}
13199
13200static int bgp_peer_count_walker(struct thread *t)
13201{
9bcb3eef 13202 struct bgp_dest *rn, *rm;
54317cba
JW
13203 const struct bgp_table *table;
13204 struct peer_pcounts *pc = THREAD_ARG(t);
13205
13206 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13207 || pc->safi == SAFI_EVPN) {
13208 /* Special handling for 2-level routing tables. */
13209 for (rn = bgp_table_top(pc->table); rn;
13210 rn = bgp_route_next(rn)) {
9bcb3eef 13211 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13212 if (table != NULL)
13213 for (rm = bgp_table_top(table); rm;
13214 rm = bgp_route_next(rm))
13215 bgp_peer_count_proc(rm, pc);
13216 }
13217 } else
13218 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13219 bgp_peer_count_proc(rn, pc);
13220
d62a17ae 13221 return 0;
718e3744 13222}
13223
d62a17ae 13224static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13225 safi_t safi, bool use_json)
856ca177 13226{
d62a17ae 13227 struct peer_pcounts pcounts = {.peer = peer};
13228 unsigned int i;
13229 json_object *json = NULL;
13230 json_object *json_loop = NULL;
856ca177 13231
d62a17ae 13232 if (use_json) {
13233 json = json_object_new_object();
13234 json_loop = json_object_new_object();
13235 }
718e3744 13236
d62a17ae 13237 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13238 || !peer->bgp->rib[afi][safi]) {
13239 if (use_json) {
13240 json_object_string_add(
13241 json, "warning",
13242 "No such neighbor or address family");
13243 vty_out(vty, "%s\n", json_object_to_json_string(json));
13244 json_object_free(json);
d5f20468 13245 json_object_free(json_loop);
d62a17ae 13246 } else
13247 vty_out(vty, "%% No such neighbor or address family\n");
13248
13249 return CMD_WARNING;
13250 }
2a71e9ce 13251
d62a17ae 13252 memset(&pcounts, 0, sizeof(pcounts));
13253 pcounts.peer = peer;
13254 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13255 pcounts.safi = safi;
d62a17ae 13256
13257 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13258 * stats for the thread-walk (i.e. ensure this can't be blamed on
13259 * on just vty_read()).
13260 */
d62a17ae 13261 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13262
13263 if (use_json) {
13264 json_object_string_add(json, "prefixCountsFor", peer->host);
13265 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13266 get_afi_safi_str(afi, safi, true));
d62a17ae 13267 json_object_int_add(json, "pfxCounter",
13268 peer->pcount[afi][safi]);
13269
13270 for (i = 0; i < PCOUNT_MAX; i++)
13271 json_object_int_add(json_loop, pcount_strs[i],
13272 pcounts.count[i]);
13273
13274 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13275
13276 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13277 json_object_string_add(json, "pfxctDriftFor",
13278 peer->host);
13279 json_object_string_add(
13280 json, "recommended",
13281 "Please report this bug, with the above command output");
13282 }
996c9314
LB
13283 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13284 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13285 json_object_free(json);
13286 } else {
13287
13288 if (peer->hostname
892fedb6 13289 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13290 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13291 peer->hostname, peer->host,
5cb5f4d0 13292 get_afi_safi_str(afi, safi, false));
d62a17ae 13293 } else {
13294 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13295 get_afi_safi_str(afi, safi, false));
d62a17ae 13296 }
13297
6cde4b45 13298 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13299 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13300
13301 for (i = 0; i < PCOUNT_MAX; i++)
13302 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13303 pcounts.count[i]);
13304
13305 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13306 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13307 vty_out(vty,
13308 "Please report this bug, with the above command output\n");
13309 }
13310 }
13311
13312 return CMD_SUCCESS;
718e3744 13313}
13314
a636c635
DW
13315DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13316 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13317 "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 13318 SHOW_STR
13319 IP_STR
13320 BGP_STR
8386ac43 13321 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13322 BGP_AFI_HELP_STR
13323 BGP_SAFI_HELP_STR
0b16f239
DS
13324 "Detailed information on TCP and BGP neighbor connections\n"
13325 "Neighbor to display information about\n"
13326 "Neighbor to display information about\n"
91d37724 13327 "Neighbor on BGP configured interface\n"
a636c635 13328 "Display detailed prefix count information\n"
9973d184 13329 JSON_STR)
0b16f239 13330{
d62a17ae 13331 afi_t afi = AFI_IP6;
13332 safi_t safi = SAFI_UNICAST;
13333 struct peer *peer;
13334 int idx = 0;
13335 struct bgp *bgp = NULL;
9f049418
DS
13336 bool uj = use_json(argc, argv);
13337
13338 if (uj)
13339 argc--;
856ca177 13340
d62a17ae 13341 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13342 &bgp, uj);
d62a17ae 13343 if (!idx)
13344 return CMD_WARNING;
0b16f239 13345
d62a17ae 13346 argv_find(argv, argc, "neighbors", &idx);
13347 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13348 if (!peer)
13349 return CMD_WARNING;
bb46e94f 13350
29c8d9da 13351 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13352}
0b16f239 13353
d6902373
PG
13354#ifdef KEEP_OLD_VPN_COMMANDS
13355DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13356 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13357 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13358 SHOW_STR
13359 IP_STR
13360 BGP_STR
d6902373 13361 BGP_VPNVX_HELP_STR
91d37724 13362 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13363 "Detailed information on TCP and BGP neighbor connections\n"
13364 "Neighbor to display information about\n"
13365 "Neighbor to display information about\n"
91d37724 13366 "Neighbor on BGP configured interface\n"
a636c635 13367 "Display detailed prefix count information\n"
9973d184 13368 JSON_STR)
a636c635 13369{
d62a17ae 13370 int idx_peer = 6;
13371 struct peer *peer;
9f049418 13372 bool uj = use_json(argc, argv);
a636c635 13373
d62a17ae 13374 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13375 if (!peer)
13376 return CMD_WARNING;
13377
13378 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13379}
13380
d6902373
PG
13381DEFUN (show_ip_bgp_vpn_all_route_prefix,
13382 show_ip_bgp_vpn_all_route_prefix_cmd,
13383 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13384 SHOW_STR
13385 IP_STR
13386 BGP_STR
d6902373 13387 BGP_VPNVX_HELP_STR
91d37724
QY
13388 "Display information about all VPNv4 NLRIs\n"
13389 "Network in the BGP routing table to display\n"
3a2d747c 13390 "Network in the BGP routing table to display\n"
9973d184 13391 JSON_STR)
91d37724 13392{
d62a17ae 13393 int idx = 0;
13394 char *network = NULL;
13395 struct bgp *bgp = bgp_get_default();
13396 if (!bgp) {
13397 vty_out(vty, "Can't find default instance\n");
13398 return CMD_WARNING;
13399 }
87e34b58 13400
d62a17ae 13401 if (argv_find(argv, argc, "A.B.C.D", &idx))
13402 network = argv[idx]->arg;
13403 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13404 network = argv[idx]->arg;
13405 else {
13406 vty_out(vty, "Unable to figure out Network\n");
13407 return CMD_WARNING;
13408 }
87e34b58 13409
d62a17ae 13410 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13411 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13412 use_json(argc, argv));
91d37724 13413}
d6902373 13414#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13415
44c69747
LK
13416DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13417 show_bgp_l2vpn_evpn_route_prefix_cmd,
13418 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13419 SHOW_STR
4c63a661
PG
13420 BGP_STR
13421 L2VPN_HELP_STR
13422 EVPN_HELP_STR
44c69747
LK
13423 "Network in the BGP routing table to display\n"
13424 "Network in the BGP routing table to display\n"
4c63a661
PG
13425 "Network in the BGP routing table to display\n"
13426 "Network in the BGP routing table to display\n"
13427 JSON_STR)
13428{
d62a17ae 13429 int idx = 0;
13430 char *network = NULL;
44c69747 13431 int prefix_check = 0;
a636c635 13432
44c69747
LK
13433 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13434 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13435 network = argv[idx]->arg;
44c69747 13436 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13437 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13438 network = argv[idx]->arg;
44c69747
LK
13439 prefix_check = 1;
13440 } else {
d62a17ae 13441 vty_out(vty, "Unable to figure out Network\n");
13442 return CMD_WARNING;
13443 }
44c69747
LK
13444 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13445 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13446 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13447}
13448
2f9bc755
DS
13449static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13450 struct bgp_table *table, int *header1,
13451 int *header2, json_object *json,
13452 json_object *json_scode,
13453 json_object *json_ocode, bool wide)
13454{
13455 uint64_t version = table ? table->version : 0;
23d0a753 13456 char buf[BUFSIZ] = {0};
2f9bc755
DS
13457
13458 if (*header1) {
13459 if (json) {
13460 json_object_int_add(json, "bgpTableVersion", version);
13461 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13462 inet_ntop(AF_INET,
13463 &bgp->router_id, buf,
13464 sizeof(buf)));
2f9bc755
DS
13465 json_object_int_add(json, "defaultLocPrf",
13466 bgp->default_local_pref);
13467 json_object_int_add(json, "localAS", bgp->as);
13468 json_object_object_add(json, "bgpStatusCodes",
13469 json_scode);
13470 json_object_object_add(json, "bgpOriginCodes",
13471 json_ocode);
13472 } else {
13473 vty_out(vty,
23d0a753
DA
13474 "BGP table version is %" PRIu64
13475 ", local router ID is %pI4, vrf id ",
13476 version, &bgp->router_id);
2f9bc755
DS
13477 if (bgp->vrf_id == VRF_UNKNOWN)
13478 vty_out(vty, "%s", VRFID_NONE_STR);
13479 else
13480 vty_out(vty, "%u", bgp->vrf_id);
13481 vty_out(vty, "\n");
13482 vty_out(vty, "Default local pref %u, ",
13483 bgp->default_local_pref);
13484 vty_out(vty, "local AS %u\n", bgp->as);
13485 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13486 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13487 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13488 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13489 }
13490 *header1 = 0;
13491 }
13492 if (*header2) {
13493 if (!json)
13494 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13495 : BGP_SHOW_HEADER));
13496 *header2 = 0;
13497 }
13498}
13499
d9478df0
TA
13500static void
13501show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13502 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13503 const char *rmap_name, json_object *json, json_object *json_ar,
13504 json_object *json_scode, json_object *json_ocode,
96c81f66 13505 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13506 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13507{
d62a17ae 13508 struct bgp_adj_in *ain;
13509 struct bgp_adj_out *adj;
9bcb3eef 13510 struct bgp_dest *dest;
d62a17ae 13511 struct bgp *bgp;
d62a17ae 13512 struct attr attr;
13513 int ret;
13514 struct update_subgroup *subgrp;
d62a17ae 13515 struct peer_af *paf;
f99def61 13516 bool route_filtered;
96f3485c
MK
13517 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13518 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13519 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13520 || (safi == SAFI_EVPN))
13521 ? true
13522 : false;
a636c635 13523
d62a17ae 13524 bgp = peer->bgp;
a636c635 13525
d62a17ae 13526 if (!bgp) {
13527 if (use_json) {
13528 json_object_string_add(json, "alert", "no BGP");
13529 vty_out(vty, "%s\n", json_object_to_json_string(json));
13530 json_object_free(json);
13531 } else
13532 vty_out(vty, "%% No bgp\n");
13533 return;
13534 }
a636c635 13535
d62a17ae 13536 subgrp = peer_subgroup(peer, afi, safi);
13537
6392aaa6 13538 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13539 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13540 char buf[BUFSIZ] = {0};
13541
d62a17ae 13542 if (use_json) {
13543 json_object_int_add(json, "bgpTableVersion",
13544 table->version);
13545 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13546 inet_ntop(AF_INET,
13547 &bgp->router_id, buf,
13548 sizeof(buf)));
01eced22
AD
13549 json_object_int_add(json, "defaultLocPrf",
13550 bgp->default_local_pref);
13551 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13552 json_object_object_add(json, "bgpStatusCodes",
13553 json_scode);
13554 json_object_object_add(json, "bgpOriginCodes",
13555 json_ocode);
07d0c4ed
DA
13556 json_object_string_add(
13557 json, "bgpOriginatingDefaultNetwork",
13558 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13559 } else {
23d0a753
DA
13560 vty_out(vty,
13561 "BGP table version is %" PRIu64
13562 ", local router ID is %pI4, vrf id ",
13563 table->version, &bgp->router_id);
9df8b37c
PZ
13564 if (bgp->vrf_id == VRF_UNKNOWN)
13565 vty_out(vty, "%s", VRFID_NONE_STR);
13566 else
13567 vty_out(vty, "%u", bgp->vrf_id);
13568 vty_out(vty, "\n");
01eced22
AD
13569 vty_out(vty, "Default local pref %u, ",
13570 bgp->default_local_pref);
13571 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13572 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13573 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13574 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13575 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13576
07d0c4ed
DA
13577 vty_out(vty, "Originating default network %s\n\n",
13578 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13579 }
d9478df0 13580 *header1 = 0;
d62a17ae 13581 }
a636c635 13582
9bcb3eef 13583 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13584 if (type == bgp_show_adj_route_received
13585 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13586 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13587 if (ain->peer != peer)
ea47320b 13588 continue;
6392aaa6 13589
d9478df0
TA
13590 show_adj_route_header(vty, bgp, table, header1,
13591 header2, json, json_scode,
13592 json_ocode, wide);
13593
13594 if ((safi == SAFI_MPLS_VPN)
13595 || (safi == SAFI_ENCAP)
13596 || (safi == SAFI_EVPN)) {
13597 if (use_json)
13598 json_object_string_add(
13599 json_ar, "rd", rd_str);
13600 else if (show_rd && rd_str) {
13601 vty_out(vty,
13602 "Route Distinguisher: %s\n",
13603 rd_str);
13604 show_rd = false;
13605 }
13606 }
6392aaa6 13607
6f4f49b2 13608 attr = *ain->attr;
f99def61
AD
13609 route_filtered = false;
13610
13611 /* Filter prefix using distribute list,
13612 * filter list or prefix list
13613 */
b54892e0 13614 const struct prefix *rn_p =
9bcb3eef 13615 bgp_dest_get_prefix(dest);
b54892e0
DS
13616 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13617 safi))
13618 == FILTER_DENY)
f99def61
AD
13619 route_filtered = true;
13620
13621 /* Filter prefix using route-map */
b54892e0
DS
13622 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13623 safi, rmap_name, NULL,
13624 0, NULL);
6392aaa6 13625
13c8e163
AD
13626 if (type == bgp_show_adj_route_filtered &&
13627 !route_filtered && ret != RMAP_DENY) {
b755861b 13628 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13629 continue;
d62a17ae 13630 }
6392aaa6 13631
d9478df0
TA
13632 if (type == bgp_show_adj_route_received
13633 && (route_filtered || ret == RMAP_DENY))
13634 (*filtered_count)++;
6392aaa6 13635
7d3cae70 13636 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13637 use_json, json_ar, wide);
b755861b 13638 bgp_attr_undup(&attr, ain->attr);
d9478df0 13639 (*output_count)++;
d62a17ae 13640 }
6392aaa6 13641 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13642 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13643 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13644 if (paf->peer != peer || !adj->attr)
924c3f6a 13645 continue;
d62a17ae 13646
d9478df0
TA
13647 show_adj_route_header(vty, bgp, table,
13648 header1, header2,
13649 json, json_scode,
13650 json_ocode, wide);
d62a17ae 13651
b54892e0 13652 const struct prefix *rn_p =
9bcb3eef 13653 bgp_dest_get_prefix(dest);
b54892e0 13654
6f4f49b2 13655 attr = *adj->attr;
b755861b 13656 ret = bgp_output_modifier(
b54892e0 13657 peer, rn_p, &attr, afi, safi,
b755861b 13658 rmap_name);
f46d8e1e 13659
b755861b 13660 if (ret != RMAP_DENY) {
d9478df0
TA
13661 if ((safi == SAFI_MPLS_VPN)
13662 || (safi == SAFI_ENCAP)
13663 || (safi == SAFI_EVPN)) {
13664 if (use_json)
13665 json_object_string_add(
13666 json_ar,
13667 "rd",
13668 rd_str);
13669 else if (show_rd
13670 && rd_str) {
13671 vty_out(vty,
13672 "Route Distinguisher: %s\n",
13673 rd_str);
13674 show_rd = false;
13675 }
13676 }
b54892e0 13677 route_vty_out_tmp(
7d3cae70
DA
13678 vty, dest, rn_p, &attr,
13679 safi, use_json, json_ar,
ae248832 13680 wide);
d9478df0 13681 (*output_count)++;
b755861b 13682 } else {
d9478df0 13683 (*filtered_count)++;
a2addae8 13684 }
b755861b
PM
13685
13686 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13687 }
f20ce998
DS
13688 } else if (type == bgp_show_adj_route_bestpath) {
13689 struct bgp_path_info *pi;
13690
d9478df0
TA
13691 show_adj_route_header(vty, bgp, table, header1, header2,
13692 json, json_scode, json_ocode,
13693 wide);
f20ce998
DS
13694
13695 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13696 pi = pi->next) {
13697 if (pi->peer != peer)
13698 continue;
13699
13700 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13701 continue;
13702
7d3cae70 13703 route_vty_out_tmp(vty, dest,
f20ce998
DS
13704 bgp_dest_get_prefix(dest),
13705 pi->attr, safi, use_json,
13706 json_ar, wide);
d9478df0 13707 (*output_count)++;
f20ce998 13708 }
d62a17ae 13709 }
13710 }
a636c635 13711}
2a71e9ce 13712
d62a17ae 13713static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13714 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13715 const char *rmap_name, uint16_t show_flags)
0b16f239 13716{
d9478df0
TA
13717 struct bgp *bgp;
13718 struct bgp_table *table;
d62a17ae 13719 json_object *json = NULL;
d9478df0
TA
13720 json_object *json_scode = NULL;
13721 json_object *json_ocode = NULL;
13722 json_object *json_ar = NULL;
96f3485c 13723 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13724
d9478df0
TA
13725 /* Init BGP headers here so they're only displayed once
13726 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13727 */
13728 int header1 = 1;
13729 int header2 = 1;
13730
13731 /*
13732 * Initialize variables for each RD
13733 * All prefixes under an RD is aggregated within "json_routes"
13734 */
13735 char rd_str[BUFSIZ] = {0};
13736 json_object *json_routes = NULL;
13737
13738
13739 /* For 2-tier tables, prefix counts need to be
13740 * maintained across multiple runs of show_adj_route()
13741 */
13742 unsigned long output_count_per_rd;
13743 unsigned long filtered_count_per_rd;
13744 unsigned long output_count = 0;
13745 unsigned long filtered_count = 0;
13746
13747 if (use_json) {
d62a17ae 13748 json = json_object_new_object();
d9478df0
TA
13749 json_ar = json_object_new_object();
13750 json_scode = json_object_new_object();
13751 json_ocode = json_object_new_object();
13752
13753 json_object_string_add(json_scode, "suppressed", "s");
13754 json_object_string_add(json_scode, "damped", "d");
13755 json_object_string_add(json_scode, "history", "h");
13756 json_object_string_add(json_scode, "valid", "*");
13757 json_object_string_add(json_scode, "best", ">");
13758 json_object_string_add(json_scode, "multipath", "=");
13759 json_object_string_add(json_scode, "internal", "i");
13760 json_object_string_add(json_scode, "ribFailure", "r");
13761 json_object_string_add(json_scode, "stale", "S");
13762 json_object_string_add(json_scode, "removed", "R");
13763
13764 json_object_string_add(json_ocode, "igp", "i");
13765 json_object_string_add(json_ocode, "egp", "e");
13766 json_object_string_add(json_ocode, "incomplete", "?");
13767 }
0b16f239 13768
d62a17ae 13769 if (!peer || !peer->afc[afi][safi]) {
13770 if (use_json) {
13771 json_object_string_add(
13772 json, "warning",
13773 "No such neighbor or address family");
13774 vty_out(vty, "%s\n", json_object_to_json_string(json));
13775 json_object_free(json);
13776 } else
13777 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13778
d62a17ae 13779 return CMD_WARNING;
13780 }
13781
6392aaa6
PM
13782 if ((type == bgp_show_adj_route_received
13783 || type == bgp_show_adj_route_filtered)
d62a17ae 13784 && !CHECK_FLAG(peer->af_flags[afi][safi],
13785 PEER_FLAG_SOFT_RECONFIG)) {
13786 if (use_json) {
13787 json_object_string_add(
13788 json, "warning",
13789 "Inbound soft reconfiguration not enabled");
13790 vty_out(vty, "%s\n", json_object_to_json_string(json));
13791 json_object_free(json);
13792 } else
13793 vty_out(vty,
13794 "%% Inbound soft reconfiguration not enabled\n");
13795
13796 return CMD_WARNING;
13797 }
0b16f239 13798
d9478df0
TA
13799 bgp = peer->bgp;
13800
13801 /* labeled-unicast routes live in the unicast table */
13802 if (safi == SAFI_LABELED_UNICAST)
13803 table = bgp->rib[afi][SAFI_UNICAST];
13804 else
13805 table = bgp->rib[afi][safi];
13806
13807 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13808 || (safi == SAFI_EVPN)) {
13809
13810 struct bgp_dest *dest;
13811
13812 for (dest = bgp_table_top(table); dest;
13813 dest = bgp_route_next(dest)) {
13814 table = bgp_dest_get_bgp_table_info(dest);
13815 if (!table)
13816 continue;
13817
13818 output_count_per_rd = 0;
13819 filtered_count_per_rd = 0;
13820
13821 if (use_json)
13822 json_routes = json_object_new_object();
13823
13824 const struct prefix_rd *prd;
13825 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13826 dest);
13827
13828 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13829
13830 show_adj_route(vty, peer, table, afi, safi, type,
13831 rmap_name, json, json_routes, json_scode,
13832 json_ocode, show_flags, &header1,
13833 &header2, rd_str, &output_count_per_rd,
13834 &filtered_count_per_rd);
13835
13836 /* Don't include an empty RD in the output! */
13837 if (json_routes && (output_count_per_rd > 0))
13838 json_object_object_add(json_ar, rd_str,
13839 json_routes);
13840
13841 output_count += output_count_per_rd;
13842 filtered_count += filtered_count_per_rd;
13843 }
13844 } else
13845 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13846 json, json_ar, json_scode, json_ocode,
13847 show_flags, &header1, &header2, rd_str,
13848 &output_count, &filtered_count);
13849
13850 if (use_json) {
13851 json_object_object_add(json, "advertisedRoutes", json_ar);
13852 json_object_int_add(json, "totalPrefixCounter", output_count);
13853 json_object_int_add(json, "filteredPrefixCounter",
13854 filtered_count);
13855
13856 vty_out(vty, "%s\n",
13857 json_object_to_json_string_ext(
13858 json, JSON_C_TO_STRING_PRETTY));
13859
13860 if (!output_count && !filtered_count) {
13861 json_object_free(json_scode);
13862 json_object_free(json_ocode);
13863 }
13864
13865 if (json)
13866 json_object_free(json);
13867
13868 } else if (output_count > 0) {
13869 if (filtered_count > 0)
13870 vty_out(vty,
13871 "\nTotal number of prefixes %ld (%ld filtered)\n",
13872 output_count, filtered_count);
13873 else
13874 vty_out(vty, "\nTotal number of prefixes %ld\n",
13875 output_count);
13876 }
0b16f239 13877
d62a17ae 13878 return CMD_SUCCESS;
a636c635 13879}
50ef26d4 13880
f20ce998
DS
13881DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13882 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13883 "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]",
13884 SHOW_STR
13885 IP_STR
13886 BGP_STR
13887 BGP_INSTANCE_HELP_STR
13888 BGP_AFI_HELP_STR
13889 BGP_SAFI_WITH_LABEL_HELP_STR
13890 "Detailed information on TCP and BGP neighbor connections\n"
13891 "Neighbor to display information about\n"
13892 "Neighbor to display information about\n"
13893 "Neighbor on BGP configured interface\n"
13894 "Display the routes selected by best path\n"
13895 JSON_STR
13896 "Increase table width for longer prefixes\n")
13897{
13898 afi_t afi = AFI_IP6;
13899 safi_t safi = SAFI_UNICAST;
13900 char *rmap_name = NULL;
13901 char *peerstr = NULL;
13902 struct bgp *bgp = NULL;
13903 struct peer *peer;
13904 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13905 int idx = 0;
96c81f66 13906 uint16_t show_flags = 0;
96f3485c
MK
13907
13908 if (uj)
13909 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13910
13911 if (wide)
13912 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13913
13914 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13915 &bgp, uj);
13916
13917 if (!idx)
13918 return CMD_WARNING;
13919
13920 argv_find(argv, argc, "neighbors", &idx);
13921 peerstr = argv[++idx]->arg;
13922
13923 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13924 if (!peer)
13925 return CMD_WARNING;
13926
96f3485c
MK
13927 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13928 show_flags);
f20ce998
DS
13929}
13930
ae248832 13931DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13932 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13933 "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 13934 SHOW_STR
13935 IP_STR
13936 BGP_STR
a636c635 13937 BGP_INSTANCE_HELP_STR
7395a2c9 13938 BGP_AFI_HELP_STR
4dd6177e 13939 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13940 "Display the entries for all address families\n"
718e3744 13941 "Detailed information on TCP and BGP neighbor connections\n"
13942 "Neighbor to display information about\n"
13943 "Neighbor to display information about\n"
91d37724 13944 "Neighbor on BGP configured interface\n"
a636c635 13945 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13946 "Display the received routes from neighbor\n"
13947 "Display the filtered routes received from neighbor\n"
a636c635
DW
13948 "Route-map to modify the attributes\n"
13949 "Name of the route map\n"
ae248832
MK
13950 JSON_STR
13951 "Increase table width for longer prefixes\n")
718e3744 13952{
d62a17ae 13953 afi_t afi = AFI_IP6;
13954 safi_t safi = SAFI_UNICAST;
13955 char *rmap_name = NULL;
13956 char *peerstr = NULL;
d62a17ae 13957 struct bgp *bgp = NULL;
13958 struct peer *peer;
6392aaa6 13959 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13960 int idx = 0;
96f3485c 13961 bool first = true;
96c81f66 13962 uint16_t show_flags = 0;
6392aaa6 13963
96f3485c 13964 if (uj) {
d62a17ae 13965 argc--;
96f3485c
MK
13966 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13967 }
13968
13969 if (all) {
13970 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13971 if (argv_find(argv, argc, "ipv4", &idx))
13972 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13973
13974 if (argv_find(argv, argc, "ipv6", &idx))
13975 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13976 }
13977
13978 if (wide)
13979 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13980
9f049418
DS
13981 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13982 &bgp, uj);
13983 if (!idx)
13984 return CMD_WARNING;
13985
d62a17ae 13986 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13987 argv_find(argv, argc, "neighbors", &idx);
13988 peerstr = argv[++idx]->arg;
8c3deaae 13989
d62a17ae 13990 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13991 if (!peer)
13992 return CMD_WARNING;
856ca177 13993
d62a17ae 13994 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13995 type = bgp_show_adj_route_advertised;
13996 else if (argv_find(argv, argc, "received-routes", &idx))
13997 type = bgp_show_adj_route_received;
13998 else if (argv_find(argv, argc, "filtered-routes", &idx))
13999 type = bgp_show_adj_route_filtered;
14000
d62a17ae 14001 if (argv_find(argv, argc, "route-map", &idx))
14002 rmap_name = argv[++idx]->arg;
95cbbd2a 14003
96f3485c
MK
14004 if (!all)
14005 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14006 show_flags);
14007 if (uj)
14008 vty_out(vty, "{\n");
14009
14010 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
14011 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
14012 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
14013 : AFI_IP6;
14014 FOREACH_SAFI (safi) {
96f3485c
MK
14015 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14016 continue;
14017
14018 if (uj) {
14019 if (first)
14020 first = false;
14021 else
14022 vty_out(vty, ",\n");
14023 vty_out(vty, "\"%s\":",
14024 get_afi_safi_str(afi, safi, true));
14025 } else
14026 vty_out(vty, "\nFor address family: %s\n",
14027 get_afi_safi_str(afi, safi, false));
14028
14029 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14030 show_flags);
14031 }
14032 } else {
14033 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
14034 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
14035 continue;
14036
14037 if (uj) {
14038 if (first)
14039 first = false;
14040 else
14041 vty_out(vty, ",\n");
14042 vty_out(vty, "\"%s\":",
14043 get_afi_safi_str(afi, safi, true));
14044 } else
14045 vty_out(vty, "\nFor address family: %s\n",
14046 get_afi_safi_str(afi, safi, false));
14047
14048 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14049 show_flags);
14050 }
14051 }
14052 if (uj)
14053 vty_out(vty, "}\n");
14054
14055 return CMD_SUCCESS;
95cbbd2a
ML
14056}
14057
718e3744 14058DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14059 show_ip_bgp_neighbor_received_prefix_filter_cmd,
8c3deaae 14060 "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14061 SHOW_STR
14062 IP_STR
14063 BGP_STR
8c3deaae
QY
14064 "Address Family\n"
14065 "Address Family\n"
718e3744 14066 "Address Family modifier\n"
14067 "Detailed information on TCP and BGP neighbor connections\n"
14068 "Neighbor to display information about\n"
14069 "Neighbor to display information about\n"
91d37724 14070 "Neighbor on BGP configured interface\n"
718e3744 14071 "Display information received from a BGP neighbor\n"
856ca177 14072 "Display the prefixlist filter\n"
9973d184 14073 JSON_STR)
718e3744 14074{
d62a17ae 14075 afi_t afi = AFI_IP6;
14076 safi_t safi = SAFI_UNICAST;
14077 char *peerstr = NULL;
14078
14079 char name[BUFSIZ];
14080 union sockunion su;
14081 struct peer *peer;
14082 int count, ret;
14083
14084 int idx = 0;
14085
14086 /* show [ip] bgp */
14087 if (argv_find(argv, argc, "ip", &idx))
14088 afi = AFI_IP;
14089 /* [<ipv4|ipv6> [unicast]] */
14090 if (argv_find(argv, argc, "ipv4", &idx))
14091 afi = AFI_IP;
14092 if (argv_find(argv, argc, "ipv6", &idx))
14093 afi = AFI_IP6;
14094 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14095 argv_find(argv, argc, "neighbors", &idx);
14096 peerstr = argv[++idx]->arg;
14097
9f049418 14098 bool uj = use_json(argc, argv);
d62a17ae 14099
14100 ret = str2sockunion(peerstr, &su);
14101 if (ret < 0) {
14102 peer = peer_lookup_by_conf_if(NULL, peerstr);
14103 if (!peer) {
14104 if (uj)
14105 vty_out(vty, "{}\n");
14106 else
14107 vty_out(vty,
14108 "%% Malformed address or name: %s\n",
14109 peerstr);
14110 return CMD_WARNING;
14111 }
14112 } else {
14113 peer = peer_lookup(NULL, &su);
14114 if (!peer) {
14115 if (uj)
14116 vty_out(vty, "{}\n");
14117 else
14118 vty_out(vty, "No peer\n");
14119 return CMD_WARNING;
14120 }
14121 }
718e3744 14122
4ced1a2c 14123 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14124 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14125 if (count) {
14126 if (!uj)
14127 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14128 get_afi_safi_str(afi, safi, false));
d62a17ae 14129 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14130 } else {
14131 if (uj)
14132 vty_out(vty, "{}\n");
14133 else
14134 vty_out(vty, "No functional output\n");
14135 }
718e3744 14136
d62a17ae 14137 return CMD_SUCCESS;
14138}
14139
14140static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14141 afi_t afi, safi_t safi,
9f049418 14142 enum bgp_show_type type, bool use_json)
d62a17ae 14143{
96c81f66 14144 uint16_t show_flags = 0;
96f3485c
MK
14145
14146 if (use_json)
14147 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14148
d62a17ae 14149 if (!peer || !peer->afc[afi][safi]) {
14150 if (use_json) {
14151 json_object *json_no = NULL;
14152 json_no = json_object_new_object();
14153 json_object_string_add(
14154 json_no, "warning",
14155 "No such neighbor or address family");
14156 vty_out(vty, "%s\n",
14157 json_object_to_json_string(json_no));
14158 json_object_free(json_no);
14159 } else
14160 vty_out(vty, "%% No such neighbor or address family\n");
14161 return CMD_WARNING;
14162 }
47fc97cc 14163
7daf25a3
TA
14164 /* labeled-unicast routes live in the unicast table */
14165 if (safi == SAFI_LABELED_UNICAST)
14166 safi = SAFI_UNICAST;
14167
1e2ce4f1
DS
14168 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14169 RPKI_NOT_BEING_USED);
718e3744 14170}
14171
dba3c1d3
PG
14172DEFUN (show_ip_bgp_flowspec_routes_detailed,
14173 show_ip_bgp_flowspec_routes_detailed_cmd,
14174 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14175 SHOW_STR
14176 IP_STR
14177 BGP_STR
14178 BGP_INSTANCE_HELP_STR
14179 BGP_AFI_HELP_STR
14180 "SAFI Flowspec\n"
14181 "Detailed information on flowspec entries\n"
14182 JSON_STR)
14183{
14184 afi_t afi = AFI_IP;
14185 safi_t safi = SAFI_UNICAST;
14186 struct bgp *bgp = NULL;
14187 int idx = 0;
9f049418 14188 bool uj = use_json(argc, argv);
96c81f66 14189 uint16_t show_flags = 0;
9f049418 14190
96f3485c 14191 if (uj) {
9f049418 14192 argc--;
96f3485c
MK
14193 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14194 }
dba3c1d3
PG
14195
14196 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14197 &bgp, uj);
dba3c1d3
PG
14198 if (!idx)
14199 return CMD_WARNING;
14200
96f3485c 14201 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14202 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14203}
14204
718e3744 14205DEFUN (show_ip_bgp_neighbor_routes,
14206 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14207 "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 14208 SHOW_STR
14209 IP_STR
14210 BGP_STR
8386ac43 14211 BGP_INSTANCE_HELP_STR
4f280b15 14212 BGP_AFI_HELP_STR
4dd6177e 14213 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14214 "Detailed information on TCP and BGP neighbor connections\n"
14215 "Neighbor to display information about\n"
14216 "Neighbor to display information about\n"
91d37724 14217 "Neighbor on BGP configured interface\n"
2525cf39 14218 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14219 "Display the dampened routes received from neighbor\n"
14220 "Display routes learned from neighbor\n"
9973d184 14221 JSON_STR)
718e3744 14222{
d62a17ae 14223 char *peerstr = NULL;
14224 struct bgp *bgp = NULL;
14225 afi_t afi = AFI_IP6;
14226 safi_t safi = SAFI_UNICAST;
14227 struct peer *peer;
14228 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14229 int idx = 0;
9f049418
DS
14230 bool uj = use_json(argc, argv);
14231
14232 if (uj)
14233 argc--;
bb46e94f 14234
d62a17ae 14235 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14236 &bgp, uj);
d62a17ae 14237 if (!idx)
14238 return CMD_WARNING;
c493f2d8 14239
d62a17ae 14240 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14241 argv_find(argv, argc, "neighbors", &idx);
14242 peerstr = argv[++idx]->arg;
8c3deaae 14243
d62a17ae 14244 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14245 if (!peer)
d62a17ae 14246 return CMD_WARNING;
bb46e94f 14247
d62a17ae 14248 if (argv_find(argv, argc, "flap-statistics", &idx))
14249 sh_type = bgp_show_type_flap_neighbor;
14250 else if (argv_find(argv, argc, "dampened-routes", &idx))
14251 sh_type = bgp_show_type_damp_neighbor;
14252 else if (argv_find(argv, argc, "routes", &idx))
14253 sh_type = bgp_show_type_neighbor;
2525cf39 14254
d62a17ae 14255 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14256}
6b0655a2 14257
734b349e 14258struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14259
d62a17ae 14260struct bgp_distance {
14261 /* Distance value for the IP source prefix. */
d7c0a89a 14262 uint8_t distance;
718e3744 14263
d62a17ae 14264 /* Name of the access-list to be matched. */
14265 char *access_list;
718e3744 14266};
14267
4f280b15
LB
14268DEFUN (show_bgp_afi_vpn_rd_route,
14269 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14270 "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
14271 SHOW_STR
14272 BGP_STR
14273 BGP_AFI_HELP_STR
14274 "Address Family modifier\n"
14275 "Display information for a route distinguisher\n"
14276 "Route Distinguisher\n"
a111dd97 14277 "All Route Distinguishers\n"
7395a2c9
DS
14278 "Network in the BGP routing table to display\n"
14279 "Network in the BGP routing table to display\n"
14280 JSON_STR)
4f280b15 14281{
d62a17ae 14282 int ret;
14283 struct prefix_rd prd;
14284 afi_t afi = AFI_MAX;
14285 int idx = 0;
4f280b15 14286
ff6566f3
DS
14287 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14288 vty_out(vty, "%% Malformed Address Family\n");
14289 return CMD_WARNING;
14290 }
14291
a111dd97
TA
14292 if (!strcmp(argv[5]->arg, "all"))
14293 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14294 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14295 RPKI_NOT_BEING_USED,
14296 use_json(argc, argv));
14297
d62a17ae 14298 ret = str2prefix_rd(argv[5]->arg, &prd);
14299 if (!ret) {
14300 vty_out(vty, "%% Malformed Route Distinguisher\n");
14301 return CMD_WARNING;
14302 }
ff6566f3 14303
d62a17ae 14304 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14305 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14306 use_json(argc, argv));
4f280b15
LB
14307}
14308
d62a17ae 14309static struct bgp_distance *bgp_distance_new(void)
718e3744 14310{
d62a17ae 14311 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14312}
14313
d62a17ae 14314static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14315{
d62a17ae 14316 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14317}
14318
37a87b8f
CS
14319int bgp_distance_set(uint8_t distance, const char *ip_str,
14320 const char *access_list_str, afi_t afi, safi_t safi,
14321 char *errmsg, size_t errmsg_len)
718e3744 14322{
d62a17ae 14323 int ret;
d62a17ae 14324 struct prefix p;
9bcb3eef 14325 struct bgp_dest *dest;
d62a17ae 14326 struct bgp_distance *bdistance;
718e3744 14327
d62a17ae 14328 ret = str2prefix(ip_str, &p);
14329 if (ret == 0) {
37a87b8f 14330 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14331 return CMD_WARNING_CONFIG_FAILED;
14332 }
718e3744 14333
d62a17ae 14334 /* Get BGP distance node. */
9bcb3eef
DS
14335 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14336 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14337 if (bdistance)
9bcb3eef 14338 bgp_dest_unlock_node(dest);
ca2e160d 14339 else {
d62a17ae 14340 bdistance = bgp_distance_new();
9bcb3eef 14341 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14342 }
718e3744 14343
d62a17ae 14344 /* Set distance value. */
14345 bdistance->distance = distance;
718e3744 14346
d62a17ae 14347 /* Reset access-list configuration. */
e1b36e13 14348 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14349 if (access_list_str)
14350 bdistance->access_list =
14351 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14352
d62a17ae 14353 return CMD_SUCCESS;
718e3744 14354}
14355
37a87b8f
CS
14356int bgp_distance_unset(uint8_t distance, const char *ip_str,
14357 const char *access_list_str, afi_t afi, safi_t safi,
14358 char *errmsg, size_t errmsg_len)
718e3744 14359{
d62a17ae 14360 int ret;
d62a17ae 14361 struct prefix p;
9bcb3eef 14362 struct bgp_dest *dest;
d62a17ae 14363 struct bgp_distance *bdistance;
718e3744 14364
d62a17ae 14365 ret = str2prefix(ip_str, &p);
14366 if (ret == 0) {
37a87b8f 14367 snprintf(errmsg, errmsg_len, "Malformed prefix\n");
d62a17ae 14368 return CMD_WARNING_CONFIG_FAILED;
14369 }
718e3744 14370
9bcb3eef
DS
14371 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14372 if (!dest) {
37a87b8f 14373 snprintf(errmsg, errmsg_len, "Can't find specified prefix\n");
d62a17ae 14374 return CMD_WARNING_CONFIG_FAILED;
14375 }
718e3744 14376
9bcb3eef 14377 bdistance = bgp_dest_get_bgp_distance_info(dest);
1f9a9fff 14378
d62a17ae 14379 if (bdistance->distance != distance) {
37a87b8f
CS
14380 snprintf(errmsg, errmsg_len,
14381 "Distance does not match configured\n");
d62a17ae 14382 return CMD_WARNING_CONFIG_FAILED;
14383 }
718e3744 14384
0a22ddfb 14385 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14386 bgp_distance_free(bdistance);
718e3744 14387
9bcb3eef
DS
14388 bgp_dest_set_bgp_path_info(dest, NULL);
14389 bgp_dest_unlock_node(dest);
14390 bgp_dest_unlock_node(dest);
718e3744 14391
d62a17ae 14392 return CMD_SUCCESS;
718e3744 14393}
14394
718e3744 14395/* Apply BGP information to distance method. */
b8685f9b 14396uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14397 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14398{
9bcb3eef 14399 struct bgp_dest *dest;
801bb996 14400 struct prefix q = {0};
d62a17ae 14401 struct peer *peer;
14402 struct bgp_distance *bdistance;
14403 struct access_list *alist;
14404 struct bgp_static *bgp_static;
14405
14406 if (!bgp)
14407 return 0;
14408
40381db7 14409 peer = pinfo->peer;
d62a17ae 14410
7b7d48e5
DS
14411 if (pinfo->attr->distance)
14412 return pinfo->attr->distance;
14413
801bb996
CS
14414 /* Check source address.
14415 * Note: for aggregate route, peer can have unspec af type.
14416 */
14417 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14418 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14419 return 0;
14420
9bcb3eef
DS
14421 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14422 if (dest) {
14423 bdistance = bgp_dest_get_bgp_distance_info(dest);
14424 bgp_dest_unlock_node(dest);
d62a17ae 14425
14426 if (bdistance->access_list) {
14427 alist = access_list_lookup(afi, bdistance->access_list);
14428 if (alist
14429 && access_list_apply(alist, p) == FILTER_PERMIT)
14430 return bdistance->distance;
14431 } else
14432 return bdistance->distance;
718e3744 14433 }
718e3744 14434
d62a17ae 14435 /* Backdoor check. */
9bcb3eef
DS
14436 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14437 if (dest) {
14438 bgp_static = bgp_dest_get_bgp_static_info(dest);
14439 bgp_dest_unlock_node(dest);
718e3744 14440
d62a17ae 14441 if (bgp_static->backdoor) {
14442 if (bgp->distance_local[afi][safi])
14443 return bgp->distance_local[afi][safi];
14444 else
14445 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14446 }
718e3744 14447 }
718e3744 14448
d62a17ae 14449 if (peer->sort == BGP_PEER_EBGP) {
14450 if (bgp->distance_ebgp[afi][safi])
14451 return bgp->distance_ebgp[afi][safi];
14452 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14453 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14454 if (bgp->distance_ibgp[afi][safi])
14455 return bgp->distance_ibgp[afi][safi];
14456 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14457 } else {
14458 if (bgp->distance_local[afi][safi])
14459 return bgp->distance_local[afi][safi];
14460 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14461 }
718e3744 14462}
14463
a612fb77
DA
14464/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14465 * we should tell ZEBRA update the routes for a specific
14466 * AFI/SAFI to reflect changes in RIB.
14467 */
37a87b8f
CS
14468void bgp_announce_routes_distance_update(struct bgp *bgp, afi_t update_afi,
14469 safi_t update_safi)
a612fb77
DA
14470{
14471 afi_t afi;
14472 safi_t safi;
14473
14474 FOREACH_AFI_SAFI (afi, safi) {
14475 if (!bgp_fibupd_safi(safi))
14476 continue;
14477
8b54bc30
DA
14478 if (afi != update_afi && safi != update_safi)
14479 continue;
14480
14481 if (BGP_DEBUG(zebra, ZEBRA))
14482 zlog_debug(
14483 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14484 __func__, afi, safi);
14485 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14486 }
14487}
14488
37a87b8f
CS
14489DEFUN_YANG(bgp_distance, bgp_distance_cmd,
14490 "distance bgp (1-255) (1-255) (1-255)",
14491 "Define an administrative distance\n"
14492 "BGP distance\n"
14493 "Distance for routes external to the AS\n"
14494 "Distance for routes internal to the AS\n"
14495 "Distance for local routes\n")
718e3744 14496{
d62a17ae 14497 int idx_number = 2;
14498 int idx_number_2 = 3;
14499 int idx_number_3 = 4;
14500 afi_t afi;
14501 safi_t safi;
37a87b8f 14502 char xpath[XPATH_MAXLEN];
718e3744 14503
d62a17ae 14504 afi = bgp_node_afi(vty);
14505 safi = bgp_node_safi(vty);
718e3744 14506
37a87b8f
CS
14507 snprintf(
14508 xpath, sizeof(xpath),
14509 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14510 yang_afi_safi_value2identity(afi, safi),
14511 bgp_afi_safi_get_container_str(afi, safi));
14512 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, argv[idx_number]->arg);
14513 snprintf(
14514 xpath, sizeof(xpath),
14515 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14516 yang_afi_safi_value2identity(afi, safi),
14517 bgp_afi_safi_get_container_str(afi, safi));
14518 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14519 argv[idx_number_2]->arg);
14520 snprintf(
14521 xpath, sizeof(xpath),
14522 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14523 yang_afi_safi_value2identity(afi, safi),
14524 bgp_afi_safi_get_container_str(afi, safi));
14525
14526 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
14527 argv[idx_number_3]->arg);
14528
14529 return nb_cli_apply_changes(vty, NULL);
14530}
14531
14532DEFUN_YANG(no_bgp_distance, no_bgp_distance_cmd,
14533 "no distance bgp [(1-255) (1-255) (1-255)]",
14534 NO_STR
14535 "Define an administrative distance\n"
14536 "BGP distance\n"
14537 "Distance for routes external to the AS\n"
14538 "Distance for routes internal to the AS\n"
14539 "Distance for local routes\n")
14540{
14541 afi_t afi;
14542 safi_t safi;
14543 char xpath[XPATH_MAXLEN];
14544
14545 afi = bgp_node_afi(vty);
14546 safi = bgp_node_safi(vty);
14547
14548 snprintf(
14549 xpath, sizeof(xpath),
14550 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/external",
14551 yang_afi_safi_value2identity(afi, safi),
14552 bgp_afi_safi_get_container_str(afi, safi));
14553 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14554 snprintf(
14555 xpath, sizeof(xpath),
14556 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/internal",
14557 yang_afi_safi_value2identity(afi, safi),
14558 bgp_afi_safi_get_container_str(afi, safi));
14559 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14560 snprintf(
14561 xpath, sizeof(xpath),
14562 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance/local",
14563 yang_afi_safi_value2identity(afi, safi),
14564 bgp_afi_safi_get_container_str(afi, safi));
14565
14566 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
14567
14568 return nb_cli_apply_changes(vty, NULL);
718e3744 14569}
14570
37a87b8f
CS
14571void cli_show_bgp_global_afi_safi_admin_distance_config(struct vty *vty,
14572 struct lyd_node *dnode,
14573 bool show_defaults)
718e3744 14574{
37a87b8f
CS
14575 uint8_t distance_ebgp, distance_ibgp, distance_local;
14576
14577 distance_ebgp = yang_dnode_get_uint8(dnode, "./external");
14578 distance_ibgp = yang_dnode_get_uint8(dnode, "./internal");
14579 distance_local = yang_dnode_get_uint8(dnode, "./local");
14580
14581 vty_out(vty, " distance bgp %d %d %d\n", distance_ebgp, distance_ibgp,
14582 distance_local);
14583}
14584
8cc7152a
CS
14585DEFPY_YANG(bgp_distance_source,
14586 bgp_distance_source_cmd,
14587 "[no] distance (1-255) <A.B.C.D/M | X:X::X:X/M>$prefix [WORD$acl]",
37a87b8f
CS
14588 NO_STR
14589 "Define an administrative distance\n"
8cc7152a 14590 "Distance value\n"
e12affc1
SW
14591 "IPv4 source prefix\n"
14592 "IPv6 source prefix\n"
37a87b8f 14593 "Access list name\n")
718e3744 14594{
37a87b8f
CS
14595 afi_t afi;
14596 safi_t safi;
14597 char xpath[XPATH_MAXLEN];
14598
14599 afi = bgp_node_afi(vty);
14600 safi = bgp_node_safi(vty);
14601
8cc7152a
CS
14602 if (!no) {
14603 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
14604 nb_cli_enqueue_change(vty, "./distance", NB_OP_MODIFY,
14605 distance_str);
14606 if (acl)
14607 nb_cli_enqueue_change(vty,
14608 "./access-list-policy-export",
14609 NB_OP_CREATE, acl);
14610 else
14611 nb_cli_enqueue_change(vty,
14612 "./access-list-policy-export",
14613 NB_OP_DESTROY, NULL);
14614 } else {
14615 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
14616 }
37a87b8f
CS
14617
14618 snprintf(
14619 xpath, sizeof(xpath),
14620 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/admin-distance-route[prefix='%s']",
14621 yang_afi_safi_value2identity(afi, safi),
8cc7152a 14622 bgp_afi_safi_get_container_str(afi, safi), prefix_str);
37a87b8f
CS
14623
14624 return nb_cli_apply_changes(vty, xpath);
734b349e
MZ
14625}
14626
37a87b8f
CS
14627void cli_show_bgp_global_afi_safi_unicast_admin_distance_route(
14628 struct vty *vty, struct lyd_node *dnode, bool show_defaults)
14629{
14630 vty_out(vty, " distance %d %s %s\n",
14631 yang_dnode_get_uint8(dnode, "./distance"),
14632 yang_dnode_get_string(dnode, "./prefix"),
14633 (yang_dnode_exists(dnode, "./access-list-policy-export"))
14634 ? yang_dnode_get_string(dnode,
14635 "./access-list-policy-export")
14636 : "");
14637}
14638
7c98d487
DA
14639DEFPY_YANG(
14640 bgp_dampening, bgp_dampening_cmd,
14641 "[no] bgp dampening [(1-45)$halflife [(1-20000)$reuse (1-20000)$suppress (1-255)$max_suppress]]",
14642 NO_STR
14643 "BGP Specific commands\n"
14644 "Enable route-flap dampening\n"
14645 "Half-life time for the penalty\n"
14646 "Value to start reusing a route\n"
14647 "Value to start suppressing a route\n"
14648 "Maximum duration to suppress a stable route\n")
37a87b8f
CS
14649{
14650 afi_t afi;
14651 safi_t safi;
14652 char xpath[XPATH_MAXLEN];
718e3744 14653
37a87b8f
CS
14654 afi = bgp_node_afi(vty);
14655 safi = bgp_node_safi(vty);
14656
d9ce5113
CS
14657 if (!no) {
14658 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "true");
14659 if (argc == 6) {
14660 nb_cli_enqueue_change(vty, "./reach-decay",
14661 NB_OP_MODIFY, halflife_str);
14662 nb_cli_enqueue_change(vty, "./reuse-above",
14663 NB_OP_MODIFY, reuse_str);
14664 nb_cli_enqueue_change(vty, "./suppress-above",
14665 NB_OP_MODIFY, suppress_str);
14666 nb_cli_enqueue_change(vty, "./unreach-decay",
7c98d487 14667 NB_OP_MODIFY, max_suppress_str);
d9ce5113
CS
14668 } if (argc == 3) {
14669 nb_cli_enqueue_change(vty, "./reach-decay",
14670 NB_OP_MODIFY, halflife_str);
14671 }
14672 } else {
14673 nb_cli_enqueue_change(vty, "./enable", NB_OP_MODIFY, "false");
14674 }
7ebe9748 14675
37a87b8f
CS
14676 snprintf(
14677 xpath, sizeof(xpath),
14678 "./global/afi-safis/afi-safi[afi-safi-name='%s']/%s/route-flap-dampening",
14679 yang_afi_safi_value2identity(afi, safi),
14680 bgp_afi_safi_get_container_str(afi, safi));
14681
14682 return nb_cli_apply_changes(vty, xpath);
718e3744 14683}
14684
37a87b8f
CS
14685void cli_show_bgp_global_afi_safi_route_flap_dampening(struct vty *vty,
14686 struct lyd_node *dnode,
14687 bool show_defaults)
718e3744 14688{
37a87b8f
CS
14689 if (!yang_dnode_get_bool(dnode, "./enable"))
14690 return;
14691
14692 int half = DEFAULT_HALF_LIFE * 60;
14693 int reuse = DEFAULT_REUSE;
14694 int suppress = DEFAULT_SUPPRESS;
14695 int max;
14696
14697 half = yang_dnode_get_uint8(dnode, "../reach-decay");
14698 reuse = yang_dnode_get_uint16(dnode, "../reuse-above");
14699 suppress = yang_dnode_get_uint16(dnode, "../suppress-above");
14700 max = yang_dnode_get_uint8(dnode, "../unreach-decay");
14701
14702 if (half == DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14703 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14704 vty_out(vty, " bgp dampening\n");
14705 else if (half != DEFAULT_HALF_LIFE * 60 && reuse == DEFAULT_REUSE
14706 && suppress == DEFAULT_SUPPRESS && max == half * 4)
14707 vty_out(vty, " bgp dampening %u\n", half);
14708 else
14709 vty_out(vty, " bgp dampening %u %d %d %d\n", half, reuse,
14710 suppress, max);
718e3744 14711}
14712
718e3744 14713/* Display specified route of BGP table. */
d62a17ae 14714static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14715 const char *ip_str, afi_t afi, safi_t safi,
14716 struct prefix_rd *prd, int prefix_check)
14717{
14718 int ret;
14719 struct prefix match;
9bcb3eef
DS
14720 struct bgp_dest *dest;
14721 struct bgp_dest *rm;
40381db7
DS
14722 struct bgp_path_info *pi;
14723 struct bgp_path_info *pi_temp;
d62a17ae 14724 struct bgp *bgp;
14725 struct bgp_table *table;
14726
14727 /* BGP structure lookup. */
14728 if (view_name) {
14729 bgp = bgp_lookup_by_name(view_name);
14730 if (bgp == NULL) {
14731 vty_out(vty, "%% Can't find BGP instance %s\n",
14732 view_name);
14733 return CMD_WARNING;
14734 }
14735 } else {
14736 bgp = bgp_get_default();
14737 if (bgp == NULL) {
14738 vty_out(vty, "%% No BGP process is configured\n");
14739 return CMD_WARNING;
14740 }
718e3744 14741 }
718e3744 14742
d62a17ae 14743 /* Check IP address argument. */
14744 ret = str2prefix(ip_str, &match);
14745 if (!ret) {
14746 vty_out(vty, "%% address is malformed\n");
14747 return CMD_WARNING;
14748 }
718e3744 14749
d62a17ae 14750 match.family = afi2family(afi);
14751
14752 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14753 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14754 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14755 dest = bgp_route_next(dest)) {
14756 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14757
9bcb3eef 14758 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14759 continue;
9bcb3eef 14760 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14761 if (!table)
ea47320b
DL
14762 continue;
14763 if ((rm = bgp_node_match(table, &match)) == NULL)
14764 continue;
d62a17ae 14765
9bcb3eef 14766 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14767
ea47320b 14768 if (!prefix_check
b54892e0 14769 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14770 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14771 while (pi) {
14772 if (pi->extra && pi->extra->damp_info) {
14773 pi_temp = pi->next;
ea47320b 14774 bgp_damp_info_free(
40ec3340
DS
14775 &pi->extra->damp_info,
14776 &bgp->damp[afi][safi],
a935f597 14777 1, afi, safi);
40381db7 14778 pi = pi_temp;
ea47320b 14779 } else
40381db7 14780 pi = pi->next;
d62a17ae 14781 }
ea47320b
DL
14782 }
14783
9bcb3eef 14784 bgp_dest_unlock_node(rm);
d62a17ae 14785 }
14786 } else {
9bcb3eef 14787 if ((dest = bgp_node_match(bgp->rib[afi][safi], &match))
d62a17ae 14788 != NULL) {
9bcb3eef 14789 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14790
d62a17ae 14791 if (!prefix_check
9bcb3eef
DS
14792 || dest_p->prefixlen == match.prefixlen) {
14793 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14794 while (pi) {
14795 if (pi->extra && pi->extra->damp_info) {
14796 pi_temp = pi->next;
c8ddbd48 14797 struct bgp_damp_info *bdi =
14798 pi->extra->damp_info;
14799 if (bdi->lastrecord
14800 == BGP_RECORD_UPDATE) {
14801 bgp_aggregate_increment(
14802 bgp,
14803 &bdi->dest->p,
14804 bdi->path,
14805 bdi->afi,
14806 bdi->safi);
14807 bgp_process(bgp,
14808 bdi->dest,
14809 bdi->afi,
14810 bdi->safi);
14811 }
d62a17ae 14812 bgp_damp_info_free(
40ec3340
DS
14813 &pi->extra->damp_info,
14814 &bgp->damp[afi][safi],
a935f597 14815 1, afi, safi);
40381db7 14816 pi = pi_temp;
d62a17ae 14817 } else
40381db7 14818 pi = pi->next;
d62a17ae 14819 }
14820 }
14821
9bcb3eef 14822 bgp_dest_unlock_node(dest);
d62a17ae 14823 }
14824 }
718e3744 14825
d62a17ae 14826 return CMD_SUCCESS;
718e3744 14827}
14828
14829DEFUN (clear_ip_bgp_dampening,
14830 clear_ip_bgp_dampening_cmd,
14831 "clear ip bgp dampening",
14832 CLEAR_STR
14833 IP_STR
14834 BGP_STR
14835 "Clear route flap dampening information\n")
14836{
40ec3340 14837 VTY_DECLVAR_CONTEXT(bgp, bgp);
c8ddbd48 14838 bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
40ec3340 14839 SAFI_UNICAST);
d62a17ae 14840 return CMD_SUCCESS;
718e3744 14841}
14842
14843DEFUN (clear_ip_bgp_dampening_prefix,
14844 clear_ip_bgp_dampening_prefix_cmd,
14845 "clear ip bgp dampening A.B.C.D/M",
14846 CLEAR_STR
14847 IP_STR
14848 BGP_STR
14849 "Clear route flap dampening information\n"
0c7b1b01 14850 "IPv4 prefix\n")
718e3744 14851{
d62a17ae 14852 int idx_ipv4_prefixlen = 4;
14853 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14854 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14855}
14856
14857DEFUN (clear_ip_bgp_dampening_address,
14858 clear_ip_bgp_dampening_address_cmd,
14859 "clear ip bgp dampening A.B.C.D",
14860 CLEAR_STR
14861 IP_STR
14862 BGP_STR
14863 "Clear route flap dampening information\n"
14864 "Network to clear damping information\n")
14865{
d62a17ae 14866 int idx_ipv4 = 4;
14867 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14868 SAFI_UNICAST, NULL, 0);
718e3744 14869}
14870
14871DEFUN (clear_ip_bgp_dampening_address_mask,
14872 clear_ip_bgp_dampening_address_mask_cmd,
14873 "clear ip bgp dampening A.B.C.D A.B.C.D",
14874 CLEAR_STR
14875 IP_STR
14876 BGP_STR
14877 "Clear route flap dampening information\n"
14878 "Network to clear damping information\n"
14879 "Network mask\n")
14880{
d62a17ae 14881 int idx_ipv4 = 4;
14882 int idx_ipv4_2 = 5;
14883 int ret;
14884 char prefix_str[BUFSIZ];
718e3744 14885
d62a17ae 14886 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14887 prefix_str, sizeof(prefix_str));
d62a17ae 14888 if (!ret) {
14889 vty_out(vty, "%% Inconsistent address and mask\n");
14890 return CMD_WARNING;
14891 }
718e3744 14892
d62a17ae 14893 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14894 NULL, 0);
718e3744 14895}
6b0655a2 14896
e3b78da8 14897static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14898{
14899 struct vty *vty = arg;
e3b78da8 14900 struct peer *peer = bucket->data;
825d9834
DS
14901 char buf[SU_ADDRSTRLEN];
14902
14903 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14904 sockunion2str(&peer->su, buf, sizeof(buf)));
14905}
14906
2a0e69ae
DS
14907DEFUN (show_bgp_listeners,
14908 show_bgp_listeners_cmd,
14909 "show bgp listeners",
14910 SHOW_STR
14911 BGP_STR
14912 "Display Listen Sockets and who created them\n")
14913{
14914 bgp_dump_listener_info(vty);
14915
14916 return CMD_SUCCESS;
14917}
14918
825d9834
DS
14919DEFUN (show_bgp_peerhash,
14920 show_bgp_peerhash_cmd,
14921 "show bgp peerhash",
14922 SHOW_STR
14923 BGP_STR
14924 "Display information about the BGP peerhash\n")
14925{
14926 struct list *instances = bm->bgp;
14927 struct listnode *node;
14928 struct bgp *bgp;
14929
14930 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14931 vty_out(vty, "BGP: %s\n", bgp->name);
14932 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14933 vty);
14934 }
14935
14936 return CMD_SUCCESS;
14937}
14938
587ff0fd 14939/* also used for encap safi */
2b791107
DL
14940static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14941 afi_t afi, safi_t safi)
d62a17ae 14942{
9bcb3eef
DS
14943 struct bgp_dest *pdest;
14944 struct bgp_dest *dest;
d62a17ae 14945 struct bgp_table *table;
b54892e0
DS
14946 const struct prefix *p;
14947 const struct prefix_rd *prd;
d62a17ae 14948 struct bgp_static *bgp_static;
14949 mpls_label_t label;
d62a17ae 14950 char rdbuf[RD_ADDRSTRLEN];
14951
14952 /* Network configuration. */
9bcb3eef
DS
14953 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14954 pdest = bgp_route_next(pdest)) {
14955 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14956 if (!table)
ea47320b 14957 continue;
d62a17ae 14958
9bcb3eef
DS
14959 for (dest = bgp_table_top(table); dest;
14960 dest = bgp_route_next(dest)) {
14961 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14962 if (bgp_static == NULL)
ea47320b 14963 continue;
d62a17ae 14964
9bcb3eef
DS
14965 p = bgp_dest_get_prefix(dest);
14966 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14967 pdest);
d62a17ae 14968
ea47320b 14969 /* "network" configuration display. */
06b9f471 14970 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14971 label = decode_label(&bgp_static->label);
14972
8228a9a7 14973 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14974 if (safi == SAFI_MPLS_VPN)
14975 vty_out(vty, " label %u", label);
14976
14977 if (bgp_static->rmap.name)
14978 vty_out(vty, " route-map %s",
14979 bgp_static->rmap.name);
e2a86ad9
DS
14980
14981 if (bgp_static->backdoor)
14982 vty_out(vty, " backdoor");
14983
ea47320b
DL
14984 vty_out(vty, "\n");
14985 }
14986 }
d62a17ae 14987}
14988
2b791107
DL
14989static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14990 afi_t afi, safi_t safi)
d62a17ae 14991{
9bcb3eef
DS
14992 struct bgp_dest *pdest;
14993 struct bgp_dest *dest;
d62a17ae 14994 struct bgp_table *table;
b54892e0
DS
14995 const struct prefix *p;
14996 const struct prefix_rd *prd;
d62a17ae 14997 struct bgp_static *bgp_static;
ff44f570 14998 char buf[PREFIX_STRLEN * 2];
d62a17ae 14999 char buf2[SU_ADDRSTRLEN];
15000 char rdbuf[RD_ADDRSTRLEN];
0a50c248 15001 char esi_buf[ESI_BYTES];
d62a17ae 15002
15003 /* Network configuration. */
9bcb3eef
DS
15004 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
15005 pdest = bgp_route_next(pdest)) {
15006 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 15007 if (!table)
ea47320b 15008 continue;
d62a17ae 15009
9bcb3eef
DS
15010 for (dest = bgp_table_top(table); dest;
15011 dest = bgp_route_next(dest)) {
15012 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15013 if (bgp_static == NULL)
ea47320b 15014 continue;
d62a17ae 15015
ea47320b 15016 char *macrouter = NULL;
d62a17ae 15017
ea47320b
DL
15018 if (bgp_static->router_mac)
15019 macrouter = prefix_mac2str(
15020 bgp_static->router_mac, NULL, 0);
15021 if (bgp_static->eth_s_id)
0a50c248
AK
15022 esi_to_str(bgp_static->eth_s_id,
15023 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
15024 p = bgp_dest_get_prefix(dest);
15025 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 15026
ea47320b 15027 /* "network" configuration display. */
06b9f471 15028 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
15029 if (p->u.prefix_evpn.route_type == 5) {
15030 char local_buf[PREFIX_STRLEN];
3714a385 15031 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
15032 struct prefix_evpn *)p)
15033 ? AF_INET
15034 : AF_INET6;
3714a385 15035 inet_ntop(family,
15036 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15037 local_buf, PREFIX_STRLEN);
772270f3
QY
15038 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15039 p->u.prefix_evpn.prefix_addr
15040 .ip_prefix_length);
197cb530
PG
15041 } else {
15042 prefix2str(p, buf, sizeof(buf));
15043 }
ea47320b 15044
a4d82a8a
PZ
15045 if (bgp_static->gatewayIp.family == AF_INET
15046 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15047 inet_ntop(bgp_static->gatewayIp.family,
15048 &bgp_static->gatewayIp.u.prefix, buf2,
15049 sizeof(buf2));
ea47320b 15050 vty_out(vty,
7bcc8dac 15051 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15052 buf, rdbuf,
15053 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15054 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15055 macrouter);
15056
0a22ddfb 15057 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15058 }
15059 }
3da6fcd5
PG
15060}
15061
718e3744 15062/* Configuration of static route announcement and aggregate
15063 information. */
2b791107
DL
15064void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15065 safi_t safi)
d62a17ae 15066{
9bcb3eef 15067 struct bgp_dest *dest;
b54892e0 15068 const struct prefix *p;
d62a17ae 15069 struct bgp_static *bgp_static;
15070 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15071
2b791107
DL
15072 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15073 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15074 return;
15075 }
d62a17ae 15076
2b791107
DL
15077 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15078 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15079 return;
15080 }
d62a17ae 15081
15082 /* Network configuration. */
9bcb3eef
DS
15083 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15084 dest = bgp_route_next(dest)) {
15085 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15086 if (bgp_static == NULL)
ea47320b 15087 continue;
d62a17ae 15088
9bcb3eef 15089 p = bgp_dest_get_prefix(dest);
d62a17ae 15090
8228a9a7 15091 vty_out(vty, " network %pFX", p);
d62a17ae 15092
ea47320b
DL
15093 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15094 vty_out(vty, " label-index %u",
15095 bgp_static->label_index);
d62a17ae 15096
ea47320b
DL
15097 if (bgp_static->rmap.name)
15098 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15099
15100 if (bgp_static->backdoor)
15101 vty_out(vty, " backdoor");
718e3744 15102
ea47320b
DL
15103 vty_out(vty, "\n");
15104 }
15105
d62a17ae 15106 /* Aggregate-address configuration. */
9bcb3eef
DS
15107 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15108 dest = bgp_route_next(dest)) {
15109 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15110 if (bgp_aggregate == NULL)
ea47320b 15111 continue;
d62a17ae 15112
9bcb3eef 15113 p = bgp_dest_get_prefix(dest);
d62a17ae 15114
8228a9a7 15115 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15116
ea47320b
DL
15117 if (bgp_aggregate->as_set)
15118 vty_out(vty, " as-set");
d62a17ae 15119
ea47320b
DL
15120 if (bgp_aggregate->summary_only)
15121 vty_out(vty, " summary-only");
718e3744 15122
20894f50
DA
15123 if (bgp_aggregate->rmap.name)
15124 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15125
229757f1
DA
15126 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15127 vty_out(vty, " origin %s",
15128 bgp_origin2str(bgp_aggregate->origin));
15129
6aabb15d
RZ
15130 if (bgp_aggregate->match_med)
15131 vty_out(vty, " matching-MED-only");
15132
365ab2e7
RZ
15133 if (bgp_aggregate->suppress_map_name)
15134 vty_out(vty, " suppress-map %s",
15135 bgp_aggregate->suppress_map_name);
15136
ea47320b
DL
15137 vty_out(vty, "\n");
15138 }
d62a17ae 15139}
734b349e 15140
2b791107 15141void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15142 safi_t safi)
d62a17ae 15143{
9bcb3eef 15144 struct bgp_dest *dest;
d62a17ae 15145 struct bgp_distance *bdistance;
15146
15147 /* Distance configuration. */
15148 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15149 && bgp->distance_local[afi][safi]
15150 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15151 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15152 || bgp->distance_local[afi][safi]
15153 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15154 vty_out(vty, " distance bgp %d %d %d\n",
15155 bgp->distance_ebgp[afi][safi],
15156 bgp->distance_ibgp[afi][safi],
15157 bgp->distance_local[afi][safi]);
15158 }
734b349e 15159
9bcb3eef
DS
15160 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15161 dest = bgp_route_next(dest)) {
15162 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15163 if (bdistance != NULL)
56ca3b5b 15164 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15165 bdistance->distance, dest,
d62a17ae 15166 bdistance->access_list ? bdistance->access_list
15167 : "");
ca2e160d 15168 }
718e3744 15169}
15170
15171/* Allocate routing table structure and install commands. */
d62a17ae 15172void bgp_route_init(void)
15173{
15174 afi_t afi;
15175 safi_t safi;
15176
15177 /* Init BGP distance table. */
05c7a1cc 15178 FOREACH_AFI_SAFI (afi, safi)
960035b2 15179 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15180
15181 /* IPv4 BGP commands. */
15182 install_element(BGP_NODE, &bgp_table_map_cmd);
15183 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15184 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15185
554b3b10 15186 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15187
15188 /* IPv4 unicast configuration. */
15189 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15190 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15191 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15192
554b3b10 15193 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15194
15195 /* IPv4 multicast configuration. */
15196 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15197 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15198 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15199 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15200
15201 /* IPv4 labeled-unicast configuration. */
fb985e0c 15202 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15203 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15204
d62a17ae 15205 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15206 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 15207 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15208 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 15209 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 15210 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15211 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15212 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15213
15214 install_element(VIEW_NODE,
15215 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15216 install_element(VIEW_NODE,
15217 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15218 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15219 install_element(VIEW_NODE,
15220 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15221#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15222 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15223#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15224 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15225 install_element(VIEW_NODE,
44c69747 15226 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15227
d62a17ae 15228 /* BGP dampening clear commands */
15229 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15230 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15231
d62a17ae 15232 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15233 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15234
15235 /* prefix count */
15236 install_element(ENABLE_NODE,
15237 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15238#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15239 install_element(ENABLE_NODE,
15240 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15241#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15242
d62a17ae 15243 /* New config IPv6 BGP commands. */
15244 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15245 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15246 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15247
554b3b10 15248 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15249
15250 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15251
fb985e0c
DA
15252 /* IPv6 labeled unicast address family. */
15253 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15254 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15255
d62a17ae 15256 install_element(BGP_NODE, &bgp_distance_cmd);
15257 install_element(BGP_NODE, &no_bgp_distance_cmd);
15258 install_element(BGP_NODE, &bgp_distance_source_cmd);
d62a17ae 15259 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15260 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15261 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
d62a17ae 15262 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15263 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15264 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
d62a17ae 15265 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15266 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
8cc7152a 15267 install_element(BGP_IPV6_NODE, &bgp_distance_source_cmd);
d62a17ae 15268 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15269 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
8cc7152a 15270 install_element(BGP_IPV6M_NODE, &bgp_distance_source_cmd);
d62a17ae 15271
ef5f4b23 15272 /* BGP dampening */
d9ce5113
CS
15273 install_element(BGP_NODE, &bgp_dampening_cmd);
15274 install_element(BGP_IPV4_NODE, &bgp_dampening_cmd);
15275 install_element(BGP_IPV4M_NODE, &bgp_dampening_cmd);
15276 install_element(BGP_IPV4L_NODE, &bgp_dampening_cmd);
15277 install_element(BGP_IPV6_NODE, &bgp_dampening_cmd);
15278 install_element(BGP_IPV6M_NODE, &bgp_dampening_cmd);
15279 install_element(BGP_IPV6L_NODE, &bgp_dampening_cmd);
d62a17ae 15280
15281 /* Large Communities */
15282 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15283 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15284
15285 /* show bgp ipv4 flowspec detailed */
15286 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15287
2a0e69ae 15288 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15289 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15290}
15291
15292void bgp_route_finish(void)
15293{
15294 afi_t afi;
15295 safi_t safi;
15296
05c7a1cc
QY
15297 FOREACH_AFI_SAFI (afi, safi) {
15298 bgp_table_unlock(bgp_distance_table[afi][safi]);
15299 bgp_distance_table[afi][safi] = NULL;
15300 }
228da428 15301}