]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_route.c
tools: Add coccinelle script to replace inet_ntop inside JSON
[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"
65efcfce 91
e2a86ad9
DS
92#ifndef VTYSH_EXTRACT_PL
93#include "bgpd/bgp_route_clippy.c"
94#endif
aee875b5 95
7fd28dd2
PR
96DEFINE_HOOK(bgp_snmp_update_stats,
97 (struct bgp_node *rn, struct bgp_path_info *pi, bool added),
8451921b 98 (rn, pi, added));
7fd28dd2 99
b5b99af8
DS
100DEFINE_HOOK(bgp_rpki_prefix_status,
101 (struct peer *peer, struct attr *attr,
102 const struct prefix *prefix),
8451921b 103 (peer, attr, prefix));
b5b99af8 104
2aad8c42
MS
105/* Render dest to prefix_rd based on safi */
106static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
107 safi_t safi);
108
718e3744 109/* Extern from bgp_dump.c */
dde72586
SH
110extern const char *bgp_origin_str[];
111extern const char *bgp_origin_long_str[];
3742de8d 112
b7d08f5a 113/* PMSI strings. */
114#define PMSI_TNLTYPE_STR_NO_INFO "No info"
115#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
116static const struct message bgp_pmsi_tnltype_str[] = {
117 {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO},
118 {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"},
119 {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"},
120 {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"},
121 {PMSI_TNLTYPE_PIM_SM, "PIM-SM"},
122 {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"},
123 {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"},
124 {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"},
88fbc36f 125 {0}
126};
b7d08f5a 127
9df8b37c 128#define VRFID_NONE_STR "-"
46aeabed 129#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
9df8b37c 130
4a11bf2c 131DEFINE_HOOK(bgp_process,
9bcb3eef
DS
132 (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
133 struct peer *peer, bool withdraw),
8451921b 134 (bgp, afi, safi, bn, peer, withdraw));
4a11bf2c 135
4056a5f6
RZ
136/** Test if path is suppressed. */
137static bool bgp_path_suppressed(struct bgp_path_info *pi)
138{
139 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
140 return false;
141
142 return listcount(pi->extra->aggr_suppressors) > 0;
143}
4a11bf2c 144
9bcb3eef 145struct bgp_dest *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
5a1ae2c2 146 safi_t safi, const struct prefix *p,
d62a17ae 147 struct prefix_rd *prd)
148{
9bcb3eef
DS
149 struct bgp_dest *dest;
150 struct bgp_dest *pdest = NULL;
d62a17ae 151
152 assert(table);
d62a17ae 153
154 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
155 || (safi == SAFI_EVPN)) {
9bcb3eef 156 pdest = bgp_node_get(table, (struct prefix *)prd);
d62a17ae 157
9bcb3eef
DS
158 if (!bgp_dest_has_bgp_path_info_data(pdest))
159 bgp_dest_set_bgp_table_info(
160 pdest, bgp_table_init(table->bgp, afi, safi));
d62a17ae 161 else
9bcb3eef
DS
162 bgp_dest_unlock_node(pdest);
163 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 164 }
718e3744 165
9bcb3eef 166 dest = bgp_node_get(table, p);
718e3744 167
d62a17ae 168 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
169 || (safi == SAFI_EVPN))
9bcb3eef 170 dest->pdest = pdest;
718e3744 171
9bcb3eef 172 return dest;
718e3744 173}
6b0655a2 174
9bcb3eef 175struct bgp_dest *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi,
bd494ec5 176 safi_t safi, const struct prefix *p,
d62a17ae 177 struct prefix_rd *prd)
128ea8ab 178{
9bcb3eef
DS
179 struct bgp_dest *dest;
180 struct bgp_dest *pdest = NULL;
128ea8ab 181
d62a17ae 182 if (!table)
183 return NULL;
128ea8ab 184
d62a17ae 185 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
186 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
187 pdest = bgp_node_lookup(table, (struct prefix *)prd);
188 if (!pdest)
d62a17ae 189 return NULL;
128ea8ab 190
9bcb3eef
DS
191 if (!bgp_dest_has_bgp_path_info_data(pdest)) {
192 bgp_dest_unlock_node(pdest);
d62a17ae 193 return NULL;
194 }
128ea8ab 195
9bcb3eef 196 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 197 }
128ea8ab 198
9bcb3eef 199 dest = bgp_node_lookup(table, p);
128ea8ab 200
9bcb3eef 201 return dest;
128ea8ab 202}
203
18ee8310
DS
204/* Allocate bgp_path_info_extra */
205static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
fb982c25 206{
4b7e6066
DS
207 struct bgp_path_info_extra *new;
208 new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
209 sizeof(struct bgp_path_info_extra));
b57ba6d2
MK
210 new->label[0] = MPLS_INVALID_LABEL;
211 new->num_labels = 0;
3e3708cb
PG
212 new->bgp_fs_pbr = NULL;
213 new->bgp_fs_iprule = NULL;
d62a17ae 214 return new;
fb982c25
PJ
215}
216
a2e219fe 217void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
fb982c25 218{
4b7e6066 219 struct bgp_path_info_extra *e;
d62a17ae 220
c93a3b77
DS
221 if (!extra || !*extra)
222 return;
d62a17ae 223
c93a3b77 224 e = *extra;
4538f895 225 if (e->damp_info)
b4f7f45b
IR
226 bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
227 e->damp_info->safi);
4538f895 228
c93a3b77
DS
229 e->damp_info = NULL;
230 if (e->parent) {
40381db7 231 struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
c93a3b77 232
40381db7 233 if (bpi->net) {
0e70e6c8
DL
234 /* FIXME: since multiple e may have the same e->parent
235 * and e->parent->net is holding a refcount for each
236 * of them, we need to do some fudging here.
237 *
40381db7
DS
238 * WARNING: if bpi->net->lock drops to 0, bpi may be
239 * freed as well (because bpi->net was holding the
240 * last reference to bpi) => write after free!
0e70e6c8
DL
241 */
242 unsigned refcount;
243
40381db7 244 bpi = bgp_path_info_lock(bpi);
c10e14e9 245 refcount = bgp_dest_get_lock_count(bpi->net) - 1;
9bcb3eef 246 bgp_dest_unlock_node((struct bgp_dest *)bpi->net);
0e70e6c8 247 if (!refcount)
40381db7
DS
248 bpi->net = NULL;
249 bgp_path_info_unlock(bpi);
0e70e6c8 250 }
18ee8310 251 bgp_path_info_unlock(e->parent);
c93a3b77 252 e->parent = NULL;
d62a17ae 253 }
c93a3b77
DS
254
255 if (e->bgp_orig)
256 bgp_unlock(e->bgp_orig);
c26edcda 257
ff3bf9a4
DS
258 if (e->aggr_suppressors)
259 list_delete(&e->aggr_suppressors);
260
60605cbc
AK
261 if (e->mh_info)
262 bgp_evpn_path_mh_info_free(e->mh_info);
26c03e43 263
ce3c0614
PG
264 if ((*extra)->bgp_fs_iprule)
265 list_delete(&((*extra)->bgp_fs_iprule));
c26edcda 266 if ((*extra)->bgp_fs_pbr)
6a154c88 267 list_delete(&((*extra)->bgp_fs_pbr));
c93a3b77 268 XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
fb982c25
PJ
269}
270
18ee8310
DS
271/* Get bgp_path_info extra information for the given bgp_path_info, lazy
272 * allocated if required.
fb982c25 273 */
40381db7 274struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
fb982c25 275{
40381db7
DS
276 if (!pi->extra)
277 pi->extra = bgp_path_info_extra_new();
278 return pi->extra;
fb982c25
PJ
279}
280
718e3744 281/* Free bgp route information. */
9b6d8fcf 282static void bgp_path_info_free(struct bgp_path_info *path)
718e3744 283{
05864da7 284 bgp_attr_unintern(&path->attr);
fb018d25 285
9b6d8fcf
DS
286 bgp_unlink_nexthop(path);
287 bgp_path_info_extra_free(&path->extra);
288 bgp_path_info_mpath_free(&path->mpath);
62918377
RW
289 if (path->net)
290 bgp_addpath_free_info_data(&path->tx_addpath,
291 &path->net->tx_addpath);
718e3744 292
9b6d8fcf 293 peer_unlock(path->peer); /* bgp_path_info peer reference */
200df115 294
9b6d8fcf 295 XFREE(MTYPE_BGP_ROUTE, path);
718e3744 296}
297
9b6d8fcf 298struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path)
200df115 299{
9b6d8fcf
DS
300 path->lock++;
301 return path;
200df115 302}
303
9b6d8fcf 304struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
200df115 305{
9b6d8fcf
DS
306 assert(path && path->lock > 0);
307 path->lock--;
d62a17ae 308
9b6d8fcf 309 if (path->lock == 0) {
200df115 310#if 0
311 zlog_debug ("%s: unlocked and freeing", __func__);
312 zlog_backtrace (LOG_DEBUG);
313#endif
9b6d8fcf 314 bgp_path_info_free(path);
d62a17ae 315 return NULL;
316 }
200df115 317
318#if 0
9b6d8fcf 319 if (path->lock == 1)
200df115 320 {
321 zlog_debug ("%s: unlocked to 1", __func__);
322 zlog_backtrace (LOG_DEBUG);
323 }
324#endif
d62a17ae 325
9b6d8fcf 326 return path;
200df115 327}
328
f009ff26 329/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
9bcb3eef 330static int bgp_dest_set_defer_flag(struct bgp_dest *dest, bool delete)
f009ff26 331{
332 struct peer *peer;
333 struct bgp_path_info *old_pi, *nextpi;
08c2d52a 334 bool set_flag = false;
f009ff26 335 struct bgp *bgp = NULL;
336 struct bgp_table *table = NULL;
337 afi_t afi = 0;
338 safi_t safi = 0;
f009ff26 339
340 /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
341 * then the route selection is deferred
342 */
9bcb3eef 343 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER) && (!delete))
f009ff26 344 return 0;
345
9bcb3eef 346 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) {
b54892e0 347 if (BGP_DEBUG(update, UPDATE_OUT))
36235319 348 zlog_debug(
56ca3b5b
DL
349 "Route %pBD is in workqueue and being processed, not deferred.",
350 dest);
b54892e0 351
5f9c1aa2 352 return 0;
353 }
354
9bcb3eef 355 table = bgp_dest_table(dest);
f009ff26 356 if (table) {
357 bgp = table->bgp;
358 afi = table->afi;
359 safi = table->safi;
360 }
361
9bcb3eef 362 for (old_pi = bgp_dest_get_bgp_path_info(dest);
f009ff26 363 (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
364 if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
365 continue;
366
367 /* Route selection is deferred if there is a stale path which
368 * which indicates peer is in restart mode
369 */
36235319
QY
370 if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
371 && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 372 set_flag = true;
f009ff26 373 } else {
374 /* If the peer is graceful restart capable and peer is
375 * restarting mode, set the flag BGP_NODE_SELECT_DEFER
376 */
377 peer = old_pi->peer;
36235319
QY
378 if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
379 && BGP_PEER_RESTARTING_MODE(peer)
380 && (old_pi
381 && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
08c2d52a 382 set_flag = true;
f009ff26 383 }
384 }
385 if (set_flag)
386 break;
387 }
388
389 /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
390 * is active
391 */
2ba1fe69 392 if (set_flag && table) {
f009ff26 393 if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
26742171
DS
394 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
395 bgp->gr_info[afi][safi].gr_deferred++;
9bcb3eef 396 SET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 397 if (BGP_DEBUG(update, UPDATE_OUT))
26742171
DS
398 zlog_debug("DEFER route %pBD, dest %p", dest,
399 dest);
f009ff26 400 return 0;
401 }
402 }
403 return -1;
404}
405
9bcb3eef 406void bgp_path_info_add(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 407{
4b7e6066 408 struct bgp_path_info *top;
718e3744 409
9bcb3eef 410 top = bgp_dest_get_bgp_path_info(dest);
d62a17ae 411
6f94b685 412 pi->next = top;
40381db7 413 pi->prev = NULL;
d62a17ae 414 if (top)
40381db7 415 top->prev = pi;
9bcb3eef 416 bgp_dest_set_bgp_path_info(dest, pi);
d62a17ae 417
40381db7 418 bgp_path_info_lock(pi);
9bcb3eef 419 bgp_dest_lock_node(dest);
40381db7 420 peer_lock(pi->peer); /* bgp_path_info peer reference */
9bcb3eef 421 bgp_dest_set_defer_flag(dest, false);
7fd28dd2 422 hook_call(bgp_snmp_update_stats, dest, pi, true);
718e3744 423}
424
d62a17ae 425/* Do the actual removal of info from RIB, for use by bgp_process
b40d939b 426 completion callback *only* */
9bcb3eef 427void bgp_path_info_reap(struct bgp_dest *dest, struct bgp_path_info *pi)
718e3744 428{
40381db7
DS
429 if (pi->next)
430 pi->next->prev = pi->prev;
431 if (pi->prev)
432 pi->prev->next = pi->next;
d62a17ae 433 else
9bcb3eef 434 bgp_dest_set_bgp_path_info(dest, pi->next);
d62a17ae 435
40381db7
DS
436 bgp_path_info_mpath_dequeue(pi);
437 bgp_path_info_unlock(pi);
7fd28dd2 438 hook_call(bgp_snmp_update_stats, dest, pi, false);
9bcb3eef 439 bgp_dest_unlock_node(dest);
718e3744 440}
441
9bcb3eef 442void bgp_path_info_delete(struct bgp_dest *dest, struct bgp_path_info *pi)
b40d939b 443{
9bcb3eef 444 bgp_path_info_set_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 445 /* set of previous already took care of pcount */
40381db7 446 UNSET_FLAG(pi->flags, BGP_PATH_VALID);
b40d939b 447}
448
18ee8310 449/* undo the effects of a previous call to bgp_path_info_delete; typically
8d45210e
AS
450 called when a route is deleted and then quickly re-added before the
451 deletion has been processed */
9bcb3eef 452void bgp_path_info_restore(struct bgp_dest *dest, struct bgp_path_info *pi)
8d45210e 453{
9bcb3eef 454 bgp_path_info_unset_flag(dest, pi, BGP_PATH_REMOVED);
d62a17ae 455 /* unset of previous already took care of pcount */
40381db7 456 SET_FLAG(pi->flags, BGP_PATH_VALID);
8d45210e
AS
457}
458
d62a17ae 459/* Adjust pcount as required */
9bcb3eef 460static void bgp_pcount_adjust(struct bgp_dest *dest, struct bgp_path_info *pi)
1a392d46 461{
d62a17ae 462 struct bgp_table *table;
67174041 463
9bcb3eef 464 assert(dest && bgp_dest_table(dest));
40381db7 465 assert(pi && pi->peer && pi->peer->bgp);
6f58544d 466
9bcb3eef 467 table = bgp_dest_table(dest);
67174041 468
40381db7 469 if (pi->peer == pi->peer->bgp->peer_self)
d62a17ae 470 return;
471
40381db7
DS
472 if (!BGP_PATH_COUNTABLE(pi)
473 && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
d62a17ae 474
40381db7 475 UNSET_FLAG(pi->flags, BGP_PATH_COUNTED);
d62a17ae 476
477 /* slight hack, but more robust against errors. */
40381db7
DS
478 if (pi->peer->pcount[table->afi][table->safi])
479 pi->peer->pcount[table->afi][table->safi]--;
d8d084d9 480 else
450971aa 481 flog_err(EC_LIB_DEVELOPMENT,
d8d084d9 482 "Asked to decrement 0 prefix count for peer");
40381db7
DS
483 } else if (BGP_PATH_COUNTABLE(pi)
484 && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
485 SET_FLAG(pi->flags, BGP_PATH_COUNTED);
486 pi->peer->pcount[table->afi][table->safi]++;
d62a17ae 487 }
1a392d46
PJ
488}
489
40381db7
DS
490static int bgp_label_index_differs(struct bgp_path_info *pi1,
491 struct bgp_path_info *pi2)
28d58fd7 492{
40381db7 493 return (!(pi1->attr->label_index == pi2->attr->label_index));
28d58fd7 494}
1a392d46 495
18ee8310 496/* Set/unset bgp_path_info flags, adjusting any other state as needed.
1a392d46
PJ
497 * This is here primarily to keep prefix-count in check.
498 */
9bcb3eef 499void bgp_path_info_set_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 500 uint32_t flag)
1a392d46 501{
40381db7 502 SET_FLAG(pi->flags, flag);
d62a17ae 503
504 /* early bath if we know it's not a flag that changes countability state
505 */
506 if (!CHECK_FLAG(flag,
1defdda8 507 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 508 return;
509
9bcb3eef 510 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
511}
512
9bcb3eef 513void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
18ee8310 514 uint32_t flag)
1a392d46 515{
40381db7 516 UNSET_FLAG(pi->flags, flag);
d62a17ae 517
518 /* early bath if we know it's not a flag that changes countability state
519 */
520 if (!CHECK_FLAG(flag,
1defdda8 521 BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED))
d62a17ae 522 return;
523
9bcb3eef 524 bgp_pcount_adjust(dest, pi);
1a392d46
PJ
525}
526
718e3744 527/* Get MED value. If MED value is missing and "bgp bestpath
528 missing-as-worst" is specified, treat it as the worst value. */
d7c0a89a 529static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
d62a17ae 530{
531 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
532 return attr->med;
533 else {
892fedb6 534 if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
d62a17ae 535 return BGP_MED_MAX;
536 else
537 return 0;
538 }
718e3744 539}
540
7533cad7
QY
541void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
542 size_t buf_len)
2ec1e66f 543{
40381db7 544 if (pi->addpath_rx_id)
7533cad7
QY
545 snprintf(buf, buf_len, "path %s (addpath rxid %d)",
546 pi->peer->host, pi->addpath_rx_id);
d62a17ae 547 else
7533cad7 548 snprintf(buf, buf_len, "path %s", pi->peer->host);
d62a17ae 549}
9fbdd100 550
d62a17ae 551/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
552 */
18ee8310
DS
553static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
554 struct bgp_path_info *exist, int *paths_eq,
555 struct bgp_maxpaths_cfg *mpath_cfg, int debug,
fdf81fa0
DS
556 char *pfx_buf, afi_t afi, safi_t safi,
557 enum bgp_path_selection_reason *reason)
d62a17ae 558{
5df26422 559 const struct prefix *new_p;
d62a17ae 560 struct attr *newattr, *existattr;
561 bgp_peer_sort_t new_sort;
562 bgp_peer_sort_t exist_sort;
d7c0a89a
QY
563 uint32_t new_pref;
564 uint32_t exist_pref;
565 uint32_t new_med;
566 uint32_t exist_med;
567 uint32_t new_weight;
568 uint32_t exist_weight;
d62a17ae 569 uint32_t newm, existm;
570 struct in_addr new_id;
571 struct in_addr exist_id;
572 int new_cluster;
573 int exist_cluster;
574 int internal_as_route;
575 int confed_as_route;
04d14c8b 576 int ret = 0;
ee88563a
JM
577 int igp_metric_ret = 0;
578 int peer_sort_ret = -1;
d62a17ae 579 char new_buf[PATH_ADDPATH_STR_BUFFER];
580 char exist_buf[PATH_ADDPATH_STR_BUFFER];
d7c0a89a
QY
581 uint32_t new_mm_seq;
582 uint32_t exist_mm_seq;
6d8c603a 583 int nh_cmp;
d071f237
AK
584 esi_t *exist_esi;
585 esi_t *new_esi;
586 bool same_esi;
587 bool old_proxy;
588 bool new_proxy;
33c6e933 589 bool new_origin, exist_origin;
d62a17ae 590
591 *paths_eq = 0;
592
593 /* 0. Null check. */
594 if (new == NULL) {
fdf81fa0 595 *reason = bgp_path_selection_none;
d62a17ae 596 if (debug)
597 zlog_debug("%s: new is NULL", pfx_buf);
598 return 0;
599 }
2ec1e66f 600
d62a17ae 601 if (debug)
7533cad7
QY
602 bgp_path_info_path_with_addpath_rx_str(new, new_buf,
603 sizeof(new_buf));
718e3744 604
d62a17ae 605 if (exist == NULL) {
fdf81fa0 606 *reason = bgp_path_selection_first;
d62a17ae 607 if (debug)
4378495a
DS
608 zlog_debug("%s(%s): %s is the initial bestpath",
609 pfx_buf, bgp->name_pretty, new_buf);
d62a17ae 610 return 1;
611 }
2ec1e66f 612
d62a17ae 613 if (debug) {
7533cad7
QY
614 bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
615 sizeof(exist_buf));
4378495a
DS
616 zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
617 pfx_buf, bgp->name_pretty, new_buf, new->flags,
618 exist_buf, exist->flags);
d62a17ae 619 }
8ff56318 620
d62a17ae 621 newattr = new->attr;
622 existattr = exist->attr;
623
5df26422
NS
624 new_p = bgp_dest_get_prefix(new->net);
625
d62a17ae 626 /* For EVPN routes, we cannot just go by local vs remote, we have to
627 * look at the MAC mobility sequence number, if present.
628 */
5df26422
NS
629 if ((safi == SAFI_EVPN)
630 && (new_p->u.prefix_evpn.route_type == BGP_EVPN_MAC_IP_ROUTE)) {
d62a17ae 631 /* This is an error condition described in RFC 7432 Section
632 * 15.2. The RFC
633 * states that in this scenario "the PE MUST alert the operator"
634 * but it
635 * does not state what other action to take. In order to provide
636 * some
637 * consistency in this scenario we are going to prefer the path
638 * with the
639 * sticky flag.
640 */
641 if (newattr->sticky != existattr->sticky) {
642 if (!debug) {
5df26422
NS
643 prefix2str(new_p, pfx_buf,
644 sizeof(*pfx_buf)
645 * PREFIX2STR_BUFFER);
18ee8310 646 bgp_path_info_path_with_addpath_rx_str(
7533cad7
QY
647 new, new_buf, sizeof(new_buf));
648 bgp_path_info_path_with_addpath_rx_str(
649 exist, exist_buf, sizeof(exist_buf));
d62a17ae 650 }
651
652 if (newattr->sticky && !existattr->sticky) {
fdf81fa0 653 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
654 if (debug)
655 zlog_debug(
656 "%s: %s wins over %s due to sticky MAC flag",
657 pfx_buf, new_buf, exist_buf);
d62a17ae 658 return 1;
659 }
660
661 if (!newattr->sticky && existattr->sticky) {
fdf81fa0 662 *reason = bgp_path_selection_evpn_sticky_mac;
deff24ca
DS
663 if (debug)
664 zlog_debug(
665 "%s: %s loses to %s due to sticky MAC flag",
666 pfx_buf, new_buf, exist_buf);
d62a17ae 667 return 0;
668 }
669 }
128ea8ab 670
d071f237
AK
671 new_esi = bgp_evpn_attr_get_esi(newattr);
672 exist_esi = bgp_evpn_attr_get_esi(existattr);
673 if (bgp_evpn_is_esi_valid(new_esi) &&
674 !memcmp(new_esi, exist_esi, sizeof(esi_t))) {
675 same_esi = true;
676 } else {
677 same_esi = false;
678 }
679
680 /* If both paths have the same non-zero ES and
681 * one path is local it wins.
682 * PS: Note the local path wins even if the remote
683 * has the higher MM seq. The local path's
684 * MM seq will be fixed up to match the highest
685 * rem seq, subsequently.
686 */
687 if (same_esi) {
688 char esi_buf[ESI_STR_LEN];
689
690 if (bgp_evpn_is_path_local(bgp, new)) {
691 *reason = bgp_path_selection_evpn_local_path;
692 if (debug)
693 zlog_debug(
694 "%s: %s wins over %s as ES %s is same and local",
695 pfx_buf, new_buf, exist_buf,
696 esi_to_str(new_esi, esi_buf,
697 sizeof(esi_buf)));
698 return 1;
699 }
700 if (bgp_evpn_is_path_local(bgp, exist)) {
701 *reason = bgp_path_selection_evpn_local_path;
702 if (debug)
703 zlog_debug(
704 "%s: %s loses to %s as ES %s is same and local",
705 pfx_buf, new_buf, exist_buf,
706 esi_to_str(new_esi, esi_buf,
707 sizeof(esi_buf)));
708 return 0;
709 }
710 }
711
d62a17ae 712 new_mm_seq = mac_mobility_seqnum(newattr);
713 exist_mm_seq = mac_mobility_seqnum(existattr);
8ff56318 714
d62a17ae 715 if (new_mm_seq > exist_mm_seq) {
fdf81fa0 716 *reason = bgp_path_selection_evpn_seq;
d62a17ae 717 if (debug)
718 zlog_debug(
719 "%s: %s wins over %s due to MM seq %u > %u",
720 pfx_buf, new_buf, exist_buf, new_mm_seq,
721 exist_mm_seq);
722 return 1;
723 }
8ff56318 724
d62a17ae 725 if (new_mm_seq < exist_mm_seq) {
fdf81fa0 726 *reason = bgp_path_selection_evpn_seq;
d62a17ae 727 if (debug)
728 zlog_debug(
729 "%s: %s loses to %s due to MM seq %u < %u",
730 pfx_buf, new_buf, exist_buf, new_mm_seq,
731 exist_mm_seq);
732 return 0;
733 }
6d8c603a 734
d071f237
AK
735 /* if the sequence numbers and ESI are the same and one path
736 * is non-proxy it wins (over proxy)
737 */
738 new_proxy = bgp_evpn_attr_is_proxy(newattr);
739 old_proxy = bgp_evpn_attr_is_proxy(existattr);
740 if (same_esi && bgp_evpn_attr_is_local_es(newattr) &&
741 old_proxy != new_proxy) {
742 if (!new_proxy) {
743 *reason = bgp_path_selection_evpn_non_proxy;
744 if (debug)
745 zlog_debug(
746 "%s: %s wins over %s, same seq/es and non-proxy",
747 pfx_buf, new_buf, exist_buf);
748 return 1;
749 }
750
751 *reason = bgp_path_selection_evpn_non_proxy;
752 if (debug)
753 zlog_debug(
754 "%s: %s loses to %s, same seq/es and non-proxy",
755 pfx_buf, new_buf, exist_buf);
756 return 0;
757 }
758
6d8c603a
AK
759 /*
760 * if sequence numbers are the same path with the lowest IP
761 * wins
762 */
763 nh_cmp = bgp_path_info_nexthop_cmp(new, exist);
764 if (nh_cmp < 0) {
fdf81fa0 765 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
766 if (debug)
767 zlog_debug(
23d0a753 768 "%s: %s wins over %s due to same MM seq %u and lower IP %pI4",
6d8c603a 769 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 770 &new->attr->nexthop);
6d8c603a
AK
771 return 1;
772 }
773 if (nh_cmp > 0) {
fdf81fa0 774 *reason = bgp_path_selection_evpn_lower_ip;
6d8c603a
AK
775 if (debug)
776 zlog_debug(
23d0a753 777 "%s: %s loses to %s due to same MM seq %u and higher IP %pI4",
6d8c603a 778 pfx_buf, new_buf, exist_buf, new_mm_seq,
23d0a753 779 &new->attr->nexthop);
6d8c603a
AK
780 return 0;
781 }
d62a17ae 782 }
9fbdd100 783
d62a17ae 784 /* 1. Weight check. */
d62a17ae 785 new_weight = newattr->weight;
786 exist_weight = existattr->weight;
8ff56318 787
d62a17ae 788 if (new_weight > exist_weight) {
fdf81fa0 789 *reason = bgp_path_selection_weight;
d62a17ae 790 if (debug)
791 zlog_debug("%s: %s wins over %s due to weight %d > %d",
792 pfx_buf, new_buf, exist_buf, new_weight,
793 exist_weight);
794 return 1;
795 }
718e3744 796
d62a17ae 797 if (new_weight < exist_weight) {
fdf81fa0 798 *reason = bgp_path_selection_weight;
d62a17ae 799 if (debug)
800 zlog_debug("%s: %s loses to %s due to weight %d < %d",
801 pfx_buf, new_buf, exist_buf, new_weight,
802 exist_weight);
803 return 0;
804 }
9fbdd100 805
d62a17ae 806 /* 2. Local preference check. */
807 new_pref = exist_pref = bgp->default_local_pref;
808
809 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
810 new_pref = newattr->local_pref;
811 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
812 exist_pref = existattr->local_pref;
813
814 if (new_pref > exist_pref) {
fdf81fa0 815 *reason = bgp_path_selection_local_pref;
d62a17ae 816 if (debug)
817 zlog_debug(
818 "%s: %s wins over %s due to localpref %d > %d",
819 pfx_buf, new_buf, exist_buf, new_pref,
820 exist_pref);
821 return 1;
822 }
718e3744 823
d62a17ae 824 if (new_pref < exist_pref) {
fdf81fa0 825 *reason = bgp_path_selection_local_pref;
d62a17ae 826 if (debug)
827 zlog_debug(
828 "%s: %s loses to %s due to localpref %d < %d",
829 pfx_buf, new_buf, exist_buf, new_pref,
830 exist_pref);
831 return 0;
832 }
9fbdd100 833
d62a17ae 834 /* 3. Local route check. We prefer:
835 * - BGP_ROUTE_STATIC
836 * - BGP_ROUTE_AGGREGATE
837 * - BGP_ROUTE_REDISTRIBUTE
838 */
33c6e933
DS
839 new_origin = !(new->sub_type == BGP_ROUTE_NORMAL ||
840 new->sub_type == BGP_ROUTE_IMPORTED);
841 exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL ||
842 exist->sub_type == BGP_ROUTE_IMPORTED);
843
844 if (new_origin && !exist_origin) {
fdf81fa0 845 *reason = bgp_path_selection_local_route;
d62a17ae 846 if (debug)
847 zlog_debug(
848 "%s: %s wins over %s due to preferred BGP_ROUTE type",
849 pfx_buf, new_buf, exist_buf);
850 return 1;
851 }
718e3744 852
33c6e933 853 if (!new_origin && exist_origin) {
fdf81fa0 854 *reason = bgp_path_selection_local_route;
d62a17ae 855 if (debug)
856 zlog_debug(
857 "%s: %s loses to %s due to preferred BGP_ROUTE type",
858 pfx_buf, new_buf, exist_buf);
859 return 0;
6811845b 860 }
718e3744 861
d62a17ae 862 /* 4. AS path length check. */
892fedb6 863 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
d62a17ae 864 int exist_hops = aspath_count_hops(existattr->aspath);
865 int exist_confeds = aspath_count_confeds(existattr->aspath);
866
892fedb6 867 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
d62a17ae 868 int aspath_hops;
869
870 aspath_hops = aspath_count_hops(newattr->aspath);
871 aspath_hops += aspath_count_confeds(newattr->aspath);
872
873 if (aspath_hops < (exist_hops + exist_confeds)) {
fdf81fa0 874 *reason = bgp_path_selection_confed_as_path;
d62a17ae 875 if (debug)
876 zlog_debug(
877 "%s: %s wins over %s due to aspath (with confeds) hopcount %d < %d",
878 pfx_buf, new_buf, exist_buf,
879 aspath_hops,
880 (exist_hops + exist_confeds));
881 return 1;
882 }
883
884 if (aspath_hops > (exist_hops + exist_confeds)) {
fdf81fa0 885 *reason = bgp_path_selection_confed_as_path;
d62a17ae 886 if (debug)
887 zlog_debug(
888 "%s: %s loses to %s due to aspath (with confeds) hopcount %d > %d",
889 pfx_buf, new_buf, exist_buf,
890 aspath_hops,
891 (exist_hops + exist_confeds));
892 return 0;
893 }
894 } else {
895 int newhops = aspath_count_hops(newattr->aspath);
896
897 if (newhops < exist_hops) {
fdf81fa0 898 *reason = bgp_path_selection_as_path;
d62a17ae 899 if (debug)
900 zlog_debug(
901 "%s: %s wins over %s due to aspath hopcount %d < %d",
902 pfx_buf, new_buf, exist_buf,
903 newhops, exist_hops);
904 return 1;
905 }
906
907 if (newhops > exist_hops) {
fdf81fa0 908 *reason = bgp_path_selection_as_path;
d62a17ae 909 if (debug)
910 zlog_debug(
911 "%s: %s loses to %s due to aspath hopcount %d > %d",
912 pfx_buf, new_buf, exist_buf,
913 newhops, exist_hops);
914 return 0;
915 }
916 }
917 }
9fbdd100 918
d62a17ae 919 /* 5. Origin check. */
920 if (newattr->origin < existattr->origin) {
fdf81fa0 921 *reason = bgp_path_selection_origin;
d62a17ae 922 if (debug)
923 zlog_debug("%s: %s wins over %s due to ORIGIN %s < %s",
924 pfx_buf, new_buf, exist_buf,
925 bgp_origin_long_str[newattr->origin],
926 bgp_origin_long_str[existattr->origin]);
927 return 1;
928 }
718e3744 929
d62a17ae 930 if (newattr->origin > existattr->origin) {
fdf81fa0 931 *reason = bgp_path_selection_origin;
d62a17ae 932 if (debug)
933 zlog_debug("%s: %s loses to %s due to ORIGIN %s > %s",
934 pfx_buf, new_buf, exist_buf,
935 bgp_origin_long_str[newattr->origin],
936 bgp_origin_long_str[existattr->origin]);
937 return 0;
938 }
718e3744 939
d62a17ae 940 /* 6. MED check. */
941 internal_as_route = (aspath_count_hops(newattr->aspath) == 0
942 && aspath_count_hops(existattr->aspath) == 0);
943 confed_as_route = (aspath_count_confeds(newattr->aspath) > 0
944 && aspath_count_confeds(existattr->aspath) > 0
945 && aspath_count_hops(newattr->aspath) == 0
946 && aspath_count_hops(existattr->aspath) == 0);
947
892fedb6
DA
948 if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
949 || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
d62a17ae 950 || aspath_cmp_left(newattr->aspath, existattr->aspath)
951 || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
952 || internal_as_route) {
953 new_med = bgp_med_value(new->attr, bgp);
954 exist_med = bgp_med_value(exist->attr, bgp);
955
956 if (new_med < exist_med) {
fdf81fa0 957 *reason = bgp_path_selection_med;
d62a17ae 958 if (debug)
959 zlog_debug(
960 "%s: %s wins over %s due to MED %d < %d",
961 pfx_buf, new_buf, exist_buf, new_med,
962 exist_med);
963 return 1;
964 }
8ff56318 965
d62a17ae 966 if (new_med > exist_med) {
fdf81fa0 967 *reason = bgp_path_selection_med;
d62a17ae 968 if (debug)
969 zlog_debug(
970 "%s: %s loses to %s due to MED %d > %d",
971 pfx_buf, new_buf, exist_buf, new_med,
972 exist_med);
973 return 0;
974 }
975 }
9fbdd100 976
d62a17ae 977 /* 7. Peer type check. */
978 new_sort = new->peer->sort;
979 exist_sort = exist->peer->sort;
980
981 if (new_sort == BGP_PEER_EBGP
982 && (exist_sort == BGP_PEER_IBGP || exist_sort == BGP_PEER_CONFED)) {
fdf81fa0 983 *reason = bgp_path_selection_peer;
d62a17ae 984 if (debug)
985 zlog_debug(
986 "%s: %s wins over %s due to eBGP peer > iBGP peer",
987 pfx_buf, new_buf, exist_buf);
ee88563a
JM
988 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
989 return 1;
990 peer_sort_ret = 1;
d62a17ae 991 }
718e3744 992
d62a17ae 993 if (exist_sort == BGP_PEER_EBGP
994 && (new_sort == BGP_PEER_IBGP || new_sort == BGP_PEER_CONFED)) {
fdf81fa0 995 *reason = bgp_path_selection_peer;
d62a17ae 996 if (debug)
997 zlog_debug(
998 "%s: %s loses to %s due to iBGP peer < eBGP peer",
999 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1000 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1001 return 0;
1002 peer_sort_ret = 0;
d62a17ae 1003 }
8ff56318 1004
d62a17ae 1005 /* 8. IGP metric check. */
1006 newm = existm = 0;
8ff56318 1007
d62a17ae 1008 if (new->extra)
1009 newm = new->extra->igpmetric;
1010 if (exist->extra)
1011 existm = exist->extra->igpmetric;
9fbdd100 1012
d62a17ae 1013 if (newm < existm) {
ee88563a 1014 if (debug && peer_sort_ret < 0)
d62a17ae 1015 zlog_debug(
d588b995 1016 "%s: %s wins over %s due to IGP metric %u < %u",
d62a17ae 1017 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1018 igp_metric_ret = 1;
d62a17ae 1019 }
718e3744 1020
d62a17ae 1021 if (newm > existm) {
ee88563a 1022 if (debug && peer_sort_ret < 0)
d62a17ae 1023 zlog_debug(
d588b995 1024 "%s: %s loses to %s due to IGP metric %u > %u",
d62a17ae 1025 pfx_buf, new_buf, exist_buf, newm, existm);
ee88563a 1026 igp_metric_ret = 0;
5e242b0d 1027 }
5e242b0d 1028
d62a17ae 1029 /* 9. Same IGP metric. Compare the cluster list length as
1030 representative of IGP hops metric. Rewrite the metric value
1031 pair (newm, existm) with the cluster list length. Prefer the
1032 path with smaller cluster list length. */
1033 if (newm == existm) {
bf0d28dc
DS
1034 if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
1035 && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
d62a17ae 1036 && (mpath_cfg == NULL
1037 || CHECK_FLAG(
1038 mpath_cfg->ibgp_flags,
1039 BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN))) {
1040 newm = BGP_CLUSTER_LIST_LENGTH(new->attr);
1041 existm = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1042
1043 if (newm < existm) {
ee88563a 1044 if (debug && peer_sort_ret < 0)
d62a17ae 1045 zlog_debug(
d588b995 1046 "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
d62a17ae 1047 pfx_buf, new_buf, exist_buf,
1048 newm, existm);
ee88563a 1049 igp_metric_ret = 1;
d62a17ae 1050 }
1051
1052 if (newm > existm) {
ee88563a 1053 if (debug && peer_sort_ret < 0)
d62a17ae 1054 zlog_debug(
d588b995 1055 "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
d62a17ae 1056 pfx_buf, new_buf, exist_buf,
1057 newm, existm);
ee88563a 1058 igp_metric_ret = 0;
d62a17ae 1059 }
1060 }
1061 }
31a4638f 1062
d62a17ae 1063 /* 10. confed-external vs. confed-internal */
1064 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
1065 if (new_sort == BGP_PEER_CONFED
1066 && exist_sort == BGP_PEER_IBGP) {
fdf81fa0 1067 *reason = bgp_path_selection_confed;
d62a17ae 1068 if (debug)
1069 zlog_debug(
1070 "%s: %s wins over %s due to confed-external peer > confed-internal peer",
1071 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1072 if (!CHECK_FLAG(bgp->flags,
1073 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1074 return 1;
1075 peer_sort_ret = 1;
d62a17ae 1076 }
718e3744 1077
d62a17ae 1078 if (exist_sort == BGP_PEER_CONFED
1079 && new_sort == BGP_PEER_IBGP) {
fdf81fa0 1080 *reason = bgp_path_selection_confed;
d62a17ae 1081 if (debug)
1082 zlog_debug(
1083 "%s: %s loses to %s due to confed-internal peer < confed-external peer",
1084 pfx_buf, new_buf, exist_buf);
ee88563a
JM
1085 if (!CHECK_FLAG(bgp->flags,
1086 BGP_FLAG_PEERTYPE_MULTIPATH_RELAX))
1087 return 0;
1088 peer_sort_ret = 0;
d62a17ae 1089 }
1090 }
718e3744 1091
d62a17ae 1092 /* 11. Maximum path check. */
1093 if (newm == existm) {
1094 /* If one path has a label but the other does not, do not treat
1095 * them as equals for multipath
1096 */
a4d82a8a 1097 if ((new->extra &&bgp_is_valid_label(&new->extra->label[0]))
d62a17ae 1098 != (exist->extra
b57ba6d2 1099 && bgp_is_valid_label(&exist->extra->label[0]))) {
d62a17ae 1100 if (debug)
1101 zlog_debug(
1102 "%s: %s and %s cannot be multipath, one has a label while the other does not",
1103 pfx_buf, new_buf, exist_buf);
892fedb6
DA
1104 } else if (CHECK_FLAG(bgp->flags,
1105 BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
d62a17ae 1106
1107 /*
1108 * For the two paths, all comparison steps till IGP
1109 * metric
1110 * have succeeded - including AS_PATH hop count. Since
1111 * 'bgp
1112 * bestpath as-path multipath-relax' knob is on, we
1113 * don't need
1114 * an exact match of AS_PATH. Thus, mark the paths are
1115 * equal.
1116 * That will trigger both these paths to get into the
1117 * multipath
1118 * array.
1119 */
1120 *paths_eq = 1;
1121
1122 if (debug)
1123 zlog_debug(
1124 "%s: %s and %s are equal via multipath-relax",
1125 pfx_buf, new_buf, exist_buf);
1126 } else if (new->peer->sort == BGP_PEER_IBGP) {
1127 if (aspath_cmp(new->attr->aspath,
1128 exist->attr->aspath)) {
1129 *paths_eq = 1;
1130
1131 if (debug)
1132 zlog_debug(
1133 "%s: %s and %s are equal via matching aspaths",
1134 pfx_buf, new_buf, exist_buf);
1135 }
1136 } else if (new->peer->as == exist->peer->as) {
1137 *paths_eq = 1;
1138
1139 if (debug)
1140 zlog_debug(
1141 "%s: %s and %s are equal via same remote-as",
1142 pfx_buf, new_buf, exist_buf);
1143 }
1144 } else {
1145 /*
1146 * TODO: If unequal cost ibgp multipath is enabled we can
1147 * mark the paths as equal here instead of returning
1148 */
ee88563a
JM
1149
1150 /* Prior to the addition of BGP_FLAG_PEERTYPE_MULTIPATH_RELAX,
1151 * if either step 7 or 10 (peer type checks) yielded a winner,
1152 * that result was returned immediately. Returning from step 10
1153 * ignored the return value computed in steps 8 and 9 (IGP
1154 * metric checks). In order to preserve that behavior, if
1155 * peer_sort_ret is set, return that rather than igp_metric_ret.
1156 */
1157 ret = peer_sort_ret;
1158 if (peer_sort_ret < 0) {
1159 ret = igp_metric_ret;
1160 if (debug) {
1161 if (ret == 1)
1162 zlog_debug(
1163 "%s: %s wins over %s after IGP metric comparison",
1164 pfx_buf, new_buf, exist_buf);
1165 else
1166 zlog_debug(
1167 "%s: %s loses to %s after IGP metric comparison",
1168 pfx_buf, new_buf, exist_buf);
1169 }
1170 *reason = bgp_path_selection_igp_metric;
d62a17ae 1171 }
1172 return ret;
1173 }
718e3744 1174
ee88563a
JM
1175 /*
1176 * At this point, the decision whether to set *paths_eq = 1 has been
1177 * completed. If we deferred returning because of bestpath peer-type
1178 * relax configuration, return now.
1179 */
1180 if (peer_sort_ret >= 0)
1181 return peer_sort_ret;
1182
d62a17ae 1183 /* 12. If both paths are external, prefer the path that was received
1184 first (the oldest one). This step minimizes route-flap, since a
1185 newer path won't displace an older one, even if it was the
1186 preferred route based on the additional decision criteria below. */
892fedb6 1187 if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
d62a17ae 1188 && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
1defdda8 1189 if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1190 *reason = bgp_path_selection_older;
d62a17ae 1191 if (debug)
1192 zlog_debug(
1193 "%s: %s wins over %s due to oldest external",
1194 pfx_buf, new_buf, exist_buf);
1195 return 1;
1196 }
9fbdd100 1197
1defdda8 1198 if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) {
fdf81fa0 1199 *reason = bgp_path_selection_older;
d62a17ae 1200 if (debug)
1201 zlog_debug(
1202 "%s: %s loses to %s due to oldest external",
1203 pfx_buf, new_buf, exist_buf);
1204 return 0;
1205 }
1206 }
718e3744 1207
d62a17ae 1208 /* 13. Router-ID comparision. */
1209 /* If one of the paths is "stale", the corresponding peer router-id will
1210 * be 0 and would always win over the other path. If originator id is
1211 * used for the comparision, it will decide which path is better.
1212 */
1213 if (newattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1214 new_id.s_addr = newattr->originator_id.s_addr;
1215 else
1216 new_id.s_addr = new->peer->remote_id.s_addr;
1217 if (existattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
1218 exist_id.s_addr = existattr->originator_id.s_addr;
1219 else
1220 exist_id.s_addr = exist->peer->remote_id.s_addr;
1221
1222 if (ntohl(new_id.s_addr) < ntohl(exist_id.s_addr)) {
fdf81fa0 1223 *reason = bgp_path_selection_router_id;
d62a17ae 1224 if (debug)
1225 zlog_debug(
1226 "%s: %s wins over %s due to Router-ID comparison",
1227 pfx_buf, new_buf, exist_buf);
1228 return 1;
1229 }
718e3744 1230
d62a17ae 1231 if (ntohl(new_id.s_addr) > ntohl(exist_id.s_addr)) {
fdf81fa0 1232 *reason = bgp_path_selection_router_id;
d62a17ae 1233 if (debug)
1234 zlog_debug(
1235 "%s: %s loses to %s due to Router-ID comparison",
1236 pfx_buf, new_buf, exist_buf);
1237 return 0;
1238 }
9fbdd100 1239
d62a17ae 1240 /* 14. Cluster length comparision. */
1241 new_cluster = BGP_CLUSTER_LIST_LENGTH(new->attr);
1242 exist_cluster = BGP_CLUSTER_LIST_LENGTH(exist->attr);
1243
1244 if (new_cluster < exist_cluster) {
fdf81fa0 1245 *reason = bgp_path_selection_cluster_length;
d62a17ae 1246 if (debug)
1247 zlog_debug(
1248 "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
1249 pfx_buf, new_buf, exist_buf, new_cluster,
1250 exist_cluster);
1251 return 1;
1252 }
718e3744 1253
d62a17ae 1254 if (new_cluster > exist_cluster) {
fdf81fa0 1255 *reason = bgp_path_selection_cluster_length;
d62a17ae 1256 if (debug)
1257 zlog_debug(
1258 "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
1259 pfx_buf, new_buf, exist_buf, new_cluster,
1260 exist_cluster);
1261 return 0;
1262 }
9fbdd100 1263
d62a17ae 1264 /* 15. Neighbor address comparision. */
1265 /* Do this only if neither path is "stale" as stale paths do not have
1266 * valid peer information (as the connection may or may not be up).
1267 */
1defdda8 1268 if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) {
fdf81fa0 1269 *reason = bgp_path_selection_stale;
d62a17ae 1270 if (debug)
1271 zlog_debug(
1272 "%s: %s wins over %s due to latter path being STALE",
1273 pfx_buf, new_buf, exist_buf);
1274 return 1;
1275 }
0de5153c 1276
1defdda8 1277 if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) {
fdf81fa0 1278 *reason = bgp_path_selection_stale;
d62a17ae 1279 if (debug)
1280 zlog_debug(
1281 "%s: %s loses to %s due to former path being STALE",
1282 pfx_buf, new_buf, exist_buf);
1283 return 0;
1284 }
718e3744 1285
d62a17ae 1286 /* locally configured routes to advertise do not have su_remote */
fdf81fa0
DS
1287 if (new->peer->su_remote == NULL) {
1288 *reason = bgp_path_selection_local_configured;
d62a17ae 1289 return 0;
fdf81fa0
DS
1290 }
1291 if (exist->peer->su_remote == NULL) {
1292 *reason = bgp_path_selection_local_configured;
d62a17ae 1293 return 1;
fdf81fa0 1294 }
9fbdd100 1295
d62a17ae 1296 ret = sockunion_cmp(new->peer->su_remote, exist->peer->su_remote);
1297
1298 if (ret == 1) {
fdf81fa0 1299 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1300 if (debug)
1301 zlog_debug(
1302 "%s: %s loses to %s due to Neighor IP comparison",
1303 pfx_buf, new_buf, exist_buf);
1304 return 0;
1305 }
1306
1307 if (ret == -1) {
fdf81fa0 1308 *reason = bgp_path_selection_neighbor_ip;
d62a17ae 1309 if (debug)
1310 zlog_debug(
1311 "%s: %s wins over %s due to Neighor IP comparison",
1312 pfx_buf, new_buf, exist_buf);
1313 return 1;
1314 }
9fbdd100 1315
fdf81fa0 1316 *reason = bgp_path_selection_default;
d62a17ae 1317 if (debug)
1318 zlog_debug("%s: %s wins over %s due to nothing left to compare",
1319 pfx_buf, new_buf, exist_buf);
718e3744 1320
d62a17ae 1321 return 1;
718e3744 1322}
1323
d071f237
AK
1324
1325int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
1326 struct bgp_path_info *exist, int *paths_eq)
1327{
1328 enum bgp_path_selection_reason reason;
1329 char pfx_buf[PREFIX2STR_BUFFER];
1330
1331 return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf,
1332 AFI_L2VPN, SAFI_EVPN, &reason);
1333}
1334
65efcfce
LB
1335/* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist
1336 * is preferred, or 0 if they are the same (usually will only occur if
d62a17ae 1337 * multipath is enabled
65efcfce 1338 * This version is compatible with */
18ee8310
DS
1339int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new,
1340 struct bgp_path_info *exist, char *pfx_buf,
fdf81fa0
DS
1341 afi_t afi, safi_t safi,
1342 enum bgp_path_selection_reason *reason)
d62a17ae 1343{
1344 int paths_eq;
1345 int ret;
18ee8310 1346 ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf,
fdf81fa0 1347 afi, safi, reason);
d62a17ae 1348
1349 if (paths_eq)
1350 ret = 0;
1351 else {
1352 if (ret == 1)
1353 ret = -1;
1354 else
1355 ret = 1;
1356 }
1357 return ret;
65efcfce
LB
1358}
1359
5a1ae2c2
DS
1360static enum filter_type bgp_input_filter(struct peer *peer,
1361 const struct prefix *p,
d62a17ae 1362 struct attr *attr, afi_t afi,
1363 safi_t safi)
718e3744 1364{
d62a17ae 1365 struct bgp_filter *filter;
6401252f 1366 enum filter_type ret = FILTER_PERMIT;
718e3744 1367
d62a17ae 1368 filter = &peer->filter[afi][safi];
718e3744 1369
d62a17ae 1370#define FILTER_EXIST_WARN(F, f, filter) \
1371 if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \
d8d084d9
DS
1372 zlog_debug("%s: Could not find configured input %s-list %s!", \
1373 peer->host, #f, F##_IN_NAME(filter));
d62a17ae 1374
1375 if (DISTRIBUTE_IN_NAME(filter)) {
1376 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
1377
6401252f
QY
1378 if (access_list_apply(DISTRIBUTE_IN(filter), p)
1379 == FILTER_DENY) {
1380 ret = FILTER_DENY;
1381 goto done;
1382 }
d62a17ae 1383 }
1384
1385 if (PREFIX_LIST_IN_NAME(filter)) {
1386 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
1387
6401252f
QY
1388 if (prefix_list_apply(PREFIX_LIST_IN(filter), p)
1389 == PREFIX_DENY) {
1390 ret = FILTER_DENY;
1391 goto done;
1392 }
d62a17ae 1393 }
1394
1395 if (FILTER_LIST_IN_NAME(filter)) {
1396 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
1397
1398 if (as_list_apply(FILTER_LIST_IN(filter), attr->aspath)
6401252f
QY
1399 == AS_FILTER_DENY) {
1400 ret = FILTER_DENY;
1401 goto done;
1402 }
d62a17ae 1403 }
1404
6401252f 1405done:
c7bb4f00 1406 if (frrtrace_enabled(frr_bgp, input_filter)) {
6401252f
QY
1407 char pfxprint[PREFIX2STR_BUFFER];
1408
1409 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1410 frrtrace(5, frr_bgp, input_filter, peer, pfxprint, afi, safi,
1411 ret == FILTER_PERMIT ? "permit" : "deny");
6401252f
QY
1412 }
1413
1414 return ret;
650f76c2 1415#undef FILTER_EXIST_WARN
718e3744 1416}
1417
b8685f9b
DS
1418static enum filter_type bgp_output_filter(struct peer *peer,
1419 const struct prefix *p,
d62a17ae 1420 struct attr *attr, afi_t afi,
1421 safi_t safi)
718e3744 1422{
d62a17ae 1423 struct bgp_filter *filter;
6401252f 1424 enum filter_type ret = FILTER_PERMIT;
d62a17ae 1425
1426 filter = &peer->filter[afi][safi];
1427
1428#define FILTER_EXIST_WARN(F, f, filter) \
1429 if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \
d8d084d9
DS
1430 zlog_debug("%s: Could not find configured output %s-list %s!", \
1431 peer->host, #f, F##_OUT_NAME(filter));
718e3744 1432
d62a17ae 1433 if (DISTRIBUTE_OUT_NAME(filter)) {
1434 FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter);
718e3744 1435
6401252f
QY
1436 if (access_list_apply(DISTRIBUTE_OUT(filter), p)
1437 == FILTER_DENY) {
1438 ret = FILTER_DENY;
1439 goto done;
1440 }
d62a17ae 1441 }
1442
1443 if (PREFIX_LIST_OUT_NAME(filter)) {
1444 FILTER_EXIST_WARN(PREFIX_LIST, prefix, filter);
650f76c2 1445
d62a17ae 1446 if (prefix_list_apply(PREFIX_LIST_OUT(filter), p)
6401252f
QY
1447 == PREFIX_DENY) {
1448 ret = FILTER_DENY;
1449 goto done;
1450 }
d62a17ae 1451 }
718e3744 1452
d62a17ae 1453 if (FILTER_LIST_OUT_NAME(filter)) {
1454 FILTER_EXIST_WARN(FILTER_LIST, as, filter);
718e3744 1455
d62a17ae 1456 if (as_list_apply(FILTER_LIST_OUT(filter), attr->aspath)
6401252f
QY
1457 == AS_FILTER_DENY) {
1458 ret = FILTER_DENY;
1459 goto done;
1460 }
1461 }
1462
c7bb4f00 1463 if (frrtrace_enabled(frr_bgp, output_filter)) {
6401252f
QY
1464 char pfxprint[PREFIX2STR_BUFFER];
1465
1466 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
1467 frrtrace(5, frr_bgp, output_filter, peer, pfxprint, afi, safi,
1468 ret == FILTER_PERMIT ? "permit" : "deny");
d62a17ae 1469 }
718e3744 1470
6401252f
QY
1471done:
1472 return ret;
650f76c2 1473#undef FILTER_EXIST_WARN
718e3744 1474}
1475
1476/* If community attribute includes no_export then return 1. */
3dc339cd 1477static bool bgp_community_filter(struct peer *peer, struct attr *attr)
d62a17ae 1478{
1479 if (attr->community) {
1480 /* NO_ADVERTISE check. */
1481 if (community_include(attr->community, COMMUNITY_NO_ADVERTISE))
3dc339cd 1482 return true;
d62a17ae 1483
1484 /* NO_EXPORT check. */
1485 if (peer->sort == BGP_PEER_EBGP
1486 && community_include(attr->community, COMMUNITY_NO_EXPORT))
3dc339cd 1487 return true;
d62a17ae 1488
1489 /* NO_EXPORT_SUBCONFED check. */
1490 if (peer->sort == BGP_PEER_EBGP
1491 || peer->sort == BGP_PEER_CONFED)
1492 if (community_include(attr->community,
1493 COMMUNITY_NO_EXPORT_SUBCONFED))
3dc339cd 1494 return true;
d62a17ae 1495 }
3dc339cd 1496 return false;
718e3744 1497}
1498
1499/* Route reflection loop check. */
3dc339cd 1500static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
718e3744 1501{
d62a17ae 1502 struct in_addr cluster_id;
779fee93 1503 struct cluster_list *cluster = bgp_attr_get_cluster(attr);
718e3744 1504
779fee93 1505 if (cluster) {
d62a17ae 1506 if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
1507 cluster_id = peer->bgp->cluster_id;
1508 else
1509 cluster_id = peer->bgp->router_id;
1510
779fee93 1511 if (cluster_loop_check(cluster, cluster_id))
3dc339cd 1512 return true;
d62a17ae 1513 }
3dc339cd 1514 return false;
718e3744 1515}
6b0655a2 1516
5a1ae2c2 1517static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1518 struct attr *attr, afi_t afi, safi_t safi,
82b692c0 1519 const char *rmap_name, mpls_label_t *label,
9bcb3eef 1520 uint32_t num_labels, struct bgp_dest *dest)
718e3744 1521{
d62a17ae 1522 struct bgp_filter *filter;
82b692c0
LK
1523 struct bgp_path_info rmap_path = { 0 };
1524 struct bgp_path_info_extra extra = { 0 };
d62a17ae 1525 route_map_result_t ret;
1526 struct route_map *rmap = NULL;
718e3744 1527
d62a17ae 1528 filter = &peer->filter[afi][safi];
718e3744 1529
d62a17ae 1530 /* Apply default weight value. */
1531 if (peer->weight[afi][safi])
1532 attr->weight = peer->weight[afi][safi];
718e3744 1533
d62a17ae 1534 if (rmap_name) {
1535 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1536
d62a17ae 1537 if (rmap == NULL)
1538 return RMAP_DENY;
1539 } else {
1540 if (ROUTE_MAP_IN_NAME(filter)) {
1541 rmap = ROUTE_MAP_IN(filter);
98a4a44e 1542
d62a17ae 1543 if (rmap == NULL)
1544 return RMAP_DENY;
1545 }
1546 }
0b16f239 1547
d62a17ae 1548 /* Route map apply. */
1549 if (rmap) {
40381db7 1550 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1551 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1552 rmap_path.peer = peer;
1553 rmap_path.attr = attr;
82b692c0 1554 rmap_path.extra = &extra;
9bcb3eef 1555 rmap_path.net = dest;
196c6b09 1556
82b692c0
LK
1557 extra.num_labels = num_labels;
1558 if (label && num_labels && num_labels <= BGP_MAX_LABELS)
1559 memcpy(extra.label, label,
1560 num_labels * sizeof(mpls_label_t));
718e3744 1561
d62a17ae 1562 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
ac41b2a2 1563
d62a17ae 1564 /* Apply BGP route map to the attribute. */
1782514f 1565 ret = route_map_apply(rmap, p, &rmap_path);
0b16f239 1566
d62a17ae 1567 peer->rmap_type = 0;
0b16f239 1568
1f2263be 1569 if (ret == RMAP_DENYMATCH)
d62a17ae 1570 return RMAP_DENY;
0b16f239 1571 }
d62a17ae 1572 return RMAP_PERMIT;
0b16f239
DS
1573}
1574
5f040085 1575static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
d62a17ae 1576 struct attr *attr, afi_t afi, safi_t safi,
1577 const char *rmap_name)
0b16f239 1578{
40381db7 1579 struct bgp_path_info rmap_path;
d62a17ae 1580 route_map_result_t ret;
1581 struct route_map *rmap = NULL;
d7c0a89a 1582 uint8_t rmap_type;
0b16f239 1583
b787157a
DS
1584 /*
1585 * So if we get to this point and have no rmap_name
1586 * we want to just show the output as it currently
1587 * exists.
1588 */
1589 if (!rmap_name)
1590 return RMAP_PERMIT;
0b16f239 1591
d62a17ae 1592 /* Apply default weight value. */
1593 if (peer->weight[afi][safi])
1594 attr->weight = peer->weight[afi][safi];
0b16f239 1595
b787157a 1596 rmap = route_map_lookup_by_name(rmap_name);
98a4a44e 1597
b787157a
DS
1598 /*
1599 * If we have a route map name and we do not find
1600 * the routemap that means we have an implicit
1601 * deny.
1602 */
1603 if (rmap == NULL)
1604 return RMAP_DENY;
0b16f239 1605
40381db7 1606 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
d62a17ae 1607 /* Route map apply. */
b787157a 1608 /* Duplicate current value to new strucutre for modification. */
40381db7
DS
1609 rmap_path.peer = peer;
1610 rmap_path.attr = attr;
0b16f239 1611
0f672529 1612 rmap_type = peer->rmap_type;
b787157a 1613 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
0b16f239 1614
b787157a 1615 /* Apply BGP route map to the attribute. */
1782514f 1616 ret = route_map_apply(rmap, p, &rmap_path);
ac41b2a2 1617
0f672529 1618 peer->rmap_type = rmap_type;
b787157a
DS
1619
1620 if (ret == RMAP_DENYMATCH)
1621 /*
1622 * caller has multiple error paths with bgp_attr_flush()
1623 */
1624 return RMAP_DENY;
ac41b2a2 1625
d62a17ae 1626 return RMAP_PERMIT;
718e3744 1627}
6b0655a2 1628
5000f21c 1629/* If this is an EBGP peer with remove-private-AS */
d62a17ae 1630static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
1631 struct peer *peer, struct attr *attr)
1632{
1633 if (peer->sort == BGP_PEER_EBGP
1634 && (peer_af_flag_check(peer, afi, safi,
1635 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1636 || peer_af_flag_check(peer, afi, safi,
1637 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)
1638 || peer_af_flag_check(peer, afi, safi,
1639 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)
1640 || peer_af_flag_check(peer, afi, safi,
1641 PEER_FLAG_REMOVE_PRIVATE_AS))) {
1642 // Take action on the entire aspath
1643 if (peer_af_flag_check(peer, afi, safi,
1644 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)
1645 || peer_af_flag_check(peer, afi, safi,
1646 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
1647 if (peer_af_flag_check(
1648 peer, afi, safi,
1649 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
1650 attr->aspath = aspath_replace_private_asns(
bf26b80e 1651 attr->aspath, bgp->as, peer->as);
d62a17ae 1652
1653 // The entire aspath consists of private ASNs so create
1654 // an empty aspath
1655 else if (aspath_private_as_check(attr->aspath))
1656 attr->aspath = aspath_empty_get();
1657
1658 // There are some public and some private ASNs, remove
1659 // the private ASNs
1660 else
1661 attr->aspath = aspath_remove_private_asns(
bf26b80e 1662 attr->aspath, peer->as);
d62a17ae 1663 }
1664
1665 // 'all' was not specified so the entire aspath must be private
1666 // ASNs
1667 // for us to do anything
1668 else if (aspath_private_as_check(attr->aspath)) {
1669 if (peer_af_flag_check(
1670 peer, afi, safi,
1671 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
1672 attr->aspath = aspath_replace_private_asns(
bf26b80e 1673 attr->aspath, bgp->as, peer->as);
d62a17ae 1674 else
1675 attr->aspath = aspath_empty_get();
1676 }
1677 }
5000f21c
DS
1678}
1679
c7122e14 1680/* If this is an EBGP peer with as-override */
d62a17ae 1681static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
1682 struct peer *peer, struct attr *attr)
1683{
1684 if (peer->sort == BGP_PEER_EBGP
1685 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
1686 if (aspath_single_asn_check(attr->aspath, peer->as))
1687 attr->aspath = aspath_replace_specific_asn(
1688 attr->aspath, peer->as, bgp->as);
1689 }
1690}
1691
7f323236
DW
1692void bgp_attr_add_gshut_community(struct attr *attr)
1693{
1694 struct community *old;
1695 struct community *new;
1696 struct community *merge;
1697 struct community *gshut;
1698
1699 old = attr->community;
1700 gshut = community_str2com("graceful-shutdown");
1701
990f4f91 1702 assert(gshut);
1703
7f323236
DW
1704 if (old) {
1705 merge = community_merge(community_dup(old), gshut);
1706
a4d82a8a 1707 if (old->refcnt == 0)
3c1f53de 1708 community_free(&old);
7f323236
DW
1709
1710 new = community_uniq_sort(merge);
3c1f53de 1711 community_free(&merge);
7f323236
DW
1712 } else {
1713 new = community_dup(gshut);
1714 }
1715
3c1f53de 1716 community_free(&gshut);
7f323236
DW
1717 attr->community = new;
1718 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
1719
1720 /* When we add the graceful-shutdown community we must also
1721 * lower the local-preference */
1722 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1723 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
1724}
1725
1726
e73c112e
MK
1727/* Notify BGP Conditional advertisement scanner process. */
1728void bgp_notify_conditional_adv_scanner(struct update_subgroup *subgrp)
1729{
1730 struct peer *temp_peer;
1731 struct peer *peer = SUBGRP_PEER(subgrp);
1732 struct listnode *temp_node, *temp_nnode = NULL;
1733 afi_t afi = SUBGRP_AFI(subgrp);
1734 safi_t safi = SUBGRP_SAFI(subgrp);
1735 struct bgp *bgp = SUBGRP_INST(subgrp);
1736 struct bgp_filter *filter = &peer->filter[afi][safi];
1737
1738 if (!ADVERTISE_MAP_NAME(filter))
1739 return;
1740
1741 for (ALL_LIST_ELEMENTS(bgp->peer, temp_node, temp_nnode, temp_peer)) {
1742 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
1743 continue;
1744
1745 if (peer != temp_peer)
1746 continue;
1747
1748 temp_peer->advmap_table_change = true;
1749 break;
1750 }
1751}
1752
1753
f2ee6d5c 1754void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
c7122e14 1755{
960035b2 1756 if (family == AF_INET) {
975a328e
DA
1757 attr->nexthop.s_addr = INADDR_ANY;
1758 attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
960035b2 1759 }
d62a17ae 1760 if (family == AF_INET6)
1761 memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
ace295a9
MK
1762 if (family == AF_EVPN)
1763 memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4);
c7122e14
DS
1764}
1765
9bcb3eef 1766bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
b8685f9b 1767 struct update_subgroup *subgrp,
7f7940e6
MK
1768 const struct prefix *p, struct attr *attr,
1769 bool skip_rmap_check)
d62a17ae 1770{
1771 struct bgp_filter *filter;
1772 struct peer *from;
1773 struct peer *peer;
1774 struct peer *onlypeer;
1775 struct bgp *bgp;
40381db7 1776 struct attr *piattr;
b68885f9 1777 route_map_result_t ret;
d62a17ae 1778 int transparent;
1779 int reflect;
1780 afi_t afi;
1781 safi_t safi;
1782 int samepeer_safe = 0; /* for synthetic mplsvpns routes */
7b651a32 1783 bool nh_reset = false;
1784 uint64_t cum_bw;
d62a17ae 1785
1786 if (DISABLE_BGP_ANNOUNCE)
3dc339cd 1787 return false;
d62a17ae 1788
1789 afi = SUBGRP_AFI(subgrp);
1790 safi = SUBGRP_SAFI(subgrp);
1791 peer = SUBGRP_PEER(subgrp);
1792 onlypeer = NULL;
1793 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
1794 onlypeer = SUBGRP_PFIRST(subgrp)->peer;
1795
40381db7 1796 from = pi->peer;
d62a17ae 1797 filter = &peer->filter[afi][safi];
1798 bgp = SUBGRP_INST(subgrp);
40381db7
DS
1799 piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi)
1800 : pi->attr;
3f9c7369 1801
49e5a4a0 1802#ifdef ENABLE_BGP_VNC
d62a17ae 1803 if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN)
40381db7
DS
1804 && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT)
1805 || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) {
d62a17ae 1806
1807 /*
1808 * direct and direct_ext type routes originate internally even
1809 * though they can have peer pointers that reference other
1810 * systems
1811 */
8228a9a7
DS
1812 zlog_debug("%s: pfx %pFX bgp_direct->vpn route peer safe",
1813 __func__, p);
d62a17ae 1814 samepeer_safe = 1;
1815 }
65efcfce
LB
1816#endif
1817
ddb5b488
PZ
1818 if (((afi == AFI_IP) || (afi == AFI_IP6))
1819 && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
40381db7
DS
1820 && (pi->type == ZEBRA_ROUTE_BGP)
1821 && (pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488
PZ
1822
1823 /* Applies to routes leaked vpn->vrf and vrf->vpn */
1824
1825 samepeer_safe = 1;
1826 }
1827
d62a17ae 1828 /* With addpath we may be asked to TX all kinds of paths so make sure
40381db7
DS
1829 * pi is valid */
1830 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)
1831 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)
1832 || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
3dc339cd 1833 return false;
d62a17ae 1834 }
adbac85e 1835
d62a17ae 1836 /* If this is not the bestpath then check to see if there is an enabled
1837 * addpath
1838 * feature that requires us to advertise it */
40381db7 1839 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
dcc68b5e 1840 if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) {
3dc339cd 1841 return false;
d62a17ae 1842 }
1843 }
06370dac 1844
d62a17ae 1845 /* Aggregate-address suppress check. */
4056a5f6
RZ
1846 if (bgp_path_suppressed(pi) && !UNSUPPRESS_MAP_NAME(filter))
1847 return false;
3f9c7369 1848
13b7e7f0
DS
1849 /*
1850 * If we are doing VRF 2 VRF leaking via the import
1851 * statement, we want to prevent the route going
1852 * off box as that the RT and RD created are localy
1853 * significant and globaly useless.
1854 */
40381db7
DS
1855 if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
1856 && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
3dc339cd 1857 return false;
13b7e7f0 1858
d62a17ae 1859 /* If it's labeled safi, make sure the route has a valid label. */
1860 if (safi == SAFI_LABELED_UNICAST) {
9bcb3eef 1861 mpls_label_t label = bgp_adv_label(dest, pi, peer, afi, safi);
d62a17ae 1862 if (!bgp_is_valid_label(&label)) {
1863 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1864 zlog_debug("u%" PRIu64 ":s%" PRIu64
1865 " %pFX is filtered - no label (%p)",
d62a17ae 1866 subgrp->update_group->id, subgrp->id,
8228a9a7 1867 p, &label);
3dc339cd 1868 return false;
d62a17ae 1869 }
1870 }
cd1964ff 1871
d62a17ae 1872 /* Do not send back route to sender. */
1873 if (onlypeer && from == onlypeer) {
3dc339cd 1874 return false;
d62a17ae 1875 }
3f9c7369 1876
d62a17ae 1877 /* Do not send the default route in the BGP table if the neighbor is
1878 * configured for default-originate */
1879 if (CHECK_FLAG(peer->af_flags[afi][safi],
1880 PEER_FLAG_DEFAULT_ORIGINATE)) {
1881 if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY)
3dc339cd 1882 return false;
d62a17ae 1883 else if (p->family == AF_INET6 && p->prefixlen == 0)
3dc339cd 1884 return false;
d62a17ae 1885 }
4125bb67 1886
d62a17ae 1887 /* Transparency check. */
1888 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1889 && CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1890 transparent = 1;
1891 else
1892 transparent = 0;
1893
1894 /* If community is not disabled check the no-export and local. */
40381db7 1895 if (!transparent && bgp_community_filter(peer, piattr)) {
d62a17ae 1896 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
9e291289
DA
1897 zlog_debug("%s: community filter check fail for %pFX",
1898 __func__, p);
3dc339cd 1899 return false;
d62a17ae 1900 }
3f9c7369 1901
d62a17ae 1902 /* If the attribute has originator-id and it is same as remote
1903 peer's id. */
40381db7
DS
1904 if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
1905 && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
d62a17ae 1906 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1907 zlog_debug(
8228a9a7
DS
1908 "%s [Update:SEND] %pFX originator-id is same as remote router-id",
1909 onlypeer->host, p);
3dc339cd 1910 return false;
d62a17ae 1911 }
3f9c7369 1912
d62a17ae 1913 /* ORF prefix-list filter check */
1914 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV)
1915 && (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV)
1916 || CHECK_FLAG(peer->af_cap[afi][safi],
1917 PEER_CAP_ORF_PREFIX_SM_OLD_RCV)))
1918 if (peer->orf_plist[afi][safi]) {
1919 if (prefix_list_apply(peer->orf_plist[afi][safi], p)
1920 == PREFIX_DENY) {
1921 if (bgp_debug_update(NULL, p,
1922 subgrp->update_group, 0))
1923 zlog_debug(
8228a9a7
DS
1924 "%s [Update:SEND] %pFX is filtered via ORF",
1925 peer->host, p);
3dc339cd 1926 return false;
d62a17ae 1927 }
1928 }
1929
1930 /* Output filter check. */
40381db7 1931 if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
d62a17ae 1932 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
1933 zlog_debug("%s [Update:SEND] %pFX is filtered",
1934 peer->host, p);
3dc339cd 1935 return false;
d62a17ae 1936 }
3f9c7369 1937
d62a17ae 1938 /* AS path loop check. */
2b31007c
RZ
1939 if (onlypeer && onlypeer->as_path_loop_detection
1940 && aspath_loop_check(piattr->aspath, onlypeer->as)) {
d62a17ae 1941 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1942 zlog_debug(
3efd0893 1943 "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
d62a17ae 1944 onlypeer->host, onlypeer->as);
3dc339cd 1945 return false;
d62a17ae 1946 }
3f9c7369 1947
d62a17ae 1948 /* If we're a CONFED we need to loop check the CONFED ID too */
1949 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
40381db7 1950 if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
d62a17ae 1951 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
1952 zlog_debug(
3efd0893 1953 "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
d62a17ae 1954 peer->host, bgp->confed_id);
3dc339cd 1955 return false;
d62a17ae 1956 }
3f9c7369 1957 }
3f9c7369 1958
d62a17ae 1959 /* Route-Reflect check. */
1960 if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
1961 reflect = 1;
1962 else
1963 reflect = 0;
1964
1965 /* IBGP reflection check. */
1966 if (reflect && !samepeer_safe) {
1967 /* A route from a Client peer. */
1968 if (CHECK_FLAG(from->af_flags[afi][safi],
1969 PEER_FLAG_REFLECTOR_CLIENT)) {
1970 /* Reflect to all the Non-Client peers and also to the
1971 Client peers other than the originator. Originator
1972 check
1973 is already done. So there is noting to do. */
1974 /* no bgp client-to-client reflection check. */
892fedb6
DA
1975 if (CHECK_FLAG(bgp->flags,
1976 BGP_FLAG_NO_CLIENT_TO_CLIENT))
d62a17ae 1977 if (CHECK_FLAG(peer->af_flags[afi][safi],
1978 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1979 return false;
d62a17ae 1980 } else {
1981 /* A route from a Non-client peer. Reflect to all other
1982 clients. */
1983 if (!CHECK_FLAG(peer->af_flags[afi][safi],
1984 PEER_FLAG_REFLECTOR_CLIENT))
3dc339cd 1985 return false;
d62a17ae 1986 }
1987 }
3f9c7369 1988
d62a17ae 1989 /* For modify attribute, copy it to temporary structure. */
6f4f49b2 1990 *attr = *piattr;
d62a17ae 1991
1992 /* If local-preference is not set. */
1993 if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED)
1994 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)))) {
1995 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
1996 attr->local_pref = bgp->default_local_pref;
3f9c7369 1997 }
3f9c7369 1998
d62a17ae 1999 /* If originator-id is not set and the route is to be reflected,
2000 set the originator id */
2001 if (reflect
2002 && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
2003 IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
2004 SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
2005 }
3f9c7369 2006
d62a17ae 2007 /* Remove MED if its an EBGP peer - will get overwritten by route-maps
2008 */
2009 if (peer->sort == BGP_PEER_EBGP
2010 && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
2011 if (from != bgp->peer_self && !transparent
2012 && !CHECK_FLAG(peer->af_flags[afi][safi],
2013 PEER_FLAG_MED_UNCHANGED))
2014 attr->flag &=
2015 ~(ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
2016 }
3f9c7369 2017
d62a17ae 2018 /* Since the nexthop attribute can vary per peer, it is not explicitly
2019 * set
2020 * in announce check, only certain flags and length (or number of
2021 * nexthops
2022 * -- for IPv6/MP_REACH) are set here in order to guide the update
2023 * formation
2024 * code in setting the nexthop(s) on a per peer basis in
2025 * reformat_peer().
2026 * Typically, the source nexthop in the attribute is preserved but in
2027 * the
2028 * scenarios where we know it will always be overwritten, we reset the
2029 * nexthop to "0" in an attempt to achieve better Update packing. An
2030 * example of this is when a prefix from each of 2 IBGP peers needs to
2031 * be
2032 * announced to an EBGP peer (and they have the same attributes barring
2033 * their nexthop).
2034 */
2035 if (reflect)
2036 SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
2037
2038#define NEXTHOP_IS_V6 \
2039 ((safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN \
2040 && (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))) \
2041 || ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) \
2042 && attr->mp_nexthop_len >= IPV6_MAX_BYTELEN))
2043
2044 /* IPv6/MP starts with 1 nexthop. The link-local address is passed only
2045 * if
2046 * the peer (group) is configured to receive link-local nexthop
2047 * unchanged
c728d027
DA
2048 * and it is available in the prefix OR we're not reflecting the route,
2049 * link-local nexthop address is valid and
d62a17ae 2050 * the peer (group) to whom we're going to announce is on a shared
2051 * network
2052 * and this is either a self-originated route or the peer is EBGP.
c728d027
DA
2053 * By checking if nexthop LL address is valid we are sure that
2054 * we do not announce LL address as `::`.
d62a17ae 2055 */
2056 if (NEXTHOP_IS_V6) {
2057 attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
2058 if ((CHECK_FLAG(peer->af_flags[afi][safi],
2059 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
2060 && IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
c728d027
DA
2061 || (!reflect
2062 && IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local)
2063 && peer->shared_network
d62a17ae 2064 && (from == bgp->peer_self
2065 || peer->sort == BGP_PEER_EBGP))) {
2066 attr->mp_nexthop_len =
2067 BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
2068 }
3f9c7369 2069
d62a17ae 2070 /* Clear off link-local nexthop in source, whenever it is not
2071 * needed to
2072 * ensure more prefixes share the same attribute for
2073 * announcement.
2074 */
2075 if (!(CHECK_FLAG(peer->af_flags[afi][safi],
2076 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)))
2077 memset(&attr->mp_nexthop_local, 0, IPV6_MAX_BYTELEN);
2078 }
3f9c7369 2079
d62a17ae 2080 bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
2081 bgp_peer_as_override(bgp, afi, safi, peer, attr);
2082
2083 /* Route map & unsuppress-map apply. */
7f7940e6 2084 if (!skip_rmap_check
e73c112e 2085 && (ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
b8694ef4
DS
2086 struct bgp_path_info rmap_path = {0};
2087 struct bgp_path_info_extra dummy_rmap_path_extra = {0};
2088 struct attr dummy_attr = {0};
d62a17ae 2089
e34291b8 2090 /* Fill temp path_info */
9bcb3eef
DS
2091 prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
2092 pi, peer, attr);
16f7ce2b 2093
d62a17ae 2094 /* don't confuse inbound and outbound setting */
2095 RESET_FLAG(attr->rmap_change_flags);
2096
2097 /*
2098 * The route reflector is not allowed to modify the attributes
2099 * of the reflected IBGP routes unless explicitly allowed.
2100 */
2101 if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
892fedb6
DA
2102 && !CHECK_FLAG(bgp->flags,
2103 BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
6f4f49b2 2104 dummy_attr = *attr;
40381db7 2105 rmap_path.attr = &dummy_attr;
d62a17ae 2106 }
3f9c7369 2107
d62a17ae 2108 SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
3f9c7369 2109
4056a5f6 2110 if (bgp_path_suppressed(pi))
d62a17ae 2111 ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
1782514f 2112 &rmap_path);
d62a17ae 2113 else
2114 ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
1782514f 2115 &rmap_path);
d62a17ae 2116
2117 peer->rmap_type = 0;
2118
2119 if (ret == RMAP_DENYMATCH) {
778048bf 2120 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
8228a9a7
DS
2121 zlog_debug(
2122 "%s [Update:SEND] %pFX is filtered by route-map",
2123 peer->host, p);
778048bf 2124
d62a17ae 2125 bgp_attr_flush(attr);
3dc339cd 2126 return false;
d62a17ae 2127 }
3f9c7369 2128 }
3f9c7369 2129
9dac9fc8
DA
2130 /* RFC 8212 to prevent route leaks.
2131 * This specification intends to improve this situation by requiring the
2132 * explicit configuration of both BGP Import and Export Policies for any
2133 * External BGP (EBGP) session such as customers, peers, or
2134 * confederation boundaries for all enabled address families. Through
2135 * codification of the aforementioned requirement, operators will
2136 * benefit from consistent behavior across different BGP
2137 * implementations.
2138 */
1d3fdccf 2139 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
9dac9fc8 2140 if (!bgp_outbound_policy_exists(peer, filter))
3dc339cd 2141 return false;
9dac9fc8 2142
fb29348a
DA
2143 /* draft-ietf-idr-deprecate-as-set-confed-set
2144 * Filter routes having AS_SET or AS_CONFED_SET in the path.
2145 * Eventually, This document (if approved) updates RFC 4271
2146 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
2147 * and obsoletes RFC 6472.
2148 */
7f972cd8 2149 if (peer->bgp->reject_as_sets)
fb29348a 2150 if (aspath_check_as_sets(attr->aspath))
3dc339cd 2151 return false;
fb29348a 2152
33d022bc
DA
2153 /* Codification of AS 0 Processing */
2154 if (aspath_check_as_zero(attr->aspath))
e2369003 2155 return false;
33d022bc 2156
637e5ba4 2157 if (bgp_in_graceful_shutdown(bgp)) {
a4d82a8a
PZ
2158 if (peer->sort == BGP_PEER_IBGP
2159 || peer->sort == BGP_PEER_CONFED) {
7f323236
DW
2160 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
2161 attr->local_pref = BGP_GSHUT_LOCAL_PREF;
2162 } else {
2163 bgp_attr_add_gshut_community(attr);
2164 }
2165 }
2166
d62a17ae 2167 /* After route-map has been applied, we check to see if the nexthop to
2168 * be carried in the attribute (that is used for the announcement) can
2169 * be cleared off or not. We do this in all cases where we would be
2170 * setting the nexthop to "ourselves". For IPv6, we only need to
2171 * consider
2172 * the global nexthop here; the link-local nexthop would have been
2173 * cleared
2174 * already, and if not, it is required by the update formation code.
2175 * Also see earlier comments in this function.
2176 */
2177 /*
2178 * If route-map has performed some operation on the nexthop or the peer
2179 * configuration says to pass it unchanged, we cannot reset the nexthop
2180 * here, so only attempt to do it if these aren't true. Note that the
2181 * route-map handler itself might have cleared the nexthop, if for
2182 * example,
2183 * it is configured as 'peer-address'.
2184 */
2185 if (!bgp_rmap_nhop_changed(attr->rmap_change_flags,
40381db7 2186 piattr->rmap_change_flags)
d62a17ae 2187 && !transparent
2188 && !CHECK_FLAG(peer->af_flags[afi][safi],
2189 PEER_FLAG_NEXTHOP_UNCHANGED)) {
2190 /* We can reset the nexthop, if setting (or forcing) it to
2191 * 'self' */
2192 if (CHECK_FLAG(peer->af_flags[afi][safi],
2193 PEER_FLAG_NEXTHOP_SELF)
2194 || CHECK_FLAG(peer->af_flags[afi][safi],
2195 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2196 if (!reflect
2197 || CHECK_FLAG(peer->af_flags[afi][safi],
7b651a32 2198 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
d62a17ae 2199 subgroup_announce_reset_nhop(
2200 (peer_cap_enhe(peer, afi, safi)
2201 ? AF_INET6
2202 : p->family),
2203 attr);
7b651a32 2204 nh_reset = true;
2205 }
d62a17ae 2206 } else if (peer->sort == BGP_PEER_EBGP) {
2207 /* Can also reset the nexthop if announcing to EBGP, but
2208 * only if
2209 * no peer in the subgroup is on a shared subnet.
2210 * Note: 3rd party nexthop currently implemented for
2211 * IPv4 only.
2212 */
737af885
BS
2213 if ((p->family == AF_INET) &&
2214 (!bgp_subgrp_multiaccess_check_v4(
2215 piattr->nexthop,
7b651a32 2216 subgrp, from))) {
d62a17ae 2217 subgroup_announce_reset_nhop(
2218 (peer_cap_enhe(peer, afi, safi)
a4d82a8a
PZ
2219 ? AF_INET6
2220 : p->family),
737af885 2221 attr);
7b651a32 2222 nh_reset = true;
2223 }
737af885
BS
2224
2225 if ((p->family == AF_INET6) &&
2226 (!bgp_subgrp_multiaccess_check_v6(
2227 piattr->mp_nexthop_global,
7b651a32 2228 subgrp, from))) {
737af885
BS
2229 subgroup_announce_reset_nhop(
2230 (peer_cap_enhe(peer, afi, safi)
2231 ? AF_INET6
2232 : p->family),
2233 attr);
7b651a32 2234 nh_reset = true;
2235 }
737af885
BS
2236
2237
2238
40381db7 2239 } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) {
960035b2
PZ
2240 /*
2241 * This flag is used for leaked vpn-vrf routes
2242 */
2243 int family = p->family;
2244
2245 if (peer_cap_enhe(peer, afi, safi))
2246 family = AF_INET6;
2247
2248 if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
2249 zlog_debug(
1defdda8 2250 "%s: BGP_PATH_ANNC_NH_SELF, family=%s",
960035b2
PZ
2251 __func__, family2str(family));
2252 subgroup_announce_reset_nhop(family, attr);
7b651a32 2253 nh_reset = true;
d62a17ae 2254 }
63696f1d 2255 }
960035b2 2256
63696f1d 2257 /* If IPv6/MP and nexthop does not have any override and happens
2258 * to
2259 * be a link-local address, reset it so that we don't pass along
2260 * the
2261 * source's link-local IPv6 address to recipients who may not be
2262 * on
2263 * the same interface.
2264 */
2265 if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi)) {
7b651a32 2266 if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_global)) {
63696f1d 2267 subgroup_announce_reset_nhop(AF_INET6, attr);
7b651a32 2268 nh_reset = true;
2269 }
d62a17ae 2270 }
3f9c7369 2271
7b651a32 2272 /*
2273 * When the next hop is set to ourselves, if all multipaths have
2274 * link-bandwidth announce the cumulative bandwidth as that makes
2275 * the most sense. However, don't modify if the link-bandwidth has
2276 * been explicitly set by user policy.
2277 */
2278 if (nh_reset &&
f7e1c681 2279 bgp_path_info_mpath_chkwtd(bgp, pi) &&
7b651a32 2280 (cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
2281 !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
2282 attr->ecommunity = ecommunity_replace_linkbw(
27aa23a4
DA
2283 bgp->as, attr->ecommunity, cum_bw,
2284 CHECK_FLAG(peer->flags,
2285 PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
7b651a32 2286
3dc339cd 2287 return true;
3f9c7369
DS
2288}
2289
f009ff26 2290static int bgp_route_select_timer_expire(struct thread *thread)
2291{
2292 struct afi_safi_info *info;
2293 afi_t afi;
2294 safi_t safi;
2295 struct bgp *bgp;
2296
2297 info = THREAD_ARG(thread);
2298 afi = info->afi;
2299 safi = info->safi;
2300 bgp = info->bgp;
2301
2302 if (BGP_DEBUG(update, UPDATE_OUT))
36235319
QY
2303 zlog_debug("afi %d, safi %d : route select timer expired", afi,
2304 safi);
f009ff26 2305
2306 bgp->gr_info[afi][safi].t_route_select = NULL;
2307
2308 XFREE(MTYPE_TMP, info);
2309
2310 /* Best path selection */
2311 return bgp_best_path_select_defer(bgp, afi, safi);
2312}
2313
9bcb3eef 2314void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
d62a17ae 2315 struct bgp_maxpaths_cfg *mpath_cfg,
4b7e6066
DS
2316 struct bgp_path_info_pair *result, afi_t afi,
2317 safi_t safi)
2318{
2319 struct bgp_path_info *new_select;
2320 struct bgp_path_info *old_select;
40381db7
DS
2321 struct bgp_path_info *pi;
2322 struct bgp_path_info *pi1;
2323 struct bgp_path_info *pi2;
2324 struct bgp_path_info *nextpi = NULL;
d62a17ae 2325 int paths_eq, do_mpath, debug;
2326 struct list mp_list;
2327 char pfx_buf[PREFIX2STR_BUFFER];
2328 char path_buf[PATH_ADDPATH_STR_BUFFER];
2329
2330 bgp_mp_list_init(&mp_list);
2331 do_mpath =
2332 (mpath_cfg->maxpaths_ebgp > 1 || mpath_cfg->maxpaths_ibgp > 1);
2333
9bcb3eef 2334 debug = bgp_debug_bestpath(dest);
d62a17ae 2335
2336 if (debug)
9bcb3eef 2337 prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
d62a17ae 2338
9bcb3eef 2339 dest->reason = bgp_path_selection_none;
d62a17ae 2340 /* bgp deterministic-med */
2341 new_select = NULL;
892fedb6 2342 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
d62a17ae 2343
1defdda8 2344 /* Clear BGP_PATH_DMED_SELECTED for all paths */
9bcb3eef 2345 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2346 pi1 = pi1->next)
9bcb3eef 2347 bgp_path_info_unset_flag(dest, pi1,
18ee8310 2348 BGP_PATH_DMED_SELECTED);
d62a17ae 2349
9bcb3eef 2350 for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
6f94b685 2351 pi1 = pi1->next) {
40381db7 2352 if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK))
d62a17ae 2353 continue;
40381db7 2354 if (BGP_PATH_HOLDDOWN(pi1))
d62a17ae 2355 continue;
ea8b2282 2356 if (pi1->peer != bgp->peer_self)
feb17238 2357 if (!peer_established(pi1->peer))
d62a17ae 2358 continue;
2359
40381db7
DS
2360 new_select = pi1;
2361 if (pi1->next) {
2362 for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
2363 if (CHECK_FLAG(pi2->flags,
1defdda8 2364 BGP_PATH_DMED_CHECK))
d62a17ae 2365 continue;
40381db7 2366 if (BGP_PATH_HOLDDOWN(pi2))
d62a17ae 2367 continue;
ea8b2282 2368 if (pi2->peer != bgp->peer_self
d62a17ae 2369 && !CHECK_FLAG(
ea8b2282
DS
2370 pi2->peer->sflags,
2371 PEER_STATUS_NSF_WAIT))
40381db7 2372 if (pi2->peer->status
d62a17ae 2373 != Established)
2374 continue;
2375
121e245d
DS
2376 if (!aspath_cmp_left(pi1->attr->aspath,
2377 pi2->attr->aspath)
2378 && !aspath_cmp_left_confed(
40381db7 2379 pi1->attr->aspath,
121e245d
DS
2380 pi2->attr->aspath))
2381 continue;
d62a17ae 2382
121e245d
DS
2383 if (bgp_path_info_cmp(
2384 bgp, pi2, new_select,
2385 &paths_eq, mpath_cfg, debug,
fdf81fa0 2386 pfx_buf, afi, safi,
9bcb3eef 2387 &dest->reason)) {
121e245d 2388 bgp_path_info_unset_flag(
9bcb3eef 2389 dest, new_select,
121e245d
DS
2390 BGP_PATH_DMED_SELECTED);
2391 new_select = pi2;
d62a17ae 2392 }
121e245d
DS
2393
2394 bgp_path_info_set_flag(
9bcb3eef 2395 dest, pi2, BGP_PATH_DMED_CHECK);
d62a17ae 2396 }
2397 }
9bcb3eef 2398 bgp_path_info_set_flag(dest, new_select,
18ee8310 2399 BGP_PATH_DMED_CHECK);
9bcb3eef 2400 bgp_path_info_set_flag(dest, new_select,
18ee8310 2401 BGP_PATH_DMED_SELECTED);
d62a17ae 2402
2403 if (debug) {
18ee8310 2404 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2405 new_select, path_buf, sizeof(path_buf));
8228a9a7 2406 zlog_debug(
4378495a
DS
2407 "%pBD(%s): %s is the bestpath from AS %u",
2408 dest, bgp->name_pretty, path_buf,
8228a9a7
DS
2409 aspath_get_first_as(
2410 new_select->attr->aspath));
d62a17ae 2411 }
2412 }
2413 }
96450faf 2414
d62a17ae 2415 /* Check old selected route and new selected route. */
2416 old_select = NULL;
2417 new_select = NULL;
9bcb3eef 2418 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2419 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
19ea4cec
DS
2420 enum bgp_path_selection_reason reason;
2421
40381db7
DS
2422 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
2423 old_select = pi;
d62a17ae 2424
40381db7 2425 if (BGP_PATH_HOLDDOWN(pi)) {
d62a17ae 2426 /* reap REMOVED routes, if needs be
2427 * selected route must stay for a while longer though
2428 */
40381db7
DS
2429 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
2430 && (pi != old_select))
9bcb3eef 2431 bgp_path_info_reap(dest, pi);
d62a17ae 2432
ddb5b488 2433 if (debug)
40381db7
DS
2434 zlog_debug("%s: pi %p in holddown", __func__,
2435 pi);
ddb5b488 2436
d62a17ae 2437 continue;
2438 }
96450faf 2439
40381db7
DS
2440 if (pi->peer && pi->peer != bgp->peer_self
2441 && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
feb17238 2442 if (!peer_established(pi->peer)) {
ddb5b488
PZ
2443
2444 if (debug)
2445 zlog_debug(
40381db7
DS
2446 "%s: pi %p non self peer %s not estab state",
2447 __func__, pi, pi->peer->host);
ddb5b488 2448
d62a17ae 2449 continue;
ddb5b488 2450 }
9fbdd100 2451
892fedb6 2452 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
40381db7 2453 && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
9bcb3eef 2454 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
ddb5b488 2455 if (debug)
40381db7 2456 zlog_debug("%s: pi %p dmed", __func__, pi);
d62a17ae 2457 continue;
2458 }
9fbdd100 2459
9bcb3eef 2460 bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
06370dac 2461
9bcb3eef 2462 reason = dest->reason;
40381db7 2463 if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
9bcb3eef
DS
2464 debug, pfx_buf, afi, safi,
2465 &dest->reason)) {
19ea4cec
DS
2466 if (new_select == NULL &&
2467 reason != bgp_path_selection_none)
9bcb3eef 2468 dest->reason = reason;
40381db7 2469 new_select = pi;
d62a17ae 2470 }
2471 }
718e3744 2472
d62a17ae 2473 /* Now that we know which path is the bestpath see if any of the other
2474 * paths
2475 * qualify as multipaths
2476 */
2477 if (debug) {
2478 if (new_select)
7533cad7
QY
2479 bgp_path_info_path_with_addpath_rx_str(
2480 new_select, path_buf, sizeof(path_buf));
d62a17ae 2481 else
772270f3 2482 snprintf(path_buf, sizeof(path_buf), "NONE");
d62a17ae 2483 zlog_debug(
4378495a
DS
2484 "%pBD(%s): After path selection, newbest is %s oldbest was %s",
2485 dest, bgp->name_pretty, path_buf,
d62a17ae 2486 old_select ? old_select->peer->host : "NONE");
96450faf 2487 }
9fbdd100 2488
d62a17ae 2489 if (do_mpath && new_select) {
9bcb3eef 2490 for (pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 2491 (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
d62a17ae 2492
2493 if (debug)
18ee8310 2494 bgp_path_info_path_with_addpath_rx_str(
7533cad7 2495 pi, path_buf, sizeof(path_buf));
d62a17ae 2496
40381db7 2497 if (pi == new_select) {
d62a17ae 2498 if (debug)
2499 zlog_debug(
4378495a
DS
2500 "%pBD(%s): %s is the bestpath, add to the multipath list",
2501 dest, bgp->name_pretty,
2502 path_buf);
40381db7 2503 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2504 continue;
2505 }
2506
40381db7 2507 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2508 continue;
2509
40381db7
DS
2510 if (pi->peer && pi->peer != bgp->peer_self
2511 && !CHECK_FLAG(pi->peer->sflags,
d62a17ae 2512 PEER_STATUS_NSF_WAIT))
feb17238 2513 if (!peer_established(pi->peer))
d62a17ae 2514 continue;
2515
40381db7 2516 if (!bgp_path_info_nexthop_cmp(pi, new_select)) {
d62a17ae 2517 if (debug)
2518 zlog_debug(
8228a9a7
DS
2519 "%pBD: %s has the same nexthop as the bestpath, skip it",
2520 dest, path_buf);
d62a17ae 2521 continue;
2522 }
2523
40381db7 2524 bgp_path_info_cmp(bgp, pi, new_select, &paths_eq,
fdf81fa0 2525 mpath_cfg, debug, pfx_buf, afi, safi,
9bcb3eef 2526 &dest->reason);
d62a17ae 2527
2528 if (paths_eq) {
2529 if (debug)
2530 zlog_debug(
8228a9a7
DS
2531 "%pBD: %s is equivalent to the bestpath, add to the multipath list",
2532 dest, path_buf);
40381db7 2533 bgp_mp_list_add(&mp_list, pi);
d62a17ae 2534 }
2535 }
2536 }
fee0f4c6 2537
4378495a 2538 bgp_path_info_mpath_update(bgp, dest, new_select, old_select, &mp_list,
18ee8310
DS
2539 mpath_cfg);
2540 bgp_path_info_mpath_aggregate_update(new_select, old_select);
d62a17ae 2541 bgp_mp_list_clear(&mp_list);
96450faf 2542
9bcb3eef 2543 bgp_addpath_update_ids(bgp, dest, afi, safi);
dcc68b5e 2544
d62a17ae 2545 result->old = old_select;
2546 result->new = new_select;
96450faf 2547
d62a17ae 2548 return;
fee0f4c6 2549}
2550
3f9c7369
DS
2551/*
2552 * A new route/change in bestpath of an existing route. Evaluate the path
2553 * for advertisement to the subgroup.
2554 */
3dc339cd
DA
2555void subgroup_process_announce_selected(struct update_subgroup *subgrp,
2556 struct bgp_path_info *selected,
9bcb3eef 2557 struct bgp_dest *dest,
3dc339cd 2558 uint32_t addpath_tx_id)
d62a17ae 2559{
b54892e0 2560 const struct prefix *p;
d62a17ae 2561 struct peer *onlypeer;
2562 struct attr attr;
2563 afi_t afi;
2564 safi_t safi;
a77e2f4b
S
2565 struct bgp *bgp;
2566 bool advertise;
adbac85e 2567
9bcb3eef 2568 p = bgp_dest_get_prefix(dest);
d62a17ae 2569 afi = SUBGRP_AFI(subgrp);
2570 safi = SUBGRP_SAFI(subgrp);
a77e2f4b 2571 bgp = SUBGRP_INST(subgrp);
d62a17ae 2572 onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
2573 : NULL);
2574
2dbe669b
DA
2575 if (BGP_DEBUG(update, UPDATE_OUT))
2576 zlog_debug("%s: p=%pFX, selected=%p", __func__, p, selected);
e0207895 2577
d62a17ae 2578 /* First update is deferred until ORF or ROUTE-REFRESH is received */
996c9314
LB
2579 if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi],
2580 PEER_STATUS_ORF_WAIT_REFRESH))
3dc339cd 2581 return;
d62a17ae 2582
2583 memset(&attr, 0, sizeof(struct attr));
2584 /* It's initialized in bgp_announce_check() */
2585
a77e2f4b
S
2586 /* Announcement to the subgroup. If the route is filtered withdraw it.
2587 * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
2588 * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
2589 * route
d62a17ae 2590 */
a77e2f4b
S
2591 advertise = bgp_check_advertise(bgp, dest);
2592
d62a17ae 2593 if (selected) {
7f7940e6 2594 if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
a77e2f4b
S
2595 false)) {
2596 /* Route is selected, if the route is already installed
2597 * in FIB, then it is advertised
2598 */
2599 if (advertise)
2600 bgp_adj_out_set_subgroup(dest, subgrp, &attr,
2601 selected);
2602 } else
9bcb3eef 2603 bgp_adj_out_unset_subgroup(dest, subgrp, 1,
dcc68b5e 2604 addpath_tx_id);
d62a17ae 2605 }
2606
2607 /* If selected is NULL we must withdraw the path using addpath_tx_id */
2608 else {
9bcb3eef 2609 bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id);
d62a17ae 2610 }
200df115 2611}
fee0f4c6 2612
3064bf43 2613/*
e1072051 2614 * Clear IGP changed flag and attribute changed flag for a route (all paths).
2615 * This is called at the end of route processing.
3064bf43 2616 */
9bcb3eef 2617void bgp_zebra_clear_route_change_flags(struct bgp_dest *dest)
3064bf43 2618{
40381db7 2619 struct bgp_path_info *pi;
3064bf43 2620
9bcb3eef 2621 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 2622 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 2623 continue;
40381db7
DS
2624 UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED);
2625 UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED);
d62a17ae 2626 }
3064bf43 2627}
2628
2629/*
2630 * Has the route changed from the RIB's perspective? This is invoked only
2631 * if the route selection returns the same best route as earlier - to
2632 * determine if we need to update zebra or not.
2633 */
9bcb3eef 2634bool bgp_zebra_has_route_changed(struct bgp_path_info *selected)
d62a17ae 2635{
4b7e6066 2636 struct bgp_path_info *mpinfo;
d62a17ae 2637
2bb9eff4
DS
2638 /* If this is multipath, check all selected paths for any nexthop
2639 * change or attribute change. Some attribute changes (e.g., community)
2640 * aren't of relevance to the RIB, but we'll update zebra to ensure
2641 * we handle the case of BGP nexthop change. This is the behavior
2642 * when the best path has an attribute change anyway.
d62a17ae 2643 */
1defdda8 2644 if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED)
b1875e65 2645 || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)
2646 || CHECK_FLAG(selected->flags, BGP_PATH_LINK_BW_CHG))
3dc339cd 2647 return true;
d62a17ae 2648
2bb9eff4
DS
2649 /*
2650 * If this is multipath, check all selected paths for any nexthop change
d62a17ae 2651 */
18ee8310
DS
2652 for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo;
2653 mpinfo = bgp_path_info_mpath_next(mpinfo)) {
1defdda8
DS
2654 if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED)
2655 || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED))
3dc339cd 2656 return true;
d62a17ae 2657 }
3064bf43 2658
d62a17ae 2659 /* Nothing has changed from the RIB's perspective. */
3dc339cd 2660 return false;
3064bf43 2661}
2662
d62a17ae 2663struct bgp_process_queue {
2664 struct bgp *bgp;
9bcb3eef 2665 STAILQ_HEAD(, bgp_dest) pqueue;
aac24838
JB
2666#define BGP_PROCESS_QUEUE_EOIU_MARKER (1 << 0)
2667 unsigned int flags;
2668 unsigned int queued;
200df115 2669};
2670
3b0c17e1 2671static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
9bcb3eef 2672 safi_t safi, struct bgp_dest *dest,
3b0c17e1 2673 struct bgp_path_info *new_select,
2674 struct bgp_path_info *old_select)
2675{
9bcb3eef 2676 const struct prefix *p = bgp_dest_get_prefix(dest);
3b0c17e1 2677
2678 if ((afi != AFI_IP && afi != AFI_IP6) || (safi != SAFI_UNICAST))
2679 return;
2680
2681 if (advertise_type5_routes(bgp, afi) && new_select
2682 && is_route_injectable_into_evpn(new_select)) {
2683
2684 /* apply the route-map */
2685 if (bgp->adv_cmd_rmap[afi][safi].map) {
2686 route_map_result_t ret;
2687 struct bgp_path_info rmap_path;
2688 struct bgp_path_info_extra rmap_path_extra;
2689 struct attr dummy_attr;
2690
2691 dummy_attr = *new_select->attr;
2692
2693 /* Fill temp path_info */
9bcb3eef 2694 prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
3b0c17e1 2695 new_select, new_select->peer,
2696 &dummy_attr);
2697
2698 RESET_FLAG(dummy_attr.rmap_change_flags);
2699
2700 ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
1782514f 2701 p, &rmap_path);
3b0c17e1 2702
2703 if (ret == RMAP_DENYMATCH) {
2704 bgp_attr_flush(&dummy_attr);
2705 bgp_evpn_withdraw_type5_route(bgp, p, afi,
2706 safi);
2707 } else
2708 bgp_evpn_advertise_type5_route(
2709 bgp, p, &dummy_attr, afi, safi);
2710 } else {
2711 bgp_evpn_advertise_type5_route(bgp, p, new_select->attr,
2712 afi, safi);
2713 }
2714 } else if (advertise_type5_routes(bgp, afi) && old_select
2715 && is_route_injectable_into_evpn(old_select))
2716 bgp_evpn_withdraw_type5_route(bgp, p, afi, safi);
2717}
2718
bb2ca692
MS
2719/*
2720 * Utility to determine whether a particular path_info should use
2721 * the IMPLICIT_NULL label. This is pretty specialized: it's only called
2722 * in a path where we basically _know_ this is a BGP-LU route.
2723 */
2724static bool bgp_lu_need_imp_null(const struct bgp_path_info *new_select)
2725{
2726 /* Certain types get imp null; so do paths where the nexthop is
2727 * not labeled.
2728 */
2729 if (new_select->sub_type == BGP_ROUTE_STATIC
2730 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2731 || new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
2732 return true;
2733 else if (new_select->extra == NULL ||
2734 !bgp_is_valid_label(&new_select->extra->label[0]))
2735 /* TODO -- should be configurable? */
2736 return true;
2737 else
2738 return false;
2739}
2740
3103e8d2
DS
2741/*
2742 * old_select = The old best path
2743 * new_select = the new best path
2744 *
2745 * if (!old_select && new_select)
2746 * We are sending new information on.
2747 *
2748 * if (old_select && new_select) {
2749 * if (new_select != old_select)
2750 * We have a new best path send a change
2751 * else
2752 * We've received a update with new attributes that needs
2753 * to be passed on.
2754 * }
2755 *
2756 * if (old_select && !new_select)
2757 * We have no eligible route that we can announce or the rn
2758 * is being removed.
2759 */
9bcb3eef 2760static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
aac24838 2761 afi_t afi, safi_t safi)
d62a17ae 2762{
4b7e6066
DS
2763 struct bgp_path_info *new_select;
2764 struct bgp_path_info *old_select;
2765 struct bgp_path_info_pair old_and_new;
ddb5b488 2766 int debug = 0;
d62a17ae 2767
892fedb6 2768 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
9bcb3eef
DS
2769 if (dest)
2770 debug = bgp_debug_bestpath(dest);
b54892e0 2771 if (debug)
f4c713ae 2772 zlog_debug(
56ca3b5b 2773 "%s: bgp delete in progress, ignoring event, p=%pBD",
9bcb3eef 2774 __func__, dest);
f4c713ae
LB
2775 return;
2776 }
d62a17ae 2777 /* Is it end of initial update? (after startup) */
9bcb3eef 2778 if (!dest) {
e36f61b5
DS
2779 frr_timestamp(3, bgp->update_delay_zebra_resume_time,
2780 sizeof(bgp->update_delay_zebra_resume_time));
d62a17ae 2781
2782 bgp->main_zebra_update_hold = 0;
05c7a1cc
QY
2783 FOREACH_AFI_SAFI (afi, safi) {
2784 if (bgp_fibupd_safi(safi))
2785 bgp_zebra_announce_table(bgp, afi, safi);
2786 }
d62a17ae 2787 bgp->main_peers_update_hold = 0;
2788
2789 bgp_start_routeadv(bgp);
aac24838 2790 return;
d62a17ae 2791 }
cb1faec9 2792
9bcb3eef 2793 const struct prefix *p = bgp_dest_get_prefix(dest);
b575a12c 2794
9bcb3eef 2795 debug = bgp_debug_bestpath(dest);
b54892e0 2796 if (debug)
4378495a
DS
2797 zlog_debug("%s: p=%pBDi(%s) afi=%s, safi=%s start", __func__,
2798 dest, bgp->name_pretty, afi2str(afi),
2799 safi2str(safi));
ddb5b488 2800
f009ff26 2801 /* The best path calculation for the route is deferred if
2802 * BGP_NODE_SELECT_DEFER is set
2803 */
9bcb3eef 2804 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 2805 if (BGP_DEBUG(update, UPDATE_OUT))
02c671af 2806 zlog_debug("SELECT_DEFER flag set for route %p", dest);
f009ff26 2807 return;
2808 }
2809
d62a17ae 2810 /* Best path selection. */
9bcb3eef 2811 bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
d62a17ae 2812 afi, safi);
2813 old_select = old_and_new.old;
2814 new_select = old_and_new.new;
2815
2816 /* Do we need to allocate or free labels?
2817 * Right now, since we only deal with per-prefix labels, it is not
57592a53
AD
2818 * necessary to do this upon changes to best path. Exceptions:
2819 * - label index has changed -> recalculate resulting label
2820 * - path_info sub_type changed -> switch to/from implicit-null
2821 * - no valid label (due to removed static label binding) -> get new one
d62a17ae 2822 */
318cac96 2823 if (bgp->allocate_mpls_labels[afi][safi]) {
d62a17ae 2824 if (new_select) {
2825 if (!old_select
2826 || bgp_label_index_differs(new_select, old_select)
57592a53 2827 || new_select->sub_type != old_select->sub_type
9bcb3eef 2828 || !bgp_is_valid_label(&dest->local_label)) {
57592a53
AD
2829 /* Enforced penultimate hop popping:
2830 * implicit-null for local routes, aggregate
2831 * and redistributed routes
2832 */
bb2ca692 2833 if (bgp_lu_need_imp_null(new_select)) {
d62a17ae 2834 if (CHECK_FLAG(
9bcb3eef 2835 dest->flags,
992dd67e
PR
2836 BGP_NODE_REGISTERED_FOR_LABEL)
2837 || CHECK_FLAG(
2838 dest->flags,
2839 BGP_NODE_LABEL_REQUESTED))
9bcb3eef 2840 bgp_unregister_for_label(dest);
70e98a7f 2841 label_ntop(MPLS_LABEL_IMPLICIT_NULL, 1,
9bcb3eef
DS
2842 &dest->local_label);
2843 bgp_set_valid_label(&dest->local_label);
d62a17ae 2844 } else
9bcb3eef
DS
2845 bgp_register_for_label(dest,
2846 new_select);
d62a17ae 2847 }
9bcb3eef 2848 } else if (CHECK_FLAG(dest->flags,
992dd67e
PR
2849 BGP_NODE_REGISTERED_FOR_LABEL)
2850 || CHECK_FLAG(dest->flags,
2851 BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2852 bgp_unregister_for_label(dest);
318cac96 2853 }
992dd67e
PR
2854 } else if (CHECK_FLAG(dest->flags, BGP_NODE_REGISTERED_FOR_LABEL)
2855 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED)) {
9bcb3eef 2856 bgp_unregister_for_label(dest);
d62a17ae 2857 }
cd1964ff 2858
b54892e0 2859 if (debug)
ddb5b488 2860 zlog_debug(
4378495a
DS
2861 "%s: p=%pBD(%s) afi=%s, safi=%s, old_select=%p, new_select=%p",
2862 __func__, dest, bgp->name_pretty, afi2str(afi),
2863 safi2str(safi), old_select, new_select);
ddb5b488 2864
d62a17ae 2865 /* If best route remains the same and this is not due to user-initiated
2866 * clear, see exactly what needs to be done.
2867 */
d62a17ae 2868 if (old_select && old_select == new_select
9bcb3eef 2869 && !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
1defdda8 2870 && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
dcc68b5e 2871 && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
9bcb3eef 2872 if (bgp_zebra_has_route_changed(old_select)) {
49e5a4a0 2873#ifdef ENABLE_BGP_VNC
d62a17ae 2874 vnc_import_bgp_add_route(bgp, p, old_select);
2875 vnc_import_bgp_exterior_add_route(bgp, p, old_select);
65efcfce 2876#endif
bb744275 2877 if (bgp_fibupd_safi(safi)
ddb5b488
PZ
2878 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2879
2880 if (new_select->type == ZEBRA_ROUTE_BGP
2881 && (new_select->sub_type == BGP_ROUTE_NORMAL
2882 || new_select->sub_type
2883 == BGP_ROUTE_IMPORTED))
2884
9bcb3eef 2885 bgp_zebra_announce(dest, p, old_select,
ddb5b488
PZ
2886 bgp, afi, safi);
2887 }
d62a17ae 2888 }
d62a17ae 2889
2890 /* If there is a change of interest to peers, reannounce the
2891 * route. */
1defdda8 2892 if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
b1875e65 2893 || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
9bcb3eef
DS
2894 || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
2895 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2896
2897 /* unicast routes must also be annouced to
2898 * labeled-unicast update-groups */
2899 if (safi == SAFI_UNICAST)
2900 group_announce_route(bgp, afi,
9bcb3eef 2901 SAFI_LABELED_UNICAST, dest,
d62a17ae 2902 new_select);
2903
1defdda8 2904 UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED);
9bcb3eef 2905 UNSET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
d62a17ae 2906 }
fee0f4c6 2907
3b0c17e1 2908 /* advertise/withdraw type-5 routes */
2909 if (CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
2910 || CHECK_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG))
2911 bgp_process_evpn_route_injection(
9bcb3eef 2912 bgp, afi, safi, dest, old_select, old_select);
3b0c17e1 2913
b1875e65 2914 UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
2915 UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
9bcb3eef
DS
2916 bgp_zebra_clear_route_change_flags(dest);
2917 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 2918 return;
d62a17ae 2919 }
8ad7271d 2920
d62a17ae 2921 /* If the user did "clear ip bgp prefix x.x.x.x" this flag will be set
2922 */
9bcb3eef 2923 UNSET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
d62a17ae 2924
2925 /* bestpath has changed; bump version */
2926 if (old_select || new_select) {
9bcb3eef 2927 bgp_bump_version(dest);
d62a17ae 2928
2929 if (!bgp->t_rmap_def_originate_eval) {
2930 bgp_lock(bgp);
2931 thread_add_timer(
2932 bm->master,
2933 update_group_refresh_default_originate_route_map,
2934 bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
2935 &bgp->t_rmap_def_originate_eval);
2936 }
2937 }
3f9c7369 2938
d62a17ae 2939 if (old_select)
9bcb3eef 2940 bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
d62a17ae 2941 if (new_select) {
ddb5b488
PZ
2942 if (debug)
2943 zlog_debug("%s: setting SELECTED flag", __func__);
9bcb3eef
DS
2944 bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
2945 bgp_path_info_unset_flag(dest, new_select,
2946 BGP_PATH_ATTR_CHANGED);
1defdda8 2947 UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG);
b1875e65 2948 UNSET_FLAG(new_select->flags, BGP_PATH_LINK_BW_CHG);
d62a17ae 2949 }
338b3424 2950
49e5a4a0 2951#ifdef ENABLE_BGP_VNC
d62a17ae 2952 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
2953 if (old_select != new_select) {
2954 if (old_select) {
2955 vnc_import_bgp_exterior_del_route(bgp, p,
2956 old_select);
2957 vnc_import_bgp_del_route(bgp, p, old_select);
2958 }
2959 if (new_select) {
2960 vnc_import_bgp_exterior_add_route(bgp, p,
2961 new_select);
2962 vnc_import_bgp_add_route(bgp, p, new_select);
2963 }
2964 }
2965 }
65efcfce
LB
2966#endif
2967
9bcb3eef 2968 group_announce_route(bgp, afi, safi, dest, new_select);
d62a17ae 2969
2970 /* unicast routes must also be annouced to labeled-unicast update-groups
2971 */
2972 if (safi == SAFI_UNICAST)
9bcb3eef 2973 group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
d62a17ae 2974 new_select);
2975
2976 /* FIB update. */
2977 if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
2978 && !bgp_option_check(BGP_OPT_NO_FIB)) {
2979 if (new_select && new_select->type == ZEBRA_ROUTE_BGP
2980 && (new_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488 2981 || new_select->sub_type == BGP_ROUTE_AGGREGATE
2b659f33
MK
2982 || new_select->sub_type == BGP_ROUTE_IMPORTED)) {
2983
2984 /* if this is an evpn imported type-5 prefix,
2985 * we need to withdraw the route first to clear
2986 * the nh neigh and the RMAC entry.
2987 */
2988 if (old_select &&
2989 is_route_parent_evpn(old_select))
2990 bgp_zebra_withdraw(p, old_select, bgp, safi);
ddb5b488 2991
9bcb3eef 2992 bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
2b659f33 2993 } else {
d62a17ae 2994 /* Withdraw the route from the kernel. */
2995 if (old_select && old_select->type == ZEBRA_ROUTE_BGP
2996 && (old_select->sub_type == BGP_ROUTE_NORMAL
ddb5b488
PZ
2997 || old_select->sub_type == BGP_ROUTE_AGGREGATE
2998 || old_select->sub_type == BGP_ROUTE_IMPORTED))
2999
568e10ca 3000 bgp_zebra_withdraw(p, old_select, bgp, safi);
d62a17ae 3001 }
718e3744 3002 }
3064bf43 3003
9bcb3eef 3004 bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
3b0c17e1 3005 old_select);
5424b7ba 3006
d62a17ae 3007 /* Clear any route change flags. */
9bcb3eef 3008 bgp_zebra_clear_route_change_flags(dest);
3064bf43 3009
18ee8310 3010 /* Reap old select bgp_path_info, if it has been removed */
1defdda8 3011 if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED))
9bcb3eef 3012 bgp_path_info_reap(dest, old_select);
d62a17ae 3013
9bcb3eef 3014 UNSET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
aac24838 3015 return;
718e3744 3016}
3017
f009ff26 3018/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
3019int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
3020{
9bcb3eef 3021 struct bgp_dest *dest;
f009ff26 3022 int cnt = 0;
3023 struct afi_safi_info *thread_info;
f009ff26 3024
56c226e7
DS
3025 if (bgp->gr_info[afi][safi].t_route_select) {
3026 struct thread *t = bgp->gr_info[afi][safi].t_route_select;
3027
3028 thread_info = THREAD_ARG(t);
3029 XFREE(MTYPE_TMP, thread_info);
f009ff26 3030 BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
56c226e7 3031 }
f009ff26 3032
3033 if (BGP_DEBUG(update, UPDATE_OUT)) {
36235319
QY
3034 zlog_debug("%s: processing route for %s : cnt %d", __func__,
3035 get_afi_safi_str(afi, safi, false),
26742171 3036 bgp->gr_info[afi][safi].gr_deferred);
f009ff26 3037 }
3038
3039 /* Process the route list */
6338d242
DS
3040 for (dest = bgp_table_top(bgp->rib[afi][safi]);
3041 dest && bgp->gr_info[afi][safi].gr_deferred != 0;
26742171
DS
3042 dest = bgp_route_next(dest)) {
3043 if (!CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER))
3044 continue;
3045
3046 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
3047 bgp->gr_info[afi][safi].gr_deferred--;
3048 bgp_process_main_one(bgp, dest, afi, safi);
3049 cnt++;
3050 if (cnt >= BGP_MAX_BEST_ROUTE_SELECT) {
3051 bgp_dest_unlock_node(dest);
3052 break;
f009ff26 3053 }
f009ff26 3054 }
3055
9e3b51a7 3056 /* Send EOR message when all routes are processed */
6338d242 3057 if (!bgp->gr_info[afi][safi].gr_deferred) {
9e3b51a7 3058 bgp_send_delayed_eor(bgp);
8c48b3b6 3059 /* Send route processing complete message to RIB */
3060 bgp_zebra_update(afi, safi, bgp->vrf_id,
36235319 3061 ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
f009ff26 3062 return 0;
9e3b51a7 3063 }
f009ff26 3064
3065 thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
f009ff26 3066
3067 thread_info->afi = afi;
3068 thread_info->safi = safi;
3069 thread_info->bgp = bgp;
3070
3071 /* If there are more routes to be processed, start the
3072 * selection timer
3073 */
3074 thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
3075 BGP_ROUTE_SELECT_DELAY,
3076 &bgp->gr_info[afi][safi].t_route_select);
f009ff26 3077 return 0;
3078}
3079
aac24838 3080static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
200df115 3081{
aac24838
JB
3082 struct bgp_process_queue *pqnode = data;
3083 struct bgp *bgp = pqnode->bgp;
d62a17ae 3084 struct bgp_table *table;
9bcb3eef 3085 struct bgp_dest *dest;
aac24838
JB
3086
3087 /* eoiu marker */
3088 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)) {
3089 bgp_process_main_one(bgp, NULL, 0, 0);
60466a63
QY
3090 /* should always have dedicated wq call */
3091 assert(STAILQ_FIRST(&pqnode->pqueue) == NULL);
aac24838
JB
3092 return WQ_SUCCESS;
3093 }
3094
ac021f40 3095 while (!STAILQ_EMPTY(&pqnode->pqueue)) {
9bcb3eef 3096 dest = STAILQ_FIRST(&pqnode->pqueue);
ac021f40 3097 STAILQ_REMOVE_HEAD(&pqnode->pqueue, pq);
9bcb3eef
DS
3098 STAILQ_NEXT(dest, pq) = NULL; /* complete unlink */
3099 table = bgp_dest_table(dest);
3100 /* note, new DESTs may be added as part of processing */
3101 bgp_process_main_one(bgp, dest, table->afi, table->safi);
cb1faec9 3102
9bcb3eef 3103 bgp_dest_unlock_node(dest);
d62a17ae 3104 bgp_table_unlock(table);
3105 }
aac24838
JB
3106
3107 return WQ_SUCCESS;
3108}
3109
3110static void bgp_processq_del(struct work_queue *wq, void *data)
3111{
3112 struct bgp_process_queue *pqnode = data;
3113
3114 bgp_unlock(pqnode->bgp);
3115
3116 XFREE(MTYPE_BGP_PROCESS_QUEUE, pqnode);
200df115 3117}
3118
b6c386bb 3119void bgp_process_queue_init(struct bgp *bgp)
200df115 3120{
b6c386bb
DS
3121 if (!bgp->process_queue) {
3122 char name[BUFSIZ];
3123
3124 snprintf(name, BUFSIZ, "process_queue %s", bgp->name_pretty);
3125 bgp->process_queue = work_queue_new(bm->master, name);
3126 }
3127
3128 bgp->process_queue->spec.workfunc = &bgp_process_wq;
3129 bgp->process_queue->spec.del_item_data = &bgp_processq_del;
3130 bgp->process_queue->spec.max_retries = 0;
3131 bgp->process_queue->spec.hold = 50;
d62a17ae 3132 /* Use a higher yield value of 50ms for main queue processing */
b6c386bb 3133 bgp->process_queue->spec.yield = 50 * 1000L;
200df115 3134}
3135
cfe8d15a 3136static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
aac24838
JB
3137{
3138 struct bgp_process_queue *pqnode;
3139
a4d82a8a
PZ
3140 pqnode = XCALLOC(MTYPE_BGP_PROCESS_QUEUE,
3141 sizeof(struct bgp_process_queue));
aac24838
JB
3142
3143 /* unlocked in bgp_processq_del */
3144 pqnode->bgp = bgp_lock(bgp);
3145 STAILQ_INIT(&pqnode->pqueue);
3146
aac24838
JB
3147 return pqnode;
3148}
3149
9bcb3eef 3150void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
fee0f4c6 3151{
aac24838 3152#define ARBITRARY_PROCESS_QLEN 10000
b6c386bb 3153 struct work_queue *wq = bgp->process_queue;
d62a17ae 3154 struct bgp_process_queue *pqnode;
cfe8d15a 3155 int pqnode_reuse = 0;
495f0b13 3156
d62a17ae 3157 /* already scheduled for processing? */
9bcb3eef 3158 if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
d62a17ae 3159 return;
2e02b9b2 3160
f009ff26 3161 /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
3162 * the workqueue
3163 */
9bcb3eef 3164 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
f009ff26 3165 if (BGP_DEBUG(update, UPDATE_OUT))
3166 zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
9bcb3eef 3167 dest);
f009ff26 3168 return;
3169 }
3170
46aeabed
LS
3171 if (CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG)) {
3172 if (BGP_DEBUG(update, UPDATE_OUT))
3173 zlog_debug(
3174 "Soft reconfigure table in progress for route %p",
3175 dest);
3176 return;
3177 }
3178
aac24838 3179 if (wq == NULL)
d62a17ae 3180 return;
3181
aac24838 3182 /* Add route nodes to an existing work queue item until reaching the
a4d82a8a
PZ
3183 limit only if is from the same BGP view and it's not an EOIU marker
3184 */
aac24838
JB
3185 if (work_queue_item_count(wq)) {
3186 struct work_queue_item *item = work_queue_last_item(wq);
3187 pqnode = item->data;
228da428 3188
a4d82a8a
PZ
3189 if (CHECK_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER)
3190 || pqnode->bgp != bgp
3191 || pqnode->queued >= ARBITRARY_PROCESS_QLEN)
cfe8d15a
LB
3192 pqnode = bgp_processq_alloc(bgp);
3193 else
3194 pqnode_reuse = 1;
aac24838 3195 } else
cfe8d15a 3196 pqnode = bgp_processq_alloc(bgp);
aac24838 3197 /* all unlocked in bgp_process_wq */
9bcb3eef 3198 bgp_table_lock(bgp_dest_table(dest));
aac24838 3199
9bcb3eef
DS
3200 SET_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED);
3201 bgp_dest_lock_node(dest);
aac24838 3202
60466a63 3203 /* can't be enqueued twice */
9bcb3eef
DS
3204 assert(STAILQ_NEXT(dest, pq) == NULL);
3205 STAILQ_INSERT_TAIL(&pqnode->pqueue, dest, pq);
aac24838
JB
3206 pqnode->queued++;
3207
cfe8d15a
LB
3208 if (!pqnode_reuse)
3209 work_queue_add(wq, pqnode);
3210
d62a17ae 3211 return;
fee0f4c6 3212}
0a486e5f 3213
d62a17ae 3214void bgp_add_eoiu_mark(struct bgp *bgp)
cb1faec9 3215{
d62a17ae 3216 struct bgp_process_queue *pqnode;
cb1faec9 3217
b6c386bb 3218 if (bgp->process_queue == NULL)
d62a17ae 3219 return;
2e02b9b2 3220
cfe8d15a 3221 pqnode = bgp_processq_alloc(bgp);
cb1faec9 3222
aac24838 3223 SET_FLAG(pqnode->flags, BGP_PROCESS_QUEUE_EOIU_MARKER);
b6c386bb 3224 work_queue_add(bgp->process_queue, pqnode);
cb1faec9
DS
3225}
3226
d62a17ae 3227static int bgp_maximum_prefix_restart_timer(struct thread *thread)
0a486e5f 3228{
d62a17ae 3229 struct peer *peer;
0a486e5f 3230
d62a17ae 3231 peer = THREAD_ARG(thread);
3232 peer->t_pmax_restart = NULL;
0a486e5f 3233
d62a17ae 3234 if (bgp_debug_neighbor_events(peer))
3235 zlog_debug(
3236 "%s Maximum-prefix restart timer expired, restore peering",
3237 peer->host);
0a486e5f 3238
a9bafa95 3239 if ((peer_clear(peer, NULL) < 0) && bgp_debug_neighbor_events(peer))
15569c58 3240 zlog_debug("%s: %s peer_clear failed", __func__, peer->host);
0a486e5f 3241
d62a17ae 3242 return 0;
0a486e5f 3243}
3244
9cbd06e0
DA
3245static uint32_t bgp_filtered_routes_count(struct peer *peer, afi_t afi,
3246 safi_t safi)
3247{
3248 uint32_t count = 0;
f41b0459 3249 bool filtered = false;
9cbd06e0
DA
3250 struct bgp_dest *dest;
3251 struct bgp_adj_in *ain;
40bb2ccf 3252 struct attr attr = {};
9cbd06e0
DA
3253 struct bgp_table *table = peer->bgp->rib[afi][safi];
3254
3255 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
3256 for (ain = dest->adj_in; ain; ain = ain->next) {
3257 const struct prefix *rn_p = bgp_dest_get_prefix(dest);
40bb2ccf
DA
3258
3259 attr = *ain->attr;
9cbd06e0
DA
3260
3261 if (bgp_input_filter(peer, rn_p, &attr, afi, safi)
3262 == FILTER_DENY)
f41b0459
DA
3263 filtered = true;
3264
3265 if (bgp_input_modifier(
3266 peer, rn_p, &attr, afi, safi,
3267 ROUTE_MAP_IN_NAME(&peer->filter[afi][safi]),
3268 NULL, 0, NULL)
3269 == RMAP_DENY)
3270 filtered = true;
3271
3272 if (filtered)
9cbd06e0 3273 count++;
f41b0459
DA
3274
3275 bgp_attr_undup(&attr, ain->attr);
9cbd06e0
DA
3276 }
3277 }
3278
3279 return count;
3280}
3281
3dc339cd
DA
3282bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
3283 int always)
718e3744 3284{
d62a17ae 3285 iana_afi_t pkt_afi;
5c525538 3286 iana_safi_t pkt_safi;
9cbd06e0
DA
3287 uint32_t pcount = (CHECK_FLAG(peer->af_flags[afi][safi],
3288 PEER_FLAG_MAX_PREFIX_FORCE))
3289 ? bgp_filtered_routes_count(peer, afi, safi)
3290 + peer->pcount[afi][safi]
3291 : peer->pcount[afi][safi];
9cabb64b 3292
d62a17ae 3293 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
3dc339cd 3294 return false;
e0701b79 3295
9cbd06e0 3296 if (pcount > peer->pmax[afi][safi]) {
d62a17ae 3297 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3298 PEER_STATUS_PREFIX_LIMIT)
3299 && !always)
3dc339cd 3300 return false;
e0701b79 3301
d62a17ae 3302 zlog_info(
6cde4b45 3303 "%%MAXPFXEXCEED: No. of %s prefix received from %s %u exceed, limit %u",
9cbd06e0
DA
3304 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3305 peer->pmax[afi][safi]);
d62a17ae 3306 SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
3307
3308 if (CHECK_FLAG(peer->af_flags[afi][safi],
3309 PEER_FLAG_MAX_PREFIX_WARNING))
3dc339cd 3310 return false;
d62a17ae 3311
3312 /* Convert AFI, SAFI to values for packet. */
3313 pkt_afi = afi_int2iana(afi);
3314 pkt_safi = safi_int2iana(safi);
3315 {
d7c0a89a 3316 uint8_t ndata[7];
d62a17ae 3317
3318 ndata[0] = (pkt_afi >> 8);
3319 ndata[1] = pkt_afi;
3320 ndata[2] = pkt_safi;
3321 ndata[3] = (peer->pmax[afi][safi] >> 24);
3322 ndata[4] = (peer->pmax[afi][safi] >> 16);
3323 ndata[5] = (peer->pmax[afi][safi] >> 8);
3324 ndata[6] = (peer->pmax[afi][safi]);
3325
3326 SET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3327 bgp_notify_send_with_data(peer, BGP_NOTIFY_CEASE,
3328 BGP_NOTIFY_CEASE_MAX_PREFIX,
3329 ndata, 7);
3330 }
3331
3332 /* Dynamic peers will just close their connection. */
3333 if (peer_dynamic_neighbor(peer))
3dc339cd 3334 return true;
d62a17ae 3335
3336 /* restart timer start */
3337 if (peer->pmax_restart[afi][safi]) {
3338 peer->v_pmax_restart =
3339 peer->pmax_restart[afi][safi] * 60;
3340
3341 if (bgp_debug_neighbor_events(peer))
3342 zlog_debug(
3343 "%s Maximum-prefix restart timer started for %d secs",
3344 peer->host, peer->v_pmax_restart);
3345
3346 BGP_TIMER_ON(peer->t_pmax_restart,
3347 bgp_maximum_prefix_restart_timer,
3348 peer->v_pmax_restart);
3349 }
3350
3dc339cd 3351 return true;
d62a17ae 3352 } else
3353 UNSET_FLAG(peer->af_sflags[afi][safi],
3354 PEER_STATUS_PREFIX_LIMIT);
3355
b1823b69
DS
3356 if (pcount
3357 > (peer->pmax[afi][safi] * peer->pmax_threshold[afi][safi] / 100)) {
d62a17ae 3358 if (CHECK_FLAG(peer->af_sflags[afi][safi],
3359 PEER_STATUS_PREFIX_THRESHOLD)
3360 && !always)
3dc339cd 3361 return false;
d62a17ae 3362
3363 zlog_info(
6cde4b45 3364 "%%MAXPFX: No. of %s prefix received from %s reaches %u, max %u",
9cbd06e0
DA
3365 get_afi_safi_str(afi, safi, false), peer->host, pcount,
3366 peer->pmax[afi][safi]);
d62a17ae 3367 SET_FLAG(peer->af_sflags[afi][safi],
3368 PEER_STATUS_PREFIX_THRESHOLD);
3369 } else
3370 UNSET_FLAG(peer->af_sflags[afi][safi],
3371 PEER_STATUS_PREFIX_THRESHOLD);
3dc339cd 3372 return false;
718e3744 3373}
3374
b40d939b 3375/* Unconditionally remove the route from the RIB, without taking
3376 * damping into consideration (eg, because the session went down)
3377 */
9bcb3eef 3378void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
4b7e6066 3379 struct peer *peer, afi_t afi, safi_t safi)
718e3744 3380{
f009ff26 3381
3382 struct bgp *bgp = NULL;
3383 bool delete_route = false;
3384
9bcb3eef
DS
3385 bgp_aggregate_decrement(peer->bgp, bgp_dest_get_prefix(dest), pi, afi,
3386 safi);
d62a17ae 3387
f009ff26 3388 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 3389 bgp_path_info_delete(dest, pi); /* keep historical info */
d62a17ae 3390
f009ff26 3391 /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
3392 * flag
3393 */
3394 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3395 delete_route = true;
9bcb3eef 3396 else if (bgp_dest_set_defer_flag(dest, true) < 0)
36235319 3397 delete_route = true;
f009ff26 3398 if (delete_route) {
9bcb3eef
DS
3399 if (CHECK_FLAG(dest->flags, BGP_NODE_SELECT_DEFER)) {
3400 UNSET_FLAG(dest->flags, BGP_NODE_SELECT_DEFER);
f009ff26 3401 bgp = pi->peer->bgp;
26742171 3402 bgp->gr_info[afi][safi].gr_deferred--;
f009ff26 3403 }
3404 }
3405 }
4a11bf2c 3406
9bcb3eef
DS
3407 hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
3408 bgp_process(peer->bgp, dest, afi, safi);
d62a17ae 3409}
3410
9bcb3eef 3411static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
d62a17ae 3412 struct peer *peer, afi_t afi, safi_t safi,
3413 struct prefix_rd *prd)
3414{
9bcb3eef 3415 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 3416
d62a17ae 3417 /* apply dampening, if result is suppressed, we'll be retaining
18ee8310 3418 * the bgp_path_info in the RIB for historical reference.
d62a17ae 3419 */
b4f7f45b
IR
3420 if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
3421 && peer->sort == BGP_PEER_EBGP)
3422 if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
3423 == BGP_DAMP_SUPPRESSED) {
3424 bgp_aggregate_decrement(peer->bgp, p, pi, afi,
3425 safi);
3426 return;
d62a17ae 3427 }
3428
49e5a4a0 3429#ifdef ENABLE_BGP_VNC
d62a17ae 3430 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3431 struct bgp_dest *pdest = NULL;
d62a17ae 3432 struct bgp_table *table = NULL;
3433
9bcb3eef
DS
3434 pdest = bgp_node_get(peer->bgp->rib[afi][safi],
3435 (struct prefix *)prd);
3436 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3437 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3438
3439 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
b54892e0 3440 peer->bgp, prd, table, p, pi);
d62a17ae 3441 }
9bcb3eef 3442 bgp_dest_unlock_node(pdest);
d62a17ae 3443 }
3444 if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
40381db7 3445 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
65efcfce 3446
b54892e0
DS
3447 vnc_import_bgp_del_route(peer->bgp, p, pi);
3448 vnc_import_bgp_exterior_del_route(peer->bgp, p, pi);
d62a17ae 3449 }
65efcfce 3450 }
d62a17ae 3451#endif
128ea8ab 3452
d62a17ae 3453 /* If this is an EVPN route, process for un-import. */
3454 if (safi == SAFI_EVPN)
b54892e0 3455 bgp_evpn_unimport_route(peer->bgp, afi, safi, p, pi);
128ea8ab 3456
9bcb3eef 3457 bgp_rib_remove(dest, pi, peer, afi, safi);
718e3744 3458}
3459
4b7e6066
DS
3460struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
3461 struct peer *peer, struct attr *attr,
9bcb3eef 3462 struct bgp_dest *dest)
fb018d25 3463{
4b7e6066 3464 struct bgp_path_info *new;
fb018d25 3465
d62a17ae 3466 /* Make new BGP info. */
4b7e6066 3467 new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info));
d62a17ae 3468 new->type = type;
3469 new->instance = instance;
3470 new->sub_type = sub_type;
3471 new->peer = peer;
3472 new->attr = attr;
3473 new->uptime = bgp_clock();
9bcb3eef 3474 new->net = dest;
d62a17ae 3475 return new;
fb018d25
DS
3476}
3477
40381db7 3478static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
d62a17ae 3479 union gw_addr *gw_ip)
3480{
6c924775
DS
3481 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
3482 union gw_addr path_gw_ip, *path_gw_ip_remote;
11ebf4ed 3483 union {
0a50c248 3484 esi_t esi;
11ebf4ed
DS
3485 union gw_addr ip;
3486 } temp;
d62a17ae 3487
3488 if (afi != AFI_L2VPN)
3489 return true;
11ebf4ed 3490
6c924775 3491 path_gw_ip = eo->gw_ip;
11ebf4ed
DS
3492
3493 if (gw_ip == NULL) {
3494 memset(&temp, 0, sizeof(temp));
40381db7 3495 path_gw_ip_remote = &temp.ip;
11ebf4ed 3496 } else
40381db7 3497 path_gw_ip_remote = gw_ip;
11ebf4ed 3498
6c924775 3499 return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
684a7227
PG
3500}
3501
c265ee22 3502/* Check if received nexthop is valid or not. */
e7cbe5e5
NT
3503bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
3504 uint8_t type, uint8_t stype, struct attr *attr,
9bcb3eef 3505 struct bgp_dest *dest)
d62a17ae 3506{
2dbe3fa9 3507 bool ret = false;
b099a5c8
DA
3508 bool is_bgp_static_route =
3509 (type == ZEBRA_ROUTE_BGP && stype == BGP_ROUTE_STATIC) ? true
3510 : false;
d62a17ae 3511
e8442016
DS
3512 /*
3513 * Only validated for unicast and multicast currently.
3514 * Also valid for EVPN where the nexthop is an IP address.
3515 * If we are a bgp static route being checked then there is
3516 * no need to check to see if the nexthop is martian as
3517 * that it should be ok.
3518 */
3519 if (is_bgp_static_route ||
3520 (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN))
3dc339cd 3521 return false;
d62a17ae 3522
3523 /* If NEXT_HOP is present, validate it. */
3524 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
e8442016 3525 if (attr->nexthop.s_addr == INADDR_ANY
d62a17ae 3526 || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
9bcb3eef 3527 || bgp_nexthop_self(bgp, afi, type, stype, attr, dest))
3dc339cd 3528 return true;
d62a17ae 3529 }
c265ee22 3530
d62a17ae 3531 /* If MP_NEXTHOP is present, validate it. */
3532 /* Note: For IPv6 nexthops, we only validate the global (1st) nexthop;
3533 * there is code in bgp_attr.c to ignore the link-local (2nd) nexthop if
3534 * it is not an IPv6 link-local address.
0355b41d
DA
3535 *
3536 * If we receive an UPDATE with nexthop length set to 32 bytes
3537 * we shouldn't discard an UPDATE if it's set to (::).
3538 * The link-local (2st) is validated along the code path later.
d62a17ae 3539 */
3540 if (attr->mp_nexthop_len) {
3541 switch (attr->mp_nexthop_len) {
3542 case BGP_ATTR_NHLEN_IPV4:
3543 case BGP_ATTR_NHLEN_VPNV4:
e8442016 3544 ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
975a328e
DA
3545 || IPV4_CLASS_DE(
3546 ntohl(attr->mp_nexthop_global_in.s_addr))
3547 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3548 dest));
d62a17ae 3549 break;
3550
3551 case BGP_ATTR_NHLEN_IPV6_GLOBAL:
d62a17ae 3552 case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
e8442016 3553 ret = (IN6_IS_ADDR_UNSPECIFIED(
b099a5c8 3554 &attr->mp_nexthop_global)
d62a17ae 3555 || IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3556 || IN6_IS_ADDR_MULTICAST(
b099a5c8
DA
3557 &attr->mp_nexthop_global)
3558 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3559 dest));
d62a17ae 3560 break;
0355b41d
DA
3561 case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
3562 ret = (IN6_IS_ADDR_LOOPBACK(&attr->mp_nexthop_global)
3563 || IN6_IS_ADDR_MULTICAST(
3564 &attr->mp_nexthop_global)
3565 || bgp_nexthop_self(bgp, afi, type, stype, attr,
9bcb3eef 3566 dest));
0355b41d 3567 break;
d62a17ae 3568
3569 default:
3dc339cd 3570 ret = true;
d62a17ae 3571 break;
3572 }
3573 }
c265ee22 3574
d62a17ae 3575 return ret;
3576}
3577
aade37d7 3578static void bgp_attr_add_no_export_community(struct attr *attr)
2721dd61
DA
3579{
3580 struct community *old;
3581 struct community *new;
3582 struct community *merge;
aade37d7 3583 struct community *no_export;
2721dd61
DA
3584
3585 old = attr->community;
aade37d7 3586 no_export = community_str2com("no-export");
2721dd61 3587
b4efa101
DA
3588 assert(no_export);
3589
2721dd61 3590 if (old) {
aade37d7 3591 merge = community_merge(community_dup(old), no_export);
2721dd61
DA
3592
3593 if (!old->refcnt)
3594 community_free(&old);
3595
3596 new = community_uniq_sort(merge);
3597 community_free(&merge);
3598 } else {
aade37d7 3599 new = community_dup(no_export);
2721dd61
DA
3600 }
3601
aade37d7 3602 community_free(&no_export);
2721dd61
DA
3603
3604 attr->community = new;
3605 attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
3606}
3607
5a1ae2c2 3608int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 3609 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 3610 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 3611 uint32_t num_labels, int soft_reconfig,
a4d82a8a 3612 struct bgp_route_evpn *evpn)
d62a17ae 3613{
3614 int ret;
3615 int aspath_loop_count = 0;
9bcb3eef 3616 struct bgp_dest *dest;
d62a17ae 3617 struct bgp *bgp;
3618 struct attr new_attr;
3619 struct attr *attr_new;
40381db7 3620 struct bgp_path_info *pi;
4b7e6066
DS
3621 struct bgp_path_info *new;
3622 struct bgp_path_info_extra *extra;
d62a17ae 3623 const char *reason;
3624 char pfx_buf[BGP_PRD_PATH_STRLEN];
d62a17ae 3625 int connected = 0;
3626 int do_loop_check = 1;
3627 int has_valid_label = 0;
7c312383 3628 afi_t nh_afi;
949b0f24 3629 uint8_t pi_type = 0;
3630 uint8_t pi_sub_type = 0;
9146341f 3631 bool force_evpn_import = false;
949b0f24 3632
c7bb4f00 3633 if (frrtrace_enabled(frr_bgp, process_update)) {
6401252f
QY
3634 char pfxprint[PREFIX2STR_BUFFER];
3635
3636 prefix2str(p, pfxprint, sizeof(pfxprint));
c7bb4f00
QY
3637 frrtrace(6, frr_bgp, process_update, peer, pfxprint, addpath_id,
3638 afi, safi, attr);
6401252f
QY
3639 }
3640
49e5a4a0 3641#ifdef ENABLE_BGP_VNC
d62a17ae 3642 int vnc_implicit_withdraw = 0;
65efcfce 3643#endif
d62a17ae 3644 int same_attr = 0;
718e3744 3645
d62a17ae 3646 memset(&new_attr, 0, sizeof(struct attr));
3647 new_attr.label_index = BGP_INVALID_LABEL_INDEX;
3648 new_attr.label = MPLS_INVALID_LABEL;
f9a3a260 3649
d62a17ae 3650 bgp = peer->bgp;
9bcb3eef 3651 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
b57ba6d2
MK
3652 /* TODO: Check to see if we can get rid of "is_valid_label" */
3653 if (afi == AFI_L2VPN && safi == SAFI_EVPN)
3654 has_valid_label = (num_labels > 0) ? 1 : 0;
3655 else
3656 has_valid_label = bgp_is_valid_label(label);
718e3744 3657
28f66de2
MS
3658 if (has_valid_label)
3659 assert(label != NULL);
3660
66ff6089
AD
3661 /* Update overlay index of the attribute */
3662 if (afi == AFI_L2VPN && evpn)
3663 memcpy(&attr->evpn_overlay, evpn,
3664 sizeof(struct bgp_route_evpn));
3665
d62a17ae 3666 /* When peer's soft reconfiguration enabled. Record input packet in
3667 Adj-RIBs-In. */
3668 if (!soft_reconfig
3669 && CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
3670 && peer != bgp->peer_self)
9bcb3eef 3671 bgp_adj_in_set(dest, peer, attr, addpath_id);
d62a17ae 3672
3673 /* Check previously received route. */
9bcb3eef 3674 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
3675 if (pi->peer == peer && pi->type == type
3676 && pi->sub_type == sub_type
3677 && pi->addpath_rx_id == addpath_id)
d62a17ae 3678 break;
3679
3680 /* AS path local-as loop check. */
3681 if (peer->change_local_as) {
c4368918
DW
3682 if (peer->allowas_in[afi][safi])
3683 aspath_loop_count = peer->allowas_in[afi][safi];
a4d82a8a
PZ
3684 else if (!CHECK_FLAG(peer->flags,
3685 PEER_FLAG_LOCAL_AS_NO_PREPEND))
d62a17ae 3686 aspath_loop_count = 1;
3687
3688 if (aspath_loop_check(attr->aspath, peer->change_local_as)
3689 > aspath_loop_count) {
b4d46cc9 3690 peer->stat_pfx_aspath_loop++;
692174a1 3691 reason = "as-path contains our own AS;";
d62a17ae 3692 goto filtered;
3693 }
718e3744 3694 }
718e3744 3695
d62a17ae 3696 /* If the peer is configured for "allowas-in origin" and the last ASN in
3697 * the
3698 * as-path is our ASN then we do not need to call aspath_loop_check
3699 */
3700 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN_ORIGIN))
3701 if (aspath_get_last_as(attr->aspath) == bgp->as)
3702 do_loop_check = 0;
3703
3704 /* AS path loop check. */
3705 if (do_loop_check) {
3706 if (aspath_loop_check(attr->aspath, bgp->as)
3707 > peer->allowas_in[afi][safi]
3708 || (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)
3709 && aspath_loop_check(attr->aspath, bgp->confed_id)
3710 > peer->allowas_in[afi][safi])) {
b4d46cc9 3711 peer->stat_pfx_aspath_loop++;
d62a17ae 3712 reason = "as-path contains our own AS;";
3713 goto filtered;
3714 }
3715 }
aac9ef6c 3716
d62a17ae 3717 /* Route reflector originator ID check. */
3718 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)
3719 && IPV4_ADDR_SAME(&bgp->router_id, &attr->originator_id)) {
b4d46cc9 3720 peer->stat_pfx_originator_loop++;
d62a17ae 3721 reason = "originator is us;";
3722 goto filtered;
3723 }
718e3744 3724
d62a17ae 3725 /* Route reflector cluster ID check. */
3726 if (bgp_cluster_filter(peer, attr)) {
b4d46cc9 3727 peer->stat_pfx_cluster_loop++;
d62a17ae 3728 reason = "reflected from the same cluster;";
3729 goto filtered;
3730 }
718e3744 3731
d62a17ae 3732 /* Apply incoming filter. */
3733 if (bgp_input_filter(peer, p, attr, afi, safi) == FILTER_DENY) {
b4d46cc9 3734 peer->stat_pfx_filter++;
d62a17ae 3735 reason = "filter;";
3736 goto filtered;
3737 }
718e3744 3738
a8b72dc6
DA
3739 /* RFC 8212 to prevent route leaks.
3740 * This specification intends to improve this situation by requiring the
3741 * explicit configuration of both BGP Import and Export Policies for any
3742 * External BGP (EBGP) session such as customers, peers, or
3743 * confederation boundaries for all enabled address families. Through
3744 * codification of the aforementioned requirement, operators will
3745 * benefit from consistent behavior across different BGP
3746 * implementations.
3747 */
1d3fdccf 3748 if (CHECK_FLAG(bgp->flags, BGP_FLAG_EBGP_REQUIRES_POLICY))
a8b72dc6
DA
3749 if (!bgp_inbound_policy_exists(peer,
3750 &peer->filter[afi][safi])) {
3751 reason = "inbound policy missing";
3752 goto filtered;
3753 }
3754
fb29348a
DA
3755 /* draft-ietf-idr-deprecate-as-set-confed-set
3756 * Filter routes having AS_SET or AS_CONFED_SET in the path.
3757 * Eventually, This document (if approved) updates RFC 4271
3758 * and RFC 5065 by eliminating AS_SET and AS_CONFED_SET types,
3759 * and obsoletes RFC 6472.
3760 */
7f972cd8 3761 if (peer->bgp->reject_as_sets)
fb29348a
DA
3762 if (aspath_check_as_sets(attr->aspath)) {
3763 reason =
3764 "as-path contains AS_SET or AS_CONFED_SET type;";
3765 goto filtered;
3766 }
3767
6f4f49b2 3768 new_attr = *attr;
d62a17ae 3769
3770 /* Apply incoming route-map.
3771 * NB: new_attr may now contain newly allocated values from route-map
3772 * "set"
3773 * commands, so we need bgp_attr_flush in the error paths, until we
3774 * intern
3775 * the attr (which takes over the memory references) */
9bcb3eef
DS
3776 if (bgp_input_modifier(peer, p, &new_attr, afi, safi, NULL, label,
3777 num_labels, dest)
3778 == RMAP_DENY) {
b4d46cc9 3779 peer->stat_pfx_filter++;
d62a17ae 3780 reason = "route-map;";
3781 bgp_attr_flush(&new_attr);
3782 goto filtered;
3783 }
718e3744 3784
05864da7 3785 if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
1276ce38
PG
3786 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
3787 /* remove from RIB previous entry */
3788 bgp_zebra_withdraw(p, pi, bgp, safi);
3789 }
3790
7f323236
DW
3791 if (peer->sort == BGP_PEER_EBGP) {
3792
2721dd61
DA
3793 /* rfc7999:
3794 * A BGP speaker receiving an announcement tagged with the
3795 * BLACKHOLE community SHOULD add the NO_ADVERTISE or
3796 * NO_EXPORT community as defined in RFC1997, or a
3797 * similar community, to prevent propagation of the
3798 * prefix outside the local AS. The community to prevent
3799 * propagation SHOULD be chosen according to the operator's
3800 * routing policy.
3801 */
3802 if (new_attr.community
3803 && community_include(new_attr.community,
3804 COMMUNITY_BLACKHOLE))
aade37d7 3805 bgp_attr_add_no_export_community(&new_attr);
2721dd61 3806
a4d82a8a
PZ
3807 /* If we receive the graceful-shutdown community from an eBGP
3808 * peer we must lower local-preference */
3809 if (new_attr.community
3810 && community_include(new_attr.community, COMMUNITY_GSHUT)) {
7f323236
DW
3811 new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
3812 new_attr.local_pref = BGP_GSHUT_LOCAL_PREF;
3813
a4d82a8a
PZ
3814 /* If graceful-shutdown is configured then add the GSHUT
3815 * community to all paths received from eBGP peers */
637e5ba4 3816 } else if (bgp_in_graceful_shutdown(peer->bgp))
7f323236 3817 bgp_attr_add_gshut_community(&new_attr);
7f323236
DW
3818 }
3819
949b0f24 3820 if (pi) {
3821 pi_type = pi->type;
3822 pi_sub_type = pi->sub_type;
3823 }
3824
d62a17ae 3825 /* next hop check. */
a4d82a8a 3826 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
9bcb3eef
DS
3827 && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
3828 &new_attr, dest)) {
b4d46cc9 3829 peer->stat_pfx_nh_invalid++;
d62a17ae 3830 reason = "martian or self next-hop;";
3831 bgp_attr_flush(&new_attr);
3832 goto filtered;
3833 }
718e3744 3834
5c14a191 3835 if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
b4d46cc9 3836 peer->stat_pfx_nh_invalid++;
4e802e66
DS
3837 reason = "self mac;";
3838 goto filtered;
3839 }
3840
a1b773e2
DS
3841 /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
3842 * condition :
3843 * Suppress fib is enabled
3844 * BGP_OPT_NO_FIB is not enabled
3845 * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
3846 * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
3847 */
3848 if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
3849 && (sub_type == BGP_ROUTE_NORMAL)
3850 && (!bgp_option_check(BGP_OPT_NO_FIB))
3851 && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
3852 SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
3853
d62a17ae 3854 attr_new = bgp_attr_intern(&new_attr);
3855
9cbd06e0
DA
3856 /* If maximum prefix count is configured and current prefix
3857 * count exeed it.
3858 */
3859 if (bgp_maximum_prefix_overflow(peer, afi, safi, 0))
3860 return -1;
3861
d62a17ae 3862 /* If the update is implicit withdraw. */
40381db7
DS
3863 if (pi) {
3864 pi->uptime = bgp_clock();
3865 same_attr = attrhash_cmp(pi->attr, attr_new);
d62a17ae 3866
9bcb3eef 3867 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 3868
d62a17ae 3869 /* Same attribute comes in. */
40381db7 3870 if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
aeadbd9e 3871 && same_attr
d62a17ae 3872 && (!has_valid_label
40381db7 3873 || memcmp(&(bgp_path_info_extra_get(pi))->label, label,
b57ba6d2 3874 num_labels * sizeof(mpls_label_t))
66ff6089 3875 == 0)) {
b4f7f45b
IR
3876 if (CHECK_FLAG(bgp->af_flags[afi][safi],
3877 BGP_CONFIG_DAMPENING)
d62a17ae 3878 && peer->sort == BGP_PEER_EBGP
40381db7 3879 && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
d62a17ae 3880 if (bgp_debug_update(peer, p, NULL, 1)) {
3881 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3882 afi, safi, prd, p, label,
3883 num_labels, addpath_id ? 1 : 0,
66ff6089 3884 addpath_id, evpn, pfx_buf,
a4d82a8a 3885 sizeof(pfx_buf));
d62a17ae 3886 zlog_debug("%s rcvd %s", peer->host,
3887 pfx_buf);
3888 }
3889
9bcb3eef 3890 if (bgp_damp_update(pi, dest, afi, safi)
d62a17ae 3891 != BGP_DAMP_SUPPRESSED) {
40381db7 3892 bgp_aggregate_increment(bgp, p, pi, afi,
d62a17ae 3893 safi);
9bcb3eef 3894 bgp_process(bgp, dest, afi, safi);
d62a17ae 3895 }
3896 } else /* Duplicate - odd */
3897 {
3898 if (bgp_debug_update(peer, p, NULL, 1)) {
3899 if (!peer->rcvd_attr_printed) {
3900 zlog_debug(
3901 "%s rcvd UPDATE w/ attr: %s",
3902 peer->host,
3903 peer->rcvd_attr_str);
3904 peer->rcvd_attr_printed = 1;
3905 }
3906
3907 bgp_debug_rdpfxpath2str(
a4d82a8a
PZ
3908 afi, safi, prd, p, label,
3909 num_labels, addpath_id ? 1 : 0,
66ff6089 3910 addpath_id, evpn, pfx_buf,
a4d82a8a 3911 sizeof(pfx_buf));
d62a17ae 3912 zlog_debug(
3913 "%s rcvd %s...duplicate ignored",
3914 peer->host, pfx_buf);
3915 }
3916
3917 /* graceful restart STALE flag unset. */
40381db7 3918 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
18ee8310 3919 bgp_path_info_unset_flag(
9bcb3eef
DS
3920 dest, pi, BGP_PATH_STALE);
3921 bgp_dest_set_defer_flag(dest, false);
3922 bgp_process(bgp, dest, afi, safi);
d62a17ae 3923 }
3924 }
3925
9bcb3eef 3926 bgp_dest_unlock_node(dest);
d62a17ae 3927 bgp_attr_unintern(&attr_new);
3928
3929 return 0;
3930 }
718e3744 3931
d62a17ae 3932 /* Withdraw/Announce before we fully processed the withdraw */
40381db7 3933 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
d62a17ae 3934 if (bgp_debug_update(peer, p, NULL, 1)) {
3935 bgp_debug_rdpfxpath2str(
a4d82a8a 3936 afi, safi, prd, p, label, num_labels,
66ff6089 3937 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 3938 pfx_buf, sizeof(pfx_buf));
d62a17ae 3939 zlog_debug(
3940 "%s rcvd %s, flapped quicker than processing",
3941 peer->host, pfx_buf);
3942 }
3943
9bcb3eef 3944 bgp_path_info_restore(dest, pi);
9146341f 3945
3946 /*
3947 * If the BGP_PATH_REMOVED flag is set, then EVPN
3948 * routes would have been unimported already when a
3949 * prior BGP withdraw processing happened. Such routes
3950 * need to be imported again, so flag accordingly.
3951 */
3952 force_evpn_import = true;
d62a17ae 3953 }
718e3744 3954
d62a17ae 3955 /* Received Logging. */
3956 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a
PZ
3957 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label,
3958 num_labels, addpath_id ? 1 : 0,
66ff6089 3959 addpath_id, evpn, pfx_buf,
a4d82a8a 3960 sizeof(pfx_buf));
d62a17ae 3961 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
3962 }
718e3744 3963
d62a17ae 3964 /* graceful restart STALE flag unset. */
f009ff26 3965 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
9bcb3eef
DS
3966 bgp_path_info_unset_flag(dest, pi, BGP_PATH_STALE);
3967 bgp_dest_set_defer_flag(dest, false);
f009ff26 3968 }
d62a17ae 3969
3970 /* The attribute is changed. */
9bcb3eef 3971 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 3972
3973 /* implicit withdraw, decrement aggregate and pcount here.
3974 * only if update is accepted, they'll increment below.
3975 */
40381db7 3976 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
d62a17ae 3977
3978 /* Update bgp route dampening information. */
b4f7f45b 3979 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 3980 && peer->sort == BGP_PEER_EBGP) {
3981 /* This is implicit withdraw so we should update
b4f7f45b
IR
3982 dampening
3983 information. */
40381db7 3984 if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
9bcb3eef 3985 bgp_damp_withdraw(pi, dest, afi, safi, 1);
d62a17ae 3986 }
49e5a4a0 3987#ifdef ENABLE_BGP_VNC
d62a17ae 3988 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 3989 struct bgp_dest *pdest = NULL;
d62a17ae 3990 struct bgp_table *table = NULL;
3991
9bcb3eef
DS
3992 pdest = bgp_node_get(bgp->rib[afi][safi],
3993 (struct prefix *)prd);
3994 if (bgp_dest_has_bgp_path_info_data(pdest)) {
3995 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 3996
3997 vnc_import_bgp_del_vnc_host_route_mode_resolve_nve(
40381db7 3998 bgp, prd, table, p, pi);
d62a17ae 3999 }
9bcb3eef 4000 bgp_dest_unlock_node(pdest);
d62a17ae 4001 }
4002 if ((afi == AFI_IP || afi == AFI_IP6)
4003 && (safi == SAFI_UNICAST)) {
40381db7 4004 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 4005 /*
4006 * Implicit withdraw case.
4007 */
4008 ++vnc_implicit_withdraw;
40381db7
DS
4009 vnc_import_bgp_del_route(bgp, p, pi);
4010 vnc_import_bgp_exterior_del_route(bgp, p, pi);
d62a17ae 4011 }
4012 }
65efcfce 4013#endif
128ea8ab 4014
d62a17ae 4015 /* Special handling for EVPN update of an existing route. If the
4016 * extended community attribute has changed, we need to
4017 * un-import
4018 * the route using its existing extended community. It will be
4019 * subsequently processed for import with the new extended
4020 * community.
4021 */
6f8c9c11
PR
4022 if (((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN))
4023 && !same_attr) {
40381db7 4024 if ((pi->attr->flag
d62a17ae 4025 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))
4026 && (attr_new->flag
4027 & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
4028 int cmp;
4029
40381db7 4030 cmp = ecommunity_cmp(pi->attr->ecommunity,
d62a17ae 4031 attr_new->ecommunity);
4032 if (!cmp) {
4033 if (bgp_debug_update(peer, p, NULL, 1))
4034 zlog_debug(
4035 "Change in EXT-COMM, existing %s new %s",
4036 ecommunity_str(
40381db7 4037 pi->attr->ecommunity),
d62a17ae 4038 ecommunity_str(
4039 attr_new->ecommunity));
6f8c9c11
PR
4040 if (safi == SAFI_EVPN)
4041 bgp_evpn_unimport_route(
4042 bgp, afi, safi, p, pi);
4043 else /* SAFI_MPLS_VPN */
4044 vpn_leak_to_vrf_withdraw(bgp,
4045 pi);
d62a17ae 4046 }
4047 }
4048 }
718e3744 4049
d62a17ae 4050 /* Update to new attribute. */
40381db7
DS
4051 bgp_attr_unintern(&pi->attr);
4052 pi->attr = attr_new;
d62a17ae 4053
4054 /* Update MPLS label */
4055 if (has_valid_label) {
40381db7 4056 extra = bgp_path_info_extra_get(pi);
8ba71050
NS
4057 if (extra->label != label) {
4058 memcpy(&extra->label, label,
dbd587da 4059 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4060 extra->num_labels = num_labels;
4061 }
b57ba6d2
MK
4062 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4063 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4064 }
718e3744 4065
e496b420
HS
4066 /* Update SRv6 SID */
4067 if (attr->srv6_l3vpn) {
4068 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4069 if (sid_diff(&extra->sid[0].sid,
4070 &attr->srv6_l3vpn->sid)) {
4071 sid_copy(&extra->sid[0].sid,
e496b420
HS
4072 &attr->srv6_l3vpn->sid);
4073 extra->num_sids = 1;
cc8f05df 4074
16f3db2d
RS
4075 extra->sid[0].loc_block_len = 0;
4076 extra->sid[0].loc_node_len = 0;
4077 extra->sid[0].func_len = 0;
4078 extra->sid[0].arg_len = 0;
4079
4080 if (attr->srv6_l3vpn->loc_block_len != 0) {
4081 extra->sid[0].loc_block_len =
4082 attr->srv6_l3vpn->loc_block_len;
4083 extra->sid[0].loc_node_len =
4084 attr->srv6_l3vpn->loc_node_len;
4085 extra->sid[0].func_len =
4086 attr->srv6_l3vpn->func_len;
4087 extra->sid[0].arg_len =
4088 attr->srv6_l3vpn->arg_len;
4089 }
4090
cc8f05df
RS
4091 /*
4092 * draft-ietf-bess-srv6-services-07
4093 * The part of SRv6 SID may be encoded as MPLS
4094 * Label for the efficient packing.
4095 */
4096 if (attr->srv6_l3vpn->transposition_len != 0)
4097 transpose_sid(
16f3db2d 4098 &extra->sid[0].sid,
cc8f05df
RS
4099 decode_label(label),
4100 attr->srv6_l3vpn
4101 ->transposition_offset,
4102 attr->srv6_l3vpn
4103 ->transposition_len);
e496b420
HS
4104 }
4105 } else if (attr->srv6_vpn) {
4106 extra = bgp_path_info_extra_get(pi);
16f3db2d
RS
4107 if (sid_diff(&extra->sid[0].sid,
4108 &attr->srv6_vpn->sid)) {
4109 sid_copy(&extra->sid[0].sid,
4110 &attr->srv6_vpn->sid);
e496b420
HS
4111 extra->num_sids = 1;
4112 }
4113 }
4114
49e5a4a0 4115#ifdef ENABLE_BGP_VNC
d62a17ae 4116 if ((afi == AFI_IP || afi == AFI_IP6)
4117 && (safi == SAFI_UNICAST)) {
4118 if (vnc_implicit_withdraw) {
4119 /*
4120 * Add back the route with its new attributes
4121 * (e.g., nexthop).
4122 * The route is still selected, until the route
4123 * selection
4124 * queued by bgp_process actually runs. We have
4125 * to make this
4126 * update to the VNC side immediately to avoid
4127 * racing against
4128 * configuration changes (e.g., route-map
4129 * changes) which
4130 * trigger re-importation of the entire RIB.
4131 */
40381db7
DS
4132 vnc_import_bgp_add_route(bgp, p, pi);
4133 vnc_import_bgp_exterior_add_route(bgp, p, pi);
d62a17ae 4134 }
4135 }
65efcfce
LB
4136#endif
4137
d62a17ae 4138 /* Update bgp route dampening information. */
b4f7f45b 4139 if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
d62a17ae 4140 && peer->sort == BGP_PEER_EBGP) {
4141 /* Now we do normal update dampening. */
9bcb3eef 4142 ret = bgp_damp_update(pi, dest, afi, safi);
d62a17ae 4143 if (ret == BGP_DAMP_SUPPRESSED) {
9bcb3eef 4144 bgp_dest_unlock_node(dest);
d62a17ae 4145 return 0;
4146 }
4147 }
128ea8ab 4148
d62a17ae 4149 /* Nexthop reachability check - for unicast and
4150 * labeled-unicast.. */
7c312383
AD
4151 if (((afi == AFI_IP || afi == AFI_IP6)
4152 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4153 || (safi == SAFI_EVPN &&
4154 bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4155 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4156 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4157 && !CHECK_FLAG(peer->flags,
4158 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4159 && !CHECK_FLAG(bgp->flags,
4160 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4161 connected = 1;
4162 else
4163 connected = 0;
4164
960035b2
PZ
4165 struct bgp *bgp_nexthop = bgp;
4166
40381db7
DS
4167 if (pi->extra && pi->extra->bgp_orig)
4168 bgp_nexthop = pi->extra->bgp_orig;
960035b2 4169
7c312383
AD
4170 nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
4171
4172 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi,
654a5978
PG
4173 safi, pi, NULL, connected,
4174 p)
a4d82a8a 4175 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef
DS
4176 bgp_path_info_set_flag(dest, pi,
4177 BGP_PATH_VALID);
d62a17ae 4178 else {
4179 if (BGP_DEBUG(nht, NHT)) {
1b78780b
DL
4180 zlog_debug("%s(%pI4): NH unresolved",
4181 __func__,
4182 (in_addr_t *)&attr_new->nexthop);
d62a17ae 4183 }
9bcb3eef 4184 bgp_path_info_unset_flag(dest, pi,
18ee8310 4185 BGP_PATH_VALID);
d62a17ae 4186 }
4187 } else
9bcb3eef 4188 bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
d62a17ae 4189
49e5a4a0 4190#ifdef ENABLE_BGP_VNC
d62a17ae 4191 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4192 struct bgp_dest *pdest = NULL;
d62a17ae 4193 struct bgp_table *table = NULL;
4194
9bcb3eef
DS
4195 pdest = bgp_node_get(bgp->rib[afi][safi],
4196 (struct prefix *)prd);
4197 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4198 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4199
4200 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
40381db7 4201 bgp, prd, table, p, pi);
d62a17ae 4202 }
9bcb3eef 4203 bgp_dest_unlock_node(pdest);
d62a17ae 4204 }
4205#endif
718e3744 4206
d62a17ae 4207 /* If this is an EVPN route and some attribute has changed,
9146341f 4208 * or we are explicitly told to perform a route import, process
d62a17ae 4209 * route for import. If the extended community has changed, we
4210 * would
4211 * have done the un-import earlier and the import would result
4212 * in the
4213 * route getting injected into appropriate L2 VNIs. If it is
4214 * just
4215 * some other attribute change, the import will result in
4216 * updating
4217 * the attributes for the route in the VNI(s).
4218 */
9146341f 4219 if (safi == SAFI_EVPN &&
4220 (!same_attr || force_evpn_import) &&
7c312383 4221 CHECK_FLAG(pi->flags, BGP_PATH_VALID))
40381db7 4222 bgp_evpn_import_route(bgp, afi, safi, p, pi);
d62a17ae 4223
4224 /* Process change. */
40381db7 4225 bgp_aggregate_increment(bgp, p, pi, afi, safi);
d62a17ae 4226
9bcb3eef
DS
4227 bgp_process(bgp, dest, afi, safi);
4228 bgp_dest_unlock_node(dest);
558d1fec 4229
ddb5b488
PZ
4230 if (SAFI_UNICAST == safi
4231 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4232 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4233
40381db7 4234 vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4235 }
4236 if ((SAFI_MPLS_VPN == safi)
4237 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4238
40381db7 4239 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488
PZ
4240 }
4241
49e5a4a0 4242#ifdef ENABLE_BGP_VNC
d62a17ae 4243 if (SAFI_MPLS_VPN == safi) {
4244 mpls_label_t label_decoded = decode_label(label);
28070ee3 4245
d62a17ae 4246 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4247 type, sub_type, &label_decoded);
4248 }
4249 if (SAFI_ENCAP == safi) {
4250 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi,
4251 type, sub_type, NULL);
4252 }
28070ee3
PZ
4253#endif
4254
d62a17ae 4255 return 0;
4256 } // End of implicit withdraw
718e3744 4257
d62a17ae 4258 /* Received Logging. */
4259 if (bgp_debug_update(peer, p, NULL, 1)) {
4260 if (!peer->rcvd_attr_printed) {
4261 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4262 peer->rcvd_attr_str);
4263 peer->rcvd_attr_printed = 1;
4264 }
718e3744 4265
a4d82a8a 4266 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4267 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4268 pfx_buf, sizeof(pfx_buf));
d62a17ae 4269 zlog_debug("%s rcvd %s", peer->host, pfx_buf);
4270 }
718e3744 4271
d62a17ae 4272 /* Make new BGP info. */
9bcb3eef 4273 new = info_make(type, sub_type, 0, peer, attr_new, dest);
718e3744 4274
d62a17ae 4275 /* Update MPLS label */
4276 if (has_valid_label) {
18ee8310 4277 extra = bgp_path_info_extra_get(new);
8ba71050 4278 if (extra->label != label) {
dbd587da
QY
4279 memcpy(&extra->label, label,
4280 num_labels * sizeof(mpls_label_t));
8ba71050
NS
4281 extra->num_labels = num_labels;
4282 }
b57ba6d2
MK
4283 if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
4284 bgp_set_valid_label(&extra->label[0]);
fc9a856f 4285 }
718e3744 4286
e496b420
HS
4287 /* Update SRv6 SID */
4288 if (safi == SAFI_MPLS_VPN) {
4289 extra = bgp_path_info_extra_get(new);
4290 if (attr->srv6_l3vpn) {
16f3db2d 4291 sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
e496b420 4292 extra->num_sids = 1;
cc8f05df 4293
16f3db2d
RS
4294 extra->sid[0].loc_block_len =
4295 attr->srv6_l3vpn->loc_block_len;
4296 extra->sid[0].loc_node_len =
4297 attr->srv6_l3vpn->loc_node_len;
4298 extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
4299 extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
4300
cc8f05df
RS
4301 /*
4302 * draft-ietf-bess-srv6-services-07
4303 * The part of SRv6 SID may be encoded as MPLS Label for
4304 * the efficient packing.
4305 */
4306 if (attr->srv6_l3vpn->transposition_len != 0)
4307 transpose_sid(
16f3db2d 4308 &extra->sid[0].sid, decode_label(label),
cc8f05df
RS
4309 attr->srv6_l3vpn->transposition_offset,
4310 attr->srv6_l3vpn->transposition_len);
e496b420 4311 } else if (attr->srv6_vpn) {
16f3db2d 4312 sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
e496b420
HS
4313 extra->num_sids = 1;
4314 }
4315 }
4316
d62a17ae 4317 /* Nexthop reachability check. */
7c312383
AD
4318 if (((afi == AFI_IP || afi == AFI_IP6)
4319 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
4320 || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) {
c8d6f0d6
DA
4321 if (safi != SAFI_EVPN && peer->sort == BGP_PEER_EBGP
4322 && peer->ttl == BGP_DEFAULT_TTL
d62a17ae 4323 && !CHECK_FLAG(peer->flags,
4324 PEER_FLAG_DISABLE_CONNECTED_CHECK)
892fedb6
DA
4325 && !CHECK_FLAG(bgp->flags,
4326 BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
d62a17ae 4327 connected = 1;
4328 else
4329 connected = 0;
4330
7c312383
AD
4331 nh_afi = BGP_ATTR_NH_AFI(afi, new->attr);
4332
4053e952 4333 if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, safi, new, NULL,
654a5978 4334 connected, p)
a4d82a8a 4335 || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD))
9bcb3eef 4336 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4337 else {
4338 if (BGP_DEBUG(nht, NHT)) {
4339 char buf1[INET6_ADDRSTRLEN];
4340 inet_ntop(AF_INET,
4341 (const void *)&attr_new->nexthop,
4342 buf1, INET6_ADDRSTRLEN);
15569c58
DA
4343 zlog_debug("%s(%s): NH unresolved", __func__,
4344 buf1);
d62a17ae 4345 }
9bcb3eef 4346 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 4347 }
4348 } else
9bcb3eef 4349 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
a82478b9 4350
d62a17ae 4351 /* Addpath ID */
4352 new->addpath_rx_id = addpath_id;
4353
4354 /* Increment prefix */
4355 bgp_aggregate_increment(bgp, p, new, afi, safi);
4356
4357 /* Register new BGP information. */
9bcb3eef 4358 bgp_path_info_add(dest, new);
d62a17ae 4359
4360 /* route_node_get lock */
9bcb3eef 4361 bgp_dest_unlock_node(dest);
558d1fec 4362
49e5a4a0 4363#ifdef ENABLE_BGP_VNC
d62a17ae 4364 if (safi == SAFI_MPLS_VPN) {
9bcb3eef 4365 struct bgp_dest *pdest = NULL;
d62a17ae 4366 struct bgp_table *table = NULL;
4367
9bcb3eef
DS
4368 pdest = bgp_node_get(bgp->rib[afi][safi], (struct prefix *)prd);
4369 if (bgp_dest_has_bgp_path_info_data(pdest)) {
4370 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 4371
4372 vnc_import_bgp_add_vnc_host_route_mode_resolve_nve(
4373 bgp, prd, table, p, new);
4374 }
9bcb3eef 4375 bgp_dest_unlock_node(pdest);
d62a17ae 4376 }
65efcfce
LB
4377#endif
4378
d62a17ae 4379 /* If this is an EVPN route, process for import. */
7c312383 4380 if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID))
d62a17ae 4381 bgp_evpn_import_route(bgp, afi, safi, p, new);
128ea8ab 4382
9bcb3eef 4383 hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
4a11bf2c 4384
d62a17ae 4385 /* Process change. */
9bcb3eef 4386 bgp_process(bgp, dest, afi, safi);
718e3744 4387
ddb5b488
PZ
4388 if (SAFI_UNICAST == safi
4389 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4390 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4391 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
4392 }
4393 if ((SAFI_MPLS_VPN == safi)
4394 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4395
4396 vpn_leak_to_vrf_update(bgp, new);
4397 }
49e5a4a0 4398#ifdef ENABLE_BGP_VNC
d62a17ae 4399 if (SAFI_MPLS_VPN == safi) {
4400 mpls_label_t label_decoded = decode_label(label);
28070ee3 4401
d62a17ae 4402 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4403 sub_type, &label_decoded);
4404 }
4405 if (SAFI_ENCAP == safi) {
4406 rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type,
4407 sub_type, NULL);
4408 }
28070ee3
PZ
4409#endif
4410
d62a17ae 4411 return 0;
718e3744 4412
d62a17ae 4413/* This BGP update is filtered. Log the reason then update BGP
4414 entry. */
4415filtered:
9bcb3eef 4416 hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
4a11bf2c 4417
d62a17ae 4418 if (bgp_debug_update(peer, p, NULL, 1)) {
4419 if (!peer->rcvd_attr_printed) {
4420 zlog_debug("%s rcvd UPDATE w/ attr: %s", peer->host,
4421 peer->rcvd_attr_str);
4422 peer->rcvd_attr_printed = 1;
4423 }
718e3744 4424
a4d82a8a 4425 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
66ff6089 4426 addpath_id ? 1 : 0, addpath_id, evpn,
6c995628 4427 pfx_buf, sizeof(pfx_buf));
d62a17ae 4428 zlog_debug("%s rcvd UPDATE about %s -- DENIED due to: %s",
4429 peer->host, pfx_buf, reason);
4430 }
128ea8ab 4431
40381db7 4432 if (pi) {
d62a17ae 4433 /* If this is an EVPN route, un-import it as it is now filtered.
4434 */
4435 if (safi == SAFI_EVPN)
40381db7 4436 bgp_evpn_unimport_route(bgp, afi, safi, p, pi);
718e3744 4437
ddb5b488
PZ
4438 if (SAFI_UNICAST == safi
4439 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4440 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4441
40381db7 4442 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4443 }
4444 if ((SAFI_MPLS_VPN == safi)
4445 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4446
40381db7 4447 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4448 }
4449
9bcb3eef 4450 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 4451 }
4452
9bcb3eef 4453 bgp_dest_unlock_node(dest);
558d1fec 4454
49e5a4a0 4455#ifdef ENABLE_BGP_VNC
d62a17ae 4456 /*
4457 * Filtered update is treated as an implicit withdrawal (see
4458 * bgp_rib_remove()
4459 * a few lines above)
4460 */
4461 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4462 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4463 0);
4464 }
97736e32
PZ
4465#endif
4466
d62a17ae 4467 return 0;
718e3744 4468}
4469
26a3ffd6 4470int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
d62a17ae 4471 struct attr *attr, afi_t afi, safi_t safi, int type,
a4d82a8a 4472 int sub_type, struct prefix_rd *prd, mpls_label_t *label,
d7c0a89a 4473 uint32_t num_labels, struct bgp_route_evpn *evpn)
718e3744 4474{
d62a17ae 4475 struct bgp *bgp;
4476 char pfx_buf[BGP_PRD_PATH_STRLEN];
9bcb3eef 4477 struct bgp_dest *dest;
40381db7 4478 struct bgp_path_info *pi;
718e3744 4479
49e5a4a0 4480#ifdef ENABLE_BGP_VNC
d62a17ae 4481 if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) {
4482 rfapiProcessWithdraw(peer, NULL, p, prd, NULL, afi, safi, type,
4483 0);
4484 }
28070ee3
PZ
4485#endif
4486
d62a17ae 4487 bgp = peer->bgp;
4488
4489 /* Lookup node. */
9bcb3eef 4490 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
d62a17ae 4491
4492 /* If peer is soft reconfiguration enabled. Record input packet for
4493 * further calculation.
4494 *
4495 * Cisco IOS 12.4(24)T4 on session establishment sends withdraws for all
4496 * routes that are filtered. This tanks out Quagga RS pretty badly due
4497 * to
4498 * the iteration over all RS clients.
4499 * Since we need to remove the entry from adj_in anyway, do that first
4500 * and
4501 * if there was no entry, we don't need to do anything more.
4502 */
4503 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
4504 && peer != bgp->peer_self)
9bcb3eef 4505 if (!bgp_adj_in_unset(dest, peer, addpath_id)) {
b4d46cc9
DL
4506 peer->stat_pfx_dup_withdraw++;
4507
d62a17ae 4508 if (bgp_debug_update(peer, p, NULL, 1)) {
4509 bgp_debug_rdpfxpath2str(
a4d82a8a 4510 afi, safi, prd, p, label, num_labels,
6c995628
AD
4511 addpath_id ? 1 : 0, addpath_id, NULL,
4512 pfx_buf, sizeof(pfx_buf));
d62a17ae 4513 zlog_debug(
4514 "%s withdrawing route %s not in adj-in",
4515 peer->host, pfx_buf);
4516 }
9bcb3eef 4517 bgp_dest_unlock_node(dest);
d62a17ae 4518 return 0;
4519 }
cd808e74 4520
d62a17ae 4521 /* Lookup withdrawn route. */
9bcb3eef 4522 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
4523 if (pi->peer == peer && pi->type == type
4524 && pi->sub_type == sub_type
4525 && pi->addpath_rx_id == addpath_id)
d62a17ae 4526 break;
4527
4528 /* Logging. */
4529 if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4530 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4531 addpath_id ? 1 : 0, addpath_id, NULL,
4532 pfx_buf, sizeof(pfx_buf));
d62a17ae 4533 zlog_debug("%s rcvd UPDATE about %s -- withdrawn", peer->host,
4534 pfx_buf);
4535 }
718e3744 4536
d62a17ae 4537 /* Withdraw specified route from routing table. */
40381db7 4538 if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
9bcb3eef 4539 bgp_rib_withdraw(dest, pi, peer, afi, safi, prd);
ddb5b488
PZ
4540 if (SAFI_UNICAST == safi
4541 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
4542 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 4543 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488
PZ
4544 }
4545 if ((SAFI_MPLS_VPN == safi)
4546 && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
4547
40381db7 4548 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488
PZ
4549 }
4550 } else if (bgp_debug_update(peer, p, NULL, 1)) {
a4d82a8a 4551 bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
6c995628
AD
4552 addpath_id ? 1 : 0, addpath_id, NULL,
4553 pfx_buf, sizeof(pfx_buf));
d62a17ae 4554 zlog_debug("%s Can't find the route %s", peer->host, pfx_buf);
4555 }
718e3744 4556
d62a17ae 4557 /* Unlock bgp_node_get() lock. */
9bcb3eef 4558 bgp_dest_unlock_node(dest);
d62a17ae 4559
4560 return 0;
718e3744 4561}
6b0655a2 4562
d62a17ae 4563void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
4564 int withdraw)
718e3744 4565{
d62a17ae 4566 struct update_subgroup *subgrp;
4567 subgrp = peer_subgroup(peer, afi, safi);
4568 subgroup_default_originate(subgrp, withdraw);
3f9c7369 4569}
6182d65b 4570
718e3744 4571
3f9c7369
DS
4572/*
4573 * bgp_stop_announce_route_timer
4574 */
d62a17ae 4575void bgp_stop_announce_route_timer(struct peer_af *paf)
3f9c7369 4576{
d62a17ae 4577 if (!paf->t_announce_route)
4578 return;
4579
50478845 4580 thread_cancel(&paf->t_announce_route);
718e3744 4581}
6b0655a2 4582
3f9c7369
DS
4583/*
4584 * bgp_announce_route_timer_expired
4585 *
4586 * Callback that is invoked when the route announcement timer for a
4587 * peer_af expires.
4588 */
d62a17ae 4589static int bgp_announce_route_timer_expired(struct thread *t)
718e3744 4590{
d62a17ae 4591 struct peer_af *paf;
4592 struct peer *peer;
558d1fec 4593
d62a17ae 4594 paf = THREAD_ARG(t);
4595 peer = paf->peer;
718e3744 4596
feb17238 4597 if (!peer_established(peer))
d62a17ae 4598 return 0;
3f9c7369 4599
d62a17ae 4600 if (!peer->afc_nego[paf->afi][paf->safi])
4601 return 0;
3f9c7369 4602
d62a17ae 4603 peer_af_announce_route(paf, 1);
c5aec50b
MK
4604
4605 /* Notify BGP conditional advertisement scanner percess */
c385f82a 4606 peer->advmap_config_change[paf->afi][paf->safi] = true;
c5aec50b 4607
d62a17ae 4608 return 0;
718e3744 4609}
4610
3f9c7369
DS
4611/*
4612 * bgp_announce_route
4613 *
4614 * *Triggers* announcement of routes of a given AFI/SAFI to a peer.
e1a32ec1
DS
4615 *
4616 * if force is true we will force an update even if the update
4617 * limiting code is attempted to kick in.
3f9c7369 4618 */
e1a32ec1 4619void bgp_announce_route(struct peer *peer, afi_t afi, safi_t safi, bool force)
d62a17ae 4620{
4621 struct peer_af *paf;
4622 struct update_subgroup *subgrp;
4623
4624 paf = peer_af_find(peer, afi, safi);
4625 if (!paf)
4626 return;
4627 subgrp = PAF_SUBGRP(paf);
4628
4629 /*
4630 * Ignore if subgroup doesn't exist (implies AF is not negotiated)
4631 * or a refresh has already been triggered.
4632 */
4633 if (!subgrp || paf->t_announce_route)
4634 return;
4635
e1a32ec1
DS
4636 if (force)
4637 SET_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES);
4638
d62a17ae 4639 /*
4640 * Start a timer to stagger/delay the announce. This serves
4641 * two purposes - announcement can potentially be combined for
4642 * multiple peers and the announcement doesn't happen in the
4643 * vty context.
4644 */
4645 thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
4646 (subgrp->peer_count == 1)
4647 ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS
4648 : BGP_ANNOUNCE_ROUTE_DELAY_MS,
4649 &paf->t_announce_route);
3f9c7369
DS
4650}
4651
4652/*
4653 * Announce routes from all AF tables to a peer.
4654 *
4655 * This should ONLY be called when there is a need to refresh the
4656 * routes to the peer based on a policy change for this peer alone
4657 * or a route refresh request received from the peer.
4658 * The operation will result in splitting the peer from its existing
4659 * subgroups and putting it in new subgroups.
4660 */
d62a17ae 4661void bgp_announce_route_all(struct peer *peer)
718e3744 4662{
d62a17ae 4663 afi_t afi;
4664 safi_t safi;
4665
05c7a1cc 4666 FOREACH_AFI_SAFI (afi, safi)
e1a32ec1 4667 bgp_announce_route(peer, afi, safi, false);
718e3744 4668}
6b0655a2 4669
46aeabed
LS
4670/* Flag or unflag bgp_dest to determine whether it should be treated by
4671 * bgp_soft_reconfig_table_task.
4672 * Flag if flag is true. Unflag if flag is false.
4673 */
4674static void bgp_soft_reconfig_table_flag(struct bgp_table *table, bool flag)
4675{
4676 struct bgp_dest *dest;
4677 struct bgp_adj_in *ain;
4678
4679 if (!table)
4680 return;
4681
4682 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
4683 for (ain = dest->adj_in; ain; ain = ain->next) {
4684 if (ain->peer != NULL)
4685 break;
4686 }
4687 if (flag && ain != NULL && ain->peer != NULL)
4688 SET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4689 else
4690 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4691 }
4692}
4693
4694static int bgp_soft_reconfig_table_update(struct peer *peer,
4695 struct bgp_dest *dest,
4696 struct bgp_adj_in *ain, afi_t afi,
4697 safi_t safi, struct prefix_rd *prd)
4698{
4699 struct bgp_path_info *pi;
4700 uint32_t num_labels = 0;
4701 mpls_label_t *label_pnt = NULL;
4702 struct bgp_route_evpn evpn;
4703
4704 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
4705 if (pi->peer == peer)
4706 break;
4707
4708 if (pi && pi->extra)
4709 num_labels = pi->extra->num_labels;
4710 if (num_labels)
4711 label_pnt = &pi->extra->label[0];
4712 if (pi)
4713 memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
4714 sizeof(evpn));
4715 else
4716 memset(&evpn, 0, sizeof(evpn));
4717
4718 return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
4719 ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
4720 BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
4721 &evpn);
4722}
4723
d62a17ae 4724static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
4725 struct bgp_table *table,
4726 struct prefix_rd *prd)
718e3744 4727{
d62a17ae 4728 int ret;
9bcb3eef 4729 struct bgp_dest *dest;
d62a17ae 4730 struct bgp_adj_in *ain;
718e3744 4731
d62a17ae 4732 if (!table)
4733 table = peer->bgp->rib[afi][safi];
718e3744 4734
9bcb3eef
DS
4735 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
4736 for (ain = dest->adj_in; ain; ain = ain->next) {
ea47320b
DL
4737 if (ain->peer != peer)
4738 continue;
8692c506 4739
46aeabed
LS
4740 ret = bgp_soft_reconfig_table_update(peer, dest, ain,
4741 afi, safi, prd);
ea47320b
DL
4742
4743 if (ret < 0) {
9bcb3eef 4744 bgp_dest_unlock_node(dest);
ea47320b 4745 return;
d62a17ae 4746 }
4747 }
718e3744 4748}
4749
46aeabed
LS
4750/* Do soft reconfig table per bgp table.
4751 * Walk on SOFT_RECONFIG_TASK_MAX_PREFIX bgp_dest,
4752 * when BGP_NODE_SOFT_RECONFIG is set,
4753 * reconfig bgp_dest for list of table->soft_reconfig_peers peers.
4754 * Schedule a new thread to continue the job.
4755 * Without splitting the full job into several part,
4756 * vtysh waits for the job to finish before responding to a BGP command
4757 */
4758static int bgp_soft_reconfig_table_task(struct thread *thread)
4759{
4760 uint32_t iter, max_iter;
4761 int ret;
4762 struct bgp_dest *dest;
4763 struct bgp_adj_in *ain;
4764 struct peer *peer;
4765 struct bgp_table *table;
4766 struct prefix_rd *prd;
4767 struct listnode *node, *nnode;
4768
4769 table = THREAD_ARG(thread);
4770 prd = NULL;
4771
4772 max_iter = SOFT_RECONFIG_TASK_MAX_PREFIX;
4773 if (table->soft_reconfig_init) {
4774 /* first call of the function with a new srta structure.
4775 * Don't do any treatment this time on nodes
4776 * in order vtysh to respond quickly
4777 */
4778 max_iter = 0;
4779 }
4780
4781 for (iter = 0, dest = bgp_table_top(table); (dest && iter < max_iter);
4782 dest = bgp_route_next(dest)) {
4783 if (!CHECK_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG))
4784 continue;
4785
4786 UNSET_FLAG(dest->flags, BGP_NODE_SOFT_RECONFIG);
4787
4788 for (ain = dest->adj_in; ain; ain = ain->next) {
4789 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node,
4790 nnode, peer)) {
4791 if (ain->peer != peer)
4792 continue;
4793
4794 ret = bgp_soft_reconfig_table_update(
4795 peer, dest, ain, table->afi,
4796 table->safi, prd);
4797 iter++;
4798
4799 if (ret < 0) {
4800 bgp_dest_unlock_node(dest);
4801 listnode_delete(
4802 table->soft_reconfig_peers,
4803 peer);
4804 bgp_announce_route(peer, table->afi,
e1a32ec1 4805 table->safi, false);
46aeabed
LS
4806 if (list_isempty(
4807 table->soft_reconfig_peers)) {
4808 list_delete(
4809 &table->soft_reconfig_peers);
4810 bgp_soft_reconfig_table_flag(
4811 table, false);
4812 return 0;
4813 }
4814 }
4815 }
4816 }
4817 }
4818
4819 /* we're either starting the initial iteration,
4820 * or we're going to continue an ongoing iteration
4821 */
4822 if (dest || table->soft_reconfig_init) {
4823 table->soft_reconfig_init = false;
4824 thread_add_event(bm->master, bgp_soft_reconfig_table_task,
4825 table, 0, &table->soft_reconfig_thread);
4826 return 0;
4827 }
4828 /* we're done, clean up the background iteration context info and
4829 schedule route annoucement
4830 */
4831 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode, peer)) {
4832 listnode_delete(table->soft_reconfig_peers, peer);
e1a32ec1 4833 bgp_announce_route(peer, table->afi, table->safi, false);
46aeabed
LS
4834 }
4835
4836 list_delete(&table->soft_reconfig_peers);
4837
4838 return 0;
4839}
4840
4841
4842/* Cancel soft_reconfig_table task matching bgp instance, bgp_table
4843 * and peer.
4844 * - bgp cannot be NULL
4845 * - if table and peer are NULL, cancel all threads within the bgp instance
4846 * - if table is NULL and peer is not,
4847 * remove peer in all threads within the bgp instance
4848 * - if peer is NULL, cancel all threads matching table within the bgp instance
4849 */
4850void bgp_soft_reconfig_table_task_cancel(const struct bgp *bgp,
4851 const struct bgp_table *table,
4852 const struct peer *peer)
4853{
4854 struct peer *npeer;
4855 struct listnode *node, *nnode;
4856 int afi, safi;
4857 struct bgp_table *ntable;
4858
4859 if (!bgp)
4860 return;
4861
4862 FOREACH_AFI_SAFI (afi, safi) {
4863 ntable = bgp->rib[afi][safi];
4864 if (!ntable)
4865 continue;
4866 if (table && table != ntable)
4867 continue;
4868
4869 for (ALL_LIST_ELEMENTS(ntable->soft_reconfig_peers, node, nnode,
4870 npeer)) {
4871 if (peer && peer != npeer)
4872 continue;
4873 listnode_delete(ntable->soft_reconfig_peers, npeer);
4874 }
4875
4876 if (!ntable->soft_reconfig_peers
4877 || !list_isempty(ntable->soft_reconfig_peers))
4878 continue;
4879
4880 list_delete(&ntable->soft_reconfig_peers);
4881 bgp_soft_reconfig_table_flag(ntable, false);
4882 BGP_TIMER_OFF(ntable->soft_reconfig_thread);
4883 }
4884}
4885
d62a17ae 4886void bgp_soft_reconfig_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 4887{
9bcb3eef 4888 struct bgp_dest *dest;
d62a17ae 4889 struct bgp_table *table;
46aeabed
LS
4890 struct listnode *node, *nnode;
4891 struct peer *npeer;
4892 struct peer_af *paf;
718e3744 4893
feb17238 4894 if (!peer_established(peer))
d62a17ae 4895 return;
718e3744 4896
d62a17ae 4897 if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)
46aeabed
LS
4898 && (safi != SAFI_EVPN)) {
4899 table = peer->bgp->rib[afi][safi];
4900 if (!table)
4901 return;
4902
4903 table->soft_reconfig_init = true;
4904
4905 if (!table->soft_reconfig_peers)
4906 table->soft_reconfig_peers = list_new();
4907 npeer = NULL;
4908 /* add peer to the table soft_reconfig_peers if not already
4909 * there
4910 */
4911 for (ALL_LIST_ELEMENTS(table->soft_reconfig_peers, node, nnode,
4912 npeer)) {
4913 if (peer == npeer)
4914 break;
4915 }
4916 if (peer != npeer)
4917 listnode_add(table->soft_reconfig_peers, peer);
4918
4919 /* (re)flag all bgp_dest in table. Existing soft_reconfig_in job
4920 * on table would start back at the beginning.
4921 */
4922 bgp_soft_reconfig_table_flag(table, true);
4923
4924 if (!table->soft_reconfig_thread)
4925 thread_add_event(bm->master,
4926 bgp_soft_reconfig_table_task, table, 0,
4927 &table->soft_reconfig_thread);
4928 /* Cancel bgp_announce_route_timer_expired threads.
4929 * bgp_announce_route_timer_expired threads have been scheduled
4930 * to announce routes as soon as the soft_reconfigure process
4931 * finishes.
4932 * In this case, soft_reconfigure is also scheduled by using
4933 * a thread but is planned after the
4934 * bgp_announce_route_timer_expired threads. It means that,
4935 * without cancelling the threads, the route announcement task
4936 * would run before the soft reconfiguration one. That would
4937 * useless and would block vtysh during several seconds. Route
4938 * announcements are rescheduled as soon as the soft_reconfigure
4939 * process finishes.
4940 */
4941 paf = peer_af_find(peer, afi, safi);
4942 if (paf)
4943 bgp_stop_announce_route_timer(paf);
4944 } else
9bcb3eef
DS
4945 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
4946 dest = bgp_route_next(dest)) {
4947 table = bgp_dest_get_bgp_table_info(dest);
67009e22 4948
b54892e0
DS
4949 if (table == NULL)
4950 continue;
8692c506 4951
9bcb3eef 4952 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0
DS
4953 struct prefix_rd prd;
4954
4955 prd.family = AF_UNSPEC;
4956 prd.prefixlen = 64;
4957 memcpy(&prd.val, p->u.val, 8);
4958
4959 bgp_soft_reconfig_table(peer, afi, safi, table, &prd);
67009e22 4960 }
718e3744 4961}
6b0655a2 4962
228da428 4963
d62a17ae 4964struct bgp_clear_node_queue {
9bcb3eef 4965 struct bgp_dest *dest;
228da428
CC
4966};
4967
d62a17ae 4968static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
200df115 4969{
d62a17ae 4970 struct bgp_clear_node_queue *cnq = data;
9bcb3eef 4971 struct bgp_dest *dest = cnq->dest;
d62a17ae 4972 struct peer *peer = wq->spec.data;
40381db7 4973 struct bgp_path_info *pi;
3103e8d2 4974 struct bgp *bgp;
9bcb3eef
DS
4975 afi_t afi = bgp_dest_table(dest)->afi;
4976 safi_t safi = bgp_dest_table(dest)->safi;
d62a17ae 4977
9bcb3eef 4978 assert(dest && peer);
3103e8d2 4979 bgp = peer->bgp;
d62a17ae 4980
4981 /* It is possible that we have multiple paths for a prefix from a peer
4982 * if that peer is using AddPath.
4983 */
9bcb3eef 4984 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 4985 if (pi->peer != peer)
ea47320b
DL
4986 continue;
4987
4988 /* graceful restart STALE flag set. */
9af52ccf
DA
4989 if (((CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT)
4990 && peer->nsf[afi][safi])
4991 || CHECK_FLAG(peer->af_sflags[afi][safi],
4992 PEER_STATUS_ENHANCED_REFRESH))
40381db7
DS
4993 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
4994 && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
9bcb3eef 4995 bgp_path_info_set_flag(dest, pi, BGP_PATH_STALE);
ea47320b
DL
4996 else {
4997 /* If this is an EVPN route, process for
4998 * un-import. */
4999 if (safi == SAFI_EVPN)
9bcb3eef
DS
5000 bgp_evpn_unimport_route(
5001 bgp, afi, safi,
5002 bgp_dest_get_prefix(dest), pi);
3103e8d2
DS
5003 /* Handle withdraw for VRF route-leaking and L3VPN */
5004 if (SAFI_UNICAST == safi
5005 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
960035b2 5006 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
3103e8d2 5007 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 5008 bgp, pi);
960035b2 5009 }
3103e8d2 5010 if (SAFI_MPLS_VPN == safi &&
960035b2 5011 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5012 vpn_leak_to_vrf_withdraw(bgp, pi);
960035b2 5013 }
3103e8d2 5014
9bcb3eef 5015 bgp_rib_remove(dest, pi, peer, afi, safi);
d62a17ae 5016 }
ea47320b 5017 }
d62a17ae 5018 return WQ_SUCCESS;
200df115 5019}
5020
d62a17ae 5021static void bgp_clear_node_queue_del(struct work_queue *wq, void *data)
200df115 5022{
d62a17ae 5023 struct bgp_clear_node_queue *cnq = data;
9bcb3eef
DS
5024 struct bgp_dest *dest = cnq->dest;
5025 struct bgp_table *table = bgp_dest_table(dest);
228da428 5026
9bcb3eef 5027 bgp_dest_unlock_node(dest);
d62a17ae 5028 bgp_table_unlock(table);
5029 XFREE(MTYPE_BGP_CLEAR_NODE_QUEUE, cnq);
200df115 5030}
5031
d62a17ae 5032static void bgp_clear_node_complete(struct work_queue *wq)
200df115 5033{
d62a17ae 5034 struct peer *peer = wq->spec.data;
64e580a7 5035
d62a17ae 5036 /* Tickle FSM to start moving again */
5037 BGP_EVENT_ADD(peer, Clearing_Completed);
5038
5039 peer_unlock(peer); /* bgp_clear_route */
200df115 5040}
718e3744 5041
d62a17ae 5042static void bgp_clear_node_queue_init(struct peer *peer)
200df115 5043{
d62a17ae 5044 char wname[sizeof("clear xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
5045
5046 snprintf(wname, sizeof(wname), "clear %s", peer->host);
5047#undef CLEAR_QUEUE_NAME_LEN
5048
0ce1ca80 5049 peer->clear_node_queue = work_queue_new(bm->master, wname);
d62a17ae 5050 peer->clear_node_queue->spec.hold = 10;
5051 peer->clear_node_queue->spec.workfunc = &bgp_clear_route_node;
5052 peer->clear_node_queue->spec.del_item_data = &bgp_clear_node_queue_del;
5053 peer->clear_node_queue->spec.completion_func = &bgp_clear_node_complete;
5054 peer->clear_node_queue->spec.max_retries = 0;
5055
5056 /* we only 'lock' this peer reference when the queue is actually active
5057 */
5058 peer->clear_node_queue->spec.data = peer;
65ca75e0
PJ
5059}
5060
d62a17ae 5061static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi,
5062 struct bgp_table *table)
65ca75e0 5063{
9bcb3eef 5064 struct bgp_dest *dest;
b6c386bb 5065 int force = peer->bgp->process_queue ? 0 : 1;
6cf159b9 5066
d62a17ae 5067 if (!table)
5068 table = peer->bgp->rib[afi][safi];
dc83d712 5069
d62a17ae 5070 /* If still no table => afi/safi isn't configured at all or smth. */
5071 if (!table)
5072 return;
dc83d712 5073
9bcb3eef 5074 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
40381db7 5075 struct bgp_path_info *pi, *next;
d62a17ae 5076 struct bgp_adj_in *ain;
5077 struct bgp_adj_in *ain_next;
5078
5079 /* XXX:TODO: This is suboptimal, every non-empty route_node is
5080 * queued for every clearing peer, regardless of whether it is
5081 * relevant to the peer at hand.
5082 *
5083 * Overview: There are 3 different indices which need to be
5084 * scrubbed, potentially, when a peer is removed:
5085 *
5086 * 1 peer's routes visible via the RIB (ie accepted routes)
5087 * 2 peer's routes visible by the (optional) peer's adj-in index
5088 * 3 other routes visible by the peer's adj-out index
5089 *
5090 * 3 there is no hurry in scrubbing, once the struct peer is
5091 * removed from bgp->peer, we could just GC such deleted peer's
5092 * adj-outs at our leisure.
5093 *
5094 * 1 and 2 must be 'scrubbed' in some way, at least made
5095 * invisible via RIB index before peer session is allowed to be
5096 * brought back up. So one needs to know when such a 'search' is
5097 * complete.
5098 *
5099 * Ideally:
5100 *
5101 * - there'd be a single global queue or a single RIB walker
5102 * - rather than tracking which route_nodes still need to be
5103 * examined on a peer basis, we'd track which peers still
5104 * aren't cleared
5105 *
5106 * Given that our per-peer prefix-counts now should be reliable,
5107 * this may actually be achievable. It doesn't seem to be a huge
5108 * problem at this time,
5109 *
5110 * It is possible that we have multiple paths for a prefix from
5111 * a peer
5112 * if that peer is using AddPath.
5113 */
9bcb3eef 5114 ain = dest->adj_in;
d62a17ae 5115 while (ain) {
5116 ain_next = ain->next;
5117
6a840fd9 5118 if (ain->peer == peer)
9bcb3eef 5119 bgp_adj_in_remove(dest, ain);
d62a17ae 5120
5121 ain = ain_next;
5122 }
5123
9bcb3eef 5124 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
40381db7
DS
5125 next = pi->next;
5126 if (pi->peer != peer)
d62a17ae 5127 continue;
5128
5129 if (force)
9bcb3eef 5130 bgp_path_info_reap(dest, pi);
d62a17ae 5131 else {
5132 struct bgp_clear_node_queue *cnq;
5133
5134 /* both unlocked in bgp_clear_node_queue_del */
9bcb3eef
DS
5135 bgp_table_lock(bgp_dest_table(dest));
5136 bgp_dest_lock_node(dest);
d62a17ae 5137 cnq = XCALLOC(
5138 MTYPE_BGP_CLEAR_NODE_QUEUE,
5139 sizeof(struct bgp_clear_node_queue));
9bcb3eef 5140 cnq->dest = dest;
d62a17ae 5141 work_queue_add(peer->clear_node_queue, cnq);
5142 break;
5143 }
5144 }
5145 }
5146 return;
5147}
5148
5149void bgp_clear_route(struct peer *peer, afi_t afi, safi_t safi)
5150{
9bcb3eef 5151 struct bgp_dest *dest;
d62a17ae 5152 struct bgp_table *table;
5153
5154 if (peer->clear_node_queue == NULL)
5155 bgp_clear_node_queue_init(peer);
5156
5157 /* bgp_fsm.c keeps sessions in state Clearing, not transitioning to
5158 * Idle until it receives a Clearing_Completed event. This protects
5159 * against peers which flap faster than we can we clear, which could
5160 * lead to:
5161 *
5162 * a) race with routes from the new session being installed before
5163 * clear_route_node visits the node (to delete the route of that
5164 * peer)
5165 * b) resource exhaustion, clear_route_node likely leads to an entry
5166 * on the process_main queue. Fast-flapping could cause that queue
5167 * to grow and grow.
5168 */
5169
5170 /* lock peer in assumption that clear-node-queue will get nodes; if so,
5171 * the unlock will happen upon work-queue completion; other wise, the
5172 * unlock happens at the end of this function.
5173 */
5174 if (!peer->clear_node_queue->thread)
5175 peer_lock(peer);
5176
5177 if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN)
5178 bgp_clear_route_table(peer, afi, safi, NULL);
5179 else
9bcb3eef
DS
5180 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5181 dest = bgp_route_next(dest)) {
5182 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5183 if (!table)
5184 continue;
5185
5186 bgp_clear_route_table(peer, afi, safi, table);
5187 }
d62a17ae 5188
5189 /* unlock if no nodes got added to the clear-node-queue. */
5190 if (!peer->clear_node_queue->thread)
5191 peer_unlock(peer);
718e3744 5192}
d62a17ae 5193
5194void bgp_clear_route_all(struct peer *peer)
718e3744 5195{
d62a17ae 5196 afi_t afi;
5197 safi_t safi;
718e3744 5198
05c7a1cc
QY
5199 FOREACH_AFI_SAFI (afi, safi)
5200 bgp_clear_route(peer, afi, safi);
65efcfce 5201
49e5a4a0 5202#ifdef ENABLE_BGP_VNC
d62a17ae 5203 rfapiProcessPeerDown(peer);
65efcfce 5204#endif
718e3744 5205}
5206
d62a17ae 5207void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5208{
d62a17ae 5209 struct bgp_table *table;
9bcb3eef 5210 struct bgp_dest *dest;
d62a17ae 5211 struct bgp_adj_in *ain;
5212 struct bgp_adj_in *ain_next;
718e3744 5213
d62a17ae 5214 table = peer->bgp->rib[afi][safi];
718e3744 5215
d62a17ae 5216 /* It is possible that we have multiple paths for a prefix from a peer
5217 * if that peer is using AddPath.
5218 */
9bcb3eef
DS
5219 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
5220 ain = dest->adj_in;
43143c8f 5221
d62a17ae 5222 while (ain) {
5223 ain_next = ain->next;
43143c8f 5224
6a840fd9 5225 if (ain->peer == peer)
9bcb3eef 5226 bgp_adj_in_remove(dest, ain);
43143c8f 5227
d62a17ae 5228 ain = ain_next;
5229 }
5230 }
718e3744 5231}
93406d87 5232
d62a17ae 5233void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5234{
9bcb3eef 5235 struct bgp_dest *dest;
40381db7 5236 struct bgp_path_info *pi;
d62a17ae 5237 struct bgp_table *table;
5238
9af52ccf 5239 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
9bcb3eef
DS
5240 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5241 dest = bgp_route_next(dest)) {
5242 struct bgp_dest *rm;
d62a17ae 5243
5244 /* look for neighbor in tables */
9bcb3eef 5245 table = bgp_dest_get_bgp_table_info(dest);
67009e22 5246 if (!table)
ea47320b
DL
5247 continue;
5248
5249 for (rm = bgp_table_top(table); rm;
5250 rm = bgp_route_next(rm))
9bcb3eef 5251 for (pi = bgp_dest_get_bgp_path_info(rm); pi;
6f94b685 5252 pi = pi->next) {
40381db7 5253 if (pi->peer != peer)
ea47320b 5254 continue;
40381db7 5255 if (!CHECK_FLAG(pi->flags,
1defdda8 5256 BGP_PATH_STALE))
ea47320b
DL
5257 break;
5258
40381db7 5259 bgp_rib_remove(rm, pi, peer, afi, safi);
ea47320b
DL
5260 break;
5261 }
d62a17ae 5262 }
5263 } else {
9bcb3eef
DS
5264 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5265 dest = bgp_route_next(dest))
5266 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
6f94b685 5267 pi = pi->next) {
40381db7 5268 if (pi->peer != peer)
ea47320b 5269 continue;
40381db7 5270 if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE))
d62a17ae 5271 break;
9bcb3eef 5272 bgp_rib_remove(dest, pi, peer, afi, safi);
ea47320b
DL
5273 break;
5274 }
d62a17ae 5275 }
93406d87 5276}
6b0655a2 5277
9af52ccf
DA
5278void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
5279{
5280 struct bgp_dest *dest, *ndest;
5281 struct bgp_path_info *pi;
5282 struct bgp_table *table;
5283
5284 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
5285 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5286 dest = bgp_route_next(dest)) {
5287 table = bgp_dest_get_bgp_table_info(dest);
5288 if (!table)
5289 continue;
5290
5291 for (ndest = bgp_table_top(table); ndest;
5292 ndest = bgp_route_next(ndest)) {
5293 for (pi = bgp_dest_get_bgp_path_info(ndest); pi;
5294 pi = pi->next) {
5295 if (pi->peer != peer)
5296 continue;
5297
5298 if ((CHECK_FLAG(
5299 peer->af_sflags[afi][safi],
5300 PEER_STATUS_ENHANCED_REFRESH))
5301 && !CHECK_FLAG(pi->flags,
5302 BGP_PATH_STALE)
5303 && !CHECK_FLAG(
5304 pi->flags,
5305 BGP_PATH_UNUSEABLE)) {
5306 if (bgp_debug_neighbor_events(
5307 peer))
5308 zlog_debug(
5309 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5310 peer->host,
5311 afi2str(afi),
5312 safi2str(safi),
5313 bgp_dest_get_prefix(
5314 ndest));
5315
5316 bgp_path_info_set_flag(
5317 ndest, pi,
5318 BGP_PATH_STALE);
5319 }
5320 }
5321 }
5322 }
5323 } else {
5324 for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
5325 dest = bgp_route_next(dest)) {
5326 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
5327 pi = pi->next) {
5328 if (pi->peer != peer)
5329 continue;
5330
5331 if ((CHECK_FLAG(peer->af_sflags[afi][safi],
5332 PEER_STATUS_ENHANCED_REFRESH))
5333 && !CHECK_FLAG(pi->flags, BGP_PATH_STALE)
5334 && !CHECK_FLAG(pi->flags,
5335 BGP_PATH_UNUSEABLE)) {
5336 if (bgp_debug_neighbor_events(peer))
5337 zlog_debug(
5338 "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
5339 peer->host,
5340 afi2str(afi),
5341 safi2str(safi),
5342 bgp_dest_get_prefix(
5343 dest));
5344
5345 bgp_path_info_set_flag(dest, pi,
5346 BGP_PATH_STALE);
5347 }
5348 }
5349 }
5350 }
5351}
5352
3dc339cd 5353bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5354{
e0df4c04 5355 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5356 return true;
e0df4c04 5357
9dac9fc8
DA
5358 if (peer->sort == BGP_PEER_EBGP
5359 && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter)
5360 || FILTER_LIST_OUT_NAME(filter)
5361 || DISTRIBUTE_OUT_NAME(filter)))
3dc339cd
DA
5362 return true;
5363 return false;
9dac9fc8
DA
5364}
5365
3dc339cd 5366bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
9dac9fc8 5367{
e0df4c04 5368 if (peer->sort == BGP_PEER_IBGP)
3dc339cd 5369 return true;
e0df4c04 5370
9dac9fc8
DA
5371 if (peer->sort == BGP_PEER_EBGP
5372 && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter)
5373 || FILTER_LIST_IN_NAME(filter)
5374 || DISTRIBUTE_IN_NAME(filter)))
3dc339cd
DA
5375 return true;
5376 return false;
9dac9fc8
DA
5377}
5378
568e10ca 5379static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
5380 safi_t safi)
bb86c601 5381{
9bcb3eef 5382 struct bgp_dest *dest;
40381db7 5383 struct bgp_path_info *pi;
4b7e6066 5384 struct bgp_path_info *next;
bb86c601 5385
9bcb3eef
DS
5386 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
5387 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = next) {
5388 const struct prefix *p = bgp_dest_get_prefix(dest);
b54892e0 5389
40381db7 5390 next = pi->next;
1b7bb747
CS
5391
5392 /* Unimport EVPN routes from VRFs */
5393 if (safi == SAFI_EVPN)
5394 bgp_evpn_unimport_route(bgp, AFI_L2VPN,
b54892e0 5395 SAFI_EVPN, p, pi);
1b7bb747 5396
40381db7
DS
5397 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
5398 && pi->type == ZEBRA_ROUTE_BGP
5399 && (pi->sub_type == BGP_ROUTE_NORMAL
5400 || pi->sub_type == BGP_ROUTE_AGGREGATE
5401 || pi->sub_type == BGP_ROUTE_IMPORTED)) {
ddb5b488 5402
d62a17ae 5403 if (bgp_fibupd_safi(safi))
b54892e0 5404 bgp_zebra_withdraw(p, pi, bgp, safi);
d62a17ae 5405 }
9514b37d 5406
9bcb3eef 5407 bgp_path_info_reap(dest, pi);
d62a17ae 5408 }
bb86c601
LB
5409}
5410
718e3744 5411/* Delete all kernel routes. */
d62a17ae 5412void bgp_cleanup_routes(struct bgp *bgp)
5413{
5414 afi_t afi;
9bcb3eef 5415 struct bgp_dest *dest;
67009e22 5416 struct bgp_table *table;
d62a17ae 5417
5418 for (afi = AFI_IP; afi < AFI_MAX; ++afi) {
5419 if (afi == AFI_L2VPN)
5420 continue;
568e10ca 5421 bgp_cleanup_table(bgp, bgp->rib[afi][SAFI_UNICAST],
5422 SAFI_UNICAST);
d62a17ae 5423 /*
5424 * VPN and ENCAP and EVPN tables are two-level (RD is top level)
5425 */
5426 if (afi != AFI_L2VPN) {
5427 safi_t safi;
5428 safi = SAFI_MPLS_VPN;
9bcb3eef
DS
5429 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5430 dest = bgp_route_next(dest)) {
5431 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5432 if (table != NULL) {
5433 bgp_cleanup_table(bgp, table, safi);
5434 bgp_table_finish(&table);
9bcb3eef
DS
5435 bgp_dest_set_bgp_table_info(dest, NULL);
5436 bgp_dest_unlock_node(dest);
d62a17ae 5437 }
5438 }
5439 safi = SAFI_ENCAP;
9bcb3eef
DS
5440 for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
5441 dest = bgp_route_next(dest)) {
5442 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5443 if (table != NULL) {
5444 bgp_cleanup_table(bgp, table, safi);
5445 bgp_table_finish(&table);
9bcb3eef
DS
5446 bgp_dest_set_bgp_table_info(dest, NULL);
5447 bgp_dest_unlock_node(dest);
d62a17ae 5448 }
5449 }
5450 }
5451 }
9bcb3eef
DS
5452 for (dest = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); dest;
5453 dest = bgp_route_next(dest)) {
5454 table = bgp_dest_get_bgp_table_info(dest);
67009e22
DS
5455 if (table != NULL) {
5456 bgp_cleanup_table(bgp, table, SAFI_EVPN);
5457 bgp_table_finish(&table);
9bcb3eef
DS
5458 bgp_dest_set_bgp_table_info(dest, NULL);
5459 bgp_dest_unlock_node(dest);
d62a17ae 5460 }
bb86c601 5461 }
718e3744 5462}
5463
d62a17ae 5464void bgp_reset(void)
718e3744 5465{
d62a17ae 5466 vty_reset();
5467 bgp_zclient_reset();
5468 access_list_reset();
5469 prefix_list_reset();
718e3744 5470}
6b0655a2 5471
d62a17ae 5472static int bgp_addpath_encode_rx(struct peer *peer, afi_t afi, safi_t safi)
adbac85e 5473{
d62a17ae 5474 return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV)
5475 && CHECK_FLAG(peer->af_cap[afi][safi],
5476 PEER_CAP_ADDPATH_AF_TX_RCV));
adbac85e
DW
5477}
5478
718e3744 5479/* Parse NLRI stream. Withdraw NLRI is recognized by NULL attr
5480 value. */
d62a17ae 5481int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
5482 struct bgp_nlri *packet)
5483{
d7c0a89a
QY
5484 uint8_t *pnt;
5485 uint8_t *lim;
d62a17ae 5486 struct prefix p;
5487 int psize;
5488 int ret;
5489 afi_t afi;
5490 safi_t safi;
5491 int addpath_encoded;
d7c0a89a 5492 uint32_t addpath_id;
d62a17ae 5493
d62a17ae 5494 pnt = packet->nlri;
5495 lim = pnt + packet->length;
5496 afi = packet->afi;
5497 safi = packet->safi;
5498 addpath_id = 0;
5499 addpath_encoded = bgp_addpath_encode_rx(peer, afi, safi);
5500
5501 /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
5502 syntactic validity. If the field is syntactically incorrect,
5503 then the Error Subcode is set to Invalid Network Field. */
5504 for (; pnt < lim; pnt += psize) {
5505 /* Clear prefix structure. */
5506 memset(&p, 0, sizeof(struct prefix));
5507
5508 if (addpath_encoded) {
5509
5510 /* When packet overflow occurs return immediately. */
761ed665 5511 if (pnt + BGP_ADDPATH_ID_LEN >= lim)
513386b5 5512 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5513
a3a850a1 5514 memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
454d85cf 5515 addpath_id = ntohl(addpath_id);
d62a17ae 5516 pnt += BGP_ADDPATH_ID_LEN;
5517 }
718e3744 5518
d62a17ae 5519 /* Fetch prefix length. */
5520 p.prefixlen = *pnt++;
5521 /* afi/safi validity already verified by caller,
5522 * bgp_update_receive */
5523 p.family = afi2family(afi);
5524
5525 /* Prefix length check. */
5526 if (p.prefixlen > prefix_blen(&p) * 8) {
af4c2728 5527 flog_err(
e50f7cfd 5528 EC_BGP_UPDATE_RCV,
14454c9f 5529 "%s [Error] Update packet error (wrong prefix length %d for afi %u)",
d62a17ae 5530 peer->host, p.prefixlen, packet->afi);
513386b5 5531 return BGP_NLRI_PARSE_ERROR_PREFIX_LENGTH;
d62a17ae 5532 }
6b0655a2 5533
d62a17ae 5534 /* Packet size overflow check. */
5535 psize = PSIZE(p.prefixlen);
5536
5537 /* When packet overflow occur return immediately. */
5538 if (pnt + psize > lim) {
af4c2728 5539 flog_err(
e50f7cfd 5540 EC_BGP_UPDATE_RCV,
d62a17ae 5541 "%s [Error] Update packet error (prefix length %d overflows packet)",
5542 peer->host, p.prefixlen);
513386b5 5543 return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
d62a17ae 5544 }
5545
5546 /* Defensive coding, double-check the psize fits in a struct
5547 * prefix */
5548 if (psize > (ssize_t)sizeof(p.u)) {
af4c2728 5549 flog_err(
e50f7cfd 5550 EC_BGP_UPDATE_RCV,
d62a17ae 5551 "%s [Error] Update packet error (prefix length %d too large for prefix storage %zu)",
5552 peer->host, p.prefixlen, sizeof(p.u));
513386b5 5553 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5554 }
5555
5556 /* Fetch prefix from NLRI packet. */
a85297a7 5557 memcpy(p.u.val, pnt, psize);
d62a17ae 5558
5559 /* Check address. */
5560 if (afi == AFI_IP && safi == SAFI_UNICAST) {
5561 if (IN_CLASSD(ntohl(p.u.prefix4.s_addr))) {
5562 /* From RFC4271 Section 6.3:
5563 *
5564 * If a prefix in the NLRI field is semantically
5565 * incorrect
5566 * (e.g., an unexpected multicast IP address),
5567 * an error SHOULD
5568 * be logged locally, and the prefix SHOULD be
5569 * ignored.
a4d82a8a 5570 */
af4c2728 5571 flog_err(
e50f7cfd 5572 EC_BGP_UPDATE_RCV,
23d0a753
DA
5573 "%s: IPv4 unicast NLRI is multicast address %pI4, ignoring",
5574 peer->host, &p.u.prefix4);
d62a17ae 5575 continue;
5576 }
5577 }
5578
5579 /* Check address. */
5580 if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
5581 if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
af4c2728 5582 flog_err(
e50f7cfd 5583 EC_BGP_UPDATE_RCV,
c0d72166
DS
5584 "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
5585 peer->host, &p.u.prefix6);
d62a17ae 5586
5587 continue;
5588 }
5589 if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
af4c2728 5590 flog_err(
e50f7cfd 5591 EC_BGP_UPDATE_RCV,
c0d72166
DS
5592 "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
5593 peer->host, &p.u.prefix6);
d62a17ae 5594
5595 continue;
5596 }
5597 }
5598
5599 /* Normal process. */
5600 if (attr)
5601 ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
5602 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
b57ba6d2 5603 NULL, NULL, 0, 0, NULL);
d62a17ae 5604 else
5605 ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
5606 safi, ZEBRA_ROUTE_BGP,
a4d82a8a
PZ
5607 BGP_ROUTE_NORMAL, NULL, NULL, 0,
5608 NULL);
d62a17ae 5609
513386b5
DA
5610 /* Do not send BGP notification twice when maximum-prefix count
5611 * overflow. */
5612 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5613 return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
5614
5615 /* Address family configuration mismatch. */
d62a17ae 5616 if (ret < 0)
513386b5 5617 return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
d62a17ae 5618 }
5619
5620 /* Packet length consistency check. */
5621 if (pnt != lim) {
af4c2728 5622 flog_err(
e50f7cfd 5623 EC_BGP_UPDATE_RCV,
d62a17ae 5624 "%s [Error] Update packet error (prefix length mismatch with total length)",
5625 peer->host);
513386b5 5626 return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
d62a17ae 5627 }
6b0655a2 5628
513386b5 5629 return BGP_NLRI_PARSE_OK;
718e3744 5630}
5631
d62a17ae 5632static struct bgp_static *bgp_static_new(void)
718e3744 5633{
d62a17ae 5634 return XCALLOC(MTYPE_BGP_STATIC, sizeof(struct bgp_static));
718e3744 5635}
5636
d62a17ae 5637static void bgp_static_free(struct bgp_static *bgp_static)
fee0f4c6 5638{
0a22ddfb 5639 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 5640 route_map_counter_decrement(bgp_static->rmap.map);
5641
0a22ddfb 5642 XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
d62a17ae 5643 XFREE(MTYPE_BGP_STATIC, bgp_static);
5644}
5645
5f040085 5646void bgp_static_update(struct bgp *bgp, const struct prefix *p,
d62a17ae 5647 struct bgp_static *bgp_static, afi_t afi, safi_t safi)
5648{
9bcb3eef 5649 struct bgp_dest *dest;
40381db7 5650 struct bgp_path_info *pi;
4b7e6066 5651 struct bgp_path_info *new;
40381db7 5652 struct bgp_path_info rmap_path;
d62a17ae 5653 struct attr attr;
5654 struct attr *attr_new;
b68885f9 5655 route_map_result_t ret;
49e5a4a0 5656#ifdef ENABLE_BGP_VNC
d62a17ae 5657 int vnc_implicit_withdraw = 0;
65efcfce 5658#endif
fee0f4c6 5659
d62a17ae 5660 assert(bgp_static);
dd8103a9 5661
9bcb3eef 5662 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5663
d62a17ae 5664 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
718e3744 5665
d62a17ae 5666 attr.nexthop = bgp_static->igpnexthop;
5667 attr.med = bgp_static->igpmetric;
5668 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
41367172 5669
d62a17ae 5670 if (bgp_static->atomic)
5671 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
6cf48acc 5672
d62a17ae 5673 /* Store label index, if required. */
5674 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) {
5675 attr.label_index = bgp_static->label_index;
5676 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
5677 }
718e3744 5678
d62a17ae 5679 /* Apply route-map. */
5680 if (bgp_static->rmap.name) {
5681 struct attr attr_tmp = attr;
80ced710 5682
40381db7
DS
5683 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
5684 rmap_path.peer = bgp->peer_self;
5685 rmap_path.attr = &attr_tmp;
fee0f4c6 5686
d62a17ae 5687 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
286e1e71 5688
1782514f 5689 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
fee0f4c6 5690
d62a17ae 5691 bgp->peer_self->rmap_type = 0;
718e3744 5692
d62a17ae 5693 if (ret == RMAP_DENYMATCH) {
5694 /* Free uninterned attribute. */
5695 bgp_attr_flush(&attr_tmp);
718e3744 5696
d62a17ae 5697 /* Unintern original. */
5698 aspath_unintern(&attr.aspath);
5699 bgp_static_withdraw(bgp, p, afi, safi);
5700 return;
5701 }
7f323236 5702
637e5ba4 5703 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5704 bgp_attr_add_gshut_community(&attr_tmp);
5705
d62a17ae 5706 attr_new = bgp_attr_intern(&attr_tmp);
7f323236
DW
5707 } else {
5708
637e5ba4 5709 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
5710 bgp_attr_add_gshut_community(&attr);
5711
d62a17ae 5712 attr_new = bgp_attr_intern(&attr);
7f323236 5713 }
718e3744 5714
9bcb3eef 5715 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5716 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5717 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5718 break;
5719
40381db7
DS
5720 if (pi) {
5721 if (attrhash_cmp(pi->attr, attr_new)
5722 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
892fedb6 5723 && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
9bcb3eef 5724 bgp_dest_unlock_node(dest);
d62a17ae 5725 bgp_attr_unintern(&attr_new);
5726 aspath_unintern(&attr.aspath);
5727 return;
5728 } else {
5729 /* The attribute is changed. */
9bcb3eef 5730 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 5731
5732 /* Rewrite BGP route information. */
40381db7 5733 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 5734 bgp_path_info_restore(dest, pi);
d62a17ae 5735 else
40381db7 5736 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
49e5a4a0 5737#ifdef ENABLE_BGP_VNC
d62a17ae 5738 if ((afi == AFI_IP || afi == AFI_IP6)
5739 && (safi == SAFI_UNICAST)) {
40381db7 5740 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 5741 /*
5742 * Implicit withdraw case.
40381db7 5743 * We have to do this before pi is
d62a17ae 5744 * changed
5745 */
5746 ++vnc_implicit_withdraw;
40381db7 5747 vnc_import_bgp_del_route(bgp, p, pi);
d62a17ae 5748 vnc_import_bgp_exterior_del_route(
40381db7 5749 bgp, p, pi);
d62a17ae 5750 }
5751 }
65efcfce 5752#endif
40381db7
DS
5753 bgp_attr_unintern(&pi->attr);
5754 pi->attr = attr_new;
5755 pi->uptime = bgp_clock();
49e5a4a0 5756#ifdef ENABLE_BGP_VNC
d62a17ae 5757 if ((afi == AFI_IP || afi == AFI_IP6)
5758 && (safi == SAFI_UNICAST)) {
5759 if (vnc_implicit_withdraw) {
40381db7 5760 vnc_import_bgp_add_route(bgp, p, pi);
d62a17ae 5761 vnc_import_bgp_exterior_add_route(
40381db7 5762 bgp, p, pi);
d62a17ae 5763 }
5764 }
65efcfce 5765#endif
718e3744 5766
d62a17ae 5767 /* Nexthop reachability check. */
892fedb6 5768 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5769 && (safi == SAFI_UNICAST
5770 || safi == SAFI_LABELED_UNICAST)) {
960035b2
PZ
5771
5772 struct bgp *bgp_nexthop = bgp;
5773
40381db7
DS
5774 if (pi->extra && pi->extra->bgp_orig)
5775 bgp_nexthop = pi->extra->bgp_orig;
960035b2
PZ
5776
5777 if (bgp_find_or_add_nexthop(bgp, bgp_nexthop,
4053e952 5778 afi, safi, pi, NULL,
654a5978 5779 0, p))
9bcb3eef 5780 bgp_path_info_set_flag(dest, pi,
18ee8310 5781 BGP_PATH_VALID);
d62a17ae 5782 else {
5783 if (BGP_DEBUG(nht, NHT)) {
5784 char buf1[INET6_ADDRSTRLEN];
5785 inet_ntop(p->family,
5786 &p->u.prefix, buf1,
5787 INET6_ADDRSTRLEN);
5788 zlog_debug(
5789 "%s(%s): Route not in table, not advertising",
15569c58 5790 __func__, buf1);
d62a17ae 5791 }
18ee8310 5792 bgp_path_info_unset_flag(
9bcb3eef 5793 dest, pi, BGP_PATH_VALID);
d62a17ae 5794 }
5795 } else {
5796 /* Delete the NHT structure if any, if we're
5797 * toggling between
5798 * enabling/disabling import check. We
5799 * deregister the route
5800 * from NHT to avoid overloading NHT and the
5801 * process interaction
5802 */
40381db7 5803 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5804 bgp_path_info_set_flag(dest, pi,
5805 BGP_PATH_VALID);
d62a17ae 5806 }
5807 /* Process change. */
40381db7 5808 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 5809 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
5810
5811 if (SAFI_UNICAST == safi
5812 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5813 || bgp->inst_type
5814 == BGP_INSTANCE_TYPE_DEFAULT)) {
5815 vpn_leak_from_vrf_update(bgp_get_default(), bgp,
40381db7 5816 pi);
ddb5b488
PZ
5817 }
5818
9bcb3eef 5819 bgp_dest_unlock_node(dest);
d62a17ae 5820 aspath_unintern(&attr.aspath);
5821 return;
5822 }
718e3744 5823 }
718e3744 5824
d62a17ae 5825 /* Make new BGP info. */
5826 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 5827 attr_new, dest);
d62a17ae 5828 /* Nexthop reachability check. */
892fedb6 5829 if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
d62a17ae 5830 && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
654a5978
PG
5831 if (bgp_find_or_add_nexthop(bgp, bgp, afi, safi, new, NULL, 0,
5832 p))
9bcb3eef 5833 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5834 else {
5835 if (BGP_DEBUG(nht, NHT)) {
5836 char buf1[INET6_ADDRSTRLEN];
5837 inet_ntop(p->family, &p->u.prefix, buf1,
5838 INET6_ADDRSTRLEN);
5839 zlog_debug(
5840 "%s(%s): Route not in table, not advertising",
15569c58 5841 __func__, buf1);
d62a17ae 5842 }
9bcb3eef 5843 bgp_path_info_unset_flag(dest, new, BGP_PATH_VALID);
d62a17ae 5844 }
5845 } else {
5846 /* Delete the NHT structure if any, if we're toggling between
5847 * enabling/disabling import check. We deregister the route
5848 * from NHT to avoid overloading NHT and the process interaction
5849 */
5850 bgp_unlink_nexthop(new);
5851
9bcb3eef 5852 bgp_path_info_set_flag(dest, new, BGP_PATH_VALID);
fc9a856f 5853 }
078430f6 5854
d62a17ae 5855 /* Aggregate address increment. */
5856 bgp_aggregate_increment(bgp, p, new, afi, safi);
718e3744 5857
d62a17ae 5858 /* Register new BGP information. */
9bcb3eef 5859 bgp_path_info_add(dest, new);
718e3744 5860
d62a17ae 5861 /* route_node_get lock */
9bcb3eef 5862 bgp_dest_unlock_node(dest);
d62a17ae 5863
5864 /* Process change. */
9bcb3eef 5865 bgp_process(bgp, dest, afi, safi);
d62a17ae 5866
ddb5b488
PZ
5867 if (SAFI_UNICAST == safi
5868 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5869 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
5870 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
5871 }
5872
d62a17ae 5873 /* Unintern original. */
5874 aspath_unintern(&attr.aspath);
718e3744 5875}
5876
5f040085 5877void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
d62a17ae 5878 safi_t safi)
718e3744 5879{
9bcb3eef 5880 struct bgp_dest *dest;
40381db7 5881 struct bgp_path_info *pi;
718e3744 5882
9bcb3eef 5883 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL);
718e3744 5884
d62a17ae 5885 /* Check selected route and self inserted route. */
9bcb3eef 5886 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5887 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5888 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5889 break;
5890
5891 /* Withdraw static BGP route from routing table. */
40381db7 5892 if (pi) {
ddb5b488
PZ
5893 if (SAFI_UNICAST == safi
5894 && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
5895 || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
40381db7 5896 vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi);
ddb5b488 5897 }
40381db7
DS
5898 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
5899 bgp_unlink_nexthop(pi);
9bcb3eef
DS
5900 bgp_path_info_delete(dest, pi);
5901 bgp_process(bgp, dest, afi, safi);
d62a17ae 5902 }
718e3744 5903
d62a17ae 5904 /* Unlock bgp_node_lookup. */
9bcb3eef 5905 bgp_dest_unlock_node(dest);
718e3744 5906}
5907
137446f9
LB
5908/*
5909 * Used for SAFI_MPLS_VPN and SAFI_ENCAP
5910 */
5f040085 5911static void bgp_static_withdraw_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5912 afi_t afi, safi_t safi,
5913 struct prefix_rd *prd)
718e3744 5914{
9bcb3eef 5915 struct bgp_dest *dest;
40381db7 5916 struct bgp_path_info *pi;
718e3744 5917
9bcb3eef 5918 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
718e3744 5919
d62a17ae 5920 /* Check selected route and self inserted route. */
9bcb3eef 5921 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
5922 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
5923 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 5924 break;
718e3744 5925
d62a17ae 5926 /* Withdraw static BGP route from routing table. */
40381db7 5927 if (pi) {
49e5a4a0 5928#ifdef ENABLE_BGP_VNC
d62a17ae 5929 rfapiProcessWithdraw(
40381db7 5930 pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type,
d62a17ae 5931 1); /* Kill, since it is an administrative change */
65efcfce 5932#endif
ddb5b488
PZ
5933 if (SAFI_MPLS_VPN == safi
5934 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 5935 vpn_leak_to_vrf_withdraw(bgp, pi);
ddb5b488 5936 }
40381db7 5937 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
9bcb3eef
DS
5938 bgp_path_info_delete(dest, pi);
5939 bgp_process(bgp, dest, afi, safi);
d62a17ae 5940 }
718e3744 5941
d62a17ae 5942 /* Unlock bgp_node_lookup. */
9bcb3eef 5943 bgp_dest_unlock_node(dest);
718e3744 5944}
5945
5f040085 5946static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
d62a17ae 5947 struct bgp_static *bgp_static, afi_t afi,
5948 safi_t safi)
137446f9 5949{
9bcb3eef 5950 struct bgp_dest *dest;
4b7e6066 5951 struct bgp_path_info *new;
d62a17ae 5952 struct attr *attr_new;
5953 struct attr attr = {0};
40381db7 5954 struct bgp_path_info *pi;
49e5a4a0 5955#ifdef ENABLE_BGP_VNC
d62a17ae 5956 mpls_label_t label = 0;
65efcfce 5957#endif
d7c0a89a 5958 uint32_t num_labels = 0;
d62a17ae 5959 union gw_addr add;
137446f9 5960
d62a17ae 5961 assert(bgp_static);
137446f9 5962
b57ba6d2
MK
5963 if (bgp_static->label != MPLS_INVALID_LABEL)
5964 num_labels = 1;
9bcb3eef
DS
5965 dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p,
5966 &bgp_static->prd);
137446f9 5967
d62a17ae 5968 bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
137446f9 5969
d62a17ae 5970 attr.nexthop = bgp_static->igpnexthop;
5971 attr.med = bgp_static->igpmetric;
5972 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
137446f9 5973
d62a17ae 5974 if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN)
5975 || (safi == SAFI_ENCAP)) {
5976 if (afi == AFI_IP) {
5977 attr.mp_nexthop_global_in = bgp_static->igpnexthop;
5978 attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
5979 }
5980 }
5981 if (afi == AFI_L2VPN) {
5982 if (bgp_static->gatewayIp.family == AF_INET)
5983 add.ipv4.s_addr =
5984 bgp_static->gatewayIp.u.prefix4.s_addr;
5985 else if (bgp_static->gatewayIp.family == AF_INET6)
5986 memcpy(&(add.ipv6), &(bgp_static->gatewayIp.u.prefix6),
5987 sizeof(struct in6_addr));
0a50c248 5988 memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t));
d62a17ae 5989 if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
5990 struct bgp_encap_type_vxlan bet;
5991 memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
3714a385 5992 bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
d62a17ae 5993 bgp_encap_type_vxlan_to_tlv(&bet, &attr);
5994 }
5995 if (bgp_static->router_mac) {
5996 bgp_add_routermac_ecom(&attr, bgp_static->router_mac);
5997 }
5998 }
5999 /* Apply route-map. */
6000 if (bgp_static->rmap.name) {
6001 struct attr attr_tmp = attr;
40381db7 6002 struct bgp_path_info rmap_path;
b68885f9 6003 route_map_result_t ret;
137446f9 6004
40381db7
DS
6005 rmap_path.peer = bgp->peer_self;
6006 rmap_path.attr = &attr_tmp;
137446f9 6007
d62a17ae 6008 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
137446f9 6009
1782514f 6010 ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
137446f9 6011
d62a17ae 6012 bgp->peer_self->rmap_type = 0;
137446f9 6013
d62a17ae 6014 if (ret == RMAP_DENYMATCH) {
6015 /* Free uninterned attribute. */
6016 bgp_attr_flush(&attr_tmp);
137446f9 6017
d62a17ae 6018 /* Unintern original. */
6019 aspath_unintern(&attr.aspath);
6020 bgp_static_withdraw_safi(bgp, p, afi, safi,
6021 &bgp_static->prd);
6022 return;
6023 }
137446f9 6024
d62a17ae 6025 attr_new = bgp_attr_intern(&attr_tmp);
6026 } else {
6027 attr_new = bgp_attr_intern(&attr);
6028 }
137446f9 6029
9bcb3eef 6030 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6031 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6032 && pi->sub_type == BGP_ROUTE_STATIC)
d62a17ae 6033 break;
6034
40381db7 6035 if (pi) {
d62a17ae 6036 memset(&add, 0, sizeof(union gw_addr));
40381db7 6037 if (attrhash_cmp(pi->attr, attr_new)
0a50c248 6038 && overlay_index_equal(afi, pi, &add)
40381db7 6039 && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
9bcb3eef 6040 bgp_dest_unlock_node(dest);
d62a17ae 6041 bgp_attr_unintern(&attr_new);
6042 aspath_unintern(&attr.aspath);
6043 return;
6044 } else {
6045 /* The attribute is changed. */
9bcb3eef 6046 bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
d62a17ae 6047
6048 /* Rewrite BGP route information. */
40381db7 6049 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
9bcb3eef 6050 bgp_path_info_restore(dest, pi);
d62a17ae 6051 else
40381db7
DS
6052 bgp_aggregate_decrement(bgp, p, pi, afi, safi);
6053 bgp_attr_unintern(&pi->attr);
6054 pi->attr = attr_new;
6055 pi->uptime = bgp_clock();
49e5a4a0 6056#ifdef ENABLE_BGP_VNC
40381db7
DS
6057 if (pi->extra)
6058 label = decode_label(&pi->extra->label[0]);
65efcfce 6059#endif
137446f9 6060
d62a17ae 6061 /* Process change. */
40381db7 6062 bgp_aggregate_increment(bgp, p, pi, afi, safi);
9bcb3eef 6063 bgp_process(bgp, dest, afi, safi);
ddb5b488
PZ
6064
6065 if (SAFI_MPLS_VPN == safi
6066 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
40381db7 6067 vpn_leak_to_vrf_update(bgp, pi);
ddb5b488 6068 }
49e5a4a0 6069#ifdef ENABLE_BGP_VNC
40381db7
DS
6070 rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd,
6071 pi->attr, afi, safi, pi->type,
6072 pi->sub_type, &label);
65efcfce 6073#endif
9bcb3eef 6074 bgp_dest_unlock_node(dest);
d62a17ae 6075 aspath_unintern(&attr.aspath);
6076 return;
6077 }
6078 }
137446f9
LB
6079
6080
d62a17ae 6081 /* Make new BGP info. */
6082 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
9bcb3eef 6083 attr_new, dest);
1defdda8 6084 SET_FLAG(new->flags, BGP_PATH_VALID);
18ee8310 6085 new->extra = bgp_path_info_extra_new();
b57ba6d2
MK
6086 if (num_labels) {
6087 new->extra->label[0] = bgp_static->label;
6088 new->extra->num_labels = num_labels;
6089 }
49e5a4a0 6090#ifdef ENABLE_BGP_VNC
d62a17ae 6091 label = decode_label(&bgp_static->label);
65efcfce 6092#endif
137446f9 6093
d62a17ae 6094 /* Aggregate address increment. */
6095 bgp_aggregate_increment(bgp, p, new, afi, safi);
137446f9 6096
d62a17ae 6097 /* Register new BGP information. */
9bcb3eef 6098 bgp_path_info_add(dest, new);
d62a17ae 6099 /* route_node_get lock */
9bcb3eef 6100 bgp_dest_unlock_node(dest);
137446f9 6101
d62a17ae 6102 /* Process change. */
9bcb3eef 6103 bgp_process(bgp, dest, afi, safi);
137446f9 6104
ddb5b488
PZ
6105 if (SAFI_MPLS_VPN == safi
6106 && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
6107 vpn_leak_to_vrf_update(bgp, new);
6108 }
49e5a4a0 6109#ifdef ENABLE_BGP_VNC
d62a17ae 6110 rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
6111 safi, new->type, new->sub_type, &label);
65efcfce
LB
6112#endif
6113
d62a17ae 6114 /* Unintern original. */
6115 aspath_unintern(&attr.aspath);
137446f9
LB
6116}
6117
718e3744 6118/* Configure static BGP network. When user don't run zebra, static
6119 route should be installed as valid. */
585f1adc
IR
6120static int bgp_static_set(struct vty *vty, const char *negate,
6121 const char *ip_str, afi_t afi, safi_t safi,
6122 const char *rmap, int backdoor, uint32_t label_index)
d62a17ae 6123{
585f1adc
IR
6124 VTY_DECLVAR_CONTEXT(bgp, bgp);
6125 int ret;
d62a17ae 6126 struct prefix p;
6127 struct bgp_static *bgp_static;
9bcb3eef 6128 struct bgp_dest *dest;
d7c0a89a 6129 uint8_t need_update = 0;
d62a17ae 6130
585f1adc
IR
6131 /* Convert IP prefix string to struct prefix. */
6132 ret = str2prefix(ip_str, &p);
6133 if (!ret) {
6134 vty_out(vty, "%% Malformed prefix\n");
6135 return CMD_WARNING_CONFIG_FAILED;
6136 }
6137 if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
6138 vty_out(vty, "%% Malformed prefix (link-local address)\n");
6139 return CMD_WARNING_CONFIG_FAILED;
6140 }
6141
d62a17ae 6142 apply_mask(&p);
718e3744 6143
e2a86ad9 6144 if (negate) {
718e3744 6145
e2a86ad9 6146 /* Set BGP static route configuration. */
9bcb3eef 6147 dest = bgp_node_lookup(bgp->route[afi][safi], &p);
d62a17ae 6148
9bcb3eef 6149 if (!dest) {
585f1adc
IR
6150 vty_out(vty, "%% Can't find static route specified\n");
6151 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6152 }
6153
9bcb3eef 6154 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6155
e2a86ad9
DS
6156 if ((label_index != BGP_INVALID_LABEL_INDEX)
6157 && (label_index != bgp_static->label_index)) {
585f1adc
IR
6158 vty_out(vty,
6159 "%% label-index doesn't match static route\n");
70d9b134 6160 bgp_dest_unlock_node(dest);
585f1adc 6161 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6162 }
d62a17ae 6163
e2a86ad9
DS
6164 if ((rmap && bgp_static->rmap.name)
6165 && strcmp(rmap, bgp_static->rmap.name)) {
585f1adc
IR
6166 vty_out(vty,
6167 "%% route-map name doesn't match static route\n");
70d9b134 6168 bgp_dest_unlock_node(dest);
585f1adc 6169 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 6170 }
718e3744 6171
e2a86ad9
DS
6172 /* Update BGP RIB. */
6173 if (!bgp_static->backdoor)
6174 bgp_static_withdraw(bgp, &p, afi, safi);
718e3744 6175
e2a86ad9
DS
6176 /* Clear configuration. */
6177 bgp_static_free(bgp_static);
9bcb3eef
DS
6178 bgp_dest_set_bgp_static_info(dest, NULL);
6179 bgp_dest_unlock_node(dest);
6180 bgp_dest_unlock_node(dest);
e2a86ad9 6181 } else {
718e3744 6182
e2a86ad9 6183 /* Set BGP static route configuration. */
9bcb3eef
DS
6184 dest = bgp_node_get(bgp->route[afi][safi], &p);
6185 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 6186 if (bgp_static) {
e2a86ad9 6187 /* Configuration change. */
e2a86ad9
DS
6188 /* Label index cannot be changed. */
6189 if (bgp_static->label_index != label_index) {
585f1adc
IR
6190 vty_out(vty, "%% cannot change label-index\n");
6191 return CMD_WARNING_CONFIG_FAILED;
e2a86ad9 6192 }
d62a17ae 6193
e2a86ad9 6194 /* Check previous routes are installed into BGP. */
a4d82a8a
PZ
6195 if (bgp_static->valid
6196 && bgp_static->backdoor != backdoor)
e2a86ad9 6197 need_update = 1;
718e3744 6198
e2a86ad9 6199 bgp_static->backdoor = backdoor;
718e3744 6200
e2a86ad9 6201 if (rmap) {
0a22ddfb
QY
6202 XFREE(MTYPE_ROUTE_MAP_NAME,
6203 bgp_static->rmap.name);
b4897fa5 6204 route_map_counter_decrement(
6205 bgp_static->rmap.map);
e2a86ad9
DS
6206 bgp_static->rmap.name =
6207 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6208 bgp_static->rmap.map =
6209 route_map_lookup_by_name(rmap);
b4897fa5 6210 route_map_counter_increment(
6211 bgp_static->rmap.map);
e2a86ad9 6212 } else {
0a22ddfb
QY
6213 XFREE(MTYPE_ROUTE_MAP_NAME,
6214 bgp_static->rmap.name);
b4897fa5 6215 route_map_counter_decrement(
6216 bgp_static->rmap.map);
e2a86ad9
DS
6217 bgp_static->rmap.map = NULL;
6218 bgp_static->valid = 0;
6219 }
9bcb3eef 6220 bgp_dest_unlock_node(dest);
e2a86ad9
DS
6221 } else {
6222 /* New configuration. */
6223 bgp_static = bgp_static_new();
6224 bgp_static->backdoor = backdoor;
6225 bgp_static->valid = 0;
6226 bgp_static->igpmetric = 0;
975a328e 6227 bgp_static->igpnexthop.s_addr = INADDR_ANY;
e2a86ad9 6228 bgp_static->label_index = label_index;
718e3744 6229
e2a86ad9 6230 if (rmap) {
0a22ddfb
QY
6231 XFREE(MTYPE_ROUTE_MAP_NAME,
6232 bgp_static->rmap.name);
b4897fa5 6233 route_map_counter_decrement(
6234 bgp_static->rmap.map);
e2a86ad9
DS
6235 bgp_static->rmap.name =
6236 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
6237 bgp_static->rmap.map =
6238 route_map_lookup_by_name(rmap);
b4897fa5 6239 route_map_counter_increment(
6240 bgp_static->rmap.map);
e2a86ad9 6241 }
9bcb3eef 6242 bgp_dest_set_bgp_static_info(dest, bgp_static);
e2a86ad9 6243 }
d62a17ae 6244
e2a86ad9
DS
6245 bgp_static->valid = 1;
6246 if (need_update)
6247 bgp_static_withdraw(bgp, &p, afi, safi);
d62a17ae 6248
e2a86ad9
DS
6249 if (!bgp_static->backdoor)
6250 bgp_static_update(bgp, &p, bgp_static, afi, safi);
6251 }
d62a17ae 6252
585f1adc 6253 return CMD_SUCCESS;
d62a17ae 6254}
6255
6256void bgp_static_add(struct bgp *bgp)
6257{
6258 afi_t afi;
6259 safi_t safi;
9bcb3eef
DS
6260 struct bgp_dest *dest;
6261 struct bgp_dest *rm;
d62a17ae 6262 struct bgp_table *table;
6263 struct bgp_static *bgp_static;
6264
47fc6261 6265 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6266 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6267 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6268 dest = bgp_route_next(dest)) {
6269 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6270 continue;
ea47320b 6271
05c7a1cc
QY
6272 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6273 || (safi == SAFI_EVPN)) {
9bcb3eef 6274 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6275
6276 for (rm = bgp_table_top(table); rm;
6277 rm = bgp_route_next(rm)) {
a78beeb5 6278 bgp_static =
9bcb3eef 6279 bgp_dest_get_bgp_static_info(
5a8ba9fc 6280 rm);
9bcb3eef
DS
6281 bgp_static_update_safi(
6282 bgp, bgp_dest_get_prefix(rm),
6283 bgp_static, afi, safi);
d62a17ae 6284 }
05c7a1cc 6285 } else {
5a8ba9fc 6286 bgp_static_update(
9bcb3eef
DS
6287 bgp, bgp_dest_get_prefix(dest),
6288 bgp_dest_get_bgp_static_info(dest), afi,
5a8ba9fc 6289 safi);
ea47320b 6290 }
05c7a1cc 6291 }
47fc6261 6292 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
6aeb9e78
DS
6293}
6294
718e3744 6295/* Called from bgp_delete(). Delete all static routes from the BGP
6296 instance. */
d62a17ae 6297void bgp_static_delete(struct bgp *bgp)
6298{
6299 afi_t afi;
6300 safi_t safi;
9bcb3eef
DS
6301 struct bgp_dest *dest;
6302 struct bgp_dest *rm;
d62a17ae 6303 struct bgp_table *table;
6304 struct bgp_static *bgp_static;
6305
05c7a1cc 6306 FOREACH_AFI_SAFI (afi, safi)
9bcb3eef
DS
6307 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6308 dest = bgp_route_next(dest)) {
6309 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6310 continue;
ea47320b 6311
05c7a1cc
QY
6312 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6313 || (safi == SAFI_EVPN)) {
9bcb3eef 6314 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6315
6316 for (rm = bgp_table_top(table); rm;
6317 rm = bgp_route_next(rm)) {
a78beeb5 6318 bgp_static =
9bcb3eef 6319 bgp_dest_get_bgp_static_info(
5a8ba9fc 6320 rm);
c7d14ba6
PG
6321 if (!bgp_static)
6322 continue;
6323
05c7a1cc 6324 bgp_static_withdraw_safi(
9bcb3eef 6325 bgp, bgp_dest_get_prefix(rm),
b54892e0
DS
6326 AFI_IP, safi,
6327 (struct prefix_rd *)
9bcb3eef
DS
6328 bgp_dest_get_prefix(
6329 dest));
ea47320b 6330 bgp_static_free(bgp_static);
811c6797 6331 bgp_dest_set_bgp_static_info(rm,
9bcb3eef 6332 NULL);
811c6797 6333 bgp_dest_unlock_node(rm);
d62a17ae 6334 }
05c7a1cc 6335 } else {
9bcb3eef 6336 bgp_static = bgp_dest_get_bgp_static_info(dest);
b54892e0 6337 bgp_static_withdraw(bgp,
9bcb3eef 6338 bgp_dest_get_prefix(dest),
b54892e0 6339 afi, safi);
05c7a1cc 6340 bgp_static_free(bgp_static);
9bcb3eef
DS
6341 bgp_dest_set_bgp_static_info(dest, NULL);
6342 bgp_dest_unlock_node(dest);
ea47320b 6343 }
05c7a1cc 6344 }
d62a17ae 6345}
6346
6347void bgp_static_redo_import_check(struct bgp *bgp)
6348{
6349 afi_t afi;
6350 safi_t safi;
9bcb3eef
DS
6351 struct bgp_dest *dest;
6352 struct bgp_dest *rm;
d62a17ae 6353 struct bgp_table *table;
6354 struct bgp_static *bgp_static;
6355
6356 /* Use this flag to force reprocessing of the route */
892fedb6 6357 SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
05c7a1cc 6358 FOREACH_AFI_SAFI (afi, safi) {
9bcb3eef
DS
6359 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
6360 dest = bgp_route_next(dest)) {
6361 if (!bgp_dest_has_bgp_path_info_data(dest))
05c7a1cc 6362 continue;
ea47320b 6363
05c7a1cc
QY
6364 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
6365 || (safi == SAFI_EVPN)) {
9bcb3eef 6366 table = bgp_dest_get_bgp_table_info(dest);
05c7a1cc
QY
6367
6368 for (rm = bgp_table_top(table); rm;
6369 rm = bgp_route_next(rm)) {
a78beeb5 6370 bgp_static =
9bcb3eef 6371 bgp_dest_get_bgp_static_info(
5a8ba9fc 6372 rm);
9bcb3eef
DS
6373 bgp_static_update_safi(
6374 bgp, bgp_dest_get_prefix(rm),
6375 bgp_static, afi, safi);
d62a17ae 6376 }
05c7a1cc 6377 } else {
9bcb3eef
DS
6378 bgp_static = bgp_dest_get_bgp_static_info(dest);
6379 bgp_static_update(bgp,
6380 bgp_dest_get_prefix(dest),
6381 bgp_static, afi, safi);
ea47320b 6382 }
05c7a1cc
QY
6383 }
6384 }
892fedb6 6385 UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
d62a17ae 6386}
6387
6388static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
6389 safi_t safi)
6390{
6391 struct bgp_table *table;
9bcb3eef 6392 struct bgp_dest *dest;
40381db7 6393 struct bgp_path_info *pi;
d62a17ae 6394
dfb6fd1d
NT
6395 /* Do not install the aggregate route if BGP is in the
6396 * process of termination.
6397 */
892fedb6
DA
6398 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
6399 || (bgp->peer_self == NULL))
dfb6fd1d
NT
6400 return;
6401
d62a17ae 6402 table = bgp->rib[afi][safi];
9bcb3eef
DS
6403 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6404 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7
DS
6405 if (pi->peer == bgp->peer_self
6406 && ((pi->type == ZEBRA_ROUTE_BGP
6407 && pi->sub_type == BGP_ROUTE_STATIC)
6408 || (pi->type != ZEBRA_ROUTE_BGP
6409 && pi->sub_type
d62a17ae 6410 == BGP_ROUTE_REDISTRIBUTE))) {
9bcb3eef
DS
6411 bgp_aggregate_decrement(
6412 bgp, bgp_dest_get_prefix(dest), pi, afi,
6413 safi);
40381db7 6414 bgp_unlink_nexthop(pi);
9bcb3eef
DS
6415 bgp_path_info_delete(dest, pi);
6416 bgp_process(bgp, dest, afi, safi);
d62a17ae 6417 }
6418 }
6419 }
ad4cbda1 6420}
6421
6422/*
6423 * Purge all networks and redistributed routes from routing table.
6424 * Invoked upon the instance going down.
6425 */
d62a17ae 6426void bgp_purge_static_redist_routes(struct bgp *bgp)
ad4cbda1 6427{
d62a17ae 6428 afi_t afi;
6429 safi_t safi;
ad4cbda1 6430
05c7a1cc
QY
6431 FOREACH_AFI_SAFI (afi, safi)
6432 bgp_purge_af_static_redist_routes(bgp, afi, safi);
ad4cbda1 6433}
6434
137446f9
LB
6435/*
6436 * gpz 110624
6437 * Currently this is used to set static routes for VPN and ENCAP.
6438 * I think it can probably be factored with bgp_static_set.
6439 */
d62a17ae 6440int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
6441 const char *ip_str, const char *rd_str,
6442 const char *label_str, const char *rmap_str,
6443 int evpn_type, const char *esi, const char *gwip,
6444 const char *ethtag, const char *routermac)
6445{
6446 VTY_DECLVAR_CONTEXT(bgp, bgp);
6447 int ret;
6448 struct prefix p;
6449 struct prefix_rd prd;
9bcb3eef
DS
6450 struct bgp_dest *pdest;
6451 struct bgp_dest *dest;
d62a17ae 6452 struct bgp_table *table;
6453 struct bgp_static *bgp_static;
6454 mpls_label_t label = MPLS_INVALID_LABEL;
6455 struct prefix gw_ip;
6456
6457 /* validate ip prefix */
6458 ret = str2prefix(ip_str, &p);
6459 if (!ret) {
6460 vty_out(vty, "%% Malformed prefix\n");
6461 return CMD_WARNING_CONFIG_FAILED;
6462 }
6463 apply_mask(&p);
6464 if ((afi == AFI_L2VPN)
6465 && (bgp_build_evpn_prefix(evpn_type,
6466 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6467 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6468 return CMD_WARNING_CONFIG_FAILED;
6469 }
718e3744 6470
d62a17ae 6471 ret = str2prefix_rd(rd_str, &prd);
6472 if (!ret) {
6473 vty_out(vty, "%% Malformed rd\n");
6474 return CMD_WARNING_CONFIG_FAILED;
6475 }
718e3744 6476
d62a17ae 6477 if (label_str) {
6478 unsigned long label_val;
6479 label_val = strtoul(label_str, NULL, 10);
6480 encode_label(label_val, &label);
6481 }
9bedbb1e 6482
d62a17ae 6483 if (safi == SAFI_EVPN) {
6484 if (esi && str2esi(esi, NULL) == 0) {
6485 vty_out(vty, "%% Malformed ESI\n");
6486 return CMD_WARNING_CONFIG_FAILED;
6487 }
6488 if (routermac && prefix_str2mac(routermac, NULL) == 0) {
6489 vty_out(vty, "%% Malformed Router MAC\n");
6490 return CMD_WARNING_CONFIG_FAILED;
6491 }
6492 if (gwip) {
6493 memset(&gw_ip, 0, sizeof(struct prefix));
6494 ret = str2prefix(gwip, &gw_ip);
6495 if (!ret) {
6496 vty_out(vty, "%% Malformed GatewayIp\n");
6497 return CMD_WARNING_CONFIG_FAILED;
6498 }
6499 if ((gw_ip.family == AF_INET
3714a385 6500 && is_evpn_prefix_ipaddr_v6(
d62a17ae 6501 (struct prefix_evpn *)&p))
6502 || (gw_ip.family == AF_INET6
3714a385 6503 && is_evpn_prefix_ipaddr_v4(
d62a17ae 6504 (struct prefix_evpn *)&p))) {
6505 vty_out(vty,
6506 "%% GatewayIp family differs with IP prefix\n");
6507 return CMD_WARNING_CONFIG_FAILED;
6508 }
6509 }
6510 }
9bcb3eef
DS
6511 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6512 if (!bgp_dest_has_bgp_path_info_data(pdest))
6513 bgp_dest_set_bgp_table_info(pdest,
67009e22 6514 bgp_table_init(bgp, afi, safi));
9bcb3eef 6515 table = bgp_dest_get_bgp_table_info(pdest);
d62a17ae 6516
9bcb3eef 6517 dest = bgp_node_get(table, &p);
d62a17ae 6518
9bcb3eef 6519 if (bgp_dest_has_bgp_path_info_data(dest)) {
d62a17ae 6520 vty_out(vty, "%% Same network configuration exists\n");
9bcb3eef 6521 bgp_dest_unlock_node(dest);
d62a17ae 6522 } else {
6523 /* New configuration. */
6524 bgp_static = bgp_static_new();
6525 bgp_static->backdoor = 0;
6526 bgp_static->valid = 0;
6527 bgp_static->igpmetric = 0;
975a328e 6528 bgp_static->igpnexthop.s_addr = INADDR_ANY;
d62a17ae 6529 bgp_static->label = label;
6530 bgp_static->prd = prd;
6531
6532 if (rmap_str) {
0a22ddfb 6533 XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
b4897fa5 6534 route_map_counter_decrement(bgp_static->rmap.map);
d62a17ae 6535 bgp_static->rmap.name =
6536 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
6537 bgp_static->rmap.map =
6538 route_map_lookup_by_name(rmap_str);
b4897fa5 6539 route_map_counter_increment(bgp_static->rmap.map);
d62a17ae 6540 }
718e3744 6541
d62a17ae 6542 if (safi == SAFI_EVPN) {
6543 if (esi) {
6544 bgp_static->eth_s_id =
6545 XCALLOC(MTYPE_ATTR,
0a50c248 6546 sizeof(esi_t));
d62a17ae 6547 str2esi(esi, bgp_static->eth_s_id);
6548 }
6549 if (routermac) {
6550 bgp_static->router_mac =
28328ea9 6551 XCALLOC(MTYPE_ATTR, ETH_ALEN + 1);
56cb79b6
A
6552 (void)prefix_str2mac(routermac,
6553 bgp_static->router_mac);
d62a17ae 6554 }
6555 if (gwip)
6556 prefix_copy(&bgp_static->gatewayIp, &gw_ip);
6557 }
9bcb3eef 6558 bgp_dest_set_bgp_static_info(dest, bgp_static);
718e3744 6559
d62a17ae 6560 bgp_static->valid = 1;
6561 bgp_static_update_safi(bgp, &p, bgp_static, afi, safi);
6562 }
718e3744 6563
d62a17ae 6564 return CMD_SUCCESS;
718e3744 6565}
6566
6567/* Configure static BGP network. */
d62a17ae 6568int bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty,
6569 const char *ip_str, const char *rd_str,
6570 const char *label_str, int evpn_type, const char *esi,
6571 const char *gwip, const char *ethtag)
6572{
6573 VTY_DECLVAR_CONTEXT(bgp, bgp);
6574 int ret;
6575 struct prefix p;
6576 struct prefix_rd prd;
9bcb3eef
DS
6577 struct bgp_dest *pdest;
6578 struct bgp_dest *dest;
d62a17ae 6579 struct bgp_table *table;
6580 struct bgp_static *bgp_static;
6581 mpls_label_t label = MPLS_INVALID_LABEL;
6582
6583 /* Convert IP prefix string to struct prefix. */
6584 ret = str2prefix(ip_str, &p);
6585 if (!ret) {
6586 vty_out(vty, "%% Malformed prefix\n");
6587 return CMD_WARNING_CONFIG_FAILED;
6588 }
6589 apply_mask(&p);
6590 if ((afi == AFI_L2VPN)
6591 && (bgp_build_evpn_prefix(evpn_type,
6592 ethtag != NULL ? atol(ethtag) : 0, &p))) {
6593 vty_out(vty, "%% L2VPN prefix could not be forged\n");
6594 return CMD_WARNING_CONFIG_FAILED;
6595 }
6596 ret = str2prefix_rd(rd_str, &prd);
6597 if (!ret) {
6598 vty_out(vty, "%% Malformed rd\n");
6599 return CMD_WARNING_CONFIG_FAILED;
6600 }
718e3744 6601
d62a17ae 6602 if (label_str) {
6603 unsigned long label_val;
6604 label_val = strtoul(label_str, NULL, 10);
6605 encode_label(label_val, &label);
6606 }
718e3744 6607
9bcb3eef
DS
6608 pdest = bgp_node_get(bgp->route[afi][safi], (struct prefix *)&prd);
6609 if (!bgp_dest_has_bgp_path_info_data(pdest))
6610 bgp_dest_set_bgp_table_info(pdest,
67009e22 6611 bgp_table_init(bgp, afi, safi));
d62a17ae 6612 else
9bcb3eef
DS
6613 bgp_dest_unlock_node(pdest);
6614 table = bgp_dest_get_bgp_table_info(pdest);
718e3744 6615
9bcb3eef 6616 dest = bgp_node_lookup(table, &p);
6b0655a2 6617
9bcb3eef 6618 if (dest) {
d62a17ae 6619 bgp_static_withdraw_safi(bgp, &p, afi, safi, &prd);
73ac8160 6620
9bcb3eef 6621 bgp_static = bgp_dest_get_bgp_static_info(dest);
d62a17ae 6622 bgp_static_free(bgp_static);
9bcb3eef
DS
6623 bgp_dest_set_bgp_static_info(dest, NULL);
6624 bgp_dest_unlock_node(dest);
6625 bgp_dest_unlock_node(dest);
d62a17ae 6626 } else
6627 vty_out(vty, "%% Can't find the route\n");
6628
6629 return CMD_SUCCESS;
6630}
6631
6632static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
6633 const char *rmap_name)
6634{
6635 VTY_DECLVAR_CONTEXT(bgp, bgp);
6636 struct bgp_rmap *rmap;
6637
6638 rmap = &bgp->table_map[afi][safi];
6639 if (rmap_name) {
0a22ddfb 6640 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6641 route_map_counter_decrement(rmap->map);
d62a17ae 6642 rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
6643 rmap->map = route_map_lookup_by_name(rmap_name);
b4897fa5 6644 route_map_counter_increment(rmap->map);
d62a17ae 6645 } else {
0a22ddfb 6646 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6647 route_map_counter_decrement(rmap->map);
d62a17ae 6648 rmap->map = NULL;
6649 }
73ac8160 6650
d62a17ae 6651 if (bgp_fibupd_safi(safi))
6652 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6653
d62a17ae 6654 return CMD_SUCCESS;
73ac8160
DS
6655}
6656
d62a17ae 6657static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
6658 const char *rmap_name)
73ac8160 6659{
d62a17ae 6660 VTY_DECLVAR_CONTEXT(bgp, bgp);
6661 struct bgp_rmap *rmap;
73ac8160 6662
d62a17ae 6663 rmap = &bgp->table_map[afi][safi];
0a22ddfb 6664 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
b4897fa5 6665 route_map_counter_decrement(rmap->map);
d62a17ae 6666 rmap->map = NULL;
73ac8160 6667
d62a17ae 6668 if (bgp_fibupd_safi(safi))
6669 bgp_zebra_announce_table(bgp, afi, safi);
73ac8160 6670
d62a17ae 6671 return CMD_SUCCESS;
73ac8160
DS
6672}
6673
2b791107 6674void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 6675 safi_t safi)
73ac8160 6676{
d62a17ae 6677 if (bgp->table_map[afi][safi].name) {
d62a17ae 6678 vty_out(vty, " table-map %s\n",
6679 bgp->table_map[afi][safi].name);
6680 }
73ac8160
DS
6681}
6682
73ac8160
DS
6683DEFUN (bgp_table_map,
6684 bgp_table_map_cmd,
6685 "table-map WORD",
6686 "BGP table to RIB route download filter\n"
6687 "Name of the route map\n")
6688{
d62a17ae 6689 int idx_word = 1;
6690 return bgp_table_map_set(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6691 argv[idx_word]->arg);
73ac8160
DS
6692}
6693DEFUN (no_bgp_table_map,
6694 no_bgp_table_map_cmd,
6695 "no table-map WORD",
3a2d747c 6696 NO_STR
73ac8160
DS
6697 "BGP table to RIB route download filter\n"
6698 "Name of the route map\n")
6699{
d62a17ae 6700 int idx_word = 2;
6701 return bgp_table_map_unset(vty, bgp_node_afi(vty), bgp_node_safi(vty),
6702 argv[idx_word]->arg);
73ac8160
DS
6703}
6704
585f1adc
IR
6705DEFPY(bgp_network,
6706 bgp_network_cmd,
6707 "[no] network \
6708 <A.B.C.D/M$prefix|A.B.C.D$address [mask A.B.C.D$netmask]> \
6709 [{route-map WORD$map_name|label-index (0-1048560)$label_index| \
6710 backdoor$backdoor}]",
6711 NO_STR
6712 "Specify a network to announce via BGP\n"
6713 "IPv4 prefix\n"
6714 "Network number\n"
6715 "Network mask\n"
6716 "Network mask\n"
6717 "Route-map to modify the attributes\n"
6718 "Name of the route map\n"
6719 "Label index to associate with the prefix\n"
6720 "Label index value\n"
6721 "Specify a BGP backdoor route\n")
6722{
6723 char addr_prefix_str[BUFSIZ];
e2a86ad9
DS
6724
6725 if (address_str) {
6726 int ret;
718e3744 6727
e2a86ad9 6728 ret = netmask_str2prefix_str(address_str, netmask_str,
7533cad7
QY
6729 addr_prefix_str,
6730 sizeof(addr_prefix_str));
e2a86ad9
DS
6731 if (!ret) {
6732 vty_out(vty, "%% Inconsistent address and mask\n");
6733 return CMD_WARNING_CONFIG_FAILED;
6734 }
d62a17ae 6735 }
718e3744 6736
585f1adc
IR
6737 return bgp_static_set(
6738 vty, no, address_str ? addr_prefix_str : prefix_str, AFI_IP,
6739 bgp_node_safi(vty), map_name, backdoor ? 1 : 0,
6740 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
718e3744 6741}
6742
585f1adc
IR
6743DEFPY(ipv6_bgp_network,
6744 ipv6_bgp_network_cmd,
6745 "[no] network X:X::X:X/M$prefix \
6746 [{route-map WORD$map_name|label-index (0-1048560)$label_index}]",
6747 NO_STR
6748 "Specify a network to announce via BGP\n"
6749 "IPv6 prefix\n"
6750 "Route-map to modify the attributes\n"
6751 "Name of the route map\n"
6752 "Label index to associate with the prefix\n"
6753 "Label index value\n")
37a87b8f 6754{
585f1adc
IR
6755 return bgp_static_set(
6756 vty, no, prefix_str, AFI_IP6, bgp_node_safi(vty), map_name, 0,
6757 label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
1b6d5c7e
VV
6758}
6759
d62a17ae 6760static struct bgp_aggregate *bgp_aggregate_new(void)
718e3744 6761{
d62a17ae 6762 return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
718e3744 6763}
6764
d62a17ae 6765static void bgp_aggregate_free(struct bgp_aggregate *aggregate)
718e3744 6766{
365ab2e7
RZ
6767 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
6768 route_map_counter_decrement(aggregate->suppress_map);
20894f50
DA
6769 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
6770 route_map_counter_decrement(aggregate->rmap.map);
d62a17ae 6771 XFREE(MTYPE_BGP_AGGREGATE, aggregate);
6772}
718e3744 6773
365ab2e7
RZ
6774/**
6775 * Helper function to avoid repeated code: prepare variables for a
6776 * `route_map_apply` call.
6777 *
6778 * \returns `true` on route map match, otherwise `false`.
6779 */
6780static bool aggr_suppress_map_test(struct bgp *bgp,
6781 struct bgp_aggregate *aggregate,
6782 struct bgp_path_info *pi)
6783{
6784 const struct prefix *p = bgp_dest_get_prefix(pi->net);
6785 route_map_result_t rmr = RMAP_DENYMATCH;
6786 struct bgp_path_info rmap_path = {};
6787 struct attr attr = {};
6788
6789 /* No route map entries created, just don't match. */
6790 if (aggregate->suppress_map == NULL)
6791 return false;
6792
6793 /* Call route map matching and return result. */
6794 attr.aspath = aspath_empty();
6795 rmap_path.peer = bgp->peer_self;
6796 rmap_path.attr = &attr;
6797
6798 SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
1782514f 6799 rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
365ab2e7
RZ
6800 bgp->peer_self->rmap_type = 0;
6801
6802 bgp_attr_flush(&attr);
6803
6804 return rmr == RMAP_PERMITMATCH;
6805}
6806
4056a5f6
RZ
6807/** Test whether the aggregation has suppressed this path or not. */
6808static bool aggr_suppress_exists(struct bgp_aggregate *aggregate,
6809 struct bgp_path_info *pi)
6810{
6811 if (pi->extra == NULL || pi->extra->aggr_suppressors == NULL)
6812 return false;
6813
6814 return listnode_lookup(pi->extra->aggr_suppressors, aggregate) != NULL;
6815}
6816
6817/**
6818 * Suppress this path and keep the reference.
6819 *
6820 * \returns `true` if needs processing otherwise `false`.
6821 */
6822static bool aggr_suppress_path(struct bgp_aggregate *aggregate,
6823 struct bgp_path_info *pi)
6824{
6825 struct bgp_path_info_extra *pie;
6826
6827 /* Path is already suppressed by this aggregation. */
6828 if (aggr_suppress_exists(aggregate, pi))
6829 return false;
6830
6831 pie = bgp_path_info_extra_get(pi);
6832
6833 /* This is the first suppression, allocate memory and list it. */
6834 if (pie->aggr_suppressors == NULL)
6835 pie->aggr_suppressors = list_new();
6836
6837 listnode_add(pie->aggr_suppressors, aggregate);
6838
6839 /* Only mark for processing if suppressed. */
6840 if (listcount(pie->aggr_suppressors) == 1) {
6ba6de7e
RZ
6841 if (BGP_DEBUG(update, UPDATE_OUT))
6842 zlog_debug("aggregate-address suppressing: %pFX",
6843 bgp_dest_get_prefix(pi->net));
6844
4056a5f6
RZ
6845 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6846 return true;
6847 }
6848
6849 return false;
6850}
6851
6852/**
6853 * Unsuppress this path and remove the reference.
6854 *
6855 * \returns `true` if needs processing otherwise `false`.
6856 */
6857static bool aggr_unsuppress_path(struct bgp_aggregate *aggregate,
6858 struct bgp_path_info *pi)
6859{
6860 /* Path wasn't suppressed. */
6861 if (!aggr_suppress_exists(aggregate, pi))
6862 return false;
6863
6864 listnode_delete(pi->extra->aggr_suppressors, aggregate);
6865
6866 /* Unsuppress and free extra memory if last item. */
6867 if (listcount(pi->extra->aggr_suppressors) == 0) {
6ba6de7e
RZ
6868 if (BGP_DEBUG(update, UPDATE_OUT))
6869 zlog_debug("aggregate-address unsuppressing: %pFX",
6870 bgp_dest_get_prefix(pi->net));
6871
4056a5f6
RZ
6872 list_delete(&pi->extra->aggr_suppressors);
6873 bgp_path_info_set_flag(pi->net, pi, BGP_PATH_ATTR_CHANGED);
6874 return true;
6875 }
6876
6877 return false;
6878}
6879
3dc339cd
DA
6880static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin,
6881 struct aspath *aspath,
6882 struct community *comm,
6883 struct ecommunity *ecomm,
6884 struct lcommunity *lcomm)
eaaf8adb
DS
6885{
6886 static struct aspath *ae = NULL;
6887
6888 if (!ae)
6889 ae = aspath_empty();
6890
40381db7 6891 if (!pi)
3dc339cd 6892 return false;
eaaf8adb 6893
40381db7 6894 if (origin != pi->attr->origin)
3dc339cd 6895 return false;
eaaf8adb 6896
40381db7 6897 if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae))
3dc339cd 6898 return false;
29f7d023 6899
40381db7 6900 if (!community_cmp(pi->attr->community, comm))
3dc339cd 6901 return false;
eaaf8adb 6902
3da2cc32 6903 if (!ecommunity_cmp(pi->attr->ecommunity, ecomm))
3dc339cd 6904 return false;
eaaf8adb 6905
dd18c5a9 6906 if (!lcommunity_cmp(pi->attr->lcommunity, lcomm))
3dc339cd 6907 return false;
dd18c5a9 6908
40381db7 6909 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
3dc339cd 6910 return false;
7ce8a8e0 6911
3dc339cd 6912 return true;
eaaf8adb
DS
6913}
6914
5f040085
DS
6915static void bgp_aggregate_install(
6916 struct bgp *bgp, afi_t afi, safi_t safi, const struct prefix *p,
6917 uint8_t origin, struct aspath *aspath, struct community *community,
6918 struct ecommunity *ecommunity, struct lcommunity *lcommunity,
6919 uint8_t atomic_aggregate, struct bgp_aggregate *aggregate)
c701010e 6920{
9bcb3eef 6921 struct bgp_dest *dest;
c701010e 6922 struct bgp_table *table;
6f94b685 6923 struct bgp_path_info *pi, *orig, *new;
20894f50 6924 struct attr *attr;
c701010e
DS
6925
6926 table = bgp->rib[afi][safi];
6927
9bcb3eef 6928 dest = bgp_node_get(table, p);
eaaf8adb 6929
9bcb3eef 6930 for (orig = pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
6931 if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP
6932 && pi->sub_type == BGP_ROUTE_AGGREGATE)
eaaf8adb
DS
6933 break;
6934
6aabb15d
RZ
6935 /*
6936 * If we have paths with different MEDs, then don't install
6937 * (or uninstall) the aggregate route.
6938 */
6939 if (aggregate->match_med && aggregate->med_mismatched)
6940 goto uninstall_aggregate_route;
6941
c701010e 6942 if (aggregate->count > 0) {
eaaf8adb
DS
6943 /*
6944 * If the aggregate information has not changed
6945 * no need to re-install it again.
6946 */
6f94b685 6947 if (bgp_aggregate_info_same(orig, origin, aspath, community,
dd18c5a9 6948 ecommunity, lcommunity)) {
9bcb3eef 6949 bgp_dest_unlock_node(dest);
eaaf8adb
DS
6950
6951 if (aspath)
6952 aspath_free(aspath);
6953 if (community)
3c1f53de 6954 community_free(&community);
3da2cc32
DS
6955 if (ecommunity)
6956 ecommunity_free(&ecommunity);
dd18c5a9
DS
6957 if (lcommunity)
6958 lcommunity_free(&lcommunity);
eaaf8adb
DS
6959
6960 return;
6961 }
6962
6963 /*
6964 * Mark the old as unusable
6965 */
40381db7 6966 if (pi)
9bcb3eef 6967 bgp_path_info_delete(dest, pi);
eaaf8adb 6968
20894f50
DA
6969 attr = bgp_attr_aggregate_intern(
6970 bgp, origin, aspath, community, ecommunity, lcommunity,
6971 aggregate, atomic_aggregate, p);
6972
6973 if (!attr) {
6974 bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
a4559740 6975 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
6976 zlog_debug("%s: %pFX null attribute", __func__,
6977 p);
20894f50
DA
6978 return;
6979 }
6980
3da2cc32 6981 new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0,
9bcb3eef 6982 bgp->peer_self, attr, dest);
20894f50 6983
1defdda8 6984 SET_FLAG(new->flags, BGP_PATH_VALID);
c701010e 6985
9bcb3eef
DS
6986 bgp_path_info_add(dest, new);
6987 bgp_process(bgp, dest, afi, safi);
c701010e 6988 } else {
6aabb15d 6989 uninstall_aggregate_route:
6f94b685 6990 for (pi = orig; pi; pi = pi->next)
40381db7
DS
6991 if (pi->peer == bgp->peer_self
6992 && pi->type == ZEBRA_ROUTE_BGP
6993 && pi->sub_type == BGP_ROUTE_AGGREGATE)
c701010e
DS
6994 break;
6995
6996 /* Withdraw static BGP route from routing table. */
40381db7 6997 if (pi) {
9bcb3eef
DS
6998 bgp_path_info_delete(dest, pi);
6999 bgp_process(bgp, dest, afi, safi);
c701010e
DS
7000 }
7001 }
7002
9bcb3eef 7003 bgp_dest_unlock_node(dest);
c701010e
DS
7004}
7005
6aabb15d
RZ
7006/**
7007 * Check if the current path has different MED than other known paths.
7008 *
7009 * \returns `true` if the MED matched the others else `false`.
7010 */
7011static bool bgp_aggregate_med_match(struct bgp_aggregate *aggregate,
7012 struct bgp *bgp, struct bgp_path_info *pi)
7013{
7014 uint32_t cur_med = bgp_med_value(pi->attr, bgp);
7015
7016 /* This is the first route being analyzed. */
7017 if (!aggregate->med_initialized) {
7018 aggregate->med_initialized = true;
7019 aggregate->med_mismatched = false;
7020 aggregate->med_matched_value = cur_med;
7021 } else {
7022 /* Check if routes with different MED showed up. */
7023 if (cur_med != aggregate->med_matched_value)
7024 aggregate->med_mismatched = true;
7025 }
7026
7027 return !aggregate->med_mismatched;
7028}
7029
7030/**
7031 * Initializes and tests all routes in the aggregate address path for MED
7032 * values.
7033 *
7034 * \returns `true` if all MEDs are the same otherwise `false`.
7035 */
7036static bool bgp_aggregate_test_all_med(struct bgp_aggregate *aggregate,
7037 struct bgp *bgp, const struct prefix *p,
7038 afi_t afi, safi_t safi)
7039{
7040 struct bgp_table *table = bgp->rib[afi][safi];
7041 const struct prefix *dest_p;
7042 struct bgp_dest *dest, *top;
7043 struct bgp_path_info *pi;
7044 bool med_matched = true;
7045
7046 aggregate->med_initialized = false;
7047
7048 top = bgp_node_get(table, p);
7049 for (dest = bgp_node_get(table, p); dest;
7050 dest = bgp_route_next_until(dest, top)) {
7051 dest_p = bgp_dest_get_prefix(dest);
7052 if (dest_p->prefixlen <= p->prefixlen)
7053 continue;
7054
7055 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7056 if (BGP_PATH_HOLDDOWN(pi))
7057 continue;
7058 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7059 continue;
7060 if (!bgp_aggregate_med_match(aggregate, bgp, pi)) {
7061 med_matched = false;
7062 break;
7063 }
7064 }
7065 if (!med_matched)
7066 break;
7067 }
7068 bgp_dest_unlock_node(top);
7069
7070 return med_matched;
7071}
7072
7073/**
7074 * Toggles the route suppression status for this aggregate address
7075 * configuration.
7076 */
4056a5f6
RZ
7077void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
7078 struct bgp *bgp, const struct prefix *p,
7079 afi_t afi, safi_t safi, bool suppress)
6aabb15d
RZ
7080{
7081 struct bgp_table *table = bgp->rib[afi][safi];
6aabb15d
RZ
7082 const struct prefix *dest_p;
7083 struct bgp_dest *dest, *top;
7084 struct bgp_path_info *pi;
7085 bool toggle_suppression;
7086
7087 /* We've found a different MED we must revert any suppressed routes. */
7088 top = bgp_node_get(table, p);
7089 for (dest = bgp_node_get(table, p); dest;
7090 dest = bgp_route_next_until(dest, top)) {
7091 dest_p = bgp_dest_get_prefix(dest);
7092 if (dest_p->prefixlen <= p->prefixlen)
7093 continue;
7094
7095 toggle_suppression = false;
7096 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
7097 if (BGP_PATH_HOLDDOWN(pi))
7098 continue;
7099 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7100 continue;
7101
6aabb15d
RZ
7102 /* We are toggling suppression back. */
7103 if (suppress) {
6aabb15d 7104 /* Suppress route if not suppressed already. */
4056a5f6
RZ
7105 if (aggr_suppress_path(aggregate, pi))
7106 toggle_suppression = true;
6aabb15d
RZ
7107 continue;
7108 }
7109
6aabb15d 7110 /* Install route if there is no more suppression. */
4056a5f6 7111 if (aggr_unsuppress_path(aggregate, pi))
6aabb15d 7112 toggle_suppression = true;
6aabb15d
RZ
7113 }
7114
7115 if (toggle_suppression)
7116 bgp_process(bgp, dest, afi, safi);
7117 }
7118 bgp_dest_unlock_node(top);
7119}
7120
7121/**
7122 * Aggregate address MED matching incremental test: this function is called
7123 * when the initial aggregation occurred and we are only testing a single
7124 * new path.
7125 *
7126 * In addition to testing and setting the MED validity it also installs back
7127 * suppressed routes (if summary is configured).
7128 *
7129 * Must not be called in `bgp_aggregate_route`.
7130 */
7131static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
7132 struct bgp *bgp, const struct prefix *p,
7133 afi_t afi, safi_t safi,
7134 struct bgp_path_info *pi, bool is_adding)
7135{
7136 /* MED matching disabled. */
7137 if (!aggregate->match_med)
7138 return;
7139
7140 /* Aggregation with different MED, nothing to do. */
7141 if (aggregate->med_mismatched)
7142 return;
7143
7144 /*
7145 * Test the current entry:
7146 *
7147 * is_adding == true: if the new entry doesn't match then we must
7148 * install all suppressed routes.
7149 *
7150 * is_adding == false: if the entry being removed was the last
7151 * unmatching entry then we can suppress all routes.
7152 */
7153 if (!is_adding) {
7154 if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
7155 && aggregate->summary_only)
7156 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
7157 safi, true);
7158 } else
7159 bgp_aggregate_med_match(aggregate, bgp, pi);
7160
7161 /* No mismatches, just quit. */
7162 if (!aggregate->med_mismatched)
7163 return;
7164
7165 /* Route summarization is disabled. */
7166 if (!aggregate->summary_only)
7167 return;
7168
7169 bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi, false);
7170}
7171
b5d58c32 7172/* Update an aggregate as routes are added/removed from the BGP table */
5f040085
DS
7173void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
7174 safi_t safi, struct bgp_aggregate *aggregate)
d62a17ae 7175{
7176 struct bgp_table *table;
9bcb3eef
DS
7177 struct bgp_dest *top;
7178 struct bgp_dest *dest;
d7c0a89a 7179 uint8_t origin;
d62a17ae 7180 struct aspath *aspath = NULL;
d62a17ae 7181 struct community *community = NULL;
3da2cc32 7182 struct ecommunity *ecommunity = NULL;
dd18c5a9 7183 struct lcommunity *lcommunity = NULL;
40381db7 7184 struct bgp_path_info *pi;
d62a17ae 7185 unsigned long match = 0;
d7c0a89a 7186 uint8_t atomic_aggregate = 0;
d62a17ae 7187
9f822fa2
S
7188 /* If the bgp instance is being deleted or self peer is deleted
7189 * then do not create aggregate route
7190 */
892fedb6
DA
7191 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7192 || (bgp->peer_self == NULL))
9f822fa2
S
7193 return;
7194
6aabb15d
RZ
7195 /* Initialize and test routes for MED difference. */
7196 if (aggregate->match_med)
7197 bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi);
7198
4056a5f6
RZ
7199 /*
7200 * Reset aggregate count: we might've been called from route map
7201 * update so in that case we must retest all more specific routes.
7202 *
7203 * \see `bgp_route_map_process_update`.
7204 */
7205 aggregate->count = 0;
7206 aggregate->incomplete_origin_count = 0;
7207 aggregate->incomplete_origin_count = 0;
7208 aggregate->egp_origin_count = 0;
7209
d62a17ae 7210 /* ORIGIN attribute: If at least one route among routes that are
7211 aggregated has ORIGIN with the value INCOMPLETE, then the
7212 aggregated route must have the ORIGIN attribute with the value
7213 INCOMPLETE. Otherwise, if at least one route among routes that
7214 are aggregated has ORIGIN with the value EGP, then the aggregated
7215 route must have the origin attribute with the value EGP. In all
7216 other case the value of the ORIGIN attribute of the aggregated
7217 route is INTERNAL. */
7218 origin = BGP_ORIGIN_IGP;
718e3744 7219
d62a17ae 7220 table = bgp->rib[afi][safi];
718e3744 7221
d62a17ae 7222 top = bgp_node_get(table, p);
9bcb3eef
DS
7223 for (dest = bgp_node_get(table, p); dest;
7224 dest = bgp_route_next_until(dest, top)) {
7225 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7226
9bcb3eef 7227 if (dest_p->prefixlen <= p->prefixlen)
c2ff8b3e 7228 continue;
d62a17ae 7229
a77e2f4b
S
7230 /* If suppress fib is enabled and route not installed
7231 * in FIB, skip the route
7232 */
7233 if (!bgp_check_advertise(bgp, dest))
7234 continue;
7235
c2ff8b3e 7236 match = 0;
d62a17ae 7237
9bcb3eef 7238 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7239 if (BGP_PATH_HOLDDOWN(pi))
c2ff8b3e 7240 continue;
718e3744 7241
40381db7 7242 if (pi->attr->flag
c2ff8b3e
DS
7243 & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
7244 atomic_aggregate = 1;
d62a17ae 7245
40381db7 7246 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
c2ff8b3e 7247 continue;
d62a17ae 7248
f273fef1
DS
7249 /*
7250 * summary-only aggregate route suppress
7251 * aggregated route announcements.
6aabb15d
RZ
7252 *
7253 * MED matching:
7254 * Don't create summaries if MED didn't match
7255 * otherwise neither the specific routes and the
7256 * aggregation will be announced.
f273fef1 7257 */
6aabb15d
RZ
7258 if (aggregate->summary_only
7259 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6
RZ
7260 if (aggr_suppress_path(aggregate, pi))
7261 match++;
d62a17ae 7262 }
c2ff8b3e 7263
365ab2e7
RZ
7264 /*
7265 * Suppress more specific routes that match the route
7266 * map results.
7267 *
7268 * MED matching:
7269 * Don't suppress routes if MED matching is enabled and
7270 * it mismatched otherwise we might end up with no
7271 * routes for this path.
7272 */
7273 if (aggregate->suppress_map_name
7274 && AGGREGATE_MED_VALID(aggregate)
7275 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6
RZ
7276 if (aggr_suppress_path(aggregate, pi))
7277 match++;
d62a17ae 7278 }
c2ff8b3e
DS
7279
7280 aggregate->count++;
7281
f273fef1
DS
7282 /*
7283 * If at least one route among routes that are
7284 * aggregated has ORIGIN with the value INCOMPLETE,
7285 * then the aggregated route MUST have the ORIGIN
7286 * attribute with the value INCOMPLETE. Otherwise, if
7287 * at least one route among routes that are aggregated
7288 * has ORIGIN with the value EGP, then the aggregated
7289 * route MUST have the ORIGIN attribute with the value
7290 * EGP.
7291 */
fc968841
NT
7292 switch (pi->attr->origin) {
7293 case BGP_ORIGIN_INCOMPLETE:
7294 aggregate->incomplete_origin_count++;
7295 break;
7296 case BGP_ORIGIN_EGP:
7297 aggregate->egp_origin_count++;
7298 break;
7299 default:
7300 /*Do nothing.
7301 */
7302 break;
7303 }
c2ff8b3e
DS
7304
7305 if (!aggregate->as_set)
7306 continue;
7307
f273fef1
DS
7308 /*
7309 * as-set aggregate route generate origin, as path,
7310 * and community aggregation.
7311 */
fc968841
NT
7312 /* Compute aggregate route's as-path.
7313 */
ef51a7d8 7314 bgp_compute_aggregate_aspath_hash(aggregate,
7315 pi->attr->aspath);
c2ff8b3e 7316
fc968841
NT
7317 /* Compute aggregate route's community.
7318 */
7319 if (pi->attr->community)
21fec674 7320 bgp_compute_aggregate_community_hash(
fc968841
NT
7321 aggregate,
7322 pi->attr->community);
dd18c5a9 7323
fc968841
NT
7324 /* Compute aggregate route's extended community.
7325 */
7326 if (pi->attr->ecommunity)
4edd83f9 7327 bgp_compute_aggregate_ecommunity_hash(
fc968841
NT
7328 aggregate,
7329 pi->attr->ecommunity);
7330
7331 /* Compute aggregate route's large community.
7332 */
7333 if (pi->attr->lcommunity)
f1eb1f05 7334 bgp_compute_aggregate_lcommunity_hash(
fc968841
NT
7335 aggregate,
7336 pi->attr->lcommunity);
d62a17ae 7337 }
c2ff8b3e 7338 if (match)
9bcb3eef 7339 bgp_process(bgp, dest, afi, safi);
c2ff8b3e 7340 }
21fec674 7341 if (aggregate->as_set) {
ef51a7d8 7342 bgp_compute_aggregate_aspath_val(aggregate);
21fec674 7343 bgp_compute_aggregate_community_val(aggregate);
4edd83f9 7344 bgp_compute_aggregate_ecommunity_val(aggregate);
f1eb1f05 7345 bgp_compute_aggregate_lcommunity_val(aggregate);
21fec674 7346 }
7347
f1eb1f05 7348
9bcb3eef 7349 bgp_dest_unlock_node(top);
718e3744 7350
718e3744 7351
fc968841
NT
7352 if (aggregate->incomplete_origin_count > 0)
7353 origin = BGP_ORIGIN_INCOMPLETE;
7354 else if (aggregate->egp_origin_count > 0)
7355 origin = BGP_ORIGIN_EGP;
d62a17ae 7356
229757f1
DA
7357 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7358 origin = aggregate->origin;
7359
fc968841
NT
7360 if (aggregate->as_set) {
7361 if (aggregate->aspath)
7362 /* Retrieve aggregate route's as-path.
7363 */
7364 aspath = aspath_dup(aggregate->aspath);
d62a17ae 7365
fc968841
NT
7366 if (aggregate->community)
7367 /* Retrieve aggregate route's community.
7368 */
7369 community = community_dup(aggregate->community);
3da2cc32 7370
fc968841
NT
7371 if (aggregate->ecommunity)
7372 /* Retrieve aggregate route's ecommunity.
7373 */
7374 ecommunity = ecommunity_dup(aggregate->ecommunity);
dd18c5a9 7375
fc968841
NT
7376 if (aggregate->lcommunity)
7377 /* Retrieve aggregate route's lcommunity.
7378 */
7379 lcommunity = lcommunity_dup(aggregate->lcommunity);
718e3744 7380 }
718e3744 7381
c701010e 7382 bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
dd18c5a9
DS
7383 ecommunity, lcommunity, atomic_aggregate,
7384 aggregate);
718e3744 7385}
7386
5f040085
DS
7387void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
7388 safi_t safi, struct bgp_aggregate *aggregate)
3b7db173
DS
7389{
7390 struct bgp_table *table;
9bcb3eef
DS
7391 struct bgp_dest *top;
7392 struct bgp_dest *dest;
40381db7 7393 struct bgp_path_info *pi;
3b7db173
DS
7394 unsigned long match;
7395
7396 table = bgp->rib[afi][safi];
7397
7398 /* If routes exists below this node, generate aggregate routes. */
7399 top = bgp_node_get(table, p);
9bcb3eef
DS
7400 for (dest = bgp_node_get(table, p); dest;
7401 dest = bgp_route_next_until(dest, top)) {
7402 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7403
9bcb3eef 7404 if (dest_p->prefixlen <= p->prefixlen)
3b7db173
DS
7405 continue;
7406 match = 0;
7407
9bcb3eef 7408 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
40381db7 7409 if (BGP_PATH_HOLDDOWN(pi))
3b7db173
DS
7410 continue;
7411
40381db7 7412 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
3b7db173
DS
7413 continue;
7414
6aabb15d
RZ
7415 if (aggregate->summary_only && pi->extra
7416 && AGGREGATE_MED_VALID(aggregate)) {
4056a5f6 7417 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7418 match++;
3b7db173 7419 }
3b7db173 7420
365ab2e7
RZ
7421 if (aggregate->suppress_map_name
7422 && AGGREGATE_MED_VALID(aggregate)
7423 && aggr_suppress_map_test(bgp, aggregate, pi)) {
4056a5f6 7424 if (aggr_unsuppress_path(aggregate, pi))
3b7db173 7425 match++;
3b7db173 7426 }
365ab2e7 7427
3b7db173 7428 aggregate->count--;
fc968841
NT
7429
7430 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7431 aggregate->incomplete_origin_count--;
7432 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7433 aggregate->egp_origin_count--;
7434
7435 if (aggregate->as_set) {
7436 /* Remove as-path from aggregate.
7437 */
ef51a7d8 7438 bgp_remove_aspath_from_aggregate_hash(
fc968841
NT
7439 aggregate,
7440 pi->attr->aspath);
7441
7442 if (pi->attr->community)
7443 /* Remove community from aggregate.
7444 */
21fec674 7445 bgp_remove_comm_from_aggregate_hash(
fc968841
NT
7446 aggregate,
7447 pi->attr->community);
7448
7449 if (pi->attr->ecommunity)
7450 /* Remove ecommunity from aggregate.
7451 */
4edd83f9 7452 bgp_remove_ecomm_from_aggregate_hash(
fc968841
NT
7453 aggregate,
7454 pi->attr->ecommunity);
7455
7456 if (pi->attr->lcommunity)
7457 /* Remove lcommunity from aggregate.
7458 */
f1eb1f05 7459 bgp_remove_lcomm_from_aggregate_hash(
fc968841
NT
7460 aggregate,
7461 pi->attr->lcommunity);
7462 }
3b7db173
DS
7463 }
7464
7465 /* If this node was suppressed, process the change. */
7466 if (match)
9bcb3eef 7467 bgp_process(bgp, dest, afi, safi);
3b7db173 7468 }
f1eb1f05 7469 if (aggregate->as_set) {
ef51a7d8 7470 aspath_free(aggregate->aspath);
7471 aggregate->aspath = NULL;
21fec674 7472 if (aggregate->community)
7473 community_free(&aggregate->community);
4edd83f9 7474 if (aggregate->ecommunity)
7475 ecommunity_free(&aggregate->ecommunity);
f1eb1f05 7476 if (aggregate->lcommunity)
7477 lcommunity_free(&aggregate->lcommunity);
7478 }
7479
9bcb3eef 7480 bgp_dest_unlock_node(top);
3b7db173 7481}
718e3744 7482
5f040085
DS
7483static void bgp_add_route_to_aggregate(struct bgp *bgp,
7484 const struct prefix *aggr_p,
fc968841
NT
7485 struct bgp_path_info *pinew, afi_t afi,
7486 safi_t safi,
7487 struct bgp_aggregate *aggregate)
7488{
7489 uint8_t origin;
7490 struct aspath *aspath = NULL;
7491 uint8_t atomic_aggregate = 0;
7492 struct community *community = NULL;
7493 struct ecommunity *ecommunity = NULL;
7494 struct lcommunity *lcommunity = NULL;
7495
a4559740 7496 /* If the bgp instance is being deleted or self peer is deleted
7497 * then do not create aggregate route
7498 */
7499 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7500 || (bgp->peer_self == NULL))
7501 return;
7502
fc968841
NT
7503 /* ORIGIN attribute: If at least one route among routes that are
7504 * aggregated has ORIGIN with the value INCOMPLETE, then the
7505 * aggregated route must have the ORIGIN attribute with the value
7506 * INCOMPLETE. Otherwise, if at least one route among routes that
7507 * are aggregated has ORIGIN with the value EGP, then the aggregated
7508 * route must have the origin attribute with the value EGP. In all
7509 * other case the value of the ORIGIN attribute of the aggregated
7510 * route is INTERNAL.
7511 */
7512 origin = BGP_ORIGIN_IGP;
7513
7514 aggregate->count++;
7515
6aabb15d
RZ
7516 /*
7517 * This must be called before `summary` check to avoid
7518 * "suppressing" twice.
7519 */
7520 if (aggregate->match_med)
7521 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
7522 pinew, true);
7523
7524 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
4056a5f6 7525 aggr_suppress_path(aggregate, pinew);
fc968841 7526
365ab2e7
RZ
7527 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
7528 && aggr_suppress_map_test(bgp, aggregate, pinew))
4056a5f6 7529 aggr_suppress_path(aggregate, pinew);
fc968841
NT
7530
7531 switch (pinew->attr->origin) {
7532 case BGP_ORIGIN_INCOMPLETE:
7533 aggregate->incomplete_origin_count++;
7534 break;
7535 case BGP_ORIGIN_EGP:
7536 aggregate->egp_origin_count++;
7537 break;
7538 default:
7539 /* Do nothing.
7540 */
7541 break;
7542 }
7543
7544 if (aggregate->incomplete_origin_count > 0)
7545 origin = BGP_ORIGIN_INCOMPLETE;
7546 else if (aggregate->egp_origin_count > 0)
7547 origin = BGP_ORIGIN_EGP;
7548
229757f1
DA
7549 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7550 origin = aggregate->origin;
7551
fc968841
NT
7552 if (aggregate->as_set) {
7553 /* Compute aggregate route's as-path.
7554 */
7555 bgp_compute_aggregate_aspath(aggregate,
7556 pinew->attr->aspath);
7557
7558 /* Compute aggregate route's community.
7559 */
7560 if (pinew->attr->community)
7561 bgp_compute_aggregate_community(
7562 aggregate,
7563 pinew->attr->community);
7564
7565 /* Compute aggregate route's extended community.
7566 */
7567 if (pinew->attr->ecommunity)
7568 bgp_compute_aggregate_ecommunity(
7569 aggregate,
7570 pinew->attr->ecommunity);
7571
7572 /* Compute aggregate route's large community.
7573 */
7574 if (pinew->attr->lcommunity)
7575 bgp_compute_aggregate_lcommunity(
7576 aggregate,
7577 pinew->attr->lcommunity);
7578
7579 /* Retrieve aggregate route's as-path.
7580 */
7581 if (aggregate->aspath)
7582 aspath = aspath_dup(aggregate->aspath);
7583
7584 /* Retrieve aggregate route's community.
7585 */
7586 if (aggregate->community)
7587 community = community_dup(aggregate->community);
7588
7589 /* Retrieve aggregate route's ecommunity.
7590 */
7591 if (aggregate->ecommunity)
7592 ecommunity = ecommunity_dup(aggregate->ecommunity);
7593
7594 /* Retrieve aggregate route's lcommunity.
7595 */
7596 if (aggregate->lcommunity)
7597 lcommunity = lcommunity_dup(aggregate->lcommunity);
7598 }
7599
7600 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7601 aspath, community, ecommunity,
7602 lcommunity, atomic_aggregate, aggregate);
7603}
7604
7605static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
7606 safi_t safi,
7607 struct bgp_path_info *pi,
7608 struct bgp_aggregate *aggregate,
5f040085 7609 const struct prefix *aggr_p)
fc968841
NT
7610{
7611 uint8_t origin;
7612 struct aspath *aspath = NULL;
7613 uint8_t atomic_aggregate = 0;
7614 struct community *community = NULL;
7615 struct ecommunity *ecommunity = NULL;
7616 struct lcommunity *lcommunity = NULL;
7617 unsigned long match = 0;
7618
a4559740 7619 /* If the bgp instance is being deleted or self peer is deleted
7620 * then do not create aggregate route
7621 */
7622 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
7623 || (bgp->peer_self == NULL))
7624 return;
7625
fc968841
NT
7626 if (BGP_PATH_HOLDDOWN(pi))
7627 return;
7628
7629 if (pi->sub_type == BGP_ROUTE_AGGREGATE)
7630 return;
7631
4056a5f6
RZ
7632 if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
7633 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7634 match++;
fc968841 7635
365ab2e7 7636 if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
4056a5f6
RZ
7637 && aggr_suppress_map_test(bgp, aggregate, pi))
7638 if (aggr_unsuppress_path(aggregate, pi))
fc968841 7639 match++;
fc968841 7640
6aabb15d 7641 /*
365ab2e7 7642 * This must be called after `summary`, `suppress-map` check to avoid
6aabb15d
RZ
7643 * "unsuppressing" twice.
7644 */
7645 if (aggregate->match_med)
7646 bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
7647 true);
7648
fc968841
NT
7649 if (aggregate->count > 0)
7650 aggregate->count--;
7651
7652 if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
7653 aggregate->incomplete_origin_count--;
7654 else if (pi->attr->origin == BGP_ORIGIN_EGP)
7655 aggregate->egp_origin_count--;
7656
7657 if (aggregate->as_set) {
7658 /* Remove as-path from aggregate.
7659 */
7660 bgp_remove_aspath_from_aggregate(aggregate,
7661 pi->attr->aspath);
7662
7663 if (pi->attr->community)
7664 /* Remove community from aggregate.
7665 */
7666 bgp_remove_community_from_aggregate(
7667 aggregate,
7668 pi->attr->community);
7669
7670 if (pi->attr->ecommunity)
7671 /* Remove ecommunity from aggregate.
7672 */
7673 bgp_remove_ecommunity_from_aggregate(
7674 aggregate,
7675 pi->attr->ecommunity);
7676
7677 if (pi->attr->lcommunity)
7678 /* Remove lcommunity from aggregate.
7679 */
7680 bgp_remove_lcommunity_from_aggregate(
7681 aggregate,
7682 pi->attr->lcommunity);
7683 }
7684
7685 /* If this node was suppressed, process the change. */
7686 if (match)
7687 bgp_process(bgp, pi->net, afi, safi);
7688
7689 origin = BGP_ORIGIN_IGP;
7690 if (aggregate->incomplete_origin_count > 0)
7691 origin = BGP_ORIGIN_INCOMPLETE;
7692 else if (aggregate->egp_origin_count > 0)
7693 origin = BGP_ORIGIN_EGP;
7694
229757f1
DA
7695 if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
7696 origin = aggregate->origin;
7697
fc968841
NT
7698 if (aggregate->as_set) {
7699 /* Retrieve aggregate route's as-path.
7700 */
7701 if (aggregate->aspath)
7702 aspath = aspath_dup(aggregate->aspath);
7703
7704 /* Retrieve aggregate route's community.
7705 */
7706 if (aggregate->community)
7707 community = community_dup(aggregate->community);
7708
7709 /* Retrieve aggregate route's ecommunity.
7710 */
7711 if (aggregate->ecommunity)
7712 ecommunity = ecommunity_dup(aggregate->ecommunity);
7713
7714 /* Retrieve aggregate route's lcommunity.
7715 */
7716 if (aggregate->lcommunity)
7717 lcommunity = lcommunity_dup(aggregate->lcommunity);
7718 }
7719
7720 bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
7721 aspath, community, ecommunity,
7722 lcommunity, atomic_aggregate, aggregate);
7723}
7724
5a1ae2c2 7725void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
40381db7 7726 struct bgp_path_info *pi, afi_t afi, safi_t safi)
718e3744 7727{
9bcb3eef
DS
7728 struct bgp_dest *child;
7729 struct bgp_dest *dest;
d62a17ae 7730 struct bgp_aggregate *aggregate;
7731 struct bgp_table *table;
718e3744 7732
d62a17ae 7733 table = bgp->aggregate[afi][safi];
f018db83 7734
d62a17ae 7735 /* No aggregates configured. */
7736 if (bgp_table_top_nolock(table) == NULL)
7737 return;
f018db83 7738
d62a17ae 7739 if (p->prefixlen == 0)
7740 return;
718e3744 7741
40381db7 7742 if (BGP_PATH_HOLDDOWN(pi))
d62a17ae 7743 return;
718e3744 7744
a77e2f4b
S
7745 /* If suppress fib is enabled and route not installed
7746 * in FIB, do not update the aggregate route
7747 */
7748 if (!bgp_check_advertise(bgp, pi->net))
7749 return;
7750
d62a17ae 7751 child = bgp_node_get(table, p);
718e3744 7752
d62a17ae 7753 /* Aggregate address configuration check. */
9bcb3eef
DS
7754 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7755 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7756
9bcb3eef
DS
7757 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7758 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
7759 bgp_add_route_to_aggregate(bgp, dest_p, pi, afi, safi,
b54892e0 7760 aggregate);
d62a17ae 7761 }
b1e62edd 7762 }
9bcb3eef 7763 bgp_dest_unlock_node(child);
718e3744 7764}
7765
5a1ae2c2 7766void bgp_aggregate_decrement(struct bgp *bgp, const struct prefix *p,
4b7e6066 7767 struct bgp_path_info *del, afi_t afi, safi_t safi)
718e3744 7768{
9bcb3eef
DS
7769 struct bgp_dest *child;
7770 struct bgp_dest *dest;
d62a17ae 7771 struct bgp_aggregate *aggregate;
7772 struct bgp_table *table;
718e3744 7773
d62a17ae 7774 table = bgp->aggregate[afi][safi];
718e3744 7775
d62a17ae 7776 /* No aggregates configured. */
7777 if (bgp_table_top_nolock(table) == NULL)
7778 return;
718e3744 7779
d62a17ae 7780 if (p->prefixlen == 0)
7781 return;
718e3744 7782
d62a17ae 7783 child = bgp_node_get(table, p);
718e3744 7784
d62a17ae 7785 /* Aggregate address configuration check. */
9bcb3eef
DS
7786 for (dest = child; dest; dest = bgp_dest_parent_nolock(dest)) {
7787 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 7788
9bcb3eef
DS
7789 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
7790 if (aggregate != NULL && dest_p->prefixlen < p->prefixlen) {
b54892e0 7791 bgp_remove_route_from_aggregate(bgp, afi, safi, del,
9bcb3eef 7792 aggregate, dest_p);
d62a17ae 7793 }
b1e62edd 7794 }
9bcb3eef 7795 bgp_dest_unlock_node(child);
d62a17ae 7796}
718e3744 7797
718e3744 7798/* Aggregate route attribute. */
7799#define AGGREGATE_SUMMARY_ONLY 1
7800#define AGGREGATE_AS_SET 1
fb29348a 7801#define AGGREGATE_AS_UNSET 0
718e3744 7802
229757f1
DA
7803static const char *bgp_origin2str(uint8_t origin)
7804{
7805 switch (origin) {
7806 case BGP_ORIGIN_IGP:
7807 return "igp";
7808 case BGP_ORIGIN_EGP:
7809 return "egp";
7810 case BGP_ORIGIN_INCOMPLETE:
7811 return "incomplete";
7812 }
7813 return "n/a";
7814}
7815
fdeb5a81 7816static const char *bgp_rpki_validation2str(enum rpki_states v_state)
b5b99af8
DS
7817{
7818 switch (v_state) {
fdeb5a81
DS
7819 case RPKI_NOT_BEING_USED:
7820 return "not used";
7821 case RPKI_VALID:
b5b99af8 7822 return "valid";
fdeb5a81 7823 case RPKI_NOTFOUND:
b5b99af8 7824 return "not found";
fdeb5a81 7825 case RPKI_INVALID:
b5b99af8 7826 return "invalid";
b5b99af8 7827 }
fdeb5a81
DS
7828
7829 assert(!"We should never get here this is a dev escape");
b5b99af8
DS
7830 return "ERROR";
7831}
7832
585f1adc
IR
7833static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
7834 afi_t afi, safi_t safi)
718e3744 7835{
585f1adc
IR
7836 VTY_DECLVAR_CONTEXT(bgp, bgp);
7837 int ret;
7838 struct prefix p;
9bcb3eef 7839 struct bgp_dest *dest;
d62a17ae 7840 struct bgp_aggregate *aggregate;
718e3744 7841
585f1adc
IR
7842 /* Convert string to prefix structure. */
7843 ret = str2prefix(prefix_str, &p);
7844 if (!ret) {
7845 vty_out(vty, "Malformed prefix\n");
7846 return CMD_WARNING_CONFIG_FAILED;
7847 }
7848 apply_mask(&p);
a4559740 7849
d62a17ae 7850 /* Old configuration check. */
585f1adc 7851 dest = bgp_node_lookup(bgp->aggregate[afi][safi], &p);
9bcb3eef 7852 if (!dest) {
585f1adc
IR
7853 vty_out(vty,
7854 "%% There is no aggregate-address configuration.\n");
7855 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7856 }
f6269b4f 7857
9bcb3eef 7858 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
585f1adc
IR
7859 bgp_aggregate_delete(bgp, &p, afi, safi, aggregate);
7860 bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL,
7861 NULL, NULL, 0, aggregate);
d62a17ae 7862
7863 /* Unlock aggregate address configuration. */
9bcb3eef 7864 bgp_dest_set_bgp_aggregate_info(dest, NULL);
fc968841
NT
7865
7866 if (aggregate->community)
7867 community_free(&aggregate->community);
7868
7869 if (aggregate->community_hash) {
7870 /* Delete all communities in the hash.
7871 */
7872 hash_clean(aggregate->community_hash,
7873 bgp_aggr_community_remove);
7874 /* Free up the community_hash.
7875 */
7876 hash_free(aggregate->community_hash);
7877 }
7878
7879 if (aggregate->ecommunity)
7880 ecommunity_free(&aggregate->ecommunity);
7881
7882 if (aggregate->ecommunity_hash) {
7883 /* Delete all ecommunities in the hash.
7884 */
7885 hash_clean(aggregate->ecommunity_hash,
7886 bgp_aggr_ecommunity_remove);
7887 /* Free up the ecommunity_hash.
7888 */
7889 hash_free(aggregate->ecommunity_hash);
7890 }
7891
7892 if (aggregate->lcommunity)
7893 lcommunity_free(&aggregate->lcommunity);
7894
7895 if (aggregate->lcommunity_hash) {
7896 /* Delete all lcommunities in the hash.
7897 */
7898 hash_clean(aggregate->lcommunity_hash,
7899 bgp_aggr_lcommunity_remove);
7900 /* Free up the lcommunity_hash.
7901 */
7902 hash_free(aggregate->lcommunity_hash);
7903 }
7904
7905 if (aggregate->aspath)
7906 aspath_free(aggregate->aspath);
7907
7908 if (aggregate->aspath_hash) {
7909 /* Delete all as-paths in the hash.
7910 */
7911 hash_clean(aggregate->aspath_hash,
7912 bgp_aggr_aspath_remove);
7913 /* Free up the aspath_hash.
7914 */
7915 hash_free(aggregate->aspath_hash);
7916 }
7917
d62a17ae 7918 bgp_aggregate_free(aggregate);
9bcb3eef
DS
7919 bgp_dest_unlock_node(dest);
7920 bgp_dest_unlock_node(dest);
d62a17ae 7921
585f1adc 7922 return CMD_SUCCESS;
d62a17ae 7923}
7924
585f1adc
IR
7925static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
7926 safi_t safi, const char *rmap,
7927 uint8_t summary_only, uint8_t as_set,
7928 uint8_t origin, bool match_med,
7929 const char *suppress_map)
d62a17ae 7930{
585f1adc 7931 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 7932 int ret;
585f1adc 7933 struct prefix p;
9bcb3eef 7934 struct bgp_dest *dest;
d62a17ae 7935 struct bgp_aggregate *aggregate;
fb29348a 7936 uint8_t as_set_new = as_set;
d62a17ae 7937
365ab2e7 7938 if (suppress_map && summary_only) {
585f1adc 7939 vty_out(vty,
365ab2e7 7940 "'summary-only' and 'suppress-map' can't be used at the same time\n");
585f1adc 7941 return CMD_WARNING_CONFIG_FAILED;
365ab2e7
RZ
7942 }
7943
585f1adc
IR
7944 /* Convert string to prefix structure. */
7945 ret = str2prefix(prefix_str, &p);
7946 if (!ret) {
7947 vty_out(vty, "Malformed prefix\n");
7948 return CMD_WARNING_CONFIG_FAILED;
7949 }
7950 apply_mask(&p);
d62a17ae 7951
585f1adc
IR
7952 if ((afi == AFI_IP && p.prefixlen == IPV4_MAX_BITLEN) ||
7953 (afi == AFI_IP6 && p.prefixlen == IPV6_MAX_BITLEN)) {
7954 vty_out(vty, "Specified prefix: %s will not result in any useful aggregation, disallowing\n",
7955 prefix_str);
7956 return CMD_WARNING_CONFIG_FAILED;
3624ac81
DS
7957 }
7958
d62a17ae 7959 /* Old configuration check. */
585f1adc 7960 dest = bgp_node_get(bgp->aggregate[afi][safi], &p);
9bcb3eef 7961 aggregate = bgp_dest_get_bgp_aggregate_info(dest);
d62a17ae 7962
20894f50 7963 if (aggregate) {
585f1adc 7964 vty_out(vty, "There is already same aggregate network.\n");
d62a17ae 7965 /* try to remove the old entry */
585f1adc 7966 ret = bgp_aggregate_unset(vty, prefix_str, afi, safi);
d62a17ae 7967 if (ret) {
585f1adc 7968 vty_out(vty, "Error deleting aggregate.\n");
9bcb3eef 7969 bgp_dest_unlock_node(dest);
585f1adc 7970 return CMD_WARNING_CONFIG_FAILED;
d62a17ae 7971 }
7972 }
718e3744 7973
d62a17ae 7974 /* Make aggregate address structure. */
7975 aggregate = bgp_aggregate_new();
7976 aggregate->summary_only = summary_only;
6aabb15d 7977 aggregate->match_med = match_med;
fb29348a
DA
7978
7979 /* Network operators MUST NOT locally generate any new
7980 * announcements containing AS_SET or AS_CONFED_SET. If they have
7981 * announced routes with AS_SET or AS_CONFED_SET in them, then they
7982 * SHOULD withdraw those routes and re-announce routes for the
7983 * aggregate or component prefixes (i.e., the more-specific routes
7984 * subsumed by the previously aggregated route) without AS_SET
7985 * or AS_CONFED_SET in the updates.
7986 */
7f972cd8 7987 if (bgp->reject_as_sets) {
fb29348a
DA
7988 if (as_set == AGGREGATE_AS_SET) {
7989 as_set_new = AGGREGATE_AS_UNSET;
7990 zlog_warn(
63efca0e 7991 "%s: Ignoring as-set because `bgp reject-as-sets` is enabled.",
fb29348a 7992 __func__);
585f1adc 7993 vty_out(vty,
fb29348a
DA
7994 "Ignoring as-set because `bgp reject-as-sets` is enabled.\n");
7995 }
7996 }
7997
7998 aggregate->as_set = as_set_new;
d62a17ae 7999 aggregate->safi = safi;
229757f1
DA
8000 /* Override ORIGIN attribute if defined.
8001 * E.g.: Cisco and Juniper set ORIGIN for aggregated address
8002 * to IGP which is not what rfc4271 says.
8003 * This enables the same behavior, optionally.
8004 */
8005 aggregate->origin = origin;
20894f50
DA
8006
8007 if (rmap) {
8008 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
8009 route_map_counter_decrement(aggregate->rmap.map);
8010 aggregate->rmap.name =
8011 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
8012 aggregate->rmap.map = route_map_lookup_by_name(rmap);
8013 route_map_counter_increment(aggregate->rmap.map);
8014 }
365ab2e7
RZ
8015
8016 if (suppress_map) {
8017 XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->suppress_map_name);
8018 route_map_counter_decrement(aggregate->suppress_map);
8019
8020 aggregate->suppress_map_name =
8021 XSTRDUP(MTYPE_ROUTE_MAP_NAME, suppress_map);
8022 aggregate->suppress_map =
8023 route_map_lookup_by_name(aggregate->suppress_map_name);
8024 route_map_counter_increment(aggregate->suppress_map);
8025 }
8026
9bcb3eef 8027 bgp_dest_set_bgp_aggregate_info(dest, aggregate);
718e3744 8028
d62a17ae 8029 /* Aggregate address insert into BGP routing table. */
585f1adc 8030 bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
718e3744 8031
585f1adc 8032 return CMD_SUCCESS;
718e3744 8033}
8034
585f1adc
IR
8035DEFPY(aggregate_addressv4, aggregate_addressv4_cmd,
8036 "[no] aggregate-address <A.B.C.D/M$prefix|A.B.C.D$addr A.B.C.D$mask> [{"
8037 "as-set$as_set_s"
8038 "|summary-only$summary_only"
8039 "|route-map WORD$rmap_name"
8040 "|origin <egp|igp|incomplete>$origin_s"
8041 "|matching-MED-only$match_med"
8042 "|suppress-map WORD$suppress_map"
8043 "}]",
8044 NO_STR
8045 "Configure BGP aggregate entries\n"
8046 "Aggregate prefix\n" "Aggregate address\n" "Aggregate mask\n"
8047 "Generate AS set path information\n"
8048 "Filter more specific routes from updates\n"
8049 "Apply route map to aggregate network\n"
8050 "Route map name\n"
8051 "BGP origin code\n"
8052 "Remote EGP\n"
8053 "Local IGP\n"
8054 "Unknown heritage\n"
8055 "Only aggregate routes with matching MED\n"
8056 "Suppress the selected more specific routes\n"
8057 "Route map with the route selectors\n")
8058{
8059 const char *prefix_s = NULL;
554b3b10 8060 safi_t safi = bgp_node_safi(vty);
585f1adc
IR
8061 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8062 int as_set = AGGREGATE_AS_UNSET;
554b3b10 8063 char prefix_buf[PREFIX2STR_BUFFER];
d62a17ae 8064
554b3b10 8065 if (addr_str) {
7533cad7
QY
8066 if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
8067 sizeof(prefix_buf))
554b3b10
RZ
8068 == 0) {
8069 vty_out(vty, "%% Inconsistent address and mask\n");
8070 return CMD_WARNING_CONFIG_FAILED;
8071 }
585f1adc
IR
8072 prefix_s = prefix_buf;
8073 } else
8074 prefix_s = prefix_str;
37a87b8f 8075
585f1adc
IR
8076 if (origin_s) {
8077 if (strcmp(origin_s, "egp") == 0)
8078 origin = BGP_ORIGIN_EGP;
8079 else if (strcmp(origin_s, "igp") == 0)
8080 origin = BGP_ORIGIN_IGP;
8081 else if (strcmp(origin_s, "incomplete") == 0)
8082 origin = BGP_ORIGIN_INCOMPLETE;
8083 }
90e21f35 8084
585f1adc
IR
8085 if (as_set_s)
8086 as_set = AGGREGATE_AS_SET;
554b3b10 8087
585f1adc 8088 /* Handle configuration removal, otherwise installation. */
554b3b10 8089 if (no)
585f1adc
IR
8090 return bgp_aggregate_unset(vty, prefix_s, AFI_IP, safi);
8091
8092 return bgp_aggregate_set(vty, prefix_s, AFI_IP, safi, rmap_name,
8093 summary_only != NULL, as_set, origin,
8094 match_med != NULL, suppress_map);
8095}
8096
8097DEFPY(aggregate_addressv6, aggregate_addressv6_cmd,
8098 "[no] aggregate-address X:X::X:X/M$prefix [{"
8099 "as-set$as_set_s"
8100 "|summary-only$summary_only"
8101 "|route-map WORD$rmap_name"
8102 "|origin <egp|igp|incomplete>$origin_s"
8103 "|matching-MED-only$match_med"
8104 "|suppress-map WORD$suppress_map"
8105 "}]",
8106 NO_STR
8107 "Configure BGP aggregate entries\n"
8108 "Aggregate prefix\n"
8109 "Generate AS set path information\n"
8110 "Filter more specific routes from updates\n"
8111 "Apply route map to aggregate network\n"
8112 "Route map name\n"
8113 "BGP origin code\n"
8114 "Remote EGP\n"
8115 "Local IGP\n"
8116 "Unknown heritage\n"
8117 "Only aggregate routes with matching MED\n"
8118 "Suppress the selected more specific routes\n"
8119 "Route map with the route selectors\n")
8120{
8121 uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
8122 int as_set = AGGREGATE_AS_UNSET;
8123
8124 if (origin_s) {
8125 if (strcmp(origin_s, "egp") == 0)
8126 origin = BGP_ORIGIN_EGP;
8127 else if (strcmp(origin_s, "igp") == 0)
8128 origin = BGP_ORIGIN_IGP;
8129 else if (strcmp(origin_s, "incomplete") == 0)
8130 origin = BGP_ORIGIN_INCOMPLETE;
8131 }
8132
8133 if (as_set_s)
8134 as_set = AGGREGATE_AS_SET;
8135
8136 /* Handle configuration removal, otherwise installation. */
554b3b10 8137 if (no)
585f1adc
IR
8138 return bgp_aggregate_unset(vty, prefix_str, AFI_IP6,
8139 SAFI_UNICAST);
554b3b10 8140
585f1adc
IR
8141 return bgp_aggregate_set(vty, prefix_str, AFI_IP6, SAFI_UNICAST,
8142 rmap_name, summary_only != NULL, as_set,
8143 origin, match_med != NULL, suppress_map);
718e3744 8144}
8145
718e3744 8146/* Redistribute route treatment. */
d62a17ae 8147void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
9de1f7ff 8148 const union g_addr *nexthop, ifindex_t ifindex,
957f74c3 8149 enum nexthop_types_t nhtype, uint8_t distance,
0789eb69
KM
8150 enum blackhole_type bhtype, uint32_t metric,
8151 uint8_t type, unsigned short instance,
8152 route_tag_t tag)
d62a17ae 8153{
4b7e6066 8154 struct bgp_path_info *new;
40381db7
DS
8155 struct bgp_path_info *bpi;
8156 struct bgp_path_info rmap_path;
9bcb3eef 8157 struct bgp_dest *bn;
d62a17ae 8158 struct attr attr;
8159 struct attr *new_attr;
8160 afi_t afi;
b68885f9 8161 route_map_result_t ret;
d62a17ae 8162 struct bgp_redist *red;
8163
8164 /* Make default attribute. */
8165 bgp_attr_default_set(&attr, BGP_ORIGIN_INCOMPLETE);
401b0636
DS
8166 /*
8167 * This must not be NULL to satisfy Coverity SA
8168 */
8169 assert(attr.aspath);
9de1f7ff 8170
a4d82a8a 8171 switch (nhtype) {
9de1f7ff
DS
8172 case NEXTHOP_TYPE_IFINDEX:
8173 break;
8174 case NEXTHOP_TYPE_IPV4:
8175 case NEXTHOP_TYPE_IPV4_IFINDEX:
8176 attr.nexthop = nexthop->ipv4;
8177 break;
8178 case NEXTHOP_TYPE_IPV6:
8179 case NEXTHOP_TYPE_IPV6_IFINDEX:
8180 attr.mp_nexthop_global = nexthop->ipv6;
8181 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
8182 break;
8183 case NEXTHOP_TYPE_BLACKHOLE:
74489921
RW
8184 switch (p->family) {
8185 case AF_INET:
9de1f7ff 8186 attr.nexthop.s_addr = INADDR_ANY;
74489921
RW
8187 break;
8188 case AF_INET6:
9de1f7ff
DS
8189 memset(&attr.mp_nexthop_global, 0,
8190 sizeof(attr.mp_nexthop_global));
74489921 8191 attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
9de1f7ff 8192 break;
74489921 8193 }
0789eb69 8194 attr.bh_type = bhtype;
9de1f7ff 8195 break;
d62a17ae 8196 }
0789eb69 8197 attr.nh_type = nhtype;
74489921 8198 attr.nh_ifindex = ifindex;
f04a80a5 8199
d62a17ae 8200 attr.med = metric;
957f74c3 8201 attr.distance = distance;
d62a17ae 8202 attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
8203 attr.tag = tag;
718e3744 8204
d62a17ae 8205 afi = family2afi(p->family);
6aeb9e78 8206
d62a17ae 8207 red = bgp_redist_lookup(bgp, afi, type, instance);
8208 if (red) {
8209 struct attr attr_new;
718e3744 8210
d62a17ae 8211 /* Copy attribute for modification. */
6f4f49b2 8212 attr_new = attr;
718e3744 8213
d62a17ae 8214 if (red->redist_metric_flag)
8215 attr_new.med = red->redist_metric;
718e3744 8216
d62a17ae 8217 /* Apply route-map. */
8218 if (red->rmap.name) {
40381db7
DS
8219 memset(&rmap_path, 0, sizeof(struct bgp_path_info));
8220 rmap_path.peer = bgp->peer_self;
8221 rmap_path.attr = &attr_new;
718e3744 8222
d62a17ae 8223 SET_FLAG(bgp->peer_self->rmap_type,
8224 PEER_RMAP_TYPE_REDISTRIBUTE);
8225
1782514f 8226 ret = route_map_apply(red->rmap.map, p, &rmap_path);
d62a17ae 8227
8228 bgp->peer_self->rmap_type = 0;
8229
8230 if (ret == RMAP_DENYMATCH) {
8231 /* Free uninterned attribute. */
8232 bgp_attr_flush(&attr_new);
8233
8234 /* Unintern original. */
8235 aspath_unintern(&attr.aspath);
8236 bgp_redistribute_delete(bgp, p, type, instance);
8237 return;
8238 }
8239 }
8240
637e5ba4 8241 if (bgp_in_graceful_shutdown(bgp))
7f323236
DW
8242 bgp_attr_add_gshut_community(&attr_new);
8243
d62a17ae 8244 bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8245 SAFI_UNICAST, p, NULL);
8246
8247 new_attr = bgp_attr_intern(&attr_new);
8248
9bcb3eef 8249 for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next)
40381db7
DS
8250 if (bpi->peer == bgp->peer_self
8251 && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE)
d62a17ae 8252 break;
8253
40381db7 8254 if (bpi) {
d62a17ae 8255 /* Ensure the (source route) type is updated. */
40381db7
DS
8256 bpi->type = type;
8257 if (attrhash_cmp(bpi->attr, new_attr)
8258 && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
d62a17ae 8259 bgp_attr_unintern(&new_attr);
8260 aspath_unintern(&attr.aspath);
9bcb3eef 8261 bgp_dest_unlock_node(bn);
d62a17ae 8262 return;
8263 } else {
8264 /* The attribute is changed. */
40381db7 8265 bgp_path_info_set_flag(bn, bpi,
18ee8310 8266 BGP_PATH_ATTR_CHANGED);
d62a17ae 8267
8268 /* Rewrite BGP route information. */
40381db7
DS
8269 if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED))
8270 bgp_path_info_restore(bn, bpi);
d62a17ae 8271 else
40381db7
DS
8272 bgp_aggregate_decrement(
8273 bgp, p, bpi, afi, SAFI_UNICAST);
8274 bgp_attr_unintern(&bpi->attr);
8275 bpi->attr = new_attr;
8276 bpi->uptime = bgp_clock();
d62a17ae 8277
8278 /* Process change. */
40381db7 8279 bgp_aggregate_increment(bgp, p, bpi, afi,
d62a17ae 8280 SAFI_UNICAST);
8281 bgp_process(bgp, bn, afi, SAFI_UNICAST);
9bcb3eef 8282 bgp_dest_unlock_node(bn);
d62a17ae 8283 aspath_unintern(&attr.aspath);
ddb5b488
PZ
8284
8285 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8286 || (bgp->inst_type
8287 == BGP_INSTANCE_TYPE_DEFAULT)) {
8288
8289 vpn_leak_from_vrf_update(
40381db7 8290 bgp_get_default(), bgp, bpi);
ddb5b488 8291 }
d62a17ae 8292 return;
8293 }
8294 }
8295
8296 new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance,
8297 bgp->peer_self, new_attr, bn);
1defdda8 8298 SET_FLAG(new->flags, BGP_PATH_VALID);
d62a17ae 8299
8300 bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST);
18ee8310 8301 bgp_path_info_add(bn, new);
9bcb3eef 8302 bgp_dest_unlock_node(bn);
d62a17ae 8303 bgp_process(bgp, bn, afi, SAFI_UNICAST);
ddb5b488
PZ
8304
8305 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8306 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8307
8308 vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
8309 }
d62a17ae 8310 }
8311
8312 /* Unintern original. */
8313 aspath_unintern(&attr.aspath);
718e3744 8314}
8315
d7c0a89a
QY
8316void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
8317 unsigned short instance)
718e3744 8318{
d62a17ae 8319 afi_t afi;
9bcb3eef 8320 struct bgp_dest *dest;
40381db7 8321 struct bgp_path_info *pi;
d62a17ae 8322 struct bgp_redist *red;
718e3744 8323
d62a17ae 8324 afi = family2afi(p->family);
718e3744 8325
d62a17ae 8326 red = bgp_redist_lookup(bgp, afi, type, instance);
8327 if (red) {
9bcb3eef
DS
8328 dest = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
8329 SAFI_UNICAST, p, NULL);
d62a17ae 8330
9bcb3eef 8331 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7 8332 if (pi->peer == bgp->peer_self && pi->type == type)
d62a17ae 8333 break;
8334
40381db7 8335 if (pi) {
ddb5b488
PZ
8336 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8337 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8338
8339 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8340 bgp, pi);
ddb5b488 8341 }
40381db7 8342 bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8343 bgp_path_info_delete(dest, pi);
8344 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8345 }
9bcb3eef 8346 bgp_dest_unlock_node(dest);
d62a17ae 8347 }
8348}
8349
8350/* Withdraw specified route type's route. */
8351void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
d7c0a89a 8352 unsigned short instance)
d62a17ae 8353{
9bcb3eef 8354 struct bgp_dest *dest;
40381db7 8355 struct bgp_path_info *pi;
d62a17ae 8356 struct bgp_table *table;
8357
8358 table = bgp->rib[afi][SAFI_UNICAST];
8359
9bcb3eef
DS
8360 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
8361 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
40381db7
DS
8362 if (pi->peer == bgp->peer_self && pi->type == type
8363 && pi->instance == instance)
d62a17ae 8364 break;
8365
40381db7 8366 if (pi) {
ddb5b488
PZ
8367 if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
8368 || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
8369
8370 vpn_leak_from_vrf_withdraw(bgp_get_default(),
40381db7 8371 bgp, pi);
ddb5b488 8372 }
9bcb3eef 8373 bgp_aggregate_decrement(bgp, bgp_dest_get_prefix(dest),
b54892e0 8374 pi, afi, SAFI_UNICAST);
9bcb3eef
DS
8375 bgp_path_info_delete(dest, pi);
8376 bgp_process(bgp, dest, afi, SAFI_UNICAST);
d62a17ae 8377 }
718e3744 8378 }
718e3744 8379}
6b0655a2 8380
718e3744 8381/* Static function to display route. */
7d3cae70
DA
8382static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
8383 struct vty *vty, json_object *json, bool wide)
718e3744 8384{
be054588 8385 int len = 0;
d62a17ae 8386 char buf[BUFSIZ];
50e05855 8387 char buf2[BUFSIZ];
718e3744 8388
d62a17ae 8389 if (p->family == AF_INET) {
c6462ff4 8390 if (!json) {
8228a9a7 8391 len = vty_out(vty, "%pFX", p);
c6462ff4
MK
8392 } else {
8393 json_object_string_add(json, "prefix",
8394 inet_ntop(p->family,
8395 &p->u.prefix, buf,
8396 BUFSIZ));
8397 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df 8398 prefix2str(p, buf2, PREFIX_STRLEN);
50e05855 8399 json_object_string_add(json, "network", buf2);
7d3cae70 8400 json_object_int_add(json, "version", dest->version);
c6462ff4 8401 }
d62a17ae 8402 } else if (p->family == AF_ETHERNET) {
8228a9a7 8403 len = vty_out(vty, "%pFX", p);
b03b8898 8404 } else if (p->family == AF_EVPN) {
57f7feb6 8405 if (!json)
2dbe669b 8406 len = vty_out(vty, "%pFX", (struct prefix_evpn *)p);
57f7feb6 8407 else
60466a63 8408 bgp_evpn_route2json((struct prefix_evpn *)p, json);
dba3c1d3
PG
8409 } else if (p->family == AF_FLOWSPEC) {
8410 route_vty_out_flowspec(vty, p, NULL,
d33fc23b
PG
8411 json ?
8412 NLRI_STRING_FORMAT_JSON_SIMPLE :
8413 NLRI_STRING_FORMAT_MIN, json);
9c92b5f7 8414 } else {
c6462ff4 8415 if (!json)
8228a9a7 8416 len = vty_out(vty, "%pFX", p);
50e05855
AD
8417 else {
8418 json_object_string_add(json, "prefix",
8419 inet_ntop(p->family,
8420 &p->u.prefix, buf,
8421 BUFSIZ));
8422 json_object_int_add(json, "prefixLen", p->prefixlen);
37d4e0df
AD
8423 prefix2str(p, buf2, PREFIX_STRLEN);
8424 json_object_string_add(json, "network", buf2);
7d3cae70 8425 json_object_int_add(json, "version", dest->version);
37d4e0df 8426 }
9c92b5f7 8427 }
d62a17ae 8428
9c92b5f7 8429 if (!json) {
ae248832 8430 len = wide ? (45 - len) : (17 - len);
9c92b5f7
MK
8431 if (len < 1)
8432 vty_out(vty, "\n%*s", 20, " ");
8433 else
8434 vty_out(vty, "%*s", len, " ");
8435 }
718e3744 8436}
8437
d62a17ae 8438enum bgp_display_type {
8439 normal_list,
718e3744 8440};
8441
1d7260a1 8442const char *bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
bbb46eb5
DA
8443{
8444 switch (reason) {
8445 case bgp_path_selection_none:
8446 return "Nothing to Select";
8447 case bgp_path_selection_first:
8448 return "First path received";
8449 case bgp_path_selection_evpn_sticky_mac:
8450 return "EVPN Sticky Mac";
8451 case bgp_path_selection_evpn_seq:
8452 return "EVPN sequence number";
8453 case bgp_path_selection_evpn_lower_ip:
8454 return "EVPN lower IP";
8455 case bgp_path_selection_evpn_local_path:
8456 return "EVPN local ES path";
8457 case bgp_path_selection_evpn_non_proxy:
8458 return "EVPN non proxy";
8459 case bgp_path_selection_weight:
8460 return "Weight";
8461 case bgp_path_selection_local_pref:
8462 return "Local Pref";
8463 case bgp_path_selection_local_route:
8464 return "Local Route";
8465 case bgp_path_selection_confed_as_path:
8466 return "Confederation based AS Path";
8467 case bgp_path_selection_as_path:
8468 return "AS Path";
8469 case bgp_path_selection_origin:
8470 return "Origin";
8471 case bgp_path_selection_med:
8472 return "MED";
8473 case bgp_path_selection_peer:
8474 return "Peer Type";
8475 case bgp_path_selection_confed:
8476 return "Confed Peer Type";
8477 case bgp_path_selection_igp_metric:
8478 return "IGP Metric";
8479 case bgp_path_selection_older:
8480 return "Older Path";
8481 case bgp_path_selection_router_id:
8482 return "Router ID";
8483 case bgp_path_selection_cluster_length:
bcab253c 8484 return "Cluster length";
bbb46eb5
DA
8485 case bgp_path_selection_stale:
8486 return "Path Staleness";
8487 case bgp_path_selection_local_configured:
8488 return "Locally configured route";
8489 case bgp_path_selection_neighbor_ip:
8490 return "Neighbor IP";
8491 case bgp_path_selection_default:
8492 return "Nothing left to compare";
8493 }
8494 return "Invalid (internal error)";
8495}
8496
18ee8310 8497/* Print the short form route status for a bgp_path_info */
4b7e6066 8498static void route_vty_short_status_out(struct vty *vty,
9b6d8fcf 8499 struct bgp_path_info *path,
82c298be 8500 const struct prefix *p,
d62a17ae 8501 json_object *json_path)
718e3744 8502{
82c298be
DA
8503 enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
8504
d62a17ae 8505 if (json_path) {
b05a1c8b 8506
d62a17ae 8507 /* Route status display. */
9b6d8fcf 8508 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8509 json_object_boolean_true_add(json_path, "removed");
b05a1c8b 8510
9b6d8fcf 8511 if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8512 json_object_boolean_true_add(json_path, "stale");
b05a1c8b 8513
4056a5f6 8514 if (path->extra && bgp_path_suppressed(path))
d62a17ae 8515 json_object_boolean_true_add(json_path, "suppressed");
b05a1c8b 8516
9b6d8fcf
DS
8517 if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8518 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8519 json_object_boolean_true_add(json_path, "valid");
b05a1c8b 8520
d62a17ae 8521 /* Selected */
9b6d8fcf 8522 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8523 json_object_boolean_true_add(json_path, "history");
b05a1c8b 8524
9b6d8fcf 8525 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8526 json_object_boolean_true_add(json_path, "damped");
b05a1c8b 8527
bbb46eb5 8528 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
d62a17ae 8529 json_object_boolean_true_add(json_path, "bestpath");
bbb46eb5
DA
8530 json_object_string_add(json_path, "selectionReason",
8531 bgp_path_selection_reason2str(
8532 path->net->reason));
8533 }
b05a1c8b 8534
9b6d8fcf 8535 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8536 json_object_boolean_true_add(json_path, "multipath");
b05a1c8b 8537
d62a17ae 8538 /* Internal route. */
9b6d8fcf
DS
8539 if ((path->peer->as)
8540 && (path->peer->as == path->peer->local_as))
d62a17ae 8541 json_object_string_add(json_path, "pathFrom",
8542 "internal");
8543 else
8544 json_object_string_add(json_path, "pathFrom",
8545 "external");
b05a1c8b 8546
d62a17ae 8547 return;
8548 }
b05a1c8b 8549
82c298be
DA
8550 /* RPKI validation state */
8551 rpki_state =
8552 hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
8553
8554 if (rpki_state == RPKI_VALID)
8555 vty_out(vty, "V");
8556 else if (rpki_state == RPKI_INVALID)
8557 vty_out(vty, "I");
8558 else if (rpki_state == RPKI_NOTFOUND)
8559 vty_out(vty, "N");
8560
d62a17ae 8561 /* Route status display. */
9b6d8fcf 8562 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
d62a17ae 8563 vty_out(vty, "R");
9b6d8fcf 8564 else if (CHECK_FLAG(path->flags, BGP_PATH_STALE))
d62a17ae 8565 vty_out(vty, "S");
4056a5f6 8566 else if (bgp_path_suppressed(path))
d62a17ae 8567 vty_out(vty, "s");
9b6d8fcf
DS
8568 else if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
8569 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8570 vty_out(vty, "*");
8571 else
8572 vty_out(vty, " ");
8573
8574 /* Selected */
9b6d8fcf 8575 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 8576 vty_out(vty, "h");
9b6d8fcf 8577 else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
d62a17ae 8578 vty_out(vty, "d");
9b6d8fcf 8579 else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 8580 vty_out(vty, ">");
9b6d8fcf 8581 else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH))
d62a17ae 8582 vty_out(vty, "=");
8583 else
8584 vty_out(vty, " ");
718e3744 8585
d62a17ae 8586 /* Internal route. */
9b6d8fcf
DS
8587 if (path->peer && (path->peer->as)
8588 && (path->peer->as == path->peer->local_as))
d62a17ae 8589 vty_out(vty, "i");
8590 else
8591 vty_out(vty, " ");
b40d939b 8592}
8593
2ba93fd6
DA
8594static char *bgp_nexthop_hostname(struct peer *peer,
8595 struct bgp_nexthop_cache *bnc)
25b5da8d 8596{
892fedb6 8597 if (peer->hostname
aef999a2 8598 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_NEXTHOP_HOSTNAME))
25b5da8d
DA
8599 return peer->hostname;
8600 return NULL;
8601}
8602
b40d939b 8603/* called from terminal list command */
bd494ec5 8604void route_vty_out(struct vty *vty, const struct prefix *p,
9b6d8fcf 8605 struct bgp_path_info *path, int display, safi_t safi,
ae248832 8606 json_object *json_paths, bool wide)
d62a17ae 8607{
aef999a2 8608 int len;
515c2602 8609 struct attr *attr = path->attr;
d62a17ae 8610 json_object *json_path = NULL;
8611 json_object *json_nexthops = NULL;
8612 json_object *json_nexthop_global = NULL;
8613 json_object *json_nexthop_ll = NULL;
6f214dd3 8614 json_object *json_ext_community = NULL;
9df8b37c 8615 char vrf_id_str[VRF_NAMSIZ] = {0};
1defdda8 8616 bool nexthop_self =
9b6d8fcf 8617 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
9df8b37c 8618 bool nexthop_othervrf = false;
43089216 8619 vrf_id_t nexthop_vrfid = VRF_DEFAULT;
4d97eea6 8620 const char *nexthop_vrfname = VRF_DEFAULT_NAME;
2ba93fd6
DA
8621 char *nexthop_hostname =
8622 bgp_nexthop_hostname(path->peer, path->nexthop);
b5e140c8 8623 char esi_buf[ESI_STR_LEN];
d62a17ae 8624
8625 if (json_paths)
8626 json_path = json_object_new_object();
8627
8628 /* short status lead text */
82c298be 8629 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 8630
8631 if (!json_paths) {
8632 /* print prefix and mask */
8633 if (!display)
7d3cae70 8634 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8635 else
ae248832 8636 vty_out(vty, "%*s", (wide ? 45 : 17), " ");
9c92b5f7 8637 } else {
7d3cae70 8638 route_vty_out_route(path->net, p, vty, json_path, wide);
d62a17ae 8639 }
47fc97cc 8640
9df8b37c
PZ
8641 /*
8642 * If vrf id of nexthop is different from that of prefix,
8643 * set up printable string to append
8644 */
9b6d8fcf 8645 if (path->extra && path->extra->bgp_orig) {
9df8b37c
PZ
8646 const char *self = "";
8647
8648 if (nexthop_self)
8649 self = "<";
8650
8651 nexthop_othervrf = true;
9b6d8fcf 8652 nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 8653
9b6d8fcf 8654 if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
9df8b37c
PZ
8655 snprintf(vrf_id_str, sizeof(vrf_id_str),
8656 "@%s%s", VRFID_NONE_STR, self);
8657 else
8658 snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
9b6d8fcf 8659 path->extra->bgp_orig->vrf_id, self);
9df8b37c 8660
9b6d8fcf
DS
8661 if (path->extra->bgp_orig->inst_type
8662 != BGP_INSTANCE_TYPE_DEFAULT)
9df8b37c 8663
9b6d8fcf 8664 nexthop_vrfname = path->extra->bgp_orig->name;
9df8b37c
PZ
8665 } else {
8666 const char *self = "";
8667
8668 if (nexthop_self)
8669 self = "<";
8670
8671 snprintf(vrf_id_str, sizeof(vrf_id_str), "%s", self);
8672 }
8673
445c2480
DS
8674 /*
8675 * For ENCAP and EVPN routes, nexthop address family is not
8676 * neccessarily the same as the prefix address family.
8677 * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field
8678 * EVPN routes are also exchanged with a MP nexthop. Currently,
8679 * this
8680 * is only IPv4, the value will be present in either
8681 * attr->nexthop or
8682 * attr->mp_nexthop_global_in
8683 */
8684 if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) {
8685 char buf[BUFSIZ];
8686 char nexthop[128];
8687 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
8688
8689 switch (af) {
8690 case AF_INET:
772270f3
QY
8691 snprintf(nexthop, sizeof(nexthop), "%s",
8692 inet_ntop(af, &attr->mp_nexthop_global_in, buf,
8693 BUFSIZ));
445c2480
DS
8694 break;
8695 case AF_INET6:
772270f3
QY
8696 snprintf(nexthop, sizeof(nexthop), "%s",
8697 inet_ntop(af, &attr->mp_nexthop_global, buf,
8698 BUFSIZ));
445c2480
DS
8699 break;
8700 default:
772270f3 8701 snprintf(nexthop, sizeof(nexthop), "?");
445c2480 8702 break;
d62a17ae 8703 }
d62a17ae 8704
445c2480
DS
8705 if (json_paths) {
8706 json_nexthop_global = json_object_new_object();
8707
515c2602
DA
8708 json_object_string_add(json_nexthop_global, "ip",
8709 nexthop);
8710
939a97f4 8711 if (path->peer->hostname)
515c2602
DA
8712 json_object_string_add(json_nexthop_global,
8713 "hostname",
939a97f4 8714 path->peer->hostname);
515c2602
DA
8715
8716 json_object_string_add(json_nexthop_global, "afi",
8717 (af == AF_INET) ? "ipv4"
8718 : "ipv6");
445c2480
DS
8719 json_object_boolean_true_add(json_nexthop_global,
8720 "used");
aef999a2
DA
8721 } else {
8722 if (nexthop_hostname)
8723 len = vty_out(vty, "%s(%s)%s", nexthop,
8724 nexthop_hostname, vrf_id_str);
8725 else
8726 len = vty_out(vty, "%s%s", nexthop, vrf_id_str);
8727
ae248832 8728 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8729 if (len < 1)
8730 vty_out(vty, "\n%*s", 36, " ");
8731 else
8732 vty_out(vty, "%*s", len, " ");
8733 }
445c2480
DS
8734 } else if (safi == SAFI_EVPN) {
8735 if (json_paths) {
23d0a753
DA
8736 char buf[BUFSIZ] = {0};
8737
445c2480
DS
8738 json_nexthop_global = json_object_new_object();
8739
515c2602 8740 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8741 inet_ntop(AF_INET,
8742 &attr->nexthop, buf,
8743 sizeof(buf)));
515c2602 8744
939a97f4 8745 if (path->peer->hostname)
515c2602
DA
8746 json_object_string_add(json_nexthop_global,
8747 "hostname",
939a97f4 8748 path->peer->hostname);
515c2602 8749
a4d82a8a
PZ
8750 json_object_string_add(json_nexthop_global, "afi",
8751 "ipv4");
445c2480
DS
8752 json_object_boolean_true_add(json_nexthop_global,
8753 "used");
aef999a2
DA
8754 } else {
8755 if (nexthop_hostname)
8756 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8757 nexthop_hostname, vrf_id_str);
8758 else
8759 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8760 vrf_id_str);
8761
ae248832 8762 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8763 if (len < 1)
8764 vty_out(vty, "\n%*s", 36, " ");
8765 else
8766 vty_out(vty, "%*s", len, " ");
8767 }
d33fc23b 8768 } else if (safi == SAFI_FLOWSPEC) {
975a328e 8769 if (attr->nexthop.s_addr != INADDR_ANY) {
026b914a 8770 if (json_paths) {
23d0a753
DA
8771 char buf[BUFSIZ] = {0};
8772
026b914a 8773 json_nexthop_global = json_object_new_object();
515c2602 8774
026b914a
PG
8775 json_object_string_add(json_nexthop_global,
8776 "afi", "ipv4");
515c2602
DA
8777 json_object_string_add(
8778 json_nexthop_global, "ip",
23d0a753
DA
8779 inet_ntop(AF_INET, &attr->nexthop, buf,
8780 sizeof(buf)));
515c2602 8781
939a97f4 8782 if (path->peer->hostname)
515c2602
DA
8783 json_object_string_add(
8784 json_nexthop_global, "hostname",
939a97f4 8785 path->peer->hostname);
515c2602 8786
50e05855
AD
8787 json_object_boolean_true_add(
8788 json_nexthop_global,
026b914a
PG
8789 "used");
8790 } else {
aef999a2
DA
8791 if (nexthop_hostname)
8792 len = vty_out(vty, "%pI4(%s)%s",
8793 &attr->nexthop,
8794 nexthop_hostname,
8795 vrf_id_str);
8796 else
8797 len = vty_out(vty, "%pI4%s",
8798 &attr->nexthop,
8799 vrf_id_str);
8800
ae248832 8801 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8802 if (len < 1)
8803 vty_out(vty, "\n%*s", 36, " ");
8804 else
8805 vty_out(vty, "%*s", len, " ");
026b914a
PG
8806 }
8807 }
d33fc23b 8808 } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8809 if (json_paths) {
23d0a753
DA
8810 char buf[BUFSIZ] = {0};
8811
445c2480 8812 json_nexthop_global = json_object_new_object();
d62a17ae 8813
515c2602 8814 json_object_string_add(json_nexthop_global, "ip",
23d0a753
DA
8815 inet_ntop(AF_INET,
8816 &attr->nexthop, buf,
8817 sizeof(buf)));
515c2602 8818
939a97f4 8819 if (path->peer->hostname)
515c2602
DA
8820 json_object_string_add(json_nexthop_global,
8821 "hostname",
939a97f4 8822 path->peer->hostname);
445c2480 8823
a4d82a8a
PZ
8824 json_object_string_add(json_nexthop_global, "afi",
8825 "ipv4");
445c2480
DS
8826 json_object_boolean_true_add(json_nexthop_global,
8827 "used");
8828 } else {
aef999a2
DA
8829 if (nexthop_hostname)
8830 len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
8831 nexthop_hostname, vrf_id_str);
8832 else
8833 len = vty_out(vty, "%pI4%s", &attr->nexthop,
8834 vrf_id_str);
9df8b37c 8835
ae248832 8836 len = wide ? (41 - len) : (16 - len);
aef999a2
DA
8837 if (len < 1)
8838 vty_out(vty, "\n%*s", 36, " ");
8839 else
8840 vty_out(vty, "%*s", len, " ");
d62a17ae 8841 }
445c2480 8842 }
b05a1c8b 8843
445c2480 8844 /* IPv6 Next Hop */
a4d82a8a 8845 else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
445c2480 8846 char buf[BUFSIZ];
d62a17ae 8847
445c2480
DS
8848 if (json_paths) {
8849 json_nexthop_global = json_object_new_object();
a4d82a8a 8850 json_object_string_add(
515c2602
DA
8851 json_nexthop_global, "ip",
8852 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
8853 buf, BUFSIZ));
8854
939a97f4 8855 if (path->peer->hostname)
515c2602
DA
8856 json_object_string_add(json_nexthop_global,
8857 "hostname",
939a97f4 8858 path->peer->hostname);
515c2602 8859
a4d82a8a
PZ
8860 json_object_string_add(json_nexthop_global, "afi",
8861 "ipv6");
8862 json_object_string_add(json_nexthop_global, "scope",
8863 "global");
445c2480
DS
8864
8865 /* We display both LL & GL if both have been
8866 * received */
0606039c
DA
8867 if ((attr->mp_nexthop_len
8868 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
9b6d8fcf 8869 || (path->peer->conf_if)) {
a4d82a8a 8870 json_nexthop_ll = json_object_new_object();
d62a17ae 8871 json_object_string_add(
515c2602
DA
8872 json_nexthop_ll, "ip",
8873 inet_ntop(AF_INET6,
8874 &attr->mp_nexthop_local, buf,
8875 BUFSIZ));
8876
939a97f4 8877 if (path->peer->hostname)
515c2602
DA
8878 json_object_string_add(
8879 json_nexthop_ll, "hostname",
939a97f4 8880 path->peer->hostname);
515c2602 8881
a4d82a8a
PZ
8882 json_object_string_add(json_nexthop_ll, "afi",
8883 "ipv6");
8884 json_object_string_add(json_nexthop_ll, "scope",
445c2480 8885 "link-local");
d62a17ae 8886
a4d82a8a
PZ
8887 if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
8888 &attr->mp_nexthop_local)
445c2480
DS
8889 != 0)
8890 && !attr->mp_nexthop_prefer_global)
d62a17ae 8891 json_object_boolean_true_add(
a4d82a8a 8892 json_nexthop_ll, "used");
445c2480
DS
8893 else
8894 json_object_boolean_true_add(
a4d82a8a 8895 json_nexthop_global, "used");
445c2480
DS
8896 } else
8897 json_object_boolean_true_add(
8898 json_nexthop_global, "used");
8899 } else {
8900 /* Display LL if LL/Global both in table unless
8901 * prefer-global is set */
0606039c
DA
8902 if (((attr->mp_nexthop_len
8903 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
445c2480 8904 && !attr->mp_nexthop_prefer_global)
9b6d8fcf
DS
8905 || (path->peer->conf_if)) {
8906 if (path->peer->conf_if) {
a4d82a8a 8907 len = vty_out(vty, "%s",
9b6d8fcf 8908 path->peer->conf_if);
ae248832
MK
8909 /* len of IPv6 addr + max len of def
8910 * ifname */
8911 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8912
8913 if (len < 1)
a4d82a8a 8914 vty_out(vty, "\n%*s", 36, " ");
445c2480 8915 else
a4d82a8a 8916 vty_out(vty, "%*s", len, " ");
d62a17ae 8917 } else {
aef999a2
DA
8918 if (nexthop_hostname)
8919 len = vty_out(
8920 vty, "%pI6(%s)%s",
8921 &attr->mp_nexthop_local,
8922 nexthop_hostname,
8923 vrf_id_str);
8924 else
8925 len = vty_out(
8926 vty, "%pI6%s",
8927 &attr->mp_nexthop_local,
8928 vrf_id_str);
8929
ae248832 8930 len = wide ? (41 - len) : (16 - len);
d62a17ae 8931
8932 if (len < 1)
a4d82a8a 8933 vty_out(vty, "\n%*s", 36, " ");
d62a17ae 8934 else
a4d82a8a 8935 vty_out(vty, "%*s", len, " ");
d62a17ae 8936 }
445c2480 8937 } else {
aef999a2
DA
8938 if (nexthop_hostname)
8939 len = vty_out(vty, "%pI6(%s)%s",
8940 &attr->mp_nexthop_global,
8941 nexthop_hostname,
8942 vrf_id_str);
8943 else
8944 len = vty_out(vty, "%pI6%s",
8945 &attr->mp_nexthop_global,
8946 vrf_id_str);
8947
ae248832 8948 len = wide ? (41 - len) : (16 - len);
445c2480
DS
8949
8950 if (len < 1)
8951 vty_out(vty, "\n%*s", 36, " ");
8952 else
8953 vty_out(vty, "%*s", len, " ");
d62a17ae 8954 }
8955 }
445c2480 8956 }
718e3744 8957
445c2480
DS
8958 /* MED/Metric */
8959 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
0fbac0b4 8960 if (json_paths)
50e05855 8961 json_object_int_add(json_path, "metric", attr->med);
ae248832
MK
8962 else if (wide)
8963 vty_out(vty, "%7u", attr->med);
0fbac0b4 8964 else
445c2480 8965 vty_out(vty, "%10u", attr->med);
ae248832
MK
8966 else if (!json_paths) {
8967 if (wide)
8968 vty_out(vty, "%*s", 7, " ");
8969 else
8970 vty_out(vty, "%*s", 10, " ");
8971 }
d62a17ae 8972
445c2480
DS
8973 /* Local Pref */
8974 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
0fbac0b4 8975 if (json_paths)
50e05855 8976 json_object_int_add(json_path, "locPrf",
0fbac0b4
DA
8977 attr->local_pref);
8978 else
445c2480
DS
8979 vty_out(vty, "%7u", attr->local_pref);
8980 else if (!json_paths)
8981 vty_out(vty, " ");
d62a17ae 8982
445c2480
DS
8983 if (json_paths)
8984 json_object_int_add(json_path, "weight", attr->weight);
8985 else
8986 vty_out(vty, "%7u ", attr->weight);
47fc97cc 8987
445c2480
DS
8988 if (json_paths) {
8989 char buf[BUFSIZ];
a4d82a8a
PZ
8990 json_object_string_add(
8991 json_path, "peerId",
9b6d8fcf 8992 sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN));
445c2480 8993 }
b05a1c8b 8994
445c2480
DS
8995 /* Print aspath */
8996 if (attr->aspath) {
0fbac0b4 8997 if (json_paths)
50e05855 8998 json_object_string_add(json_path, "path",
0fbac0b4
DA
8999 attr->aspath->str);
9000 else
445c2480 9001 aspath_print_vty(vty, "%s", attr->aspath, " ");
d62a17ae 9002 }
f1aa5d8a 9003
445c2480
DS
9004 /* Print origin */
9005 if (json_paths)
a4d82a8a
PZ
9006 json_object_string_add(json_path, "origin",
9007 bgp_origin_long_str[attr->origin]);
445c2480
DS
9008 else
9009 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9010
9df8b37c 9011 if (json_paths) {
d071f237 9012 if (bgp_evpn_is_esi_valid(&attr->esi)) {
b5e140c8
AK
9013 json_object_string_add(json_path, "esi",
9014 esi_to_str(&attr->esi,
9015 esi_buf, sizeof(esi_buf)));
9016 }
6f214dd3
CS
9017 if (safi == SAFI_EVPN &&
9018 attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9019 json_ext_community = json_object_new_object();
9020 json_object_string_add(json_ext_community,
9021 "string",
9022 attr->ecommunity->str);
9023 json_object_object_add(json_path,
9024 "extendedCommunity",
9025 json_ext_community);
9026 }
9027
9df8b37c
PZ
9028 if (nexthop_self)
9029 json_object_boolean_true_add(json_path,
9030 "announceNexthopSelf");
9031 if (nexthop_othervrf) {
9032 json_object_string_add(json_path, "nhVrfName",
9033 nexthop_vrfname);
9034
9035 json_object_int_add(json_path, "nhVrfId",
9036 ((nexthop_vrfid == VRF_UNKNOWN)
9037 ? -1
9038 : (int)nexthop_vrfid));
9039 }
9040 }
9041
d62a17ae 9042 if (json_paths) {
9043 if (json_nexthop_global || json_nexthop_ll) {
9044 json_nexthops = json_object_new_array();
f1aa5d8a 9045
d62a17ae 9046 if (json_nexthop_global)
9047 json_object_array_add(json_nexthops,
9048 json_nexthop_global);
f1aa5d8a 9049
d62a17ae 9050 if (json_nexthop_ll)
9051 json_object_array_add(json_nexthops,
9052 json_nexthop_ll);
f1aa5d8a 9053
d62a17ae 9054 json_object_object_add(json_path, "nexthops",
9055 json_nexthops);
9056 }
9057
9058 json_object_array_add(json_paths, json_path);
9059 } else {
9060 vty_out(vty, "\n");
6f214dd3 9061
b5e140c8 9062 if (safi == SAFI_EVPN) {
d071f237 9063 if (bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 9064 /* XXX - add these params to the json out */
b5e140c8 9065 vty_out(vty, "%*s", 20, " ");
229587fb
AK
9066 vty_out(vty, "ESI:%s",
9067 esi_to_str(&attr->esi, esi_buf,
9068 sizeof(esi_buf)));
60605cbc 9069
229587fb 9070 vty_out(vty, "\n");
b5e140c8
AK
9071 }
9072 if (attr->flag &
9073 ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
9074 vty_out(vty, "%*s", 20, " ");
9075 vty_out(vty, "%s\n", attr->ecommunity->str);
9076 }
6f214dd3
CS
9077 }
9078
49e5a4a0 9079#ifdef ENABLE_BGP_VNC
d62a17ae 9080 /* prints an additional line, indented, with VNC info, if
9081 * present */
9082 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
9b6d8fcf 9083 rfapi_vty_out_vncinfo(vty, p, path, safi);
65efcfce 9084#endif
d62a17ae 9085 }
9086}
718e3744 9087
9088/* called from terminal list command */
7d3cae70
DA
9089void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
9090 const struct prefix *p, struct attr *attr, safi_t safi,
9091 bool use_json, json_object *json_ar, bool wide)
d62a17ae 9092{
9093 json_object *json_status = NULL;
9094 json_object *json_net = NULL;
aef999a2 9095 int len;
d62a17ae 9096 char buff[BUFSIZ];
dc387b0f 9097
d62a17ae 9098 /* Route status display. */
9099 if (use_json) {
9100 json_status = json_object_new_object();
9101 json_net = json_object_new_object();
9102 } else {
9103 vty_out(vty, "*");
9104 vty_out(vty, ">");
9105 vty_out(vty, " ");
9106 }
718e3744 9107
d62a17ae 9108 /* print prefix and mask */
50e05855 9109 if (use_json) {
dc387b0f
LK
9110 if (safi == SAFI_EVPN)
9111 bgp_evpn_route2json((struct prefix_evpn *)p, json_net);
9112 else if (p->family == AF_INET || p->family == AF_INET6) {
9113 json_object_string_add(
9114 json_net, "addrPrefix",
9115 inet_ntop(p->family, &p->u.prefix, buff,
9116 BUFSIZ));
9117 json_object_int_add(json_net, "prefixLen",
9118 p->prefixlen);
9119 prefix2str(p, buff, PREFIX_STRLEN);
9120 json_object_string_add(json_net, "network", buff);
9121 }
50e05855 9122 } else
7d3cae70 9123 route_vty_out_route(dest, p, vty, NULL, wide);
d62a17ae 9124
9125 /* Print attribute */
9126 if (attr) {
9127 if (use_json) {
23d0a753
DA
9128 char buf[BUFSIZ] = {0};
9129
d62a17ae 9130 if (p->family == AF_INET
9131 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
d62a17ae 9132 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
dc387b0f 9133 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
d62a17ae 9134 json_object_string_add(
9135 json_net, "nextHop",
23d0a753
DA
9136 inet_ntop(
9137 AF_INET,
9138 &attr->mp_nexthop_global_in,
9139 buf, sizeof(buf)));
d62a17ae 9140 else
9141 json_object_string_add(
9142 json_net, "nextHop",
23d0a753
DA
9143 inet_ntop(AF_INET,
9144 &attr->nexthop, buf,
9145 sizeof(buf)));
d62a17ae 9146 } else if (p->family == AF_INET6
9147 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9148 char buf[BUFSIZ];
9149
9150 json_object_string_add(
aa0a10fc 9151 json_net, "nextHopGlobal",
d62a17ae 9152 inet_ntop(AF_INET6,
9153 &attr->mp_nexthop_global, buf,
9154 BUFSIZ));
23d0a753
DA
9155 } else if (p->family == AF_EVPN
9156 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
9157 char buf[BUFSIZ] = {0};
9158
9159 json_object_string_add(
9160 json_net, "nextHop",
9161 inet_ntop(AF_INET,
9162 &attr->mp_nexthop_global_in,
9163 buf, sizeof(buf)));
9164 }
d62a17ae 9165
9166 if (attr->flag
9167 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
9168 json_object_int_add(json_net, "metric",
9169 attr->med);
9170
0fbac0b4 9171 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
50e05855 9172 json_object_int_add(json_net, "locPrf",
0fbac0b4 9173 attr->local_pref);
d62a17ae 9174
9175 json_object_int_add(json_net, "weight", attr->weight);
9176
9177 /* Print aspath */
0fbac0b4 9178 if (attr->aspath)
50e05855 9179 json_object_string_add(json_net, "path",
0fbac0b4 9180 attr->aspath->str);
d62a17ae 9181
9182 /* Print origin */
9183 json_object_string_add(json_net, "bgpOriginCode",
9184 bgp_origin_str[attr->origin]);
9185 } else {
9186 if (p->family == AF_INET
9187 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9188 || safi == SAFI_EVPN
9189 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9190 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9191 || safi == SAFI_EVPN)
23d0a753
DA
9192 vty_out(vty, "%-16pI4",
9193 &attr->mp_nexthop_global_in);
ae248832 9194 else if (wide)
23d0a753 9195 vty_out(vty, "%-41pI4", &attr->nexthop);
d62a17ae 9196 else
23d0a753 9197 vty_out(vty, "%-16pI4", &attr->nexthop);
d62a17ae 9198 } else if (p->family == AF_INET6
9199 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
d62a17ae 9200 char buf[BUFSIZ];
9201
9202 len = vty_out(
9203 vty, "%s",
9204 inet_ntop(AF_INET6,
9205 &attr->mp_nexthop_global, buf,
9206 BUFSIZ));
ae248832 9207 len = wide ? (41 - len) : (16 - len);
d62a17ae 9208 if (len < 1)
9209 vty_out(vty, "\n%*s", 36, " ");
9210 else
9211 vty_out(vty, "%*s", len, " ");
9212 }
9213 if (attr->flag
9214 & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
ae248832
MK
9215 if (wide)
9216 vty_out(vty, "%7u", attr->med);
9217 else
9218 vty_out(vty, "%10u", attr->med);
9219 else if (wide)
9220 vty_out(vty, " ");
d62a17ae 9221 else
9222 vty_out(vty, " ");
718e3744 9223
d62a17ae 9224 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
9225 vty_out(vty, "%7u", attr->local_pref);
9226 else
9227 vty_out(vty, " ");
9228
9229 vty_out(vty, "%7u ", attr->weight);
9230
9231 /* Print aspath */
9232 if (attr->aspath)
9233 aspath_print_vty(vty, "%s", attr->aspath, " ");
9234
9235 /* Print origin */
9236 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9237 }
9238 }
9239 if (use_json) {
9240 json_object_boolean_true_add(json_status, "*");
9241 json_object_boolean_true_add(json_status, ">");
9242 json_object_object_add(json_net, "appliedStatusSymbols",
9243 json_status);
1608ff77 9244
dc387b0f
LK
9245 prefix2str(p, buff, PREFIX_STRLEN);
9246 json_object_object_add(json_ar, buff, json_net);
d62a17ae 9247 } else
9248 vty_out(vty, "\n");
9249}
9250
bd494ec5 9251void route_vty_out_tag(struct vty *vty, const struct prefix *p,
9b6d8fcf 9252 struct bgp_path_info *path, int display, safi_t safi,
d62a17ae 9253 json_object *json)
9254{
9255 json_object *json_out = NULL;
9256 struct attr *attr;
9257 mpls_label_t label = MPLS_INVALID_LABEL;
9258
9b6d8fcf 9259 if (!path->extra)
d62a17ae 9260 return;
9261
9262 if (json)
9263 json_out = json_object_new_object();
9264
9265 /* short status lead text */
82c298be 9266 route_vty_short_status_out(vty, path, p, json_out);
d62a17ae 9267
9268 /* print prefix and mask */
9269 if (json == NULL) {
9270 if (!display)
7d3cae70 9271 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9272 else
9273 vty_out(vty, "%*s", 17, " ");
9274 }
9275
9276 /* Print attribute */
9b6d8fcf 9277 attr = path->attr;
05864da7
DS
9278 if (((p->family == AF_INET)
9279 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9280 || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9281 || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9282 char buf[BUFSIZ] = {0};
9283
05864da7
DS
9284 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9285 || safi == SAFI_EVPN) {
9286 if (json)
9287 json_object_string_add(
9288 json_out, "mpNexthopGlobalIn",
23d0a753
DA
9289 inet_ntop(AF_INET,
9290 &attr->mp_nexthop_global_in,
9291 buf, sizeof(buf)));
05864da7 9292 else
23d0a753
DA
9293 vty_out(vty, "%-16pI4",
9294 &attr->mp_nexthop_global_in);
05864da7
DS
9295 } else {
9296 if (json)
9297 json_object_string_add(
9298 json_out, "nexthop",
23d0a753
DA
9299 inet_ntop(AF_INET, &attr->nexthop, buf,
9300 sizeof(buf)));
05864da7 9301 else
23d0a753 9302 vty_out(vty, "%-16pI4", &attr->nexthop);
05864da7
DS
9303 }
9304 } else if (((p->family == AF_INET6)
9305 && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
9306 || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
9307 || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
9308 char buf_a[512];
9309
9310 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
9311 if (json)
9312 json_object_string_add(
9313 json_out, "mpNexthopGlobalIn",
9314 inet_ntop(AF_INET6,
9315 &attr->mp_nexthop_global,
9316 buf_a, sizeof(buf_a)));
9317 else
9318 vty_out(vty, "%s",
9319 inet_ntop(AF_INET6,
9320 &attr->mp_nexthop_global,
9321 buf_a, sizeof(buf_a)));
9322 } else if (attr->mp_nexthop_len
9323 == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
9324 snprintfrr(buf_a, sizeof(buf_a), "%pI6(%pI6)",
9325 &attr->mp_nexthop_global,
9326 &attr->mp_nexthop_local);
9327 if (json)
9328 json_object_string_add(json_out,
9329 "mpNexthopGlobalLocal",
9330 buf_a);
9331 else
9332 vty_out(vty, "%s", buf_a);
d62a17ae 9333 }
9334 }
9335
9b6d8fcf 9336 label = decode_label(&path->extra->label[0]);
d62a17ae 9337
9338 if (bgp_is_valid_label(&label)) {
9339 if (json) {
9340 json_object_int_add(json_out, "notag", label);
9341 json_object_array_add(json, json_out);
9342 } else {
9343 vty_out(vty, "notag/%d", label);
9344 vty_out(vty, "\n");
9345 }
700ddfed
PG
9346 } else if (!json)
9347 vty_out(vty, "\n");
d62a17ae 9348}
718e3744 9349
bd494ec5 9350void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
9b6d8fcf 9351 struct bgp_path_info *path, int display,
d62a17ae 9352 json_object *json_paths)
718e3744 9353{
d62a17ae 9354 struct attr *attr;
14f51eba 9355 char buf[BUFSIZ] = {0};
d62a17ae 9356 json_object *json_path = NULL;
14f51eba
LK
9357 json_object *json_nexthop = NULL;
9358 json_object *json_overlay = NULL;
856ca177 9359
9b6d8fcf 9360 if (!path->extra)
d62a17ae 9361 return;
718e3744 9362
14f51eba
LK
9363 if (json_paths) {
9364 json_path = json_object_new_object();
9365 json_overlay = json_object_new_object();
9366 json_nexthop = json_object_new_object();
9367 }
9368
d62a17ae 9369 /* short status lead text */
82c298be 9370 route_vty_short_status_out(vty, path, p, json_path);
856ca177 9371
d62a17ae 9372 /* print prefix and mask */
9373 if (!display)
7d3cae70 9374 route_vty_out_route(path->net, p, vty, json_path, false);
d62a17ae 9375 else
9376 vty_out(vty, "%*s", 17, " ");
9377
9378 /* Print attribute */
9b6d8fcf 9379 attr = path->attr;
05864da7
DS
9380 char buf1[BUFSIZ];
9381 int af = NEXTHOP_FAMILY(attr->mp_nexthop_len);
d62a17ae 9382
05864da7
DS
9383 switch (af) {
9384 case AF_INET:
9385 inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ);
9386 if (!json_path) {
9387 vty_out(vty, "%-16s", buf);
9388 } else {
9389 json_object_string_add(json_nexthop, "ip", buf);
14f51eba 9390
05864da7 9391 json_object_string_add(json_nexthop, "afi", "ipv4");
14f51eba 9392
05864da7
DS
9393 json_object_object_add(json_path, "nexthop",
9394 json_nexthop);
9395 }
9396 break;
9397 case AF_INET6:
9398 inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ);
9399 inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ);
9400 if (!json_path) {
9401 vty_out(vty, "%s(%s)", buf, buf1);
9402 } else {
9403 json_object_string_add(json_nexthop, "ipv6Global", buf);
14f51eba 9404
05864da7
DS
9405 json_object_string_add(json_nexthop, "ipv6LinkLocal",
9406 buf1);
14f51eba 9407
05864da7 9408 json_object_string_add(json_nexthop, "afi", "ipv6");
14f51eba 9409
05864da7
DS
9410 json_object_object_add(json_path, "nexthop",
9411 json_nexthop);
9412 }
9413 break;
9414 default:
9415 if (!json_path) {
9416 vty_out(vty, "?");
9417 } else {
9418 json_object_string_add(json_nexthop, "Error",
9419 "Unsupported address-family");
d62a17ae 9420 }
05864da7 9421 }
988258b4 9422
6c924775
DS
9423 const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
9424
9425 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
9426 inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
9427 else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
9428 inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
14f51eba 9429
05864da7
DS
9430 if (!json_path)
9431 vty_out(vty, "/%s", buf);
9432 else
9433 json_object_string_add(json_overlay, "gw", buf);
9434
9435 if (attr->ecommunity) {
9436 char *mac = NULL;
9437 struct ecommunity_val *routermac = ecommunity_lookup(
9438 attr->ecommunity, ECOMMUNITY_ENCODE_EVPN,
9439 ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC);
9440
9441 if (routermac)
9442 mac = ecom_mac2str((char *)routermac->val);
9443 if (mac) {
9444 if (!json_path) {
c4efd0f4 9445 vty_out(vty, "/%s", mac);
05864da7
DS
9446 } else {
9447 json_object_string_add(json_overlay, "rmac",
9448 mac);
988258b4 9449 }
05864da7 9450 XFREE(MTYPE_TMP, mac);
988258b4 9451 }
05864da7 9452 }
718e3744 9453
05864da7
DS
9454 if (!json_path) {
9455 vty_out(vty, "\n");
9456 } else {
9457 json_object_object_add(json_path, "overlay", json_overlay);
14f51eba 9458
05864da7 9459 json_object_array_add(json_paths, json_path);
14f51eba 9460 }
d62a17ae 9461}
718e3744 9462
d62a17ae 9463/* dampening route */
5f040085
DS
9464static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
9465 struct bgp_path_info *path, int display,
9466 afi_t afi, safi_t safi, bool use_json,
e5be8c1d 9467 json_object *json_paths)
d62a17ae 9468{
e5be8c1d 9469 struct attr *attr = path->attr;
d62a17ae 9470 int len;
9471 char timebuf[BGP_UPTIME_LEN];
e5be8c1d
DA
9472 json_object *json_path = NULL;
9473
9474 if (use_json)
9475 json_path = json_object_new_object();
d62a17ae 9476
9477 /* short status lead text */
e5be8c1d 9478 route_vty_short_status_out(vty, path, p, json_path);
d62a17ae 9479
9480 /* print prefix and mask */
9481 if (!use_json) {
9482 if (!display)
7d3cae70 9483 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9484 else
9485 vty_out(vty, "%*s", 17, " ");
d62a17ae 9486
e5be8c1d
DA
9487 len = vty_out(vty, "%s", path->peer->host);
9488 len = 17 - len;
9489
9490 if (len < 1)
d62a17ae 9491 vty_out(vty, "\n%*s", 34, " ");
d62a17ae 9492 else
9493 vty_out(vty, "%*s", len, " ");
d62a17ae 9494
9b6d8fcf
DS
9495 vty_out(vty, "%s ",
9496 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9497 BGP_UPTIME_LEN, afi, safi,
e5be8c1d 9498 use_json, NULL));
d62a17ae 9499
e5be8c1d 9500 if (attr->aspath)
05864da7 9501 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9502
05864da7
DS
9503 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9504
d62a17ae 9505 vty_out(vty, "\n");
e5be8c1d
DA
9506 } else {
9507 bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, afi,
9508 safi, use_json, json_path);
9509
9510 if (attr->aspath)
9511 json_object_string_add(json_path, "asPath",
9512 attr->aspath->str);
9513
9514 json_object_string_add(json_path, "origin",
9515 bgp_origin_str[attr->origin]);
9516 json_object_string_add(json_path, "peerHost", path->peer->host);
9517
9518 json_object_array_add(json_paths, json_path);
9519 }
d62a17ae 9520}
718e3744 9521
d62a17ae 9522/* flap route */
5f040085
DS
9523static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
9524 struct bgp_path_info *path, int display,
9525 afi_t afi, safi_t safi, bool use_json,
31258046 9526 json_object *json_paths)
784d3a42 9527{
31258046 9528 struct attr *attr = path->attr;
d62a17ae 9529 struct bgp_damp_info *bdi;
9530 char timebuf[BGP_UPTIME_LEN];
9531 int len;
31258046 9532 json_object *json_path = NULL;
784d3a42 9533
9b6d8fcf 9534 if (!path->extra)
d62a17ae 9535 return;
784d3a42 9536
31258046
DA
9537 if (use_json)
9538 json_path = json_object_new_object();
9539
9b6d8fcf 9540 bdi = path->extra->damp_info;
784d3a42 9541
d62a17ae 9542 /* short status lead text */
31258046 9543 route_vty_short_status_out(vty, path, p, json_path);
784d3a42 9544
d62a17ae 9545 if (!use_json) {
9546 if (!display)
7d3cae70 9547 route_vty_out_route(path->net, p, vty, NULL, false);
d62a17ae 9548 else
9549 vty_out(vty, "%*s", 17, " ");
784d3a42 9550
31258046
DA
9551 len = vty_out(vty, "%s", path->peer->host);
9552 len = 16 - len;
9553 if (len < 1)
d62a17ae 9554 vty_out(vty, "\n%*s", 33, " ");
d62a17ae 9555 else
9556 vty_out(vty, "%*s", len, " ");
784d3a42 9557
31258046
DA
9558 len = vty_out(vty, "%d", bdi->flap);
9559 len = 5 - len;
9560 if (len < 1)
d62a17ae 9561 vty_out(vty, " ");
d62a17ae 9562 else
9563 vty_out(vty, "%*s", len, " ");
d62a17ae 9564
996c9314
LB
9565 vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf,
9566 BGP_UPTIME_LEN, 0, NULL));
d62a17ae 9567
31258046
DA
9568 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9569 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
d62a17ae 9570 vty_out(vty, "%s ",
9b6d8fcf 9571 bgp_damp_reuse_time_vty(vty, path, timebuf,
a935f597 9572 BGP_UPTIME_LEN, afi,
31258046
DA
9573 safi, use_json, NULL));
9574 else
d62a17ae 9575 vty_out(vty, "%*s ", 8, " ");
d62a17ae 9576
31258046 9577 if (attr->aspath)
05864da7 9578 aspath_print_vty(vty, "%s", attr->aspath, " ");
05864da7 9579
05864da7
DS
9580 vty_out(vty, "%s", bgp_origin_str[attr->origin]);
9581
d62a17ae 9582 vty_out(vty, "\n");
31258046
DA
9583 } else {
9584 json_object_string_add(json_path, "peerHost", path->peer->host);
9585 json_object_int_add(json_path, "bdiFlap", bdi->flap);
9586
9587 peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, use_json,
9588 json_path);
9589
9590 if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
9591 && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
9592 bgp_damp_reuse_time_vty(vty, path, timebuf,
9593 BGP_UPTIME_LEN, afi, safi,
9594 use_json, json_path);
9595
9596 if (attr->aspath)
9597 json_object_string_add(json_path, "asPath",
9598 attr->aspath->str);
9599
9600 json_object_string_add(json_path, "origin",
9601 bgp_origin_str[attr->origin]);
9602
9603 json_object_array_add(json_paths, json_path);
9604 }
d62a17ae 9605}
9606
9607static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
9608 int *first, const char *header,
9609 json_object *json_adv_to)
9610{
9611 char buf1[INET6_ADDRSTRLEN];
9612 json_object *json_peer = NULL;
9613
9614 if (json_adv_to) {
9615 /* 'advertised-to' is a dictionary of peers we have advertised
9616 * this
9617 * prefix too. The key is the peer's IP or swpX, the value is
9618 * the
9619 * hostname if we know it and "" if not.
9620 */
9621 json_peer = json_object_new_object();
9622
9623 if (peer->hostname)
9624 json_object_string_add(json_peer, "hostname",
9625 peer->hostname);
9626
9627 if (peer->conf_if)
9628 json_object_object_add(json_adv_to, peer->conf_if,
9629 json_peer);
9630 else
9631 json_object_object_add(
9632 json_adv_to,
9633 sockunion2str(&peer->su, buf1, SU_ADDRSTRLEN),
9634 json_peer);
9635 } else {
9636 if (*first) {
9637 vty_out(vty, "%s", header);
9638 *first = 0;
9639 }
9640
9641 if (peer->hostname
892fedb6 9642 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 9643 if (peer->conf_if)
9644 vty_out(vty, " %s(%s)", peer->hostname,
9645 peer->conf_if);
9646 else
9647 vty_out(vty, " %s(%s)", peer->hostname,
9648 sockunion2str(&peer->su, buf1,
9649 SU_ADDRSTRLEN));
9650 } else {
9651 if (peer->conf_if)
9652 vty_out(vty, " %s", peer->conf_if);
9653 else
9654 vty_out(vty, " %s",
9655 sockunion2str(&peer->su, buf1,
9656 SU_ADDRSTRLEN));
9657 }
9658 }
784d3a42
PG
9659}
9660
dcc68b5e
MS
9661static void route_vty_out_tx_ids(struct vty *vty,
9662 struct bgp_addpath_info_data *d)
9663{
9664 int i;
9665
9666 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
9667 vty_out(vty, "TX-%s %u%s", bgp_addpath_names(i)->human_name,
9668 d->addpath_tx_id[i],
9669 i < BGP_ADDPATH_MAX - 1 ? " " : "\n");
9670 }
9671}
9672
5e4d4c8a 9673static void route_vty_out_detail_es_info(struct vty *vty,
229587fb
AK
9674 struct bgp_path_info *pi,
9675 struct attr *attr,
9676 json_object *json_path)
5e4d4c8a
AK
9677{
9678 char esi_buf[ESI_STR_LEN];
9679 bool es_local = !!CHECK_FLAG(attr->es_flags, ATTR_ES_IS_LOCAL);
9680 bool peer_router = !!CHECK_FLAG(attr->es_flags,
9681 ATTR_ES_PEER_ROUTER);
9682 bool peer_active = !!CHECK_FLAG(attr->es_flags,
9683 ATTR_ES_PEER_ACTIVE);
9684 bool peer_proxy = !!CHECK_FLAG(attr->es_flags,
9685 ATTR_ES_PEER_PROXY);
5e4d4c8a
AK
9686 esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf));
9687 if (json_path) {
9688 json_object *json_es_info = NULL;
9689
9690 json_object_string_add(
9691 json_path, "esi",
9692 esi_buf);
9693 if (es_local || bgp_evpn_attr_is_sync(attr)) {
9694 json_es_info = json_object_new_object();
9695 if (es_local)
9696 json_object_boolean_true_add(
9697 json_es_info, "localEs");
9698 if (peer_active)
9699 json_object_boolean_true_add(
9700 json_es_info, "peerActive");
9701 if (peer_proxy)
9702 json_object_boolean_true_add(
9703 json_es_info, "peerProxy");
9704 if (peer_router)
9705 json_object_boolean_true_add(
9706 json_es_info, "peerRouter");
9707 if (attr->mm_sync_seqnum)
9708 json_object_int_add(
9709 json_es_info, "peerSeq",
9710 attr->mm_sync_seqnum);
9711 json_object_object_add(
9712 json_path, "es_info",
9713 json_es_info);
9714 }
9715 } else {
9716 if (bgp_evpn_attr_is_sync(attr))
9717 vty_out(vty,
9718 " ESI %s %s peer-info: (%s%s%sMM: %d)\n",
9719 esi_buf,
9720 es_local ? "local-es":"",
9721 peer_proxy ? "proxy " : "",
9722 peer_active ? "active ":"",
9723 peer_router ? "router ":"",
9724 attr->mm_sync_seqnum);
9725 else
9726 vty_out(vty, " ESI %s %s\n",
9727 esi_buf,
9728 es_local ? "local-es":"");
9729 }
9730}
9731
4933eaaf
DS
9732void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
9733 struct bgp_path_info *path, afi_t afi, safi_t safi,
4027d19b
DS
9734 enum rpki_states rpki_curr_state,
9735 json_object *json_paths)
d62a17ae 9736{
9737 char buf[INET6_ADDRSTRLEN];
9738 char buf1[BUFSIZ];
515c2602 9739 struct attr *attr = path->attr;
d62a17ae 9740 int sockunion_vty_out(struct vty *, union sockunion *);
9741 time_t tbuf;
9742 json_object *json_bestpath = NULL;
9743 json_object *json_cluster_list = NULL;
9744 json_object *json_cluster_list_list = NULL;
9745 json_object *json_ext_community = NULL;
9746 json_object *json_last_update = NULL;
7fd077aa 9747 json_object *json_pmsi = NULL;
d62a17ae 9748 json_object *json_nexthop_global = NULL;
9749 json_object *json_nexthop_ll = NULL;
9750 json_object *json_nexthops = NULL;
9751 json_object *json_path = NULL;
9752 json_object *json_peer = NULL;
9753 json_object *json_string = NULL;
9754 json_object *json_adv_to = NULL;
9755 int first = 0;
9756 struct listnode *node, *nnode;
9757 struct peer *peer;
9758 int addpath_capable;
9759 int has_adj;
9760 unsigned int first_as;
1defdda8 9761 bool nexthop_self =
9b6d8fcf 9762 CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
dcc68b5e 9763 int i;
2ba93fd6
DA
9764 char *nexthop_hostname =
9765 bgp_nexthop_hostname(path->peer, path->nexthop);
d62a17ae 9766
9767 if (json_paths) {
9768 json_path = json_object_new_object();
9769 json_peer = json_object_new_object();
9770 json_nexthop_global = json_object_new_object();
9771 }
9772
8304dabf
AD
9773 if (safi == SAFI_EVPN) {
9774 if (!json_paths)
9775 vty_out(vty, " Route %pRN", bn);
9776 }
9777
44c69747 9778 if (path->extra) {
b57ba6d2 9779 char tag_buf[30];
d62a17ae 9780
d62a17ae 9781 tag_buf[0] = '\0';
9b6d8fcf
DS
9782 if (path->extra && path->extra->num_labels) {
9783 bgp_evpn_label2str(path->extra->label,
9784 path->extra->num_labels, tag_buf,
a4d82a8a 9785 sizeof(tag_buf));
d62a17ae 9786 }
d7325ee7 9787 if (safi == SAFI_EVPN) {
44c69747 9788 if (!json_paths) {
44c69747
LK
9789 if (tag_buf[0] != '\0')
9790 vty_out(vty, " VNI %s", tag_buf);
44c69747
LK
9791 } else {
9792 if (tag_buf[0])
9793 json_object_string_add(json_path, "VNI",
9794 tag_buf);
9795 }
d7325ee7
DD
9796 }
9797
44c69747 9798 if (path->extra && path->extra->parent && !json_paths) {
4b7e6066 9799 struct bgp_path_info *parent_ri;
9bcb3eef 9800 struct bgp_dest *dest, *pdest;
d62a17ae 9801
9b6d8fcf 9802 parent_ri = (struct bgp_path_info *)path->extra->parent;
9bcb3eef
DS
9803 dest = parent_ri->net;
9804 if (dest && dest->pdest) {
9805 pdest = dest->pdest;
9806 prefix_rd2str(
9807 (struct prefix_rd *)bgp_dest_get_prefix(
9808 pdest),
9809 buf1, sizeof(buf1));
d7325ee7 9810 if (is_pi_family_evpn(parent_ri)) {
2dbe669b 9811 vty_out(vty,
58bff4d1 9812 " Imported from %s:%pFX, VNI %s",
2dbe669b
DA
9813 buf1,
9814 (struct prefix_evpn *)
9815 bgp_dest_get_prefix(
9816 dest),
9817 tag_buf);
58bff4d1
AK
9818 if (attr->es_flags & ATTR_ES_L3_NHG)
9819 vty_out(vty, ", L3NHG %s",
9820 (attr->es_flags
9821 & ATTR_ES_L3_NHG_ACTIVE)
9822 ? "active"
9823 : "inactive");
9824 vty_out(vty, "\n");
9825
d7325ee7 9826 } else
2dbe669b
DA
9827 vty_out(vty,
9828 " Imported from %s:%pFX\n",
9829 buf1,
9830 (struct prefix_evpn *)
9831 bgp_dest_get_prefix(
9832 dest));
d62a17ae 9833 }
9834 }
9835 }
d62a17ae 9836
8304dabf
AD
9837 if (safi == SAFI_EVPN
9838 && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) {
9839 char gwip_buf[INET6_ADDRSTRLEN];
9840
9841 if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)&bn->p))
9842 inet_ntop(AF_INET, &attr->evpn_overlay.gw_ip.ipv4,
9843 gwip_buf, sizeof(gwip_buf));
9844 else
9845 inet_ntop(AF_INET6, &attr->evpn_overlay.gw_ip.ipv6,
9846 gwip_buf, sizeof(gwip_buf));
9847
9848 if (json_paths)
9849 json_object_string_add(json_path, "gatewayIP",
9850 gwip_buf);
9851 else
9852 vty_out(vty, " Gateway IP %s", gwip_buf);
9853 }
9854
9855 if (safi == SAFI_EVPN)
9856 vty_out(vty, "\n");
9857
05864da7
DS
9858 /* Line1 display AS-path, Aggregator */
9859 if (attr->aspath) {
9860 if (json_paths) {
9861 if (!attr->aspath->json)
9862 aspath_str_update(attr->aspath, true);
9863 json_object_lock(attr->aspath->json);
9864 json_object_object_add(json_path, "aspath",
9865 attr->aspath->json);
9866 } else {
9867 if (attr->aspath->segments)
9868 aspath_print_vty(vty, " %s", attr->aspath, "");
d62a17ae 9869 else
05864da7 9870 vty_out(vty, " Local");
d62a17ae 9871 }
05864da7 9872 }
d62a17ae 9873
05864da7
DS
9874 if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) {
9875 if (json_paths)
9876 json_object_boolean_true_add(json_path, "removed");
9877 else
9878 vty_out(vty, ", (removed)");
9879 }
d62a17ae 9880
05864da7
DS
9881 if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) {
9882 if (json_paths)
9883 json_object_boolean_true_add(json_path, "stale");
9884 else
9885 vty_out(vty, ", (stale)");
9886 }
d62a17ae 9887
05864da7
DS
9888 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
9889 if (json_paths) {
23d0a753
DA
9890 char buf[BUFSIZ] = {0};
9891
05864da7
DS
9892 json_object_int_add(json_path, "aggregatorAs",
9893 attr->aggregator_as);
23d0a753
DA
9894 json_object_string_add(json_path, "aggregatorId",
9895 inet_ntop(AF_INET,
9896 &attr->aggregator_addr,
9897 buf, sizeof(buf)));
05864da7 9898 } else {
88d495a9
DA
9899 vty_out(vty, ", (aggregated by %u %pI4)",
9900 attr->aggregator_as, &attr->aggregator_addr);
d62a17ae 9901 }
05864da7 9902 }
d62a17ae 9903
05864da7
DS
9904 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9905 PEER_FLAG_REFLECTOR_CLIENT)) {
9906 if (json_paths)
9907 json_object_boolean_true_add(json_path,
9908 "rxedFromRrClient");
9909 else
9910 vty_out(vty, ", (Received from a RR-client)");
9911 }
d62a17ae 9912
05864da7
DS
9913 if (CHECK_FLAG(path->peer->af_flags[afi][safi],
9914 PEER_FLAG_RSERVER_CLIENT)) {
9915 if (json_paths)
9916 json_object_boolean_true_add(json_path,
9917 "rxedFromRsClient");
9918 else
9919 vty_out(vty, ", (Received from a RS-client)");
9920 }
d62a17ae 9921
05864da7
DS
9922 if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
9923 if (json_paths)
9924 json_object_boolean_true_add(json_path,
9925 "dampeningHistoryEntry");
9926 else
9927 vty_out(vty, ", (history entry)");
9928 } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) {
9929 if (json_paths)
9930 json_object_boolean_true_add(json_path,
9931 "dampeningSuppressed");
9932 else
9933 vty_out(vty, ", (suppressed due to dampening)");
9934 }
d62a17ae 9935
05864da7
DS
9936 if (!json_paths)
9937 vty_out(vty, "\n");
d62a17ae 9938
05864da7
DS
9939 /* Line2 display Next-hop, Neighbor, Router-id */
9940 /* Display the nexthop */
9bcb3eef 9941 const struct prefix *bn_p = bgp_dest_get_prefix(bn);
b54892e0
DS
9942
9943 if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
9944 || bn_p->family == AF_EVPN)
05864da7
DS
9945 && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
9946 || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
23d0a753
DA
9947 char buf[BUFSIZ] = {0};
9948
05864da7
DS
9949 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
9950 || safi == SAFI_EVPN) {
515c2602 9951 if (json_paths) {
d62a17ae 9952 json_object_string_add(
515c2602 9953 json_nexthop_global, "ip",
23d0a753
DA
9954 inet_ntop(AF_INET,
9955 &attr->mp_nexthop_global_in,
9956 buf, sizeof(buf)));
515c2602 9957
939a97f4 9958 if (path->peer->hostname)
515c2602
DA
9959 json_object_string_add(
9960 json_nexthop_global, "hostname",
939a97f4 9961 path->peer->hostname);
aef999a2
DA
9962 } else {
9963 if (nexthop_hostname)
9964 vty_out(vty, " %pI4(%s)",
9965 &attr->mp_nexthop_global_in,
9966 nexthop_hostname);
9967 else
9968 vty_out(vty, " %pI4",
9969 &attr->mp_nexthop_global_in);
9970 }
d62a17ae 9971 } else {
515c2602 9972 if (json_paths) {
05864da7 9973 json_object_string_add(
515c2602 9974 json_nexthop_global, "ip",
23d0a753
DA
9975 inet_ntop(AF_INET, &attr->nexthop, buf,
9976 sizeof(buf)));
515c2602 9977
939a97f4 9978 if (path->peer->hostname)
515c2602
DA
9979 json_object_string_add(
9980 json_nexthop_global, "hostname",
939a97f4 9981 path->peer->hostname);
aef999a2
DA
9982 } else {
9983 if (nexthop_hostname)
9984 vty_out(vty, " %pI4(%s)",
9985 &attr->nexthop,
9986 nexthop_hostname);
9987 else
9988 vty_out(vty, " %pI4",
9989 &attr->nexthop);
9990 }
d62a17ae 9991 }
9992
05864da7
DS
9993 if (json_paths)
9994 json_object_string_add(json_nexthop_global, "afi",
9995 "ipv4");
9996 } else {
9997 if (json_paths) {
9998 json_object_string_add(
515c2602
DA
9999 json_nexthop_global, "ip",
10000 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
10001 buf, INET6_ADDRSTRLEN));
10002
939a97f4 10003 if (path->peer->hostname)
515c2602
DA
10004 json_object_string_add(json_nexthop_global,
10005 "hostname",
939a97f4 10006 path->peer->hostname);
515c2602 10007
05864da7
DS
10008 json_object_string_add(json_nexthop_global, "afi",
10009 "ipv6");
10010 json_object_string_add(json_nexthop_global, "scope",
10011 "global");
10012 } else {
aef999a2
DA
10013 if (nexthop_hostname)
10014 vty_out(vty, " %pI6(%s)",
10015 &attr->mp_nexthop_global,
10016 nexthop_hostname);
10017 else
10018 vty_out(vty, " %pI6",
10019 &attr->mp_nexthop_global);
d62a17ae 10020 }
05864da7 10021 }
d62a17ae 10022
05864da7
DS
10023 /* Display the IGP cost or 'inaccessible' */
10024 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10025 if (json_paths)
10026 json_object_boolean_false_add(json_nexthop_global,
10027 "accessible");
10028 else
10029 vty_out(vty, " (inaccessible)");
10030 } else {
10031 if (path->extra && path->extra->igpmetric) {
d62a17ae 10032 if (json_paths)
05864da7
DS
10033 json_object_int_add(json_nexthop_global,
10034 "metric",
10035 path->extra->igpmetric);
d62a17ae 10036 else
05864da7
DS
10037 vty_out(vty, " (metric %u)",
10038 path->extra->igpmetric);
d62a17ae 10039 }
10040
05864da7 10041 /* IGP cost is 0, display this only for json */
d62a17ae 10042 else {
d62a17ae 10043 if (json_paths)
05864da7
DS
10044 json_object_int_add(json_nexthop_global,
10045 "metric", 0);
d62a17ae 10046 }
d62a17ae 10047
05864da7
DS
10048 if (json_paths)
10049 json_object_boolean_true_add(json_nexthop_global,
10050 "accessible");
10051 }
d62a17ae 10052
05864da7
DS
10053 /* Display peer "from" output */
10054 /* This path was originated locally */
10055 if (path->peer == bgp->peer_self) {
d62a17ae 10056
05864da7 10057 if (safi == SAFI_EVPN
b54892e0 10058 || (bn_p->family == AF_INET
05864da7 10059 && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
d62a17ae 10060 if (json_paths)
05864da7
DS
10061 json_object_string_add(json_peer, "peerId",
10062 "0.0.0.0");
d62a17ae 10063 else
05864da7
DS
10064 vty_out(vty, " from 0.0.0.0 ");
10065 } else {
d62a17ae 10066 if (json_paths)
05864da7
DS
10067 json_object_string_add(json_peer, "peerId",
10068 "::");
d62a17ae 10069 else
05864da7 10070 vty_out(vty, " from :: ");
d62a17ae 10071 }
d62a17ae 10072
23d0a753
DA
10073 if (json_paths) {
10074 char buf[BUFSIZ] = {0};
10075
05864da7 10076 json_object_string_add(json_peer, "routerId",
23d0a753
DA
10077 inet_ntop(AF_INET,
10078 &bgp->router_id, buf,
10079 sizeof(buf)));
10080 } else {
10081 vty_out(vty, "(%pI4)", &bgp->router_id);
10082 }
05864da7 10083 }
d62a17ae 10084
05864da7
DS
10085 /* We RXed this path from one of our peers */
10086 else {
10087
10088 if (json_paths) {
10089 json_object_string_add(json_peer, "peerId",
10090 sockunion2str(&path->peer->su,
10091 buf,
10092 SU_ADDRSTRLEN));
10093 json_object_string_add(json_peer, "routerId",
10094 inet_ntop(AF_INET,
10095 &path->peer->remote_id,
10096 buf1, sizeof(buf1)));
10097
10098 if (path->peer->hostname)
10099 json_object_string_add(json_peer, "hostname",
10100 path->peer->hostname);
10101
10102 if (path->peer->domainname)
10103 json_object_string_add(json_peer, "domainname",
10104 path->peer->domainname);
10105
10106 if (path->peer->conf_if)
10107 json_object_string_add(json_peer, "interface",
10108 path->peer->conf_if);
10109 } else {
10110 if (path->peer->conf_if) {
10111 if (path->peer->hostname
892fedb6
DA
10112 && CHECK_FLAG(path->peer->bgp->flags,
10113 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10114 vty_out(vty, " from %s(%s)",
10115 path->peer->hostname,
10116 path->peer->conf_if);
d62a17ae 10117 else
05864da7 10118 vty_out(vty, " from %s",
9b6d8fcf 10119 path->peer->conf_if);
d62a17ae 10120 } else {
05864da7 10121 if (path->peer->hostname
892fedb6
DA
10122 && CHECK_FLAG(path->peer->bgp->flags,
10123 BGP_FLAG_SHOW_HOSTNAME))
05864da7
DS
10124 vty_out(vty, " from %s(%s)",
10125 path->peer->hostname,
10126 path->peer->host);
d62a17ae 10127 else
05864da7
DS
10128 vty_out(vty, " from %s",
10129 sockunion2str(&path->peer->su,
10130 buf,
10131 SU_ADDRSTRLEN));
d62a17ae 10132 }
d62a17ae 10133
05864da7 10134 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
23d0a753 10135 vty_out(vty, " (%pI4)", &attr->originator_id);
05864da7
DS
10136 else
10137 vty_out(vty, " (%s)",
10138 inet_ntop(AF_INET,
10139 &path->peer->remote_id, buf1,
10140 sizeof(buf1)));
d62a17ae 10141 }
05864da7 10142 }
9df8b37c 10143
05864da7
DS
10144 /*
10145 * Note when vrfid of nexthop is different from that of prefix
10146 */
10147 if (path->extra && path->extra->bgp_orig) {
10148 vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
9df8b37c 10149
05864da7
DS
10150 if (json_paths) {
10151 const char *vn;
9df8b37c 10152
05864da7
DS
10153 if (path->extra->bgp_orig->inst_type
10154 == BGP_INSTANCE_TYPE_DEFAULT)
10155 vn = VRF_DEFAULT_NAME;
10156 else
10157 vn = path->extra->bgp_orig->name;
9df8b37c 10158
05864da7 10159 json_object_string_add(json_path, "nhVrfName", vn);
9df8b37c 10160
05864da7
DS
10161 if (nexthop_vrfid == VRF_UNKNOWN) {
10162 json_object_int_add(json_path, "nhVrfId", -1);
9df8b37c 10163 } else {
05864da7
DS
10164 json_object_int_add(json_path, "nhVrfId",
10165 (int)nexthop_vrfid);
9df8b37c 10166 }
05864da7
DS
10167 } else {
10168 if (nexthop_vrfid == VRF_UNKNOWN)
10169 vty_out(vty, " vrf ?");
137147c6
DS
10170 else {
10171 struct vrf *vrf;
10172
10173 vrf = vrf_lookup_by_id(nexthop_vrfid);
10174 vty_out(vty, " vrf %s(%u)",
10175 VRF_LOGNAME(vrf), nexthop_vrfid);
10176 }
9df8b37c 10177 }
05864da7 10178 }
9df8b37c 10179
05864da7
DS
10180 if (nexthop_self) {
10181 if (json_paths) {
10182 json_object_boolean_true_add(json_path,
10183 "announceNexthopSelf");
10184 } else {
10185 vty_out(vty, " announce-nh-self");
9df8b37c 10186 }
05864da7 10187 }
9df8b37c 10188
05864da7
DS
10189 if (!json_paths)
10190 vty_out(vty, "\n");
d62a17ae 10191
05864da7
DS
10192 /* display the link-local nexthop */
10193 if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
10194 if (json_paths) {
10195 json_nexthop_ll = json_object_new_object();
10196 json_object_string_add(
515c2602
DA
10197 json_nexthop_ll, "ip",
10198 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10199 buf, INET6_ADDRSTRLEN));
10200
939a97f4 10201 if (path->peer->hostname)
515c2602
DA
10202 json_object_string_add(json_nexthop_ll,
10203 "hostname",
939a97f4 10204 path->peer->hostname);
515c2602 10205
05864da7
DS
10206 json_object_string_add(json_nexthop_ll, "afi", "ipv6");
10207 json_object_string_add(json_nexthop_ll, "scope",
10208 "link-local");
d62a17ae 10209
05864da7
DS
10210 json_object_boolean_true_add(json_nexthop_ll,
10211 "accessible");
d62a17ae 10212
05864da7 10213 if (!attr->mp_nexthop_prefer_global)
d62a17ae 10214 json_object_boolean_true_add(json_nexthop_ll,
05864da7
DS
10215 "used");
10216 else
10217 json_object_boolean_true_add(
10218 json_nexthop_global, "used");
10219 } else {
10220 vty_out(vty, " (%s) %s\n",
10221 inet_ntop(AF_INET6, &attr->mp_nexthop_local,
10222 buf, INET6_ADDRSTRLEN),
10223 attr->mp_nexthop_prefer_global
10224 ? "(prefer-global)"
10225 : "(used)");
d62a17ae 10226 }
05864da7
DS
10227 }
10228 /* If we do not have a link-local nexthop then we must flag the
10229 global as "used" */
10230 else {
10231 if (json_paths)
10232 json_object_boolean_true_add(json_nexthop_global,
10233 "used");
10234 }
d62a17ae 10235
b5e140c8 10236 if (safi == SAFI_EVPN &&
5e4d4c8a 10237 bgp_evpn_is_esi_valid(&attr->esi)) {
229587fb 10238 route_vty_out_detail_es_info(vty, path, attr, json_path);
b5e140c8
AK
10239 }
10240
05864da7
DS
10241 /* Line 3 display Origin, Med, Locpref, Weight, Tag, valid,
10242 * Int/Ext/Local, Atomic, best */
10243 if (json_paths)
10244 json_object_string_add(json_path, "origin",
10245 bgp_origin_long_str[attr->origin]);
10246 else
10247 vty_out(vty, " Origin %s",
10248 bgp_origin_long_str[attr->origin]);
9df8b37c 10249
05864da7 10250 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
0fbac0b4 10251 if (json_paths)
05864da7 10252 json_object_int_add(json_path, "metric", attr->med);
0fbac0b4 10253 else
05864da7
DS
10254 vty_out(vty, ", metric %u", attr->med);
10255 }
9df8b37c 10256
05864da7
DS
10257 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
10258 if (json_paths)
0fbac0b4 10259 json_object_int_add(json_path, "locPrf",
05864da7
DS
10260 attr->local_pref);
10261 else
10262 vty_out(vty, ", localpref %u", attr->local_pref);
10263 }
9df8b37c 10264
05864da7
DS
10265 if (attr->weight != 0) {
10266 if (json_paths)
10267 json_object_int_add(json_path, "weight", attr->weight);
10268 else
10269 vty_out(vty, ", weight %u", attr->weight);
10270 }
9df8b37c 10271
05864da7
DS
10272 if (attr->tag != 0) {
10273 if (json_paths)
10274 json_object_int_add(json_path, "tag", attr->tag);
10275 else
10276 vty_out(vty, ", tag %" ROUTE_TAG_PRI, attr->tag);
10277 }
9df8b37c 10278
05864da7
DS
10279 if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
10280 if (json_paths)
10281 json_object_boolean_false_add(json_path, "valid");
10282 else
10283 vty_out(vty, ", invalid");
10284 } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) {
10285 if (json_paths)
10286 json_object_boolean_true_add(json_path, "valid");
10287 else
10288 vty_out(vty, ", valid");
10289 }
9df8b37c 10290
7d3cae70
DA
10291 if (json_paths)
10292 json_object_int_add(json_path, "version", bn->version);
10293
05864da7
DS
10294 if (path->peer != bgp->peer_self) {
10295 if (path->peer->as == path->peer->local_as) {
10296 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
10297 if (json_paths)
10298 json_object_string_add(
10299 json_peer, "type",
10300 "confed-internal");
d62a17ae 10301 else
05864da7 10302 vty_out(vty, ", confed-internal");
d62a17ae 10303 } else {
05864da7
DS
10304 if (json_paths)
10305 json_object_string_add(
10306 json_peer, "type", "internal");
10307 else
10308 vty_out(vty, ", internal");
9df8b37c 10309 }
05864da7
DS
10310 } else {
10311 if (bgp_confederation_peers_check(bgp,
10312 path->peer->as)) {
10313 if (json_paths)
10314 json_object_string_add(
10315 json_peer, "type",
10316 "confed-external");
d62a17ae 10317 else
05864da7 10318 vty_out(vty, ", confed-external");
d62a17ae 10319 } else {
05864da7
DS
10320 if (json_paths)
10321 json_object_string_add(
10322 json_peer, "type", "external");
10323 else
10324 vty_out(vty, ", external");
d62a17ae 10325 }
10326 }
05864da7
DS
10327 } else if (path->sub_type == BGP_ROUTE_AGGREGATE) {
10328 if (json_paths) {
10329 json_object_boolean_true_add(json_path, "aggregated");
10330 json_object_boolean_true_add(json_path, "local");
10331 } else {
10332 vty_out(vty, ", aggregated, local");
10333 }
10334 } else if (path->type != ZEBRA_ROUTE_BGP) {
10335 if (json_paths)
10336 json_object_boolean_true_add(json_path, "sourced");
10337 else
10338 vty_out(vty, ", sourced");
10339 } else {
10340 if (json_paths) {
10341 json_object_boolean_true_add(json_path, "sourced");
10342 json_object_boolean_true_add(json_path, "local");
10343 } else {
10344 vty_out(vty, ", sourced, local");
d62a17ae 10345 }
05864da7 10346 }
718e3744 10347
05864da7 10348 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
d62a17ae 10349 if (json_paths)
05864da7
DS
10350 json_object_boolean_true_add(json_path,
10351 "atomicAggregate");
d62a17ae 10352 else
05864da7
DS
10353 vty_out(vty, ", atomic-aggregate");
10354 }
d62a17ae 10355
05864da7
DS
10356 if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)
10357 || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)
10358 && bgp_path_info_mpath_count(path))) {
10359 if (json_paths)
10360 json_object_boolean_true_add(json_path, "multipath");
10361 else
10362 vty_out(vty, ", multipath");
10363 }
50e05855 10364
05864da7
DS
10365 // Mark the bestpath(s)
10366 if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) {
10367 first_as = aspath_get_first_as(attr->aspath);
718e3744 10368
05864da7
DS
10369 if (json_paths) {
10370 if (!json_bestpath)
10371 json_bestpath = json_object_new_object();
10372 json_object_int_add(json_bestpath, "bestpathFromAs",
10373 first_as);
10374 } else {
10375 if (first_as)
10376 vty_out(vty, ", bestpath-from-AS %u", first_as);
d62a17ae 10377 else
05864da7 10378 vty_out(vty, ", bestpath-from-AS Local");
d62a17ae 10379 }
05864da7 10380 }
718e3744 10381
05864da7
DS
10382 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) {
10383 if (json_paths) {
10384 if (!json_bestpath)
10385 json_bestpath = json_object_new_object();
10386 json_object_boolean_true_add(json_bestpath, "overall");
10387 json_object_string_add(
10388 json_bestpath, "selectionReason",
10389 bgp_path_selection_reason2str(bn->reason));
10390 } else {
10391 vty_out(vty, ", best");
10392 vty_out(vty, " (%s)",
10393 bgp_path_selection_reason2str(bn->reason));
d62a17ae 10394 }
05864da7 10395 }
718e3744 10396
4027d19b 10397 if (rpki_curr_state != RPKI_NOT_BEING_USED) {
b5b99af8
DS
10398 if (json_paths)
10399 json_object_string_add(
10400 json_path, "rpkiValidationState",
4027d19b 10401 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8 10402 else
1d327209 10403 vty_out(vty, ", rpki validation-state: %s",
4027d19b 10404 bgp_rpki_validation2str(rpki_curr_state));
b5b99af8
DS
10405 }
10406
05864da7
DS
10407 if (json_bestpath)
10408 json_object_object_add(json_path, "bestpath", json_bestpath);
718e3744 10409
05864da7
DS
10410 if (!json_paths)
10411 vty_out(vty, "\n");
10412
10413 /* Line 4 display Community */
29e72930 10414 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
05864da7
DS
10415 if (json_paths) {
10416 if (!attr->community->json)
10417 community_str(attr->community, true);
10418 json_object_lock(attr->community->json);
10419 json_object_object_add(json_path, "community",
10420 attr->community->json);
10421 } else {
10422 vty_out(vty, " Community: %s\n",
10423 attr->community->str);
d62a17ae 10424 }
05864da7 10425 }
718e3744 10426
05864da7
DS
10427 /* Line 5 display Extended-community */
10428 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) {
10429 if (json_paths) {
10430 json_ext_community = json_object_new_object();
10431 json_object_string_add(json_ext_community, "string",
10432 attr->ecommunity->str);
10433 json_object_object_add(json_path, "extendedCommunity",
10434 json_ext_community);
d62a17ae 10435 } else {
05864da7
DS
10436 vty_out(vty, " Extended Community: %s\n",
10437 attr->ecommunity->str);
d62a17ae 10438 }
05864da7 10439 }
718e3744 10440
05864da7
DS
10441 /* Line 6 display Large community */
10442 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
10443 if (json_paths) {
10444 if (!attr->lcommunity->json)
10445 lcommunity_str(attr->lcommunity, true);
10446 json_object_lock(attr->lcommunity->json);
10447 json_object_object_add(json_path, "largeCommunity",
10448 attr->lcommunity->json);
10449 } else {
10450 vty_out(vty, " Large Community: %s\n",
10451 attr->lcommunity->str);
d62a17ae 10452 }
05864da7 10453 }
718e3744 10454
05864da7
DS
10455 /* Line 7 display Originator, Cluster-id */
10456 if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
10457 || (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
23d0a753
DA
10458 char buf[BUFSIZ] = {0};
10459
05864da7 10460 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) {
d62a17ae 10461 if (json_paths)
05864da7
DS
10462 json_object_string_add(
10463 json_path, "originatorId",
23d0a753
DA
10464 inet_ntop(AF_INET, &attr->originator_id,
10465 buf, sizeof(buf)));
d62a17ae 10466 else
23d0a753
DA
10467 vty_out(vty, " Originator: %pI4",
10468 &attr->originator_id);
d62a17ae 10469 }
856ca177 10470
05864da7 10471 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
779fee93
DS
10472 struct cluster_list *cluster =
10473 bgp_attr_get_cluster(attr);
05864da7 10474 int i;
d62a17ae 10475
10476 if (json_paths) {
05864da7
DS
10477 json_cluster_list = json_object_new_object();
10478 json_cluster_list_list =
10479 json_object_new_array();
10480
779fee93 10481 for (i = 0; i < cluster->length / 4; i++) {
05864da7 10482 json_string = json_object_new_string(
779fee93
DS
10483 inet_ntop(AF_INET,
10484 &cluster->list[i],
10485 buf, sizeof(buf)));
05864da7
DS
10486 json_object_array_add(
10487 json_cluster_list_list,
10488 json_string);
10489 }
718e3744 10490
05864da7
DS
10491 /*
10492 * struct cluster_list does not have
10493 * "str" variable like aspath and community
10494 * do. Add this someday if someone asks
10495 * for it.
10496 * json_object_string_add(json_cluster_list,
779fee93 10497 * "string", cluster->str);
05864da7
DS
10498 */
10499 json_object_object_add(json_cluster_list,
10500 "list",
10501 json_cluster_list_list);
10502 json_object_object_add(json_path, "clusterList",
10503 json_cluster_list);
0dc8ee70 10504 } else {
05864da7
DS
10505 vty_out(vty, ", Cluster list: ");
10506
779fee93 10507 for (i = 0; i < cluster->length / 4; i++) {
23d0a753 10508 vty_out(vty, "%pI4 ",
779fee93 10509 &cluster->list[i]);
05864da7 10510 }
0dc8ee70 10511 }
d62a17ae 10512 }
718e3744 10513
d62a17ae 10514 if (!json_paths)
10515 vty_out(vty, "\n");
05864da7 10516 }
d62a17ae 10517
05864da7 10518 if (path->extra && path->extra->damp_info)
b4f7f45b 10519 bgp_damp_info_vty(vty, path, afi, safi, json_path);
adbac85e 10520
05864da7
DS
10521 /* Remote Label */
10522 if (path->extra && bgp_is_valid_label(&path->extra->label[0])
10523 && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
10524 mpls_label_t label = label_pton(&path->extra->label[0]);
d62a17ae 10525
05864da7
DS
10526 if (json_paths)
10527 json_object_int_add(json_path, "remoteLabel", label);
10528 else
10529 vty_out(vty, " Remote label: %d\n", label);
10530 }
d62a17ae 10531
e496b420
HS
10532 /* Remote SID */
10533 if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
16f3db2d 10534 inet_ntop(AF_INET6, &path->extra->sid[0].sid, buf, sizeof(buf));
e496b420
HS
10535 if (json_paths)
10536 json_object_string_add(json_path, "remoteSid", buf);
10537 else
10538 vty_out(vty, " Remote SID: %s\n", buf);
10539 }
10540
05864da7
DS
10541 /* Label Index */
10542 if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
10543 if (json_paths)
10544 json_object_int_add(json_path, "labelIndex",
10545 attr->label_index);
10546 else
10547 vty_out(vty, " Label Index: %d\n",
10548 attr->label_index);
10549 }
d62a17ae 10550
05864da7
DS
10551 /* Line 8 display Addpath IDs */
10552 if (path->addpath_rx_id
10553 || bgp_addpath_info_has_ids(&path->tx_addpath)) {
10554 if (json_paths) {
10555 json_object_int_add(json_path, "addpathRxId",
10556 path->addpath_rx_id);
d62a17ae 10557
05864da7
DS
10558 /* Keep backwards compatibility with the old API
10559 * by putting TX All's ID in the old field
10560 */
10561 json_object_int_add(
10562 json_path, "addpathTxId",
10563 path->tx_addpath
10564 .addpath_tx_id[BGP_ADDPATH_ALL]);
d62a17ae 10565
05864da7
DS
10566 /* ... but create a specific field for each
10567 * strategy
10568 */
10569 for (i = 0; i < BGP_ADDPATH_MAX; i++) {
10570 json_object_int_add(
10571 json_path,
10572 bgp_addpath_names(i)->id_json_name,
10573 path->tx_addpath.addpath_tx_id[i]);
d62a17ae 10574 }
05864da7
DS
10575 } else {
10576 vty_out(vty, " AddPath ID: RX %u, ",
10577 path->addpath_rx_id);
d62a17ae 10578
05864da7 10579 route_vty_out_tx_ids(vty, &path->tx_addpath);
d62a17ae 10580 }
05864da7 10581 }
520d5d76 10582
05864da7
DS
10583 /* If we used addpath to TX a non-bestpath we need to display
10584 * "Advertised to" on a path-by-path basis
10585 */
10586 if (bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
10587 first = 1;
dcc68b5e 10588
05864da7
DS
10589 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
10590 addpath_capable =
10591 bgp_addpath_encode_tx(peer, afi, safi);
10592 has_adj = bgp_adj_out_lookup(
10593 peer, path->net,
10594 bgp_addpath_id_for_peer(peer, afi, safi,
10595 &path->tx_addpath));
10596
10597 if ((addpath_capable && has_adj)
10598 || (!addpath_capable && has_adj
10599 && CHECK_FLAG(path->flags,
10600 BGP_PATH_SELECTED))) {
10601 if (json_path && !json_adv_to)
10602 json_adv_to = json_object_new_object();
dcc68b5e 10603
05864da7
DS
10604 route_vty_out_advertised_to(
10605 vty, peer, &first,
10606 " Advertised to:", json_adv_to);
d62a17ae 10607 }
10608 }
718e3744 10609
05864da7
DS
10610 if (json_path) {
10611 if (json_adv_to) {
10612 json_object_object_add(
10613 json_path, "advertisedTo", json_adv_to);
d62a17ae 10614 }
05864da7
DS
10615 } else {
10616 if (!first) {
10617 vty_out(vty, "\n");
d62a17ae 10618 }
10619 }
05864da7 10620 }
b05a1c8b 10621
05864da7
DS
10622 /* Line 9 display Uptime */
10623 tbuf = time(NULL) - (bgp_clock() - path->uptime);
10624 if (json_paths) {
10625 json_last_update = json_object_new_object();
10626 json_object_int_add(json_last_update, "epoch", tbuf);
10627 json_object_string_add(json_last_update, "string",
10628 ctime(&tbuf));
10629 json_object_object_add(json_path, "lastUpdate",
10630 json_last_update);
10631 } else
10632 vty_out(vty, " Last update: %s", ctime(&tbuf));
b7d08f5a 10633
05864da7
DS
10634 /* Line 10 display PMSI tunnel attribute, if present */
10635 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
2a3f51cf
DS
10636 const char *str = lookup_msg(bgp_pmsi_tnltype_str,
10637 bgp_attr_get_pmsi_tnl_type(attr),
10638 PMSI_TNLTYPE_STR_DEFAULT);
7fd077aa 10639
05864da7
DS
10640 if (json_paths) {
10641 json_pmsi = json_object_new_object();
10642 json_object_string_add(json_pmsi, "tunnelType", str);
10643 json_object_int_add(json_pmsi, "label",
10644 label2vni(&attr->label));
10645 json_object_object_add(json_path, "pmsi", json_pmsi);
10646 } else
10647 vty_out(vty, " PMSI Tunnel Type: %s, label: %d\n",
10648 str, label2vni(&attr->label));
d62a17ae 10649 }
f1aa5d8a 10650
92269aa2
DS
10651 /* Output some debug about internal state of the dest flags */
10652 if (json_paths) {
10653 if (CHECK_FLAG(bn->flags, BGP_NODE_PROCESS_SCHEDULED))
10654 json_object_boolean_true_add(json_path, "processScheduled");
10655 if (CHECK_FLAG(bn->flags, BGP_NODE_USER_CLEAR))
10656 json_object_boolean_true_add(json_path, "userCleared");
10657 if (CHECK_FLAG(bn->flags, BGP_NODE_LABEL_CHANGED))
10658 json_object_boolean_true_add(json_path, "labelChanged");
10659 if (CHECK_FLAG(bn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
10660 json_object_boolean_true_add(json_path, "registeredForLabel");
10661 if (CHECK_FLAG(bn->flags, BGP_NODE_SELECT_DEFER))
10662 json_object_boolean_true_add(json_path, "selectDefered");
10663 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED))
10664 json_object_boolean_true_add(json_path, "fibInstalled");
10665 if (CHECK_FLAG(bn->flags, BGP_NODE_FIB_INSTALL_PENDING))
10666 json_object_boolean_true_add(json_path, "fibPending");
10667 }
10668
d62a17ae 10669 /* We've constructed the json object for this path, add it to the json
10670 * array of paths
10671 */
10672 if (json_paths) {
10673 if (json_nexthop_global || json_nexthop_ll) {
10674 json_nexthops = json_object_new_array();
f1aa5d8a 10675
d62a17ae 10676 if (json_nexthop_global)
10677 json_object_array_add(json_nexthops,
10678 json_nexthop_global);
f1aa5d8a 10679
d62a17ae 10680 if (json_nexthop_ll)
10681 json_object_array_add(json_nexthops,
10682 json_nexthop_ll);
f1aa5d8a 10683
d62a17ae 10684 json_object_object_add(json_path, "nexthops",
10685 json_nexthops);
10686 }
10687
10688 json_object_object_add(json_path, "peer", json_peer);
10689 json_object_array_add(json_paths, json_path);
05864da7 10690 }
b366b518
BB
10691}
10692
96ade3ed 10693#define BGP_SHOW_HEADER_CSV "Flags, Network, Next Hop, Metric, LocPrf, Weight, Path"
181039f3
DL
10694#define BGP_SHOW_DAMP_HEADER " Network From Reuse Path\n"
10695#define BGP_SHOW_FLAP_HEADER " Network From Flaps Duration Reuse Path\n"
718e3744 10696
d62a17ae 10697static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
10698 const char *prefix_list_str, afi_t afi,
10699 safi_t safi, enum bgp_show_type type);
10700static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
10701 const char *filter, afi_t afi, safi_t safi,
10702 enum bgp_show_type type);
10703static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
10704 const char *rmap_str, afi_t afi, safi_t safi,
10705 enum bgp_show_type type);
10706static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
10707 const char *com, int exact, afi_t afi,
10708 safi_t safi);
10709static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
10710 const char *prefix, afi_t afi, safi_t safi,
10711 enum bgp_show_type type);
a4d82a8a 10712static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
10713 afi_t afi, safi_t safi, enum bgp_show_type type,
10714 bool use_json);
7f323236
DW
10715static int bgp_show_community(struct vty *vty, struct bgp *bgp,
10716 const char *comstr, int exact, afi_t afi,
96c81f66 10717 safi_t safi, uint16_t show_flags);
d62a17ae 10718
1ae44dfc 10719static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
d62a17ae 10720 struct bgp_table *table, enum bgp_show_type type,
edfee30d 10721 void *output_arg, const char *rd, int is_last,
96f3485c 10722 unsigned long *output_cum, unsigned long *total_cum,
96c81f66 10723 unsigned long *json_header_depth, uint16_t show_flags,
4027d19b 10724 enum rpki_states rpki_target_state)
d62a17ae 10725{
40381db7 10726 struct bgp_path_info *pi;
9bcb3eef 10727 struct bgp_dest *dest;
2aad8c42
MS
10728 bool header = true;
10729 bool json_detail_header = false;
d62a17ae 10730 int display;
1ae44dfc
LB
10731 unsigned long output_count = 0;
10732 unsigned long total_count = 0;
d62a17ae 10733 struct prefix *p;
d62a17ae 10734 json_object *json_paths = NULL;
10735 int first = 1;
96f3485c
MK
10736 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
10737 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
10738 bool all = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
d62a17ae 10739
1ae44dfc 10740 if (output_cum && *output_cum != 0)
2aad8c42 10741 header = false;
1ae44dfc 10742
9386b588 10743 if (use_json && !*json_header_depth) {
96f3485c
MK
10744 if (all)
10745 *json_header_depth = 1;
10746 else {
10747 vty_out(vty, "{\n");
10748 *json_header_depth = 2;
10749 }
10750
d62a17ae 10751 vty_out(vty,
23d0a753
DA
10752 " \"vrfId\": %d,\n \"vrfName\": \"%s\",\n \"tableVersion\": %" PRId64
10753 ",\n \"routerId\": \"%pI4\",\n \"defaultLocPrf\": %u,\n"
01eced22 10754 " \"localAS\": %u,\n \"routes\": { ",
a8bf7d9c 10755 bgp->vrf_id == VRF_UNKNOWN ? -1 : (int)bgp->vrf_id,
5742e42b 10756 bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
23d0a753
DA
10757 ? VRF_DEFAULT_NAME
10758 : bgp->name,
10759 table->version, &bgp->router_id,
01eced22 10760 bgp->default_local_pref, bgp->as);
9386b588 10761 if (rd) {
445c2480 10762 vty_out(vty, " \"routeDistinguishers\" : {");
9386b588
PZ
10763 ++*json_header_depth;
10764 }
d62a17ae 10765 }
718e3744 10766
445c2480
DS
10767 if (use_json && rd) {
10768 vty_out(vty, " \"%s\" : { ", rd);
10769 }
10770
2aad8c42
MS
10771 /* Check for 'json detail', where we need header output once per dest */
10772 if (use_json && CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL) &&
10773 type != bgp_show_type_dampend_paths &&
10774 type != bgp_show_type_damp_neighbor &&
10775 type != bgp_show_type_flap_statistics &&
10776 type != bgp_show_type_flap_neighbor)
10777 json_detail_header = true;
10778
d62a17ae 10779 /* Start processing of routes. */
9bcb3eef
DS
10780 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
10781 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
4027d19b 10782 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
2aad8c42 10783 bool json_detail = json_detail_header;
b54892e0 10784
9bcb3eef 10785 pi = bgp_dest_get_bgp_path_info(dest);
6f94b685 10786 if (pi == NULL)
98ce9a06 10787 continue;
d62a17ae 10788
98ce9a06 10789 display = 0;
98ce9a06
DS
10790 if (use_json)
10791 json_paths = json_object_new_array();
10792 else
10793 json_paths = NULL;
d62a17ae 10794
6f94b685 10795 for (; pi; pi = pi->next) {
98ce9a06 10796 total_count++;
1e2ce4f1 10797
7d3cae70
DA
10798 if (type == bgp_show_type_prefix_version) {
10799 uint32_t version =
10800 strtoul(output_arg, NULL, 10);
10801 if (dest->version < version)
10802 continue;
10803 }
10804
a70a28a5
DA
10805 if (type == bgp_show_type_community_alias) {
10806 char *alias = output_arg;
10807 char **communities;
10808 int num;
10809 bool found = false;
10810
10811 if (pi->attr->community) {
10812 frrstr_split(pi->attr->community->str,
10813 " ", &communities, &num);
10814 for (int i = 0; i < num; i++) {
10815 const char *com2alias =
10816 bgp_community2alias(
10817 communities[i]);
cd9cc0e6
IR
10818 if (!found
10819 && strcmp(alias, com2alias)
10820 == 0)
a70a28a5 10821 found = true;
cd9cc0e6
IR
10822 XFREE(MTYPE_TMP,
10823 communities[i]);
a70a28a5 10824 }
cd9cc0e6 10825 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10826 }
10827
10828 if (!found && pi->attr->lcommunity) {
10829 frrstr_split(pi->attr->lcommunity->str,
10830 " ", &communities, &num);
10831 for (int i = 0; i < num; i++) {
10832 const char *com2alias =
10833 bgp_community2alias(
10834 communities[i]);
cd9cc0e6
IR
10835 if (!found
10836 && strcmp(alias, com2alias)
10837 == 0)
a70a28a5 10838 found = true;
cd9cc0e6
IR
10839 XFREE(MTYPE_TMP,
10840 communities[i]);
a70a28a5 10841 }
cd9cc0e6 10842 XFREE(MTYPE_TMP, communities);
a70a28a5
DA
10843 }
10844
10845 if (!found)
10846 continue;
10847 }
10848
1e2ce4f1
DS
10849 if (type == bgp_show_type_rpki) {
10850 if (dest_p->family == AF_INET
10851 || dest_p->family == AF_INET6)
4027d19b 10852 rpki_curr_state = hook_call(
1e2ce4f1
DS
10853 bgp_rpki_prefix_status,
10854 pi->peer, pi->attr, dest_p);
4027d19b
DS
10855 if (rpki_target_state != RPKI_NOT_BEING_USED
10856 && rpki_curr_state != rpki_target_state)
1e2ce4f1
DS
10857 continue;
10858 }
10859
98ce9a06
DS
10860 if (type == bgp_show_type_flap_statistics
10861 || type == bgp_show_type_flap_neighbor
10862 || type == bgp_show_type_dampend_paths
10863 || type == bgp_show_type_damp_neighbor) {
40381db7 10864 if (!(pi->extra && pi->extra->damp_info))
98ce9a06
DS
10865 continue;
10866 }
10867 if (type == bgp_show_type_regexp) {
10868 regex_t *regex = output_arg;
d62a17ae 10869
40381db7 10870 if (bgp_regexec(regex, pi->attr->aspath)
98ce9a06
DS
10871 == REG_NOMATCH)
10872 continue;
10873 }
10874 if (type == bgp_show_type_prefix_list) {
10875 struct prefix_list *plist = output_arg;
d62a17ae 10876
9bcb3eef 10877 if (prefix_list_apply(plist, dest_p)
98ce9a06
DS
10878 != PREFIX_PERMIT)
10879 continue;
10880 }
10881 if (type == bgp_show_type_filter_list) {
10882 struct as_list *as_list = output_arg;
d62a17ae 10883
40381db7 10884 if (as_list_apply(as_list, pi->attr->aspath)
98ce9a06
DS
10885 != AS_FILTER_PERMIT)
10886 continue;
10887 }
10888 if (type == bgp_show_type_route_map) {
10889 struct route_map *rmap = output_arg;
9b6d8fcf 10890 struct bgp_path_info path;
98ce9a06 10891 struct attr dummy_attr;
b68885f9 10892 route_map_result_t ret;
d62a17ae 10893
6f4f49b2 10894 dummy_attr = *pi->attr;
d62a17ae 10895
40381db7 10896 path.peer = pi->peer;
9b6d8fcf 10897 path.attr = &dummy_attr;
d62a17ae 10898
1782514f 10899 ret = route_map_apply(rmap, dest_p, &path);
ee522f57 10900 bgp_attr_flush(&dummy_attr);
98ce9a06
DS
10901 if (ret == RMAP_DENYMATCH)
10902 continue;
10903 }
10904 if (type == bgp_show_type_neighbor
10905 || type == bgp_show_type_flap_neighbor
10906 || type == bgp_show_type_damp_neighbor) {
10907 union sockunion *su = output_arg;
10908
40381db7
DS
10909 if (pi->peer == NULL
10910 || pi->peer->su_remote == NULL
10911 || !sockunion_same(pi->peer->su_remote, su))
98ce9a06
DS
10912 continue;
10913 }
10914 if (type == bgp_show_type_cidr_only) {
d7c0a89a 10915 uint32_t destination;
d62a17ae 10916
9bcb3eef 10917 destination = ntohl(dest_p->u.prefix4.s_addr);
98ce9a06 10918 if (IN_CLASSC(destination)
9bcb3eef 10919 && dest_p->prefixlen == 24)
98ce9a06
DS
10920 continue;
10921 if (IN_CLASSB(destination)
9bcb3eef 10922 && dest_p->prefixlen == 16)
98ce9a06
DS
10923 continue;
10924 if (IN_CLASSA(destination)
9bcb3eef 10925 && dest_p->prefixlen == 8)
98ce9a06
DS
10926 continue;
10927 }
10928 if (type == bgp_show_type_prefix_longer) {
f7813c7c 10929 p = output_arg;
9bcb3eef 10930 if (!prefix_match(p, dest_p))
98ce9a06
DS
10931 continue;
10932 }
10933 if (type == bgp_show_type_community_all) {
40381db7 10934 if (!pi->attr->community)
98ce9a06
DS
10935 continue;
10936 }
10937 if (type == bgp_show_type_community) {
10938 struct community *com = output_arg;
d62a17ae 10939
40381db7
DS
10940 if (!pi->attr->community
10941 || !community_match(pi->attr->community,
98ce9a06
DS
10942 com))
10943 continue;
10944 }
10945 if (type == bgp_show_type_community_exact) {
10946 struct community *com = output_arg;
d62a17ae 10947
40381db7
DS
10948 if (!pi->attr->community
10949 || !community_cmp(pi->attr->community, com))
98ce9a06
DS
10950 continue;
10951 }
10952 if (type == bgp_show_type_community_list) {
10953 struct community_list *list = output_arg;
d62a17ae 10954
40381db7 10955 if (!community_list_match(pi->attr->community,
a4d82a8a 10956 list))
98ce9a06
DS
10957 continue;
10958 }
a4d82a8a 10959 if (type == bgp_show_type_community_list_exact) {
98ce9a06 10960 struct community_list *list = output_arg;
d62a17ae 10961
98ce9a06 10962 if (!community_list_exact_match(
40381db7 10963 pi->attr->community, list))
98ce9a06
DS
10964 continue;
10965 }
10966 if (type == bgp_show_type_lcommunity) {
10967 struct lcommunity *lcom = output_arg;
d62a17ae 10968
40381db7
DS
10969 if (!pi->attr->lcommunity
10970 || !lcommunity_match(pi->attr->lcommunity,
98ce9a06
DS
10971 lcom))
10972 continue;
10973 }
36a206db 10974
10975 if (type == bgp_show_type_lcommunity_exact) {
10976 struct lcommunity *lcom = output_arg;
10977
10978 if (!pi->attr->lcommunity
10979 || !lcommunity_cmp(pi->attr->lcommunity,
10980 lcom))
10981 continue;
10982 }
98ce9a06
DS
10983 if (type == bgp_show_type_lcommunity_list) {
10984 struct community_list *list = output_arg;
d62a17ae 10985
40381db7 10986 if (!lcommunity_list_match(pi->attr->lcommunity,
a4d82a8a 10987 list))
98ce9a06
DS
10988 continue;
10989 }
36a206db 10990 if (type
10991 == bgp_show_type_lcommunity_list_exact) {
10992 struct community_list *list = output_arg;
10993
10994 if (!lcommunity_list_exact_match(
10995 pi->attr->lcommunity, list))
10996 continue;
10997 }
98ce9a06 10998 if (type == bgp_show_type_lcommunity_all) {
40381db7 10999 if (!pi->attr->lcommunity)
98ce9a06
DS
11000 continue;
11001 }
11002 if (type == bgp_show_type_dampend_paths
11003 || type == bgp_show_type_damp_neighbor) {
40381db7
DS
11004 if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)
11005 || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
98ce9a06
DS
11006 continue;
11007 }
11008
11009 if (!use_json && header) {
23d0a753
DA
11010 vty_out(vty,
11011 "BGP table version is %" PRIu64
11012 ", local router ID is %pI4, vrf id ",
11013 table->version, &bgp->router_id);
9df8b37c
PZ
11014 if (bgp->vrf_id == VRF_UNKNOWN)
11015 vty_out(vty, "%s", VRFID_NONE_STR);
11016 else
11017 vty_out(vty, "%u", bgp->vrf_id);
11018 vty_out(vty, "\n");
01eced22
AD
11019 vty_out(vty, "Default local pref %u, ",
11020 bgp->default_local_pref);
11021 vty_out(vty, "local AS %u\n", bgp->as);
98ce9a06 11022 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 11023 vty_out(vty, BGP_SHOW_NCODE_HEADER);
98ce9a06 11024 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 11025 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 11026 if (type == bgp_show_type_dampend_paths
11027 || type == bgp_show_type_damp_neighbor)
98ce9a06 11028 vty_out(vty, BGP_SHOW_DAMP_HEADER);
a4d82a8a
PZ
11029 else if (type == bgp_show_type_flap_statistics
11030 || type == bgp_show_type_flap_neighbor)
98ce9a06 11031 vty_out(vty, BGP_SHOW_FLAP_HEADER);
d62a17ae 11032 else
ae248832
MK
11033 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
11034 : BGP_SHOW_HEADER));
2aad8c42
MS
11035 header = false;
11036
11037 } else if (json_detail && json_paths != NULL) {
11038 const struct prefix_rd *prd;
11039 json_object *jtemp;
11040
11041 /* Use common detail header, for most types;
11042 * need a json 'object'.
11043 */
11044
11045 jtemp = json_object_new_object();
11046 prd = bgp_rd_from_dest(dest, safi);
11047
11048 route_vty_out_detail_header(
11049 vty, bgp, dest, prd, table->afi,
11050 safi, jtemp);
11051
11052 json_object_array_add(json_paths, jtemp);
11053
11054 json_detail = false;
d62a17ae 11055 }
2aad8c42 11056
98ce9a06
DS
11057 if (rd != NULL && !display && !output_count) {
11058 if (!use_json)
11059 vty_out(vty,
11060 "Route Distinguisher: %s\n",
11061 rd);
d62a17ae 11062 }
98ce9a06
DS
11063 if (type == bgp_show_type_dampend_paths
11064 || type == bgp_show_type_damp_neighbor)
9bcb3eef 11065 damp_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11066 AFI_IP, safi, use_json,
11067 json_paths);
98ce9a06
DS
11068 else if (type == bgp_show_type_flap_statistics
11069 || type == bgp_show_type_flap_neighbor)
9bcb3eef 11070 flap_route_vty_out(vty, dest_p, pi, display,
b54892e0
DS
11071 AFI_IP, safi, use_json,
11072 json_paths);
f280c93b
DA
11073 else {
11074 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
11075 route_vty_out_detail(
11076 vty, bgp, dest, pi,
11077 family2afi(dest_p->family),
11078 safi, RPKI_NOT_BEING_USED,
11079 json_paths);
11080 else
11081 route_vty_out(vty, dest_p, pi, display,
11082 safi, json_paths, wide);
11083 }
98ce9a06 11084 display++;
d62a17ae 11085 }
11086
98ce9a06
DS
11087 if (display) {
11088 output_count++;
11089 if (!use_json)
11090 continue;
11091
625d2931 11092 /* encode prefix */
9bcb3eef 11093 if (dest_p->family == AF_FLOWSPEC) {
625d2931
PG
11094 char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
11095
1840384b 11096
b54892e0
DS
11097 bgp_fs_nlri_get_string(
11098 (unsigned char *)
9bcb3eef
DS
11099 dest_p->u.prefix_flowspec.ptr,
11100 dest_p->u.prefix_flowspec.prefixlen,
1840384b 11101 retstr, NLRI_STRING_FORMAT_MIN, NULL,
4371bf91
PG
11102 family2afi(dest_p->u
11103 .prefix_flowspec.family));
625d2931 11104 if (first)
b54892e0 11105 vty_out(vty, "\"%s/%d\": ", retstr,
9bcb3eef 11106 dest_p->u.prefix_flowspec
b54892e0 11107 .prefixlen);
625d2931 11108 else
b54892e0 11109 vty_out(vty, ",\"%s/%d\": ", retstr,
9bcb3eef 11110 dest_p->u.prefix_flowspec
b54892e0 11111 .prefixlen);
625d2931 11112 } else {
625d2931 11113 if (first)
1b78780b 11114 vty_out(vty, "\"%pFX\": ", dest_p);
625d2931 11115 else
1b78780b 11116 vty_out(vty, ",\"%pFX\": ", dest_p);
625d2931 11117 }
98ce9a06 11118 vty_out(vty, "%s",
f4ec52f7
DA
11119 json_object_to_json_string_ext(
11120 json_paths, JSON_C_TO_STRING_PRETTY));
98ce9a06 11121 json_object_free(json_paths);
449feb8e 11122 json_paths = NULL;
98ce9a06 11123 first = 0;
1f83ed02
DS
11124 } else
11125 json_object_free(json_paths);
98ce9a06
DS
11126 }
11127
1ae44dfc
LB
11128 if (output_cum) {
11129 output_count += *output_cum;
11130 *output_cum = output_count;
11131 }
11132 if (total_cum) {
11133 total_count += *total_cum;
11134 *total_cum = total_count;
11135 }
d62a17ae 11136 if (use_json) {
9386b588 11137 if (rd) {
a4d82a8a 11138 vty_out(vty, " }%s ", (is_last ? "" : ","));
9386b588
PZ
11139 }
11140 if (is_last) {
a4d82a8a
PZ
11141 unsigned long i;
11142 for (i = 0; i < *json_header_depth; ++i)
11143 vty_out(vty, " } ");
96f3485c
MK
11144 if (!all)
11145 vty_out(vty, "\n");
9386b588 11146 }
d62a17ae 11147 } else {
1ae44dfc
LB
11148 if (is_last) {
11149 /* No route is displayed */
11150 if (output_count == 0) {
11151 if (type == bgp_show_type_normal)
11152 vty_out(vty,
11153 "No BGP prefixes displayed, %ld exist\n",
11154 total_count);
11155 } else
d62a17ae 11156 vty_out(vty,
1ae44dfc
LB
11157 "\nDisplayed %ld routes and %ld total paths\n",
11158 output_count, total_count);
11159 }
d62a17ae 11160 }
718e3744 11161
d62a17ae 11162 return CMD_SUCCESS;
718e3744 11163}
11164
1ae44dfc
LB
11165int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
11166 struct bgp_table *table, struct prefix_rd *prd_match,
9f049418 11167 enum bgp_show_type type, void *output_arg, bool use_json)
1ae44dfc 11168{
9bcb3eef 11169 struct bgp_dest *dest, *next;
1ae44dfc
LB
11170 unsigned long output_cum = 0;
11171 unsigned long total_cum = 0;
9386b588 11172 unsigned long json_header_depth = 0;
67009e22 11173 struct bgp_table *itable;
0136788c 11174 bool show_msg;
96c81f66 11175 uint16_t show_flags = 0;
0136788c
LB
11176
11177 show_msg = (!use_json && type == bgp_show_type_normal);
1ae44dfc 11178
96f3485c
MK
11179 if (use_json)
11180 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11181
9bcb3eef
DS
11182 for (dest = bgp_table_top(table); dest; dest = next) {
11183 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11184
9bcb3eef
DS
11185 next = bgp_route_next(dest);
11186 if (prd_match && memcmp(dest_p->u.val, prd_match->val, 8) != 0)
1ae44dfc 11187 continue;
67009e22 11188
9bcb3eef 11189 itable = bgp_dest_get_bgp_table_info(dest);
67009e22 11190 if (itable != NULL) {
1ae44dfc 11191 struct prefix_rd prd;
06b9f471 11192 char rd[RD_ADDRSTRLEN];
1ae44dfc 11193
9bcb3eef 11194 memcpy(&prd, dest_p, sizeof(struct prefix_rd));
06b9f471 11195 prefix_rd2str(&prd, rd, sizeof(rd));
67009e22 11196 bgp_show_table(vty, bgp, safi, itable, type, output_arg,
96f3485c
MK
11197 rd, next == NULL, &output_cum,
11198 &total_cum, &json_header_depth,
1e2ce4f1 11199 show_flags, RPKI_NOT_BEING_USED);
0136788c
LB
11200 if (next == NULL)
11201 show_msg = false;
1ae44dfc
LB
11202 }
11203 }
0136788c
LB
11204 if (show_msg) {
11205 if (output_cum == 0)
11206 vty_out(vty, "No BGP prefixes displayed, %ld exist\n",
11207 total_cum);
11208 else
11209 vty_out(vty,
11210 "\nDisplayed %ld routes and %ld total paths\n",
11211 output_cum, total_cum);
11212 }
1ae44dfc
LB
11213 return CMD_SUCCESS;
11214}
2aad8c42 11215
d62a17ae 11216static int bgp_show(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
96f3485c 11217 enum bgp_show_type type, void *output_arg,
96c81f66 11218 uint16_t show_flags, enum rpki_states rpki_target_state)
fee0f4c6 11219{
d62a17ae 11220 struct bgp_table *table;
9386b588 11221 unsigned long json_header_depth = 0;
96f3485c 11222 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
fee0f4c6 11223
d62a17ae 11224 if (bgp == NULL) {
11225 bgp = bgp_get_default();
11226 }
fee0f4c6 11227
d62a17ae 11228 if (bgp == NULL) {
11229 if (!use_json)
11230 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11231 else
11232 vty_out(vty, "{}\n");
d62a17ae 11233 return CMD_WARNING;
11234 }
4dd6177e 11235
cd8c2a27
MS
11236 /* Labeled-unicast routes live in the unicast table. */
11237 if (safi == SAFI_LABELED_UNICAST)
11238 safi = SAFI_UNICAST;
11239
1ae44dfc 11240 table = bgp->rib[afi][safi];
d62a17ae 11241 /* use MPLS and ENCAP specific shows until they are merged */
11242 if (safi == SAFI_MPLS_VPN) {
1ae44dfc
LB
11243 return bgp_show_table_rd(vty, bgp, safi, table, NULL, type,
11244 output_arg, use_json);
d62a17ae 11245 }
dba3c1d3
PG
11246
11247 if (safi == SAFI_FLOWSPEC && type == bgp_show_type_detail) {
11248 return bgp_show_table_flowspec(vty, bgp, afi, table, type,
11249 output_arg, use_json,
11250 1, NULL, NULL);
11251 }
fee0f4c6 11252
96f3485c 11253 return bgp_show_table(vty, bgp, safi, table, type, output_arg, NULL, 1,
1e2ce4f1 11254 NULL, NULL, &json_header_depth, show_flags,
4027d19b 11255 rpki_target_state);
fee0f4c6 11256}
11257
d62a17ae 11258static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
96c81f66 11259 safi_t safi, uint16_t show_flags)
f186de26 11260{
d62a17ae 11261 struct listnode *node, *nnode;
11262 struct bgp *bgp;
11263 int is_first = 1;
9f049418 11264 bool route_output = false;
96f3485c 11265 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
f186de26 11266
d62a17ae 11267 if (use_json)
11268 vty_out(vty, "{\n");
9f689658 11269
d62a17ae 11270 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
9f049418 11271 route_output = true;
d62a17ae 11272 if (use_json) {
11273 if (!is_first)
11274 vty_out(vty, ",\n");
11275 else
11276 is_first = 0;
11277
11278 vty_out(vty, "\"%s\":",
11279 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11280 ? VRF_DEFAULT_NAME
d62a17ae 11281 : bgp->name);
11282 } else {
11283 vty_out(vty, "\nInstance %s:\n",
11284 (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
5742e42b 11285 ? VRF_DEFAULT_NAME
d62a17ae 11286 : bgp->name);
11287 }
11288 bgp_show(vty, bgp, afi, safi, bgp_show_type_normal, NULL,
1e2ce4f1 11289 show_flags, RPKI_NOT_BEING_USED);
d62a17ae 11290 }
9f689658 11291
d62a17ae 11292 if (use_json)
11293 vty_out(vty, "}\n");
9f049418
DS
11294 else if (!route_output)
11295 vty_out(vty, "%% BGP instance not found\n");
f186de26 11296}
11297
718e3744 11298/* Header of detailed BGP route information */
d62a17ae 11299void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
edfee30d
MS
11300 struct bgp_dest *dest,
11301 const struct prefix_rd *prd,
d62a17ae 11302 afi_t afi, safi_t safi, json_object *json)
11303{
40381db7 11304 struct bgp_path_info *pi;
b54892e0 11305 const struct prefix *p;
d62a17ae 11306 struct peer *peer;
11307 struct listnode *node, *nnode;
06b9f471 11308 char buf1[RD_ADDRSTRLEN];
0291c246 11309 char prefix_str[BUFSIZ];
d62a17ae 11310 int count = 0;
11311 int best = 0;
11312 int suppress = 0;
c5f1e1b2
C
11313 int accept_own = 0;
11314 int route_filter_translated_v4 = 0;
11315 int route_filter_v4 = 0;
11316 int route_filter_translated_v6 = 0;
11317 int route_filter_v6 = 0;
11318 int llgr_stale = 0;
11319 int no_llgr = 0;
11320 int accept_own_nexthop = 0;
11321 int blackhole = 0;
d62a17ae 11322 int no_export = 0;
11323 int no_advertise = 0;
11324 int local_as = 0;
c5f1e1b2 11325 int no_peer = 0;
d62a17ae 11326 int first = 1;
11327 int has_valid_label = 0;
11328 mpls_label_t label = 0;
11329 json_object *json_adv_to = NULL;
9bedbb1e 11330
9bcb3eef
DS
11331 p = bgp_dest_get_prefix(dest);
11332 has_valid_label = bgp_is_valid_label(&dest->local_label);
d62a17ae 11333
11334 if (has_valid_label)
9bcb3eef 11335 label = label_pton(&dest->local_label);
d62a17ae 11336
44c69747 11337 if (safi == SAFI_EVPN) {
d62a17ae 11338
44c69747 11339 if (!json) {
2dbe669b 11340 vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
06b9f471 11341 prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
f137734b 11342 : "",
2dbe669b 11343 prd ? ":" : "", (struct prefix_evpn *)p);
44c69747
LK
11344 } else {
11345 json_object_string_add(json, "rd",
11346 prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
11347 "");
11348 bgp_evpn_route2json((struct prefix_evpn *)p, json);
11349 }
11350 } else {
11351 if (!json) {
9119ef3a
DA
11352 vty_out(vty,
11353 "BGP routing table entry for %s%s%pFX, version %" PRIu64
11354 "\n",
d62a17ae 11355 ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
8228a9a7
DS
11356 ? prefix_rd2str(prd, buf1,
11357 sizeof(buf1))
11358 : ""),
9119ef3a
DA
11359 safi == SAFI_MPLS_VPN ? ":" : "", p,
11360 dest->version);
cd1964ff 11361
9119ef3a 11362 } else {
44c69747
LK
11363 json_object_string_add(json, "prefix",
11364 prefix2str(p, prefix_str, sizeof(prefix_str)));
9119ef3a
DA
11365 json_object_int_add(json, "version", dest->version);
11366
11367 }
44c69747
LK
11368 }
11369
11370 if (has_valid_label) {
11371 if (json)
11372 json_object_int_add(json, "localLabel", label);
11373 else
d62a17ae 11374 vty_out(vty, "Local label: %d\n", label);
44c69747
LK
11375 }
11376
11377 if (!json)
d62a17ae 11378 if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
d62a17ae 11379 vty_out(vty, "not allocated\n");
718e3744 11380
9bcb3eef 11381 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
d62a17ae 11382 count++;
40381db7 11383 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
d62a17ae 11384 best = count;
4056a5f6 11385 if (bgp_path_suppressed(pi))
d62a17ae 11386 suppress = 1;
cee9c031 11387
40381db7 11388 if (pi->attr->community == NULL)
cee9c031
QY
11389 continue;
11390
11391 no_advertise += community_include(
40381db7
DS
11392 pi->attr->community, COMMUNITY_NO_ADVERTISE);
11393 no_export += community_include(pi->attr->community,
cee9c031 11394 COMMUNITY_NO_EXPORT);
40381db7 11395 local_as += community_include(pi->attr->community,
cee9c031 11396 COMMUNITY_LOCAL_AS);
40381db7 11397 accept_own += community_include(pi->attr->community,
cee9c031
QY
11398 COMMUNITY_ACCEPT_OWN);
11399 route_filter_translated_v4 += community_include(
40381db7 11400 pi->attr->community,
cee9c031
QY
11401 COMMUNITY_ROUTE_FILTER_TRANSLATED_v4);
11402 route_filter_translated_v6 += community_include(
40381db7 11403 pi->attr->community,
cee9c031
QY
11404 COMMUNITY_ROUTE_FILTER_TRANSLATED_v6);
11405 route_filter_v4 += community_include(
40381db7 11406 pi->attr->community, COMMUNITY_ROUTE_FILTER_v4);
cee9c031 11407 route_filter_v6 += community_include(
40381db7
DS
11408 pi->attr->community, COMMUNITY_ROUTE_FILTER_v6);
11409 llgr_stale += community_include(pi->attr->community,
cee9c031 11410 COMMUNITY_LLGR_STALE);
40381db7 11411 no_llgr += community_include(pi->attr->community,
cee9c031
QY
11412 COMMUNITY_NO_LLGR);
11413 accept_own_nexthop +=
40381db7 11414 community_include(pi->attr->community,
cee9c031 11415 COMMUNITY_ACCEPT_OWN_NEXTHOP);
40381db7 11416 blackhole += community_include(pi->attr->community,
cee9c031 11417 COMMUNITY_BLACKHOLE);
40381db7 11418 no_peer += community_include(pi->attr->community,
cee9c031 11419 COMMUNITY_NO_PEER);
d62a17ae 11420 }
718e3744 11421 }
718e3744 11422
d62a17ae 11423 if (!json) {
11424 vty_out(vty, "Paths: (%d available", count);
11425 if (best) {
11426 vty_out(vty, ", best #%d", best);
b84060bb
PG
11427 if (safi == SAFI_UNICAST) {
11428 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
11429 vty_out(vty, ", table %s",
11430 VRF_DEFAULT_NAME);
11431 else
11432 vty_out(vty, ", vrf %s",
11433 bgp->name);
11434 }
d62a17ae 11435 } else
11436 vty_out(vty, ", no best path");
11437
c5f1e1b2
C
11438 if (accept_own)
11439 vty_out(vty,
11440 ", accept own local route exported and imported in different VRF");
11441 else if (route_filter_translated_v4)
11442 vty_out(vty,
11443 ", mark translated RTs for VPNv4 route filtering");
11444 else if (route_filter_v4)
11445 vty_out(vty,
11446 ", attach RT as-is for VPNv4 route filtering");
11447 else if (route_filter_translated_v6)
11448 vty_out(vty,
11449 ", mark translated RTs for VPNv6 route filtering");
11450 else if (route_filter_v6)
11451 vty_out(vty,
11452 ", attach RT as-is for VPNv6 route filtering");
11453 else if (llgr_stale)
11454 vty_out(vty,
11455 ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart");
11456 else if (no_llgr)
11457 vty_out(vty,
11458 ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations");
11459 else if (accept_own_nexthop)
11460 vty_out(vty,
11461 ", accept local nexthop");
11462 else if (blackhole)
11463 vty_out(vty, ", inform peer to blackhole prefix");
d62a17ae 11464 else if (no_export)
11465 vty_out(vty, ", not advertised to EBGP peer");
c5f1e1b2
C
11466 else if (no_advertise)
11467 vty_out(vty, ", not advertised to any peer");
d62a17ae 11468 else if (local_as)
11469 vty_out(vty, ", not advertised outside local AS");
c5f1e1b2
C
11470 else if (no_peer)
11471 vty_out(vty,
11472 ", inform EBGP peer not to advertise to their EBGP peers");
d62a17ae 11473
11474 if (suppress)
11475 vty_out(vty,
11476 ", Advertisements suppressed by an aggregate.");
11477 vty_out(vty, ")\n");
11478 }
718e3744 11479
d62a17ae 11480 /* If we are not using addpath then we can display Advertised to and
11481 * that will
11482 * show what peers we advertised the bestpath to. If we are using
11483 * addpath
11484 * though then we must display Advertised to on a path-by-path basis. */
dcc68b5e 11485 if (!bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
d62a17ae 11486 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
9bcb3eef 11487 if (bgp_adj_out_lookup(peer, dest, 0)) {
d62a17ae 11488 if (json && !json_adv_to)
11489 json_adv_to = json_object_new_object();
11490
11491 route_vty_out_advertised_to(
11492 vty, peer, &first,
11493 " Advertised to non peer-group peers:\n ",
11494 json_adv_to);
11495 }
11496 }
11497
11498 if (json) {
11499 if (json_adv_to) {
11500 json_object_object_add(json, "advertisedTo",
11501 json_adv_to);
11502 }
11503 } else {
11504 if (first)
11505 vty_out(vty, " Not advertised to any peer");
11506 vty_out(vty, "\n");
11507 }
11508 }
718e3744 11509}
11510
edfee30d 11511static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
9bcb3eef
DS
11512 struct bgp_dest *bgp_node, struct vty *vty,
11513 struct bgp *bgp, afi_t afi, safi_t safi,
11514 json_object *json, enum bgp_path_type pathtype,
4027d19b 11515 int *display, enum rpki_states rpki_target_state)
44c69747
LK
11516{
11517 struct bgp_path_info *pi;
11518 int header = 1;
11519 char rdbuf[RD_ADDRSTRLEN];
11520 json_object *json_header = NULL;
11521 json_object *json_paths = NULL;
4933eaaf 11522 const struct prefix *p = bgp_dest_get_prefix(bgp_node);
44c69747 11523
9bcb3eef 11524 for (pi = bgp_dest_get_bgp_path_info(bgp_node); pi; pi = pi->next) {
4027d19b 11525 enum rpki_states rpki_curr_state = RPKI_NOT_BEING_USED;
4933eaaf
DS
11526
11527 if (p->family == AF_INET || p->family == AF_INET6)
4027d19b
DS
11528 rpki_curr_state = hook_call(bgp_rpki_prefix_status,
11529 pi->peer, pi->attr, p);
4933eaaf 11530
4027d19b
DS
11531 if (rpki_target_state != RPKI_NOT_BEING_USED
11532 && rpki_curr_state != rpki_target_state)
4933eaaf 11533 continue;
44c69747
LK
11534
11535 if (json && !json_paths) {
11536 /* Instantiate json_paths only if path is valid */
11537 json_paths = json_object_new_array();
11538 if (pfx_rd) {
11539 prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
11540 json_header = json_object_new_object();
11541 } else
11542 json_header = json;
11543 }
11544
11545 if (header) {
11546 route_vty_out_detail_header(
11547 vty, bgp, bgp_node, pfx_rd,
11548 AFI_IP, safi, json_header);
11549 header = 0;
11550 }
11551 (*display)++;
11552
11553 if (pathtype == BGP_PATH_SHOW_ALL
11554 || (pathtype == BGP_PATH_SHOW_BESTPATH
11555 && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
11556 || (pathtype == BGP_PATH_SHOW_MULTIPATH
11557 && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
11558 || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
4933eaaf 11559 route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
4027d19b 11560 safi, rpki_curr_state, json_paths);
44c69747
LK
11561 }
11562
11563 if (json && json_paths) {
11564 json_object_object_add(json_header, "paths", json_paths);
11565
11566 if (pfx_rd)
11567 json_object_object_add(json, rdbuf, json_header);
11568 }
11569}
11570
2aad8c42
MS
11571/*
11572 * Return rd based on safi
11573 */
11574static const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
11575 safi_t safi)
11576{
11577 switch (safi) {
11578 case SAFI_MPLS_VPN:
11579 case SAFI_ENCAP:
11580 case SAFI_EVPN:
11581 return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
11582 default:
11583 return NULL;
11584
11585 }
11586}
11587
718e3744 11588/* Display specified route of BGP table. */
d62a17ae 11589static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
11590 struct bgp_table *rib, const char *ip_str,
11591 afi_t afi, safi_t safi,
4027d19b 11592 enum rpki_states rpki_target_state,
d62a17ae 11593 struct prefix_rd *prd, int prefix_check,
9f049418 11594 enum bgp_path_type pathtype, bool use_json)
d62a17ae 11595{
11596 int ret;
d62a17ae 11597 int display = 0;
11598 struct prefix match;
9bcb3eef
DS
11599 struct bgp_dest *dest;
11600 struct bgp_dest *rm;
d62a17ae 11601 struct bgp_table *table;
11602 json_object *json = NULL;
11603 json_object *json_paths = NULL;
11604
11605 /* Check IP address argument. */
11606 ret = str2prefix(ip_str, &match);
11607 if (!ret) {
11608 vty_out(vty, "address is malformed\n");
11609 return CMD_WARNING;
11610 }
718e3744 11611
d62a17ae 11612 match.family = afi2family(afi);
b05a1c8b 11613
44c69747 11614 if (use_json)
d62a17ae 11615 json = json_object_new_object();
718e3744 11616
44c69747 11617 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
9bcb3eef
DS
11618 for (dest = bgp_table_top(rib); dest;
11619 dest = bgp_route_next(dest)) {
11620 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11621
9bcb3eef 11622 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 11623 continue;
9bcb3eef 11624 table = bgp_dest_get_bgp_table_info(dest);
67009e22 11625 if (!table)
ea47320b 11626 continue;
d62a17ae 11627
4953391b
DA
11628 rm = bgp_node_match(table, &match);
11629 if (rm == NULL)
ea47320b 11630 continue;
d62a17ae 11631
9bcb3eef 11632 const struct prefix *rm_p = bgp_dest_get_prefix(rm);
ea47320b 11633 if (prefix_check
b54892e0 11634 && rm_p->prefixlen != match.prefixlen) {
9bcb3eef 11635 bgp_dest_unlock_node(rm);
ea47320b
DL
11636 continue;
11637 }
d62a17ae 11638
9bcb3eef 11639 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11640 bgp, afi, safi, json, pathtype,
4027d19b 11641 &display, rpki_target_state);
44c69747 11642
9bcb3eef 11643 bgp_dest_unlock_node(rm);
44c69747
LK
11644 }
11645 } else if (safi == SAFI_EVPN) {
9bcb3eef 11646 struct bgp_dest *longest_pfx;
cded3b72 11647 bool is_exact_pfxlen_match = false;
44c69747 11648
9bcb3eef
DS
11649 for (dest = bgp_table_top(rib); dest;
11650 dest = bgp_route_next(dest)) {
11651 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 11652
9bcb3eef 11653 if (prd && memcmp(&dest_p->u.val, prd->val, 8) != 0)
44c69747 11654 continue;
9bcb3eef 11655 table = bgp_dest_get_bgp_table_info(dest);
44c69747
LK
11656 if (!table)
11657 continue;
11658
11659 longest_pfx = NULL;
cded3b72 11660 is_exact_pfxlen_match = false;
44c69747
LK
11661 /*
11662 * Search through all the prefixes for a match. The
11663 * pfx's are enumerated in ascending order of pfxlens.
11664 * So, the last pfx match is the longest match. Set
11665 * is_exact_pfxlen_match when we get exact pfxlen match
11666 */
11667 for (rm = bgp_table_top(table); rm;
11668 rm = bgp_route_next(rm)) {
b54892e0 11669 const struct prefix *rm_p =
9bcb3eef 11670 bgp_dest_get_prefix(rm);
44c69747
LK
11671 /*
11672 * Get prefixlen of the ip-prefix within type5
11673 * evpn route
11674 */
b54892e0
DS
11675 if (evpn_type5_prefix_match(rm_p, &match)
11676 && rm->info) {
44c69747
LK
11677 longest_pfx = rm;
11678 int type5_pfxlen =
b54892e0
DS
11679 bgp_evpn_get_type5_prefixlen(
11680 rm_p);
44c69747 11681 if (type5_pfxlen == match.prefixlen) {
cded3b72 11682 is_exact_pfxlen_match = true;
9bcb3eef 11683 bgp_dest_unlock_node(rm);
44c69747
LK
11684 break;
11685 }
d62a17ae 11686 }
11687 }
ea47320b 11688
44c69747
LK
11689 if (!longest_pfx)
11690 continue;
11691
11692 if (prefix_check && !is_exact_pfxlen_match)
11693 continue;
11694
11695 rm = longest_pfx;
9bcb3eef 11696 bgp_dest_lock_node(rm);
44c69747 11697
9bcb3eef 11698 bgp_show_path_info((struct prefix_rd *)dest_p, rm, vty,
b54892e0 11699 bgp, afi, safi, json, pathtype,
4027d19b 11700 &display, rpki_target_state);
44c69747 11701
9bcb3eef 11702 bgp_dest_unlock_node(rm);
d62a17ae 11703 }
98a9dbc7 11704 } else if (safi == SAFI_FLOWSPEC) {
44c69747
LK
11705 if (use_json)
11706 json_paths = json_object_new_array();
11707
63a0b7a9
PG
11708 display = bgp_flowspec_display_match_per_ip(afi, rib,
11709 &match, prefix_check,
11710 vty,
11711 use_json,
11712 json_paths);
d5f20468
SP
11713 if (use_json) {
11714 if (display)
11715 json_object_object_add(json, "paths",
11716 json_paths);
11717 else
11718 json_object_free(json_paths);
11719 }
d62a17ae 11720 } else {
4953391b
DA
11721 dest = bgp_node_match(rib, &match);
11722 if (dest != NULL) {
9bcb3eef 11723 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
d62a17ae 11724 if (!prefix_check
9bcb3eef
DS
11725 || dest_p->prefixlen == match.prefixlen) {
11726 bgp_show_path_info(NULL, dest, vty, bgp, afi,
11727 safi, json, pathtype,
4027d19b 11728 &display, rpki_target_state);
d62a17ae 11729 }
11730
9bcb3eef 11731 bgp_dest_unlock_node(dest);
d62a17ae 11732 }
11733 }
e5eee9af 11734
d62a17ae 11735 if (use_json) {
996c9314 11736 vty_out(vty, "%s\n", json_object_to_json_string_ext(
44c69747
LK
11737 json, JSON_C_TO_STRING_PRETTY |
11738 JSON_C_TO_STRING_NOSLASHESCAPE));
d62a17ae 11739 json_object_free(json);
11740 } else {
11741 if (!display) {
11742 vty_out(vty, "%% Network not in table\n");
11743 return CMD_WARNING;
11744 }
11745 }
b05a1c8b 11746
d62a17ae 11747 return CMD_SUCCESS;
718e3744 11748}
11749
fee0f4c6 11750/* Display specified route of Main RIB */
d62a17ae 11751static int bgp_show_route(struct vty *vty, struct bgp *bgp, const char *ip_str,
11752 afi_t afi, safi_t safi, struct prefix_rd *prd,
11753 int prefix_check, enum bgp_path_type pathtype,
4027d19b 11754 enum rpki_states rpki_target_state, bool use_json)
d62a17ae 11755{
9b86009a 11756 if (!bgp) {
d62a17ae 11757 bgp = bgp_get_default();
9b86009a
RW
11758 if (!bgp) {
11759 if (!use_json)
11760 vty_out(vty, "No BGP process is configured\n");
16307668
RW
11761 else
11762 vty_out(vty, "{}\n");
9b86009a
RW
11763 return CMD_WARNING;
11764 }
11765 }
d62a17ae 11766
11767 /* labeled-unicast routes live in the unicast table */
11768 if (safi == SAFI_LABELED_UNICAST)
11769 safi = SAFI_UNICAST;
11770
11771 return bgp_show_route_in_table(vty, bgp, bgp->rib[afi][safi], ip_str,
4027d19b 11772 afi, safi, rpki_target_state, prd,
8aa22bbb 11773 prefix_check, pathtype, use_json);
d62a17ae 11774}
11775
11776static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
36a206db 11777 struct cmd_token **argv, bool exact, afi_t afi,
11778 safi_t safi, bool uj)
d62a17ae 11779{
11780 struct lcommunity *lcom;
11781 struct buffer *b;
11782 int i;
11783 char *str;
11784 int first = 0;
96c81f66 11785 uint16_t show_flags = 0;
4f28b2b5 11786 int ret;
96f3485c
MK
11787
11788 if (uj)
11789 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
d62a17ae 11790
11791 b = buffer_new(1024);
11792 for (i = 0; i < argc; i++) {
11793 if (first)
11794 buffer_putc(b, ' ');
11795 else {
11796 if (strmatch(argv[i]->text, "AA:BB:CC")) {
11797 first = 1;
11798 buffer_putstr(b, argv[i]->arg);
11799 }
11800 }
11801 }
11802 buffer_putc(b, '\0');
57d187bc 11803
d62a17ae 11804 str = buffer_getstr(b);
11805 buffer_free(b);
57d187bc 11806
d62a17ae 11807 lcom = lcommunity_str2com(str);
11808 XFREE(MTYPE_TMP, str);
11809 if (!lcom) {
11810 vty_out(vty, "%% Large-community malformed\n");
11811 return CMD_WARNING;
11812 }
57d187bc 11813
4f28b2b5 11814 ret = bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11815 (exact ? bgp_show_type_lcommunity_exact
11816 : bgp_show_type_lcommunity),
11817 lcom, show_flags, RPKI_NOT_BEING_USED);
4f28b2b5
DS
11818
11819 lcommunity_free(&lcom);
11820 return ret;
57d187bc
JS
11821}
11822
d62a17ae 11823static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
36a206db 11824 const char *lcom, bool exact, afi_t afi,
11825 safi_t safi, bool uj)
57d187bc 11826{
d62a17ae 11827 struct community_list *list;
96c81f66 11828 uint16_t show_flags = 0;
96f3485c
MK
11829
11830 if (uj)
11831 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11832
57d187bc 11833
e237b0d2 11834 list = community_list_lookup(bgp_clist, lcom, 0,
d62a17ae 11835 LARGE_COMMUNITY_LIST_MASTER);
11836 if (list == NULL) {
11837 vty_out(vty, "%% %s is not a valid large-community-list name\n",
11838 lcom);
11839 return CMD_WARNING;
11840 }
57d187bc 11841
36a206db 11842 return bgp_show(vty, bgp, afi, safi,
11843 (exact ? bgp_show_type_lcommunity_list_exact
ae248832 11844 : bgp_show_type_lcommunity_list),
1e2ce4f1 11845 list, show_flags, RPKI_NOT_BEING_USED);
fee0f4c6 11846}
11847
52951b63
DS
11848DEFUN (show_ip_bgp_large_community_list,
11849 show_ip_bgp_large_community_list_cmd,
77a3a95e 11850 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] large-community-list <(1-500)|LCOMMUNITY_LIST_NAME> [exact-match] [json]",
52951b63
DS
11851 SHOW_STR
11852 IP_STR
11853 BGP_STR
11854 BGP_INSTANCE_HELP_STR
9bedbb1e 11855 BGP_AFI_HELP_STR
4dd6177e 11856 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11857 "Display routes matching the large-community-list\n"
11858 "large-community-list number\n"
11859 "large-community-list name\n"
36a206db 11860 "Exact match of the large-communities\n"
52951b63
DS
11861 JSON_STR)
11862{
d62a17ae 11863 afi_t afi = AFI_IP6;
11864 safi_t safi = SAFI_UNICAST;
11865 int idx = 0;
36a206db 11866 bool exact_match = 0;
4d678463 11867 struct bgp *bgp = NULL;
9f049418 11868 bool uj = use_json(argc, argv);
d62a17ae 11869
ef3364f0
DA
11870 if (uj)
11871 argc--;
4d678463 11872
ef3364f0
DA
11873 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11874 &bgp, uj);
11875 if (!idx)
11876 return CMD_WARNING;
d62a17ae 11877
11878 argv_find(argv, argc, "large-community-list", &idx);
36a206db 11879
11880 const char *clist_number_or_name = argv[++idx]->arg;
11881
11882 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
11883 exact_match = 1;
11884
11885 return bgp_show_lcommunity_list(vty, bgp, clist_number_or_name,
11886 exact_match, afi, safi, uj);
52951b63
DS
11887}
11888DEFUN (show_ip_bgp_large_community,
11889 show_ip_bgp_large_community_cmd,
36a206db 11890 "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
11891 SHOW_STR
11892 IP_STR
11893 BGP_STR
11894 BGP_INSTANCE_HELP_STR
9bedbb1e 11895 BGP_AFI_HELP_STR
4dd6177e 11896 BGP_SAFI_WITH_LABEL_HELP_STR
52951b63
DS
11897 "Display routes matching the large-communities\n"
11898 "List of large-community numbers\n"
36a206db 11899 "Exact match of the large-communities\n"
52951b63
DS
11900 JSON_STR)
11901{
d62a17ae 11902 afi_t afi = AFI_IP6;
11903 safi_t safi = SAFI_UNICAST;
11904 int idx = 0;
36a206db 11905 bool exact_match = 0;
4d678463 11906 struct bgp *bgp = NULL;
9f049418 11907 bool uj = use_json(argc, argv);
96c81f66 11908 uint16_t show_flags = 0;
d62a17ae 11909
96f3485c
MK
11910 if (uj) {
11911 argc--;
11912 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
11913 }
4d678463 11914
96f3485c
MK
11915 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11916 &bgp, uj);
11917 if (!idx)
11918 return CMD_WARNING;
d62a17ae 11919
36a206db 11920 if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
11921 if (argv_find(argv, argc, "exact-match", &idx))
11922 exact_match = 1;
11923 return bgp_show_lcommunity(vty, bgp, argc, argv,
11924 exact_match, afi, safi, uj);
11925 } else
d62a17ae 11926 return bgp_show(vty, bgp, afi, safi,
1e2ce4f1
DS
11927 bgp_show_type_lcommunity_all, NULL, show_flags,
11928 RPKI_NOT_BEING_USED);
52951b63
DS
11929}
11930
71f1613a
DA
11931static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
11932 safi_t safi, struct json_object *json_array);
d62a17ae 11933static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
893cccd0 11934 safi_t safi, struct json_object *json);
e01ca200 11935
7b2ff250 11936
9ab0cf58
PG
11937DEFUN(show_ip_bgp_statistics_all, show_ip_bgp_statistics_all_cmd,
11938 "show [ip] bgp [<view|vrf> VIEWVRFNAME] statistics-all [json]",
11939 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR
11940 "Display number of prefixes for all afi/safi\n" JSON_STR)
4265b261
PG
11941{
11942 bool uj = use_json(argc, argv);
11943 struct bgp *bgp = NULL;
ec76a1d1
DA
11944 safi_t safi = SAFI_UNICAST;
11945 afi_t afi = AFI_IP6;
4265b261 11946 int idx = 0;
6c9d22e2
PG
11947 struct json_object *json_all = NULL;
11948 struct json_object *json_afi_safi = NULL;
4265b261
PG
11949
11950 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
11951 &bgp, false);
71f1613a 11952 if (!idx)
4265b261 11953 return CMD_WARNING;
6c9d22e2 11954
4265b261 11955 if (uj)
6c9d22e2 11956 json_all = json_object_new_object();
4265b261 11957
9ab0cf58
PG
11958 FOREACH_AFI_SAFI (afi, safi) {
11959 /*
11960 * So limit output to those afi/safi pairs that
11961 * actually have something interesting in them
11962 */
11963 if (strmatch(get_afi_safi_str(afi, safi, true),
11964 "Unknown")) {
11965 continue;
11966 }
11967 if (uj) {
11968 json_afi_safi = json_object_new_array();
11969 json_object_object_add(
11970 json_all,
11971 get_afi_safi_str(afi, safi, true),
11972 json_afi_safi);
11973 } else {
11974 json_afi_safi = NULL;
6c9d22e2 11975 }
9ab0cf58
PG
11976
11977 bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
4265b261 11978 }
6c9d22e2
PG
11979
11980 if (uj) {
9ab0cf58
PG
11981 vty_out(vty, "%s",
11982 json_object_to_json_string_ext(
11983 json_all, JSON_C_TO_STRING_PRETTY));
6c9d22e2 11984 json_object_free(json_all);
4265b261 11985 }
6c9d22e2 11986
4265b261
PG
11987 return CMD_SUCCESS;
11988}
11989
7b2ff250 11990/* BGP route print out function without JSON */
14718643
PG
11991DEFUN (show_ip_bgp_l2vpn_evpn_statistics,
11992 show_ip_bgp_l2vpn_evpn_statistics_cmd,
9ab0cf58 11993 "show [ip] bgp [<view|vrf> VIEWVRFNAME] l2vpn evpn statistics [json]",
14718643
PG
11994 SHOW_STR
11995 IP_STR
11996 BGP_STR
11997 BGP_INSTANCE_HELP_STR
11998 L2VPN_HELP_STR
11999 EVPN_HELP_STR
12000 "BGP RIB advertisement statistics\n"
12001 JSON_STR)
12002{
ec76a1d1
DA
12003 afi_t afi = AFI_IP6;
12004 safi_t safi = SAFI_UNICAST;
14718643
PG
12005 struct bgp *bgp = NULL;
12006 int idx = 0, ret;
12007 bool uj = use_json(argc, argv);
12008 struct json_object *json_afi_safi = NULL, *json = NULL;
12009
12010 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12011 &bgp, false);
12012 if (!idx)
12013 return CMD_WARNING;
12014
12015 if (uj)
12016 json_afi_safi = json_object_new_array();
12017 else
12018 json_afi_safi = NULL;
12019
12020 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12021
12022 if (uj) {
12023 json = json_object_new_object();
12024 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12025 json_afi_safi);
12026 vty_out(vty, "%s", json_object_to_json_string_ext(
12027 json, JSON_C_TO_STRING_PRETTY));
12028 json_object_free(json);
12029 }
12030 return ret;
12031}
12032
893cccd0 12033/* BGP route print out function without JSON */
9ab0cf58
PG
12034DEFUN(show_ip_bgp_afi_safi_statistics, show_ip_bgp_afi_safi_statistics_cmd,
12035 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12036 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12037 "]]\
893cccd0 12038 statistics [json]",
9ab0cf58
PG
12039 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12040 BGP_SAFI_WITH_LABEL_HELP_STR
12041 "BGP RIB advertisement statistics\n" JSON_STR)
893cccd0 12042{
ec76a1d1
DA
12043 afi_t afi = AFI_IP6;
12044 safi_t safi = SAFI_UNICAST;
893cccd0
PG
12045 struct bgp *bgp = NULL;
12046 int idx = 0, ret;
12047 bool uj = use_json(argc, argv);
6c9d22e2 12048 struct json_object *json_afi_safi = NULL, *json = NULL;
893cccd0
PG
12049
12050 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12051 &bgp, false);
12052 if (!idx)
12053 return CMD_WARNING;
6c9d22e2 12054
893cccd0 12055 if (uj)
6c9d22e2
PG
12056 json_afi_safi = json_object_new_array();
12057 else
12058 json_afi_safi = NULL;
12059
12060 ret = bgp_table_stats(vty, bgp, afi, safi, json_afi_safi);
12061
12062 if (uj) {
12063 json = json_object_new_object();
12064 json_object_object_add(json, get_afi_safi_str(afi, safi, true),
12065 json_afi_safi);
9ab0cf58
PG
12066 vty_out(vty, "%s",
12067 json_object_to_json_string_ext(
12068 json, JSON_C_TO_STRING_PRETTY));
893cccd0
PG
12069 json_object_free(json);
12070 }
12071 return ret;
893cccd0 12072}
7b2ff250
DW
12073
12074/* BGP route print out function without JSON */
96f3485c 12075DEFPY(show_ip_bgp, show_ip_bgp_cmd,
9ab0cf58
PG
12076 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12077 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12078 "]]\
96f3485c 12079 <[all$all] dampening <parameters>\
7b2ff250
DW
12080 |route-map WORD\
12081 |prefix-list WORD\
de71d43e 12082 |filter-list AS_PATH_FILTER_NAME\
96870ecb 12083 |community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
7b2ff250
DW
12084 |A.B.C.D/M longer-prefixes\
12085 |X:X::X:X/M longer-prefixes\
893cccd0 12086 >",
9ab0cf58
PG
12087 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12088 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 12089 "Display the entries for all address families\n"
9ab0cf58
PG
12090 "Display detailed information about dampening\n"
12091 "Display detail of configured dampening parameters\n"
12092 "Display routes matching the route-map\n"
12093 "A route-map to match on\n"
12094 "Display routes conforming to the prefix-list\n"
12095 "Prefix-list name\n"
12096 "Display routes conforming to the filter-list\n"
12097 "Regular expression access list name\n"
12098 "Display routes matching the community-list\n"
12099 "community-list number\n"
12100 "community-list name\n"
12101 "Exact match of the communities\n"
12102 "IPv4 prefix\n"
12103 "Display route and more specific routes\n"
12104 "IPv6 prefix\n"
12105 "Display route and more specific routes\n")
718e3744 12106{
d62a17ae 12107 afi_t afi = AFI_IP6;
12108 safi_t safi = SAFI_UNICAST;
12109 int exact_match = 0;
d62a17ae 12110 struct bgp *bgp = NULL;
12111 int idx = 0;
96c81f66 12112 uint16_t show_flags = 0;
96f3485c
MK
12113
12114 /* [<ipv4|ipv6> [all]] */
12115 if (all) {
12116 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12117 if (argv_find(argv, argc, "ipv4", &idx))
12118 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12119
12120 if (argv_find(argv, argc, "ipv6", &idx))
12121 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12122 }
d62a17ae 12123
12124 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12125 &bgp, false);
d62a17ae 12126 if (!idx)
12127 return CMD_WARNING;
12128
d62a17ae 12129 if (argv_find(argv, argc, "dampening", &idx)) {
7b2ff250 12130 if (argv_find(argv, argc, "parameters", &idx))
96f3485c
MK
12131 return bgp_show_dampening_parameters(vty, afi, safi,
12132 show_flags);
d62a17ae 12133 }
c016b6c7 12134
d62a17ae 12135 if (argv_find(argv, argc, "prefix-list", &idx))
12136 return bgp_show_prefix_list(vty, bgp, argv[idx + 1]->arg, afi,
12137 safi, bgp_show_type_prefix_list);
12138
12139 if (argv_find(argv, argc, "filter-list", &idx))
12140 return bgp_show_filter_list(vty, bgp, argv[idx + 1]->arg, afi,
12141 safi, bgp_show_type_filter_list);
12142
d62a17ae 12143 if (argv_find(argv, argc, "route-map", &idx))
12144 return bgp_show_route_map(vty, bgp, argv[idx + 1]->arg, afi,
12145 safi, bgp_show_type_route_map);
12146
d62a17ae 12147 if (argv_find(argv, argc, "community-list", &idx)) {
12148 const char *clist_number_or_name = argv[++idx]->arg;
12149 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
12150 exact_match = 1;
12151 return bgp_show_community_list(vty, bgp, clist_number_or_name,
12152 exact_match, afi, safi);
12153 }
12154 /* prefix-longer */
12155 if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12156 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12157 return bgp_show_prefix_longer(vty, bgp, argv[idx]->arg, afi,
12158 safi,
12159 bgp_show_type_prefix_longer);
12160
7b2ff250
DW
12161 return CMD_WARNING;
12162}
12163
12164/* BGP route print out function with JSON */
a70a28a5
DA
12165DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
12166 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
12167 " [" BGP_SAFI_WITH_LABEL_CMD_STR
12168 "]]\
96f3485c 12169 [all$all]\
cf4898bc
QY
12170 [cidr-only\
12171 |dampening <flap-statistics|dampened-paths>\
12172 |community [AA:NN|local-AS|no-advertise|no-export\
12173 |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\
12174 |accept-own|accept-own-nexthop|route-filter-v6\
12175 |route-filter-v4|route-filter-translated-v6\
12176 |route-filter-translated-v4] [exact-match]\
1e2ce4f1 12177 |rpki <invalid|valid|notfound>\
7d3cae70 12178 |version (1-4294967295)\
b4ad2fae 12179 |alias ALIAS_NAME\
f280c93b 12180 ] [json$uj [detail$detail] | wide$wide]",
a70a28a5
DA
12181 SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
12182 BGP_SAFI_WITH_LABEL_HELP_STR
12183 "Display the entries for all address families\n"
12184 "Display only routes with non-natural netmasks\n"
12185 "Display detailed information about dampening\n"
12186 "Display flap statistics of routes\n"
12187 "Display paths suppressed due to dampening\n"
12188 "Display routes matching the communities\n" COMMUNITY_AANN_STR
12189 "Do not send outside local AS (well-known community)\n"
12190 "Do not advertise to any peer (well-known community)\n"
12191 "Do not export to next AS (well-known community)\n"
12192 "Graceful shutdown (well-known community)\n"
12193 "Do not export to any peer (well-known community)\n"
12194 "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
12195 "Staled Long-lived Graceful Restart VPN route (well-known community)\n"
12196 "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
12197 "Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
12198 "Should accept VPN route with local nexthop (well-known community)\n"
12199 "RT VPNv6 route filtering (well-known community)\n"
12200 "RT VPNv4 route filtering (well-known community)\n"
12201 "RT translated VPNv6 route filtering (well-known community)\n"
12202 "RT translated VPNv4 route filtering (well-known community)\n"
12203 "Exact match of the communities\n"
12204 "RPKI route types\n"
12205 "A valid path as determined by rpki\n"
12206 "A invalid path as determined by rpki\n"
12207 "A path that has no rpki data\n"
12208 "Display prefixes with matching version numbers\n"
12209 "Version number and above\n"
12210 "Display prefixes with matching BGP community alias\n"
12211 "BGP community alias\n" JSON_STR
12212 "Display detailed version of JSON output\n"
12213 "Increase table width for longer prefixes\n")
7b2ff250
DW
12214{
12215 afi_t afi = AFI_IP6;
12216 safi_t safi = SAFI_UNICAST;
12217 enum bgp_show_type sh_type = bgp_show_type_normal;
12218 struct bgp *bgp = NULL;
12219 int idx = 0;
d0086e8e 12220 int exact_match = 0;
96f3485c 12221 char *community = NULL;
7d3cae70 12222 char *prefix_version = NULL;
a70a28a5 12223 char *bgp_community_alias = NULL;
96f3485c 12224 bool first = true;
96c81f66 12225 uint16_t show_flags = 0;
4027d19b 12226 enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
96f3485c
MK
12227
12228 if (uj) {
9f049418 12229 argc--;
96f3485c
MK
12230 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12231 }
12232
f280c93b
DA
12233 if (detail)
12234 SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
12235
96f3485c
MK
12236 /* [<ipv4|ipv6> [all]] */
12237 if (all) {
12238 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
12239
12240 if (argv_find(argv, argc, "ipv4", &idx))
12241 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
12242
12243 if (argv_find(argv, argc, "ipv6", &idx))
12244 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
12245 }
12246
12247 if (wide)
12248 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
7b2ff250
DW
12249
12250 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12251 &bgp, uj);
7b2ff250
DW
12252 if (!idx)
12253 return CMD_WARNING;
12254
7b2ff250 12255 if (argv_find(argv, argc, "cidr-only", &idx))
96f3485c 12256 sh_type = bgp_show_type_cidr_only;
7b2ff250
DW
12257
12258 if (argv_find(argv, argc, "dampening", &idx)) {
12259 if (argv_find(argv, argc, "dampened-paths", &idx))
96f3485c 12260 sh_type = bgp_show_type_dampend_paths;
7b2ff250 12261 else if (argv_find(argv, argc, "flap-statistics", &idx))
96f3485c 12262 sh_type = bgp_show_type_flap_statistics;
7b2ff250
DW
12263 }
12264
12265 if (argv_find(argv, argc, "community", &idx)) {
79bc257a 12266 char *maybecomm = NULL;
d0086e8e 12267
79bc257a
RW
12268 if (idx + 1 < argc) {
12269 if (argv[idx + 1]->type == VARIABLE_TKN)
12270 maybecomm = argv[idx + 1]->arg;
12271 else
12272 maybecomm = argv[idx + 1]->text;
12273 }
12274
cf4898bc
QY
12275 if (maybecomm && !strmatch(maybecomm, "json")
12276 && !strmatch(maybecomm, "exact-match"))
12277 community = maybecomm;
d0086e8e 12278
cf4898bc
QY
12279 if (argv_find(argv, argc, "exact-match", &idx))
12280 exact_match = 1;
d0086e8e 12281
96f3485c
MK
12282 if (!community)
12283 sh_type = bgp_show_type_community_all;
12284 }
12285
1e2ce4f1
DS
12286 if (argv_find(argv, argc, "rpki", &idx)) {
12287 sh_type = bgp_show_type_rpki;
12288 if (argv_find(argv, argc, "valid", &idx))
4027d19b 12289 rpki_target_state = RPKI_VALID;
1e2ce4f1 12290 else if (argv_find(argv, argc, "invalid", &idx))
4027d19b 12291 rpki_target_state = RPKI_INVALID;
1e2ce4f1
DS
12292 }
12293
7d3cae70
DA
12294 /* Display prefixes with matching version numbers */
12295 if (argv_find(argv, argc, "version", &idx)) {
12296 sh_type = bgp_show_type_prefix_version;
12297 prefix_version = argv[idx + 1]->arg;
12298 }
12299
a70a28a5
DA
12300 /* Display prefixes with matching BGP community alias */
12301 if (argv_find(argv, argc, "alias", &idx)) {
12302 sh_type = bgp_show_type_community_alias;
12303 bgp_community_alias = argv[idx + 1]->arg;
12304 }
12305
96f3485c
MK
12306 if (!all) {
12307 /* show bgp: AFI_IP6, show ip bgp: AFI_IP */
cf4898bc
QY
12308 if (community)
12309 return bgp_show_community(vty, bgp, community,
96f3485c
MK
12310 exact_match, afi, safi,
12311 show_flags);
7d3cae70
DA
12312 else if (prefix_version)
12313 return bgp_show(vty, bgp, afi, safi, sh_type,
12314 prefix_version, show_flags,
12315 rpki_target_state);
a70a28a5
DA
12316 else if (bgp_community_alias)
12317 return bgp_show(vty, bgp, afi, safi, sh_type,
12318 bgp_community_alias, show_flags,
12319 rpki_target_state);
cf4898bc 12320 else
96f3485c 12321 return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
4027d19b 12322 show_flags, rpki_target_state);
96f3485c
MK
12323 } else {
12324 /* show <ip> bgp ipv4 all: AFI_IP, show <ip> bgp ipv6 all:
12325 * AFI_IP6 */
12326
12327 if (uj)
12328 vty_out(vty, "{\n");
12329
12330 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12331 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
12332 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
12333 ? AFI_IP
12334 : AFI_IP6;
12335 FOREACH_SAFI (safi) {
96f3485c
MK
12336 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12337 continue;
12338
12339 if (uj) {
12340 if (first)
12341 first = false;
12342 else
12343 vty_out(vty, ",\n");
12344 vty_out(vty, "\"%s\":{\n",
12345 get_afi_safi_str(afi, safi,
12346 true));
12347 } else
12348 vty_out(vty,
12349 "\nFor address family: %s\n",
12350 get_afi_safi_str(afi, safi,
12351 false));
12352
12353 if (community)
12354 bgp_show_community(vty, bgp, community,
12355 exact_match, afi,
12356 safi, show_flags);
7d3cae70
DA
12357 else if (prefix_version)
12358 return bgp_show(vty, bgp, afi, safi,
12359 sh_type, prefix_version,
12360 show_flags,
12361 rpki_target_state);
a70a28a5
DA
12362 else if (bgp_community_alias)
12363 return bgp_show(
12364 vty, bgp, afi, safi, sh_type,
12365 bgp_community_alias, show_flags,
12366 rpki_target_state);
96f3485c
MK
12367 else
12368 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12369 NULL, show_flags,
4027d19b 12370 rpki_target_state);
96f3485c
MK
12371 if (uj)
12372 vty_out(vty, "}\n");
12373 }
12374 } else {
12375 /* show <ip> bgp all: for each AFI and SAFI*/
12376 FOREACH_AFI_SAFI (afi, safi) {
96f3485c
MK
12377 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
12378 continue;
12379
12380 if (uj) {
12381 if (first)
12382 first = false;
12383 else
12384 vty_out(vty, ",\n");
d0086e8e 12385
96f3485c
MK
12386 vty_out(vty, "\"%s\":{\n",
12387 get_afi_safi_str(afi, safi,
12388 true));
12389 } else
12390 vty_out(vty,
12391 "\nFor address family: %s\n",
12392 get_afi_safi_str(afi, safi,
12393 false));
12394
12395 if (community)
12396 bgp_show_community(vty, bgp, community,
12397 exact_match, afi,
12398 safi, show_flags);
7d3cae70
DA
12399 else if (prefix_version)
12400 return bgp_show(vty, bgp, afi, safi,
12401 sh_type, prefix_version,
12402 show_flags,
12403 rpki_target_state);
96f3485c
MK
12404 else
12405 bgp_show(vty, bgp, afi, safi, sh_type,
1e2ce4f1 12406 NULL, show_flags,
4027d19b 12407 rpki_target_state);
96f3485c
MK
12408 if (uj)
12409 vty_out(vty, "}\n");
12410 }
12411 }
12412 if (uj)
12413 vty_out(vty, "}\n");
12414 }
12415 return CMD_SUCCESS;
a636c635 12416}
47fc97cc 12417
718e3744 12418DEFUN (show_ip_bgp_route,
12419 show_ip_bgp_route_cmd,
8aa22bbb 12420 "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 12421 SHOW_STR
12422 IP_STR
12423 BGP_STR
a636c635 12424 BGP_INSTANCE_HELP_STR
4f280b15 12425 BGP_AFI_HELP_STR
4dd6177e 12426 BGP_SAFI_WITH_LABEL_HELP_STR
b05a1c8b 12427 "Network in the BGP routing table to display\n"
0c7b1b01 12428 "IPv4 prefix\n"
8c3deaae 12429 "Network in the BGP routing table to display\n"
0c7b1b01 12430 "IPv6 prefix\n"
4092b06c 12431 "Display only the bestpath\n"
b05a1c8b 12432 "Display only multipaths\n"
8aa22bbb
DS
12433 "Display only paths that match the specified rpki state\n"
12434 "A valid path as determined by rpki\n"
12435 "A invalid path as determined by rpki\n"
12436 "A path that has no rpki data\n"
9973d184 12437 JSON_STR)
4092b06c 12438{
d62a17ae 12439 int prefix_check = 0;
ae19d7dd 12440
d62a17ae 12441 afi_t afi = AFI_IP6;
12442 safi_t safi = SAFI_UNICAST;
12443 char *prefix = NULL;
12444 struct bgp *bgp = NULL;
12445 enum bgp_path_type path_type;
9f049418 12446 bool uj = use_json(argc, argv);
b05a1c8b 12447
d62a17ae 12448 int idx = 0;
ae19d7dd 12449
d62a17ae 12450 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12451 &bgp, uj);
d62a17ae 12452 if (!idx)
12453 return CMD_WARNING;
c41247f5 12454
d62a17ae 12455 if (!bgp) {
12456 vty_out(vty,
12457 "Specified 'all' vrf's but this command currently only works per view/vrf\n");
12458 return CMD_WARNING;
12459 }
a636c635 12460
d62a17ae 12461 /* <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> */
12462 if (argv_find(argv, argc, "A.B.C.D", &idx)
12463 || argv_find(argv, argc, "X:X::X:X", &idx))
12464 prefix_check = 0;
12465 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)
12466 || argv_find(argv, argc, "X:X::X:X/M", &idx))
12467 prefix_check = 1;
12468
12469 if ((argv[idx]->type == IPV6_TKN || argv[idx]->type == IPV6_PREFIX_TKN)
12470 && afi != AFI_IP6) {
12471 vty_out(vty,
12472 "%% Cannot specify IPv6 address or prefix with IPv4 AFI\n");
12473 return CMD_WARNING;
12474 }
12475 if ((argv[idx]->type == IPV4_TKN || argv[idx]->type == IPV4_PREFIX_TKN)
12476 && afi != AFI_IP) {
12477 vty_out(vty,
12478 "%% Cannot specify IPv4 address or prefix with IPv6 AFI\n");
12479 return CMD_WARNING;
12480 }
12481
12482 prefix = argv[idx]->arg;
12483
12484 /* [<bestpath|multipath>] */
12485 if (argv_find(argv, argc, "bestpath", &idx))
360660c6 12486 path_type = BGP_PATH_SHOW_BESTPATH;
d62a17ae 12487 else if (argv_find(argv, argc, "multipath", &idx))
360660c6 12488 path_type = BGP_PATH_SHOW_MULTIPATH;
d62a17ae 12489 else
360660c6 12490 path_type = BGP_PATH_SHOW_ALL;
a636c635 12491
d62a17ae 12492 return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check,
8aa22bbb 12493 path_type, RPKI_NOT_BEING_USED, uj);
4092b06c
DS
12494}
12495
8c3deaae
QY
12496DEFUN (show_ip_bgp_regexp,
12497 show_ip_bgp_regexp_cmd,
3e5b31b3 12498 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] regexp REGEX [json]",
8c3deaae
QY
12499 SHOW_STR
12500 IP_STR
12501 BGP_STR
b00b230a 12502 BGP_INSTANCE_HELP_STR
4f280b15 12503 BGP_AFI_HELP_STR
4dd6177e 12504 BGP_SAFI_WITH_LABEL_HELP_STR
8c3deaae 12505 "Display routes matching the AS path regular expression\n"
3e5b31b3
DA
12506 "A regular-expression (1234567890_^|[,{}() ]$*+.?-\\) to match the BGP AS paths\n"
12507 JSON_STR)
8c3deaae 12508{
d62a17ae 12509 afi_t afi = AFI_IP6;
12510 safi_t safi = SAFI_UNICAST;
12511 struct bgp *bgp = NULL;
3e5b31b3
DA
12512 bool uj = use_json(argc, argv);
12513 char *regstr = NULL;
8c3deaae 12514
d62a17ae 12515 int idx = 0;
12516 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 12517 &bgp, false);
d62a17ae 12518 if (!idx)
12519 return CMD_WARNING;
8c3deaae 12520
d62a17ae 12521 // get index of regex
3e5b31b3
DA
12522 if (argv_find(argv, argc, "REGEX", &idx))
12523 regstr = argv[idx]->arg;
8c3deaae 12524
5f71d11c 12525 assert(regstr);
3e5b31b3
DA
12526 return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
12527 bgp_show_type_regexp, uj);
8c3deaae
QY
12528}
12529
ae248832 12530DEFPY (show_ip_bgp_instance_all,
a636c635 12531 show_ip_bgp_instance_all_cmd,
ae248832 12532 "show [ip] bgp <view|vrf> all ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] [json$uj | wide$wide]",
4092b06c 12533 SHOW_STR
a636c635 12534 IP_STR
4092b06c 12535 BGP_STR
a636c635 12536 BGP_INSTANCE_ALL_HELP_STR
4f280b15 12537 BGP_AFI_HELP_STR
4dd6177e 12538 BGP_SAFI_WITH_LABEL_HELP_STR
ae248832
MK
12539 JSON_STR
12540 "Increase table width for longer prefixes\n")
4092b06c 12541{
54d05dea 12542 afi_t afi = AFI_IP6;
d62a17ae 12543 safi_t safi = SAFI_UNICAST;
12544 struct bgp *bgp = NULL;
d62a17ae 12545 int idx = 0;
96c81f66 12546 uint16_t show_flags = 0;
ae19d7dd 12547
96f3485c 12548 if (uj) {
d62a17ae 12549 argc--;
96f3485c
MK
12550 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
12551 }
12552
12553 if (wide)
12554 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
e3e29b32 12555
9f049418
DS
12556 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
12557 &bgp, uj);
12558 if (!idx)
12559 return CMD_WARNING;
12560
96f3485c 12561 bgp_show_all_instances_routes_vty(vty, afi, safi, show_flags);
d62a17ae 12562 return CMD_SUCCESS;
e3e29b32
LB
12563}
12564
a4d82a8a 12565static int bgp_show_regexp(struct vty *vty, struct bgp *bgp, const char *regstr,
3e5b31b3
DA
12566 afi_t afi, safi_t safi, enum bgp_show_type type,
12567 bool use_json)
718e3744 12568{
d62a17ae 12569 regex_t *regex;
12570 int rc;
96c81f66 12571 uint16_t show_flags = 0;
96f3485c
MK
12572
12573 if (use_json)
12574 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
e3e29b32 12575
c3900853 12576 if (!config_bgp_aspath_validate(regstr)) {
157a43d5 12577 vty_out(vty, "Invalid character in REGEX %s\n",
c3900853
DA
12578 regstr);
12579 return CMD_WARNING_CONFIG_FAILED;
12580 }
12581
d62a17ae 12582 regex = bgp_regcomp(regstr);
12583 if (!regex) {
12584 vty_out(vty, "Can't compile regexp %s\n", regstr);
12585 return CMD_WARNING;
12586 }
a636c635 12587
1e2ce4f1
DS
12588 rc = bgp_show(vty, bgp, afi, safi, type, regex, show_flags,
12589 RPKI_NOT_BEING_USED);
d62a17ae 12590 bgp_regex_free(regex);
12591 return rc;
e3e29b32
LB
12592}
12593
d62a17ae 12594static int bgp_show_prefix_list(struct vty *vty, struct bgp *bgp,
12595 const char *prefix_list_str, afi_t afi,
12596 safi_t safi, enum bgp_show_type type)
e3e29b32 12597{
d62a17ae 12598 struct prefix_list *plist;
96c81f66 12599 uint16_t show_flags = 0;
718e3744 12600
d62a17ae 12601 plist = prefix_list_lookup(afi, prefix_list_str);
12602 if (plist == NULL) {
12603 vty_out(vty, "%% %s is not a valid prefix-list name\n",
12604 prefix_list_str);
12605 return CMD_WARNING;
12606 }
718e3744 12607
1e2ce4f1
DS
12608 return bgp_show(vty, bgp, afi, safi, type, plist, show_flags,
12609 RPKI_NOT_BEING_USED);
4092b06c
DS
12610}
12611
d62a17ae 12612static int bgp_show_filter_list(struct vty *vty, struct bgp *bgp,
12613 const char *filter, afi_t afi, safi_t safi,
12614 enum bgp_show_type type)
4092b06c 12615{
d62a17ae 12616 struct as_list *as_list;
96c81f66 12617 uint16_t show_flags = 0;
718e3744 12618
d62a17ae 12619 as_list = as_list_lookup(filter);
12620 if (as_list == NULL) {
12621 vty_out(vty, "%% %s is not a valid AS-path access-list name\n",
12622 filter);
12623 return CMD_WARNING;
12624 }
a636c635 12625
1e2ce4f1
DS
12626 return bgp_show(vty, bgp, afi, safi, type, as_list, show_flags,
12627 RPKI_NOT_BEING_USED);
718e3744 12628}
12629
d62a17ae 12630static int bgp_show_route_map(struct vty *vty, struct bgp *bgp,
12631 const char *rmap_str, afi_t afi, safi_t safi,
12632 enum bgp_show_type type)
718e3744 12633{
d62a17ae 12634 struct route_map *rmap;
96c81f66 12635 uint16_t show_flags = 0;
bb46e94f 12636
d62a17ae 12637 rmap = route_map_lookup_by_name(rmap_str);
12638 if (!rmap) {
12639 vty_out(vty, "%% %s is not a valid route-map name\n", rmap_str);
12640 return CMD_WARNING;
12641 }
12642
1e2ce4f1
DS
12643 return bgp_show(vty, bgp, afi, safi, type, rmap, show_flags,
12644 RPKI_NOT_BEING_USED);
d62a17ae 12645}
12646
7f323236
DW
12647static int bgp_show_community(struct vty *vty, struct bgp *bgp,
12648 const char *comstr, int exact, afi_t afi,
96c81f66 12649 safi_t safi, uint16_t show_flags)
d62a17ae 12650{
12651 struct community *com;
d62a17ae 12652 int ret = 0;
12653
7f323236 12654 com = community_str2com(comstr);
d62a17ae 12655 if (!com) {
7f323236 12656 vty_out(vty, "%% Community malformed: %s\n", comstr);
d62a17ae 12657 return CMD_WARNING;
12658 }
12659
12660 ret = bgp_show(vty, bgp, afi, safi,
12661 (exact ? bgp_show_type_community_exact
12662 : bgp_show_type_community),
1e2ce4f1 12663 com, show_flags, RPKI_NOT_BEING_USED);
3c1f53de 12664 community_free(&com);
46c3ce83 12665
d62a17ae 12666 return ret;
718e3744 12667}
12668
d62a17ae 12669static int bgp_show_community_list(struct vty *vty, struct bgp *bgp,
12670 const char *com, int exact, afi_t afi,
12671 safi_t safi)
50ef26d4 12672{
d62a17ae 12673 struct community_list *list;
96c81f66 12674 uint16_t show_flags = 0;
50ef26d4 12675
e237b0d2 12676 list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER);
d62a17ae 12677 if (list == NULL) {
12678 vty_out(vty, "%% %s is not a valid community-list name\n", com);
12679 return CMD_WARNING;
12680 }
718e3744 12681
d62a17ae 12682 return bgp_show(vty, bgp, afi, safi,
12683 (exact ? bgp_show_type_community_list_exact
12684 : bgp_show_type_community_list),
1e2ce4f1 12685 list, show_flags, RPKI_NOT_BEING_USED);
50ef26d4 12686}
12687
d62a17ae 12688static int bgp_show_prefix_longer(struct vty *vty, struct bgp *bgp,
12689 const char *prefix, afi_t afi, safi_t safi,
12690 enum bgp_show_type type)
718e3744 12691{
d62a17ae 12692 int ret;
12693 struct prefix *p;
96c81f66 12694 uint16_t show_flags = 0;
47fc97cc 12695
d62a17ae 12696 p = prefix_new();
95cbbd2a 12697
d62a17ae 12698 ret = str2prefix(prefix, p);
12699 if (!ret) {
12700 vty_out(vty, "%% Malformed Prefix\n");
12701 return CMD_WARNING;
12702 }
47e9b292 12703
1e2ce4f1
DS
12704 ret = bgp_show(vty, bgp, afi, safi, type, p, show_flags,
12705 RPKI_NOT_BEING_USED);
63265b5c 12706 prefix_free(&p);
d62a17ae 12707 return ret;
12708}
12709
d62a17ae 12710enum bgp_stats {
12711 BGP_STATS_MAXBITLEN = 0,
12712 BGP_STATS_RIB,
12713 BGP_STATS_PREFIXES,
12714 BGP_STATS_TOTPLEN,
12715 BGP_STATS_UNAGGREGATEABLE,
12716 BGP_STATS_MAX_AGGREGATEABLE,
12717 BGP_STATS_AGGREGATES,
12718 BGP_STATS_SPACE,
12719 BGP_STATS_ASPATH_COUNT,
12720 BGP_STATS_ASPATH_MAXHOPS,
12721 BGP_STATS_ASPATH_TOTHOPS,
12722 BGP_STATS_ASPATH_MAXSIZE,
12723 BGP_STATS_ASPATH_TOTSIZE,
12724 BGP_STATS_ASN_HIGHEST,
12725 BGP_STATS_MAX,
a636c635 12726};
2815e61f 12727
9ab0cf58 12728#define TABLE_STATS_IDX_VTY 0
893cccd0
PG
12729#define TABLE_STATS_IDX_JSON 1
12730
12731static const char *table_stats_strs[][2] = {
6c9d22e2
PG
12732 [BGP_STATS_PREFIXES] = {"Total Prefixes", "totalPrefixes"},
12733 [BGP_STATS_TOTPLEN] = {"Average prefix length", "averagePrefixLength"},
12734 [BGP_STATS_RIB] = {"Total Advertisements", "totalAdvertisements"},
9ab0cf58
PG
12735 [BGP_STATS_UNAGGREGATEABLE] = {"Unaggregateable prefixes",
12736 "unaggregateablePrefixes"},
12737 [BGP_STATS_MAX_AGGREGATEABLE] = {"Maximum aggregateable prefixes",
12738 "maximumAggregateablePrefixes"},
12739 [BGP_STATS_AGGREGATES] = {"BGP Aggregate advertisements",
12740 "bgpAggregateAdvertisements"},
6c9d22e2
PG
12741 [BGP_STATS_SPACE] = {"Address space advertised",
12742 "addressSpaceAdvertised"},
9ab0cf58
PG
12743 [BGP_STATS_ASPATH_COUNT] = {"Advertisements with paths",
12744 "advertisementsWithPaths"},
12745 [BGP_STATS_ASPATH_MAXHOPS] = {"Longest AS-Path (hops)",
12746 "longestAsPath"},
12747 [BGP_STATS_ASPATH_MAXSIZE] = {"Largest AS-Path (bytes)",
12748 "largestAsPath"},
12749 [BGP_STATS_ASPATH_TOTHOPS] = {"Average AS-Path length (hops)",
12750 "averageAsPathLengthHops"},
12751 [BGP_STATS_ASPATH_TOTSIZE] = {"Average AS-Path size (bytes)",
12752 "averageAsPathSizeBytes"},
12753 [BGP_STATS_ASN_HIGHEST] = {"Highest public ASN", "highestPublicAsn"},
893cccd0 12754 [BGP_STATS_MAX] = {NULL, NULL}
a636c635 12755};
2815e61f 12756
d62a17ae 12757struct bgp_table_stats {
12758 struct bgp_table *table;
12759 unsigned long long counts[BGP_STATS_MAX];
8d0ab76d 12760 double total_space;
ff7924f6
PJ
12761};
12762
9bcb3eef 12763static void bgp_table_stats_rn(struct bgp_dest *dest, struct bgp_dest *top,
9c14ec72 12764 struct bgp_table_stats *ts, unsigned int space)
2815e61f 12765{
9bcb3eef 12766 struct bgp_dest *pdest = bgp_dest_parent_nolock(dest);
9c14ec72 12767 struct bgp_path_info *pi;
b54892e0 12768 const struct prefix *rn_p;
d62a17ae 12769
9bcb3eef 12770 if (!bgp_dest_has_bgp_path_info_data(dest))
9c14ec72 12771 return;
d62a17ae 12772
9bcb3eef 12773 rn_p = bgp_dest_get_prefix(dest);
9c14ec72 12774 ts->counts[BGP_STATS_PREFIXES]++;
b54892e0 12775 ts->counts[BGP_STATS_TOTPLEN] += rn_p->prefixlen;
ff7924f6 12776
9c14ec72 12777 /* check if the prefix is included by any other announcements */
9bcb3eef
DS
12778 while (pdest && !bgp_dest_has_bgp_path_info_data(pdest))
12779 pdest = bgp_dest_parent_nolock(pdest);
d62a17ae 12780
9bcb3eef 12781 if (pdest == NULL || pdest == top) {
9c14ec72
RW
12782 ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
12783 /* announced address space */
12784 if (space)
b54892e0 12785 ts->total_space += pow(2.0, space - rn_p->prefixlen);
9bcb3eef 12786 } else if (bgp_dest_has_bgp_path_info_data(pdest))
9c14ec72 12787 ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
d62a17ae 12788
9c14ec72 12789
9bcb3eef 12790 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
9c14ec72
RW
12791 ts->counts[BGP_STATS_RIB]++;
12792
05864da7
DS
12793 if (CHECK_FLAG(pi->attr->flag,
12794 ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)))
9c14ec72
RW
12795 ts->counts[BGP_STATS_AGGREGATES]++;
12796
12797 /* as-path stats */
05864da7 12798 if (pi->attr->aspath) {
9c14ec72
RW
12799 unsigned int hops = aspath_count_hops(pi->attr->aspath);
12800 unsigned int size = aspath_size(pi->attr->aspath);
12801 as_t highest = aspath_highest(pi->attr->aspath);
12802
12803 ts->counts[BGP_STATS_ASPATH_COUNT]++;
12804
12805 if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
12806 ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
12807
12808 if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
12809 ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
12810
12811 ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
12812 ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
9c14ec72
RW
12813 if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
12814 ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
12815 }
12816 }
12817}
12818
12819static int bgp_table_stats_walker(struct thread *t)
12820{
9bcb3eef
DS
12821 struct bgp_dest *dest, *ndest;
12822 struct bgp_dest *top;
9c14ec72
RW
12823 struct bgp_table_stats *ts = THREAD_ARG(t);
12824 unsigned int space = 0;
12825
12826 if (!(top = bgp_table_top(ts->table)))
12827 return 0;
12828
12829 switch (ts->table->afi) {
12830 case AFI_IP:
12831 space = IPV4_MAX_BITLEN;
12832 break;
12833 case AFI_IP6:
12834 space = IPV6_MAX_BITLEN;
12835 break;
3ba7b4af
TA
12836 case AFI_L2VPN:
12837 space = EVPN_ROUTE_PREFIXLEN;
12838 break;
9c14ec72
RW
12839 default:
12840 return 0;
12841 }
12842
12843 ts->counts[BGP_STATS_MAXBITLEN] = space;
12844
9bcb3eef 12845 for (dest = top; dest; dest = bgp_route_next(dest)) {
9ab0cf58
PG
12846 if (ts->table->safi == SAFI_MPLS_VPN
12847 || ts->table->safi == SAFI_ENCAP
12848 || ts->table->safi == SAFI_EVPN) {
9c14ec72
RW
12849 struct bgp_table *table;
12850
9bcb3eef 12851 table = bgp_dest_get_bgp_table_info(dest);
9c14ec72
RW
12852 if (!table)
12853 continue;
12854
12855 top = bgp_table_top(table);
9bcb3eef
DS
12856 for (ndest = bgp_table_top(table); ndest;
12857 ndest = bgp_route_next(ndest))
12858 bgp_table_stats_rn(ndest, top, ts, space);
9c14ec72 12859 } else {
9bcb3eef 12860 bgp_table_stats_rn(dest, top, ts, space);
d62a17ae 12861 }
12862 }
9c14ec72 12863
d62a17ae 12864 return 0;
2815e61f 12865}
ff7924f6 12866
71f1613a
DA
12867static void bgp_table_stats_all(struct vty *vty, afi_t afi, safi_t safi,
12868 struct json_object *json_array)
12869{
12870 struct listnode *node, *nnode;
12871 struct bgp *bgp;
12872
12873 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
12874 bgp_table_stats_single(vty, bgp, afi, safi, json_array);
12875}
12876
12877static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
12878 safi_t safi, struct json_object *json_array)
2815e61f 12879{
d62a17ae 12880 struct bgp_table_stats ts;
12881 unsigned int i;
893cccd0
PG
12882 int ret = CMD_SUCCESS;
12883 char temp_buf[20];
6c9d22e2
PG
12884 struct json_object *json = NULL;
12885
12886 if (json_array)
12887 json = json_object_new_object();
019386c2 12888
d62a17ae 12889 if (!bgp->rib[afi][safi]) {
893cccd0
PG
12890 char warning_msg[50];
12891
12892 snprintf(warning_msg, sizeof(warning_msg),
9ab0cf58
PG
12893 "%% No RIB exist's for the AFI(%d)/SAFI(%d)", afi,
12894 safi);
6c9d22e2
PG
12895
12896 if (!json)
893cccd0
PG
12897 vty_out(vty, "%s\n", warning_msg);
12898 else
9ab0cf58 12899 json_object_string_add(json, "warning", warning_msg);
6c9d22e2 12900
893cccd0
PG
12901 ret = CMD_WARNING;
12902 goto end_table_stats;
d62a17ae 12903 }
019386c2 12904
893cccd0 12905 if (!json)
5290ceab
DA
12906 vty_out(vty, "BGP %s RIB statistics (%s)\n",
12907 get_afi_safi_str(afi, safi, false), bgp->name_pretty);
12908 else
12909 json_object_string_add(json, "instance", bgp->name_pretty);
019386c2 12910
d62a17ae 12911 /* labeled-unicast routes live in the unicast table */
12912 if (safi == SAFI_LABELED_UNICAST)
12913 safi = SAFI_UNICAST;
019386c2 12914
d62a17ae 12915 memset(&ts, 0, sizeof(ts));
12916 ts.table = bgp->rib[afi][safi];
12917 thread_execute(bm->master, bgp_table_stats_walker, &ts, 0);
ff7924f6 12918
d62a17ae 12919 for (i = 0; i < BGP_STATS_MAX; i++) {
9ab0cf58
PG
12920 if ((!json && !table_stats_strs[i][TABLE_STATS_IDX_VTY])
12921 || (json && !table_stats_strs[i][TABLE_STATS_IDX_JSON]))
d62a17ae 12922 continue;
12923
12924 switch (i) {
d62a17ae 12925 case BGP_STATS_ASPATH_TOTHOPS:
12926 case BGP_STATS_ASPATH_TOTSIZE:
6c9d22e2 12927 if (!json) {
9ab0cf58
PG
12928 snprintf(
12929 temp_buf, sizeof(temp_buf), "%12.2f",
12930 ts.counts[i]
12931 ? (float)ts.counts[i]
12932 / (float)ts.counts
12933 [BGP_STATS_ASPATH_COUNT]
12934 : 0);
893cccd0 12935 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12936 table_stats_strs[i]
12937 [TABLE_STATS_IDX_VTY],
893cccd0 12938 temp_buf);
9ab0cf58
PG
12939 } else {
12940 json_object_double_add(
12941 json,
12942 table_stats_strs[i]
12943 [TABLE_STATS_IDX_JSON],
12944 ts.counts[i]
12945 ? (double)ts.counts[i]
12946 / (double)ts.counts
d62a17ae 12947 [BGP_STATS_ASPATH_COUNT]
9ab0cf58
PG
12948 : 0);
12949 }
d62a17ae 12950 break;
12951 case BGP_STATS_TOTPLEN:
6c9d22e2 12952 if (!json) {
9ab0cf58
PG
12953 snprintf(
12954 temp_buf, sizeof(temp_buf), "%12.2f",
12955 ts.counts[i]
12956 ? (float)ts.counts[i]
12957 / (float)ts.counts
12958 [BGP_STATS_PREFIXES]
12959 : 0);
893cccd0 12960 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
12961 table_stats_strs[i]
12962 [TABLE_STATS_IDX_VTY],
893cccd0 12963 temp_buf);
9ab0cf58
PG
12964 } else {
12965 json_object_double_add(
12966 json,
12967 table_stats_strs[i]
12968 [TABLE_STATS_IDX_JSON],
12969 ts.counts[i]
12970 ? (double)ts.counts[i]
12971 / (double)ts.counts
d62a17ae 12972 [BGP_STATS_PREFIXES]
9ab0cf58
PG
12973 : 0);
12974 }
d62a17ae 12975 break;
12976 case BGP_STATS_SPACE:
6c9d22e2
PG
12977 if (!json) {
12978 snprintf(temp_buf, sizeof(temp_buf), "%12g",
12979 ts.total_space);
893cccd0 12980 vty_out(vty, "%-30s: %s\n",
9ab0cf58
PG
12981 table_stats_strs[i]
12982 [TABLE_STATS_IDX_VTY],
893cccd0 12983 temp_buf);
9ab0cf58
PG
12984 } else {
12985 json_object_double_add(
12986 json,
12987 table_stats_strs[i]
12988 [TABLE_STATS_IDX_JSON],
12989 (double)ts.total_space);
12990 }
8d0ab76d 12991 if (afi == AFI_IP6) {
6c9d22e2
PG
12992 if (!json) {
12993 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
12994 "%12g",
12995 ts.total_space
12996 * pow(2.0, -128 + 32));
6c9d22e2
PG
12997 vty_out(vty, "%30s: %s\n",
12998 "/32 equivalent %s\n",
12999 temp_buf);
9ab0cf58
PG
13000 } else {
13001 json_object_double_add(
13002 json, "/32equivalent",
13003 (double)(ts.total_space
13004 * pow(2.0,
13005 -128 + 32)));
13006 }
6c9d22e2
PG
13007 if (!json) {
13008 snprintf(temp_buf, sizeof(temp_buf),
9ab0cf58
PG
13009 "%12g",
13010 ts.total_space
13011 * pow(2.0, -128 + 48));
6c9d22e2
PG
13012 vty_out(vty, "%30s: %s\n",
13013 "/48 equivalent %s\n",
13014 temp_buf);
9ab0cf58
PG
13015 } else {
13016 json_object_double_add(
13017 json, "/48equivalent",
13018 (double)(ts.total_space
13019 * pow(2.0,
13020 -128 + 48)));
13021 }
8d0ab76d 13022 } else {
6c9d22e2
PG
13023 if (!json) {
13024 snprintf(temp_buf, sizeof(temp_buf),
13025 "%12.2f",
9ab0cf58
PG
13026 ts.total_space * 100.
13027 * pow(2.0, -32));
6c9d22e2 13028 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13029 "% announced ", temp_buf);
13030 } else {
13031 json_object_double_add(
13032 json, "%announced",
13033 (double)(ts.total_space * 100.
13034 * pow(2.0, -32)));
13035 }
6c9d22e2
PG
13036 if (!json) {
13037 snprintf(temp_buf, sizeof(temp_buf),
13038 "%12.2f",
9ab0cf58
PG
13039 ts.total_space
13040 * pow(2.0, -32 + 8));
6c9d22e2
PG
13041 vty_out(vty, "%30s: %s\n",
13042 "/8 equivalent ", temp_buf);
9ab0cf58
PG
13043 } else {
13044 json_object_double_add(
13045 json, "/8equivalent",
13046 (double)(ts.total_space
13047 * pow(2.0, -32 + 8)));
13048 }
6c9d22e2
PG
13049 if (!json) {
13050 snprintf(temp_buf, sizeof(temp_buf),
13051 "%12.2f",
9ab0cf58
PG
13052 ts.total_space
13053 * pow(2.0, -32 + 24));
6c9d22e2 13054 vty_out(vty, "%30s: %s\n",
9ab0cf58
PG
13055 "/24 equivalent ", temp_buf);
13056 } else {
13057 json_object_double_add(
13058 json, "/24equivalent",
13059 (double)(ts.total_space
13060 * pow(2.0, -32 + 24)));
13061 }
8d0ab76d 13062 }
d62a17ae 13063 break;
13064 default:
6c9d22e2
PG
13065 if (!json) {
13066 snprintf(temp_buf, sizeof(temp_buf), "%12llu",
13067 ts.counts[i]);
893cccd0 13068 vty_out(vty, "%-30s: %s",
9ab0cf58
PG
13069 table_stats_strs[i]
13070 [TABLE_STATS_IDX_VTY],
13071 temp_buf);
13072 } else {
13073 json_object_int_add(
13074 json,
13075 table_stats_strs[i]
13076 [TABLE_STATS_IDX_JSON],
13077 ts.counts[i]);
13078 }
d62a17ae 13079 }
893cccd0
PG
13080 if (!json)
13081 vty_out(vty, "\n");
d62a17ae 13082 }
9ab0cf58 13083end_table_stats:
6c9d22e2
PG
13084 if (json)
13085 json_object_array_add(json_array, json);
893cccd0 13086 return ret;
d62a17ae 13087}
13088
71f1613a
DA
13089static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
13090 safi_t safi, struct json_object *json_array)
13091{
13092 if (!bgp) {
13093 bgp_table_stats_all(vty, afi, safi, json_array);
13094 return CMD_SUCCESS;
13095 }
13096
13097 return bgp_table_stats_single(vty, bgp, afi, safi, json_array);
13098}
13099
d62a17ae 13100enum bgp_pcounts {
13101 PCOUNT_ADJ_IN = 0,
13102 PCOUNT_DAMPED,
13103 PCOUNT_REMOVED,
13104 PCOUNT_HISTORY,
13105 PCOUNT_STALE,
13106 PCOUNT_VALID,
13107 PCOUNT_ALL,
13108 PCOUNT_COUNTED,
7e3d9632 13109 PCOUNT_BPATH_SELECTED,
d62a17ae 13110 PCOUNT_PFCNT, /* the figure we display to users */
13111 PCOUNT_MAX,
a636c635 13112};
718e3744 13113
2b64873d 13114static const char *const pcount_strs[] = {
9d303b37
DL
13115 [PCOUNT_ADJ_IN] = "Adj-in",
13116 [PCOUNT_DAMPED] = "Damped",
13117 [PCOUNT_REMOVED] = "Removed",
13118 [PCOUNT_HISTORY] = "History",
13119 [PCOUNT_STALE] = "Stale",
13120 [PCOUNT_VALID] = "Valid",
13121 [PCOUNT_ALL] = "All RIB",
13122 [PCOUNT_COUNTED] = "PfxCt counted",
7e3d9632 13123 [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
9d303b37
DL
13124 [PCOUNT_PFCNT] = "Useable",
13125 [PCOUNT_MAX] = NULL,
a636c635 13126};
718e3744 13127
d62a17ae 13128struct peer_pcounts {
13129 unsigned int count[PCOUNT_MAX];
13130 const struct peer *peer;
13131 const struct bgp_table *table;
54317cba 13132 safi_t safi;
a636c635 13133};
47fc97cc 13134
9bcb3eef 13135static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
d62a17ae 13136{
54317cba
JW
13137 const struct bgp_adj_in *ain;
13138 const struct bgp_path_info *pi;
d62a17ae 13139 const struct peer *peer = pc->peer;
13140
54317cba
JW
13141 for (ain = rn->adj_in; ain; ain = ain->next)
13142 if (ain->peer == peer)
13143 pc->count[PCOUNT_ADJ_IN]++;
d62a17ae 13144
9bcb3eef 13145 for (pi = bgp_dest_get_bgp_path_info(rn); pi; pi = pi->next) {
6f94b685 13146
54317cba
JW
13147 if (pi->peer != peer)
13148 continue;
d62a17ae 13149
54317cba 13150 pc->count[PCOUNT_ALL]++;
d62a17ae 13151
54317cba
JW
13152 if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED))
13153 pc->count[PCOUNT_DAMPED]++;
13154 if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
13155 pc->count[PCOUNT_HISTORY]++;
13156 if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED))
13157 pc->count[PCOUNT_REMOVED]++;
13158 if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
13159 pc->count[PCOUNT_STALE]++;
13160 if (CHECK_FLAG(pi->flags, BGP_PATH_VALID))
13161 pc->count[PCOUNT_VALID]++;
13162 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13163 pc->count[PCOUNT_PFCNT]++;
7e3d9632
DS
13164 if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13165 pc->count[PCOUNT_BPATH_SELECTED]++;
54317cba
JW
13166
13167 if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
13168 pc->count[PCOUNT_COUNTED]++;
13169 if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
13170 flog_err(
13171 EC_LIB_DEVELOPMENT,
13172 "Attempting to count but flags say it is unusable");
13173 } else {
40381db7 13174 if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE))
54317cba
JW
13175 flog_err(
13176 EC_LIB_DEVELOPMENT,
13177 "Not counted but flags say we should");
d62a17ae 13178 }
13179 }
54317cba
JW
13180}
13181
13182static int bgp_peer_count_walker(struct thread *t)
13183{
9bcb3eef 13184 struct bgp_dest *rn, *rm;
54317cba
JW
13185 const struct bgp_table *table;
13186 struct peer_pcounts *pc = THREAD_ARG(t);
13187
13188 if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP
13189 || pc->safi == SAFI_EVPN) {
13190 /* Special handling for 2-level routing tables. */
13191 for (rn = bgp_table_top(pc->table); rn;
13192 rn = bgp_route_next(rn)) {
9bcb3eef 13193 table = bgp_dest_get_bgp_table_info(rn);
54317cba
JW
13194 if (table != NULL)
13195 for (rm = bgp_table_top(table); rm;
13196 rm = bgp_route_next(rm))
13197 bgp_peer_count_proc(rm, pc);
13198 }
13199 } else
13200 for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn))
13201 bgp_peer_count_proc(rn, pc);
13202
d62a17ae 13203 return 0;
718e3744 13204}
13205
d62a17ae 13206static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
9f049418 13207 safi_t safi, bool use_json)
856ca177 13208{
d62a17ae 13209 struct peer_pcounts pcounts = {.peer = peer};
13210 unsigned int i;
13211 json_object *json = NULL;
13212 json_object *json_loop = NULL;
856ca177 13213
d62a17ae 13214 if (use_json) {
13215 json = json_object_new_object();
13216 json_loop = json_object_new_object();
13217 }
718e3744 13218
d62a17ae 13219 if (!peer || !peer->bgp || !peer->afc[afi][safi]
13220 || !peer->bgp->rib[afi][safi]) {
13221 if (use_json) {
13222 json_object_string_add(
13223 json, "warning",
13224 "No such neighbor or address family");
13225 vty_out(vty, "%s\n", json_object_to_json_string(json));
13226 json_object_free(json);
d5f20468 13227 json_object_free(json_loop);
d62a17ae 13228 } else
13229 vty_out(vty, "%% No such neighbor or address family\n");
13230
13231 return CMD_WARNING;
13232 }
2a71e9ce 13233
d62a17ae 13234 memset(&pcounts, 0, sizeof(pcounts));
13235 pcounts.peer = peer;
13236 pcounts.table = peer->bgp->rib[afi][safi];
54317cba 13237 pcounts.safi = safi;
d62a17ae 13238
13239 /* in-place call via thread subsystem so as to record execution time
d316210b
PZ
13240 * stats for the thread-walk (i.e. ensure this can't be blamed on
13241 * on just vty_read()).
13242 */
d62a17ae 13243 thread_execute(bm->master, bgp_peer_count_walker, &pcounts, 0);
13244
13245 if (use_json) {
13246 json_object_string_add(json, "prefixCountsFor", peer->host);
13247 json_object_string_add(json, "multiProtocol",
5cb5f4d0 13248 get_afi_safi_str(afi, safi, true));
d62a17ae 13249 json_object_int_add(json, "pfxCounter",
13250 peer->pcount[afi][safi]);
13251
13252 for (i = 0; i < PCOUNT_MAX; i++)
13253 json_object_int_add(json_loop, pcount_strs[i],
13254 pcounts.count[i]);
13255
13256 json_object_object_add(json, "ribTableWalkCounters", json_loop);
13257
13258 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13259 json_object_string_add(json, "pfxctDriftFor",
13260 peer->host);
13261 json_object_string_add(
13262 json, "recommended",
13263 "Please report this bug, with the above command output");
13264 }
996c9314
LB
13265 vty_out(vty, "%s\n", json_object_to_json_string_ext(
13266 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 13267 json_object_free(json);
13268 } else {
13269
13270 if (peer->hostname
892fedb6 13271 && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
d62a17ae 13272 vty_out(vty, "Prefix counts for %s/%s, %s\n",
13273 peer->hostname, peer->host,
5cb5f4d0 13274 get_afi_safi_str(afi, safi, false));
d62a17ae 13275 } else {
13276 vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
5cb5f4d0 13277 get_afi_safi_str(afi, safi, false));
d62a17ae 13278 }
13279
6cde4b45 13280 vty_out(vty, "PfxCt: %u\n", peer->pcount[afi][safi]);
d62a17ae 13281 vty_out(vty, "\nCounts from RIB table walk:\n\n");
13282
13283 for (i = 0; i < PCOUNT_MAX; i++)
13284 vty_out(vty, "%20s: %-10d\n", pcount_strs[i],
13285 pcounts.count[i]);
13286
13287 if (pcounts.count[PCOUNT_PFCNT] != peer->pcount[afi][safi]) {
13288 vty_out(vty, "%s [pcount] PfxCt drift!\n", peer->host);
13289 vty_out(vty,
13290 "Please report this bug, with the above command output\n");
13291 }
13292 }
13293
13294 return CMD_SUCCESS;
718e3744 13295}
13296
a636c635
DW
13297DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
13298 show_ip_bgp_instance_neighbor_prefix_counts_cmd,
3efd0893 13299 "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 13300 SHOW_STR
13301 IP_STR
13302 BGP_STR
8386ac43 13303 BGP_INSTANCE_HELP_STR
9bedbb1e
DW
13304 BGP_AFI_HELP_STR
13305 BGP_SAFI_HELP_STR
0b16f239
DS
13306 "Detailed information on TCP and BGP neighbor connections\n"
13307 "Neighbor to display information about\n"
13308 "Neighbor to display information about\n"
91d37724 13309 "Neighbor on BGP configured interface\n"
a636c635 13310 "Display detailed prefix count information\n"
9973d184 13311 JSON_STR)
0b16f239 13312{
d62a17ae 13313 afi_t afi = AFI_IP6;
13314 safi_t safi = SAFI_UNICAST;
13315 struct peer *peer;
13316 int idx = 0;
13317 struct bgp *bgp = NULL;
9f049418
DS
13318 bool uj = use_json(argc, argv);
13319
13320 if (uj)
13321 argc--;
856ca177 13322
d62a17ae 13323 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 13324 &bgp, uj);
d62a17ae 13325 if (!idx)
13326 return CMD_WARNING;
0b16f239 13327
d62a17ae 13328 argv_find(argv, argc, "neighbors", &idx);
13329 peer = peer_lookup_in_view(vty, bgp, argv[idx + 1]->arg, uj);
13330 if (!peer)
13331 return CMD_WARNING;
bb46e94f 13332
29c8d9da 13333 return bgp_peer_counts(vty, peer, afi, safi, uj);
a636c635 13334}
0b16f239 13335
d6902373
PG
13336#ifdef KEEP_OLD_VPN_COMMANDS
13337DEFUN (show_ip_bgp_vpn_neighbor_prefix_counts,
13338 show_ip_bgp_vpn_neighbor_prefix_counts_cmd,
13339 "show [ip] bgp <vpnv4|vpnv6> all neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
2a71e9ce
TP
13340 SHOW_STR
13341 IP_STR
13342 BGP_STR
d6902373 13343 BGP_VPNVX_HELP_STR
91d37724 13344 "Display information about all VPNv4 NLRIs\n"
2a71e9ce
TP
13345 "Detailed information on TCP and BGP neighbor connections\n"
13346 "Neighbor to display information about\n"
13347 "Neighbor to display information about\n"
91d37724 13348 "Neighbor on BGP configured interface\n"
a636c635 13349 "Display detailed prefix count information\n"
9973d184 13350 JSON_STR)
a636c635 13351{
d62a17ae 13352 int idx_peer = 6;
13353 struct peer *peer;
9f049418 13354 bool uj = use_json(argc, argv);
a636c635 13355
d62a17ae 13356 peer = peer_lookup_in_view(vty, NULL, argv[idx_peer]->arg, uj);
13357 if (!peer)
13358 return CMD_WARNING;
13359
13360 return bgp_peer_counts(vty, peer, AFI_IP, SAFI_MPLS_VPN, uj);
a636c635
DW
13361}
13362
d6902373
PG
13363DEFUN (show_ip_bgp_vpn_all_route_prefix,
13364 show_ip_bgp_vpn_all_route_prefix_cmd,
13365 "show [ip] bgp <vpnv4|vpnv6> all <A.B.C.D|A.B.C.D/M> [json]",
91d37724
QY
13366 SHOW_STR
13367 IP_STR
13368 BGP_STR
d6902373 13369 BGP_VPNVX_HELP_STR
91d37724
QY
13370 "Display information about all VPNv4 NLRIs\n"
13371 "Network in the BGP routing table to display\n"
3a2d747c 13372 "Network in the BGP routing table to display\n"
9973d184 13373 JSON_STR)
91d37724 13374{
d62a17ae 13375 int idx = 0;
13376 char *network = NULL;
13377 struct bgp *bgp = bgp_get_default();
13378 if (!bgp) {
13379 vty_out(vty, "Can't find default instance\n");
13380 return CMD_WARNING;
13381 }
87e34b58 13382
d62a17ae 13383 if (argv_find(argv, argc, "A.B.C.D", &idx))
13384 network = argv[idx]->arg;
13385 else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
13386 network = argv[idx]->arg;
13387 else {
13388 vty_out(vty, "Unable to figure out Network\n");
13389 return CMD_WARNING;
13390 }
87e34b58 13391
d62a17ae 13392 return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0,
4ad4ae64
TA
13393 BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
13394 use_json(argc, argv));
91d37724 13395}
d6902373 13396#endif /* KEEP_OLD_VPN_COMMANDS */
91d37724 13397
44c69747
LK
13398DEFUN (show_bgp_l2vpn_evpn_route_prefix,
13399 show_bgp_l2vpn_evpn_route_prefix_cmd,
13400 "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
4c63a661 13401 SHOW_STR
4c63a661
PG
13402 BGP_STR
13403 L2VPN_HELP_STR
13404 EVPN_HELP_STR
44c69747
LK
13405 "Network in the BGP routing table to display\n"
13406 "Network in the BGP routing table to display\n"
4c63a661
PG
13407 "Network in the BGP routing table to display\n"
13408 "Network in the BGP routing table to display\n"
13409 JSON_STR)
13410{
d62a17ae 13411 int idx = 0;
13412 char *network = NULL;
44c69747 13413 int prefix_check = 0;
a636c635 13414
44c69747
LK
13415 if (argv_find(argv, argc, "A.B.C.D", &idx) ||
13416 argv_find(argv, argc, "X:X::X:X", &idx))
d62a17ae 13417 network = argv[idx]->arg;
44c69747 13418 else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
62e43fd7 13419 argv_find(argv, argc, "X:X::X:X/M", &idx)) {
d62a17ae 13420 network = argv[idx]->arg;
44c69747
LK
13421 prefix_check = 1;
13422 } else {
d62a17ae 13423 vty_out(vty, "Unable to figure out Network\n");
13424 return CMD_WARNING;
13425 }
44c69747
LK
13426 return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
13427 prefix_check, BGP_PATH_SHOW_ALL,
8aa22bbb 13428 RPKI_NOT_BEING_USED, use_json(argc, argv));
d62a17ae 13429}
13430
2f9bc755
DS
13431static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
13432 struct bgp_table *table, int *header1,
13433 int *header2, json_object *json,
13434 json_object *json_scode,
13435 json_object *json_ocode, bool wide)
13436{
13437 uint64_t version = table ? table->version : 0;
23d0a753 13438 char buf[BUFSIZ] = {0};
2f9bc755
DS
13439
13440 if (*header1) {
13441 if (json) {
13442 json_object_int_add(json, "bgpTableVersion", version);
13443 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13444 inet_ntop(AF_INET,
13445 &bgp->router_id, buf,
13446 sizeof(buf)));
2f9bc755
DS
13447 json_object_int_add(json, "defaultLocPrf",
13448 bgp->default_local_pref);
13449 json_object_int_add(json, "localAS", bgp->as);
13450 json_object_object_add(json, "bgpStatusCodes",
13451 json_scode);
13452 json_object_object_add(json, "bgpOriginCodes",
13453 json_ocode);
13454 } else {
13455 vty_out(vty,
23d0a753
DA
13456 "BGP table version is %" PRIu64
13457 ", local router ID is %pI4, vrf id ",
13458 version, &bgp->router_id);
2f9bc755
DS
13459 if (bgp->vrf_id == VRF_UNKNOWN)
13460 vty_out(vty, "%s", VRFID_NONE_STR);
13461 else
13462 vty_out(vty, "%u", bgp->vrf_id);
13463 vty_out(vty, "\n");
13464 vty_out(vty, "Default local pref %u, ",
13465 bgp->default_local_pref);
13466 vty_out(vty, "local AS %u\n", bgp->as);
13467 vty_out(vty, BGP_SHOW_SCODE_HEADER);
13468 vty_out(vty, BGP_SHOW_NCODE_HEADER);
13469 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13470 vty_out(vty, BGP_SHOW_RPKI_HEADER);
2f9bc755
DS
13471 }
13472 *header1 = 0;
13473 }
13474 if (*header2) {
13475 if (!json)
13476 vty_out(vty, (wide ? BGP_SHOW_HEADER_WIDE
13477 : BGP_SHOW_HEADER));
13478 *header2 = 0;
13479 }
13480}
13481
d9478df0
TA
13482static void
13483show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
13484 afi_t afi, safi_t safi, enum bgp_show_adj_route_type type,
13485 const char *rmap_name, json_object *json, json_object *json_ar,
13486 json_object *json_scode, json_object *json_ocode,
96c81f66 13487 uint16_t show_flags, int *header1, int *header2, char *rd_str,
d9478df0 13488 unsigned long *output_count, unsigned long *filtered_count)
d62a17ae 13489{
d62a17ae 13490 struct bgp_adj_in *ain;
13491 struct bgp_adj_out *adj;
9bcb3eef 13492 struct bgp_dest *dest;
d62a17ae 13493 struct bgp *bgp;
d62a17ae 13494 struct attr attr;
13495 int ret;
13496 struct update_subgroup *subgrp;
d62a17ae 13497 struct peer_af *paf;
f99def61 13498 bool route_filtered;
96f3485c
MK
13499 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13500 bool wide = CHECK_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
d9478df0
TA
13501 bool show_rd = ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13502 || (safi == SAFI_EVPN))
13503 ? true
13504 : false;
a636c635 13505
d62a17ae 13506 bgp = peer->bgp;
a636c635 13507
d62a17ae 13508 subgrp = peer_subgroup(peer, afi, safi);
13509
6392aaa6 13510 if (type == bgp_show_adj_route_advertised && subgrp
d62a17ae 13511 && CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
23d0a753
DA
13512 char buf[BUFSIZ] = {0};
13513
d62a17ae 13514 if (use_json) {
13515 json_object_int_add(json, "bgpTableVersion",
13516 table->version);
13517 json_object_string_add(json, "bgpLocalRouterId",
23d0a753
DA
13518 inet_ntop(AF_INET,
13519 &bgp->router_id, buf,
13520 sizeof(buf)));
01eced22
AD
13521 json_object_int_add(json, "defaultLocPrf",
13522 bgp->default_local_pref);
13523 json_object_int_add(json, "localAS", bgp->as);
d62a17ae 13524 json_object_object_add(json, "bgpStatusCodes",
13525 json_scode);
13526 json_object_object_add(json, "bgpOriginCodes",
13527 json_ocode);
07d0c4ed
DA
13528 json_object_string_add(
13529 json, "bgpOriginatingDefaultNetwork",
13530 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13531 } else {
23d0a753
DA
13532 vty_out(vty,
13533 "BGP table version is %" PRIu64
13534 ", local router ID is %pI4, vrf id ",
13535 table->version, &bgp->router_id);
9df8b37c
PZ
13536 if (bgp->vrf_id == VRF_UNKNOWN)
13537 vty_out(vty, "%s", VRFID_NONE_STR);
13538 else
13539 vty_out(vty, "%u", bgp->vrf_id);
13540 vty_out(vty, "\n");
01eced22
AD
13541 vty_out(vty, "Default local pref %u, ",
13542 bgp->default_local_pref);
13543 vty_out(vty, "local AS %u\n", bgp->as);
d62a17ae 13544 vty_out(vty, BGP_SHOW_SCODE_HEADER);
9df8b37c 13545 vty_out(vty, BGP_SHOW_NCODE_HEADER);
d62a17ae 13546 vty_out(vty, BGP_SHOW_OCODE_HEADER);
82c298be 13547 vty_out(vty, BGP_SHOW_RPKI_HEADER);
d62a17ae 13548
07d0c4ed
DA
13549 vty_out(vty, "Originating default network %s\n\n",
13550 (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
d62a17ae 13551 }
d9478df0 13552 *header1 = 0;
d62a17ae 13553 }
a636c635 13554
9bcb3eef 13555 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
6392aaa6
PM
13556 if (type == bgp_show_adj_route_received
13557 || type == bgp_show_adj_route_filtered) {
9bcb3eef 13558 for (ain = dest->adj_in; ain; ain = ain->next) {
05864da7 13559 if (ain->peer != peer)
ea47320b 13560 continue;
6392aaa6 13561
d9478df0
TA
13562 show_adj_route_header(vty, bgp, table, header1,
13563 header2, json, json_scode,
13564 json_ocode, wide);
13565
13566 if ((safi == SAFI_MPLS_VPN)
13567 || (safi == SAFI_ENCAP)
13568 || (safi == SAFI_EVPN)) {
13569 if (use_json)
13570 json_object_string_add(
13571 json_ar, "rd", rd_str);
13572 else if (show_rd && rd_str) {
13573 vty_out(vty,
13574 "Route Distinguisher: %s\n",
13575 rd_str);
13576 show_rd = false;
13577 }
13578 }
6392aaa6 13579
6f4f49b2 13580 attr = *ain->attr;
f99def61
AD
13581 route_filtered = false;
13582
13583 /* Filter prefix using distribute list,
13584 * filter list or prefix list
13585 */
b54892e0 13586 const struct prefix *rn_p =
9bcb3eef 13587 bgp_dest_get_prefix(dest);
b54892e0
DS
13588 if ((bgp_input_filter(peer, rn_p, &attr, afi,
13589 safi))
13590 == FILTER_DENY)
f99def61
AD
13591 route_filtered = true;
13592
13593 /* Filter prefix using route-map */
b54892e0
DS
13594 ret = bgp_input_modifier(peer, rn_p, &attr, afi,
13595 safi, rmap_name, NULL,
13596 0, NULL);
6392aaa6 13597
13c8e163
AD
13598 if (type == bgp_show_adj_route_filtered &&
13599 !route_filtered && ret != RMAP_DENY) {
b755861b 13600 bgp_attr_undup(&attr, ain->attr);
6392aaa6 13601 continue;
d62a17ae 13602 }
6392aaa6 13603
d9478df0
TA
13604 if (type == bgp_show_adj_route_received
13605 && (route_filtered || ret == RMAP_DENY))
13606 (*filtered_count)++;
6392aaa6 13607
7d3cae70 13608 route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
ae248832 13609 use_json, json_ar, wide);
b755861b 13610 bgp_attr_undup(&attr, ain->attr);
d9478df0 13611 (*output_count)++;
d62a17ae 13612 }
6392aaa6 13613 } else if (type == bgp_show_adj_route_advertised) {
9bcb3eef 13614 RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out)
924c3f6a 13615 SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
b755861b 13616 if (paf->peer != peer || !adj->attr)
924c3f6a 13617 continue;
d62a17ae 13618
d9478df0
TA
13619 show_adj_route_header(vty, bgp, table,
13620 header1, header2,
13621 json, json_scode,
13622 json_ocode, wide);
d62a17ae 13623
b54892e0 13624 const struct prefix *rn_p =
9bcb3eef 13625 bgp_dest_get_prefix(dest);
b54892e0 13626
6f4f49b2 13627 attr = *adj->attr;
b755861b 13628 ret = bgp_output_modifier(
b54892e0 13629 peer, rn_p, &attr, afi, safi,
b755861b 13630 rmap_name);
f46d8e1e 13631
b755861b 13632 if (ret != RMAP_DENY) {
d9478df0
TA
13633 if ((safi == SAFI_MPLS_VPN)
13634 || (safi == SAFI_ENCAP)
13635 || (safi == SAFI_EVPN)) {
13636 if (use_json)
13637 json_object_string_add(
13638 json_ar,
13639 "rd",
13640 rd_str);
13641 else if (show_rd
13642 && rd_str) {
13643 vty_out(vty,
13644 "Route Distinguisher: %s\n",
13645 rd_str);
13646 show_rd = false;
13647 }
13648 }
b54892e0 13649 route_vty_out_tmp(
7d3cae70
DA
13650 vty, dest, rn_p, &attr,
13651 safi, use_json, json_ar,
ae248832 13652 wide);
d9478df0 13653 (*output_count)++;
b755861b 13654 } else {
d9478df0 13655 (*filtered_count)++;
a2addae8 13656 }
b755861b
PM
13657
13658 bgp_attr_undup(&attr, adj->attr);
924c3f6a 13659 }
f20ce998
DS
13660 } else if (type == bgp_show_adj_route_bestpath) {
13661 struct bgp_path_info *pi;
13662
d9478df0
TA
13663 show_adj_route_header(vty, bgp, table, header1, header2,
13664 json, json_scode, json_ocode,
13665 wide);
f20ce998
DS
13666
13667 for (pi = bgp_dest_get_bgp_path_info(dest); pi;
13668 pi = pi->next) {
13669 if (pi->peer != peer)
13670 continue;
13671
13672 if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
13673 continue;
13674
7d3cae70 13675 route_vty_out_tmp(vty, dest,
f20ce998
DS
13676 bgp_dest_get_prefix(dest),
13677 pi->attr, safi, use_json,
13678 json_ar, wide);
d9478df0 13679 (*output_count)++;
f20ce998 13680 }
d62a17ae 13681 }
13682 }
a636c635 13683}
2a71e9ce 13684
d62a17ae 13685static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
6392aaa6 13686 safi_t safi, enum bgp_show_adj_route_type type,
96c81f66 13687 const char *rmap_name, uint16_t show_flags)
0b16f239 13688{
d9478df0
TA
13689 struct bgp *bgp;
13690 struct bgp_table *table;
d62a17ae 13691 json_object *json = NULL;
d9478df0
TA
13692 json_object *json_scode = NULL;
13693 json_object *json_ocode = NULL;
13694 json_object *json_ar = NULL;
96f3485c 13695 bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
0b16f239 13696
d9478df0
TA
13697 /* Init BGP headers here so they're only displayed once
13698 * even if 'table' is 2-tier (MPLS_VPN, ENCAP, EVPN).
13699 */
13700 int header1 = 1;
13701 int header2 = 1;
13702
13703 /*
13704 * Initialize variables for each RD
13705 * All prefixes under an RD is aggregated within "json_routes"
13706 */
13707 char rd_str[BUFSIZ] = {0};
13708 json_object *json_routes = NULL;
13709
13710
13711 /* For 2-tier tables, prefix counts need to be
13712 * maintained across multiple runs of show_adj_route()
13713 */
13714 unsigned long output_count_per_rd;
13715 unsigned long filtered_count_per_rd;
13716 unsigned long output_count = 0;
13717 unsigned long filtered_count = 0;
13718
13719 if (use_json) {
d62a17ae 13720 json = json_object_new_object();
d9478df0
TA
13721 json_ar = json_object_new_object();
13722 json_scode = json_object_new_object();
13723 json_ocode = json_object_new_object();
13724
13725 json_object_string_add(json_scode, "suppressed", "s");
13726 json_object_string_add(json_scode, "damped", "d");
13727 json_object_string_add(json_scode, "history", "h");
13728 json_object_string_add(json_scode, "valid", "*");
13729 json_object_string_add(json_scode, "best", ">");
13730 json_object_string_add(json_scode, "multipath", "=");
13731 json_object_string_add(json_scode, "internal", "i");
13732 json_object_string_add(json_scode, "ribFailure", "r");
13733 json_object_string_add(json_scode, "stale", "S");
13734 json_object_string_add(json_scode, "removed", "R");
13735
13736 json_object_string_add(json_ocode, "igp", "i");
13737 json_object_string_add(json_ocode, "egp", "e");
13738 json_object_string_add(json_ocode, "incomplete", "?");
13739 }
0b16f239 13740
d62a17ae 13741 if (!peer || !peer->afc[afi][safi]) {
13742 if (use_json) {
13743 json_object_string_add(
13744 json, "warning",
13745 "No such neighbor or address family");
13746 vty_out(vty, "%s\n", json_object_to_json_string(json));
13747 json_object_free(json);
690c3134
MW
13748 json_object_free(json_ar);
13749 json_object_free(json_scode);
13750 json_object_free(json_ocode);
d62a17ae 13751 } else
13752 vty_out(vty, "%% No such neighbor or address family\n");
0b16f239 13753
d62a17ae 13754 return CMD_WARNING;
13755 }
13756
6392aaa6
PM
13757 if ((type == bgp_show_adj_route_received
13758 || type == bgp_show_adj_route_filtered)
d62a17ae 13759 && !CHECK_FLAG(peer->af_flags[afi][safi],
13760 PEER_FLAG_SOFT_RECONFIG)) {
13761 if (use_json) {
13762 json_object_string_add(
13763 json, "warning",
13764 "Inbound soft reconfiguration not enabled");
13765 vty_out(vty, "%s\n", json_object_to_json_string(json));
13766 json_object_free(json);
690c3134
MW
13767 json_object_free(json_ar);
13768 json_object_free(json_scode);
13769 json_object_free(json_ocode);
d62a17ae 13770 } else
13771 vty_out(vty,
13772 "%% Inbound soft reconfiguration not enabled\n");
13773
13774 return CMD_WARNING;
13775 }
0b16f239 13776
d9478df0
TA
13777 bgp = peer->bgp;
13778
13779 /* labeled-unicast routes live in the unicast table */
13780 if (safi == SAFI_LABELED_UNICAST)
13781 table = bgp->rib[afi][SAFI_UNICAST];
13782 else
13783 table = bgp->rib[afi][safi];
13784
13785 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
13786 || (safi == SAFI_EVPN)) {
13787
13788 struct bgp_dest *dest;
13789
13790 for (dest = bgp_table_top(table); dest;
13791 dest = bgp_route_next(dest)) {
13792 table = bgp_dest_get_bgp_table_info(dest);
13793 if (!table)
13794 continue;
13795
13796 output_count_per_rd = 0;
13797 filtered_count_per_rd = 0;
13798
13799 if (use_json)
13800 json_routes = json_object_new_object();
13801
13802 const struct prefix_rd *prd;
13803 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
13804 dest);
13805
13806 prefix_rd2str(prd, rd_str, sizeof(rd_str));
13807
13808 show_adj_route(vty, peer, table, afi, safi, type,
13809 rmap_name, json, json_routes, json_scode,
13810 json_ocode, show_flags, &header1,
13811 &header2, rd_str, &output_count_per_rd,
13812 &filtered_count_per_rd);
13813
13814 /* Don't include an empty RD in the output! */
13815 if (json_routes && (output_count_per_rd > 0))
13816 json_object_object_add(json_ar, rd_str,
13817 json_routes);
13818
13819 output_count += output_count_per_rd;
13820 filtered_count += filtered_count_per_rd;
13821 }
13822 } else
13823 show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
13824 json, json_ar, json_scode, json_ocode,
13825 show_flags, &header1, &header2, rd_str,
13826 &output_count, &filtered_count);
13827
13828 if (use_json) {
13829 json_object_object_add(json, "advertisedRoutes", json_ar);
13830 json_object_int_add(json, "totalPrefixCounter", output_count);
13831 json_object_int_add(json, "filteredPrefixCounter",
13832 filtered_count);
13833
13834 vty_out(vty, "%s\n",
13835 json_object_to_json_string_ext(
13836 json, JSON_C_TO_STRING_PRETTY));
13837
690c3134
MW
13838 /*
13839 * These fields only give up ownership to `json` when `header1`
13840 * is used (set to zero). See code in `show_adj_route` and
13841 * `show_adj_route_header`.
13842 */
13843 if (header1 == 1) {
d9478df0
TA
13844 json_object_free(json_scode);
13845 json_object_free(json_ocode);
13846 }
13847
690c3134 13848 json_object_free(json);
d9478df0
TA
13849 } else if (output_count > 0) {
13850 if (filtered_count > 0)
13851 vty_out(vty,
13852 "\nTotal number of prefixes %ld (%ld filtered)\n",
13853 output_count, filtered_count);
13854 else
13855 vty_out(vty, "\nTotal number of prefixes %ld\n",
13856 output_count);
13857 }
0b16f239 13858
d62a17ae 13859 return CMD_SUCCESS;
a636c635 13860}
50ef26d4 13861
f20ce998
DS
13862DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
13863 show_ip_bgp_instance_neighbor_bestpath_route_cmd,
13864 "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]",
13865 SHOW_STR
13866 IP_STR
13867 BGP_STR
13868 BGP_INSTANCE_HELP_STR
13869 BGP_AFI_HELP_STR
13870 BGP_SAFI_WITH_LABEL_HELP_STR
13871 "Detailed information on TCP and BGP neighbor connections\n"
13872 "Neighbor to display information about\n"
13873 "Neighbor to display information about\n"
13874 "Neighbor on BGP configured interface\n"
13875 "Display the routes selected by best path\n"
13876 JSON_STR
13877 "Increase table width for longer prefixes\n")
13878{
13879 afi_t afi = AFI_IP6;
13880 safi_t safi = SAFI_UNICAST;
13881 char *rmap_name = NULL;
13882 char *peerstr = NULL;
13883 struct bgp *bgp = NULL;
13884 struct peer *peer;
13885 enum bgp_show_adj_route_type type = bgp_show_adj_route_bestpath;
13886 int idx = 0;
96c81f66 13887 uint16_t show_flags = 0;
96f3485c
MK
13888
13889 if (uj)
13890 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13891
13892 if (wide)
13893 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
f20ce998
DS
13894
13895 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13896 &bgp, uj);
13897
13898 if (!idx)
13899 return CMD_WARNING;
13900
13901 argv_find(argv, argc, "neighbors", &idx);
13902 peerstr = argv[++idx]->arg;
13903
13904 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13905 if (!peer)
13906 return CMD_WARNING;
13907
96f3485c
MK
13908 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13909 show_flags);
f20ce998
DS
13910}
13911
ae248832 13912DEFPY (show_ip_bgp_instance_neighbor_advertised_route,
a636c635 13913 show_ip_bgp_instance_neighbor_advertised_route_cmd,
96f3485c 13914 "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 13915 SHOW_STR
13916 IP_STR
13917 BGP_STR
a636c635 13918 BGP_INSTANCE_HELP_STR
7395a2c9 13919 BGP_AFI_HELP_STR
4dd6177e 13920 BGP_SAFI_WITH_LABEL_HELP_STR
96f3485c 13921 "Display the entries for all address families\n"
718e3744 13922 "Detailed information on TCP and BGP neighbor connections\n"
13923 "Neighbor to display information about\n"
13924 "Neighbor to display information about\n"
91d37724 13925 "Neighbor on BGP configured interface\n"
a636c635 13926 "Display the routes advertised to a BGP neighbor\n"
6392aaa6
PM
13927 "Display the received routes from neighbor\n"
13928 "Display the filtered routes received from neighbor\n"
a636c635
DW
13929 "Route-map to modify the attributes\n"
13930 "Name of the route map\n"
ae248832
MK
13931 JSON_STR
13932 "Increase table width for longer prefixes\n")
718e3744 13933{
d62a17ae 13934 afi_t afi = AFI_IP6;
13935 safi_t safi = SAFI_UNICAST;
13936 char *rmap_name = NULL;
13937 char *peerstr = NULL;
d62a17ae 13938 struct bgp *bgp = NULL;
13939 struct peer *peer;
6392aaa6 13940 enum bgp_show_adj_route_type type = bgp_show_adj_route_advertised;
d62a17ae 13941 int idx = 0;
96f3485c 13942 bool first = true;
96c81f66 13943 uint16_t show_flags = 0;
6392aaa6 13944
96f3485c 13945 if (uj) {
d62a17ae 13946 argc--;
96f3485c
MK
13947 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
13948 }
13949
13950 if (all) {
13951 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
13952 if (argv_find(argv, argc, "ipv4", &idx))
13953 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP);
13954
13955 if (argv_find(argv, argc, "ipv6", &idx))
13956 SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6);
13957 }
13958
13959 if (wide)
13960 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
30a6a167 13961
9f049418
DS
13962 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
13963 &bgp, uj);
13964 if (!idx)
13965 return CMD_WARNING;
13966
d62a17ae 13967 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
13968 argv_find(argv, argc, "neighbors", &idx);
13969 peerstr = argv[++idx]->arg;
8c3deaae 13970
d62a17ae 13971 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
13972 if (!peer)
13973 return CMD_WARNING;
856ca177 13974
d62a17ae 13975 if (argv_find(argv, argc, "advertised-routes", &idx))
6392aaa6
PM
13976 type = bgp_show_adj_route_advertised;
13977 else if (argv_find(argv, argc, "received-routes", &idx))
13978 type = bgp_show_adj_route_received;
13979 else if (argv_find(argv, argc, "filtered-routes", &idx))
13980 type = bgp_show_adj_route_filtered;
13981
d62a17ae 13982 if (argv_find(argv, argc, "route-map", &idx))
13983 rmap_name = argv[++idx]->arg;
95cbbd2a 13984
96f3485c
MK
13985 if (!all)
13986 return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
13987 show_flags);
13988 if (uj)
13989 vty_out(vty, "{\n");
13990
13991 if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP)
13992 || CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP6)) {
13993 afi = CHECK_FLAG(show_flags, BGP_SHOW_OPT_AFI_IP) ? AFI_IP
13994 : AFI_IP6;
13995 FOREACH_SAFI (safi) {
96f3485c
MK
13996 if (!bgp_afi_safi_peer_exists(bgp, afi, safi))
13997 continue;
13998
13999 if (uj) {
14000 if (first)
14001 first = false;
14002 else
14003 vty_out(vty, ",\n");
14004 vty_out(vty, "\"%s\":",
14005 get_afi_safi_str(afi, safi, true));
14006 } else
14007 vty_out(vty, "\nFor address family: %s\n",
14008 get_afi_safi_str(afi, safi, false));
14009
14010 peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
14011 show_flags);
14012 }
14013 } else {
14014 FOREACH_AFI_SAFI (afi, 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 }
14033 if (uj)
14034 vty_out(vty, "}\n");
14035
14036 return CMD_SUCCESS;
95cbbd2a
ML
14037}
14038
718e3744 14039DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
14040 show_ip_bgp_neighbor_received_prefix_filter_cmd,
d3120452 14041 "show [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD> received prefix-filter [json]",
718e3744 14042 SHOW_STR
14043 IP_STR
14044 BGP_STR
d3120452 14045 BGP_INSTANCE_HELP_STR
8c3deaae
QY
14046 "Address Family\n"
14047 "Address Family\n"
718e3744 14048 "Address Family modifier\n"
14049 "Detailed information on TCP and BGP neighbor connections\n"
14050 "Neighbor to display information about\n"
14051 "Neighbor to display information about\n"
91d37724 14052 "Neighbor on BGP configured interface\n"
718e3744 14053 "Display information received from a BGP neighbor\n"
856ca177 14054 "Display the prefixlist filter\n"
9973d184 14055 JSON_STR)
718e3744 14056{
d62a17ae 14057 afi_t afi = AFI_IP6;
14058 safi_t safi = SAFI_UNICAST;
14059 char *peerstr = NULL;
d62a17ae 14060 char name[BUFSIZ];
d62a17ae 14061 struct peer *peer;
d3120452 14062 int count;
d62a17ae 14063 int idx = 0;
d3120452
IR
14064 struct bgp *bgp = NULL;
14065 bool uj = use_json(argc, argv);
14066
14067 if (uj)
14068 argc--;
14069
14070 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
14071 &bgp, uj);
14072 if (!idx)
14073 return CMD_WARNING;
d62a17ae 14074
d62a17ae 14075 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14076 argv_find(argv, argc, "neighbors", &idx);
14077 peerstr = argv[++idx]->arg;
14078
d3120452
IR
14079 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
14080 if (!peer)
14081 return CMD_WARNING;
718e3744 14082
4ced1a2c 14083 snprintf(name, sizeof(name), "%s.%d.%d", peer->host, afi, safi);
d62a17ae 14084 count = prefix_bgp_show_prefix_list(NULL, afi, name, uj);
14085 if (count) {
14086 if (!uj)
14087 vty_out(vty, "Address Family: %s\n",
5cb5f4d0 14088 get_afi_safi_str(afi, safi, false));
d62a17ae 14089 prefix_bgp_show_prefix_list(vty, afi, name, uj);
14090 } else {
14091 if (uj)
14092 vty_out(vty, "{}\n");
14093 else
14094 vty_out(vty, "No functional output\n");
14095 }
718e3744 14096
d62a17ae 14097 return CMD_SUCCESS;
14098}
14099
14100static int bgp_show_neighbor_route(struct vty *vty, struct peer *peer,
14101 afi_t afi, safi_t safi,
9f049418 14102 enum bgp_show_type type, bool use_json)
d62a17ae 14103{
96c81f66 14104 uint16_t show_flags = 0;
96f3485c
MK
14105
14106 if (use_json)
14107 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14108
d62a17ae 14109 if (!peer || !peer->afc[afi][safi]) {
14110 if (use_json) {
14111 json_object *json_no = NULL;
14112 json_no = json_object_new_object();
14113 json_object_string_add(
14114 json_no, "warning",
14115 "No such neighbor or address family");
14116 vty_out(vty, "%s\n",
14117 json_object_to_json_string(json_no));
14118 json_object_free(json_no);
14119 } else
14120 vty_out(vty, "%% No such neighbor or address family\n");
14121 return CMD_WARNING;
14122 }
47fc97cc 14123
7daf25a3
TA
14124 /* labeled-unicast routes live in the unicast table */
14125 if (safi == SAFI_LABELED_UNICAST)
14126 safi = SAFI_UNICAST;
14127
1e2ce4f1
DS
14128 return bgp_show(vty, peer->bgp, afi, safi, type, &peer->su, show_flags,
14129 RPKI_NOT_BEING_USED);
718e3744 14130}
14131
dba3c1d3
PG
14132DEFUN (show_ip_bgp_flowspec_routes_detailed,
14133 show_ip_bgp_flowspec_routes_detailed_cmd,
14134 "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" flowspec] detail [json]",
14135 SHOW_STR
14136 IP_STR
14137 BGP_STR
14138 BGP_INSTANCE_HELP_STR
14139 BGP_AFI_HELP_STR
14140 "SAFI Flowspec\n"
14141 "Detailed information on flowspec entries\n"
14142 JSON_STR)
14143{
458c1475 14144 afi_t afi = AFI_IP6;
dba3c1d3
PG
14145 safi_t safi = SAFI_UNICAST;
14146 struct bgp *bgp = NULL;
14147 int idx = 0;
9f049418 14148 bool uj = use_json(argc, argv);
96c81f66 14149 uint16_t show_flags = 0;
9f049418 14150
96f3485c 14151 if (uj) {
9f049418 14152 argc--;
96f3485c
MK
14153 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
14154 }
dba3c1d3
PG
14155
14156 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14157 &bgp, uj);
dba3c1d3
PG
14158 if (!idx)
14159 return CMD_WARNING;
14160
96f3485c 14161 return bgp_show(vty, bgp, afi, safi, bgp_show_type_detail, NULL,
1e2ce4f1 14162 show_flags, RPKI_NOT_BEING_USED);
dba3c1d3
PG
14163}
14164
718e3744 14165DEFUN (show_ip_bgp_neighbor_routes,
14166 show_ip_bgp_neighbor_routes_cmd,
3efd0893 14167 "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 14168 SHOW_STR
14169 IP_STR
14170 BGP_STR
8386ac43 14171 BGP_INSTANCE_HELP_STR
4f280b15 14172 BGP_AFI_HELP_STR
4dd6177e 14173 BGP_SAFI_WITH_LABEL_HELP_STR
718e3744 14174 "Detailed information on TCP and BGP neighbor connections\n"
14175 "Neighbor to display information about\n"
14176 "Neighbor to display information about\n"
91d37724 14177 "Neighbor on BGP configured interface\n"
2525cf39 14178 "Display flap statistics of the routes learned from neighbor\n"
8c3deaae
QY
14179 "Display the dampened routes received from neighbor\n"
14180 "Display routes learned from neighbor\n"
9973d184 14181 JSON_STR)
718e3744 14182{
d62a17ae 14183 char *peerstr = NULL;
14184 struct bgp *bgp = NULL;
14185 afi_t afi = AFI_IP6;
14186 safi_t safi = SAFI_UNICAST;
14187 struct peer *peer;
14188 enum bgp_show_type sh_type = bgp_show_type_neighbor;
d62a17ae 14189 int idx = 0;
9f049418
DS
14190 bool uj = use_json(argc, argv);
14191
14192 if (uj)
14193 argc--;
bb46e94f 14194
d62a17ae 14195 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
9f049418 14196 &bgp, uj);
d62a17ae 14197 if (!idx)
14198 return CMD_WARNING;
c493f2d8 14199
d62a17ae 14200 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
14201 argv_find(argv, argc, "neighbors", &idx);
14202 peerstr = argv[++idx]->arg;
8c3deaae 14203
d62a17ae 14204 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
9e6e6f46 14205 if (!peer)
d62a17ae 14206 return CMD_WARNING;
bb46e94f 14207
d62a17ae 14208 if (argv_find(argv, argc, "flap-statistics", &idx))
14209 sh_type = bgp_show_type_flap_neighbor;
14210 else if (argv_find(argv, argc, "dampened-routes", &idx))
14211 sh_type = bgp_show_type_damp_neighbor;
14212 else if (argv_find(argv, argc, "routes", &idx))
14213 sh_type = bgp_show_type_neighbor;
2525cf39 14214
d62a17ae 14215 return bgp_show_neighbor_route(vty, peer, afi, safi, sh_type, uj);
50ef26d4 14216}
6b0655a2 14217
734b349e 14218struct bgp_table *bgp_distance_table[AFI_MAX][SAFI_MAX];
718e3744 14219
d62a17ae 14220struct bgp_distance {
14221 /* Distance value for the IP source prefix. */
d7c0a89a 14222 uint8_t distance;
718e3744 14223
d62a17ae 14224 /* Name of the access-list to be matched. */
14225 char *access_list;
718e3744 14226};
14227
4f280b15
LB
14228DEFUN (show_bgp_afi_vpn_rd_route,
14229 show_bgp_afi_vpn_rd_route_cmd,
a111dd97 14230 "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
14231 SHOW_STR
14232 BGP_STR
14233 BGP_AFI_HELP_STR
14234 "Address Family modifier\n"
14235 "Display information for a route distinguisher\n"
14236 "Route Distinguisher\n"
a111dd97 14237 "All Route Distinguishers\n"
7395a2c9
DS
14238 "Network in the BGP routing table to display\n"
14239 "Network in the BGP routing table to display\n"
14240 JSON_STR)
4f280b15 14241{
d62a17ae 14242 int ret;
14243 struct prefix_rd prd;
14244 afi_t afi = AFI_MAX;
14245 int idx = 0;
4f280b15 14246
ff6566f3
DS
14247 if (!argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
14248 vty_out(vty, "%% Malformed Address Family\n");
14249 return CMD_WARNING;
14250 }
14251
a111dd97
TA
14252 if (!strcmp(argv[5]->arg, "all"))
14253 return bgp_show_route(vty, NULL, argv[6]->arg, afi,
14254 SAFI_MPLS_VPN, NULL, 0, BGP_PATH_SHOW_ALL,
14255 RPKI_NOT_BEING_USED,
14256 use_json(argc, argv));
14257
d62a17ae 14258 ret = str2prefix_rd(argv[5]->arg, &prd);
14259 if (!ret) {
14260 vty_out(vty, "%% Malformed Route Distinguisher\n");
14261 return CMD_WARNING;
14262 }
ff6566f3 14263
d62a17ae 14264 return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd,
8aa22bbb
DS
14265 0, BGP_PATH_SHOW_ALL, RPKI_NOT_BEING_USED,
14266 use_json(argc, argv));
4f280b15
LB
14267}
14268
d62a17ae 14269static struct bgp_distance *bgp_distance_new(void)
718e3744 14270{
d62a17ae 14271 return XCALLOC(MTYPE_BGP_DISTANCE, sizeof(struct bgp_distance));
718e3744 14272}
14273
d62a17ae 14274static void bgp_distance_free(struct bgp_distance *bdistance)
718e3744 14275{
d62a17ae 14276 XFREE(MTYPE_BGP_DISTANCE, bdistance);
718e3744 14277}
14278
585f1adc
IR
14279static int bgp_distance_set(struct vty *vty, const char *distance_str,
14280 const char *ip_str, const char *access_list_str)
718e3744 14281{
d62a17ae 14282 int ret;
585f1adc
IR
14283 afi_t afi;
14284 safi_t safi;
d62a17ae 14285 struct prefix p;
585f1adc 14286 uint8_t distance;
9bcb3eef 14287 struct bgp_dest *dest;
d62a17ae 14288 struct bgp_distance *bdistance;
718e3744 14289
585f1adc
IR
14290 afi = bgp_node_afi(vty);
14291 safi = bgp_node_safi(vty);
14292
d62a17ae 14293 ret = str2prefix(ip_str, &p);
14294 if (ret == 0) {
585f1adc 14295 vty_out(vty, "Malformed prefix\n");
d62a17ae 14296 return CMD_WARNING_CONFIG_FAILED;
14297 }
718e3744 14298
585f1adc
IR
14299 distance = atoi(distance_str);
14300
d62a17ae 14301 /* Get BGP distance node. */
9bcb3eef
DS
14302 dest = bgp_node_get(bgp_distance_table[afi][safi], &p);
14303 bdistance = bgp_dest_get_bgp_distance_info(dest);
ca2e160d 14304 if (bdistance)
9bcb3eef 14305 bgp_dest_unlock_node(dest);
ca2e160d 14306 else {
d62a17ae 14307 bdistance = bgp_distance_new();
9bcb3eef 14308 bgp_dest_set_bgp_distance_info(dest, bdistance);
d62a17ae 14309 }
718e3744 14310
d62a17ae 14311 /* Set distance value. */
14312 bdistance->distance = distance;
718e3744 14313
d62a17ae 14314 /* Reset access-list configuration. */
e1b36e13 14315 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14316 if (access_list_str)
14317 bdistance->access_list =
14318 XSTRDUP(MTYPE_AS_LIST, access_list_str);
718e3744 14319
d62a17ae 14320 return CMD_SUCCESS;
718e3744 14321}
14322
585f1adc
IR
14323static int bgp_distance_unset(struct vty *vty, const char *distance_str,
14324 const char *ip_str, const char *access_list_str)
718e3744 14325{
d62a17ae 14326 int ret;
585f1adc
IR
14327 afi_t afi;
14328 safi_t safi;
d62a17ae 14329 struct prefix p;
585f1adc 14330 int distance;
9bcb3eef 14331 struct bgp_dest *dest;
d62a17ae 14332 struct bgp_distance *bdistance;
718e3744 14333
585f1adc
IR
14334 afi = bgp_node_afi(vty);
14335 safi = bgp_node_safi(vty);
14336
d62a17ae 14337 ret = str2prefix(ip_str, &p);
14338 if (ret == 0) {
585f1adc 14339 vty_out(vty, "Malformed prefix\n");
d62a17ae 14340 return CMD_WARNING_CONFIG_FAILED;
14341 }
718e3744 14342
9bcb3eef
DS
14343 dest = bgp_node_lookup(bgp_distance_table[afi][safi], &p);
14344 if (!dest) {
585f1adc 14345 vty_out(vty, "Can't find specified prefix\n");
d62a17ae 14346 return CMD_WARNING_CONFIG_FAILED;
14347 }
718e3744 14348
9bcb3eef 14349 bdistance = bgp_dest_get_bgp_distance_info(dest);
585f1adc 14350 distance = atoi(distance_str);
1f9a9fff 14351
d62a17ae 14352 if (bdistance->distance != distance) {
585f1adc 14353 vty_out(vty, "Distance does not match configured\n");
89f4bd87 14354 bgp_dest_unlock_node(dest);
d62a17ae 14355 return CMD_WARNING_CONFIG_FAILED;
14356 }
718e3744 14357
0a22ddfb 14358 XFREE(MTYPE_AS_LIST, bdistance->access_list);
d62a17ae 14359 bgp_distance_free(bdistance);
718e3744 14360
9bcb3eef
DS
14361 bgp_dest_set_bgp_path_info(dest, NULL);
14362 bgp_dest_unlock_node(dest);
14363 bgp_dest_unlock_node(dest);
718e3744 14364
d62a17ae 14365 return CMD_SUCCESS;
718e3744 14366}
14367
718e3744 14368/* Apply BGP information to distance method. */
b8685f9b 14369uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo,
4b7e6066 14370 afi_t afi, safi_t safi, struct bgp *bgp)
d62a17ae 14371{
9bcb3eef 14372 struct bgp_dest *dest;
801bb996 14373 struct prefix q = {0};
d62a17ae 14374 struct peer *peer;
14375 struct bgp_distance *bdistance;
14376 struct access_list *alist;
14377 struct bgp_static *bgp_static;
14378
14379 if (!bgp)
14380 return 0;
14381
40381db7 14382 peer = pinfo->peer;
d62a17ae 14383
7b7d48e5
DS
14384 if (pinfo->attr->distance)
14385 return pinfo->attr->distance;
14386
801bb996
CS
14387 /* Check source address.
14388 * Note: for aggregate route, peer can have unspec af type.
14389 */
14390 if (pinfo->sub_type != BGP_ROUTE_AGGREGATE
14391 && !sockunion2hostprefix(&peer->su, &q))
0154d8ce
DS
14392 return 0;
14393
9bcb3eef
DS
14394 dest = bgp_node_match(bgp_distance_table[afi][safi], &q);
14395 if (dest) {
14396 bdistance = bgp_dest_get_bgp_distance_info(dest);
14397 bgp_dest_unlock_node(dest);
d62a17ae 14398
14399 if (bdistance->access_list) {
14400 alist = access_list_lookup(afi, bdistance->access_list);
14401 if (alist
14402 && access_list_apply(alist, p) == FILTER_PERMIT)
14403 return bdistance->distance;
14404 } else
14405 return bdistance->distance;
718e3744 14406 }
718e3744 14407
d62a17ae 14408 /* Backdoor check. */
9bcb3eef
DS
14409 dest = bgp_node_lookup(bgp->route[afi][safi], p);
14410 if (dest) {
14411 bgp_static = bgp_dest_get_bgp_static_info(dest);
14412 bgp_dest_unlock_node(dest);
718e3744 14413
d62a17ae 14414 if (bgp_static->backdoor) {
14415 if (bgp->distance_local[afi][safi])
14416 return bgp->distance_local[afi][safi];
14417 else
14418 return ZEBRA_IBGP_DISTANCE_DEFAULT;
14419 }
718e3744 14420 }
718e3744 14421
d62a17ae 14422 if (peer->sort == BGP_PEER_EBGP) {
14423 if (bgp->distance_ebgp[afi][safi])
14424 return bgp->distance_ebgp[afi][safi];
14425 return ZEBRA_EBGP_DISTANCE_DEFAULT;
1c00fb27 14426 } else if (peer->sort == BGP_PEER_IBGP) {
d62a17ae 14427 if (bgp->distance_ibgp[afi][safi])
14428 return bgp->distance_ibgp[afi][safi];
14429 return ZEBRA_IBGP_DISTANCE_DEFAULT;
1c00fb27
CS
14430 } else {
14431 if (bgp->distance_local[afi][safi])
14432 return bgp->distance_local[afi][safi];
14433 return ZEBRA_IBGP_DISTANCE_DEFAULT;
d62a17ae 14434 }
718e3744 14435}
14436
a612fb77
DA
14437/* If we enter `distance bgp (1-255) (1-255) (1-255)`,
14438 * we should tell ZEBRA update the routes for a specific
14439 * AFI/SAFI to reflect changes in RIB.
14440 */
585f1adc
IR
14441static void bgp_announce_routes_distance_update(struct bgp *bgp,
14442 afi_t update_afi,
14443 safi_t update_safi)
a612fb77
DA
14444{
14445 afi_t afi;
14446 safi_t safi;
14447
14448 FOREACH_AFI_SAFI (afi, safi) {
14449 if (!bgp_fibupd_safi(safi))
14450 continue;
14451
8b54bc30
DA
14452 if (afi != update_afi && safi != update_safi)
14453 continue;
14454
14455 if (BGP_DEBUG(zebra, ZEBRA))
14456 zlog_debug(
14457 "%s: Announcing routes due to distance change afi/safi (%d/%d)",
14458 __func__, afi, safi);
14459 bgp_zebra_announce_table(bgp, afi, safi);
a612fb77
DA
14460 }
14461}
14462
585f1adc
IR
14463DEFUN (bgp_distance,
14464 bgp_distance_cmd,
14465 "distance bgp (1-255) (1-255) (1-255)",
14466 "Define an administrative distance\n"
14467 "BGP distance\n"
14468 "Distance for routes external to the AS\n"
14469 "Distance for routes internal to the AS\n"
14470 "Distance for local routes\n")
718e3744 14471{
585f1adc 14472 VTY_DECLVAR_CONTEXT(bgp, bgp);
d62a17ae 14473 int idx_number = 2;
14474 int idx_number_2 = 3;
14475 int idx_number_3 = 4;
585f1adc
IR
14476 int distance_ebgp = atoi(argv[idx_number]->arg);
14477 int distance_ibgp = atoi(argv[idx_number_2]->arg);
14478 int distance_local = atoi(argv[idx_number_3]->arg);
d62a17ae 14479 afi_t afi;
14480 safi_t safi;
718e3744 14481
d62a17ae 14482 afi = bgp_node_afi(vty);
14483 safi = bgp_node_safi(vty);
718e3744 14484
585f1adc
IR
14485 if (bgp->distance_ebgp[afi][safi] != distance_ebgp
14486 || bgp->distance_ibgp[afi][safi] != distance_ibgp
14487 || bgp->distance_local[afi][safi] != distance_local) {
14488 bgp->distance_ebgp[afi][safi] = distance_ebgp;
14489 bgp->distance_ibgp[afi][safi] = distance_ibgp;
14490 bgp->distance_local[afi][safi] = distance_local;
14491 bgp_announce_routes_distance_update(bgp, afi, safi);
14492 }
14493 return CMD_SUCCESS;
14494}
37a87b8f 14495
585f1adc
IR
14496DEFUN (no_bgp_distance,
14497 no_bgp_distance_cmd,
14498 "no distance bgp [(1-255) (1-255) (1-255)]",
14499 NO_STR
14500 "Define an administrative distance\n"
14501 "BGP distance\n"
14502 "Distance for routes external to the AS\n"
14503 "Distance for routes internal to the AS\n"
14504 "Distance for local routes\n")
718e3744 14505{
585f1adc 14506 VTY_DECLVAR_CONTEXT(bgp, bgp);
37a87b8f
CS
14507 afi_t afi;
14508 safi_t safi;
37a87b8f
CS
14509
14510 afi = bgp_node_afi(vty);
14511 safi = bgp_node_safi(vty);
14512
585f1adc
IR
14513 if (bgp->distance_ebgp[afi][safi] != 0
14514 || bgp->distance_ibgp[afi][safi] != 0
14515 || bgp->distance_local[afi][safi] != 0) {
14516 bgp->distance_ebgp[afi][safi] = 0;
14517 bgp->distance_ibgp[afi][safi] = 0;
14518 bgp->distance_local[afi][safi] = 0;
14519 bgp_announce_routes_distance_update(bgp, afi, safi);
8cc7152a 14520 }
585f1adc
IR
14521 return CMD_SUCCESS;
14522}
37a87b8f 14523
37a87b8f 14524
585f1adc
IR
14525DEFUN (bgp_distance_source,
14526 bgp_distance_source_cmd,
14527 "distance (1-255) A.B.C.D/M",
14528 "Define an administrative distance\n"
14529 "Administrative distance\n"
14530 "IP source prefix\n")
14531{
14532 int idx_number = 1;
14533 int idx_ipv4_prefixlen = 2;
14534 bgp_distance_set(vty, argv[idx_number]->arg,
14535 argv[idx_ipv4_prefixlen]->arg, NULL);
14536 return CMD_SUCCESS;
734b349e
MZ
14537}
14538
585f1adc
IR
14539DEFUN (no_bgp_distance_source,
14540 no_bgp_distance_source_cmd,
14541 "no distance (1-255) A.B.C.D/M",
14542 NO_STR
14543 "Define an administrative distance\n"
14544 "Administrative distance\n"
14545 "IP source prefix\n")
37a87b8f 14546{
585f1adc
IR
14547 int idx_number = 2;
14548 int idx_ipv4_prefixlen = 3;
14549 bgp_distance_unset(vty, argv[idx_number]->arg,
14550 argv[idx_ipv4_prefixlen]->arg, NULL);
14551 return CMD_SUCCESS;
37a87b8f
CS
14552}
14553
585f1adc
IR
14554DEFUN (bgp_distance_source_access_list,
14555 bgp_distance_source_access_list_cmd,
14556 "distance (1-255) A.B.C.D/M WORD",
14557 "Define an administrative distance\n"
14558 "Administrative distance\n"
14559 "IP source prefix\n"
14560 "Access list name\n")
37a87b8f 14561{
585f1adc
IR
14562 int idx_number = 1;
14563 int idx_ipv4_prefixlen = 2;
14564 int idx_word = 3;
14565 bgp_distance_set(vty, argv[idx_number]->arg,
14566 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14567 return CMD_SUCCESS;
14568}
718e3744 14569
585f1adc
IR
14570DEFUN (no_bgp_distance_source_access_list,
14571 no_bgp_distance_source_access_list_cmd,
14572 "no distance (1-255) A.B.C.D/M WORD",
14573 NO_STR
14574 "Define an administrative distance\n"
14575 "Administrative distance\n"
14576 "IP source prefix\n"
14577 "Access list name\n")
14578{
14579 int idx_number = 2;
14580 int idx_ipv4_prefixlen = 3;
14581 int idx_word = 4;
14582 bgp_distance_unset(vty, argv[idx_number]->arg,
14583 argv[idx_ipv4_prefixlen]->arg, argv[idx_word]->arg);
14584 return CMD_SUCCESS;
14585}
37a87b8f 14586
585f1adc
IR
14587DEFUN (ipv6_bgp_distance_source,
14588 ipv6_bgp_distance_source_cmd,
14589 "distance (1-255) X:X::X:X/M",
14590 "Define an administrative distance\n"
14591 "Administrative distance\n"
14592 "IP source prefix\n")
14593{
14594 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, NULL);
14595 return CMD_SUCCESS;
14596}
7ebe9748 14597
585f1adc
IR
14598DEFUN (no_ipv6_bgp_distance_source,
14599 no_ipv6_bgp_distance_source_cmd,
14600 "no distance (1-255) X:X::X:X/M",
14601 NO_STR
14602 "Define an administrative distance\n"
14603 "Administrative distance\n"
14604 "IP source prefix\n")
14605{
14606 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, NULL);
14607 return CMD_SUCCESS;
14608}
37a87b8f 14609
585f1adc
IR
14610DEFUN (ipv6_bgp_distance_source_access_list,
14611 ipv6_bgp_distance_source_access_list_cmd,
14612 "distance (1-255) X:X::X:X/M WORD",
14613 "Define an administrative distance\n"
14614 "Administrative distance\n"
14615 "IP source prefix\n"
14616 "Access list name\n")
14617{
14618 bgp_distance_set(vty, argv[1]->arg, argv[2]->arg, argv[3]->arg);
14619 return CMD_SUCCESS;
718e3744 14620}
14621
585f1adc
IR
14622DEFUN (no_ipv6_bgp_distance_source_access_list,
14623 no_ipv6_bgp_distance_source_access_list_cmd,
14624 "no distance (1-255) X:X::X:X/M WORD",
14625 NO_STR
14626 "Define an administrative distance\n"
14627 "Administrative distance\n"
14628 "IP source prefix\n"
14629 "Access list name\n")
718e3744 14630{
585f1adc
IR
14631 bgp_distance_unset(vty, argv[2]->arg, argv[3]->arg, argv[4]->arg);
14632 return CMD_SUCCESS;
14633}
37a87b8f 14634
585f1adc
IR
14635DEFUN (bgp_damp_set,
14636 bgp_damp_set_cmd,
14637 "bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14638 "BGP Specific commands\n"
14639 "Enable route-flap dampening\n"
14640 "Half-life time for the penalty\n"
14641 "Value to start reusing a route\n"
14642 "Value to start suppressing a route\n"
14643 "Maximum duration to suppress a stable route\n")
14644{
14645 VTY_DECLVAR_CONTEXT(bgp, bgp);
14646 int idx_half_life = 2;
14647 int idx_reuse = 3;
14648 int idx_suppress = 4;
14649 int idx_max_suppress = 5;
37a87b8f
CS
14650 int half = DEFAULT_HALF_LIFE * 60;
14651 int reuse = DEFAULT_REUSE;
14652 int suppress = DEFAULT_SUPPRESS;
585f1adc
IR
14653 int max = 4 * half;
14654
14655 if (argc == 6) {
14656 half = atoi(argv[idx_half_life]->arg) * 60;
14657 reuse = atoi(argv[idx_reuse]->arg);
14658 suppress = atoi(argv[idx_suppress]->arg);
14659 max = atoi(argv[idx_max_suppress]->arg) * 60;
14660 } else if (argc == 3) {
14661 half = atoi(argv[idx_half_life]->arg) * 60;
14662 max = 4 * half;
14663 }
14664
14665 /*
14666 * These can't be 0 but our SA doesn't understand the
14667 * way our cli is constructed
14668 */
14669 assert(reuse);
14670 assert(half);
14671 if (suppress < reuse) {
14672 vty_out(vty,
14673 "Suppress value cannot be less than reuse value \n");
14674 return 0;
14675 }
14676
14677 return bgp_damp_enable(bgp, bgp_node_afi(vty), bgp_node_safi(vty), half,
14678 reuse, suppress, max);
14679}
14680
14681DEFUN (bgp_damp_unset,
14682 bgp_damp_unset_cmd,
14683 "no bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]",
14684 NO_STR
14685 "BGP Specific commands\n"
14686 "Enable route-flap dampening\n"
14687 "Half-life time for the penalty\n"
14688 "Value to start reusing a route\n"
14689 "Value to start suppressing a route\n"
14690 "Maximum duration to suppress a stable route\n")
14691{
14692 VTY_DECLVAR_CONTEXT(bgp, bgp);
14693 return bgp_damp_disable(bgp, bgp_node_afi(vty), bgp_node_safi(vty));
718e3744 14694}
14695
718e3744 14696/* Display specified route of BGP table. */
d62a17ae 14697static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
14698 const char *ip_str, afi_t afi, safi_t safi,
14699 struct prefix_rd *prd, int prefix_check)
14700{
14701 int ret;
14702 struct prefix match;
9bcb3eef
DS
14703 struct bgp_dest *dest;
14704 struct bgp_dest *rm;
40381db7
DS
14705 struct bgp_path_info *pi;
14706 struct bgp_path_info *pi_temp;
d62a17ae 14707 struct bgp *bgp;
14708 struct bgp_table *table;
14709
14710 /* BGP structure lookup. */
14711 if (view_name) {
14712 bgp = bgp_lookup_by_name(view_name);
14713 if (bgp == NULL) {
14714 vty_out(vty, "%% Can't find BGP instance %s\n",
14715 view_name);
14716 return CMD_WARNING;
14717 }
14718 } else {
14719 bgp = bgp_get_default();
14720 if (bgp == NULL) {
14721 vty_out(vty, "%% No BGP process is configured\n");
14722 return CMD_WARNING;
14723 }
718e3744 14724 }
718e3744 14725
d62a17ae 14726 /* Check IP address argument. */
14727 ret = str2prefix(ip_str, &match);
14728 if (!ret) {
14729 vty_out(vty, "%% address is malformed\n");
14730 return CMD_WARNING;
14731 }
718e3744 14732
d62a17ae 14733 match.family = afi2family(afi);
14734
14735 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)
14736 || (safi == SAFI_EVPN)) {
9bcb3eef
DS
14737 for (dest = bgp_table_top(bgp->rib[AFI_IP][safi]); dest;
14738 dest = bgp_route_next(dest)) {
14739 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14740
9bcb3eef 14741 if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
d62a17ae 14742 continue;
9bcb3eef 14743 table = bgp_dest_get_bgp_table_info(dest);
67009e22 14744 if (!table)
ea47320b 14745 continue;
4953391b
DA
14746 rm = bgp_node_match(table, &match);
14747 if (rm == NULL)
ea47320b 14748 continue;
d62a17ae 14749
9bcb3eef 14750 const struct prefix *rm_p = bgp_dest_get_prefix(dest);
b54892e0 14751
ea47320b 14752 if (!prefix_check
b54892e0 14753 || rm_p->prefixlen == match.prefixlen) {
9bcb3eef 14754 pi = bgp_dest_get_bgp_path_info(rm);
40381db7
DS
14755 while (pi) {
14756 if (pi->extra && pi->extra->damp_info) {
14757 pi_temp = pi->next;
ea47320b 14758 bgp_damp_info_free(
19971c9a 14759 pi->extra->damp_info,
5c8846f6 14760 1, afi, safi);
40381db7 14761 pi = pi_temp;
ea47320b 14762 } else
40381db7 14763 pi = pi->next;
d62a17ae 14764 }
ea47320b
DL
14765 }
14766
9bcb3eef 14767 bgp_dest_unlock_node(rm);
d62a17ae 14768 }
14769 } else {
4953391b
DA
14770 dest = bgp_node_match(bgp->rib[afi][safi], &match);
14771 if (dest != NULL) {
9bcb3eef 14772 const struct prefix *dest_p = bgp_dest_get_prefix(dest);
b54892e0 14773
d62a17ae 14774 if (!prefix_check
9bcb3eef
DS
14775 || dest_p->prefixlen == match.prefixlen) {
14776 pi = bgp_dest_get_bgp_path_info(dest);
40381db7
DS
14777 while (pi) {
14778 if (pi->extra && pi->extra->damp_info) {
14779 pi_temp = pi->next;
d62a17ae 14780 bgp_damp_info_free(
19971c9a 14781 pi->extra->damp_info,
5c8846f6 14782 1, afi, safi);
40381db7 14783 pi = pi_temp;
d62a17ae 14784 } else
40381db7 14785 pi = pi->next;
d62a17ae 14786 }
14787 }
14788
9bcb3eef 14789 bgp_dest_unlock_node(dest);
d62a17ae 14790 }
14791 }
718e3744 14792
d62a17ae 14793 return CMD_SUCCESS;
718e3744 14794}
14795
14796DEFUN (clear_ip_bgp_dampening,
14797 clear_ip_bgp_dampening_cmd,
14798 "clear ip bgp dampening",
14799 CLEAR_STR
14800 IP_STR
14801 BGP_STR
14802 "Clear route flap dampening information\n")
14803{
b4f7f45b 14804 bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
d62a17ae 14805 return CMD_SUCCESS;
718e3744 14806}
14807
14808DEFUN (clear_ip_bgp_dampening_prefix,
14809 clear_ip_bgp_dampening_prefix_cmd,
14810 "clear ip bgp dampening A.B.C.D/M",
14811 CLEAR_STR
14812 IP_STR
14813 BGP_STR
14814 "Clear route flap dampening information\n"
0c7b1b01 14815 "IPv4 prefix\n")
718e3744 14816{
d62a17ae 14817 int idx_ipv4_prefixlen = 4;
14818 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4_prefixlen]->arg,
14819 AFI_IP, SAFI_UNICAST, NULL, 1);
718e3744 14820}
14821
14822DEFUN (clear_ip_bgp_dampening_address,
14823 clear_ip_bgp_dampening_address_cmd,
14824 "clear ip bgp dampening A.B.C.D",
14825 CLEAR_STR
14826 IP_STR
14827 BGP_STR
14828 "Clear route flap dampening information\n"
14829 "Network to clear damping information\n")
14830{
d62a17ae 14831 int idx_ipv4 = 4;
14832 return bgp_clear_damp_route(vty, NULL, argv[idx_ipv4]->arg, AFI_IP,
14833 SAFI_UNICAST, NULL, 0);
718e3744 14834}
14835
14836DEFUN (clear_ip_bgp_dampening_address_mask,
14837 clear_ip_bgp_dampening_address_mask_cmd,
14838 "clear ip bgp dampening A.B.C.D A.B.C.D",
14839 CLEAR_STR
14840 IP_STR
14841 BGP_STR
14842 "Clear route flap dampening information\n"
14843 "Network to clear damping information\n"
14844 "Network mask\n")
14845{
d62a17ae 14846 int idx_ipv4 = 4;
14847 int idx_ipv4_2 = 5;
14848 int ret;
14849 char prefix_str[BUFSIZ];
718e3744 14850
d62a17ae 14851 ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
7533cad7 14852 prefix_str, sizeof(prefix_str));
d62a17ae 14853 if (!ret) {
14854 vty_out(vty, "%% Inconsistent address and mask\n");
14855 return CMD_WARNING;
14856 }
718e3744 14857
d62a17ae 14858 return bgp_clear_damp_route(vty, NULL, prefix_str, AFI_IP, SAFI_UNICAST,
14859 NULL, 0);
718e3744 14860}
6b0655a2 14861
e3b78da8 14862static void show_bgp_peerhash_entry(struct hash_bucket *bucket, void *arg)
825d9834
DS
14863{
14864 struct vty *vty = arg;
e3b78da8 14865 struct peer *peer = bucket->data;
825d9834
DS
14866 char buf[SU_ADDRSTRLEN];
14867
14868 vty_out(vty, "\tPeer: %s %s\n", peer->host,
14869 sockunion2str(&peer->su, buf, sizeof(buf)));
14870}
14871
2a0e69ae
DS
14872DEFUN (show_bgp_listeners,
14873 show_bgp_listeners_cmd,
14874 "show bgp listeners",
14875 SHOW_STR
14876 BGP_STR
14877 "Display Listen Sockets and who created them\n")
14878{
14879 bgp_dump_listener_info(vty);
14880
14881 return CMD_SUCCESS;
14882}
14883
825d9834
DS
14884DEFUN (show_bgp_peerhash,
14885 show_bgp_peerhash_cmd,
14886 "show bgp peerhash",
14887 SHOW_STR
14888 BGP_STR
14889 "Display information about the BGP peerhash\n")
14890{
14891 struct list *instances = bm->bgp;
14892 struct listnode *node;
14893 struct bgp *bgp;
14894
14895 for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) {
14896 vty_out(vty, "BGP: %s\n", bgp->name);
14897 hash_iterate(bgp->peerhash, show_bgp_peerhash_entry,
14898 vty);
14899 }
14900
14901 return CMD_SUCCESS;
14902}
14903
587ff0fd 14904/* also used for encap safi */
2b791107
DL
14905static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
14906 afi_t afi, safi_t safi)
d62a17ae 14907{
9bcb3eef
DS
14908 struct bgp_dest *pdest;
14909 struct bgp_dest *dest;
d62a17ae 14910 struct bgp_table *table;
b54892e0
DS
14911 const struct prefix *p;
14912 const struct prefix_rd *prd;
d62a17ae 14913 struct bgp_static *bgp_static;
14914 mpls_label_t label;
d62a17ae 14915 char rdbuf[RD_ADDRSTRLEN];
14916
14917 /* Network configuration. */
9bcb3eef
DS
14918 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14919 pdest = bgp_route_next(pdest)) {
14920 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14921 if (!table)
ea47320b 14922 continue;
d62a17ae 14923
9bcb3eef
DS
14924 for (dest = bgp_table_top(table); dest;
14925 dest = bgp_route_next(dest)) {
14926 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14927 if (bgp_static == NULL)
ea47320b 14928 continue;
d62a17ae 14929
9bcb3eef
DS
14930 p = bgp_dest_get_prefix(dest);
14931 prd = (const struct prefix_rd *)bgp_dest_get_prefix(
14932 pdest);
d62a17ae 14933
ea47320b 14934 /* "network" configuration display. */
06b9f471 14935 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
ea47320b
DL
14936 label = decode_label(&bgp_static->label);
14937
8228a9a7 14938 vty_out(vty, " network %pFX rd %s", p, rdbuf);
ea47320b
DL
14939 if (safi == SAFI_MPLS_VPN)
14940 vty_out(vty, " label %u", label);
14941
14942 if (bgp_static->rmap.name)
14943 vty_out(vty, " route-map %s",
14944 bgp_static->rmap.name);
e2a86ad9
DS
14945
14946 if (bgp_static->backdoor)
14947 vty_out(vty, " backdoor");
14948
ea47320b
DL
14949 vty_out(vty, "\n");
14950 }
14951 }
d62a17ae 14952}
14953
2b791107
DL
14954static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
14955 afi_t afi, safi_t safi)
d62a17ae 14956{
9bcb3eef
DS
14957 struct bgp_dest *pdest;
14958 struct bgp_dest *dest;
d62a17ae 14959 struct bgp_table *table;
b54892e0
DS
14960 const struct prefix *p;
14961 const struct prefix_rd *prd;
d62a17ae 14962 struct bgp_static *bgp_static;
ff44f570 14963 char buf[PREFIX_STRLEN * 2];
d62a17ae 14964 char buf2[SU_ADDRSTRLEN];
14965 char rdbuf[RD_ADDRSTRLEN];
0a50c248 14966 char esi_buf[ESI_BYTES];
d62a17ae 14967
14968 /* Network configuration. */
9bcb3eef
DS
14969 for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
14970 pdest = bgp_route_next(pdest)) {
14971 table = bgp_dest_get_bgp_table_info(pdest);
67009e22 14972 if (!table)
ea47320b 14973 continue;
d62a17ae 14974
9bcb3eef
DS
14975 for (dest = bgp_table_top(table); dest;
14976 dest = bgp_route_next(dest)) {
14977 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 14978 if (bgp_static == NULL)
ea47320b 14979 continue;
d62a17ae 14980
ea47320b 14981 char *macrouter = NULL;
d62a17ae 14982
ea47320b
DL
14983 if (bgp_static->router_mac)
14984 macrouter = prefix_mac2str(
14985 bgp_static->router_mac, NULL, 0);
14986 if (bgp_static->eth_s_id)
0a50c248
AK
14987 esi_to_str(bgp_static->eth_s_id,
14988 esi_buf, sizeof(esi_buf));
9bcb3eef
DS
14989 p = bgp_dest_get_prefix(dest);
14990 prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
d62a17ae 14991
ea47320b 14992 /* "network" configuration display. */
06b9f471 14993 prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
197cb530
PG
14994 if (p->u.prefix_evpn.route_type == 5) {
14995 char local_buf[PREFIX_STRLEN];
3714a385 14996 uint8_t family = is_evpn_prefix_ipaddr_v4((
a4d82a8a
PZ
14997 struct prefix_evpn *)p)
14998 ? AF_INET
14999 : AF_INET6;
3714a385 15000 inet_ntop(family,
15001 &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
a4d82a8a 15002 local_buf, PREFIX_STRLEN);
772270f3
QY
15003 snprintf(buf, sizeof(buf), "%s/%u", local_buf,
15004 p->u.prefix_evpn.prefix_addr
15005 .ip_prefix_length);
197cb530
PG
15006 } else {
15007 prefix2str(p, buf, sizeof(buf));
15008 }
ea47320b 15009
a4d82a8a
PZ
15010 if (bgp_static->gatewayIp.family == AF_INET
15011 || bgp_static->gatewayIp.family == AF_INET6)
197cb530
PG
15012 inet_ntop(bgp_static->gatewayIp.family,
15013 &bgp_static->gatewayIp.u.prefix, buf2,
15014 sizeof(buf2));
ea47320b 15015 vty_out(vty,
7bcc8dac 15016 " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
3714a385 15017 buf, rdbuf,
15018 p->u.prefix_evpn.prefix_addr.eth_tag,
0a50c248 15019 decode_label(&bgp_static->label), esi_buf, buf2,
ea47320b
DL
15020 macrouter);
15021
0a22ddfb 15022 XFREE(MTYPE_TMP, macrouter);
ea47320b
DL
15023 }
15024 }
3da6fcd5
PG
15025}
15026
718e3744 15027/* Configuration of static route announcement and aggregate
15028 information. */
2b791107
DL
15029void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
15030 safi_t safi)
d62a17ae 15031{
9bcb3eef 15032 struct bgp_dest *dest;
b54892e0 15033 const struct prefix *p;
d62a17ae 15034 struct bgp_static *bgp_static;
15035 struct bgp_aggregate *bgp_aggregate;
d62a17ae 15036
2b791107
DL
15037 if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) {
15038 bgp_config_write_network_vpn(vty, bgp, afi, safi);
15039 return;
15040 }
d62a17ae 15041
2b791107
DL
15042 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
15043 bgp_config_write_network_evpn(vty, bgp, afi, safi);
15044 return;
15045 }
d62a17ae 15046
15047 /* Network configuration. */
9bcb3eef
DS
15048 for (dest = bgp_table_top(bgp->route[afi][safi]); dest;
15049 dest = bgp_route_next(dest)) {
15050 bgp_static = bgp_dest_get_bgp_static_info(dest);
a78beeb5 15051 if (bgp_static == NULL)
ea47320b 15052 continue;
d62a17ae 15053
9bcb3eef 15054 p = bgp_dest_get_prefix(dest);
d62a17ae 15055
8228a9a7 15056 vty_out(vty, " network %pFX", p);
d62a17ae 15057
ea47320b
DL
15058 if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
15059 vty_out(vty, " label-index %u",
15060 bgp_static->label_index);
d62a17ae 15061
ea47320b
DL
15062 if (bgp_static->rmap.name)
15063 vty_out(vty, " route-map %s", bgp_static->rmap.name);
e2a86ad9
DS
15064
15065 if (bgp_static->backdoor)
15066 vty_out(vty, " backdoor");
718e3744 15067
ea47320b
DL
15068 vty_out(vty, "\n");
15069 }
15070
d62a17ae 15071 /* Aggregate-address configuration. */
9bcb3eef
DS
15072 for (dest = bgp_table_top(bgp->aggregate[afi][safi]); dest;
15073 dest = bgp_route_next(dest)) {
15074 bgp_aggregate = bgp_dest_get_bgp_aggregate_info(dest);
b1e62edd 15075 if (bgp_aggregate == NULL)
ea47320b 15076 continue;
d62a17ae 15077
9bcb3eef 15078 p = bgp_dest_get_prefix(dest);
d62a17ae 15079
8228a9a7 15080 vty_out(vty, " aggregate-address %pFX", p);
d62a17ae 15081
ea47320b
DL
15082 if (bgp_aggregate->as_set)
15083 vty_out(vty, " as-set");
d62a17ae 15084
ea47320b
DL
15085 if (bgp_aggregate->summary_only)
15086 vty_out(vty, " summary-only");
718e3744 15087
20894f50
DA
15088 if (bgp_aggregate->rmap.name)
15089 vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
15090
229757f1
DA
15091 if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
15092 vty_out(vty, " origin %s",
15093 bgp_origin2str(bgp_aggregate->origin));
15094
6aabb15d
RZ
15095 if (bgp_aggregate->match_med)
15096 vty_out(vty, " matching-MED-only");
15097
365ab2e7
RZ
15098 if (bgp_aggregate->suppress_map_name)
15099 vty_out(vty, " suppress-map %s",
15100 bgp_aggregate->suppress_map_name);
15101
ea47320b
DL
15102 vty_out(vty, "\n");
15103 }
d62a17ae 15104}
734b349e 15105
2b791107 15106void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi,
60466a63 15107 safi_t safi)
d62a17ae 15108{
9bcb3eef 15109 struct bgp_dest *dest;
d62a17ae 15110 struct bgp_distance *bdistance;
15111
15112 /* Distance configuration. */
15113 if (bgp->distance_ebgp[afi][safi] && bgp->distance_ibgp[afi][safi]
15114 && bgp->distance_local[afi][safi]
15115 && (bgp->distance_ebgp[afi][safi] != ZEBRA_EBGP_DISTANCE_DEFAULT
15116 || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT
15117 || bgp->distance_local[afi][safi]
15118 != ZEBRA_IBGP_DISTANCE_DEFAULT)) {
d62a17ae 15119 vty_out(vty, " distance bgp %d %d %d\n",
15120 bgp->distance_ebgp[afi][safi],
15121 bgp->distance_ibgp[afi][safi],
15122 bgp->distance_local[afi][safi]);
15123 }
734b349e 15124
9bcb3eef
DS
15125 for (dest = bgp_table_top(bgp_distance_table[afi][safi]); dest;
15126 dest = bgp_route_next(dest)) {
15127 bdistance = bgp_dest_get_bgp_distance_info(dest);
b54892e0 15128 if (bdistance != NULL)
56ca3b5b 15129 vty_out(vty, " distance %d %pBD %s\n",
9bcb3eef 15130 bdistance->distance, dest,
d62a17ae 15131 bdistance->access_list ? bdistance->access_list
15132 : "");
ca2e160d 15133 }
718e3744 15134}
15135
15136/* Allocate routing table structure and install commands. */
d62a17ae 15137void bgp_route_init(void)
15138{
15139 afi_t afi;
15140 safi_t safi;
15141
15142 /* Init BGP distance table. */
05c7a1cc 15143 FOREACH_AFI_SAFI (afi, safi)
960035b2 15144 bgp_distance_table[afi][safi] = bgp_table_init(NULL, afi, safi);
d62a17ae 15145
15146 /* IPv4 BGP commands. */
15147 install_element(BGP_NODE, &bgp_table_map_cmd);
15148 install_element(BGP_NODE, &bgp_network_cmd);
d62a17ae 15149 install_element(BGP_NODE, &no_bgp_table_map_cmd);
d62a17ae 15150
554b3b10 15151 install_element(BGP_NODE, &aggregate_addressv4_cmd);
d62a17ae 15152
15153 /* IPv4 unicast configuration. */
15154 install_element(BGP_IPV4_NODE, &bgp_table_map_cmd);
15155 install_element(BGP_IPV4_NODE, &bgp_network_cmd);
d62a17ae 15156 install_element(BGP_IPV4_NODE, &no_bgp_table_map_cmd);
d62a17ae 15157
554b3b10 15158 install_element(BGP_IPV4_NODE, &aggregate_addressv4_cmd);
d62a17ae 15159
15160 /* IPv4 multicast configuration. */
15161 install_element(BGP_IPV4M_NODE, &bgp_table_map_cmd);
15162 install_element(BGP_IPV4M_NODE, &bgp_network_cmd);
d62a17ae 15163 install_element(BGP_IPV4M_NODE, &no_bgp_table_map_cmd);
554b3b10 15164 install_element(BGP_IPV4M_NODE, &aggregate_addressv4_cmd);
d62a17ae 15165
15166 /* IPv4 labeled-unicast configuration. */
fb985e0c 15167 install_element(BGP_IPV4L_NODE, &bgp_network_cmd);
554b3b10 15168 install_element(BGP_IPV4L_NODE, &aggregate_addressv4_cmd);
fb985e0c 15169
d62a17ae 15170 install_element(VIEW_NODE, &show_ip_bgp_instance_all_cmd);
15171 install_element(VIEW_NODE, &show_ip_bgp_cmd);
893cccd0 15172 install_element(VIEW_NODE, &show_ip_bgp_afi_safi_statistics_cmd);
14718643 15173 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_statistics_cmd);
7b2ff250 15174 install_element(VIEW_NODE, &show_ip_bgp_json_cmd);
d62a17ae 15175 install_element(VIEW_NODE, &show_ip_bgp_route_cmd);
15176 install_element(VIEW_NODE, &show_ip_bgp_regexp_cmd);
4265b261 15177 install_element(VIEW_NODE, &show_ip_bgp_statistics_all_cmd);
d62a17ae 15178
15179 install_element(VIEW_NODE,
15180 &show_ip_bgp_instance_neighbor_advertised_route_cmd);
f20ce998
DS
15181 install_element(VIEW_NODE,
15182 &show_ip_bgp_instance_neighbor_bestpath_route_cmd);
d62a17ae 15183 install_element(VIEW_NODE, &show_ip_bgp_neighbor_routes_cmd);
15184 install_element(VIEW_NODE,
15185 &show_ip_bgp_neighbor_received_prefix_filter_cmd);
d6902373 15186#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15187 install_element(VIEW_NODE, &show_ip_bgp_vpn_all_route_prefix_cmd);
d6902373 15188#endif /* KEEP_OLD_VPN_COMMANDS */
d62a17ae 15189 install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
15190 install_element(VIEW_NODE,
44c69747 15191 &show_bgp_l2vpn_evpn_route_prefix_cmd);
57d187bc 15192
d62a17ae 15193 /* BGP dampening clear commands */
15194 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
15195 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_prefix_cmd);
718e3744 15196
d62a17ae 15197 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_cmd);
15198 install_element(ENABLE_NODE, &clear_ip_bgp_dampening_address_mask_cmd);
15199
15200 /* prefix count */
15201 install_element(ENABLE_NODE,
15202 &show_ip_bgp_instance_neighbor_prefix_counts_cmd);
d6902373 15203#ifdef KEEP_OLD_VPN_COMMANDS
d62a17ae 15204 install_element(ENABLE_NODE,
15205 &show_ip_bgp_vpn_neighbor_prefix_counts_cmd);
d6902373 15206#endif /* KEEP_OLD_VPN_COMMANDS */
ff7924f6 15207
d62a17ae 15208 /* New config IPv6 BGP commands. */
15209 install_element(BGP_IPV6_NODE, &bgp_table_map_cmd);
15210 install_element(BGP_IPV6_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15211 install_element(BGP_IPV6_NODE, &no_bgp_table_map_cmd);
d62a17ae 15212
554b3b10 15213 install_element(BGP_IPV6_NODE, &aggregate_addressv6_cmd);
d62a17ae 15214
15215 install_element(BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
d62a17ae 15216
fb985e0c
DA
15217 /* IPv6 labeled unicast address family. */
15218 install_element(BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
554b3b10 15219 install_element(BGP_IPV6L_NODE, &aggregate_addressv6_cmd);
fb985e0c 15220
d62a17ae 15221 install_element(BGP_NODE, &bgp_distance_cmd);
15222 install_element(BGP_NODE, &no_bgp_distance_cmd);
15223 install_element(BGP_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15224 install_element(BGP_NODE, &no_bgp_distance_source_cmd);
15225 install_element(BGP_NODE, &bgp_distance_source_access_list_cmd);
15226 install_element(BGP_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15227 install_element(BGP_IPV4_NODE, &bgp_distance_cmd);
15228 install_element(BGP_IPV4_NODE, &no_bgp_distance_cmd);
15229 install_element(BGP_IPV4_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15230 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_cmd);
15231 install_element(BGP_IPV4_NODE, &bgp_distance_source_access_list_cmd);
15232 install_element(BGP_IPV4_NODE, &no_bgp_distance_source_access_list_cmd);
d62a17ae 15233 install_element(BGP_IPV4M_NODE, &bgp_distance_cmd);
15234 install_element(BGP_IPV4M_NODE, &no_bgp_distance_cmd);
15235 install_element(BGP_IPV4M_NODE, &bgp_distance_source_cmd);
585f1adc
IR
15236 install_element(BGP_IPV4M_NODE, &no_bgp_distance_source_cmd);
15237 install_element(BGP_IPV4M_NODE, &bgp_distance_source_access_list_cmd);
15238 install_element(BGP_IPV4M_NODE,
15239 &no_bgp_distance_source_access_list_cmd);
d62a17ae 15240 install_element(BGP_IPV6_NODE, &bgp_distance_cmd);
15241 install_element(BGP_IPV6_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15242 install_element(BGP_IPV6_NODE, &ipv6_bgp_distance_source_cmd);
15243 install_element(BGP_IPV6_NODE, &no_ipv6_bgp_distance_source_cmd);
15244 install_element(BGP_IPV6_NODE,
15245 &ipv6_bgp_distance_source_access_list_cmd);
15246 install_element(BGP_IPV6_NODE,
15247 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15248 install_element(BGP_IPV6M_NODE, &bgp_distance_cmd);
15249 install_element(BGP_IPV6M_NODE, &no_bgp_distance_cmd);
585f1adc
IR
15250 install_element(BGP_IPV6M_NODE, &ipv6_bgp_distance_source_cmd);
15251 install_element(BGP_IPV6M_NODE, &no_ipv6_bgp_distance_source_cmd);
15252 install_element(BGP_IPV6M_NODE,
15253 &ipv6_bgp_distance_source_access_list_cmd);
15254 install_element(BGP_IPV6M_NODE,
15255 &no_ipv6_bgp_distance_source_access_list_cmd);
d62a17ae 15256
ef5f4b23 15257 /* BGP dampening */
585f1adc
IR
15258 install_element(BGP_NODE, &bgp_damp_set_cmd);
15259 install_element(BGP_NODE, &bgp_damp_unset_cmd);
15260 install_element(BGP_IPV4_NODE, &bgp_damp_set_cmd);
15261 install_element(BGP_IPV4_NODE, &bgp_damp_unset_cmd);
15262 install_element(BGP_IPV4M_NODE, &bgp_damp_set_cmd);
15263 install_element(BGP_IPV4M_NODE, &bgp_damp_unset_cmd);
15264 install_element(BGP_IPV4L_NODE, &bgp_damp_set_cmd);
15265 install_element(BGP_IPV4L_NODE, &bgp_damp_unset_cmd);
15266 install_element(BGP_IPV6_NODE, &bgp_damp_set_cmd);
15267 install_element(BGP_IPV6_NODE, &bgp_damp_unset_cmd);
15268 install_element(BGP_IPV6M_NODE, &bgp_damp_set_cmd);
15269 install_element(BGP_IPV6M_NODE, &bgp_damp_unset_cmd);
15270 install_element(BGP_IPV6L_NODE, &bgp_damp_set_cmd);
15271 install_element(BGP_IPV6L_NODE, &bgp_damp_unset_cmd);
d62a17ae 15272
15273 /* Large Communities */
15274 install_element(VIEW_NODE, &show_ip_bgp_large_community_list_cmd);
15275 install_element(VIEW_NODE, &show_ip_bgp_large_community_cmd);
dba3c1d3
PG
15276
15277 /* show bgp ipv4 flowspec detailed */
15278 install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd);
15279
2a0e69ae 15280 install_element(VIEW_NODE, &show_bgp_listeners_cmd);
825d9834 15281 install_element(VIEW_NODE, &show_bgp_peerhash_cmd);
d62a17ae 15282}
15283
15284void bgp_route_finish(void)
15285{
15286 afi_t afi;
15287 safi_t safi;
15288
05c7a1cc
QY
15289 FOREACH_AFI_SAFI (afi, safi) {
15290 bgp_table_unlock(bgp_distance_table[afi][safi]);
15291 bgp_distance_table[afi][safi] = NULL;
15292 }
228da428 15293}